diff options
Diffstat (limited to 'src/lib/routes/router.ts')
-rw-r--r-- | src/lib/routes/router.ts | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/src/lib/routes/router.ts b/src/lib/routes/router.ts new file mode 100644 index 000000000..05e0a63de --- /dev/null +++ b/src/lib/routes/router.ts @@ -0,0 +1,55 @@ +import {RouteParams, Route} from './types' + +export class Router { + routes: [string, Route][] = [] + constructor(description: Record<string, string>) { + for (const [screen, pattern] of Object.entries(description)) { + this.routes.push([screen, createRoute(pattern)]) + } + } + + matchName(name: string): Route | undefined { + for (const [screenName, route] of this.routes) { + if (screenName === name) { + return route + } + } + } + + matchPath(path: string): [string, RouteParams] { + let name = 'NotFound' + let params: RouteParams = {} + for (const [screenName, route] of this.routes) { + const res = route.match(path) + if (res) { + name = screenName + params = res.params + break + } + } + return [name, params] + } +} + +function createRoute(pattern: string): Route { + let matcherReInternal = pattern.replace( + /:([\w]+)/g, + (_m, name) => `(?<${name}>[^/]+)`, + ) + const matcherRe = new RegExp(`^${matcherReInternal}([?]|$)`, 'i') + return { + match(path: string) { + const res = matcherRe.exec(path) + if (res) { + return {params: res.groups || {}} + } + return undefined + }, + build(params: Record<string, string>) { + return pattern.replace( + /:([\w]+)/g, + (_m, name) => params[name] || 'undefined', + ) + }, + } +} |