69 lines
2.6 KiB
TypeScript
69 lines
2.6 KiB
TypeScript
|
export type RouteParams = { [p: string]: string | number } | string[] | string | number;
|
||
|
export type QueryParamsRecord = Record<string, string | number | boolean | null | undefined>;
|
||
|
export type QueryParams = string[][] | QueryParamsRecord | string | URLSearchParams;
|
||
|
|
||
|
export let routes: Record<string, string | undefined> = {};
|
||
|
export function setRoutes(newRoutes: Record<string, string | undefined>): void {
|
||
|
routes = newRoutes;
|
||
|
}
|
||
|
export function registerRoute(routeName: string, routePath: string): boolean {
|
||
|
if (!routes[routeName]) {
|
||
|
routes[routeName] = routePath;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
export let publicUrl: string;
|
||
|
export function setPublicUrl(newPublicUrl: string): void {
|
||
|
publicUrl = newPublicUrl;
|
||
|
}
|
||
|
|
||
|
export function route(
|
||
|
route: string,
|
||
|
params: RouteParams = [],
|
||
|
query: QueryParams = '',
|
||
|
absolute: boolean = false,
|
||
|
): string {
|
||
|
let path = routes[route];
|
||
|
if (path === undefined) throw new Error(`Unknown route for name ${route}.`);
|
||
|
|
||
|
const regExp = getRouteParamRegExp('[a-zA-Z0-9_-]+', 'g');
|
||
|
if (typeof params === 'string' || typeof params === 'number') {
|
||
|
path = path.replace(regExp, '' + params);
|
||
|
} else if (Array.isArray(params)) {
|
||
|
let i = 0;
|
||
|
for (const match of path.matchAll(regExp)) {
|
||
|
if (match.length > 0) {
|
||
|
path = path.replace(match[0], typeof params[i] !== 'undefined' ? params[i] : '');
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
path = path.replace(/\/+/g, '/');
|
||
|
} else {
|
||
|
for (const key of Object.keys(params)) {
|
||
|
path = path.replace(getRouteParamRegExp(key), params[key].toString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let filteredQuery: string[][] | Record<string, string> | string | URLSearchParams;
|
||
|
if (typeof query !== "string" && !(query instanceof URLSearchParams) && !Array.isArray(query)) {
|
||
|
for (const key of Object.keys(query)) {
|
||
|
if (query[key] === undefined || query[key] === null) delete query[key];
|
||
|
else if (typeof query[key] === "number") query[key] = (query[key] as number).toString();
|
||
|
else if (typeof query[key] === "boolean") query[key] = query[key] ? '1' : '0';
|
||
|
}
|
||
|
filteredQuery = query as Record<string, string>;
|
||
|
} else {
|
||
|
filteredQuery = query;
|
||
|
}
|
||
|
|
||
|
const queryStr = new URLSearchParams(filteredQuery).toString();
|
||
|
return `${absolute ? publicUrl : ''}${path}` + (queryStr.length > 0 ? '?' + queryStr : '');
|
||
|
}
|
||
|
|
||
|
export function getRouteParamRegExp(key: string, flags?: string): RegExp {
|
||
|
return new RegExp(`:${key}(\\(.+?\\))?\\??`, flags);
|
||
|
}
|