aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/route.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/route.ts')
-rw-r--r--packages/demobank-ui/src/route.ts100
1 files changed, 67 insertions, 33 deletions
diff --git a/packages/demobank-ui/src/route.ts b/packages/demobank-ui/src/route.ts
index 4b021d762..72c7802fb 100644
--- a/packages/demobank-ui/src/route.ts
+++ b/packages/demobank-ui/src/route.ts
@@ -15,43 +15,49 @@
*/
import { useNavigationContext } from "./context/navigation.js";
+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<string, never>;
+
export function urlPattern<
- T extends Record<string, string> = Record<string, never>,
+ T extends Record<string, string | undefined> = EmptyObject,
>(pattern: RegExp, reverse: (p: T) => string): RouteDefinition<T> {
+ const url = reverse as ((p: T) => AppLocation)
return {
pattern: new RegExp(pattern),
- url: reverse,
+ url,
};
}
-export type RouteDefinition<T> = {
+/**
+ * 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<T> = Record<string, T> | EmptyObject;
+
+export type RouteDefinition<T extends ObjectOf<string | undefined> = EmptyObject> = {
pattern: RegExp;
- url: (p: T) => string;
+ url: (p: T) => AppLocation;
};
const nullRountDef = {
pattern: new RegExp(/.*/),
- url: () => "",
+ url: () => "" as AppLocation,
};
-export function buildNullRoutDefinition<T>(): RouteDefinition<T> {
+export function buildNullRoutDefinition<T extends ObjectOf<string>>(): RouteDefinition<T> {
return nullRountDef;
}
-export type RouteMap<T> = {
- [n in keyof T]: RouteDefinition<T[n]>;
-};
-
-export type RouteParamsType<
- P,
- T extends keyof P,
-> = P[T] extends RouteDefinition<infer ASD> ? ASD : never;
-
-type Location<E, T extends RouteMap<E>, NAME extends keyof T> = {
- parent: T;
- name: NAME;
- values: RouteParamsType<T, NAME>;
-};
-
/**
* Search path in the pageList
* get the values from the path found
@@ -60,23 +66,28 @@ type Location<E, T extends RouteMap<E>, NAME extends keyof T> = {
* @param path
* @param params
*/
-function findMatch<DEF, RM extends RouteMap<DEF>, ROUTES extends keyof RM>(
- pagesMap: RM,
- pageList: Array<ROUTES>,
+function findMatch<T extends ObjectOf<RouteDefinition>>(
+ pagesMap: T,
+ pageList: Array<keyof T>,
path: string,
params: Record<string, string>,
-): Location<DEF, RM, ROUTES> | undefined {
+): Location<T> | 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 =
- found.groups === undefined ? {} : structuredClone(found.groups);
+ const values = {} as Record<string, any>
Object.entries(params).forEach(([key, value]) => {
values[key] = value;
});
+ 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 };
}
@@ -84,12 +95,35 @@ function findMatch<DEF, RM extends RouteMap<DEF>, ROUTES extends keyof RM>(
return undefined;
}
-export function useCurrentLocation<
- DEF,
- RM extends RouteMap<DEF>,
- ROUTES extends keyof RM,
->(pagesMap: RM) {
- const pageList = Object.keys(pagesMap) as Array<ROUTES>;
+/**
+ * get the type of the params of a location
+ *
+ */
+type RouteParamsType<
+ RouteType,
+ Key extends keyof RouteType,
+> = RouteType[Key] extends RouteDefinition<infer ParamType> ? ParamType : never;
+
+/**
+ * Helps to create a map of a type with the key
+ */
+type MapKeyValue<Type> = {
+ [Key in keyof Type]: Key extends string ? {
+ parent: Type,
+ name: Key,
+ values: RouteParamsType<Type, Key>;
+ } : never;
+}
+
+/**
+ * create a enumaration of value of a mapped type
+ */
+type EnumerationOf<T> = T[keyof T]
+
+type Location<T> = EnumerationOf<MapKeyValue<T>>
+
+export function useCurrentLocation<T extends ObjectOf<RouteDefinition<any>>>(pagesMap: T): Location<T> | undefined {
+ const pageList = Object.keys(pagesMap as object) as Array<keyof T>;
const { path, params } = useNavigationContext();
return findMatch(pagesMap, pageList, path, params);