about summary refs log tree commit diff
path: root/src/lib/routes/router.ts
blob: 05e0a63dea16cc646063312dbecb4bf2239067af (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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',
      )
    },
  }
}