Skip to content

Instantly share code, notes, and snippets.

@jrobinsonc
Last active February 8, 2025 06:41
Show Gist options
  • Select an option

  • Save jrobinsonc/04d88b126a8d0845b506a214cc1d8b07 to your computer and use it in GitHub Desktop.

Select an option

Save jrobinsonc/04d88b126a8d0845b506a214cc1d8b07 to your computer and use it in GitHub Desktop.

Revisions

  1. Jose Robinson revised this gist Aug 26, 2024. 2 changed files with 10 additions and 11 deletions.
    12 changes: 1 addition & 11 deletions buildUrl.ts → build-url.ts
    Original file line number Diff line number Diff line change
    @@ -40,14 +40,4 @@ function buildUrl<
    });

    return `${match.groups?.path}?${queryString.toString()}`;
    }

    console.log(
    buildUrl("/products?id=3", { id: 1, format: true }) ===
    "/products?id=1&format=true"
    );
    console.log(
    decodeURIComponent(
    buildUrl("/products?id=3", { id: [1, 2], format: true })
    ) === "/products?id[]=1&id[]=2&format=true"
    );
    }
    9 changes: 9 additions & 0 deletions check-build-url.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    console.log(
    buildUrl("/products?id=3", { id: 1, format: true }) ===
    "/products?id=1&format=true"
    );
    console.log(
    decodeURIComponent(
    buildUrl("/products?id=3", { id: [1, 2], format: true })
    ) === "/products?id[]=1&id[]=2&format=true"
    );
  2. Jose Robinson revised this gist Aug 26, 2024. No changes.
  3. Jose Robinson created this gist Aug 26, 2024.
    53 changes: 53 additions & 0 deletions buildUrl.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    /**
    * Constructs a URL by appending query parameters to a given path.
    *
    * @template TVariables - The shape of the params.
    *
    * @param path - Path.
    * @param params - Optional. Params to be added as query parameters to the URL.
    *
    * @returns The constructed URL.
    */
    function buildUrl<
    TVariables extends Record<string, unknown> = Record<string, unknown>
    >(path: string, params?: TVariables): string {
    if (params === undefined || Object.keys(params).length === 0) {
    return path;
    }

    const match: RegExpMatchArray | null = path.match(
    /^(?<path>[^?]*)(?:\?(?<queryString>.*))?$/
    );

    if (match === null) {
    throw new Error("Error parsing the given path");
    }

    const queryString = new URLSearchParams(match.groups?.queryString);

    Object.entries(params).forEach(([key, value]) => {
    if (Array.isArray(value)) {
    if (queryString.has(key)) {
    queryString.delete(key);
    }

    value.forEach((item: unknown): void => {
    queryString.append(`${key}[]`, String(item));
    });
    } else {
    queryString.set(key, String(value));
    }
    });

    return `${match.groups?.path}?${queryString.toString()}`;
    }

    console.log(
    buildUrl("/products?id=3", { id: 1, format: true }) ===
    "/products?id=1&format=true"
    );
    console.log(
    decodeURIComponent(
    buildUrl("/products?id=3", { id: [1, 2], format: true })
    ) === "/products?id[]=1&id[]=2&format=true"
    );