@mandujs/core 0.5.4 → 0.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +200 -200
- package/README.md +200 -200
- package/package.json +2 -2
- package/src/contract/validator.ts +2 -2
- package/src/filling/auth.ts +308 -0
- package/src/filling/context.ts +7 -1
- package/src/filling/filling.ts +83 -4
- package/src/filling/index.ts +15 -2
- package/src/generator/generate.ts +27 -6
- package/src/generator/index.ts +3 -3
- package/src/report/index.ts +1 -1
- package/src/runtime/index.ts +5 -5
- package/src/runtime/router.ts +83 -65
- package/src/runtime/server.ts +425 -425
- package/src/runtime/ssr.ts +248 -248
- package/src/spec/index.ts +3 -3
- package/src/spec/load.ts +76 -76
- package/src/spec/lock.ts +56 -56
package/src/runtime/router.ts
CHANGED
|
@@ -1,65 +1,83 @@
|
|
|
1
|
-
import type { RouteSpec } from "../spec/schema";
|
|
2
|
-
|
|
3
|
-
export interface MatchResult {
|
|
4
|
-
route: RouteSpec;
|
|
5
|
-
params: Record<string, string>;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class Router {
|
|
9
|
-
private routes: RouteSpec[] = [];
|
|
10
|
-
private compiledPatterns: Map<string, { regex: RegExp; paramNames: string[] }> = new Map();
|
|
11
|
-
|
|
12
|
-
constructor(routes: RouteSpec[] = []) {
|
|
13
|
-
this.setRoutes(routes);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
setRoutes(routes: RouteSpec[]): void {
|
|
17
|
-
this.routes = routes;
|
|
18
|
-
this.compiledPatterns.clear();
|
|
19
|
-
|
|
20
|
-
for (const route of routes) {
|
|
21
|
-
this.compiledPatterns.set(route.id, this.compilePattern(route.pattern));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
private compilePattern(pattern: string): { regex: RegExp; paramNames: string[] } {
|
|
26
|
-
const paramNames: string[] = [];
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
1
|
+
import type { RouteSpec } from "../spec/schema";
|
|
2
|
+
|
|
3
|
+
export interface MatchResult {
|
|
4
|
+
route: RouteSpec;
|
|
5
|
+
params: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class Router {
|
|
9
|
+
private routes: RouteSpec[] = [];
|
|
10
|
+
private compiledPatterns: Map<string, { regex: RegExp; paramNames: string[] }> = new Map();
|
|
11
|
+
|
|
12
|
+
constructor(routes: RouteSpec[] = []) {
|
|
13
|
+
this.setRoutes(routes);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
setRoutes(routes: RouteSpec[]): void {
|
|
17
|
+
this.routes = routes;
|
|
18
|
+
this.compiledPatterns.clear();
|
|
19
|
+
|
|
20
|
+
for (const route of routes) {
|
|
21
|
+
this.compiledPatterns.set(route.id, this.compilePattern(route.pattern));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
private compilePattern(pattern: string): { regex: RegExp; paramNames: string[] } {
|
|
26
|
+
const paramNames: string[] = [];
|
|
27
|
+
|
|
28
|
+
// 파라미터 플레이스홀더를 임시 토큰으로 대체
|
|
29
|
+
const PARAM_PLACEHOLDER = "\x00PARAM\x00";
|
|
30
|
+
const paramMatches: string[] = [];
|
|
31
|
+
|
|
32
|
+
const withPlaceholders = pattern.replace(
|
|
33
|
+
/:([a-zA-Z_][a-zA-Z0-9_]*)/g,
|
|
34
|
+
(_, paramName) => {
|
|
35
|
+
paramMatches.push(paramName);
|
|
36
|
+
return PARAM_PLACEHOLDER;
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// regex 특수문자 이스케이프 (/ 포함)
|
|
41
|
+
const escaped = withPlaceholders.replace(/[.*+?^${}()|[\]\\\/]/g, "\\$&");
|
|
42
|
+
|
|
43
|
+
// 플레이스홀더를 캡처 그룹으로 복원하고 paramNames 채우기
|
|
44
|
+
let paramIndex = 0;
|
|
45
|
+
const regexStr = escaped.replace(
|
|
46
|
+
new RegExp(PARAM_PLACEHOLDER.replace(/\x00/g, "\\x00"), "g"),
|
|
47
|
+
() => {
|
|
48
|
+
paramNames.push(paramMatches[paramIndex++]);
|
|
49
|
+
return "([^/]+)";
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const regex = new RegExp(`^${regexStr}$`);
|
|
54
|
+
return { regex, paramNames };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
match(pathname: string): MatchResult | null {
|
|
58
|
+
for (const route of this.routes) {
|
|
59
|
+
const compiled = this.compiledPatterns.get(route.id);
|
|
60
|
+
if (!compiled) continue;
|
|
61
|
+
|
|
62
|
+
const match = pathname.match(compiled.regex);
|
|
63
|
+
if (match) {
|
|
64
|
+
const params: Record<string, string> = {};
|
|
65
|
+
compiled.paramNames.forEach((name, index) => {
|
|
66
|
+
params[name] = match[index + 1];
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return { route, params };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getRoutes(): RouteSpec[] {
|
|
77
|
+
return [...this.routes];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createRouter(routes: RouteSpec[] = []): Router {
|
|
82
|
+
return new Router(routes);
|
|
83
|
+
}
|