/* This file is part of GNU Taler (C) 2022-2024 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ declare const __location: unique symbol; /** * special string that defined a location in the application * * this help to prevent wrong path */ export type AppLocation = string & { [__location]: true; }; export type EmptyObject = Record; export function urlPattern< T extends Record = EmptyObject, >(pattern: RegExp, reverse: (p: T) => string): RouteDefinition { const url = reverse as (p: T) => AppLocation; return { pattern: new RegExp(pattern), url, }; } /** * defines a location in the app * * pattern: how a string will trigger this location * url(): how a state serialize to a location */ export type ObjectOf = Record | EmptyObject; export type RouteDefinition< T extends ObjectOf = EmptyObject, > = { pattern: RegExp; url: (p: T) => AppLocation; }; const nullRountDef = { pattern: new RegExp(/.*/), url: () => "" as AppLocation, }; export function buildNullRoutDefinition< T extends ObjectOf, >(): RouteDefinition { return nullRountDef; } /** * Search path in the pageList * get the values from the path found * add params from searchParams * * @param path * @param params */ export function findMatch>( pagesMap: T, pageList: Array, path: string, params: Record, ): Location | undefined { for (let idx = 0; idx < pageList.length; idx++) { const name = pageList[idx]; const found = pagesMap[name].pattern.exec(path); if (found !== null) { const values = {} as Record; if (found.groups !== undefined) { Object.entries(found.groups).forEach(([key, value]) => { values[key] = value; }); } // @ts-expect-error values is a map string which is equivalent to the RouteParamsType return { name, parent: pagesMap, values, params }; } } return undefined; } /** * get the type of the params of a location * */ type RouteParamsType< RouteType, Key extends keyof RouteType, > = RouteType[Key] extends RouteDefinition ? ParamType : never; /** * Helps to create a map of a type with the key */ type MapKeyValue = { [Key in keyof Type]: Key extends string ? { parent: Type; name: Key; values: RouteParamsType; params: Record; } : never; }; /** * create a enumeration of value of a mapped type */ type EnumerationOf = T[keyof T]; export type Location = EnumerationOf>;