mokup 2.3.0 → 2.3.2
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/dist/bundle.cjs +2 -6
- package/dist/bundle.d.cts +1 -27
- package/dist/bundle.d.mts +1 -27
- package/dist/bundle.d.ts +1 -27
- package/dist/bundle.mjs +1 -5
- package/dist/cli-bin.d.cts +1 -0
- package/dist/cli-bin.d.mts +1 -0
- package/dist/cli-bin.d.ts +1 -0
- package/dist/index.cjs +8 -159
- package/dist/index.d.cts +7 -48
- package/dist/index.d.mts +7 -48
- package/dist/index.d.ts +7 -48
- package/dist/index.mjs +8 -159
- package/dist/shared/mokup.BZpTBIrj.mjs +10 -0
- package/dist/shared/mokup.CO9HhGox.cjs +13 -0
- package/dist/vite.cjs +53 -153
- package/dist/vite.d.cts +2 -7
- package/dist/vite.d.mts +3 -6
- package/dist/vite.d.ts +2 -7
- package/dist/vite.mjs +22 -122
- package/dist/webpack.cjs +29 -38
- package/dist/webpack.d.cts +3 -6
- package/dist/webpack.d.mts +3 -6
- package/dist/webpack.d.ts +3 -6
- package/dist/webpack.mjs +5 -14
- package/package.json +85 -24
- package/dist/shared/mokup.BXPIIxtS.cjs +0 -47
- package/dist/shared/mokup.C-hwskJ_.mjs +0 -1790
- package/dist/shared/mokup.CsBTglhs.mjs +0 -45
- package/dist/shared/mokup.DXCs9518.cjs +0 -1810
- package/dist/shared/mokup.Dkqu10Hk.d.cts +0 -379
- package/dist/shared/mokup.Dkqu10Hk.d.mts +0 -379
- package/dist/shared/mokup.Dkqu10Hk.d.ts +0 -379
- package/dist/shared/mokup.Dy9VDphS.cjs +0 -181
- package/dist/shared/mokup.Iqw32OxC.mjs +0 -174
|
@@ -1,1810 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const node_fs = require('node:fs');
|
|
4
|
-
const pathe = require('@mokup/shared/pathe');
|
|
5
|
-
const node_module = require('node:module');
|
|
6
|
-
const playgroundGrouping = require('@mokup/shared/playground-grouping');
|
|
7
|
-
const manifest = require('./mokup.Dy9VDphS.cjs');
|
|
8
|
-
const node_buffer = require('node:buffer');
|
|
9
|
-
const hono = require('@mokup/shared/hono');
|
|
10
|
-
const timing = require('@mokup/shared/timing');
|
|
11
|
-
const pathUtils = require('@mokup/shared/path-utils');
|
|
12
|
-
const node_url = require('node:url');
|
|
13
|
-
const esbuild = require('@mokup/shared/esbuild');
|
|
14
|
-
const jsoncParser = require('@mokup/shared/jsonc-parser');
|
|
15
|
-
const runtime = require('@mokup/runtime');
|
|
16
|
-
|
|
17
|
-
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
18
|
-
function normalizeMethod(method) {
|
|
19
|
-
if (!method) {
|
|
20
|
-
return void 0;
|
|
21
|
-
}
|
|
22
|
-
const normalized = method.toUpperCase();
|
|
23
|
-
if (manifest.methodSet.has(normalized)) {
|
|
24
|
-
return normalized;
|
|
25
|
-
}
|
|
26
|
-
return void 0;
|
|
27
|
-
}
|
|
28
|
-
function normalizePrefix(prefix) {
|
|
29
|
-
if (!prefix) {
|
|
30
|
-
return "";
|
|
31
|
-
}
|
|
32
|
-
const normalized = prefix.startsWith("/") ? prefix : `/${prefix}`;
|
|
33
|
-
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
34
|
-
}
|
|
35
|
-
function resolveDirs(dir, root) {
|
|
36
|
-
const raw = typeof dir === "function" ? dir(root) : dir;
|
|
37
|
-
const resolved = Array.isArray(raw) ? raw : raw ? [raw] : ["mock"];
|
|
38
|
-
const normalized = resolved.map(
|
|
39
|
-
(entry) => pathe.isAbsolute(entry) ? entry : pathe.resolve(root, entry)
|
|
40
|
-
);
|
|
41
|
-
return Array.from(new Set(normalized));
|
|
42
|
-
}
|
|
43
|
-
function normalizeIgnorePrefix(value, fallback = ["."]) {
|
|
44
|
-
const list = typeof value === "undefined" ? fallback : Array.isArray(value) ? value : [value];
|
|
45
|
-
return list.filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.DXCs9518.cjs', document.baseURI).href)));
|
|
49
|
-
const mimeTypes = {
|
|
50
|
-
".html": "text/html; charset=utf-8",
|
|
51
|
-
".css": "text/css; charset=utf-8",
|
|
52
|
-
".js": "text/javascript; charset=utf-8",
|
|
53
|
-
".map": "application/json; charset=utf-8",
|
|
54
|
-
".json": "application/json; charset=utf-8",
|
|
55
|
-
".svg": "image/svg+xml",
|
|
56
|
-
".png": "image/png",
|
|
57
|
-
".jpg": "image/jpeg",
|
|
58
|
-
".jpeg": "image/jpeg",
|
|
59
|
-
".ico": "image/x-icon"
|
|
60
|
-
};
|
|
61
|
-
function resolvePlaygroundDist() {
|
|
62
|
-
const pkgPath = require$1.resolve("@mokup/playground/package.json");
|
|
63
|
-
return pathe.join(pkgPath, "..", "dist");
|
|
64
|
-
}
|
|
65
|
-
function sendJson(res, data, statusCode = 200) {
|
|
66
|
-
res.statusCode = statusCode;
|
|
67
|
-
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
68
|
-
res.end(JSON.stringify(data, null, 2));
|
|
69
|
-
}
|
|
70
|
-
function sendFile(res, content, contentType) {
|
|
71
|
-
res.statusCode = 200;
|
|
72
|
-
res.setHeader("Content-Type", contentType);
|
|
73
|
-
res.end(content);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function normalizePlaygroundPath(value) {
|
|
77
|
-
if (!value) {
|
|
78
|
-
return "/__mokup";
|
|
79
|
-
}
|
|
80
|
-
const normalized = value.startsWith("/") ? value : `/${value}`;
|
|
81
|
-
return normalized.length > 1 && normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
82
|
-
}
|
|
83
|
-
function normalizeBase(base) {
|
|
84
|
-
if (!base || base === "/") {
|
|
85
|
-
return "";
|
|
86
|
-
}
|
|
87
|
-
return base.endsWith("/") ? base.slice(0, -1) : base;
|
|
88
|
-
}
|
|
89
|
-
function resolvePlaygroundRequestPath(base, playgroundPath) {
|
|
90
|
-
const normalizedBase = normalizeBase(base);
|
|
91
|
-
const normalizedPath = normalizePlaygroundPath(playgroundPath);
|
|
92
|
-
if (!normalizedBase) {
|
|
93
|
-
return normalizedPath;
|
|
94
|
-
}
|
|
95
|
-
if (normalizedPath.startsWith(normalizedBase)) {
|
|
96
|
-
return normalizedPath;
|
|
97
|
-
}
|
|
98
|
-
return `${normalizedBase}${normalizedPath}`;
|
|
99
|
-
}
|
|
100
|
-
function resolvePlaygroundOptions(playground) {
|
|
101
|
-
if (playground === false) {
|
|
102
|
-
return { enabled: false, path: "/__mokup", build: false };
|
|
103
|
-
}
|
|
104
|
-
if (playground && typeof playground === "object") {
|
|
105
|
-
return {
|
|
106
|
-
enabled: playground.enabled !== false,
|
|
107
|
-
path: normalizePlaygroundPath(playground.path),
|
|
108
|
-
build: playground.build === true
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
return { enabled: true, path: "/__mokup", build: false };
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function injectPlaygroundHmr(html, base) {
|
|
115
|
-
if (html.includes("mokup-playground-hmr")) {
|
|
116
|
-
return html;
|
|
117
|
-
}
|
|
118
|
-
const normalizedBase = normalizeBase(base);
|
|
119
|
-
const clientPath = `${normalizedBase}/@vite/client`;
|
|
120
|
-
const snippet = [
|
|
121
|
-
'<script type="module" id="mokup-playground-hmr">',
|
|
122
|
-
`import('${clientPath}').then(({ createHotContext }) => {`,
|
|
123
|
-
" const hot = createHotContext('/@mokup/playground')",
|
|
124
|
-
" hot.on('mokup:routes-changed', () => {",
|
|
125
|
-
" const api = window.__MOKUP_PLAYGROUND__",
|
|
126
|
-
" if (api && typeof api.reloadRoutes === 'function') {",
|
|
127
|
-
" api.reloadRoutes()",
|
|
128
|
-
" if (typeof api.notifyHotReload === 'function') {",
|
|
129
|
-
" api.notifyHotReload()",
|
|
130
|
-
" }",
|
|
131
|
-
" return",
|
|
132
|
-
" }",
|
|
133
|
-
" window.location.reload()",
|
|
134
|
-
" })",
|
|
135
|
-
"}).catch(() => {})",
|
|
136
|
-
"<\/script>"
|
|
137
|
-
].join("\n");
|
|
138
|
-
if (html.includes("</body>")) {
|
|
139
|
-
return html.replace("</body>", `${snippet}
|
|
140
|
-
</body>`);
|
|
141
|
-
}
|
|
142
|
-
return `${html}
|
|
143
|
-
${snippet}`;
|
|
144
|
-
}
|
|
145
|
-
function injectPlaygroundSw(html, script) {
|
|
146
|
-
if (!script) {
|
|
147
|
-
return html;
|
|
148
|
-
}
|
|
149
|
-
if (html.includes("mokup-playground-sw")) {
|
|
150
|
-
return html;
|
|
151
|
-
}
|
|
152
|
-
const snippet = [
|
|
153
|
-
'<script type="module" id="mokup-playground-sw">',
|
|
154
|
-
script,
|
|
155
|
-
"<\/script>"
|
|
156
|
-
].join("\n");
|
|
157
|
-
if (html.includes("</head>")) {
|
|
158
|
-
return html.replace("</head>", `${snippet}
|
|
159
|
-
</head>`);
|
|
160
|
-
}
|
|
161
|
-
if (html.includes("</body>")) {
|
|
162
|
-
return html.replace("</body>", `${snippet}
|
|
163
|
-
</body>`);
|
|
164
|
-
}
|
|
165
|
-
return `${html}
|
|
166
|
-
${snippet}`;
|
|
167
|
-
}
|
|
168
|
-
function isViteDevServer(server) {
|
|
169
|
-
return !!server && "ws" in server;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const disabledReasonSet = /* @__PURE__ */ new Set([
|
|
173
|
-
"disabled",
|
|
174
|
-
"disabled-dir",
|
|
175
|
-
"exclude",
|
|
176
|
-
"ignore-prefix",
|
|
177
|
-
"include",
|
|
178
|
-
"unknown"
|
|
179
|
-
]);
|
|
180
|
-
const ignoredReasonSet = /* @__PURE__ */ new Set([
|
|
181
|
-
"unsupported",
|
|
182
|
-
"invalid-route",
|
|
183
|
-
"unknown"
|
|
184
|
-
]);
|
|
185
|
-
function normalizeDisabledReason(reason) {
|
|
186
|
-
if (reason && disabledReasonSet.has(reason)) {
|
|
187
|
-
return reason;
|
|
188
|
-
}
|
|
189
|
-
return "unknown";
|
|
190
|
-
}
|
|
191
|
-
function normalizeIgnoredReason(reason) {
|
|
192
|
-
if (reason && ignoredReasonSet.has(reason)) {
|
|
193
|
-
return reason;
|
|
194
|
-
}
|
|
195
|
-
return "unknown";
|
|
196
|
-
}
|
|
197
|
-
function toPlaygroundRoute(route, root, groups) {
|
|
198
|
-
const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
|
|
199
|
-
const preSources = route.middlewares?.filter((entry) => entry.position === "pre").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
|
|
200
|
-
const postSources = route.middlewares?.filter((entry) => entry.position === "post").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
|
|
201
|
-
const normalSources = route.middlewares?.filter((entry) => entry.position !== "pre" && entry.position !== "post").map((entry) => playgroundGrouping.formatRouteFile(entry.source, root)) ?? [];
|
|
202
|
-
const combinedSources = [
|
|
203
|
-
...preSources,
|
|
204
|
-
...normalSources,
|
|
205
|
-
...postSources
|
|
206
|
-
];
|
|
207
|
-
const configChain = route.configChain?.map((entry) => playgroundGrouping.formatRouteFile(entry, root)) ?? [];
|
|
208
|
-
return {
|
|
209
|
-
method: route.method,
|
|
210
|
-
url: route.template,
|
|
211
|
-
file: playgroundGrouping.formatRouteFile(route.file, root),
|
|
212
|
-
type: typeof route.handler === "function" ? "handler" : "static",
|
|
213
|
-
status: route.status,
|
|
214
|
-
delay: route.delay,
|
|
215
|
-
middlewareCount: combinedSources.length,
|
|
216
|
-
middlewares: combinedSources,
|
|
217
|
-
preMiddlewareCount: preSources.length,
|
|
218
|
-
normalMiddlewareCount: normalSources.length,
|
|
219
|
-
postMiddlewareCount: postSources.length,
|
|
220
|
-
preMiddlewares: preSources,
|
|
221
|
-
normalMiddlewares: normalSources,
|
|
222
|
-
postMiddlewares: postSources,
|
|
223
|
-
configChain: configChain.length > 0 ? configChain : void 0,
|
|
224
|
-
groupKey: matchedGroup?.key,
|
|
225
|
-
group: matchedGroup?.label
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
function formatDecisionChain(chain, root) {
|
|
229
|
-
return chain.map((entry) => {
|
|
230
|
-
const formatted = {
|
|
231
|
-
step: entry.step,
|
|
232
|
-
result: entry.result
|
|
233
|
-
};
|
|
234
|
-
if (typeof entry.detail !== "undefined") {
|
|
235
|
-
formatted.detail = entry.detail;
|
|
236
|
-
}
|
|
237
|
-
if (typeof entry.source !== "undefined") {
|
|
238
|
-
const source = entry.source;
|
|
239
|
-
formatted.source = source && pathe.isAbsolute(source) ? playgroundGrouping.formatRouteFile(source, root) : source;
|
|
240
|
-
}
|
|
241
|
-
return formatted;
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
function toPlaygroundDisabledRoute(route, root, groups) {
|
|
245
|
-
const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
|
|
246
|
-
const disabled = {
|
|
247
|
-
file: playgroundGrouping.formatRouteFile(route.file, root),
|
|
248
|
-
reason: normalizeDisabledReason(route.reason)
|
|
249
|
-
};
|
|
250
|
-
if (typeof route.method !== "undefined") {
|
|
251
|
-
disabled.method = route.method;
|
|
252
|
-
}
|
|
253
|
-
if (typeof route.url !== "undefined") {
|
|
254
|
-
disabled.url = route.url;
|
|
255
|
-
}
|
|
256
|
-
if (route.configChain && route.configChain.length > 0) {
|
|
257
|
-
disabled.configChain = route.configChain.map((entry) => playgroundGrouping.formatRouteFile(entry, root));
|
|
258
|
-
}
|
|
259
|
-
if (route.decisionChain && route.decisionChain.length > 0) {
|
|
260
|
-
disabled.decisionChain = formatDecisionChain(route.decisionChain, root);
|
|
261
|
-
}
|
|
262
|
-
if (route.effectiveConfig && Object.keys(route.effectiveConfig).length > 0) {
|
|
263
|
-
disabled.effectiveConfig = route.effectiveConfig;
|
|
264
|
-
}
|
|
265
|
-
if (matchedGroup) {
|
|
266
|
-
disabled.groupKey = matchedGroup.key;
|
|
267
|
-
disabled.group = matchedGroup.label;
|
|
268
|
-
}
|
|
269
|
-
return disabled;
|
|
270
|
-
}
|
|
271
|
-
function toPlaygroundIgnoredRoute(route, root, groups) {
|
|
272
|
-
const matchedGroup = playgroundGrouping.resolveRouteGroup(route.file, groups);
|
|
273
|
-
const ignored = {
|
|
274
|
-
file: playgroundGrouping.formatRouteFile(route.file, root),
|
|
275
|
-
reason: normalizeIgnoredReason(route.reason)
|
|
276
|
-
};
|
|
277
|
-
if (matchedGroup) {
|
|
278
|
-
ignored.groupKey = matchedGroup.key;
|
|
279
|
-
ignored.group = matchedGroup.label;
|
|
280
|
-
}
|
|
281
|
-
if (route.configChain && route.configChain.length > 0) {
|
|
282
|
-
ignored.configChain = route.configChain.map((entry) => playgroundGrouping.formatRouteFile(entry, root));
|
|
283
|
-
}
|
|
284
|
-
if (route.decisionChain && route.decisionChain.length > 0) {
|
|
285
|
-
ignored.decisionChain = formatDecisionChain(route.decisionChain, root);
|
|
286
|
-
}
|
|
287
|
-
if (route.effectiveConfig && Object.keys(route.effectiveConfig).length > 0) {
|
|
288
|
-
ignored.effectiveConfig = route.effectiveConfig;
|
|
289
|
-
}
|
|
290
|
-
return ignored;
|
|
291
|
-
}
|
|
292
|
-
function toPlaygroundConfigFile(entry, root, groups) {
|
|
293
|
-
const matchedGroup = playgroundGrouping.resolveRouteGroup(entry.file, groups);
|
|
294
|
-
const configFile = {
|
|
295
|
-
file: playgroundGrouping.formatRouteFile(entry.file, root)
|
|
296
|
-
};
|
|
297
|
-
if (matchedGroup) {
|
|
298
|
-
configFile.groupKey = matchedGroup.key;
|
|
299
|
-
configFile.group = matchedGroup.label;
|
|
300
|
-
}
|
|
301
|
-
return configFile;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
function createPlaygroundMiddleware(params) {
|
|
305
|
-
const distDir = resolvePlaygroundDist();
|
|
306
|
-
const playgroundPath = params.config.path;
|
|
307
|
-
const indexPath = pathe.join(distDir, "index.html");
|
|
308
|
-
return async (req, res, next) => {
|
|
309
|
-
if (!params.config.enabled) {
|
|
310
|
-
return next();
|
|
311
|
-
}
|
|
312
|
-
const server = params.getServer?.();
|
|
313
|
-
const requestPath = resolvePlaygroundRequestPath(server?.config?.base ?? "/", playgroundPath);
|
|
314
|
-
const requestUrl = req.url ?? "/";
|
|
315
|
-
const url = new URL(requestUrl, "http://mokup.local");
|
|
316
|
-
const pathname = url.pathname;
|
|
317
|
-
const matchedPath = pathname.startsWith(requestPath) ? requestPath : pathname.startsWith(playgroundPath) ? playgroundPath : null;
|
|
318
|
-
if (!matchedPath) {
|
|
319
|
-
return next();
|
|
320
|
-
}
|
|
321
|
-
const subPath = pathname.slice(matchedPath.length);
|
|
322
|
-
if (subPath === "") {
|
|
323
|
-
const suffix = url.search ?? "";
|
|
324
|
-
res.statusCode = 302;
|
|
325
|
-
res.setHeader("Location", `${matchedPath}/${suffix}`);
|
|
326
|
-
res.end();
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
if (subPath === "" || subPath === "/" || subPath === "/index.html") {
|
|
330
|
-
try {
|
|
331
|
-
const html = await node_fs.promises.readFile(indexPath, "utf8");
|
|
332
|
-
let output = html;
|
|
333
|
-
if (isViteDevServer(server)) {
|
|
334
|
-
output = injectPlaygroundHmr(output, server.config.base ?? "/");
|
|
335
|
-
output = injectPlaygroundSw(output, params.getSwScript?.());
|
|
336
|
-
}
|
|
337
|
-
const contentType = mimeTypes[".html"] ?? "text/html; charset=utf-8";
|
|
338
|
-
sendFile(res, output, contentType);
|
|
339
|
-
} catch (error) {
|
|
340
|
-
params.logger.error("Failed to load playground index:", error);
|
|
341
|
-
res.statusCode = 500;
|
|
342
|
-
res.end("Playground is not available.");
|
|
343
|
-
}
|
|
344
|
-
return;
|
|
345
|
-
}
|
|
346
|
-
if (subPath === "/routes") {
|
|
347
|
-
const dirs = params.getDirs?.() ?? [];
|
|
348
|
-
const baseRoot = playgroundGrouping.resolveGroupRoot(dirs, server?.config?.root);
|
|
349
|
-
const groups = playgroundGrouping.resolveGroups(dirs, baseRoot);
|
|
350
|
-
const routes = params.getRoutes();
|
|
351
|
-
const disabledRoutes = params.getDisabledRoutes?.() ?? [];
|
|
352
|
-
const ignoredRoutes = params.getIgnoredRoutes?.() ?? [];
|
|
353
|
-
const configFiles = params.getConfigFiles?.() ?? [];
|
|
354
|
-
const disabledConfigFiles = params.getDisabledConfigFiles?.() ?? [];
|
|
355
|
-
sendJson(res, {
|
|
356
|
-
basePath: matchedPath,
|
|
357
|
-
root: baseRoot,
|
|
358
|
-
count: routes.length,
|
|
359
|
-
groups: groups.map((group) => ({ key: group.key, label: group.label })),
|
|
360
|
-
routes: routes.map((route) => toPlaygroundRoute(route, baseRoot, groups)),
|
|
361
|
-
disabled: disabledRoutes.map((route) => toPlaygroundDisabledRoute(route, baseRoot, groups)),
|
|
362
|
-
ignored: ignoredRoutes.map((route) => toPlaygroundIgnoredRoute(route, baseRoot, groups)),
|
|
363
|
-
configs: configFiles.map((entry) => toPlaygroundConfigFile(entry, baseRoot, groups)),
|
|
364
|
-
disabledConfigs: disabledConfigFiles.map((entry) => toPlaygroundConfigFile(entry, baseRoot, groups))
|
|
365
|
-
});
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
const relPath = subPath.replace(/^\/+/, "");
|
|
369
|
-
if (relPath.includes("..")) {
|
|
370
|
-
res.statusCode = 400;
|
|
371
|
-
res.end("Invalid path.");
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const normalizedPath = pathe.normalize(relPath);
|
|
375
|
-
const filePath = pathe.join(distDir, normalizedPath);
|
|
376
|
-
try {
|
|
377
|
-
const content = await node_fs.promises.readFile(filePath);
|
|
378
|
-
const ext = pathe.extname(filePath);
|
|
379
|
-
const contentType = mimeTypes[ext] ?? "application/octet-stream";
|
|
380
|
-
sendFile(res, content, contentType);
|
|
381
|
-
} catch {
|
|
382
|
-
return next();
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
const defaultSwPath = "/mokup-sw.js";
|
|
388
|
-
const defaultSwScope = "/";
|
|
389
|
-
function normalizeSwPath(path) {
|
|
390
|
-
if (!path) {
|
|
391
|
-
return defaultSwPath;
|
|
392
|
-
}
|
|
393
|
-
return path.startsWith("/") ? path : `/${path}`;
|
|
394
|
-
}
|
|
395
|
-
function normalizeSwScope(scope) {
|
|
396
|
-
if (!scope) {
|
|
397
|
-
return defaultSwScope;
|
|
398
|
-
}
|
|
399
|
-
return scope.startsWith("/") ? scope : `/${scope}`;
|
|
400
|
-
}
|
|
401
|
-
function normalizeBasePath(value) {
|
|
402
|
-
if (!value) {
|
|
403
|
-
return "/";
|
|
404
|
-
}
|
|
405
|
-
const normalized = value.startsWith("/") ? value : `/${value}`;
|
|
406
|
-
if (normalized.length > 1 && normalized.endsWith("/")) {
|
|
407
|
-
return normalized.slice(0, -1);
|
|
408
|
-
}
|
|
409
|
-
return normalized;
|
|
410
|
-
}
|
|
411
|
-
function resolveSwConfigFromEntries(entries, logger) {
|
|
412
|
-
let path = defaultSwPath;
|
|
413
|
-
let scope = defaultSwScope;
|
|
414
|
-
let register = true;
|
|
415
|
-
let unregister = false;
|
|
416
|
-
const basePaths = [];
|
|
417
|
-
let hasPath = false;
|
|
418
|
-
let hasScope = false;
|
|
419
|
-
let hasRegister = false;
|
|
420
|
-
let hasUnregister = false;
|
|
421
|
-
for (const entry of entries) {
|
|
422
|
-
const config = entry.sw;
|
|
423
|
-
if (config?.path) {
|
|
424
|
-
const next = normalizeSwPath(config.path);
|
|
425
|
-
if (!hasPath) {
|
|
426
|
-
path = next;
|
|
427
|
-
hasPath = true;
|
|
428
|
-
} else if (path !== next) {
|
|
429
|
-
logger.warn(`SW path "${next}" ignored; using "${path}".`);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
if (config?.scope) {
|
|
433
|
-
const next = normalizeSwScope(config.scope);
|
|
434
|
-
if (!hasScope) {
|
|
435
|
-
scope = next;
|
|
436
|
-
hasScope = true;
|
|
437
|
-
} else if (scope !== next) {
|
|
438
|
-
logger.warn(`SW scope "${next}" ignored; using "${scope}".`);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
if (typeof config?.register === "boolean") {
|
|
442
|
-
if (!hasRegister) {
|
|
443
|
-
register = config.register;
|
|
444
|
-
hasRegister = true;
|
|
445
|
-
} else if (register !== config.register) {
|
|
446
|
-
logger.warn(
|
|
447
|
-
`SW register="${String(config.register)}" ignored; using "${String(register)}".`
|
|
448
|
-
);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
if (typeof config?.unregister === "boolean") {
|
|
452
|
-
if (!hasUnregister) {
|
|
453
|
-
unregister = config.unregister;
|
|
454
|
-
hasUnregister = true;
|
|
455
|
-
} else if (unregister !== config.unregister) {
|
|
456
|
-
logger.warn(
|
|
457
|
-
`SW unregister="${String(config.unregister)}" ignored; using "${String(unregister)}".`
|
|
458
|
-
);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
if (typeof config?.basePath !== "undefined") {
|
|
462
|
-
const values = Array.isArray(config.basePath) ? config.basePath : [config.basePath];
|
|
463
|
-
for (const value of values) {
|
|
464
|
-
basePaths.push(normalizeBasePath(value));
|
|
465
|
-
}
|
|
466
|
-
continue;
|
|
467
|
-
}
|
|
468
|
-
const normalizedPrefix = normalizePrefix(entry.prefix ?? "");
|
|
469
|
-
if (normalizedPrefix) {
|
|
470
|
-
basePaths.push(normalizedPrefix);
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
return {
|
|
474
|
-
path,
|
|
475
|
-
scope,
|
|
476
|
-
register,
|
|
477
|
-
unregister,
|
|
478
|
-
basePaths: Array.from(new Set(basePaths))
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
function resolveSwConfig(options, logger) {
|
|
482
|
-
const swEntries = options.filter((entry) => entry.mode === "sw");
|
|
483
|
-
if (swEntries.length === 0) {
|
|
484
|
-
return null;
|
|
485
|
-
}
|
|
486
|
-
return resolveSwConfigFromEntries(swEntries, logger);
|
|
487
|
-
}
|
|
488
|
-
function resolveSwUnregisterConfig(options, logger) {
|
|
489
|
-
return resolveSwConfigFromEntries(options, logger);
|
|
490
|
-
}
|
|
491
|
-
function buildSwScript(params) {
|
|
492
|
-
const { routes, root } = params;
|
|
493
|
-
const runtimeImportPath = params.runtimeImportPath ?? "mokup/runtime";
|
|
494
|
-
const loggerImportPath = params.loggerImportPath ?? "@mokup/shared/logger";
|
|
495
|
-
const basePaths = params.basePaths ?? [];
|
|
496
|
-
const resolveModulePath = params.resolveModulePath ?? manifest.toViteImportPath;
|
|
497
|
-
const { manifest: manifest$1, modules } = manifest.buildManifestData({
|
|
498
|
-
routes,
|
|
499
|
-
root,
|
|
500
|
-
resolveModulePath
|
|
501
|
-
});
|
|
502
|
-
const imports = [
|
|
503
|
-
`import { createLogger } from ${JSON.stringify(loggerImportPath)}`,
|
|
504
|
-
`import { createRuntimeApp, handle } from ${JSON.stringify(runtimeImportPath)}`
|
|
505
|
-
];
|
|
506
|
-
const moduleEntries = [];
|
|
507
|
-
let moduleIndex = 0;
|
|
508
|
-
for (const entry of modules) {
|
|
509
|
-
const name = `module${moduleIndex++}`;
|
|
510
|
-
imports.push(`import * as ${name} from '${entry.id}'`);
|
|
511
|
-
moduleEntries.push({ id: entry.id, name, kind: entry.kind });
|
|
512
|
-
}
|
|
513
|
-
const lines = [];
|
|
514
|
-
lines.push(...imports, "");
|
|
515
|
-
lines.push(
|
|
516
|
-
"const logger = createLogger()",
|
|
517
|
-
"",
|
|
518
|
-
"const resolveModuleExport = (mod) => mod?.default ?? mod",
|
|
519
|
-
"",
|
|
520
|
-
"const toRuntimeRule = (value) => {",
|
|
521
|
-
" if (typeof value === 'undefined') {",
|
|
522
|
-
" return null",
|
|
523
|
-
" }",
|
|
524
|
-
" if (typeof value === 'function') {",
|
|
525
|
-
" return { response: value }",
|
|
526
|
-
" }",
|
|
527
|
-
" if (value === null) {",
|
|
528
|
-
" return { response: null }",
|
|
529
|
-
" }",
|
|
530
|
-
" if (typeof value === 'object') {",
|
|
531
|
-
" if ('response' in value) {",
|
|
532
|
-
" return value",
|
|
533
|
-
" }",
|
|
534
|
-
" if ('handler' in value) {",
|
|
535
|
-
" const handlerRule = value",
|
|
536
|
-
" return {",
|
|
537
|
-
" response: handlerRule.handler,",
|
|
538
|
-
" ...(typeof handlerRule.status === 'number' ? { status: handlerRule.status } : {}),",
|
|
539
|
-
" ...(handlerRule.headers ? { headers: handlerRule.headers } : {}),",
|
|
540
|
-
" ...(typeof handlerRule.delay === 'number' ? { delay: handlerRule.delay } : {}),",
|
|
541
|
-
" }",
|
|
542
|
-
" }",
|
|
543
|
-
" return { response: value }",
|
|
544
|
-
" }",
|
|
545
|
-
" return { response: value }",
|
|
546
|
-
"}",
|
|
547
|
-
"",
|
|
548
|
-
"const toRuntimeRules = (value) => {",
|
|
549
|
-
" if (typeof value === 'undefined') {",
|
|
550
|
-
" return []",
|
|
551
|
-
" }",
|
|
552
|
-
" if (Array.isArray(value)) {",
|
|
553
|
-
" return value.map(toRuntimeRule).filter(Boolean)",
|
|
554
|
-
" }",
|
|
555
|
-
" const rule = toRuntimeRule(value)",
|
|
556
|
-
" return rule ? [rule] : []",
|
|
557
|
-
"}",
|
|
558
|
-
""
|
|
559
|
-
);
|
|
560
|
-
lines.push(
|
|
561
|
-
`const manifest = ${JSON.stringify(manifest$1, null, 2)}`,
|
|
562
|
-
""
|
|
563
|
-
);
|
|
564
|
-
if (moduleEntries.length > 0) {
|
|
565
|
-
lines.push("const moduleMap = {");
|
|
566
|
-
for (const entry of moduleEntries) {
|
|
567
|
-
if (entry.kind === "rule") {
|
|
568
|
-
lines.push(
|
|
569
|
-
` ${JSON.stringify(entry.id)}: { default: toRuntimeRules(resolveModuleExport(${entry.name})) },`
|
|
570
|
-
);
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
lines.push(
|
|
574
|
-
` ${JSON.stringify(entry.id)}: ${entry.name},`
|
|
575
|
-
);
|
|
576
|
-
}
|
|
577
|
-
lines.push("}", "");
|
|
578
|
-
}
|
|
579
|
-
const runtimeOptions = moduleEntries.length > 0 ? "{ manifest, moduleMap }" : "{ manifest }";
|
|
580
|
-
lines.push(
|
|
581
|
-
`const basePaths = ${JSON.stringify(basePaths)}`,
|
|
582
|
-
"",
|
|
583
|
-
"self.addEventListener('install', () => {",
|
|
584
|
-
" self.skipWaiting()",
|
|
585
|
-
"})",
|
|
586
|
-
"",
|
|
587
|
-
"self.addEventListener('activate', (event) => {",
|
|
588
|
-
" event.waitUntil(self.clients.claim())",
|
|
589
|
-
"})",
|
|
590
|
-
"",
|
|
591
|
-
"const shouldHandle = (request) => {",
|
|
592
|
-
" if (!basePaths || basePaths.length === 0) {",
|
|
593
|
-
" return true",
|
|
594
|
-
" }",
|
|
595
|
-
" const pathname = new URL(request.url).pathname",
|
|
596
|
-
" return basePaths.some((basePath) => {",
|
|
597
|
-
" if (basePath === '/') {",
|
|
598
|
-
" return true",
|
|
599
|
-
" }",
|
|
600
|
-
" return pathname === basePath || pathname.startsWith(basePath + '/')",
|
|
601
|
-
" })",
|
|
602
|
-
"}",
|
|
603
|
-
"",
|
|
604
|
-
"const registerHandler = async () => {",
|
|
605
|
-
` const app = await createRuntimeApp(${runtimeOptions})`,
|
|
606
|
-
" const handler = handle(app)",
|
|
607
|
-
" self.addEventListener('fetch', (event) => {",
|
|
608
|
-
" if (!shouldHandle(event.request)) {",
|
|
609
|
-
" return",
|
|
610
|
-
" }",
|
|
611
|
-
" handler(event)",
|
|
612
|
-
" })",
|
|
613
|
-
"}",
|
|
614
|
-
"",
|
|
615
|
-
"registerHandler().catch((error) => {",
|
|
616
|
-
" logger.error('Failed to build service worker app:', error)",
|
|
617
|
-
"})",
|
|
618
|
-
""
|
|
619
|
-
);
|
|
620
|
-
return lines.join("\n");
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
function toHonoPath(route) {
|
|
624
|
-
if (!route.tokens || route.tokens.length === 0) {
|
|
625
|
-
return "/";
|
|
626
|
-
}
|
|
627
|
-
const segments = route.tokens.map((token) => {
|
|
628
|
-
if (token.type === "static") {
|
|
629
|
-
return token.value;
|
|
630
|
-
}
|
|
631
|
-
if (token.type === "param") {
|
|
632
|
-
return `:${token.name}`;
|
|
633
|
-
}
|
|
634
|
-
if (token.type === "catchall") {
|
|
635
|
-
return `:${token.name}{.+}`;
|
|
636
|
-
}
|
|
637
|
-
return `:${token.name}{.+}?`;
|
|
638
|
-
});
|
|
639
|
-
return `/${segments.join("/")}`;
|
|
640
|
-
}
|
|
641
|
-
function isValidStatus(status) {
|
|
642
|
-
return typeof status === "number" && Number.isFinite(status) && status >= 200 && status <= 599;
|
|
643
|
-
}
|
|
644
|
-
function resolveStatus(routeStatus, responseStatus) {
|
|
645
|
-
if (isValidStatus(routeStatus)) {
|
|
646
|
-
return routeStatus;
|
|
647
|
-
}
|
|
648
|
-
if (isValidStatus(responseStatus)) {
|
|
649
|
-
return responseStatus;
|
|
650
|
-
}
|
|
651
|
-
return 200;
|
|
652
|
-
}
|
|
653
|
-
function applyRouteOverrides(response, route) {
|
|
654
|
-
const headers = new Headers(response.headers);
|
|
655
|
-
const hasHeaders = !!route.headers && Object.keys(route.headers).length > 0;
|
|
656
|
-
if (route.headers) {
|
|
657
|
-
for (const [key, value] of Object.entries(route.headers)) {
|
|
658
|
-
headers.set(key, value);
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
const status = resolveStatus(route.status, response.status);
|
|
662
|
-
if (status === response.status && !hasHeaders) {
|
|
663
|
-
return response;
|
|
664
|
-
}
|
|
665
|
-
return new Response(response.body, { status, headers });
|
|
666
|
-
}
|
|
667
|
-
function resolveResponse(value, fallback) {
|
|
668
|
-
if (value instanceof Response) {
|
|
669
|
-
return value;
|
|
670
|
-
}
|
|
671
|
-
if (value && typeof value === "object" && "res" in value) {
|
|
672
|
-
const resolved = value.res;
|
|
673
|
-
if (resolved instanceof Response) {
|
|
674
|
-
return resolved;
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
return fallback;
|
|
678
|
-
}
|
|
679
|
-
function normalizeHandlerValue(c, value) {
|
|
680
|
-
if (value instanceof Response) {
|
|
681
|
-
return value;
|
|
682
|
-
}
|
|
683
|
-
if (typeof value === "undefined") {
|
|
684
|
-
const response = c.body(null);
|
|
685
|
-
if (response.status === 200) {
|
|
686
|
-
return new Response(response.body, {
|
|
687
|
-
status: 204,
|
|
688
|
-
headers: response.headers
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
return response;
|
|
692
|
-
}
|
|
693
|
-
if (typeof value === "string") {
|
|
694
|
-
return c.text(value);
|
|
695
|
-
}
|
|
696
|
-
if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
|
|
697
|
-
if (!c.res.headers.get("content-type")) {
|
|
698
|
-
c.header("content-type", "application/octet-stream");
|
|
699
|
-
}
|
|
700
|
-
const data = value instanceof ArrayBuffer ? new Uint8Array(value) : new Uint8Array(value);
|
|
701
|
-
return c.body(data);
|
|
702
|
-
}
|
|
703
|
-
return c.json(value);
|
|
704
|
-
}
|
|
705
|
-
function createRouteHandler(route) {
|
|
706
|
-
return async (c) => {
|
|
707
|
-
const value = typeof route.handler === "function" ? await route.handler(c) : route.handler;
|
|
708
|
-
return normalizeHandlerValue(c, value);
|
|
709
|
-
};
|
|
710
|
-
}
|
|
711
|
-
function createFinalizeMiddleware(route) {
|
|
712
|
-
return async (c, next) => {
|
|
713
|
-
const response = await next();
|
|
714
|
-
const resolved = resolveResponse(response, c.res);
|
|
715
|
-
if (route.delay && route.delay > 0) {
|
|
716
|
-
await timing.delay(route.delay);
|
|
717
|
-
}
|
|
718
|
-
const overridden = applyRouteOverrides(resolved, route);
|
|
719
|
-
c.res = overridden;
|
|
720
|
-
return overridden;
|
|
721
|
-
};
|
|
722
|
-
}
|
|
723
|
-
function wrapMiddleware(handler) {
|
|
724
|
-
return async (c, next) => {
|
|
725
|
-
const response = await handler(c, next);
|
|
726
|
-
return resolveResponse(response, c.res);
|
|
727
|
-
};
|
|
728
|
-
}
|
|
729
|
-
function splitRouteMiddlewares(route) {
|
|
730
|
-
const before = [];
|
|
731
|
-
const normal = [];
|
|
732
|
-
const after = [];
|
|
733
|
-
for (const entry of route.middlewares ?? []) {
|
|
734
|
-
const wrapped = wrapMiddleware(entry.handle);
|
|
735
|
-
if (entry.position === "post") {
|
|
736
|
-
after.push(wrapped);
|
|
737
|
-
} else if (entry.position === "pre") {
|
|
738
|
-
before.push(wrapped);
|
|
739
|
-
} else {
|
|
740
|
-
normal.push(wrapped);
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
return { before, normal, after };
|
|
744
|
-
}
|
|
745
|
-
function createHonoApp(routes) {
|
|
746
|
-
const app = new hono.Hono({ router: new hono.PatternRouter(), strict: false });
|
|
747
|
-
for (const route of routes) {
|
|
748
|
-
const { before, normal, after } = splitRouteMiddlewares(route);
|
|
749
|
-
app.on(
|
|
750
|
-
route.method,
|
|
751
|
-
toHonoPath(route),
|
|
752
|
-
createFinalizeMiddleware(route),
|
|
753
|
-
...before,
|
|
754
|
-
...normal,
|
|
755
|
-
...after,
|
|
756
|
-
createRouteHandler(route)
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
return app;
|
|
760
|
-
}
|
|
761
|
-
async function readRawBody(req) {
|
|
762
|
-
return await new Promise((resolve, reject) => {
|
|
763
|
-
const chunks = [];
|
|
764
|
-
req.on("data", (chunk) => {
|
|
765
|
-
if (typeof chunk === "string") {
|
|
766
|
-
chunks.push(node_buffer.Buffer.from(chunk));
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
|
-
if (chunk instanceof Uint8Array) {
|
|
770
|
-
chunks.push(chunk);
|
|
771
|
-
return;
|
|
772
|
-
}
|
|
773
|
-
chunks.push(node_buffer.Buffer.from(String(chunk)));
|
|
774
|
-
});
|
|
775
|
-
req.on("end", () => {
|
|
776
|
-
if (chunks.length === 0) {
|
|
777
|
-
resolve(null);
|
|
778
|
-
return;
|
|
779
|
-
}
|
|
780
|
-
resolve(node_buffer.Buffer.concat(chunks));
|
|
781
|
-
});
|
|
782
|
-
req.on("error", reject);
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
function buildHeaders(headers) {
|
|
786
|
-
const result = new Headers();
|
|
787
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
788
|
-
if (typeof value === "undefined") {
|
|
789
|
-
continue;
|
|
790
|
-
}
|
|
791
|
-
if (Array.isArray(value)) {
|
|
792
|
-
result.set(key, value.join(","));
|
|
793
|
-
} else {
|
|
794
|
-
result.set(key, value);
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
return result;
|
|
798
|
-
}
|
|
799
|
-
async function toRequest(req) {
|
|
800
|
-
const url = new URL(req.url ?? "/", "http://mokup.local");
|
|
801
|
-
const method = req.method ?? "GET";
|
|
802
|
-
const headers = buildHeaders(req.headers);
|
|
803
|
-
const init = { method, headers };
|
|
804
|
-
const rawBody = await readRawBody(req);
|
|
805
|
-
if (rawBody && method !== "GET" && method !== "HEAD") {
|
|
806
|
-
init.body = rawBody;
|
|
807
|
-
}
|
|
808
|
-
return new Request(url.toString(), init);
|
|
809
|
-
}
|
|
810
|
-
async function sendResponse(res, response) {
|
|
811
|
-
res.statusCode = response.status;
|
|
812
|
-
response.headers.forEach((value, key) => {
|
|
813
|
-
res.setHeader(key, value);
|
|
814
|
-
});
|
|
815
|
-
if (!response.body) {
|
|
816
|
-
res.end();
|
|
817
|
-
return;
|
|
818
|
-
}
|
|
819
|
-
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
820
|
-
res.end(buffer);
|
|
821
|
-
}
|
|
822
|
-
function hasMatch(app, method, pathname) {
|
|
823
|
-
const matchMethod = method === "HEAD" ? "GET" : method;
|
|
824
|
-
const match = app.router.match(matchMethod, pathname);
|
|
825
|
-
return !!match && match[0].length > 0;
|
|
826
|
-
}
|
|
827
|
-
function createMiddleware(getApp, logger) {
|
|
828
|
-
return async (req, res, next) => {
|
|
829
|
-
const app = getApp();
|
|
830
|
-
if (!app) {
|
|
831
|
-
return next();
|
|
832
|
-
}
|
|
833
|
-
const url = req.url ?? "/";
|
|
834
|
-
const parsedUrl = new URL(url, "http://mokup.local");
|
|
835
|
-
const pathname = parsedUrl.pathname;
|
|
836
|
-
const method = normalizeMethod(req.method) ?? "GET";
|
|
837
|
-
if (!hasMatch(app, method, pathname)) {
|
|
838
|
-
return next();
|
|
839
|
-
}
|
|
840
|
-
const startedAt = Date.now();
|
|
841
|
-
try {
|
|
842
|
-
const response = await app.fetch(await toRequest(req));
|
|
843
|
-
if (res.writableEnded) {
|
|
844
|
-
return;
|
|
845
|
-
}
|
|
846
|
-
await sendResponse(res, response);
|
|
847
|
-
logger.info(`${method} ${pathname} ${Date.now() - startedAt}ms`);
|
|
848
|
-
} catch (error) {
|
|
849
|
-
if (!res.headersSent) {
|
|
850
|
-
res.statusCode = 500;
|
|
851
|
-
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
852
|
-
}
|
|
853
|
-
res.end("Mock handler error");
|
|
854
|
-
logger.error("Mock handler failed:", error);
|
|
855
|
-
}
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
const jsonExtensions = /* @__PURE__ */ new Set([".json", ".jsonc"]);
|
|
860
|
-
function resolveTemplate(template, prefix) {
|
|
861
|
-
const normalized = template.startsWith("/") ? template : `/${template}`;
|
|
862
|
-
if (!prefix) {
|
|
863
|
-
return normalized;
|
|
864
|
-
}
|
|
865
|
-
const normalizedPrefix = normalizePrefix(prefix);
|
|
866
|
-
if (!normalizedPrefix) {
|
|
867
|
-
return normalized;
|
|
868
|
-
}
|
|
869
|
-
if (normalized === normalizedPrefix || normalized.startsWith(`${normalizedPrefix}/`)) {
|
|
870
|
-
return normalized;
|
|
871
|
-
}
|
|
872
|
-
if (normalized === "/") {
|
|
873
|
-
return `${normalizedPrefix}/`;
|
|
874
|
-
}
|
|
875
|
-
return `${normalizedPrefix}${normalized}`;
|
|
876
|
-
}
|
|
877
|
-
function stripMethodSuffix(base) {
|
|
878
|
-
const segments = base.split(".");
|
|
879
|
-
const last = segments.at(-1);
|
|
880
|
-
if (last && manifest.methodSuffixSet.has(last.toLowerCase())) {
|
|
881
|
-
segments.pop();
|
|
882
|
-
return {
|
|
883
|
-
name: segments.join("."),
|
|
884
|
-
method: last.toUpperCase()
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
return {
|
|
888
|
-
name: base,
|
|
889
|
-
method: void 0
|
|
890
|
-
};
|
|
891
|
-
}
|
|
892
|
-
function deriveRouteFromFile(file, rootDir, logger) {
|
|
893
|
-
const rel = pathUtils.toPosix(pathe.relative(rootDir, file));
|
|
894
|
-
const ext = pathe.extname(rel);
|
|
895
|
-
const withoutExt = rel.slice(0, rel.length - ext.length);
|
|
896
|
-
const dir = pathe.dirname(withoutExt);
|
|
897
|
-
const base = pathe.basename(withoutExt);
|
|
898
|
-
const { name, method } = stripMethodSuffix(base);
|
|
899
|
-
const resolvedMethod = method ?? (jsonExtensions.has(ext) ? "GET" : void 0);
|
|
900
|
-
if (!resolvedMethod) {
|
|
901
|
-
logger.warn(`Skip mock without method suffix: ${file}`);
|
|
902
|
-
return null;
|
|
903
|
-
}
|
|
904
|
-
if (!name) {
|
|
905
|
-
logger.warn(`Skip mock with empty route name: ${file}`);
|
|
906
|
-
return null;
|
|
907
|
-
}
|
|
908
|
-
const joined = dir === "." ? name : pathe.join(dir, name);
|
|
909
|
-
const segments = pathUtils.toPosix(joined).split("/");
|
|
910
|
-
if (segments.at(-1) === "index") {
|
|
911
|
-
segments.pop();
|
|
912
|
-
}
|
|
913
|
-
const template = segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
914
|
-
const parsed = runtime.parseRouteTemplate(template);
|
|
915
|
-
if (parsed.errors.length > 0) {
|
|
916
|
-
for (const error of parsed.errors) {
|
|
917
|
-
logger.warn(`${error} in ${file}`);
|
|
918
|
-
}
|
|
919
|
-
return null;
|
|
920
|
-
}
|
|
921
|
-
for (const warning of parsed.warnings) {
|
|
922
|
-
logger.warn(`${warning} in ${file}`);
|
|
923
|
-
}
|
|
924
|
-
return {
|
|
925
|
-
template: parsed.template,
|
|
926
|
-
method: resolvedMethod,
|
|
927
|
-
tokens: parsed.tokens,
|
|
928
|
-
score: parsed.score
|
|
929
|
-
};
|
|
930
|
-
}
|
|
931
|
-
function resolveRule(params) {
|
|
932
|
-
const method = params.derivedMethod;
|
|
933
|
-
if (!method) {
|
|
934
|
-
params.logger.warn(`Skip mock without method suffix: ${params.file}`);
|
|
935
|
-
return null;
|
|
936
|
-
}
|
|
937
|
-
const template = resolveTemplate(params.derivedTemplate, params.prefix);
|
|
938
|
-
const parsed = runtime.parseRouteTemplate(template);
|
|
939
|
-
if (parsed.errors.length > 0) {
|
|
940
|
-
for (const error of parsed.errors) {
|
|
941
|
-
params.logger.warn(`${error} in ${params.file}`);
|
|
942
|
-
}
|
|
943
|
-
return null;
|
|
944
|
-
}
|
|
945
|
-
for (const warning of parsed.warnings) {
|
|
946
|
-
params.logger.warn(`${warning} in ${params.file}`);
|
|
947
|
-
}
|
|
948
|
-
const route = {
|
|
949
|
-
file: params.file,
|
|
950
|
-
template: parsed.template,
|
|
951
|
-
method,
|
|
952
|
-
tokens: parsed.tokens,
|
|
953
|
-
score: parsed.score,
|
|
954
|
-
handler: params.rule.handler
|
|
955
|
-
};
|
|
956
|
-
if (typeof params.rule.status === "number") {
|
|
957
|
-
route.status = params.rule.status;
|
|
958
|
-
}
|
|
959
|
-
if (params.rule.headers) {
|
|
960
|
-
route.headers = params.rule.headers;
|
|
961
|
-
}
|
|
962
|
-
if (typeof params.rule.delay === "number") {
|
|
963
|
-
route.delay = params.rule.delay;
|
|
964
|
-
}
|
|
965
|
-
return route;
|
|
966
|
-
}
|
|
967
|
-
function sortRoutes(routes) {
|
|
968
|
-
return routes.sort((a, b) => {
|
|
969
|
-
if (a.method !== b.method) {
|
|
970
|
-
return a.method.localeCompare(b.method);
|
|
971
|
-
}
|
|
972
|
-
const scoreCompare = runtime.compareRouteScore(a.score, b.score);
|
|
973
|
-
if (scoreCompare !== 0) {
|
|
974
|
-
return scoreCompare;
|
|
975
|
-
}
|
|
976
|
-
return a.template.localeCompare(b.template);
|
|
977
|
-
});
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
async function walkDir(dir, rootDir, files) {
|
|
981
|
-
const entries = await node_fs.promises.readdir(dir, { withFileTypes: true });
|
|
982
|
-
for (const entry of entries) {
|
|
983
|
-
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
984
|
-
continue;
|
|
985
|
-
}
|
|
986
|
-
const fullPath = pathe.join(dir, entry.name);
|
|
987
|
-
if (entry.isDirectory()) {
|
|
988
|
-
await walkDir(fullPath, rootDir, files);
|
|
989
|
-
continue;
|
|
990
|
-
}
|
|
991
|
-
if (entry.isFile()) {
|
|
992
|
-
files.push({ file: fullPath, rootDir });
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
async function exists(path) {
|
|
997
|
-
try {
|
|
998
|
-
await node_fs.promises.stat(path);
|
|
999
|
-
return true;
|
|
1000
|
-
} catch {
|
|
1001
|
-
return false;
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
async function collectFiles(dirs) {
|
|
1005
|
-
const files = [];
|
|
1006
|
-
for (const dir of dirs) {
|
|
1007
|
-
if (!await exists(dir)) {
|
|
1008
|
-
continue;
|
|
1009
|
-
}
|
|
1010
|
-
await walkDir(dir, dir, files);
|
|
1011
|
-
}
|
|
1012
|
-
return files;
|
|
1013
|
-
}
|
|
1014
|
-
function isConfigFile(file) {
|
|
1015
|
-
if (file.endsWith(".d.ts")) {
|
|
1016
|
-
return false;
|
|
1017
|
-
}
|
|
1018
|
-
const base = pathe.basename(file);
|
|
1019
|
-
if (!base.startsWith("index.config.")) {
|
|
1020
|
-
return false;
|
|
1021
|
-
}
|
|
1022
|
-
const ext = pathe.extname(file).toLowerCase();
|
|
1023
|
-
return manifest.configExtensions.includes(ext);
|
|
1024
|
-
}
|
|
1025
|
-
function isSupportedFile(file) {
|
|
1026
|
-
if (file.endsWith(".d.ts")) {
|
|
1027
|
-
return false;
|
|
1028
|
-
}
|
|
1029
|
-
if (isConfigFile(file)) {
|
|
1030
|
-
return false;
|
|
1031
|
-
}
|
|
1032
|
-
const ext = pathe.extname(file).toLowerCase();
|
|
1033
|
-
return manifest.supportedExtensions.has(ext);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
const sourceRoot = pathe.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.DXCs9518.cjs', document.baseURI).href))));
|
|
1037
|
-
function resolveWorkspaceEntry(candidates) {
|
|
1038
|
-
for (const candidate of candidates) {
|
|
1039
|
-
if (node_fs.existsSync(candidate)) {
|
|
1040
|
-
return candidate;
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
return null;
|
|
1044
|
-
}
|
|
1045
|
-
const mokupSourceEntry = resolveWorkspaceEntry([
|
|
1046
|
-
pathe.resolve(sourceRoot, "../index.ts"),
|
|
1047
|
-
pathe.resolve(sourceRoot, "../../src/index.ts")
|
|
1048
|
-
]);
|
|
1049
|
-
const mokupViteSourceEntry = resolveWorkspaceEntry([
|
|
1050
|
-
pathe.resolve(sourceRoot, "../vite.ts"),
|
|
1051
|
-
pathe.resolve(sourceRoot, "../../src/vite.ts")
|
|
1052
|
-
]);
|
|
1053
|
-
function createWorkspaceResolvePlugin() {
|
|
1054
|
-
if (!mokupSourceEntry && !mokupViteSourceEntry) {
|
|
1055
|
-
return null;
|
|
1056
|
-
}
|
|
1057
|
-
return {
|
|
1058
|
-
name: "mokup:resolve-workspace",
|
|
1059
|
-
setup(build) {
|
|
1060
|
-
if (mokupSourceEntry) {
|
|
1061
|
-
build.onResolve({ filter: /^mokup$/ }, () => ({ path: mokupSourceEntry }));
|
|
1062
|
-
}
|
|
1063
|
-
if (mokupViteSourceEntry) {
|
|
1064
|
-
build.onResolve({ filter: /^mokup\/vite$/ }, () => ({ path: mokupViteSourceEntry }));
|
|
1065
|
-
}
|
|
1066
|
-
}
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
const workspaceResolvePlugin = createWorkspaceResolvePlugin();
|
|
1070
|
-
async function loadModule(file) {
|
|
1071
|
-
const ext = pathe.extname(file).toLowerCase();
|
|
1072
|
-
if (ext === ".cjs") {
|
|
1073
|
-
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('shared/mokup.DXCs9518.cjs', document.baseURI).href)));
|
|
1074
|
-
delete require$1.cache[file];
|
|
1075
|
-
return require$1(file);
|
|
1076
|
-
}
|
|
1077
|
-
if (ext === ".js" || ext === ".mjs") {
|
|
1078
|
-
return import(`${node_url.pathToFileURL(file).href}?t=${Date.now()}`);
|
|
1079
|
-
}
|
|
1080
|
-
if (ext === ".ts") {
|
|
1081
|
-
const result = await esbuild.build({
|
|
1082
|
-
entryPoints: [file],
|
|
1083
|
-
bundle: true,
|
|
1084
|
-
format: "esm",
|
|
1085
|
-
platform: "node",
|
|
1086
|
-
sourcemap: "inline",
|
|
1087
|
-
target: "es2020",
|
|
1088
|
-
write: false,
|
|
1089
|
-
...workspaceResolvePlugin ? { plugins: [workspaceResolvePlugin] } : {}
|
|
1090
|
-
});
|
|
1091
|
-
const output = result.outputFiles[0];
|
|
1092
|
-
const code = output?.text ?? "";
|
|
1093
|
-
const dataUrl = `data:text/javascript;base64,${node_buffer.Buffer.from(code).toString(
|
|
1094
|
-
"base64"
|
|
1095
|
-
)}`;
|
|
1096
|
-
return import(`${dataUrl}#${Date.now()}`);
|
|
1097
|
-
}
|
|
1098
|
-
return null;
|
|
1099
|
-
}
|
|
1100
|
-
async function loadModuleWithVite(server, file) {
|
|
1101
|
-
const asDevServer = server;
|
|
1102
|
-
if ("ssrLoadModule" in asDevServer) {
|
|
1103
|
-
const moduleNode = asDevServer.moduleGraph.getModuleById(file);
|
|
1104
|
-
if (moduleNode) {
|
|
1105
|
-
asDevServer.moduleGraph.invalidateModule(moduleNode);
|
|
1106
|
-
}
|
|
1107
|
-
return asDevServer.ssrLoadModule(file);
|
|
1108
|
-
}
|
|
1109
|
-
return loadModule(file);
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
const middlewareSymbol = Symbol.for("mokup.config.middlewares");
|
|
1113
|
-
function getConfigFileCandidates(dir) {
|
|
1114
|
-
return manifest.configExtensions.map((extension) => pathe.join(dir, `index.config${extension}`));
|
|
1115
|
-
}
|
|
1116
|
-
async function findConfigFile(dir, cache) {
|
|
1117
|
-
const cached = cache.get(dir);
|
|
1118
|
-
if (cached !== void 0) {
|
|
1119
|
-
return cached;
|
|
1120
|
-
}
|
|
1121
|
-
for (const candidate of getConfigFileCandidates(dir)) {
|
|
1122
|
-
try {
|
|
1123
|
-
await node_fs.promises.stat(candidate);
|
|
1124
|
-
cache.set(dir, candidate);
|
|
1125
|
-
return candidate;
|
|
1126
|
-
} catch {
|
|
1127
|
-
continue;
|
|
1128
|
-
}
|
|
1129
|
-
}
|
|
1130
|
-
cache.set(dir, null);
|
|
1131
|
-
return null;
|
|
1132
|
-
}
|
|
1133
|
-
async function loadConfig(file, server) {
|
|
1134
|
-
const mod = server ? await loadModuleWithVite(server, file) : await loadModule(file);
|
|
1135
|
-
if (!mod) {
|
|
1136
|
-
return null;
|
|
1137
|
-
}
|
|
1138
|
-
const raw = mod?.default ?? mod;
|
|
1139
|
-
const value = isPromise(raw) ? await raw : raw;
|
|
1140
|
-
if (!value || typeof value !== "object") {
|
|
1141
|
-
return null;
|
|
1142
|
-
}
|
|
1143
|
-
return value;
|
|
1144
|
-
}
|
|
1145
|
-
function isPromise(value) {
|
|
1146
|
-
return !!value && typeof value.then === "function";
|
|
1147
|
-
}
|
|
1148
|
-
function normalizeMiddlewares(value, source, logger, position) {
|
|
1149
|
-
if (!value) {
|
|
1150
|
-
return [];
|
|
1151
|
-
}
|
|
1152
|
-
const list = Array.isArray(value) ? value : [value];
|
|
1153
|
-
const middlewares = [];
|
|
1154
|
-
for (const [index, entry] of list.entries()) {
|
|
1155
|
-
if (typeof entry !== "function") {
|
|
1156
|
-
logger.warn(`Invalid middleware in ${source}`);
|
|
1157
|
-
continue;
|
|
1158
|
-
}
|
|
1159
|
-
middlewares.push({
|
|
1160
|
-
handle: entry,
|
|
1161
|
-
source,
|
|
1162
|
-
index,
|
|
1163
|
-
position
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
return middlewares;
|
|
1167
|
-
}
|
|
1168
|
-
function readMiddlewareMeta(config) {
|
|
1169
|
-
const value = config[middlewareSymbol];
|
|
1170
|
-
if (!value || typeof value !== "object") {
|
|
1171
|
-
return null;
|
|
1172
|
-
}
|
|
1173
|
-
const meta = value;
|
|
1174
|
-
return {
|
|
1175
|
-
pre: Array.isArray(meta.pre) ? meta.pre : [],
|
|
1176
|
-
normal: Array.isArray(meta.normal) ? meta.normal : [],
|
|
1177
|
-
post: Array.isArray(meta.post) ? meta.post : []
|
|
1178
|
-
};
|
|
1179
|
-
}
|
|
1180
|
-
async function resolveDirectoryConfig(params) {
|
|
1181
|
-
const { file, rootDir, server, logger, configCache, fileCache } = params;
|
|
1182
|
-
const resolvedRoot = pathe.normalize(rootDir);
|
|
1183
|
-
const resolvedFileDir = pathe.normalize(pathe.dirname(file));
|
|
1184
|
-
const chain = [];
|
|
1185
|
-
let current = resolvedFileDir;
|
|
1186
|
-
while (true) {
|
|
1187
|
-
chain.push(current);
|
|
1188
|
-
if (current === resolvedRoot) {
|
|
1189
|
-
break;
|
|
1190
|
-
}
|
|
1191
|
-
const parent = pathe.dirname(current);
|
|
1192
|
-
if (parent === current) {
|
|
1193
|
-
break;
|
|
1194
|
-
}
|
|
1195
|
-
current = parent;
|
|
1196
|
-
}
|
|
1197
|
-
chain.reverse();
|
|
1198
|
-
const merged = {};
|
|
1199
|
-
const preMiddlewares = [];
|
|
1200
|
-
const normalMiddlewares = [];
|
|
1201
|
-
const postMiddlewares = [];
|
|
1202
|
-
const configChain = [];
|
|
1203
|
-
const configSources = {};
|
|
1204
|
-
for (const dir of chain) {
|
|
1205
|
-
const configPath = await findConfigFile(dir, fileCache);
|
|
1206
|
-
if (!configPath) {
|
|
1207
|
-
continue;
|
|
1208
|
-
}
|
|
1209
|
-
let config = configCache.get(configPath);
|
|
1210
|
-
if (config === void 0) {
|
|
1211
|
-
config = await loadConfig(configPath, server);
|
|
1212
|
-
configCache.set(configPath, config);
|
|
1213
|
-
}
|
|
1214
|
-
if (!config) {
|
|
1215
|
-
logger.warn(`Invalid config in ${configPath}`);
|
|
1216
|
-
continue;
|
|
1217
|
-
}
|
|
1218
|
-
configChain.push(configPath);
|
|
1219
|
-
if (config.headers) {
|
|
1220
|
-
merged.headers = { ...merged.headers ?? {}, ...config.headers };
|
|
1221
|
-
configSources.headers = configPath;
|
|
1222
|
-
}
|
|
1223
|
-
if (typeof config.status === "number") {
|
|
1224
|
-
merged.status = config.status;
|
|
1225
|
-
configSources.status = configPath;
|
|
1226
|
-
}
|
|
1227
|
-
if (typeof config.delay === "number") {
|
|
1228
|
-
merged.delay = config.delay;
|
|
1229
|
-
configSources.delay = configPath;
|
|
1230
|
-
}
|
|
1231
|
-
if (typeof config.enabled === "boolean") {
|
|
1232
|
-
merged.enabled = config.enabled;
|
|
1233
|
-
configSources.enabled = configPath;
|
|
1234
|
-
}
|
|
1235
|
-
if (typeof config.ignorePrefix !== "undefined") {
|
|
1236
|
-
merged.ignorePrefix = config.ignorePrefix;
|
|
1237
|
-
configSources.ignorePrefix = configPath;
|
|
1238
|
-
}
|
|
1239
|
-
if (typeof config.include !== "undefined") {
|
|
1240
|
-
merged.include = config.include;
|
|
1241
|
-
configSources.include = configPath;
|
|
1242
|
-
}
|
|
1243
|
-
if (typeof config.exclude !== "undefined") {
|
|
1244
|
-
merged.exclude = config.exclude;
|
|
1245
|
-
configSources.exclude = configPath;
|
|
1246
|
-
}
|
|
1247
|
-
const meta = readMiddlewareMeta(config);
|
|
1248
|
-
const normalizedPre = normalizeMiddlewares(
|
|
1249
|
-
meta?.pre,
|
|
1250
|
-
configPath,
|
|
1251
|
-
logger,
|
|
1252
|
-
"pre"
|
|
1253
|
-
);
|
|
1254
|
-
const normalizedNormal = normalizeMiddlewares(
|
|
1255
|
-
meta?.normal,
|
|
1256
|
-
configPath,
|
|
1257
|
-
logger,
|
|
1258
|
-
"normal"
|
|
1259
|
-
);
|
|
1260
|
-
const normalizedLegacy = normalizeMiddlewares(
|
|
1261
|
-
config.middleware,
|
|
1262
|
-
configPath,
|
|
1263
|
-
logger,
|
|
1264
|
-
"normal"
|
|
1265
|
-
);
|
|
1266
|
-
const normalizedPost = normalizeMiddlewares(
|
|
1267
|
-
meta?.post,
|
|
1268
|
-
configPath,
|
|
1269
|
-
logger,
|
|
1270
|
-
"post"
|
|
1271
|
-
);
|
|
1272
|
-
if (normalizedPre.length > 0) {
|
|
1273
|
-
preMiddlewares.push(...normalizedPre);
|
|
1274
|
-
}
|
|
1275
|
-
if (normalizedNormal.length > 0) {
|
|
1276
|
-
normalMiddlewares.push(...normalizedNormal);
|
|
1277
|
-
}
|
|
1278
|
-
if (normalizedLegacy.length > 0) {
|
|
1279
|
-
normalMiddlewares.push(...normalizedLegacy);
|
|
1280
|
-
}
|
|
1281
|
-
if (normalizedPost.length > 0) {
|
|
1282
|
-
postMiddlewares.push(...normalizedPost);
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
return {
|
|
1286
|
-
...merged,
|
|
1287
|
-
middlewares: [...preMiddlewares, ...normalMiddlewares, ...postMiddlewares],
|
|
1288
|
-
configChain,
|
|
1289
|
-
configSources
|
|
1290
|
-
};
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
async function readJsonFile(file, logger) {
|
|
1294
|
-
try {
|
|
1295
|
-
const content = await node_fs.promises.readFile(file, "utf8");
|
|
1296
|
-
const errors = [];
|
|
1297
|
-
const data = jsoncParser.parse(content, errors, {
|
|
1298
|
-
allowTrailingComma: true,
|
|
1299
|
-
disallowComments: false
|
|
1300
|
-
});
|
|
1301
|
-
if (errors.length > 0) {
|
|
1302
|
-
logger.warn(`Invalid JSONC in ${file}`);
|
|
1303
|
-
return void 0;
|
|
1304
|
-
}
|
|
1305
|
-
return data;
|
|
1306
|
-
} catch (error) {
|
|
1307
|
-
logger.warn(`Failed to read ${file}: ${String(error)}`);
|
|
1308
|
-
return void 0;
|
|
1309
|
-
}
|
|
1310
|
-
}
|
|
1311
|
-
async function loadRules(file, server, logger) {
|
|
1312
|
-
const ext = pathe.extname(file).toLowerCase();
|
|
1313
|
-
if (ext === ".json" || ext === ".jsonc") {
|
|
1314
|
-
const json = await readJsonFile(file, logger);
|
|
1315
|
-
if (typeof json === "undefined") {
|
|
1316
|
-
return [];
|
|
1317
|
-
}
|
|
1318
|
-
return [
|
|
1319
|
-
{
|
|
1320
|
-
handler: json
|
|
1321
|
-
}
|
|
1322
|
-
];
|
|
1323
|
-
}
|
|
1324
|
-
const mod = server ? await loadModuleWithVite(server, file) : await loadModule(file);
|
|
1325
|
-
const value = mod?.default ?? mod;
|
|
1326
|
-
if (!value) {
|
|
1327
|
-
return [];
|
|
1328
|
-
}
|
|
1329
|
-
if (Array.isArray(value)) {
|
|
1330
|
-
return value;
|
|
1331
|
-
}
|
|
1332
|
-
if (typeof value === "function") {
|
|
1333
|
-
return [
|
|
1334
|
-
{
|
|
1335
|
-
handler: value
|
|
1336
|
-
}
|
|
1337
|
-
];
|
|
1338
|
-
}
|
|
1339
|
-
return [value];
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
const silentLogger = {
|
|
1343
|
-
info: () => {
|
|
1344
|
-
},
|
|
1345
|
-
warn: () => {
|
|
1346
|
-
},
|
|
1347
|
-
error: () => {
|
|
1348
|
-
},
|
|
1349
|
-
log: () => {
|
|
1350
|
-
}
|
|
1351
|
-
};
|
|
1352
|
-
function resolveSkipRoute(params) {
|
|
1353
|
-
const derived = params.derived ?? deriveRouteFromFile(params.file, params.rootDir, silentLogger);
|
|
1354
|
-
if (!derived?.method) {
|
|
1355
|
-
return null;
|
|
1356
|
-
}
|
|
1357
|
-
const resolved = resolveRule({
|
|
1358
|
-
rule: { handler: null },
|
|
1359
|
-
derivedTemplate: derived.template,
|
|
1360
|
-
derivedMethod: derived.method,
|
|
1361
|
-
prefix: params.prefix,
|
|
1362
|
-
file: params.file,
|
|
1363
|
-
logger: silentLogger
|
|
1364
|
-
});
|
|
1365
|
-
if (!resolved) {
|
|
1366
|
-
return null;
|
|
1367
|
-
}
|
|
1368
|
-
return {
|
|
1369
|
-
method: resolved.method,
|
|
1370
|
-
url: resolved.template
|
|
1371
|
-
};
|
|
1372
|
-
}
|
|
1373
|
-
function buildSkipInfo(file, reason, resolved, configChain, decisionChain, effectiveConfig) {
|
|
1374
|
-
const info = { file, reason };
|
|
1375
|
-
if (resolved) {
|
|
1376
|
-
info.method = resolved.method;
|
|
1377
|
-
info.url = resolved.url;
|
|
1378
|
-
}
|
|
1379
|
-
if (configChain && configChain.length > 0) {
|
|
1380
|
-
info.configChain = configChain;
|
|
1381
|
-
}
|
|
1382
|
-
if (decisionChain && decisionChain.length > 0) {
|
|
1383
|
-
info.decisionChain = decisionChain;
|
|
1384
|
-
}
|
|
1385
|
-
if (effectiveConfig && Object.keys(effectiveConfig).length > 0) {
|
|
1386
|
-
info.effectiveConfig = effectiveConfig;
|
|
1387
|
-
}
|
|
1388
|
-
return info;
|
|
1389
|
-
}
|
|
1390
|
-
function toFilterStrings(value) {
|
|
1391
|
-
if (!value) {
|
|
1392
|
-
return [];
|
|
1393
|
-
}
|
|
1394
|
-
const list = Array.isArray(value) ? value : [value];
|
|
1395
|
-
return list.filter((entry) => entry instanceof RegExp).map((entry) => entry.toString());
|
|
1396
|
-
}
|
|
1397
|
-
function toStringList(value) {
|
|
1398
|
-
return value.length === 1 ? value[0] : [...value];
|
|
1399
|
-
}
|
|
1400
|
-
function formatList(value) {
|
|
1401
|
-
return value.join(", ");
|
|
1402
|
-
}
|
|
1403
|
-
function testPatterns(patterns, value) {
|
|
1404
|
-
const list = Array.isArray(patterns) ? patterns : [patterns];
|
|
1405
|
-
return list.some((pattern) => pattern.test(value));
|
|
1406
|
-
}
|
|
1407
|
-
function buildEffectiveConfig(params) {
|
|
1408
|
-
const { config, effectiveInclude, effectiveExclude, effectiveIgnorePrefix } = params;
|
|
1409
|
-
const includeList = toFilterStrings(effectiveInclude);
|
|
1410
|
-
const excludeList = toFilterStrings(effectiveExclude);
|
|
1411
|
-
const effectiveConfig = {};
|
|
1412
|
-
if (config.headers && Object.keys(config.headers).length > 0) {
|
|
1413
|
-
effectiveConfig.headers = config.headers;
|
|
1414
|
-
}
|
|
1415
|
-
if (typeof config.status === "number") {
|
|
1416
|
-
effectiveConfig.status = config.status;
|
|
1417
|
-
}
|
|
1418
|
-
if (typeof config.delay === "number") {
|
|
1419
|
-
effectiveConfig.delay = config.delay;
|
|
1420
|
-
}
|
|
1421
|
-
if (typeof config.enabled !== "undefined") {
|
|
1422
|
-
effectiveConfig.enabled = config.enabled;
|
|
1423
|
-
}
|
|
1424
|
-
if (effectiveIgnorePrefix.length > 0) {
|
|
1425
|
-
effectiveConfig.ignorePrefix = toStringList(effectiveIgnorePrefix);
|
|
1426
|
-
}
|
|
1427
|
-
if (includeList.length > 0) {
|
|
1428
|
-
effectiveConfig.include = toStringList(includeList);
|
|
1429
|
-
}
|
|
1430
|
-
if (excludeList.length > 0) {
|
|
1431
|
-
effectiveConfig.exclude = toStringList(excludeList);
|
|
1432
|
-
}
|
|
1433
|
-
return effectiveConfig;
|
|
1434
|
-
}
|
|
1435
|
-
|
|
1436
|
-
function pushDecisionStep(chain, entry) {
|
|
1437
|
-
const step = {
|
|
1438
|
-
step: entry.step,
|
|
1439
|
-
result: entry.result
|
|
1440
|
-
};
|
|
1441
|
-
if (typeof entry.source !== "undefined") {
|
|
1442
|
-
step.source = entry.source;
|
|
1443
|
-
}
|
|
1444
|
-
if (typeof entry.detail !== "undefined") {
|
|
1445
|
-
step.detail = entry.detail;
|
|
1446
|
-
}
|
|
1447
|
-
chain.push(step);
|
|
1448
|
-
}
|
|
1449
|
-
function runRoutePrechecks(params) {
|
|
1450
|
-
const {
|
|
1451
|
-
fileInfo,
|
|
1452
|
-
prefix,
|
|
1453
|
-
config,
|
|
1454
|
-
configChain,
|
|
1455
|
-
globalIgnorePrefix,
|
|
1456
|
-
include,
|
|
1457
|
-
exclude,
|
|
1458
|
-
shouldCollectSkip,
|
|
1459
|
-
shouldCollectIgnore,
|
|
1460
|
-
onSkip,
|
|
1461
|
-
onIgnore
|
|
1462
|
-
} = params;
|
|
1463
|
-
const configSources = config.configSources ?? {};
|
|
1464
|
-
const decisionChain = [];
|
|
1465
|
-
const isConfigEnabled = config.enabled !== false;
|
|
1466
|
-
pushDecisionStep(decisionChain, {
|
|
1467
|
-
step: "config.enabled",
|
|
1468
|
-
result: isConfigEnabled ? "pass" : "fail",
|
|
1469
|
-
source: configSources.enabled,
|
|
1470
|
-
detail: config.enabled === false ? "enabled=false" : typeof config.enabled === "boolean" ? "enabled=true" : "enabled=true (default)"
|
|
1471
|
-
});
|
|
1472
|
-
const effectiveIgnorePrefix = typeof config.ignorePrefix !== "undefined" ? normalizeIgnorePrefix(config.ignorePrefix, []) : globalIgnorePrefix;
|
|
1473
|
-
const effectiveInclude = typeof config.include !== "undefined" ? config.include : include;
|
|
1474
|
-
const effectiveExclude = typeof config.exclude !== "undefined" ? config.exclude : exclude;
|
|
1475
|
-
const effectiveConfigParams = {
|
|
1476
|
-
config,
|
|
1477
|
-
effectiveIgnorePrefix
|
|
1478
|
-
};
|
|
1479
|
-
if (typeof effectiveInclude !== "undefined") {
|
|
1480
|
-
effectiveConfigParams.effectiveInclude = effectiveInclude;
|
|
1481
|
-
}
|
|
1482
|
-
if (typeof effectiveExclude !== "undefined") {
|
|
1483
|
-
effectiveConfigParams.effectiveExclude = effectiveExclude;
|
|
1484
|
-
}
|
|
1485
|
-
const effectiveConfig = buildEffectiveConfig(effectiveConfigParams);
|
|
1486
|
-
const effectiveConfigValue = Object.keys(effectiveConfig).length > 0 ? effectiveConfig : void 0;
|
|
1487
|
-
if (!isConfigEnabled) {
|
|
1488
|
-
if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
|
|
1489
|
-
const resolved = resolveSkipRoute({
|
|
1490
|
-
file: fileInfo.file,
|
|
1491
|
-
rootDir: fileInfo.rootDir,
|
|
1492
|
-
prefix
|
|
1493
|
-
});
|
|
1494
|
-
onSkip?.(buildSkipInfo(
|
|
1495
|
-
fileInfo.file,
|
|
1496
|
-
"disabled-dir",
|
|
1497
|
-
resolved,
|
|
1498
|
-
configChain,
|
|
1499
|
-
decisionChain,
|
|
1500
|
-
effectiveConfigValue
|
|
1501
|
-
));
|
|
1502
|
-
}
|
|
1503
|
-
return null;
|
|
1504
|
-
}
|
|
1505
|
-
if (effectiveIgnorePrefix.length > 0) {
|
|
1506
|
-
const ignoredByPrefix = pathUtils.hasIgnoredPrefix(fileInfo.file, fileInfo.rootDir, effectiveIgnorePrefix);
|
|
1507
|
-
pushDecisionStep(decisionChain, {
|
|
1508
|
-
step: "ignore-prefix",
|
|
1509
|
-
result: ignoredByPrefix ? "fail" : "pass",
|
|
1510
|
-
source: configSources.ignorePrefix,
|
|
1511
|
-
detail: `prefixes: ${formatList(effectiveIgnorePrefix)}`
|
|
1512
|
-
});
|
|
1513
|
-
if (ignoredByPrefix) {
|
|
1514
|
-
if (shouldCollectSkip && isSupportedFile(fileInfo.file)) {
|
|
1515
|
-
const resolved = resolveSkipRoute({
|
|
1516
|
-
file: fileInfo.file,
|
|
1517
|
-
rootDir: fileInfo.rootDir,
|
|
1518
|
-
prefix
|
|
1519
|
-
});
|
|
1520
|
-
onSkip?.(buildSkipInfo(
|
|
1521
|
-
fileInfo.file,
|
|
1522
|
-
"ignore-prefix",
|
|
1523
|
-
resolved,
|
|
1524
|
-
configChain,
|
|
1525
|
-
decisionChain,
|
|
1526
|
-
effectiveConfigValue
|
|
1527
|
-
));
|
|
1528
|
-
}
|
|
1529
|
-
return null;
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
const supportedFile = isSupportedFile(fileInfo.file);
|
|
1533
|
-
pushDecisionStep(decisionChain, {
|
|
1534
|
-
step: "file.supported",
|
|
1535
|
-
result: supportedFile ? "pass" : "fail",
|
|
1536
|
-
detail: supportedFile ? void 0 : "unsupported file type"
|
|
1537
|
-
});
|
|
1538
|
-
if (!supportedFile) {
|
|
1539
|
-
if (shouldCollectIgnore) {
|
|
1540
|
-
const ignoreInfo = {
|
|
1541
|
-
file: fileInfo.file,
|
|
1542
|
-
reason: "unsupported",
|
|
1543
|
-
configChain,
|
|
1544
|
-
decisionChain
|
|
1545
|
-
};
|
|
1546
|
-
if (effectiveConfigValue) {
|
|
1547
|
-
ignoreInfo.effectiveConfig = effectiveConfigValue;
|
|
1548
|
-
}
|
|
1549
|
-
onIgnore?.(ignoreInfo);
|
|
1550
|
-
}
|
|
1551
|
-
return null;
|
|
1552
|
-
}
|
|
1553
|
-
const normalizedFile = pathUtils.toPosix(fileInfo.file);
|
|
1554
|
-
if (typeof effectiveExclude !== "undefined") {
|
|
1555
|
-
const excluded = testPatterns(effectiveExclude, normalizedFile);
|
|
1556
|
-
const patterns = toFilterStrings(effectiveExclude);
|
|
1557
|
-
pushDecisionStep(decisionChain, {
|
|
1558
|
-
step: "filter.exclude",
|
|
1559
|
-
result: excluded ? "fail" : "pass",
|
|
1560
|
-
source: configSources.exclude,
|
|
1561
|
-
detail: patterns.length > 0 ? `${excluded ? "matched" : "no match"}: ${patterns.join(", ")}` : void 0
|
|
1562
|
-
});
|
|
1563
|
-
if (excluded) {
|
|
1564
|
-
if (shouldCollectSkip) {
|
|
1565
|
-
const resolved = resolveSkipRoute({
|
|
1566
|
-
file: fileInfo.file,
|
|
1567
|
-
rootDir: fileInfo.rootDir,
|
|
1568
|
-
prefix
|
|
1569
|
-
});
|
|
1570
|
-
onSkip?.(buildSkipInfo(
|
|
1571
|
-
fileInfo.file,
|
|
1572
|
-
"exclude",
|
|
1573
|
-
resolved,
|
|
1574
|
-
configChain,
|
|
1575
|
-
decisionChain,
|
|
1576
|
-
effectiveConfigValue
|
|
1577
|
-
));
|
|
1578
|
-
}
|
|
1579
|
-
return null;
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
if (typeof effectiveInclude !== "undefined") {
|
|
1583
|
-
const included = testPatterns(effectiveInclude, normalizedFile);
|
|
1584
|
-
const patterns = toFilterStrings(effectiveInclude);
|
|
1585
|
-
pushDecisionStep(decisionChain, {
|
|
1586
|
-
step: "filter.include",
|
|
1587
|
-
result: included ? "pass" : "fail",
|
|
1588
|
-
source: configSources.include,
|
|
1589
|
-
detail: patterns.length > 0 ? `${included ? "matched" : "no match"}: ${patterns.join(", ")}` : void 0
|
|
1590
|
-
});
|
|
1591
|
-
if (!included) {
|
|
1592
|
-
if (shouldCollectSkip) {
|
|
1593
|
-
const resolved = resolveSkipRoute({
|
|
1594
|
-
file: fileInfo.file,
|
|
1595
|
-
rootDir: fileInfo.rootDir,
|
|
1596
|
-
prefix
|
|
1597
|
-
});
|
|
1598
|
-
onSkip?.(buildSkipInfo(
|
|
1599
|
-
fileInfo.file,
|
|
1600
|
-
"include",
|
|
1601
|
-
resolved,
|
|
1602
|
-
configChain,
|
|
1603
|
-
decisionChain,
|
|
1604
|
-
effectiveConfigValue
|
|
1605
|
-
));
|
|
1606
|
-
}
|
|
1607
|
-
return null;
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
const result = { decisionChain };
|
|
1611
|
-
if (effectiveConfigValue) {
|
|
1612
|
-
result.effectiveConfigValue = effectiveConfigValue;
|
|
1613
|
-
}
|
|
1614
|
-
return result;
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
async function scanRoutes(params) {
|
|
1618
|
-
const routes = [];
|
|
1619
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1620
|
-
const files = await collectFiles(params.dirs);
|
|
1621
|
-
const globalIgnorePrefix = normalizeIgnorePrefix(params.ignorePrefix);
|
|
1622
|
-
const configCache = /* @__PURE__ */ new Map();
|
|
1623
|
-
const fileCache = /* @__PURE__ */ new Map();
|
|
1624
|
-
const shouldCollectSkip = typeof params.onSkip === "function";
|
|
1625
|
-
const shouldCollectIgnore = typeof params.onIgnore === "function";
|
|
1626
|
-
const shouldCollectConfig = typeof params.onConfig === "function";
|
|
1627
|
-
for (const fileInfo of files) {
|
|
1628
|
-
if (isConfigFile(fileInfo.file)) {
|
|
1629
|
-
if (shouldCollectConfig) {
|
|
1630
|
-
const configParams2 = {
|
|
1631
|
-
file: fileInfo.file,
|
|
1632
|
-
rootDir: fileInfo.rootDir,
|
|
1633
|
-
logger: params.logger,
|
|
1634
|
-
configCache,
|
|
1635
|
-
fileCache
|
|
1636
|
-
};
|
|
1637
|
-
if (params.server) {
|
|
1638
|
-
configParams2.server = params.server;
|
|
1639
|
-
}
|
|
1640
|
-
const config2 = await resolveDirectoryConfig(configParams2);
|
|
1641
|
-
params.onConfig?.({ file: fileInfo.file, enabled: config2.enabled !== false });
|
|
1642
|
-
}
|
|
1643
|
-
continue;
|
|
1644
|
-
}
|
|
1645
|
-
const configParams = {
|
|
1646
|
-
file: fileInfo.file,
|
|
1647
|
-
rootDir: fileInfo.rootDir,
|
|
1648
|
-
logger: params.logger,
|
|
1649
|
-
configCache,
|
|
1650
|
-
fileCache
|
|
1651
|
-
};
|
|
1652
|
-
if (params.server) {
|
|
1653
|
-
configParams.server = params.server;
|
|
1654
|
-
}
|
|
1655
|
-
const config = await resolveDirectoryConfig(configParams);
|
|
1656
|
-
const configChain = config.configChain ?? [];
|
|
1657
|
-
const precheckParams = {
|
|
1658
|
-
fileInfo,
|
|
1659
|
-
prefix: params.prefix,
|
|
1660
|
-
config,
|
|
1661
|
-
configChain,
|
|
1662
|
-
globalIgnorePrefix,
|
|
1663
|
-
shouldCollectSkip,
|
|
1664
|
-
shouldCollectIgnore
|
|
1665
|
-
};
|
|
1666
|
-
if (params.onSkip) {
|
|
1667
|
-
precheckParams.onSkip = params.onSkip;
|
|
1668
|
-
}
|
|
1669
|
-
if (params.onIgnore) {
|
|
1670
|
-
precheckParams.onIgnore = params.onIgnore;
|
|
1671
|
-
}
|
|
1672
|
-
if (params.include) {
|
|
1673
|
-
precheckParams.include = params.include;
|
|
1674
|
-
}
|
|
1675
|
-
if (params.exclude) {
|
|
1676
|
-
precheckParams.exclude = params.exclude;
|
|
1677
|
-
}
|
|
1678
|
-
const precheck = runRoutePrechecks(precheckParams);
|
|
1679
|
-
if (!precheck) {
|
|
1680
|
-
continue;
|
|
1681
|
-
}
|
|
1682
|
-
const { decisionChain, effectiveConfigValue } = precheck;
|
|
1683
|
-
const derived = deriveRouteFromFile(fileInfo.file, fileInfo.rootDir, params.logger);
|
|
1684
|
-
if (!derived) {
|
|
1685
|
-
if (shouldCollectIgnore) {
|
|
1686
|
-
decisionChain.push({
|
|
1687
|
-
step: "route.derived",
|
|
1688
|
-
result: "fail",
|
|
1689
|
-
source: fileInfo.file,
|
|
1690
|
-
detail: "invalid route name"
|
|
1691
|
-
});
|
|
1692
|
-
const ignoreInfo = {
|
|
1693
|
-
file: fileInfo.file,
|
|
1694
|
-
reason: "invalid-route",
|
|
1695
|
-
configChain,
|
|
1696
|
-
decisionChain
|
|
1697
|
-
};
|
|
1698
|
-
if (effectiveConfigValue) {
|
|
1699
|
-
ignoreInfo.effectiveConfig = effectiveConfigValue;
|
|
1700
|
-
}
|
|
1701
|
-
params.onIgnore?.(ignoreInfo);
|
|
1702
|
-
}
|
|
1703
|
-
continue;
|
|
1704
|
-
}
|
|
1705
|
-
decisionChain.push({
|
|
1706
|
-
step: "route.derived",
|
|
1707
|
-
result: "pass",
|
|
1708
|
-
source: fileInfo.file
|
|
1709
|
-
});
|
|
1710
|
-
const rules = await loadRules(fileInfo.file, params.server, params.logger);
|
|
1711
|
-
for (const [index, rule] of rules.entries()) {
|
|
1712
|
-
if (!rule || typeof rule !== "object") {
|
|
1713
|
-
continue;
|
|
1714
|
-
}
|
|
1715
|
-
if (rule.enabled === false) {
|
|
1716
|
-
if (shouldCollectSkip) {
|
|
1717
|
-
const resolved2 = resolveSkipRoute({
|
|
1718
|
-
file: fileInfo.file,
|
|
1719
|
-
rootDir: fileInfo.rootDir,
|
|
1720
|
-
prefix: params.prefix,
|
|
1721
|
-
derived
|
|
1722
|
-
});
|
|
1723
|
-
const ruleDecisionStep = {
|
|
1724
|
-
step: "rule.enabled",
|
|
1725
|
-
result: "fail",
|
|
1726
|
-
source: fileInfo.file,
|
|
1727
|
-
detail: "enabled=false"
|
|
1728
|
-
};
|
|
1729
|
-
const ruleDecisionChain = [...decisionChain, ruleDecisionStep];
|
|
1730
|
-
params.onSkip?.(buildSkipInfo(
|
|
1731
|
-
fileInfo.file,
|
|
1732
|
-
"disabled",
|
|
1733
|
-
resolved2,
|
|
1734
|
-
configChain,
|
|
1735
|
-
ruleDecisionChain,
|
|
1736
|
-
effectiveConfigValue
|
|
1737
|
-
));
|
|
1738
|
-
}
|
|
1739
|
-
continue;
|
|
1740
|
-
}
|
|
1741
|
-
const ruleValue = rule;
|
|
1742
|
-
const unsupportedKeys = ["response", "url", "method"].filter(
|
|
1743
|
-
(key2) => key2 in ruleValue
|
|
1744
|
-
);
|
|
1745
|
-
if (unsupportedKeys.length > 0) {
|
|
1746
|
-
params.logger.warn(
|
|
1747
|
-
`Skip mock with unsupported fields (${unsupportedKeys.join(", ")}): ${fileInfo.file}`
|
|
1748
|
-
);
|
|
1749
|
-
continue;
|
|
1750
|
-
}
|
|
1751
|
-
if (typeof rule.handler === "undefined") {
|
|
1752
|
-
params.logger.warn(`Skip mock without handler: ${fileInfo.file}`);
|
|
1753
|
-
continue;
|
|
1754
|
-
}
|
|
1755
|
-
const resolved = resolveRule({
|
|
1756
|
-
rule,
|
|
1757
|
-
derivedTemplate: derived.template,
|
|
1758
|
-
derivedMethod: derived.method,
|
|
1759
|
-
prefix: params.prefix,
|
|
1760
|
-
file: fileInfo.file,
|
|
1761
|
-
logger: params.logger
|
|
1762
|
-
});
|
|
1763
|
-
if (!resolved) {
|
|
1764
|
-
continue;
|
|
1765
|
-
}
|
|
1766
|
-
resolved.ruleIndex = index;
|
|
1767
|
-
if (configChain.length > 0) {
|
|
1768
|
-
resolved.configChain = configChain;
|
|
1769
|
-
}
|
|
1770
|
-
if (config.headers) {
|
|
1771
|
-
resolved.headers = { ...config.headers, ...resolved.headers ?? {} };
|
|
1772
|
-
}
|
|
1773
|
-
if (typeof resolved.status === "undefined" && typeof config.status === "number") {
|
|
1774
|
-
resolved.status = config.status;
|
|
1775
|
-
}
|
|
1776
|
-
if (typeof resolved.delay === "undefined" && typeof config.delay === "number") {
|
|
1777
|
-
resolved.delay = config.delay;
|
|
1778
|
-
}
|
|
1779
|
-
if (config.middlewares.length > 0) {
|
|
1780
|
-
resolved.middlewares = config.middlewares;
|
|
1781
|
-
}
|
|
1782
|
-
const key = `${resolved.method} ${resolved.template}`;
|
|
1783
|
-
if (seen.has(key)) {
|
|
1784
|
-
params.logger.warn(`Duplicate mock route ${key} from ${fileInfo.file}`);
|
|
1785
|
-
}
|
|
1786
|
-
seen.add(key);
|
|
1787
|
-
routes.push(resolved);
|
|
1788
|
-
}
|
|
1789
|
-
}
|
|
1790
|
-
return sortRoutes(routes);
|
|
1791
|
-
}
|
|
1792
|
-
|
|
1793
|
-
exports.buildSwScript = buildSwScript;
|
|
1794
|
-
exports.createHonoApp = createHonoApp;
|
|
1795
|
-
exports.createMiddleware = createMiddleware;
|
|
1796
|
-
exports.createPlaygroundMiddleware = createPlaygroundMiddleware;
|
|
1797
|
-
exports.injectPlaygroundSw = injectPlaygroundSw;
|
|
1798
|
-
exports.normalizePlaygroundPath = normalizePlaygroundPath;
|
|
1799
|
-
exports.resolveDirs = resolveDirs;
|
|
1800
|
-
exports.resolvePlaygroundDist = resolvePlaygroundDist;
|
|
1801
|
-
exports.resolvePlaygroundOptions = resolvePlaygroundOptions;
|
|
1802
|
-
exports.resolvePlaygroundRequestPath = resolvePlaygroundRequestPath;
|
|
1803
|
-
exports.resolveSwConfig = resolveSwConfig;
|
|
1804
|
-
exports.resolveSwUnregisterConfig = resolveSwUnregisterConfig;
|
|
1805
|
-
exports.scanRoutes = scanRoutes;
|
|
1806
|
-
exports.sortRoutes = sortRoutes;
|
|
1807
|
-
exports.toPlaygroundConfigFile = toPlaygroundConfigFile;
|
|
1808
|
-
exports.toPlaygroundDisabledRoute = toPlaygroundDisabledRoute;
|
|
1809
|
-
exports.toPlaygroundIgnoredRoute = toPlaygroundIgnoredRoute;
|
|
1810
|
-
exports.toPlaygroundRoute = toPlaygroundRoute;
|