@marko/run 0.0.1-beta1 → 0.0.1-beta10
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.md +385 -131
- package/dist/.tsbuildinfo +1 -0
- package/dist/adapter/default-entry.mjs +14 -5
- package/dist/adapter/dev-server.d.ts +1 -1
- package/dist/adapter/index.cjs +34 -10
- package/dist/adapter/index.d.ts +1 -0
- package/dist/adapter/index.js +34 -10
- package/dist/adapter/middleware.cjs +237 -0
- package/dist/adapter/middleware.d.ts +55 -0
- package/dist/adapter/middleware.js +209 -0
- package/dist/adapter/polyfill.d.ts +6 -0
- package/dist/cli/default.config.mjs +2 -2
- package/dist/cli/index.mjs +90 -59
- package/dist/runtime/index.cjs +0 -16
- package/dist/runtime/index.d.ts +21 -2
- package/dist/runtime/index.js +0 -7
- package/dist/runtime/internal.cjs +160 -0
- package/dist/runtime/internal.d.ts +11 -0
- package/dist/runtime/internal.js +126 -0
- package/dist/runtime/router.cjs +12 -10
- package/dist/runtime/router.d.ts +3 -4
- package/dist/runtime/router.js +9 -7
- package/dist/runtime/types.d.ts +39 -16
- package/dist/vite/codegen/index.d.ts +4 -3
- package/dist/vite/codegen/writer.d.ts +1 -1
- package/dist/vite/constants.d.ts +3 -2
- package/dist/vite/index.cjs +715 -312
- package/dist/vite/index.d.ts +4 -3
- package/dist/vite/index.js +712 -312
- package/dist/vite/types.d.ts +14 -7
- package/dist/vite/utils/config.d.ts +5 -3
- package/dist/vite/utils/route.d.ts +1 -1
- package/dist/vite/utils/server.d.ts +3 -1
- package/package.json +39 -17
- package/dist/adapter/server-old.d.ts +0 -3
- package/dist/adapter/server.d.ts +0 -6
- package/dist/adapters/node/index.d.ts +0 -5
- package/dist/adapters/node/server.d.ts +0 -3
- package/dist/adapters/static/crawler.d.ts +0 -9
- package/dist/adapters/static/default-entry.mjs +0 -1
- package/dist/adapters/static/index.cjs +0 -371
- package/dist/adapters/static/index.d.ts +0 -5
- package/dist/adapters/static/index.js +0 -341
- package/dist/adapters/static/server.d.ts +0 -3
- package/dist/runtime/request.d.ts +0 -4
package/dist/vite/index.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
// src/vite/plugin.ts
|
|
2
2
|
import path2 from "path";
|
|
3
3
|
import crypto from "crypto";
|
|
4
|
+
import fs2 from "fs";
|
|
5
|
+
import glob from "glob";
|
|
4
6
|
import { mergeConfig, normalizePath } from "vite";
|
|
5
7
|
import markoVitePlugin, { FileStore } from "@marko/vite";
|
|
6
8
|
|
|
7
9
|
// src/vite/constants.ts
|
|
8
|
-
var
|
|
9
|
-
var virtualFilePrefix = "virtual:marko-
|
|
10
|
+
var markoRunFilePrefix = "__marko-run__";
|
|
11
|
+
var virtualFilePrefix = "virtual:marko-run";
|
|
10
12
|
var virtualRoutesPrefix = `${virtualFilePrefix}/routes`;
|
|
13
|
+
var virtualRuntimePrefix = `${virtualFilePrefix}/internal`;
|
|
11
14
|
var httpVerbs = ["get", "post", "put", "delete"];
|
|
12
15
|
var serverEntryQuery = "?marko-server-entry";
|
|
13
16
|
var browserEntryQuery = "?marko-browser-entry";
|
|
@@ -47,15 +50,20 @@ function isSpecialType(type) {
|
|
|
47
50
|
return type === RoutableFileTypes.NotFound || type === RoutableFileTypes.Error;
|
|
48
51
|
}
|
|
49
52
|
async function buildRoutes(walk, basePath) {
|
|
50
|
-
|
|
53
|
+
if (basePath) {
|
|
54
|
+
basePath = basePath.replace(/^\/+|\/+$/g, "");
|
|
55
|
+
}
|
|
56
|
+
const dirStack = [];
|
|
51
57
|
const pathStack = [];
|
|
52
58
|
const paramStack = [];
|
|
53
59
|
const layoutsStack = [];
|
|
54
60
|
const middlewareStack = [];
|
|
55
61
|
const routes = /* @__PURE__ */ new Map();
|
|
56
62
|
const special = {};
|
|
63
|
+
const middleware = /* @__PURE__ */ new Set();
|
|
57
64
|
let isRoot = true;
|
|
58
|
-
let
|
|
65
|
+
let nextFileId = 1;
|
|
66
|
+
let nextRouteIndex = 1;
|
|
59
67
|
let current;
|
|
60
68
|
let children = [];
|
|
61
69
|
await walk({
|
|
@@ -83,10 +91,13 @@ async function buildRoutes(walk, basePath) {
|
|
|
83
91
|
if (!entries) {
|
|
84
92
|
current.files.set(type, entries = []);
|
|
85
93
|
}
|
|
94
|
+
const relativePath = current.originalPath ? `${current.originalPath}/${entry.name}` : entry.name;
|
|
86
95
|
entries.push({
|
|
96
|
+
id: String(nextFileId++),
|
|
87
97
|
type,
|
|
88
98
|
filePath: entry.path,
|
|
89
|
-
|
|
99
|
+
relativePath,
|
|
100
|
+
importPath: `${basePath}/${relativePath}`,
|
|
90
101
|
name: entry.name,
|
|
91
102
|
verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
|
|
92
103
|
});
|
|
@@ -97,20 +108,31 @@ async function buildRoutes(walk, basePath) {
|
|
|
97
108
|
return;
|
|
98
109
|
}
|
|
99
110
|
const { path: path3, files } = current;
|
|
100
|
-
const
|
|
101
|
-
const
|
|
111
|
+
const localMiddleware = (_a = files.get(RoutableFileTypes.Middleware)) == null ? void 0 : _a[0];
|
|
112
|
+
const localLayout = (_b = files.get(RoutableFileTypes.Layout)) == null ? void 0 : _b[0];
|
|
102
113
|
const handler = (_c = files.get(RoutableFileTypes.Handler)) == null ? void 0 : _c[0];
|
|
103
114
|
const page = (_d = files.get(RoutableFileTypes.Page)) == null ? void 0 : _d[0];
|
|
104
115
|
const middlewareStackLength = middlewareStack.length;
|
|
105
116
|
const layoutsStackLength = layoutsStack.length;
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
if (localMiddleware) {
|
|
118
|
+
middlewareStack.push(localMiddleware);
|
|
119
|
+
}
|
|
120
|
+
if (localLayout) {
|
|
121
|
+
layoutsStack.push(localLayout);
|
|
122
|
+
}
|
|
108
123
|
if (handler || page) {
|
|
109
124
|
const key = path3.replace(/(\$\$?)[^\/]*/g, "$1").replace(/^\/+/, "").replace(/[^a-z0-9_$\/]+/gi, "").replace(/\//g, "__") || "index";
|
|
110
125
|
if (routes.has(key)) {
|
|
111
|
-
|
|
126
|
+
const existing = routes.get(key);
|
|
127
|
+
const existingFiles = [existing.handler, existing.page].filter(Boolean).map((f) => f.filePath);
|
|
128
|
+
const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
|
|
129
|
+
throw new Error(`Duplicate routes for path ${path3} were defined. A route established by:
|
|
130
|
+
${existingFiles}
|
|
131
|
+
collides with
|
|
132
|
+
${currentFiles.join(" and ")}
|
|
133
|
+
`);
|
|
112
134
|
} else {
|
|
113
|
-
const index =
|
|
135
|
+
const index = nextRouteIndex++;
|
|
114
136
|
routes.set(key, {
|
|
115
137
|
index,
|
|
116
138
|
key,
|
|
@@ -123,6 +145,9 @@ async function buildRoutes(walk, basePath) {
|
|
|
123
145
|
handler,
|
|
124
146
|
score: scorePath(path3, index)
|
|
125
147
|
});
|
|
148
|
+
for (const mw of middlewareStack) {
|
|
149
|
+
middleware.add(mw);
|
|
150
|
+
}
|
|
126
151
|
}
|
|
127
152
|
}
|
|
128
153
|
if (isRoot) {
|
|
@@ -153,14 +178,16 @@ async function buildRoutes(walk, basePath) {
|
|
|
153
178
|
const prevChildren = children;
|
|
154
179
|
const prevCurrent = current;
|
|
155
180
|
const prevIsRoot = isRoot;
|
|
156
|
-
if (name.charCodeAt(0) === 95
|
|
181
|
+
if (name.charCodeAt(0) === 95) {
|
|
157
182
|
} else {
|
|
158
183
|
if (name.charCodeAt(0) === 36) {
|
|
159
184
|
if (name.charCodeAt(1) === 36) {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
185
|
+
if (name.length > 2) {
|
|
186
|
+
paramStack.push({
|
|
187
|
+
name: name.slice(2),
|
|
188
|
+
index: -1
|
|
189
|
+
});
|
|
190
|
+
}
|
|
164
191
|
} else if (name.length > 1) {
|
|
165
192
|
paramStack.push({
|
|
166
193
|
name: name.slice(1),
|
|
@@ -188,7 +215,8 @@ async function buildRoutes(walk, basePath) {
|
|
|
188
215
|
});
|
|
189
216
|
return {
|
|
190
217
|
list: [...routes.values()],
|
|
191
|
-
special
|
|
218
|
+
special,
|
|
219
|
+
middleware: [...middleware]
|
|
192
220
|
};
|
|
193
221
|
}
|
|
194
222
|
|
|
@@ -238,6 +266,17 @@ function createWriter(sink, options) {
|
|
|
238
266
|
let firstOpenIndex = 0;
|
|
239
267
|
const branches = [];
|
|
240
268
|
const openWriters = /* @__PURE__ */ new Map();
|
|
269
|
+
function write(data) {
|
|
270
|
+
if (!writer.__isActive) {
|
|
271
|
+
throw new Error("Cannot write to branch that has been joined");
|
|
272
|
+
}
|
|
273
|
+
if (openWriters.size) {
|
|
274
|
+
buffer += data;
|
|
275
|
+
} else {
|
|
276
|
+
sink(data);
|
|
277
|
+
}
|
|
278
|
+
return writer;
|
|
279
|
+
}
|
|
241
280
|
const writer = {
|
|
242
281
|
__isActive: true,
|
|
243
282
|
get indent() {
|
|
@@ -254,24 +293,16 @@ function createWriter(sink, options) {
|
|
|
254
293
|
}
|
|
255
294
|
}
|
|
256
295
|
},
|
|
257
|
-
write(data) {
|
|
258
|
-
if (
|
|
259
|
-
|
|
296
|
+
write(data, indent = false) {
|
|
297
|
+
if (indent && indentString) {
|
|
298
|
+
write(indentString);
|
|
260
299
|
}
|
|
261
|
-
|
|
262
|
-
buffer += data;
|
|
263
|
-
} else {
|
|
264
|
-
sink(data);
|
|
265
|
-
}
|
|
266
|
-
return writer;
|
|
300
|
+
return write(data);
|
|
267
301
|
},
|
|
268
302
|
writeLines(...lines) {
|
|
269
303
|
for (const line of lines) {
|
|
270
304
|
if (line) {
|
|
271
|
-
|
|
272
|
-
writer.write(indentString);
|
|
273
|
-
}
|
|
274
|
-
writer.write(line);
|
|
305
|
+
writer.write(line, true);
|
|
275
306
|
}
|
|
276
307
|
writer.write("\n");
|
|
277
308
|
}
|
|
@@ -418,16 +449,13 @@ function hasVerb(route, verb) {
|
|
|
418
449
|
}
|
|
419
450
|
|
|
420
451
|
// src/vite/codegen/index.ts
|
|
421
|
-
var DefaultCodegenOptions = {
|
|
422
|
-
trailingSlashes: "RedirectWithout"
|
|
423
|
-
};
|
|
424
452
|
function renderRouteTemplate(route) {
|
|
425
453
|
if (!route.page) {
|
|
426
454
|
throw new Error(`Route ${route.key} has no page to render`);
|
|
427
455
|
}
|
|
428
456
|
const writer = createStringWriter();
|
|
429
457
|
writer.writeLines(
|
|
430
|
-
`// ${virtualFilePrefix}/${
|
|
458
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.marko`
|
|
431
459
|
);
|
|
432
460
|
writer.branch("imports");
|
|
433
461
|
writer.writeLines("");
|
|
@@ -459,47 +487,76 @@ function renderRouteEntry(route) {
|
|
|
459
487
|
}
|
|
460
488
|
const writer = createStringWriter();
|
|
461
489
|
writer.writeLines(
|
|
462
|
-
`// ${virtualFilePrefix}/${
|
|
490
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.js`
|
|
463
491
|
);
|
|
464
492
|
const imports = writer.branch("imports");
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
i++;
|
|
493
|
+
const runtimeImports = [];
|
|
494
|
+
if (handler) {
|
|
495
|
+
runtimeImports.push("normalize");
|
|
469
496
|
}
|
|
470
|
-
if (
|
|
471
|
-
|
|
472
|
-
|
|
497
|
+
if (handler || middleware.length) {
|
|
498
|
+
runtimeImports.push("call");
|
|
499
|
+
}
|
|
500
|
+
if (!page || verbs.length > 1) {
|
|
501
|
+
runtimeImports.push("noContent");
|
|
502
|
+
}
|
|
503
|
+
if (page) {
|
|
504
|
+
runtimeImports.push("pageResponse");
|
|
505
|
+
}
|
|
506
|
+
if (runtimeImports.length) {
|
|
507
|
+
imports.writeLines(
|
|
508
|
+
`import { ${runtimeImports.join(", ")} } from '${virtualRuntimePrefix}';`
|
|
473
509
|
);
|
|
510
|
+
}
|
|
511
|
+
if (middleware.length) {
|
|
512
|
+
const names = middleware.map((m) => `mware${m.id}`);
|
|
513
|
+
imports.writeLines(
|
|
514
|
+
`import { ${names.join(
|
|
515
|
+
", "
|
|
516
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}middleware.js';`
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.length) {
|
|
520
|
+
writer.writeLines("");
|
|
521
|
+
const names = [];
|
|
522
|
+
for (const verb of handler.verbs) {
|
|
523
|
+
const importName = verb.toUpperCase();
|
|
524
|
+
names.push(importName);
|
|
525
|
+
writer.writeLines(`const ${verb}Handler = normalize(${importName});`);
|
|
526
|
+
}
|
|
474
527
|
imports.writeLines(
|
|
475
528
|
`import { ${names.join(", ")} } from './${handler.importPath}';`
|
|
476
529
|
);
|
|
477
530
|
}
|
|
478
531
|
if (page) {
|
|
479
532
|
imports.writeLines(
|
|
480
|
-
`import page from '${virtualFilePrefix}/${
|
|
533
|
+
`import page from '${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.marko${serverEntryQuery}';`
|
|
481
534
|
);
|
|
482
535
|
}
|
|
483
536
|
if (meta) {
|
|
484
537
|
imports.writeLines(
|
|
485
|
-
`export { default as meta
|
|
538
|
+
`export { default as meta${index} } from './${meta.importPath}';`
|
|
486
539
|
);
|
|
487
540
|
}
|
|
488
|
-
if (!page || verbs.length > 1) {
|
|
489
|
-
writer.writeLines("").writeBlockStart(`function create204Response() {`).writeBlockStart(`return new Response(null, {`).writeLines(`status: 204`).writeBlockEnd(`})`).writeBlockEnd(`}`);
|
|
490
|
-
}
|
|
491
541
|
for (const verb of verbs) {
|
|
492
542
|
writeRouteEntryHandler(writer, route, verb);
|
|
493
543
|
}
|
|
494
544
|
return writer.end();
|
|
495
545
|
}
|
|
496
|
-
function
|
|
497
|
-
writer.
|
|
498
|
-
`
|
|
499
|
-
["status: 200,", 'headers: { "content-type": "text/html;charset=UTF-8" }'],
|
|
500
|
-
"});"
|
|
546
|
+
function writePageResponse(writer, wrapFn) {
|
|
547
|
+
writer.writeLines(
|
|
548
|
+
`${wrapFn ? `const ${wrapFn} = () =>` : `return`} pageResponse(page, buildInput());`
|
|
501
549
|
);
|
|
502
550
|
}
|
|
551
|
+
function writeMiddleware(writer, middleware, next, wrapFn) {
|
|
552
|
+
if (wrapFn) {
|
|
553
|
+
writer.writeLines(
|
|
554
|
+
`const ${wrapFn} = () => call(${middleware}, ${next}, context);`
|
|
555
|
+
);
|
|
556
|
+
} else {
|
|
557
|
+
writer.writeLines(`return call(${middleware}, ${next}, context);`);
|
|
558
|
+
}
|
|
559
|
+
}
|
|
503
560
|
function writeRouteEntryHandler(writer, route, verb) {
|
|
504
561
|
var _a;
|
|
505
562
|
const { key, index, page, handler, middleware } = route;
|
|
@@ -507,47 +564,43 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
507
564
|
let nextName;
|
|
508
565
|
let currentName;
|
|
509
566
|
let hasBody = false;
|
|
510
|
-
writer.writeLines("")
|
|
567
|
+
writer.writeLines("");
|
|
568
|
+
if (page) {
|
|
569
|
+
writer.writeBlockStart(
|
|
570
|
+
`export async function ${verb}${index}(context, buildInput) {`
|
|
571
|
+
);
|
|
572
|
+
} else {
|
|
573
|
+
writer.writeBlockStart(`export async function ${verb}${index}(context) {`);
|
|
574
|
+
}
|
|
511
575
|
const continuations = writer.branch("cont");
|
|
512
576
|
if (page && verb === "get") {
|
|
513
|
-
currentName = "
|
|
577
|
+
currentName = "__page";
|
|
514
578
|
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
continuations.writeBlockEnd("}");
|
|
579
|
+
const name = `${verb}Handler`;
|
|
580
|
+
writePageResponse(continuations, currentName);
|
|
518
581
|
if (len) {
|
|
519
582
|
nextName = currentName;
|
|
520
|
-
currentName = `
|
|
521
|
-
continuations
|
|
522
|
-
`async function ${currentName}() {`,
|
|
523
|
-
[`return await handler$${verb}(ctx, ${nextName});`],
|
|
524
|
-
"}"
|
|
525
|
-
);
|
|
583
|
+
currentName = `__${name}`;
|
|
584
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
526
585
|
} else {
|
|
527
|
-
writer
|
|
586
|
+
writeMiddleware(writer, name, currentName);
|
|
528
587
|
hasBody = true;
|
|
529
588
|
}
|
|
530
589
|
} else if (len) {
|
|
531
|
-
continuations
|
|
532
|
-
writePageResponseContinuation(continuations);
|
|
533
|
-
continuations.writeBlockEnd("}");
|
|
590
|
+
writePageResponse(continuations, currentName);
|
|
534
591
|
nextName = currentName;
|
|
535
592
|
} else {
|
|
536
|
-
|
|
593
|
+
writePageResponse(continuations);
|
|
537
594
|
hasBody = true;
|
|
538
595
|
}
|
|
539
596
|
} else if (handler) {
|
|
540
|
-
|
|
597
|
+
const name = `${verb}Handler`;
|
|
598
|
+
currentName = `__${name}`;
|
|
599
|
+
nextName = "noContent";
|
|
541
600
|
if (len) {
|
|
542
|
-
continuations
|
|
543
|
-
`async function ${currentName}() {`,
|
|
544
|
-
[`return await handler$${verb}(ctx, create204Response);`],
|
|
545
|
-
"}"
|
|
546
|
-
);
|
|
601
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
547
602
|
} else {
|
|
548
|
-
writer
|
|
549
|
-
`return await handler$${verb}(ctx, create204Response);`
|
|
550
|
-
);
|
|
603
|
+
writeMiddleware(writer, name, nextName);
|
|
551
604
|
hasBody = true;
|
|
552
605
|
}
|
|
553
606
|
} else {
|
|
@@ -555,40 +608,48 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
555
608
|
}
|
|
556
609
|
if (!hasBody) {
|
|
557
610
|
let i = len;
|
|
558
|
-
while (--
|
|
611
|
+
while (i--) {
|
|
612
|
+
const { id } = middleware[i];
|
|
613
|
+
const name = `mware${id}`;
|
|
559
614
|
nextName = currentName;
|
|
560
|
-
currentName = `
|
|
561
|
-
continuations
|
|
562
|
-
`async function ${currentName}() {`,
|
|
563
|
-
[`return await middleware$${i + 1}(ctx, ${nextName});`],
|
|
564
|
-
"}"
|
|
565
|
-
);
|
|
615
|
+
currentName = i ? `__${name}` : "";
|
|
616
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
566
617
|
}
|
|
567
|
-
writer.writeLines(`return await middleware$1(ctx, ${currentName});`);
|
|
568
618
|
}
|
|
569
619
|
continuations.join();
|
|
570
620
|
writer.writeBlockEnd("}");
|
|
571
621
|
}
|
|
572
|
-
function renderRouter(routes, options =
|
|
622
|
+
function renderRouter(routes, options = {
|
|
623
|
+
trailingSlashes: "RedirectWithout"
|
|
624
|
+
}) {
|
|
573
625
|
const writer = createStringWriter();
|
|
574
626
|
writer.writeLines(`// @marko/run/router`);
|
|
575
627
|
const imports = writer.branch("imports");
|
|
628
|
+
imports.writeLines(
|
|
629
|
+
`import { NotHandled, NotMatched, createInput } from 'virtual:marko-run/internal';`
|
|
630
|
+
);
|
|
576
631
|
for (const route of routes.list) {
|
|
577
632
|
const verbs = getVerbs(route);
|
|
578
|
-
const names = verbs.map((verb) => `${verb}
|
|
579
|
-
route.meta && names.push(`meta
|
|
633
|
+
const names = verbs.map((verb) => `${verb}${route.index}`);
|
|
634
|
+
route.meta && names.push(`meta${route.index}`);
|
|
580
635
|
imports.writeLines(
|
|
581
636
|
`import { ${names.join(
|
|
582
637
|
", "
|
|
583
|
-
)} } from '${virtualFilePrefix}/${
|
|
638
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.js';`
|
|
584
639
|
);
|
|
585
640
|
}
|
|
586
641
|
for (const { key } of Object.values(routes.special)) {
|
|
587
642
|
imports.writeLines(
|
|
588
|
-
`import page
|
|
643
|
+
`import page${key} from '${virtualFilePrefix}/${markoRunFilePrefix}special__${key}.marko${serverEntryQuery}';`
|
|
589
644
|
);
|
|
590
645
|
}
|
|
591
|
-
writer.writeLines(
|
|
646
|
+
writer.writeLines(``).writeBlockStart(`export function match(method, pathname) {`).writeLines(
|
|
647
|
+
`if (!pathname) {
|
|
648
|
+
pathname = '/';
|
|
649
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
650
|
+
pathname = '/' + pathname;
|
|
651
|
+
}`
|
|
652
|
+
).writeBlockStart(`switch (method.toLowerCase()) {`);
|
|
592
653
|
for (const verb of httpVerbs) {
|
|
593
654
|
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
594
655
|
if (filteredRoutes.length) {
|
|
@@ -598,235 +659,477 @@ function renderRouter(routes, options = DefaultCodegenOptions) {
|
|
|
598
659
|
writer.writeBlockEnd("}");
|
|
599
660
|
}
|
|
600
661
|
}
|
|
601
|
-
writer.writeBlockEnd("}").writeBlockEnd("}");
|
|
602
|
-
writer.
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
662
|
+
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
663
|
+
writer.write(`
|
|
664
|
+
export async function invoke(route, request, platform, url = new URL(request.url)) {
|
|
665
|
+
const context = {
|
|
666
|
+
url,
|
|
667
|
+
request,
|
|
668
|
+
platform
|
|
669
|
+
};
|
|
670
|
+
const buildInput = createInput(context);
|
|
671
|
+
try {
|
|
672
|
+
if (route) {
|
|
673
|
+
context.params = route.params;
|
|
674
|
+
context.meta = route.meta;
|
|
675
|
+
try {
|
|
676
|
+
const response = await route.handler(context, buildInput);
|
|
677
|
+
if (response) return response;
|
|
678
|
+
} catch (error) {
|
|
679
|
+
if (error === NotHandled) {
|
|
680
|
+
return;
|
|
681
|
+
} else if (error !== NotMatched) {
|
|
682
|
+
throw error;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
`).indent = 2;
|
|
686
|
+
if (routes.special[RoutableFileTypes.NotFound]) {
|
|
687
|
+
writer.write(
|
|
688
|
+
` } else {
|
|
689
|
+
context.params = {};
|
|
690
|
+
context.meta = {};
|
|
691
|
+
}
|
|
692
|
+
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
693
|
+
return new Response(page404.stream(buildInput()), {
|
|
694
|
+
status: 404,
|
|
695
|
+
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
`
|
|
699
|
+
);
|
|
700
|
+
} else {
|
|
701
|
+
writer.writeBlockEnd("}");
|
|
628
702
|
}
|
|
629
|
-
writer.
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
writer.writeBlockStart(
|
|
633
|
-
`if (request.headers.get('Accept')?.includes('text/html')) {`
|
|
703
|
+
writer.indent--;
|
|
704
|
+
writer.writeBlockStart(`} catch (error) {`);
|
|
705
|
+
if (routes.special[RoutableFileTypes.Error]) {
|
|
706
|
+
writer.writeBlockStart(
|
|
707
|
+
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
634
708
|
).writeBlock(
|
|
635
|
-
`return new Response(
|
|
709
|
+
`return new Response(page500.stream(buildInput({ error })), {`,
|
|
636
710
|
[
|
|
637
711
|
`status: 500,`,
|
|
638
712
|
`headers: { "content-type": "text/html;charset=UTF-8" },`
|
|
639
713
|
],
|
|
640
714
|
`});`
|
|
641
|
-
).writeBlockEnd("}")
|
|
642
|
-
}
|
|
643
|
-
writer.writeBlockEnd("}");
|
|
644
|
-
writer.write(`
|
|
645
|
-
export function getMatchedRoute(method, url) {
|
|
646
|
-
const route = matchRoute(method, url.pathname);
|
|
647
|
-
if (route) {
|
|
648
|
-
const [handler, params = {}, meta] = route;
|
|
649
|
-
return {
|
|
650
|
-
handler,
|
|
651
|
-
params,
|
|
652
|
-
meta,
|
|
653
|
-
async invoke(request) {
|
|
654
|
-
return await invokeRoute(route, url, request);
|
|
655
|
-
}
|
|
656
|
-
}
|
|
715
|
+
).writeBlockEnd("}");
|
|
657
716
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
export async function handler(context) {
|
|
662
|
-
const response = await router(context.request);
|
|
663
|
-
//if (response.body) {
|
|
664
|
-
// context.waitUntil?.(once(Readable.from(response.body), "end"));
|
|
665
|
-
//}
|
|
666
|
-
return response;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
export async function router(request) {
|
|
717
|
+
writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
|
|
718
|
+
export async function fetch(request, platform) {
|
|
670
719
|
try {
|
|
671
720
|
const url = new URL(request.url);
|
|
672
|
-
let { pathname } = url;
|
|
673
|
-
|
|
674
|
-
if (pathname !== '/') {
|
|
675
|
-
if (pathname.endsWith('/')) {
|
|
676
|
-
pathname = pathname.replace(/\\/+$/, '');
|
|
677
|
-
`);
|
|
721
|
+
let { pathname } = url;`);
|
|
678
722
|
switch (options.trailingSlashes) {
|
|
679
723
|
case "RedirectWithout":
|
|
680
724
|
writer.write(`
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
725
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
726
|
+
url.pathname = pathname.slice(0, -1);
|
|
727
|
+
return Response.redirect(url);
|
|
728
|
+
}`);
|
|
684
729
|
break;
|
|
685
730
|
case "RedirectWith":
|
|
686
731
|
writer.write(`
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
`);
|
|
732
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
733
|
+
url.pathname = pathname + '/';
|
|
734
|
+
return Response.redirect(url);
|
|
735
|
+
}`);
|
|
691
736
|
break;
|
|
692
737
|
case "RewriteWithout":
|
|
693
738
|
writer.write(`
|
|
694
|
-
|
|
695
|
-
|
|
739
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
740
|
+
url.pathname = pathname = pathname.slice(0, -1);
|
|
741
|
+
}`);
|
|
696
742
|
break;
|
|
697
743
|
case "RewriteWith":
|
|
698
744
|
writer.write(`
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
`);
|
|
745
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
746
|
+
url.pathname = pathname = pathname + '/';
|
|
747
|
+
}`);
|
|
702
748
|
break;
|
|
703
749
|
}
|
|
704
|
-
writer.write(`
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
const route = matchRoute(request.method, pathname);
|
|
708
|
-
return await invokeRoute(route, url, request) || new Response(null, {
|
|
709
|
-
statusText: \`Not Found (No route matched \${pathname})\`,
|
|
710
|
-
status: 404
|
|
711
|
-
});
|
|
712
|
-
} catch (err) {
|
|
713
|
-
const message = import.meta.env.DEV
|
|
714
|
-
? \`Internal Server Error (\${err.message})\`
|
|
715
|
-
: "Internal Server Error";
|
|
750
|
+
writer.write(`
|
|
716
751
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
{
|
|
727
|
-
statusText: message,
|
|
728
|
-
status: 500,
|
|
729
|
-
}
|
|
730
|
-
);
|
|
752
|
+
const route = match(request.method, pathname);
|
|
753
|
+
return await invoke(route, request, platform, url);
|
|
754
|
+
} catch (error) {
|
|
755
|
+
const body = import.meta.env.DEV
|
|
756
|
+
? error.stack || error.message || "Internal Server Error"
|
|
757
|
+
: null;
|
|
758
|
+
return new Response(body, {
|
|
759
|
+
status: 500
|
|
760
|
+
});
|
|
731
761
|
}
|
|
732
762
|
}`);
|
|
733
763
|
return writer.end();
|
|
734
764
|
}
|
|
735
|
-
function writeRouterVerb(writer, trie, verb, level = 0,
|
|
736
|
-
const {
|
|
737
|
-
|
|
738
|
-
if (level
|
|
739
|
-
|
|
740
|
-
if (
|
|
765
|
+
function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
|
|
766
|
+
const { route, dynamic, catchAll } = trie;
|
|
767
|
+
let closeCount = 0;
|
|
768
|
+
if (level === 0) {
|
|
769
|
+
writer.writeLines(`const len = pathname.length;`);
|
|
770
|
+
if (route) {
|
|
741
771
|
writer.writeLines(
|
|
742
|
-
`if (
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
if (children || dynamic) {
|
|
746
|
-
writer.writeLines(
|
|
747
|
-
`const segments = pathname.split('/');`,
|
|
748
|
-
`const len = segments.length;`
|
|
749
|
-
);
|
|
750
|
-
}
|
|
751
|
-
} else {
|
|
752
|
-
if (!key) {
|
|
753
|
-
writer.writeBlockStart(`if (segments[${level}]) {`);
|
|
754
|
-
} else if (useSwitch) {
|
|
755
|
-
writer.writeBlockStart(`case '${key}':`);
|
|
756
|
-
} else {
|
|
757
|
-
writer.writeBlockStart(
|
|
758
|
-
`if (segments[${level}]?.toLowerCase() === '${key}') {`
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
if (value) {
|
|
762
|
-
writer.writeLines(
|
|
763
|
-
`if (len === ${level + 1}) return ${renderMatch(verb, value)}; // ${value.path}`
|
|
772
|
+
`if (len === 1) return ${renderMatch(verb, route)}; // ${route.path}`
|
|
764
773
|
);
|
|
774
|
+
} else if (trie.static || dynamic) {
|
|
775
|
+
writer.writeBlockStart(`if (len > 1) {`);
|
|
776
|
+
closeCount++;
|
|
765
777
|
}
|
|
766
778
|
}
|
|
767
|
-
if (
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
779
|
+
if (trie.static || dynamic) {
|
|
780
|
+
const next = level + 1;
|
|
781
|
+
const index = `i${next}`;
|
|
782
|
+
let terminal;
|
|
783
|
+
let children;
|
|
784
|
+
writer.writeLines(`const ${index} = pathname.indexOf('/', ${offset}) + 1;`);
|
|
785
|
+
if (trie.static) {
|
|
786
|
+
for (const child of trie.static.values()) {
|
|
787
|
+
if (child.route) {
|
|
788
|
+
(terminal ?? (terminal = [])).push(child);
|
|
775
789
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
for (const child of children.values()) {
|
|
779
|
-
writeRouterVerb(writer, child, verb, level + 1, pathIndex);
|
|
790
|
+
if (child.static || child.dynamic || child.catchAll) {
|
|
791
|
+
(children ?? (children = [])).push(child);
|
|
780
792
|
}
|
|
781
793
|
}
|
|
782
794
|
}
|
|
783
|
-
if (dynamic) {
|
|
784
|
-
|
|
795
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
796
|
+
closeCount++;
|
|
797
|
+
writer.writeBlockStart(`if (!${index} || ${index} === len) {`);
|
|
798
|
+
let value = `pathname.slice(${offset}, ${index} ? -1 : len)`;
|
|
799
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
800
|
+
const segment = `s${next}`;
|
|
801
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
802
|
+
value = segment;
|
|
803
|
+
}
|
|
804
|
+
if (terminal) {
|
|
805
|
+
const useSwitch = terminal.length > 1;
|
|
806
|
+
if (useSwitch) {
|
|
807
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
808
|
+
}
|
|
809
|
+
for (const { key, route: route2 } of terminal) {
|
|
810
|
+
if (useSwitch) {
|
|
811
|
+
writer.write(`case '${key}': `, true);
|
|
812
|
+
} else {
|
|
813
|
+
writer.write(`if (${value}.toLowerCase() === '${key}') `, true);
|
|
814
|
+
}
|
|
815
|
+
writer.write(
|
|
816
|
+
`return ${renderMatch(verb, route2)}; // ${route2.path}
|
|
817
|
+
`
|
|
818
|
+
);
|
|
819
|
+
}
|
|
820
|
+
if (useSwitch) {
|
|
821
|
+
writer.writeBlockEnd("}");
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
825
|
+
writer.writeLines(
|
|
826
|
+
`if (${value}) return ${renderMatch(verb, dynamic.route)}; // ${dynamic.route.path}`
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
if (children || (dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
831
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
832
|
+
writer.writeBlockEnd("} else {").indent++;
|
|
833
|
+
} else {
|
|
834
|
+
writer.writeBlockStart(`if (${index} && ${index} !== len) {`);
|
|
835
|
+
closeCount++;
|
|
836
|
+
}
|
|
837
|
+
let value = `pathname.slice(${offset}, ${index} - 1)`;
|
|
838
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic)) {
|
|
839
|
+
const segment = `s${next}`;
|
|
840
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
841
|
+
value = segment;
|
|
842
|
+
}
|
|
843
|
+
if (children) {
|
|
844
|
+
const useSwitch = children.length > 1;
|
|
845
|
+
if (useSwitch) {
|
|
846
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
847
|
+
}
|
|
848
|
+
for (const child of children) {
|
|
849
|
+
if (useSwitch) {
|
|
850
|
+
writer.writeBlockStart(`case '${child.key}': {`);
|
|
851
|
+
} else {
|
|
852
|
+
writer.writeBlockStart(
|
|
853
|
+
`if (${value}.toLowerCase() === '${child.key}') {`
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
const nextOffset = typeof offset === "string" ? index : offset + child.key.length + 1;
|
|
857
|
+
writeRouterVerb(writer, child, verb, next, nextOffset);
|
|
858
|
+
writer.writeBlockEnd("}");
|
|
859
|
+
}
|
|
860
|
+
if (useSwitch) {
|
|
861
|
+
writer.writeBlockEnd("}");
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
865
|
+
writer.writeBlockStart(`if (${value}) {`);
|
|
866
|
+
writeRouterVerb(writer, dynamic, verb, next, index);
|
|
867
|
+
writer.writeBlockEnd(`}`);
|
|
868
|
+
}
|
|
785
869
|
}
|
|
786
870
|
}
|
|
871
|
+
while (closeCount--) {
|
|
872
|
+
writer.writeBlockEnd("}");
|
|
873
|
+
}
|
|
787
874
|
if (catchAll) {
|
|
788
875
|
writer.writeLines(
|
|
789
|
-
`return ${renderMatch(verb, catchAll,
|
|
876
|
+
`return ${renderMatch(verb, catchAll, String(offset))}; // ${catchAll.path}`
|
|
790
877
|
);
|
|
791
|
-
if (level > 0) {
|
|
792
|
-
writer.indent--;
|
|
793
|
-
}
|
|
794
878
|
} else if (level === 0) {
|
|
795
|
-
writer.writeLines("return;");
|
|
796
|
-
} else if (useSwitch) {
|
|
797
|
-
writer.writeLines("break;").indent--;
|
|
798
|
-
} else {
|
|
799
|
-
writer.writeBlockEnd("}");
|
|
879
|
+
writer.writeLines("return null;");
|
|
800
880
|
}
|
|
801
881
|
}
|
|
882
|
+
function wrapPropertyName(name) {
|
|
883
|
+
return /^[^A-Za-z_$]|[^A-Za-z0-9$_]/.test(name) ? `'${name}'` : name;
|
|
884
|
+
}
|
|
802
885
|
function renderParamsInfo(params, pathIndex) {
|
|
886
|
+
if (!params.length) {
|
|
887
|
+
return "{}";
|
|
888
|
+
}
|
|
803
889
|
let result = "";
|
|
804
890
|
let catchAll = "";
|
|
805
|
-
let
|
|
891
|
+
let sep = "{";
|
|
806
892
|
for (const { name, index } of params) {
|
|
807
893
|
if (index >= 0) {
|
|
808
|
-
result +=
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
} else if (pathIndex && pathIndex >= 0) {
|
|
894
|
+
result += `${sep} ${wrapPropertyName(name)}: s${index + 1}`;
|
|
895
|
+
sep || (sep = ",");
|
|
896
|
+
} else if (pathIndex) {
|
|
812
897
|
catchAll = name;
|
|
813
898
|
}
|
|
814
899
|
}
|
|
815
900
|
if (catchAll) {
|
|
816
|
-
result +=
|
|
817
|
-
|
|
901
|
+
result += `${sep} ${wrapPropertyName(
|
|
902
|
+
catchAll
|
|
903
|
+
)}: pathname.slice(${pathIndex})`;
|
|
818
904
|
}
|
|
819
905
|
return result ? result + " }" : "{}";
|
|
820
906
|
}
|
|
821
|
-
function
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
tuple[1] = renderParamsInfo(params, pathIndex);
|
|
907
|
+
function renderParamsInfoType(params) {
|
|
908
|
+
if (!params.length) {
|
|
909
|
+
return "{}";
|
|
825
910
|
}
|
|
826
|
-
|
|
827
|
-
|
|
911
|
+
let result = "{";
|
|
912
|
+
for (const { name } of params) {
|
|
913
|
+
result += ` ${wrapPropertyName(name)}: string;`;
|
|
828
914
|
}
|
|
829
|
-
return
|
|
915
|
+
return result + " }";
|
|
916
|
+
}
|
|
917
|
+
function renderMatch(verb, route, pathIndex) {
|
|
918
|
+
var _a;
|
|
919
|
+
const handler = `${verb}${route.index}`;
|
|
920
|
+
const params = ((_a = route.params) == null ? void 0 : _a.length) ? renderParamsInfo(route.params, pathIndex) : "{}";
|
|
921
|
+
const meta = route.meta ? `meta${route.index}` : "{}";
|
|
922
|
+
return `{ handler: ${handler}, params: ${params}, meta: ${meta} }`;
|
|
923
|
+
}
|
|
924
|
+
function renderMiddleware(middleware) {
|
|
925
|
+
const writer = createStringWriter();
|
|
926
|
+
writer.writeLines(
|
|
927
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}middleware.js`
|
|
928
|
+
);
|
|
929
|
+
const imports = writer.branch("imports");
|
|
930
|
+
imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
|
|
931
|
+
writer.writeLines("");
|
|
932
|
+
for (const { id, importPath } of middleware) {
|
|
933
|
+
const importName = `middleware${id}`;
|
|
934
|
+
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
935
|
+
writer.writeLines(`export const mware${id} = normalize(${importName});`);
|
|
936
|
+
}
|
|
937
|
+
imports.join();
|
|
938
|
+
return writer.end();
|
|
939
|
+
}
|
|
940
|
+
function stripTsExtension(path3) {
|
|
941
|
+
const index = path3.lastIndexOf(".");
|
|
942
|
+
if (index !== -1) {
|
|
943
|
+
const ext = path3.slice(index + 1);
|
|
944
|
+
if (ext.toLowerCase() === "ts") {
|
|
945
|
+
return path3.slice(0, index);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
return path3;
|
|
949
|
+
}
|
|
950
|
+
function renderRouteTypeInfo(routes, pathPrefix = ".", adapterTypes = "") {
|
|
951
|
+
var _a, _b;
|
|
952
|
+
const writer = createStringWriter();
|
|
953
|
+
writer.writeLines(
|
|
954
|
+
`/*
|
|
955
|
+
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
956
|
+
Do NOT manually edit this file or your changes will be lost.
|
|
957
|
+
*/
|
|
958
|
+
`,
|
|
959
|
+
`import type { HandlerLike, Route as AnyRoute, Context as AnyContext, ValidatePath, ValidateHref } from "@marko/run";`,
|
|
960
|
+
adapterTypes,
|
|
961
|
+
`
|
|
962
|
+
|
|
963
|
+
declare global {
|
|
964
|
+
namespace MarkoRun {`
|
|
965
|
+
);
|
|
966
|
+
const pathsWriter = writer.branch("paths");
|
|
967
|
+
writer.write(`
|
|
968
|
+
type GetablePath<T extends string> = ValidatePath<GetPaths, T>;
|
|
969
|
+
type GetableHref<T extends string> = ValidateHref<GetPaths, T>;
|
|
970
|
+
type PostablePath<T extends string> = ValidatePath<PostPaths, T>;
|
|
971
|
+
type PostableHref<T extends string> = ValidateHref<PostPaths, T>;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
`);
|
|
975
|
+
const routesWriter = writer.branch("types");
|
|
976
|
+
const serverWriter = writer.branch("server");
|
|
977
|
+
const middlewareRouteTypes = /* @__PURE__ */ new Map();
|
|
978
|
+
const layoutRouteTypes = /* @__PURE__ */ new Map();
|
|
979
|
+
const getPaths = /* @__PURE__ */ new Set();
|
|
980
|
+
const postPaths = /* @__PURE__ */ new Set();
|
|
981
|
+
for (const route of routes.list) {
|
|
982
|
+
const { meta, handler, params, middleware, page, layouts } = route;
|
|
983
|
+
const routeType = `Route${route.index}`;
|
|
984
|
+
const pathType = `\`${route.path.replace(
|
|
985
|
+
/\/\$(\$?)([^\/]*)/,
|
|
986
|
+
(_, catchAll, name) => catchAll ? `/:${name || "rest"}*` : `/:${name}`
|
|
987
|
+
)}\``;
|
|
988
|
+
const paramsType = params ? renderParamsInfoType(params) : "{}";
|
|
989
|
+
let metaType = "undefined";
|
|
990
|
+
if (page || handler) {
|
|
991
|
+
const isGet = page || ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes("get"));
|
|
992
|
+
const isPost = (_b = handler == null ? void 0 : handler.verbs) == null ? void 0 : _b.includes("post");
|
|
993
|
+
if (isGet || isPost) {
|
|
994
|
+
const path3 = route.path.replace(
|
|
995
|
+
/\$(\$?)([^/]+)/g,
|
|
996
|
+
(_, s, name) => s ? `\${...${name}}` : `\${${name}}`
|
|
997
|
+
);
|
|
998
|
+
const splatIndex = path3.indexOf("/${...");
|
|
999
|
+
if (splatIndex >= 0) {
|
|
1000
|
+
const path22 = path3.slice(0, splatIndex) || "/";
|
|
1001
|
+
isGet && getPaths.add(path22);
|
|
1002
|
+
isPost && postPaths.add(path22);
|
|
1003
|
+
}
|
|
1004
|
+
isGet && getPaths.add(path3);
|
|
1005
|
+
isPost && postPaths.add(path3);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
if (meta) {
|
|
1009
|
+
metaType = `typeof import('${pathPrefix}/${stripTsExtension(
|
|
1010
|
+
meta.relativePath
|
|
1011
|
+
)}')`;
|
|
1012
|
+
if (/\.(ts|js|mjs)$/.test(meta.relativePath)) {
|
|
1013
|
+
metaType += `['default']`;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
if (handler) {
|
|
1017
|
+
writeRouteTypeModule(
|
|
1018
|
+
serverWriter,
|
|
1019
|
+
pathPrefix,
|
|
1020
|
+
handler.relativePath,
|
|
1021
|
+
routeType
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
if (page) {
|
|
1025
|
+
writer.writeLines(`
|
|
1026
|
+
declare module '${pathPrefix}/${page.relativePath}' {
|
|
1027
|
+
export interface Input {}
|
|
1028
|
+
|
|
1029
|
+
namespace MarkoRun {
|
|
1030
|
+
type Route = ${routeType};
|
|
1031
|
+
type Context = AnyContext<AnyContext['platform'], Route>;
|
|
1032
|
+
}
|
|
1033
|
+
}`);
|
|
1034
|
+
}
|
|
1035
|
+
if (middleware) {
|
|
1036
|
+
let i = 0;
|
|
1037
|
+
for (const mw of middleware) {
|
|
1038
|
+
const existing = middlewareRouteTypes.get(mw);
|
|
1039
|
+
if (!existing) {
|
|
1040
|
+
middlewareRouteTypes.set(mw, {
|
|
1041
|
+
routeTypes: [routeType],
|
|
1042
|
+
middleware: middleware.slice(0, i)
|
|
1043
|
+
});
|
|
1044
|
+
} else {
|
|
1045
|
+
existing.routeTypes.push(routeType);
|
|
1046
|
+
}
|
|
1047
|
+
i++;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
if (layouts) {
|
|
1051
|
+
for (const layout of layouts) {
|
|
1052
|
+
const existing = layoutRouteTypes.get(layout);
|
|
1053
|
+
if (!existing) {
|
|
1054
|
+
layoutRouteTypes.set(layout, {
|
|
1055
|
+
routeTypes: [routeType]
|
|
1056
|
+
});
|
|
1057
|
+
} else {
|
|
1058
|
+
existing.routeTypes.push(routeType);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
routesWriter.writeLines(
|
|
1063
|
+
`interface ${routeType} extends AnyRoute<${paramsType}, ${metaType}, ${pathType}> {}`
|
|
1064
|
+
);
|
|
1065
|
+
}
|
|
1066
|
+
pathsWriter.write(" type GetPaths =");
|
|
1067
|
+
for (const path3 of getPaths) {
|
|
1068
|
+
pathsWriter.write(`
|
|
1069
|
+
| '${path3}'`);
|
|
1070
|
+
}
|
|
1071
|
+
pathsWriter.writeLines(";", "");
|
|
1072
|
+
pathsWriter.write(" type PostPaths =");
|
|
1073
|
+
for (const path3 of postPaths) {
|
|
1074
|
+
pathsWriter.write(`
|
|
1075
|
+
| '${path3}'`);
|
|
1076
|
+
}
|
|
1077
|
+
pathsWriter.writeLines(";");
|
|
1078
|
+
pathsWriter.join();
|
|
1079
|
+
for (const [file, { routeTypes }] of middlewareRouteTypes) {
|
|
1080
|
+
writeRouteTypeModule(
|
|
1081
|
+
serverWriter,
|
|
1082
|
+
pathPrefix,
|
|
1083
|
+
file.relativePath,
|
|
1084
|
+
routeTypes.join(" | ")
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
for (const [file, { routeTypes }] of layoutRouteTypes) {
|
|
1088
|
+
writer.writeLines(`
|
|
1089
|
+
declare module '${pathPrefix}/${file.relativePath}' {
|
|
1090
|
+
export interface Input {
|
|
1091
|
+
renderBody: Marko.Body;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
namespace MarkoRun {
|
|
1095
|
+
type Route = ${routeTypes.join(" | ")};
|
|
1096
|
+
type Context = AnyContext<AnyContext['platform'], Route>;
|
|
1097
|
+
}
|
|
1098
|
+
}`);
|
|
1099
|
+
}
|
|
1100
|
+
for (const route of [routes.special["404"], routes.special["500"]]) {
|
|
1101
|
+
if (route && route.page) {
|
|
1102
|
+
writer.write(`
|
|
1103
|
+
declare module '${pathPrefix}/${route.page.relativePath}' {
|
|
1104
|
+
export interface Input {`);
|
|
1105
|
+
if (route.page.type === RoutableFileTypes.Error) {
|
|
1106
|
+
writer.write(`
|
|
1107
|
+
error: unknown;
|
|
1108
|
+
`);
|
|
1109
|
+
}
|
|
1110
|
+
writer.writeLines(`}
|
|
1111
|
+
|
|
1112
|
+
namespace MarkoRun {
|
|
1113
|
+
type Route = AnyRoute;
|
|
1114
|
+
type Context = AnyContext<AnyContext['platform'], Route>;
|
|
1115
|
+
}
|
|
1116
|
+
}`);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
serverWriter.join();
|
|
1120
|
+
return writer.end();
|
|
1121
|
+
}
|
|
1122
|
+
function writeRouteTypeModule(writer, pathPrefix, path3, routeType) {
|
|
1123
|
+
writer.writeLines(`
|
|
1124
|
+
declare module '${pathPrefix}/${stripTsExtension(path3)}' {
|
|
1125
|
+
namespace MarkoRun {
|
|
1126
|
+
type Route = ${routeType};
|
|
1127
|
+
type Context = AnyContext<AnyContext['platform'], Route>;
|
|
1128
|
+
type Handler<_Params = Route['params'], _Meta = Route['meta']> = HandlerLike<Route>;
|
|
1129
|
+
function route(handler: Handler): typeof handler;
|
|
1130
|
+
function route<_Params = Route['params'], _Meta = Route['meta']>(handler: Handler): typeof handler;
|
|
1131
|
+
}
|
|
1132
|
+
}`);
|
|
830
1133
|
}
|
|
831
1134
|
|
|
832
1135
|
// src/vite/utils/ast.ts
|
|
@@ -873,7 +1176,7 @@ function getExportIdentifiers(astProgramNode) {
|
|
|
873
1176
|
import Table from "cli-table3";
|
|
874
1177
|
import kleur from "kleur";
|
|
875
1178
|
import { gzipSizeSync } from "gzip-size";
|
|
876
|
-
import
|
|
1179
|
+
import format from "human-format";
|
|
877
1180
|
var HttpVerbColors = {
|
|
878
1181
|
get: kleur.green,
|
|
879
1182
|
post: kleur.magenta,
|
|
@@ -900,7 +1203,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
900
1203
|
headings.push("Meta");
|
|
901
1204
|
colAligns.push("center");
|
|
902
1205
|
}
|
|
903
|
-
headings.push("Size");
|
|
1206
|
+
headings.push("Size/GZip");
|
|
904
1207
|
colAligns.push("right");
|
|
905
1208
|
const table = new Table({
|
|
906
1209
|
head: headings.map((title) => kleur.bold(kleur.white(title.toUpperCase()))),
|
|
@@ -931,7 +1234,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
931
1234
|
row.push(entryType.join(" -> "));
|
|
932
1235
|
hasMiddleware && row.push(route.middleware.length || "");
|
|
933
1236
|
hasMeta && row.push(route.meta ? "\u2713" : "");
|
|
934
|
-
row.push(size ||
|
|
1237
|
+
row.push(size || "");
|
|
935
1238
|
table.push(row);
|
|
936
1239
|
}
|
|
937
1240
|
}
|
|
@@ -947,54 +1250,75 @@ function logRoutesTable(routes, bundle) {
|
|
|
947
1250
|
function computeRouteSize(route, bundle) {
|
|
948
1251
|
if (route.page) {
|
|
949
1252
|
for (const chunk of Object.values(bundle)) {
|
|
950
|
-
if (chunk.type === "chunk"
|
|
951
|
-
|
|
1253
|
+
if (chunk.type === "chunk") {
|
|
1254
|
+
for (const key of Object.keys(chunk.modules)) {
|
|
1255
|
+
if (key.startsWith(route.page.filePath)) {
|
|
1256
|
+
return computeChunkSize(chunk, bundle);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
952
1259
|
}
|
|
953
1260
|
}
|
|
954
1261
|
}
|
|
955
|
-
return 0;
|
|
1262
|
+
return [0, 0];
|
|
1263
|
+
}
|
|
1264
|
+
function byteSize(str) {
|
|
1265
|
+
return new Blob([str]).size;
|
|
956
1266
|
}
|
|
957
1267
|
function computeChunkSize(chunk, bundle, seen = /* @__PURE__ */ new Set()) {
|
|
958
1268
|
if (chunk.type === "asset") {
|
|
959
|
-
return
|
|
1269
|
+
return [
|
|
1270
|
+
byteSize(chunk.source),
|
|
1271
|
+
gzipSizeSync(chunk.source)
|
|
1272
|
+
];
|
|
960
1273
|
}
|
|
961
|
-
|
|
1274
|
+
const size = [byteSize(chunk.code), gzipSizeSync(chunk.code)];
|
|
962
1275
|
for (const id of chunk.imports) {
|
|
963
1276
|
if (!seen.has(id)) {
|
|
964
|
-
|
|
1277
|
+
const [bytes, compBytes] = computeChunkSize(bundle[id], bundle, seen);
|
|
1278
|
+
size[0] += bytes;
|
|
1279
|
+
size[1] += compBytes;
|
|
965
1280
|
seen.add(id);
|
|
966
1281
|
}
|
|
967
1282
|
}
|
|
968
1283
|
return size;
|
|
969
1284
|
}
|
|
970
|
-
function prettySize(
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}).
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
if (
|
|
978
|
-
|
|
979
|
-
|
|
1285
|
+
function prettySize([bytes, compBytes]) {
|
|
1286
|
+
if (bytes <= 0) {
|
|
1287
|
+
return kleur.gray("0.0 kB");
|
|
1288
|
+
}
|
|
1289
|
+
const [size, prefix] = format(bytes, { decimals: 1 }).split(/\s+/);
|
|
1290
|
+
const compSize = format(compBytes, { decimals: 1, prefix, unit: "B" });
|
|
1291
|
+
let str = kleur.white(size) + kleur.gray("/");
|
|
1292
|
+
if (compBytes < 20 * 1e3)
|
|
1293
|
+
str += kleur.green(compSize);
|
|
1294
|
+
else if (compBytes < 50 * 1e3)
|
|
1295
|
+
str += kleur.yellow(compSize);
|
|
1296
|
+
else
|
|
1297
|
+
kleur.bold(kleur.red(compSize));
|
|
1298
|
+
return str;
|
|
980
1299
|
}
|
|
981
1300
|
function prettyPath(path3) {
|
|
982
1301
|
return path3.replace(/\/\$\$(.*)$/, (_, p) => "/" + kleur.bold(kleur.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + kleur.bold(kleur.dim(`:${p}`)));
|
|
983
1302
|
}
|
|
984
1303
|
|
|
985
1304
|
// src/vite/utils/config.ts
|
|
986
|
-
var
|
|
987
|
-
|
|
988
|
-
|
|
1305
|
+
var PluginConfigKey = "__MARKO_RUN_PLUGIN_CONFIG__";
|
|
1306
|
+
var AdapterConfigKey = "__MARKO_RUN_ADAPTER_CONFIG__";
|
|
1307
|
+
function getConfig(obj, key) {
|
|
1308
|
+
return obj[key];
|
|
989
1309
|
}
|
|
990
|
-
function
|
|
991
|
-
|
|
992
|
-
return
|
|
1310
|
+
function setConfig(obj, key, value) {
|
|
1311
|
+
obj[key] = value;
|
|
1312
|
+
return obj;
|
|
993
1313
|
}
|
|
1314
|
+
var getExternalPluginOptions = (viteConfig) => getConfig(viteConfig, PluginConfigKey);
|
|
1315
|
+
var setExternalPluginOptions = (viteConfig, value) => setConfig(viteConfig, PluginConfigKey, value);
|
|
1316
|
+
var getExternalAdapterOptions = (viteConfig) => getConfig(viteConfig, AdapterConfigKey);
|
|
994
1317
|
|
|
995
1318
|
// src/vite/plugin.ts
|
|
1319
|
+
import { fileURLToPath } from "url";
|
|
1320
|
+
var __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
996
1321
|
var markoExt = ".marko";
|
|
997
|
-
var markoServeFilePrefix2 = "__marko-serve__";
|
|
998
1322
|
function isMarkoFile(id) {
|
|
999
1323
|
return id.endsWith(markoExt);
|
|
1000
1324
|
}
|
|
@@ -1003,8 +1327,10 @@ function markoServe(opts = {}) {
|
|
|
1003
1327
|
let store;
|
|
1004
1328
|
let root;
|
|
1005
1329
|
let resolvedRoutesDir;
|
|
1330
|
+
let typesDir;
|
|
1006
1331
|
let isBuild = false;
|
|
1007
1332
|
let isSSRBuild = false;
|
|
1333
|
+
let tsConfigExists;
|
|
1008
1334
|
let ssrEntryFiles;
|
|
1009
1335
|
let devEntryFile;
|
|
1010
1336
|
let devServer;
|
|
@@ -1013,6 +1339,7 @@ function markoServe(opts = {}) {
|
|
|
1013
1339
|
let routeDataFilename = "routes.json";
|
|
1014
1340
|
let extractVerbs;
|
|
1015
1341
|
let resolvedConfig;
|
|
1342
|
+
let typesFile;
|
|
1016
1343
|
let isStale = true;
|
|
1017
1344
|
let isRendered = false;
|
|
1018
1345
|
const virtualFiles = /* @__PURE__ */ new Map();
|
|
@@ -1020,6 +1347,20 @@ function markoServe(opts = {}) {
|
|
|
1020
1347
|
routesBuild: 0,
|
|
1021
1348
|
routesRender: 0
|
|
1022
1349
|
};
|
|
1350
|
+
async function writeTypesFile() {
|
|
1351
|
+
if (tsConfigExists ?? (tsConfigExists = await globFileExists(
|
|
1352
|
+
root,
|
|
1353
|
+
"{.tsconfig*,tsconfig*.json}"
|
|
1354
|
+
))) {
|
|
1355
|
+
const filepath = path2.join(typesDir, "routes.d.ts");
|
|
1356
|
+
const adapterTypeInfo = (adapter == null ? void 0 : adapter.writeTypeInfo) && await (adapter == null ? void 0 : adapter.writeTypeInfo());
|
|
1357
|
+
const data = renderRouteTypeInfo(routes, path2.relative(typesDir, routesDir), adapterTypeInfo);
|
|
1358
|
+
if (data !== typesFile || !fs2.existsSync(filepath)) {
|
|
1359
|
+
await ensureDir(typesDir);
|
|
1360
|
+
await fs2.promises.writeFile(filepath, typesFile = data);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1023
1364
|
async function setVirtualFiles(render = false) {
|
|
1024
1365
|
for (const route of routes.list) {
|
|
1025
1366
|
if (render && route.handler) {
|
|
@@ -1032,24 +1373,30 @@ function markoServe(opts = {}) {
|
|
|
1032
1373
|
}
|
|
1033
1374
|
if (route.page) {
|
|
1034
1375
|
virtualFiles.set(
|
|
1035
|
-
path2.join(root, `${
|
|
1376
|
+
path2.join(root, `${markoRunFilePrefix}route__${route.key}.marko`),
|
|
1036
1377
|
render ? renderRouteTemplate(route) : ""
|
|
1037
1378
|
);
|
|
1038
1379
|
}
|
|
1039
1380
|
virtualFiles.set(
|
|
1040
|
-
path2.join(root, `${
|
|
1381
|
+
path2.join(root, `${markoRunFilePrefix}route__${route.key}.js`),
|
|
1041
1382
|
render ? renderRouteEntry(route) : ""
|
|
1042
1383
|
);
|
|
1043
1384
|
}
|
|
1044
1385
|
for (const route of Object.values(routes.special)) {
|
|
1045
1386
|
virtualFiles.set(
|
|
1046
|
-
path2.join(root, `${
|
|
1387
|
+
path2.join(root, `${markoRunFilePrefix}special__${route.key}.marko`),
|
|
1047
1388
|
render ? renderRouteTemplate(route) : ""
|
|
1048
1389
|
);
|
|
1049
1390
|
}
|
|
1050
1391
|
virtualFiles.set(
|
|
1051
1392
|
"@marko/run/router",
|
|
1052
|
-
render ? renderRouter(routes,
|
|
1393
|
+
render ? renderRouter(routes, {
|
|
1394
|
+
trailingSlashes: opts.trailingSlashes || "RedirectWithout"
|
|
1395
|
+
}) : ""
|
|
1396
|
+
);
|
|
1397
|
+
virtualFiles.set(
|
|
1398
|
+
path2.join(root, `${markoRunFilePrefix}middleware.js`),
|
|
1399
|
+
render ? renderMiddleware(routes.middleware) : ""
|
|
1053
1400
|
);
|
|
1054
1401
|
}
|
|
1055
1402
|
const buildVirtualFiles = single(async () => {
|
|
@@ -1063,6 +1410,7 @@ function markoServe(opts = {}) {
|
|
|
1063
1410
|
const renderVirtualFiles = single(async () => {
|
|
1064
1411
|
const startTime = performance.now();
|
|
1065
1412
|
await setVirtualFiles(true);
|
|
1413
|
+
await writeTypesFile();
|
|
1066
1414
|
times.routesRender = performance.now() - startTime;
|
|
1067
1415
|
isRendered = true;
|
|
1068
1416
|
});
|
|
@@ -1070,23 +1418,30 @@ function markoServe(opts = {}) {
|
|
|
1070
1418
|
{
|
|
1071
1419
|
name: "marko-run-vite:pre",
|
|
1072
1420
|
enforce: "pre",
|
|
1073
|
-
async config(
|
|
1421
|
+
async config(config2, env) {
|
|
1074
1422
|
var _a, _b, _c;
|
|
1075
|
-
const externalPluginOptions =
|
|
1423
|
+
const externalPluginOptions = getExternalPluginOptions(config2);
|
|
1076
1424
|
if (externalPluginOptions) {
|
|
1077
1425
|
opts = mergeConfig(opts, externalPluginOptions);
|
|
1078
1426
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1427
|
+
if (adapter) {
|
|
1428
|
+
const externalAdapterConfig = getExternalAdapterOptions(config2);
|
|
1429
|
+
if (externalAdapterConfig && adapter.configure) {
|
|
1430
|
+
adapter.configure(externalAdapterConfig);
|
|
1431
|
+
}
|
|
1432
|
+
const adapterOptions = await ((_a = adapter.pluginOptions) == null ? void 0 : _a.call(adapter, opts));
|
|
1433
|
+
if (adapterOptions) {
|
|
1434
|
+
opts = mergeConfig(opts, adapterOptions);
|
|
1435
|
+
}
|
|
1082
1436
|
}
|
|
1083
|
-
root = normalizePath(
|
|
1437
|
+
root = normalizePath(config2.root || process.cwd());
|
|
1084
1438
|
store = opts.store || new FileStore(
|
|
1085
1439
|
`marko-serve-vite-${crypto.createHash("SHA1").update(root).digest("hex")}`
|
|
1086
1440
|
);
|
|
1087
1441
|
isBuild = env.command === "build";
|
|
1088
|
-
isSSRBuild = isBuild && Boolean((_b =
|
|
1442
|
+
isSSRBuild = isBuild && Boolean((_b = config2.build) == null ? void 0 : _b.ssr);
|
|
1089
1443
|
resolvedRoutesDir = path2.resolve(root, routesDir);
|
|
1444
|
+
typesDir = path2.join(root, ".marko-run");
|
|
1090
1445
|
devEntryFile = path2.join(root, "index.html");
|
|
1091
1446
|
let pluginConfig = {
|
|
1092
1447
|
logLevel: isBuild ? "warn" : void 0,
|
|
@@ -1097,18 +1452,18 @@ function markoServe(opts = {}) {
|
|
|
1097
1452
|
emptyOutDir: isSSRBuild
|
|
1098
1453
|
}
|
|
1099
1454
|
};
|
|
1100
|
-
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter,
|
|
1455
|
+
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter, config2));
|
|
1101
1456
|
if (adapterConfig) {
|
|
1102
1457
|
pluginConfig = mergeConfig(pluginConfig, adapterConfig);
|
|
1103
1458
|
}
|
|
1104
|
-
return
|
|
1459
|
+
return setExternalPluginOptions(pluginConfig, opts);
|
|
1105
1460
|
},
|
|
1106
|
-
configResolved(
|
|
1107
|
-
resolvedConfig =
|
|
1461
|
+
configResolved(config2) {
|
|
1462
|
+
resolvedConfig = config2;
|
|
1108
1463
|
const {
|
|
1109
1464
|
ssr,
|
|
1110
1465
|
rollupOptions: { input }
|
|
1111
|
-
} =
|
|
1466
|
+
} = config2.build;
|
|
1112
1467
|
if (typeof ssr === "string") {
|
|
1113
1468
|
ssrEntryFiles = [ssr];
|
|
1114
1469
|
} else if (typeof input === "string") {
|
|
@@ -1139,6 +1494,7 @@ function markoServe(opts = {}) {
|
|
|
1139
1494
|
if (isStale) {
|
|
1140
1495
|
for (const id of virtualFiles.keys()) {
|
|
1141
1496
|
devServer.watcher.emit("change", id);
|
|
1497
|
+
break;
|
|
1142
1498
|
}
|
|
1143
1499
|
}
|
|
1144
1500
|
}
|
|
@@ -1168,12 +1524,18 @@ function markoServe(opts = {}) {
|
|
|
1168
1524
|
},
|
|
1169
1525
|
async resolveId(importee, importer, { ssr }) {
|
|
1170
1526
|
let resolved;
|
|
1171
|
-
if (importee.startsWith(
|
|
1527
|
+
if (importee.startsWith(virtualRuntimePrefix)) {
|
|
1528
|
+
return this.resolve(
|
|
1529
|
+
path2.resolve(__dirname, "../runtime/internal"),
|
|
1530
|
+
importer,
|
|
1531
|
+
{ skipSelf: true }
|
|
1532
|
+
);
|
|
1533
|
+
} else if (importee.startsWith(virtualFilePrefix)) {
|
|
1172
1534
|
importee = path2.resolve(
|
|
1173
1535
|
root,
|
|
1174
1536
|
importee.slice(virtualFilePrefix.length + 1)
|
|
1175
1537
|
);
|
|
1176
|
-
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${
|
|
1538
|
+
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${markoRunFilePrefix}`)) {
|
|
1177
1539
|
importee = path2.resolve(root, "." + importee);
|
|
1178
1540
|
}
|
|
1179
1541
|
if (isStale) {
|
|
@@ -1259,8 +1621,8 @@ async function getVerbsFromFileBuild(context, filePath) {
|
|
|
1259
1621
|
if (result) {
|
|
1260
1622
|
const exportIds = getExportIdentifiers(result.ast);
|
|
1261
1623
|
for (const id of exportIds) {
|
|
1262
|
-
const verb = id
|
|
1263
|
-
if (httpVerbs.includes(verb)) {
|
|
1624
|
+
const verb = id.toLowerCase();
|
|
1625
|
+
if (id === verb.toUpperCase() && httpVerbs.includes(verb)) {
|
|
1264
1626
|
verbs.push(verb);
|
|
1265
1627
|
}
|
|
1266
1628
|
}
|
|
@@ -1271,12 +1633,19 @@ async function getVerbsFromFileDev(devServer, filePath) {
|
|
|
1271
1633
|
const verbs = [];
|
|
1272
1634
|
const result = await devServer.transformRequest(filePath, { ssr: true });
|
|
1273
1635
|
if (result && result.code) {
|
|
1274
|
-
const verbMatchReg = /__vite_ssr_exports__,\s+["'](
|
|
1636
|
+
const verbMatchReg = /__vite_ssr_exports__,\s+["'](GET|POST|PUT|DELETE)["']/gi;
|
|
1275
1637
|
let match = verbMatchReg.exec(result.code);
|
|
1276
1638
|
while (match) {
|
|
1277
|
-
const
|
|
1639
|
+
const id = match[1];
|
|
1640
|
+
const verb = id.toLowerCase();
|
|
1278
1641
|
if (httpVerbs.includes(verb)) {
|
|
1279
|
-
|
|
1642
|
+
if (id === verb.toUpperCase()) {
|
|
1643
|
+
verbs.push(verb);
|
|
1644
|
+
} else {
|
|
1645
|
+
console.warn(
|
|
1646
|
+
`Found export '${id}' in handler ${filePath} which is close to '${verb.toUpperCase()}'. Exported handlers need to be uppercase: GET, POST, PUT or DELETE.`
|
|
1647
|
+
);
|
|
1648
|
+
}
|
|
1280
1649
|
}
|
|
1281
1650
|
match = verbMatchReg.exec(result.code);
|
|
1282
1651
|
}
|
|
@@ -1295,20 +1664,49 @@ function single(fn) {
|
|
|
1295
1664
|
return result;
|
|
1296
1665
|
};
|
|
1297
1666
|
}
|
|
1667
|
+
async function globFileExists(root, pattern) {
|
|
1668
|
+
return new Promise((resolve, reject) => {
|
|
1669
|
+
glob(pattern, { root }, (err, matches) => {
|
|
1670
|
+
if (err) {
|
|
1671
|
+
reject(err);
|
|
1672
|
+
}
|
|
1673
|
+
resolve(matches.length > 0);
|
|
1674
|
+
});
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
async function ensureDir(dir) {
|
|
1678
|
+
if (!fs2.existsSync(dir)) {
|
|
1679
|
+
await fs2.promises.mkdir(dir, { recursive: true });
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1298
1682
|
|
|
1299
1683
|
// src/vite/utils/server.ts
|
|
1300
1684
|
import net from "net";
|
|
1301
1685
|
import cp from "child_process";
|
|
1302
|
-
|
|
1686
|
+
import { parse, config } from "dotenv";
|
|
1687
|
+
import fs3 from "fs";
|
|
1688
|
+
async function parseEnv(envFile) {
|
|
1689
|
+
if (fs3.existsSync(envFile)) {
|
|
1690
|
+
const content = await fs3.promises.readFile(envFile, "utf8");
|
|
1691
|
+
return parse(content);
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
function loadEnv(envFile) {
|
|
1695
|
+
config({ path: envFile });
|
|
1696
|
+
}
|
|
1697
|
+
async function spawnServer(cmd, port = 0, env, cwd = process.cwd(), wait = 3e4) {
|
|
1303
1698
|
if (port <= 0) {
|
|
1304
1699
|
port = await getAvailablePort();
|
|
1305
1700
|
}
|
|
1701
|
+
if (typeof env === "string") {
|
|
1702
|
+
env = await parseEnv(env);
|
|
1703
|
+
}
|
|
1306
1704
|
const proc = cp.spawn(cmd, {
|
|
1307
1705
|
cwd,
|
|
1308
1706
|
shell: true,
|
|
1309
1707
|
stdio: "inherit",
|
|
1310
1708
|
windowsHide: true,
|
|
1311
|
-
env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1709
|
+
env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1312
1710
|
});
|
|
1313
1711
|
const close = () => {
|
|
1314
1712
|
proc.unref();
|
|
@@ -1355,5 +1753,7 @@ export {
|
|
|
1355
1753
|
markoServe as default,
|
|
1356
1754
|
getAvailablePort,
|
|
1357
1755
|
isPortInUse,
|
|
1756
|
+
loadEnv,
|
|
1757
|
+
parseEnv,
|
|
1358
1758
|
spawnServer
|
|
1359
1759
|
};
|