-
-
Notifications
You must be signed in to change notification settings - Fork 815
Expand file tree
/
Copy pathrouting.ts
More file actions
110 lines (93 loc) · 3.45 KB
/
routing.ts
File metadata and controls
110 lines (93 loc) · 3.45 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { Nitro, NitroEventHandler, NitroRouteRules } from "nitro/types";
export const RuntimeRouteRules = ["headers", "redirect", "proxy", "cache", "basicAuth"] as string[];
export default function routing(nitro: Nitro) {
return {
id: "#nitro/virtual/routing",
template: () => {
const allHandlers = uniqueBy(
[
...Object.values(nitro.routing.routes.routes).flatMap((h) => h.data),
...Object.values(nitro.routing.routedMiddleware.routes).map((h) => h.data),
...nitro.routing.globalMiddleware,
],
"_importHash"
);
return /* js */ `
import * as __routeRules__ from "#nitro/runtime/route-rules";
import * as srvxNode from "srvx/node"
import * as h3 from "h3";
export const findRouteRules = ${nitro.routing.routeRules.compileToString({ serialize: serializeRouteRule, matchAll: true })}
const multiHandler = (...handlers) => {
const final = handlers.pop()
const middleware = handlers.filter(Boolean).map(h => h3.toMiddleware(h));
return (ev) => h3.callMiddleware(ev, middleware, final);
}
${allHandlers
.filter((h) => !h.lazy)
.map(
(h) =>
/* js */ `const ${h._importHash} = await import("${h.handler}").then(m => m.default).catch(() => {})`
)
.join("\n")}
${allHandlers
.filter((h) => h.lazy)
.map(
(h) =>
/* js */ `const ${h._importHash} = h3.defineLazyEventHandler(() => import("${h.handler}")${h.format === "node" ? ".then(m => srvxNode.toFetchHandler(m.default))" : ""});`
)
.join("\n")}
export const findRoute = ${nitro.routing.routes.compileToString({ serialize: serializeHandler })}
export const findRoutedMiddleware = ${nitro.routing.routedMiddleware.compileToString({ serialize: serializeHandler, matchAll: true })};
export const globalMiddleware = [
${nitro.routing.globalMiddleware.map((h) => (h.lazy ? h._importHash : `h3.toEventHandler(${h._importHash})`)).join(",")}
].filter(Boolean);
`;
},
};
}
function uniqueBy<T>(arr: T[], key: keyof T): T[] {
return [...new Map(arr.map((item) => [item[key], item])).values()];
}
// --- Serializing ---
type MaybeArray<T> = T | T[];
function serializeHandler(h: MaybeArray<NitroEventHandler & { _importHash: string }>): string {
const meta = Array.isArray(h) ? h[0] : h;
return `{${[
`route:${JSON.stringify(meta.route)}`,
meta.method && `method:${JSON.stringify(meta.method)}`,
meta.meta && `meta:${JSON.stringify(meta.meta)}`,
`handler:${
Array.isArray(h)
? `multiHandler(${h.map((handler) => serializeHandlerFn(handler)).join(",")})`
: serializeHandlerFn(h)
}`,
]
.filter(Boolean)
.join(",")}}`;
}
function serializeHandlerFn(h: NitroEventHandler & { _importHash: string }): string {
let code = h._importHash;
if (!h.lazy) {
if (h.format === "node") {
code = `srvxNode.toFetchHandler(${code})`;
}
code = `h3.toEventHandler(${code})`;
}
return code;
}
function serializeRouteRule(h: NitroRouteRules & { _route: string }): string {
return `[${Object.entries(h)
.filter(([name, options]) => options !== undefined && name[0] !== "_")
.map(([name, options]) => {
return `{${[
`name:${JSON.stringify(name)}`,
`route:${JSON.stringify(h._route)}`,
h._method && `method:${JSON.stringify(h._method)}`,
RuntimeRouteRules.includes(name) && `handler:__routeRules__.${name}`,
`options:${JSON.stringify(options)}`,
]
.filter(Boolean)
.join(",")}}`;
})
.join(",")}]`;
}