2021-11-24 18:18:55 +01:00
|
|
|
export type RouteParams = { [p: string]: string | number | undefined } | string[] | string | number;
|
2021-06-01 14:34:04 +02:00
|
|
|
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)) {
|
2021-11-24 18:18:55 +01:00
|
|
|
const paramValue = params[key];
|
|
|
|
if (paramValue) {
|
|
|
|
path = path.replace(getRouteParamRegExp(key), paramValue.toString());
|
|
|
|
}
|
2021-06-01 14:34:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-11-20 18:02:00 +01:00
|
|
|
|
|
|
|
export function hasRoute(...routesToMatch: string[]): boolean {
|
|
|
|
for (const route of routesToMatch) {
|
|
|
|
if (!routes[route]) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function hasAnyRoute(...routesToMatch: string[]): boolean {
|
|
|
|
for (const route of routesToMatch) {
|
|
|
|
if (routes[route]) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|