createUrl(endpoint, data = {}, parentPath, gateway) {
    const url = new URL(gateway ? this.resolveGateway(gateway) : this.gateway);
    const usedKeys = [];

    const { path: resolvedPath, method: resolvedMethod } = this.resolveEndpoint(endpoint, data);

    const path = []
      .concat(...(parentPath ?? []), resolvedPath)
      .filter((p) => p !== undefined)
      .join("/")
      .replace(/([/]+)/g, "/");

    const processedPath = path.replace(/:([^/]+)/g, (...res) => {
      const keyRaw = res[1];
      const [key, optional] = keyRaw.match(/([^?]+)(\??)/).slice(1, 3);
      const result = data[key];

      usedKeys.push(key);

      if (result === undefined) {
        if (optional === "?") return "";
        throw new Error(`Can't find key \`${key}\` in data [${path}]`);
      }

      return result;
    });

    url.pathname += processedPath.replace(/\/+/g, "/").replace(/\/+$/g, "");

    if (data && typeof data === "object") {
      Object.entries(data).forEach(([key, value]) => {
        if (!usedKeys.includes(key)) {
          url.searchParams.set(key, value);
        }
      });
    }

    return {
      url: url.toString(),
      method: resolvedMethod,
    };
  }
Creates a URL from gateway + endpoint path + params
@param {string} path
@param {Dict} data
@private