Skip to content

Commit 54b82ca

Browse files
committed
refactor: simplify PreparedRegExpRouter API.
1 parent e8dbcd2 commit 54b82ca

File tree

2 files changed

+64
-136
lines changed

2 files changed

+64
-136
lines changed

src/router/reg-exp-router/prepared-router.ts

Lines changed: 63 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
1-
import type { Router, ParamIndexMap } from '../../router'
1+
import type { Result, Router, ParamIndexMap } from '../../router'
22
import { METHOD_NAME_ALL } from '../../router'
33
import type { Matcher, MatcherMap } from './matcher'
4-
import { match, buildAllMatchersKey } from './matcher'
4+
import { match, buildAllMatchersKey, emptyParam } from './matcher'
55
import { RegExpRouter } from './router'
66

7-
type RelocateMap = Record<
8-
string,
9-
Record<
10-
string,
11-
[
12-
string, // method
13-
(number | string)[],
14-
ParamIndexMap | undefined
15-
][]
16-
>
17-
>
7+
type RelocateMap = Record<string, [(number | string)[], ParamIndexMap | undefined][]>
188

199
export class PreparedRegExpRouter<T> implements Router<T> {
2010
name: string = 'PreparedRegExpRouter'
@@ -27,6 +17,18 @@ export class PreparedRegExpRouter<T> implements Router<T> {
2717
}
2818

2919
add(method: string, path: string, handler: T) {
20+
const all = this.#matchers[METHOD_NAME_ALL]
21+
this.#matchers[method] ||= [
22+
all[0],
23+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
24+
all[1].map((list) => Array.isArray(list) ? list.slice() : 0) as any,
25+
Object.keys(all[2]).reduce((obj, key) => {
26+
obj[key] = [all[2][key][0].slice(), emptyParam]
27+
return obj
28+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
29+
}, {} as any),
30+
]
31+
3032
if (path === '/*' || path === '*') {
3133
const defaultHandlerData: [T, ParamIndexMap] = [handler, {}]
3234
;(method === METHOD_NAME_ALL ? Object.keys(this.#matchers) : [method]).forEach((m) => {
@@ -39,24 +41,26 @@ export class PreparedRegExpRouter<T> implements Router<T> {
3941
return
4042
}
4143

42-
const data = this.#relocateMap[method]?.[path]
44+
const data = this.#relocateMap[path]
4345
if (!data) {
4446
return
4547
}
46-
for (const [m, indexes, map] of data) {
47-
if (!map) {
48-
// assumed to be a static route
49-
this.#matchers[m][2][path][0].push([handler, {}])
50-
} else {
51-
indexes.forEach((index) => {
52-
if (typeof index === 'number') {
53-
this.#matchers[m][1][index].push([handler, map])
54-
} else {
55-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
56-
this.#matchers[m][2][index || path][0].push([handler, map as any])
57-
}
58-
})
59-
}
48+
for (const [indexes, map] of data) {
49+
;(method === METHOD_NAME_ALL ? Object.keys(this.#matchers) : [method]).forEach((m) => {
50+
if (!map) {
51+
// assumed to be a static route
52+
this.#matchers[m][2][path][0].push([handler, {}])
53+
} else {
54+
indexes.forEach((index) => {
55+
if (typeof index === 'number') {
56+
this.#matchers[m][1][index].push([handler, map])
57+
} else {
58+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59+
this.#matchers[m][2][index || path][0].push([handler, map as any])
60+
}
61+
})
62+
}
63+
})
6064
}
6165
}
6266

@@ -68,122 +72,57 @@ export class PreparedRegExpRouter<T> implements Router<T> {
6872
}
6973

7074
export const buildInitParams: (params: {
71-
routes: {
72-
method: string
73-
path: string
74-
}[]
75-
}) => ConstructorParameters<typeof PreparedRegExpRouter> = ({ routes }) => {
75+
paths: string[]
76+
}) => ConstructorParameters<typeof PreparedRegExpRouter> = ({ paths }) => {
7677
const router = new RegExpRouter<string>()
77-
for (const { method, path } of routes) {
78+
for (const path of paths) {
7879
if (path === '/*' || path === '*') {
7980
continue
8081
}
81-
router.add(method.toUpperCase(), path, path)
82+
router.add(METHOD_NAME_ALL, path, path)
8283
}
8384

8485
const matchers = router[buildAllMatchersKey]()
85-
8686
const all = matchers[METHOD_NAME_ALL]
87-
if (all) {
88-
for (const method of Object.keys(matchers)) {
89-
if (method === METHOD_NAME_ALL) {
90-
continue
91-
}
92-
93-
if (
94-
matchers[method][0].toString() !== all[0].toString() ||
95-
JSON.stringify(matchers[method][1]) !== JSON.stringify(all[1]) ||
96-
JSON.stringify(matchers[method][2]) !== JSON.stringify(all[2])
97-
) {
98-
continue
99-
}
100-
87+
Object.keys(matchers).forEach((method) => {
88+
if (method !== METHOD_NAME_ALL) {
10189
delete matchers[method]
10290
}
103-
}
91+
})
10492

10593
const relocateMap: RelocateMap = {}
106-
for (const { method, path } of routes) {
107-
if (method === METHOD_NAME_ALL) {
108-
Object.keys(matchers).forEach((m) => {
109-
matchers[m][1].forEach((list, i) => {
110-
list.forEach(([p, map]) => {
111-
if (p === path) {
112-
relocateMap[method] ||= {}
113-
relocateMap[method][path] ||= []
114-
let target = relocateMap[method][path].find(([method]) => method === m)
115-
if (!target) {
116-
target = [m, [], map]
117-
relocateMap[method][path].push(target)
118-
}
119-
if (target[1].findIndex((j) => j === i) === -1) {
120-
target[1].push(i)
121-
}
122-
}
123-
})
124-
})
125-
for (const path2 of Object.keys(matchers[m][2])) {
126-
matchers[m][2][path2][0].forEach(([p, map]) => {
127-
if (p === path) {
128-
relocateMap[method] ||= {}
129-
relocateMap[method][path] ||= []
130-
let target = relocateMap[method][path].find(([method]) => method === m)
131-
if (!target) {
132-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
133-
target = [m, [], map as any]
134-
relocateMap[method][path].push(target)
135-
}
136-
const value = path2 === path ? '' : path2
137-
if (target[1].findIndex((v) => v === value) === -1) {
138-
target[1].push(value)
139-
}
140-
}
141-
})
94+
for (const path of paths) {
95+
all[1].forEach((list, i) => {
96+
list.forEach(([p, map]) => {
97+
if (p === path) {
98+
relocateMap[path] ||= [[[], map]]
99+
if (relocateMap[path][0][0].findIndex((j) => j === i) === -1) {
100+
relocateMap[path][0][0].push(i)
101+
}
142102
}
143103
})
144-
} else {
145-
const m = method.toUpperCase()
146-
matchers[m][1].forEach((list, i) => {
147-
list.forEach(([p, map]) => {
148-
if (p === path) {
149-
relocateMap[m] ||= {}
150-
relocateMap[m][path] ||= [[m, [], map]]
151-
if (relocateMap[m][path][0][1].findIndex((j) => j === i) === -1) {
152-
relocateMap[m][path][0][1].push(i)
153-
}
104+
})
105+
for (const path2 of Object.keys(all[2])) {
106+
all[2][path2][0].forEach(([p, map]) => {
107+
if (p === path) {
108+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
109+
relocateMap[path] ||= [[[], map as any]]
110+
const value = path2 === path ? '' : path2
111+
if (relocateMap[path][0][0].findIndex((v) => v === value) === -1) {
112+
relocateMap[path][0][0].push(value)
154113
}
155-
})
114+
}
156115
})
157-
for (const path2 of Object.keys(matchers[m][2])) {
158-
matchers[m][2][path2][0].forEach(([p, map]) => {
159-
if (p === path) {
160-
relocateMap[m] ||= {}
161-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
162-
relocateMap[m][path] ||= [[m, [], map as any]]
163-
const value = path2 === path ? '' : path2
164-
if (relocateMap[m][path][0][1].findIndex((v) => v === value) === -1) {
165-
relocateMap[m][path][0][1].push(value)
166-
}
167-
}
168-
})
169-
}
170116
}
171117
}
172118

173-
for (const method of Object.keys(matchers)) {
174-
if (matchers[method][1].length === 0 && Object.keys(matchers[method][2]).length === 0) {
175-
delete matchers[method]
176-
continue
177-
}
178-
179-
for (let i = 0, len = matchers[method][1].length; i < len; i++) {
180-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
181-
matchers[method][1][i] = matchers[method][1][i] ? [] : (0 as any)
182-
}
183-
Object.keys(matchers[method][2]).forEach((path) => {
184-
matchers[method][2][path][0] = []
185-
})
119+
for (let i = 0, len = all[1].length; i < len; i++) {
120+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
121+
all[1][i] = all[1][i] ? [] : (0 as any)
186122
}
123+
Object.keys(all[2]).forEach((path) => {
124+
all[2][path][0] = []
125+
})
187126

188127
return [matchers, relocateMap]
189128
}

src/router/reg-exp-router/router.test.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -663,18 +663,7 @@ describe('Capture Group', () => {
663663
describe('PreparedRegExpRouter', async () => {
664664
const serialized = serializeInitParams(
665665
buildInitParams({
666-
routes: [
667-
{ method: 'ALL', path: '*' },
668-
{ method: 'ALL', path: '/posts/:id/*' },
669-
{ method: 'GET', path: '*' },
670-
{ method: 'GET', path: '/' },
671-
{ method: 'GET', path: '/static' },
672-
{ method: 'GET', path: '/posts/:id/*' },
673-
{ method: 'GET', path: '/posts/:id' },
674-
{ method: 'GET', path: '/posts/:id/comments' },
675-
{ method: 'POST', path: '/posts' },
676-
{ method: 'PUT', path: '/posts/:id' },
677-
],
666+
paths: ['*', '/static', '/posts/:id/*', '/posts/:id', '/posts/:id/comments', '/posts'],
678667
})
679668
)
680669

0 commit comments

Comments
 (0)