Skip to content

Instantly share code, notes, and snippets.

@JonathanTurnock
Created January 8, 2023 21:35
Show Gist options
  • Save JonathanTurnock/0be6c432cc961575aea29f3b9bc9ae82 to your computer and use it in GitHub Desktop.
Save JonathanTurnock/0be6c432cc961575aea29f3b9bc9ae82 to your computer and use it in GitHub Desktop.
Snippet for url conversion
import { toUrlString } from "./to-url-string";
describe("toUrlString", () => {
it("should transform a basic url", () => {
expect(toUrlString({ path: "/people" })).toEqual("/people");
});
it("should transform a colon parameterised url", () => {
expect(toUrlString({ path: "/people/:id", params: { id: 1 } })).toEqual("/people/1");
});
it("should transform a bracket parameterised url", () => {
expect(toUrlString({ path: "/people/{id}", params: { id: 1 } })).toEqual("/people/1");
});
it("should transform a url with query", () => {
expect(toUrlString({ path: "/people", query: { size: 20 } })).toEqual("/people?size=20");
});
it("should throw error when missing params", () => {
expect(() => toUrlString({ path: "/people/:id" })).toThrowError(
"Missing Value for 'id' in path /people/:id"
);
});
});
import { IStringifyOptions, stringify } from "qs";
type Options = {
path: string;
params?: Record<string, any>;
query?: Record<string, any>;
queryOptions?: IStringifyOptions;
};
/**
* Assembles a complete relative path from the given parameters.
*
* Brackets or colon notation can be used in the path string interchangeably
*
* @example
* toUrlString({path: "/people/:id", params: {id: 1}, query: {hello: "world"}}); // "/people/1?hello=world"
* toUrlString({path: "/people/{id}", params: {id: 1}, query: {hello: "world"}}); // "/people/1?hello=world"
*/
export const toUrlString = ({ path, params, query, queryOptions }: Options) => {
const bracketedPath = path
.split("/")
.map((part) => (part.startsWith(":") ? `{${part.replace(":", "")}}` : part))
.join("/");
const url = bracketedPath.replace(/{(\d+|[a-z$_][a-z\d$_]*?(?:\.[a-z\d$_]*?)*?)}/gi, (_, key) => {
const result = params?.[key];
if (!result) throw new Error(`Missing Value for '${key}' in path ${path}`);
return String(result);
});
if (!query) return url;
return `${url}?${stringify(query, queryOptions)}`;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment