@marko/run 0.0.1-beta2 → 0.0.1-beta4
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 +102 -74
- package/dist/adapter/default-entry.mjs +9 -3
- package/dist/adapter/dev-server.d.ts +1 -1
- package/dist/adapter/index.cjs +189 -8
- package/dist/adapter/index.d.ts +1 -0
- package/dist/adapter/index.js +188 -7
- package/dist/adapter/middleware.cjs +199 -0
- package/dist/adapter/middleware.d.ts +55 -0
- package/dist/adapter/middleware.js +168 -0
- package/dist/cli/default.config.mjs +1 -1
- package/dist/cli/index.mjs +88 -59
- package/dist/runtime/index.cjs +0 -16
- package/dist/runtime/index.d.ts +10 -2
- package/dist/runtime/index.js +0 -7
- package/dist/runtime/internal.cjs +148 -0
- package/dist/runtime/internal.d.ts +10 -0
- package/dist/runtime/internal.js +115 -0
- package/dist/runtime/router.cjs +9 -7
- package/dist/runtime/router.d.ts +4 -4
- package/dist/runtime/router.js +7 -5
- package/dist/runtime/types.d.ts +29 -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 +557 -282
- package/dist/vite/index.d.ts +4 -3
- package/dist/vite/index.js +554 -282
- package/dist/vite/types.d.ts +14 -7
- package/dist/vite/utils/config.d.ts +5 -3
- package/dist/vite/utils/server.d.ts +3 -1
- package/package.json +23 -11
package/dist/vite/index.cjs
CHANGED
|
@@ -29,6 +29,8 @@ __export(vite_exports, {
|
|
|
29
29
|
default: () => markoServe,
|
|
30
30
|
getAvailablePort: () => getAvailablePort,
|
|
31
31
|
isPortInUse: () => isPortInUse,
|
|
32
|
+
loadEnv: () => loadEnv,
|
|
33
|
+
parseEnv: () => parseEnv,
|
|
32
34
|
spawnServer: () => spawnServer
|
|
33
35
|
});
|
|
34
36
|
module.exports = __toCommonJS(vite_exports);
|
|
@@ -36,13 +38,16 @@ module.exports = __toCommonJS(vite_exports);
|
|
|
36
38
|
// src/vite/plugin.ts
|
|
37
39
|
var import_path2 = __toESM(require("path"), 1);
|
|
38
40
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
41
|
+
var import_fs2 = __toESM(require("fs"), 1);
|
|
42
|
+
var import_glob = __toESM(require("glob"), 1);
|
|
39
43
|
var import_vite = require("vite");
|
|
40
44
|
var import_vite2 = __toESM(require("@marko/vite"), 1);
|
|
41
45
|
|
|
42
46
|
// src/vite/constants.ts
|
|
43
|
-
var
|
|
44
|
-
var virtualFilePrefix = "virtual:marko-
|
|
47
|
+
var markoRunFilePrefix = "__marko-run__";
|
|
48
|
+
var virtualFilePrefix = "virtual:marko-run";
|
|
45
49
|
var virtualRoutesPrefix = `${virtualFilePrefix}/routes`;
|
|
50
|
+
var virtualRuntimePrefix = `${virtualFilePrefix}/internal`;
|
|
46
51
|
var httpVerbs = ["get", "post", "put", "delete"];
|
|
47
52
|
var serverEntryQuery = "?marko-server-entry";
|
|
48
53
|
var browserEntryQuery = "?marko-browser-entry";
|
|
@@ -82,15 +87,20 @@ function isSpecialType(type) {
|
|
|
82
87
|
return type === RoutableFileTypes.NotFound || type === RoutableFileTypes.Error;
|
|
83
88
|
}
|
|
84
89
|
async function buildRoutes(walk, basePath) {
|
|
85
|
-
|
|
90
|
+
if (basePath) {
|
|
91
|
+
basePath = basePath.replace(/^\/+|\/+$/g, "");
|
|
92
|
+
}
|
|
93
|
+
const dirStack = [];
|
|
86
94
|
const pathStack = [];
|
|
87
95
|
const paramStack = [];
|
|
88
96
|
const layoutsStack = [];
|
|
89
97
|
const middlewareStack = [];
|
|
90
98
|
const routes = /* @__PURE__ */ new Map();
|
|
91
99
|
const special = {};
|
|
100
|
+
const middleware = /* @__PURE__ */ new Set();
|
|
92
101
|
let isRoot = true;
|
|
93
|
-
let
|
|
102
|
+
let nextFileId = 1;
|
|
103
|
+
let nextRouteIndex = 1;
|
|
94
104
|
let current;
|
|
95
105
|
let children = [];
|
|
96
106
|
await walk({
|
|
@@ -118,10 +128,13 @@ async function buildRoutes(walk, basePath) {
|
|
|
118
128
|
if (!entries) {
|
|
119
129
|
current.files.set(type, entries = []);
|
|
120
130
|
}
|
|
131
|
+
const relativePath = current.originalPath ? `${current.originalPath}/${entry.name}` : entry.name;
|
|
121
132
|
entries.push({
|
|
133
|
+
id: String(nextFileId++),
|
|
122
134
|
type,
|
|
123
135
|
filePath: entry.path,
|
|
124
|
-
|
|
136
|
+
relativePath,
|
|
137
|
+
importPath: `${basePath}/${relativePath}`,
|
|
125
138
|
name: entry.name,
|
|
126
139
|
verbs: type === RoutableFileTypes.Page ? ["get"] : void 0
|
|
127
140
|
});
|
|
@@ -132,20 +145,24 @@ async function buildRoutes(walk, basePath) {
|
|
|
132
145
|
return;
|
|
133
146
|
}
|
|
134
147
|
const { path: path3, files } = current;
|
|
135
|
-
const
|
|
136
|
-
const
|
|
148
|
+
const localMiddleware = (_a = files.get(RoutableFileTypes.Middleware)) == null ? void 0 : _a[0];
|
|
149
|
+
const localLayout = (_b = files.get(RoutableFileTypes.Layout)) == null ? void 0 : _b[0];
|
|
137
150
|
const handler = (_c = files.get(RoutableFileTypes.Handler)) == null ? void 0 : _c[0];
|
|
138
151
|
const page = (_d = files.get(RoutableFileTypes.Page)) == null ? void 0 : _d[0];
|
|
139
152
|
const middlewareStackLength = middlewareStack.length;
|
|
140
153
|
const layoutsStackLength = layoutsStack.length;
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
if (localMiddleware) {
|
|
155
|
+
middlewareStack.push(localMiddleware);
|
|
156
|
+
}
|
|
157
|
+
if (localLayout) {
|
|
158
|
+
layoutsStack.push(localLayout);
|
|
159
|
+
}
|
|
143
160
|
if (handler || page) {
|
|
144
161
|
const key = path3.replace(/(\$\$?)[^\/]*/g, "$1").replace(/^\/+/, "").replace(/[^a-z0-9_$\/]+/gi, "").replace(/\//g, "__") || "index";
|
|
145
162
|
if (routes.has(key)) {
|
|
146
163
|
console.warn(`Duplicate route for path ${path3} -- ignoring`, current);
|
|
147
164
|
} else {
|
|
148
|
-
const index =
|
|
165
|
+
const index = nextRouteIndex++;
|
|
149
166
|
routes.set(key, {
|
|
150
167
|
index,
|
|
151
168
|
key,
|
|
@@ -158,6 +175,9 @@ async function buildRoutes(walk, basePath) {
|
|
|
158
175
|
handler,
|
|
159
176
|
score: scorePath(path3, index)
|
|
160
177
|
});
|
|
178
|
+
for (const mw of middlewareStack) {
|
|
179
|
+
middleware.add(mw);
|
|
180
|
+
}
|
|
161
181
|
}
|
|
162
182
|
}
|
|
163
183
|
if (isRoot) {
|
|
@@ -193,7 +213,7 @@ async function buildRoutes(walk, basePath) {
|
|
|
193
213
|
if (name.charCodeAt(0) === 36) {
|
|
194
214
|
if (name.charCodeAt(1) === 36) {
|
|
195
215
|
paramStack.push({
|
|
196
|
-
name: name.slice(2) || "
|
|
216
|
+
name: name.slice(2) || "rest",
|
|
197
217
|
index: -1
|
|
198
218
|
});
|
|
199
219
|
} else if (name.length > 1) {
|
|
@@ -223,7 +243,8 @@ async function buildRoutes(walk, basePath) {
|
|
|
223
243
|
});
|
|
224
244
|
return {
|
|
225
245
|
list: [...routes.values()],
|
|
226
|
-
special
|
|
246
|
+
special,
|
|
247
|
+
middleware: [...middleware]
|
|
227
248
|
};
|
|
228
249
|
}
|
|
229
250
|
|
|
@@ -273,6 +294,17 @@ function createWriter(sink, options) {
|
|
|
273
294
|
let firstOpenIndex = 0;
|
|
274
295
|
const branches = [];
|
|
275
296
|
const openWriters = /* @__PURE__ */ new Map();
|
|
297
|
+
function write(data) {
|
|
298
|
+
if (!writer.__isActive) {
|
|
299
|
+
throw new Error("Cannot write to branch that has been joined");
|
|
300
|
+
}
|
|
301
|
+
if (openWriters.size) {
|
|
302
|
+
buffer += data;
|
|
303
|
+
} else {
|
|
304
|
+
sink(data);
|
|
305
|
+
}
|
|
306
|
+
return writer;
|
|
307
|
+
}
|
|
276
308
|
const writer = {
|
|
277
309
|
__isActive: true,
|
|
278
310
|
get indent() {
|
|
@@ -289,24 +321,16 @@ function createWriter(sink, options) {
|
|
|
289
321
|
}
|
|
290
322
|
}
|
|
291
323
|
},
|
|
292
|
-
write(data) {
|
|
293
|
-
if (
|
|
294
|
-
|
|
295
|
-
}
|
|
296
|
-
if (openWriters.size) {
|
|
297
|
-
buffer += data;
|
|
298
|
-
} else {
|
|
299
|
-
sink(data);
|
|
324
|
+
write(data, indent = false) {
|
|
325
|
+
if (indent && indentString) {
|
|
326
|
+
write(indentString);
|
|
300
327
|
}
|
|
301
|
-
return
|
|
328
|
+
return write(data);
|
|
302
329
|
},
|
|
303
330
|
writeLines(...lines) {
|
|
304
331
|
for (const line of lines) {
|
|
305
332
|
if (line) {
|
|
306
|
-
|
|
307
|
-
writer.write(indentString);
|
|
308
|
-
}
|
|
309
|
-
writer.write(line);
|
|
333
|
+
writer.write(line, true);
|
|
310
334
|
}
|
|
311
335
|
writer.write("\n");
|
|
312
336
|
}
|
|
@@ -453,16 +477,13 @@ function hasVerb(route, verb) {
|
|
|
453
477
|
}
|
|
454
478
|
|
|
455
479
|
// src/vite/codegen/index.ts
|
|
456
|
-
var DefaultCodegenOptions = {
|
|
457
|
-
trailingSlashes: "RedirectWithout"
|
|
458
|
-
};
|
|
459
480
|
function renderRouteTemplate(route) {
|
|
460
481
|
if (!route.page) {
|
|
461
482
|
throw new Error(`Route ${route.key} has no page to render`);
|
|
462
483
|
}
|
|
463
484
|
const writer = createStringWriter();
|
|
464
485
|
writer.writeLines(
|
|
465
|
-
`// ${virtualFilePrefix}/${
|
|
486
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.marko`
|
|
466
487
|
);
|
|
467
488
|
writer.branch("imports");
|
|
468
489
|
writer.writeLines("");
|
|
@@ -494,25 +515,47 @@ function renderRouteEntry(route) {
|
|
|
494
515
|
}
|
|
495
516
|
const writer = createStringWriter();
|
|
496
517
|
writer.writeLines(
|
|
497
|
-
`// ${virtualFilePrefix}/${
|
|
518
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.js`
|
|
498
519
|
);
|
|
499
520
|
const imports = writer.branch("imports");
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
i++;
|
|
521
|
+
const runtimeImports = [];
|
|
522
|
+
if (handler) {
|
|
523
|
+
runtimeImports.push("normalize");
|
|
504
524
|
}
|
|
505
|
-
if (
|
|
506
|
-
|
|
507
|
-
|
|
525
|
+
if (handler || middleware.length) {
|
|
526
|
+
runtimeImports.push("call");
|
|
527
|
+
}
|
|
528
|
+
if (!page || verbs.length > 1) {
|
|
529
|
+
runtimeImports.push("noContent");
|
|
530
|
+
}
|
|
531
|
+
if (runtimeImports.length) {
|
|
532
|
+
imports.writeLines(
|
|
533
|
+
`import { ${runtimeImports.join(", ")} } from '${virtualRuntimePrefix}';`
|
|
508
534
|
);
|
|
535
|
+
}
|
|
536
|
+
if (middleware.length) {
|
|
537
|
+
const names = middleware.map((m) => `mware$${m.id}`);
|
|
538
|
+
imports.writeLines(
|
|
539
|
+
`import { ${names.join(
|
|
540
|
+
", "
|
|
541
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}middleware.js';`
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.length) {
|
|
545
|
+
writer.writeLines("");
|
|
546
|
+
const names = [];
|
|
547
|
+
for (const verb of handler.verbs) {
|
|
548
|
+
const name = verb === "delete" ? "del" : verb;
|
|
549
|
+
names.push(name);
|
|
550
|
+
writer.writeLines(`const handler$${name} = normalize(${name});`);
|
|
551
|
+
}
|
|
509
552
|
imports.writeLines(
|
|
510
553
|
`import { ${names.join(", ")} } from './${handler.importPath}';`
|
|
511
554
|
);
|
|
512
555
|
}
|
|
513
556
|
if (page) {
|
|
514
557
|
imports.writeLines(
|
|
515
|
-
`import page from '${virtualFilePrefix}/${
|
|
558
|
+
`import page from '${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.marko${serverEntryQuery}';`
|
|
516
559
|
);
|
|
517
560
|
}
|
|
518
561
|
if (meta) {
|
|
@@ -520,21 +563,27 @@ function renderRouteEntry(route) {
|
|
|
520
563
|
`export { default as meta$${index} } from './${meta.importPath}';`
|
|
521
564
|
);
|
|
522
565
|
}
|
|
523
|
-
if (!page || verbs.length > 1) {
|
|
524
|
-
writer.writeLines("").writeBlockStart(`function create204Response() {`).writeBlockStart(`return new Response(null, {`).writeLines(`status: 204`).writeBlockEnd(`})`).writeBlockEnd(`}`);
|
|
525
|
-
}
|
|
526
566
|
for (const verb of verbs) {
|
|
527
567
|
writeRouteEntryHandler(writer, route, verb);
|
|
528
568
|
}
|
|
529
569
|
return writer.end();
|
|
530
570
|
}
|
|
531
|
-
function
|
|
571
|
+
function writePageResponse(writer, wrapFn) {
|
|
532
572
|
writer.writeBlock(
|
|
533
|
-
`return new Response(page.stream(
|
|
573
|
+
`${wrapFn ? `const ${wrapFn} = () =>` : `return`} new Response(page.stream(buildInput()), {`,
|
|
534
574
|
["status: 200,", 'headers: { "content-type": "text/html;charset=UTF-8" }'],
|
|
535
575
|
"});"
|
|
536
576
|
);
|
|
537
577
|
}
|
|
578
|
+
function writeMiddleware(writer, middleware, next, wrapFn) {
|
|
579
|
+
if (wrapFn) {
|
|
580
|
+
writer.writeLines(
|
|
581
|
+
`const ${wrapFn} = () => call(${middleware}, ${next}, context);`
|
|
582
|
+
);
|
|
583
|
+
} else {
|
|
584
|
+
writer.writeLines(`return call(${middleware}, ${next}, context);`);
|
|
585
|
+
}
|
|
586
|
+
}
|
|
538
587
|
function writeRouteEntryHandler(writer, route, verb) {
|
|
539
588
|
var _a;
|
|
540
589
|
const { key, index, page, handler, middleware } = route;
|
|
@@ -542,47 +591,38 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
542
591
|
let nextName;
|
|
543
592
|
let currentName;
|
|
544
593
|
let hasBody = false;
|
|
545
|
-
writer.writeLines("").writeBlockStart(
|
|
594
|
+
writer.writeLines("").writeBlockStart(
|
|
595
|
+
`export async function ${verb}$${index}(context, buildInput) {`
|
|
596
|
+
);
|
|
546
597
|
const continuations = writer.branch("cont");
|
|
547
598
|
if (page && verb === "get") {
|
|
548
|
-
currentName = "
|
|
599
|
+
currentName = "__page";
|
|
549
600
|
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
continuations.writeBlockEnd("}");
|
|
601
|
+
const name = `handler$${verb}`;
|
|
602
|
+
writePageResponse(continuations, currentName);
|
|
553
603
|
if (len) {
|
|
554
604
|
nextName = currentName;
|
|
555
|
-
currentName = `
|
|
556
|
-
continuations
|
|
557
|
-
`async function ${currentName}() {`,
|
|
558
|
-
[`return await handler$${verb}(ctx, ${nextName});`],
|
|
559
|
-
"}"
|
|
560
|
-
);
|
|
605
|
+
currentName = `__${name}`;
|
|
606
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
561
607
|
} else {
|
|
562
|
-
writer
|
|
608
|
+
writeMiddleware(writer, name, currentName);
|
|
563
609
|
hasBody = true;
|
|
564
610
|
}
|
|
565
611
|
} else if (len) {
|
|
566
|
-
continuations
|
|
567
|
-
writePageResponseContinuation(continuations);
|
|
568
|
-
continuations.writeBlockEnd("}");
|
|
612
|
+
writePageResponse(continuations, currentName);
|
|
569
613
|
nextName = currentName;
|
|
570
614
|
} else {
|
|
571
|
-
|
|
615
|
+
writePageResponse(continuations);
|
|
572
616
|
hasBody = true;
|
|
573
617
|
}
|
|
574
618
|
} else if (handler) {
|
|
575
|
-
|
|
619
|
+
const name = `handler$${verb}`;
|
|
620
|
+
currentName = `__${name}`;
|
|
621
|
+
nextName = "noContent";
|
|
576
622
|
if (len) {
|
|
577
|
-
continuations
|
|
578
|
-
`async function ${currentName}() {`,
|
|
579
|
-
[`return await handler$${verb}(ctx, create204Response);`],
|
|
580
|
-
"}"
|
|
581
|
-
);
|
|
623
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
582
624
|
} else {
|
|
583
|
-
writer
|
|
584
|
-
`return await handler$${verb}(ctx, create204Response);`
|
|
585
|
-
);
|
|
625
|
+
writeMiddleware(writer, name, nextName);
|
|
586
626
|
hasBody = true;
|
|
587
627
|
}
|
|
588
628
|
} else {
|
|
@@ -590,24 +630,26 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
590
630
|
}
|
|
591
631
|
if (!hasBody) {
|
|
592
632
|
let i = len;
|
|
593
|
-
while (--
|
|
633
|
+
while (i--) {
|
|
634
|
+
const { id } = middleware[i];
|
|
635
|
+
const name = `mware$${id}`;
|
|
594
636
|
nextName = currentName;
|
|
595
|
-
currentName = `
|
|
596
|
-
continuations
|
|
597
|
-
`async function ${currentName}() {`,
|
|
598
|
-
[`return await middleware$${i + 1}(ctx, ${nextName});`],
|
|
599
|
-
"}"
|
|
600
|
-
);
|
|
637
|
+
currentName = i ? `__${name}` : "";
|
|
638
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
601
639
|
}
|
|
602
|
-
writer.writeLines(`return await middleware$1(ctx, ${currentName});`);
|
|
603
640
|
}
|
|
604
641
|
continuations.join();
|
|
605
642
|
writer.writeBlockEnd("}");
|
|
606
643
|
}
|
|
607
|
-
function renderRouter(routes, options =
|
|
644
|
+
function renderRouter(routes, options = {
|
|
645
|
+
trailingSlashes: "RedirectWithout"
|
|
646
|
+
}) {
|
|
608
647
|
const writer = createStringWriter();
|
|
609
648
|
writer.writeLines(`// @marko/run/router`);
|
|
610
649
|
const imports = writer.branch("imports");
|
|
650
|
+
imports.writeLines(
|
|
651
|
+
`import { RequestNotHandled, RequestNotMatched, createInput } from 'virtual:marko-run/internal';`
|
|
652
|
+
);
|
|
611
653
|
for (const route of routes.list) {
|
|
612
654
|
const verbs = getVerbs(route);
|
|
613
655
|
const names = verbs.map((verb) => `${verb}$${route.index}`);
|
|
@@ -615,15 +657,15 @@ function renderRouter(routes, options = DefaultCodegenOptions) {
|
|
|
615
657
|
imports.writeLines(
|
|
616
658
|
`import { ${names.join(
|
|
617
659
|
", "
|
|
618
|
-
)} } from '${virtualFilePrefix}/${
|
|
660
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.js';`
|
|
619
661
|
);
|
|
620
662
|
}
|
|
621
663
|
for (const { key } of Object.values(routes.special)) {
|
|
622
664
|
imports.writeLines(
|
|
623
|
-
`import page$${key} from '${virtualFilePrefix}/${
|
|
665
|
+
`import page$${key} from '${virtualFilePrefix}/${markoRunFilePrefix}special__${key}.marko${serverEntryQuery}';`
|
|
624
666
|
);
|
|
625
667
|
}
|
|
626
|
-
writer.writeLines(
|
|
668
|
+
writer.writeLines(``).writeBlockStart(`function findRoute(method, pathname) {`).writeBlockStart(`switch (method.toLowerCase()) {`);
|
|
627
669
|
for (const verb of httpVerbs) {
|
|
628
670
|
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
629
671
|
if (filteredRoutes.length) {
|
|
@@ -633,120 +675,105 @@ function renderRouter(routes, options = DefaultCodegenOptions) {
|
|
|
633
675
|
writer.writeBlockEnd("}");
|
|
634
676
|
}
|
|
635
677
|
}
|
|
636
|
-
writer.writeBlockEnd("}").writeBlockEnd("}");
|
|
637
|
-
writer.
|
|
638
|
-
|
|
639
|
-
if (
|
|
640
|
-
|
|
678
|
+
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
679
|
+
writer.write(`
|
|
680
|
+
export function matchRoute(method, pathname) {
|
|
681
|
+
if (!pathname) {
|
|
682
|
+
pathname = '/';
|
|
683
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
684
|
+
pathname = '/' + pathname;
|
|
641
685
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
686
|
+
return findRoute(method, pathname);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export async function invokeRoute(route, context) {
|
|
690
|
+
try {
|
|
691
|
+
const buildInput = createInput(context);
|
|
692
|
+
if (route) {
|
|
693
|
+
context.params = route.params;
|
|
694
|
+
context.meta = route.meta;
|
|
695
|
+
try {
|
|
696
|
+
const response = await route.handler(context, buildInput);
|
|
697
|
+
if (response) return response;
|
|
698
|
+
} catch (error) {
|
|
699
|
+
if (error === RequestNotHandled) {
|
|
700
|
+
return;
|
|
701
|
+
} else if (error !== RequestNotMatched) {
|
|
702
|
+
throw error;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
`).indent = 2;
|
|
706
|
+
if (routes.special[RoutableFileTypes.NotFound]) {
|
|
707
|
+
writer.write(
|
|
708
|
+
` } else {
|
|
709
|
+
context.params = {};
|
|
710
|
+
context.meta = {};
|
|
711
|
+
}
|
|
712
|
+
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
713
|
+
return new Response(page$404.stream(buildInput()), {
|
|
714
|
+
status: 404,
|
|
715
|
+
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
`
|
|
719
|
+
);
|
|
720
|
+
} else {
|
|
721
|
+
writer.writeBlockEnd("}");
|
|
663
722
|
}
|
|
664
|
-
writer.
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
writer.writeBlockStart(
|
|
668
|
-
`if (request.headers.get('Accept')?.includes('text/html')) {`
|
|
723
|
+
writer.indent--;
|
|
724
|
+
writer.writeBlockStart(`} catch (error) {`);
|
|
725
|
+
if (routes.special[RoutableFileTypes.Error]) {
|
|
726
|
+
writer.writeBlockStart(
|
|
727
|
+
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
669
728
|
).writeBlock(
|
|
670
|
-
`return new Response(page$500.stream({
|
|
729
|
+
`return new Response(page$500.stream(buildInput({ error })), {`,
|
|
671
730
|
[
|
|
672
731
|
`status: 500,`,
|
|
673
732
|
`headers: { "content-type": "text/html;charset=UTF-8" },`
|
|
674
733
|
],
|
|
675
734
|
`});`
|
|
676
|
-
).writeBlockEnd("}")
|
|
677
|
-
}
|
|
678
|
-
writer.writeBlockEnd("}");
|
|
679
|
-
writer.write(`
|
|
680
|
-
export function getMatchedRoute(method, url) {
|
|
681
|
-
const route = matchRoute(method, url.pathname);
|
|
682
|
-
if (route) {
|
|
683
|
-
const [handler, params = {}, meta] = route;
|
|
684
|
-
return {
|
|
685
|
-
handler,
|
|
686
|
-
params,
|
|
687
|
-
meta,
|
|
688
|
-
async invoke(request) {
|
|
689
|
-
return await invokeRoute(route, url, request);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
735
|
+
).writeBlockEnd("}");
|
|
692
736
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
export async function handler(context) {
|
|
697
|
-
const response = await router(context.request);
|
|
698
|
-
//if (response.body) {
|
|
699
|
-
// context.waitUntil?.(once(Readable.from(response.body), "end"));
|
|
700
|
-
//}
|
|
701
|
-
return response;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
export async function router(request) {
|
|
737
|
+
writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
|
|
738
|
+
export async function router(context) {
|
|
705
739
|
try {
|
|
706
|
-
const url =
|
|
707
|
-
let { pathname } = url;
|
|
708
|
-
|
|
709
|
-
if (pathname !== '/') {
|
|
710
|
-
if (pathname.endsWith('/')) {
|
|
711
|
-
pathname = pathname.replace(/\\/+$/, '');
|
|
712
|
-
`);
|
|
740
|
+
const { url, method } = context;
|
|
741
|
+
let { pathname } = url;`);
|
|
713
742
|
switch (options.trailingSlashes) {
|
|
714
743
|
case "RedirectWithout":
|
|
715
744
|
writer.write(`
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
745
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
746
|
+
url.pathname = pathname.slice(0, -1);
|
|
747
|
+
return Response.redirect(url);
|
|
748
|
+
}`);
|
|
719
749
|
break;
|
|
720
750
|
case "RedirectWith":
|
|
721
751
|
writer.write(`
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
`);
|
|
752
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
753
|
+
url.pathname = pathname + '/';
|
|
754
|
+
return Response.redirect(url);
|
|
755
|
+
}`);
|
|
726
756
|
break;
|
|
727
757
|
case "RewriteWithout":
|
|
728
758
|
writer.write(`
|
|
729
|
-
|
|
730
|
-
|
|
759
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
760
|
+
url.pathname = pathname = pathname.slice(0, -1);
|
|
761
|
+
}`);
|
|
731
762
|
break;
|
|
732
763
|
case "RewriteWith":
|
|
733
764
|
writer.write(`
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
`);
|
|
765
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
766
|
+
url.pathname = pathname = pathname + '/';
|
|
767
|
+
}`);
|
|
737
768
|
break;
|
|
738
769
|
}
|
|
739
|
-
writer.write(`
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
statusText: \`Not Found (No route matched \${pathname})\`,
|
|
745
|
-
status: 404
|
|
746
|
-
});
|
|
747
|
-
} catch (err) {
|
|
770
|
+
writer.write(`
|
|
771
|
+
|
|
772
|
+
const route = matchRoute(method, pathname);
|
|
773
|
+
return await invokeRoute(route, context);
|
|
774
|
+
} catch (error) {
|
|
748
775
|
const message = import.meta.env.DEV
|
|
749
|
-
? \`Internal Server Error (\${
|
|
776
|
+
? \`Internal Server Error (\${error.message})\`
|
|
750
777
|
: "Internal Server Error";
|
|
751
778
|
|
|
752
779
|
return new Response(
|
|
@@ -754,7 +781,7 @@ export async function router(request) {
|
|
|
754
781
|
error: {
|
|
755
782
|
message,
|
|
756
783
|
stack: import.meta.env.DEV
|
|
757
|
-
? \`This will only be seen in development mode\\n\\n\${
|
|
784
|
+
? \`This will only be seen in development mode\\n\\n\${error.stack}\`
|
|
758
785
|
: ""
|
|
759
786
|
}
|
|
760
787
|
}),
|
|
@@ -767,101 +794,259 @@ export async function router(request) {
|
|
|
767
794
|
}`);
|
|
768
795
|
return writer.end();
|
|
769
796
|
}
|
|
770
|
-
function writeRouterVerb(writer, trie, verb, level = 0,
|
|
771
|
-
const {
|
|
772
|
-
|
|
773
|
-
if (level
|
|
774
|
-
|
|
775
|
-
if (
|
|
776
|
-
writer.writeLines(
|
|
777
|
-
`if (pathname === '/') return ${renderMatch(verb, value)}; // ${value.path}`
|
|
778
|
-
);
|
|
779
|
-
}
|
|
780
|
-
if (children || dynamic) {
|
|
781
|
-
writer.writeLines(
|
|
782
|
-
`const segments = pathname.split('/');`,
|
|
783
|
-
`const len = segments.length;`
|
|
784
|
-
);
|
|
785
|
-
}
|
|
786
|
-
} else {
|
|
787
|
-
if (!key) {
|
|
788
|
-
writer.writeBlockStart(`if (segments[${level}]) {`);
|
|
789
|
-
} else if (useSwitch) {
|
|
790
|
-
writer.writeBlockStart(`case '${key}':`);
|
|
791
|
-
} else {
|
|
792
|
-
writer.writeBlockStart(
|
|
793
|
-
`if (segments[${level}]?.toLowerCase() === '${key}') {`
|
|
794
|
-
);
|
|
795
|
-
}
|
|
796
|
-
if (value) {
|
|
797
|
+
function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
|
|
798
|
+
const { route, dynamic, catchAll } = trie;
|
|
799
|
+
let closeCount = 0;
|
|
800
|
+
if (level === 0) {
|
|
801
|
+
writer.writeLines(`const len = pathname.length;`);
|
|
802
|
+
if (route) {
|
|
797
803
|
writer.writeLines(
|
|
798
|
-
`if (len ===
|
|
804
|
+
`if (len === 1) return ${renderMatch(verb, route)}; // ${route.path}`
|
|
799
805
|
);
|
|
806
|
+
} else if (trie.static || dynamic) {
|
|
807
|
+
writer.writeBlockStart(`if (len > 1) {`);
|
|
808
|
+
closeCount++;
|
|
800
809
|
}
|
|
801
810
|
}
|
|
802
|
-
if (
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
811
|
+
if (trie.static || dynamic) {
|
|
812
|
+
const next = level + 1;
|
|
813
|
+
const index = `i${next}`;
|
|
814
|
+
let terminal;
|
|
815
|
+
let children;
|
|
816
|
+
writer.writeLines(`const ${index} = pathname.indexOf('/', ${offset}) + 1;`);
|
|
817
|
+
if (trie.static) {
|
|
818
|
+
for (const child of trie.static.values()) {
|
|
819
|
+
if (child.route) {
|
|
820
|
+
(terminal ?? (terminal = [])).push(child);
|
|
810
821
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
822
|
+
if (child.static || child.dynamic || child.catchAll) {
|
|
823
|
+
(children ?? (children = [])).push(child);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
828
|
+
closeCount++;
|
|
829
|
+
writer.writeBlockStart(`if (!${index} || ${index} === len) {`);
|
|
830
|
+
let value = `pathname.slice(${offset}, ${index} ? -1 : len)`;
|
|
831
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
832
|
+
const segment = `s${next}`;
|
|
833
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
834
|
+
value = segment;
|
|
835
|
+
}
|
|
836
|
+
if (terminal) {
|
|
837
|
+
const useSwitch = terminal.length > 1;
|
|
838
|
+
if (useSwitch) {
|
|
839
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
840
|
+
}
|
|
841
|
+
for (const { key, route: route2 } of terminal) {
|
|
842
|
+
if (useSwitch) {
|
|
843
|
+
writer.write(`case '${key}': `, true);
|
|
844
|
+
} else {
|
|
845
|
+
writer.write(`if (${value}.toLowerCase() === '${key}') `, true);
|
|
846
|
+
}
|
|
847
|
+
writer.write(
|
|
848
|
+
`return ${renderMatch(verb, route2)}; // ${route2.path}
|
|
849
|
+
`
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
if (useSwitch) {
|
|
853
|
+
writer.writeBlockEnd("}");
|
|
815
854
|
}
|
|
816
855
|
}
|
|
856
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
857
|
+
writer.writeLines(
|
|
858
|
+
`if (${value}) return ${renderMatch(verb, dynamic.route)}; // ${dynamic.route.path}`
|
|
859
|
+
);
|
|
860
|
+
}
|
|
817
861
|
}
|
|
818
|
-
if (dynamic) {
|
|
819
|
-
|
|
862
|
+
if (children || (dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
863
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
864
|
+
writer.writeBlockEnd("} else {").indent++;
|
|
865
|
+
} else {
|
|
866
|
+
writer.writeBlockStart(`if (${index} && ${index} !== len) {`);
|
|
867
|
+
closeCount++;
|
|
868
|
+
}
|
|
869
|
+
let value = `pathname.slice(${offset}, ${index} - 1)`;
|
|
870
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic)) {
|
|
871
|
+
const segment = `s${next}`;
|
|
872
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
873
|
+
value = segment;
|
|
874
|
+
}
|
|
875
|
+
if (children) {
|
|
876
|
+
const useSwitch = children.length > 1;
|
|
877
|
+
if (useSwitch) {
|
|
878
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
879
|
+
}
|
|
880
|
+
for (const child of children) {
|
|
881
|
+
if (useSwitch) {
|
|
882
|
+
writer.writeBlockStart(`case '${child.key}': {`);
|
|
883
|
+
} else {
|
|
884
|
+
writer.writeBlockStart(
|
|
885
|
+
`if (${value}.toLowerCase() === '${child.key}') {`
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
const nextOffset = typeof offset === "string" ? index : offset + child.key.length + 1;
|
|
889
|
+
writeRouterVerb(writer, child, verb, next, nextOffset);
|
|
890
|
+
writer.writeBlockEnd("}");
|
|
891
|
+
}
|
|
892
|
+
if (useSwitch) {
|
|
893
|
+
writer.writeBlockEnd("}");
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
897
|
+
writer.writeBlockStart(`if (${value}) {`);
|
|
898
|
+
writeRouterVerb(writer, dynamic, verb, next, index);
|
|
899
|
+
writer.writeBlockEnd(`}`);
|
|
900
|
+
}
|
|
820
901
|
}
|
|
821
902
|
}
|
|
903
|
+
while (closeCount--) {
|
|
904
|
+
writer.writeBlockEnd("}");
|
|
905
|
+
}
|
|
822
906
|
if (catchAll) {
|
|
823
907
|
writer.writeLines(
|
|
824
|
-
`return ${renderMatch(verb, catchAll,
|
|
908
|
+
`return ${renderMatch(verb, catchAll, String(offset))}; // ${catchAll.path}`
|
|
825
909
|
);
|
|
826
|
-
if (level > 0) {
|
|
827
|
-
writer.indent--;
|
|
828
|
-
}
|
|
829
910
|
} else if (level === 0) {
|
|
830
|
-
writer.writeLines("return;");
|
|
831
|
-
} else if (useSwitch) {
|
|
832
|
-
writer.writeLines("break;").indent--;
|
|
833
|
-
} else {
|
|
834
|
-
writer.writeBlockEnd("}");
|
|
911
|
+
writer.writeLines("return null;");
|
|
835
912
|
}
|
|
836
913
|
}
|
|
914
|
+
function wrapPropertyName(name) {
|
|
915
|
+
return /^[^A-Za-z_$]|[^A-Za-z0-9$_]/.test(name) ? `'${name}'` : name;
|
|
916
|
+
}
|
|
837
917
|
function renderParamsInfo(params, pathIndex) {
|
|
918
|
+
if (!params.length) {
|
|
919
|
+
return "{}";
|
|
920
|
+
}
|
|
838
921
|
let result = "";
|
|
839
922
|
let catchAll = "";
|
|
840
|
-
let
|
|
923
|
+
let sep = "{";
|
|
841
924
|
for (const { name, index } of params) {
|
|
842
925
|
if (index >= 0) {
|
|
843
|
-
result +=
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
} else if (pathIndex && pathIndex >= 0) {
|
|
926
|
+
result += `${sep} ${wrapPropertyName(name)}: s${index + 1}`;
|
|
927
|
+
sep || (sep = ",");
|
|
928
|
+
} else if (pathIndex) {
|
|
847
929
|
catchAll = name;
|
|
848
930
|
}
|
|
849
931
|
}
|
|
850
932
|
if (catchAll) {
|
|
851
|
-
result +=
|
|
852
|
-
|
|
933
|
+
result += `${sep} ${wrapPropertyName(
|
|
934
|
+
catchAll
|
|
935
|
+
)}: pathname.slice(${pathIndex})`;
|
|
853
936
|
}
|
|
854
937
|
return result ? result + " }" : "{}";
|
|
855
938
|
}
|
|
856
|
-
function
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
tuple[1] = renderParamsInfo(params, pathIndex);
|
|
939
|
+
function renderParamsInfoType(params) {
|
|
940
|
+
if (!params.length) {
|
|
941
|
+
return "{}";
|
|
860
942
|
}
|
|
861
|
-
|
|
862
|
-
|
|
943
|
+
let result = "{";
|
|
944
|
+
for (const { name } of params) {
|
|
945
|
+
result += ` ${wrapPropertyName(name)}: string;`;
|
|
946
|
+
}
|
|
947
|
+
return result + " }";
|
|
948
|
+
}
|
|
949
|
+
function renderMatch(verb, route, pathIndex) {
|
|
950
|
+
var _a;
|
|
951
|
+
const handler = `${verb}$${route.index}`;
|
|
952
|
+
const params = ((_a = route.params) == null ? void 0 : _a.length) ? renderParamsInfo(route.params, pathIndex) : "{}";
|
|
953
|
+
const meta = route.meta ? `meta$${route.index}` : "{}";
|
|
954
|
+
return `{ handler: ${handler}, params: ${params}, meta: ${meta} }`;
|
|
955
|
+
}
|
|
956
|
+
function renderMiddleware(middleware) {
|
|
957
|
+
const writer = createStringWriter();
|
|
958
|
+
writer.writeLines(
|
|
959
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}middleware.js`
|
|
960
|
+
);
|
|
961
|
+
const imports = writer.branch("imports");
|
|
962
|
+
imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
|
|
963
|
+
writer.writeLines("");
|
|
964
|
+
for (const { id, importPath } of middleware) {
|
|
965
|
+
const importName = `mware${id}`;
|
|
966
|
+
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
967
|
+
writer.writeLines(`export const mware$${id} = normalize(${importName});`);
|
|
968
|
+
}
|
|
969
|
+
imports.join();
|
|
970
|
+
return writer.end();
|
|
971
|
+
}
|
|
972
|
+
function stripTsExtension(path3) {
|
|
973
|
+
const index = path3.lastIndexOf(".");
|
|
974
|
+
if (index !== -1) {
|
|
975
|
+
const ext = path3.slice(index + 1);
|
|
976
|
+
if (ext.toLowerCase() === "ts") {
|
|
977
|
+
return path3.slice(0, index);
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
return path3;
|
|
981
|
+
}
|
|
982
|
+
function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
983
|
+
const writer = createStringWriter();
|
|
984
|
+
writer.writeLines(
|
|
985
|
+
`/*
|
|
986
|
+
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
987
|
+
Do NOT manually edit this file or your changes will be lost.
|
|
988
|
+
*/
|
|
989
|
+
`,
|
|
990
|
+
`import type { HandlerLike, Route } from "@marko/run";
|
|
991
|
+
`
|
|
992
|
+
);
|
|
993
|
+
const routesWriter = writer.branch("types");
|
|
994
|
+
const middlewareRouteTypes = /* @__PURE__ */ new Map();
|
|
995
|
+
for (const route of routes.list) {
|
|
996
|
+
const { meta, handler, params, middleware } = route;
|
|
997
|
+
const routeType = `Route${route.index}`;
|
|
998
|
+
const pathType = `\`${route.path.replace(
|
|
999
|
+
/\/\$(\$?)([^\/]*)/,
|
|
1000
|
+
(_, catchAll, name) => catchAll ? `/:${name || "rest"}*` : `/:${name}`
|
|
1001
|
+
)}\``;
|
|
1002
|
+
const paramsType = params ? renderParamsInfoType(params) : "{}";
|
|
1003
|
+
let metaType = "undefined";
|
|
1004
|
+
if (meta) {
|
|
1005
|
+
metaType = `typeof import('${pathPrefix}/${stripTsExtension(
|
|
1006
|
+
meta.relativePath
|
|
1007
|
+
)}')`;
|
|
1008
|
+
if (/\.(ts|js|mjs)$/.test(meta.relativePath)) {
|
|
1009
|
+
metaType += `['default']`;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
if (handler) {
|
|
1013
|
+
writeRouteTypeModule(writer, pathPrefix, handler.relativePath, routeType);
|
|
1014
|
+
}
|
|
1015
|
+
if (middleware) {
|
|
1016
|
+
let i = 0;
|
|
1017
|
+
for (const mw of middleware) {
|
|
1018
|
+
const existing = middlewareRouteTypes.get(mw);
|
|
1019
|
+
if (!existing) {
|
|
1020
|
+
middlewareRouteTypes.set(mw, {
|
|
1021
|
+
routeTypes: [routeType],
|
|
1022
|
+
middleware: middleware.slice(0, i)
|
|
1023
|
+
});
|
|
1024
|
+
} else {
|
|
1025
|
+
existing.routeTypes.push(routeType);
|
|
1026
|
+
}
|
|
1027
|
+
i++;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
routesWriter.writeLines(
|
|
1031
|
+
`interface ${routeType} extends Route<${paramsType}, ${metaType}, ${pathType}> {}`
|
|
1032
|
+
);
|
|
863
1033
|
}
|
|
864
|
-
|
|
1034
|
+
for (const [file, { routeTypes }] of middlewareRouteTypes) {
|
|
1035
|
+
const routeType = routeTypes.length > 1 ? routeTypes.join(" | ") : routeTypes[0];
|
|
1036
|
+
writeRouteTypeModule(writer, pathPrefix, file.relativePath, routeType);
|
|
1037
|
+
}
|
|
1038
|
+
return writer.end();
|
|
1039
|
+
}
|
|
1040
|
+
function writeRouteTypeModule(writer, pathPrefix, path3, routeType) {
|
|
1041
|
+
writer.writeLines(`
|
|
1042
|
+
declare module '${pathPrefix}/${stripTsExtension(path3)}' {
|
|
1043
|
+
namespace Marko {
|
|
1044
|
+
type CurrentRoute = ${routeType};
|
|
1045
|
+
type Handler<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']> = HandlerLike<CurrentRoute>;
|
|
1046
|
+
function route(handler: Handler): typeof handler;
|
|
1047
|
+
function route<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']>(handler: Handler): typeof handler;
|
|
1048
|
+
}
|
|
1049
|
+
}`);
|
|
865
1050
|
}
|
|
866
1051
|
|
|
867
1052
|
// src/vite/utils/ast.ts
|
|
@@ -908,7 +1093,7 @@ function getExportIdentifiers(astProgramNode) {
|
|
|
908
1093
|
var import_cli_table3 = __toESM(require("cli-table3"), 1);
|
|
909
1094
|
var import_kleur = __toESM(require("kleur"), 1);
|
|
910
1095
|
var import_gzip_size = require("gzip-size");
|
|
911
|
-
var
|
|
1096
|
+
var import_human_format = __toESM(require("human-format"), 1);
|
|
912
1097
|
var HttpVerbColors = {
|
|
913
1098
|
get: import_kleur.default.green,
|
|
914
1099
|
post: import_kleur.default.magenta,
|
|
@@ -935,7 +1120,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
935
1120
|
headings.push("Meta");
|
|
936
1121
|
colAligns.push("center");
|
|
937
1122
|
}
|
|
938
|
-
headings.push("Size");
|
|
1123
|
+
headings.push("Size/GZip");
|
|
939
1124
|
colAligns.push("right");
|
|
940
1125
|
const table = new import_cli_table3.default({
|
|
941
1126
|
head: headings.map((title) => import_kleur.default.bold(import_kleur.default.white(title.toUpperCase()))),
|
|
@@ -966,7 +1151,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
966
1151
|
row.push(entryType.join(" -> "));
|
|
967
1152
|
hasMiddleware && row.push(route.middleware.length || "");
|
|
968
1153
|
hasMeta && row.push(route.meta ? "\u2713" : "");
|
|
969
|
-
row.push(size ||
|
|
1154
|
+
row.push(size || "");
|
|
970
1155
|
table.push(row);
|
|
971
1156
|
}
|
|
972
1157
|
}
|
|
@@ -982,54 +1167,76 @@ function logRoutesTable(routes, bundle) {
|
|
|
982
1167
|
function computeRouteSize(route, bundle) {
|
|
983
1168
|
if (route.page) {
|
|
984
1169
|
for (const chunk of Object.values(bundle)) {
|
|
985
|
-
if (chunk.type === "chunk"
|
|
986
|
-
|
|
1170
|
+
if (chunk.type === "chunk") {
|
|
1171
|
+
for (const key of Object.keys(chunk.modules)) {
|
|
1172
|
+
if (key.startsWith(route.page.filePath)) {
|
|
1173
|
+
return computeChunkSize(chunk, bundle);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
987
1176
|
}
|
|
988
1177
|
}
|
|
989
1178
|
}
|
|
990
|
-
return 0;
|
|
1179
|
+
return [0, 0];
|
|
1180
|
+
}
|
|
1181
|
+
function byteSize(str) {
|
|
1182
|
+
return new Blob([str]).size;
|
|
991
1183
|
}
|
|
992
1184
|
function computeChunkSize(chunk, bundle, seen = /* @__PURE__ */ new Set()) {
|
|
993
1185
|
if (chunk.type === "asset") {
|
|
994
|
-
return
|
|
1186
|
+
return [
|
|
1187
|
+
byteSize(chunk.source),
|
|
1188
|
+
(0, import_gzip_size.gzipSizeSync)(chunk.source)
|
|
1189
|
+
];
|
|
995
1190
|
}
|
|
996
|
-
|
|
1191
|
+
const size = [byteSize(chunk.code), (0, import_gzip_size.gzipSizeSync)(chunk.code)];
|
|
997
1192
|
for (const id of chunk.imports) {
|
|
998
1193
|
if (!seen.has(id)) {
|
|
999
|
-
|
|
1194
|
+
const [bytes, compBytes] = computeChunkSize(bundle[id], bundle, seen);
|
|
1195
|
+
size[0] += bytes;
|
|
1196
|
+
size[1] += compBytes;
|
|
1000
1197
|
seen.add(id);
|
|
1001
1198
|
}
|
|
1002
1199
|
}
|
|
1003
1200
|
return size;
|
|
1004
1201
|
}
|
|
1005
|
-
function prettySize(
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
if (
|
|
1013
|
-
|
|
1014
|
-
|
|
1202
|
+
function prettySize([bytes, compBytes]) {
|
|
1203
|
+
if (bytes <= 0) {
|
|
1204
|
+
return import_kleur.default.gray("0.0 kB");
|
|
1205
|
+
}
|
|
1206
|
+
const [size, prefix] = (0, import_human_format.default)(bytes, { decimals: 1 }).split(/\s+/);
|
|
1207
|
+
const compSize = (0, import_human_format.default)(compBytes, { decimals: 1, prefix, unit: "B" });
|
|
1208
|
+
let str = import_kleur.default.white(size) + import_kleur.default.gray("/");
|
|
1209
|
+
if (compBytes < 20 * 1e3)
|
|
1210
|
+
str += import_kleur.default.green(compSize);
|
|
1211
|
+
else if (compBytes < 50 * 1e3)
|
|
1212
|
+
str += import_kleur.default.yellow(compSize);
|
|
1213
|
+
else
|
|
1214
|
+
import_kleur.default.bold(import_kleur.default.red(compSize));
|
|
1215
|
+
return str;
|
|
1015
1216
|
}
|
|
1016
1217
|
function prettyPath(path3) {
|
|
1017
1218
|
return path3.replace(/\/\$\$(.*)$/, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + import_kleur.default.bold(import_kleur.default.dim(`:${p}`)));
|
|
1018
1219
|
}
|
|
1019
1220
|
|
|
1020
1221
|
// src/vite/utils/config.ts
|
|
1021
|
-
var
|
|
1022
|
-
|
|
1023
|
-
|
|
1222
|
+
var PluginConfigKey = "__MARKO_RUN_PLUGIN_CONFIG__";
|
|
1223
|
+
var AdapterConfigKey = "__MARKO_RUN_ADAPTER_CONFIG__";
|
|
1224
|
+
function getConfig(obj, key) {
|
|
1225
|
+
return obj[key];
|
|
1024
1226
|
}
|
|
1025
|
-
function
|
|
1026
|
-
|
|
1027
|
-
return
|
|
1227
|
+
function setConfig(obj, key, value) {
|
|
1228
|
+
obj[key] = value;
|
|
1229
|
+
return obj;
|
|
1028
1230
|
}
|
|
1231
|
+
var getExternalPluginOptions = (viteConfig) => getConfig(viteConfig, PluginConfigKey);
|
|
1232
|
+
var setExternalPluginOptions = (viteConfig, value) => setConfig(viteConfig, PluginConfigKey, value);
|
|
1233
|
+
var getExternalAdapterOptions = (viteConfig) => getConfig(viteConfig, AdapterConfigKey);
|
|
1029
1234
|
|
|
1030
1235
|
// src/vite/plugin.ts
|
|
1236
|
+
var import_url = require("url");
|
|
1237
|
+
var import_meta = {};
|
|
1238
|
+
var __dirname = (0, import_url.fileURLToPath)(new URL(".", import_meta.url));
|
|
1031
1239
|
var markoExt = ".marko";
|
|
1032
|
-
var markoServeFilePrefix2 = "__marko-serve__";
|
|
1033
1240
|
function isMarkoFile(id) {
|
|
1034
1241
|
return id.endsWith(markoExt);
|
|
1035
1242
|
}
|
|
@@ -1038,8 +1245,10 @@ function markoServe(opts = {}) {
|
|
|
1038
1245
|
let store;
|
|
1039
1246
|
let root;
|
|
1040
1247
|
let resolvedRoutesDir;
|
|
1248
|
+
let typesDir;
|
|
1041
1249
|
let isBuild = false;
|
|
1042
1250
|
let isSSRBuild = false;
|
|
1251
|
+
let tsConfigExists;
|
|
1043
1252
|
let ssrEntryFiles;
|
|
1044
1253
|
let devEntryFile;
|
|
1045
1254
|
let devServer;
|
|
@@ -1048,6 +1257,7 @@ function markoServe(opts = {}) {
|
|
|
1048
1257
|
let routeDataFilename = "routes.json";
|
|
1049
1258
|
let extractVerbs;
|
|
1050
1259
|
let resolvedConfig;
|
|
1260
|
+
let typesFile;
|
|
1051
1261
|
let isStale = true;
|
|
1052
1262
|
let isRendered = false;
|
|
1053
1263
|
const virtualFiles = /* @__PURE__ */ new Map();
|
|
@@ -1055,6 +1265,20 @@ function markoServe(opts = {}) {
|
|
|
1055
1265
|
routesBuild: 0,
|
|
1056
1266
|
routesRender: 0
|
|
1057
1267
|
};
|
|
1268
|
+
async function writeTypesFile() {
|
|
1269
|
+
if (tsConfigExists ?? (tsConfigExists = await globFileExists(
|
|
1270
|
+
root,
|
|
1271
|
+
"{.tsconfig*,tsconfig*.json}"
|
|
1272
|
+
))) {
|
|
1273
|
+
const filepath = import_path2.default.join(typesDir, "routes.d.ts");
|
|
1274
|
+
const adapterTypeInfo = (adapter == null ? void 0 : adapter.writeTypeInfo) && await (adapter == null ? void 0 : adapter.writeTypeInfo());
|
|
1275
|
+
const data = renderRouteTypeInfo(routes, import_path2.default.relative(typesDir, routesDir)) + adapterTypeInfo;
|
|
1276
|
+
if (data !== typesFile || !import_fs2.default.existsSync(filepath)) {
|
|
1277
|
+
await ensureDir(typesDir);
|
|
1278
|
+
await import_fs2.default.promises.writeFile(filepath, typesFile = data);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1058
1282
|
async function setVirtualFiles(render = false) {
|
|
1059
1283
|
for (const route of routes.list) {
|
|
1060
1284
|
if (render && route.handler) {
|
|
@@ -1067,31 +1291,37 @@ function markoServe(opts = {}) {
|
|
|
1067
1291
|
}
|
|
1068
1292
|
if (route.page) {
|
|
1069
1293
|
virtualFiles.set(
|
|
1070
|
-
import_path2.default.join(root, `${
|
|
1294
|
+
import_path2.default.join(root, `${markoRunFilePrefix}route__${route.key}.marko`),
|
|
1071
1295
|
render ? renderRouteTemplate(route) : ""
|
|
1072
1296
|
);
|
|
1073
1297
|
}
|
|
1074
1298
|
virtualFiles.set(
|
|
1075
|
-
import_path2.default.join(root, `${
|
|
1299
|
+
import_path2.default.join(root, `${markoRunFilePrefix}route__${route.key}.js`),
|
|
1076
1300
|
render ? renderRouteEntry(route) : ""
|
|
1077
1301
|
);
|
|
1078
1302
|
}
|
|
1079
1303
|
for (const route of Object.values(routes.special)) {
|
|
1080
1304
|
virtualFiles.set(
|
|
1081
|
-
import_path2.default.join(root, `${
|
|
1305
|
+
import_path2.default.join(root, `${markoRunFilePrefix}special__${route.key}.marko`),
|
|
1082
1306
|
render ? renderRouteTemplate(route) : ""
|
|
1083
1307
|
);
|
|
1084
1308
|
}
|
|
1085
1309
|
virtualFiles.set(
|
|
1086
1310
|
"@marko/run/router",
|
|
1087
|
-
render ? renderRouter(routes,
|
|
1311
|
+
render ? renderRouter(routes, {
|
|
1312
|
+
trailingSlashes: opts.trailingSlashes || "RedirectWithout"
|
|
1313
|
+
}) : ""
|
|
1314
|
+
);
|
|
1315
|
+
virtualFiles.set(
|
|
1316
|
+
import_path2.default.join(root, `${markoRunFilePrefix}middleware.js`),
|
|
1317
|
+
render ? renderMiddleware(routes.middleware) : ""
|
|
1088
1318
|
);
|
|
1089
1319
|
}
|
|
1090
1320
|
const buildVirtualFiles = single(async () => {
|
|
1091
1321
|
const startTime = performance.now();
|
|
1092
1322
|
routes = await buildRoutes(createFSWalker(resolvedRoutesDir), routesDir);
|
|
1093
1323
|
times.routesBuild = performance.now() - startTime;
|
|
1094
|
-
await setVirtualFiles(false);
|
|
1324
|
+
await Promise.all([writeTypesFile(), setVirtualFiles(false)]);
|
|
1095
1325
|
isStale = false;
|
|
1096
1326
|
isRendered = false;
|
|
1097
1327
|
});
|
|
@@ -1105,23 +1335,30 @@ function markoServe(opts = {}) {
|
|
|
1105
1335
|
{
|
|
1106
1336
|
name: "marko-run-vite:pre",
|
|
1107
1337
|
enforce: "pre",
|
|
1108
|
-
async config(
|
|
1338
|
+
async config(config2, env) {
|
|
1109
1339
|
var _a, _b, _c;
|
|
1110
|
-
const externalPluginOptions =
|
|
1340
|
+
const externalPluginOptions = getExternalPluginOptions(config2);
|
|
1111
1341
|
if (externalPluginOptions) {
|
|
1112
1342
|
opts = (0, import_vite.mergeConfig)(opts, externalPluginOptions);
|
|
1113
1343
|
}
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1344
|
+
if (adapter) {
|
|
1345
|
+
const externalAdapterConfig = getExternalAdapterOptions(config2);
|
|
1346
|
+
if (externalAdapterConfig && adapter.configure) {
|
|
1347
|
+
adapter.configure(externalAdapterConfig);
|
|
1348
|
+
}
|
|
1349
|
+
const adapterOptions = await ((_a = adapter.pluginOptions) == null ? void 0 : _a.call(adapter, opts));
|
|
1350
|
+
if (adapterOptions) {
|
|
1351
|
+
opts = (0, import_vite.mergeConfig)(opts, adapterOptions);
|
|
1352
|
+
}
|
|
1117
1353
|
}
|
|
1118
|
-
root = (0, import_vite.normalizePath)(
|
|
1354
|
+
root = (0, import_vite.normalizePath)(config2.root || process.cwd());
|
|
1119
1355
|
store = opts.store || new import_vite2.FileStore(
|
|
1120
1356
|
`marko-serve-vite-${import_crypto.default.createHash("SHA1").update(root).digest("hex")}`
|
|
1121
1357
|
);
|
|
1122
1358
|
isBuild = env.command === "build";
|
|
1123
|
-
isSSRBuild = isBuild && Boolean((_b =
|
|
1359
|
+
isSSRBuild = isBuild && Boolean((_b = config2.build) == null ? void 0 : _b.ssr);
|
|
1124
1360
|
resolvedRoutesDir = import_path2.default.resolve(root, routesDir);
|
|
1361
|
+
typesDir = import_path2.default.join(root, ".marko-run");
|
|
1125
1362
|
devEntryFile = import_path2.default.join(root, "index.html");
|
|
1126
1363
|
let pluginConfig = {
|
|
1127
1364
|
logLevel: isBuild ? "warn" : void 0,
|
|
@@ -1132,18 +1369,18 @@ function markoServe(opts = {}) {
|
|
|
1132
1369
|
emptyOutDir: isSSRBuild
|
|
1133
1370
|
}
|
|
1134
1371
|
};
|
|
1135
|
-
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter,
|
|
1372
|
+
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter, config2));
|
|
1136
1373
|
if (adapterConfig) {
|
|
1137
1374
|
pluginConfig = (0, import_vite.mergeConfig)(pluginConfig, adapterConfig);
|
|
1138
1375
|
}
|
|
1139
|
-
return
|
|
1376
|
+
return setExternalPluginOptions(pluginConfig, opts);
|
|
1140
1377
|
},
|
|
1141
|
-
configResolved(
|
|
1142
|
-
resolvedConfig =
|
|
1378
|
+
configResolved(config2) {
|
|
1379
|
+
resolvedConfig = config2;
|
|
1143
1380
|
const {
|
|
1144
1381
|
ssr,
|
|
1145
1382
|
rollupOptions: { input }
|
|
1146
|
-
} =
|
|
1383
|
+
} = config2.build;
|
|
1147
1384
|
if (typeof ssr === "string") {
|
|
1148
1385
|
ssrEntryFiles = [ssr];
|
|
1149
1386
|
} else if (typeof input === "string") {
|
|
@@ -1174,6 +1411,7 @@ function markoServe(opts = {}) {
|
|
|
1174
1411
|
if (isStale) {
|
|
1175
1412
|
for (const id of virtualFiles.keys()) {
|
|
1176
1413
|
devServer.watcher.emit("change", id);
|
|
1414
|
+
break;
|
|
1177
1415
|
}
|
|
1178
1416
|
}
|
|
1179
1417
|
}
|
|
@@ -1203,12 +1441,18 @@ function markoServe(opts = {}) {
|
|
|
1203
1441
|
},
|
|
1204
1442
|
async resolveId(importee, importer, { ssr }) {
|
|
1205
1443
|
let resolved;
|
|
1206
|
-
if (importee.startsWith(
|
|
1444
|
+
if (importee.startsWith(virtualRuntimePrefix)) {
|
|
1445
|
+
return this.resolve(
|
|
1446
|
+
import_path2.default.resolve(__dirname, "../runtime/internal"),
|
|
1447
|
+
importer,
|
|
1448
|
+
{ skipSelf: true }
|
|
1449
|
+
);
|
|
1450
|
+
} else if (importee.startsWith(virtualFilePrefix)) {
|
|
1207
1451
|
importee = import_path2.default.resolve(
|
|
1208
1452
|
root,
|
|
1209
1453
|
importee.slice(virtualFilePrefix.length + 1)
|
|
1210
1454
|
);
|
|
1211
|
-
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${
|
|
1455
|
+
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${markoRunFilePrefix}`)) {
|
|
1212
1456
|
importee = import_path2.default.resolve(root, "." + importee);
|
|
1213
1457
|
}
|
|
1214
1458
|
if (isStale) {
|
|
@@ -1330,20 +1574,49 @@ function single(fn) {
|
|
|
1330
1574
|
return result;
|
|
1331
1575
|
};
|
|
1332
1576
|
}
|
|
1577
|
+
async function globFileExists(root, pattern) {
|
|
1578
|
+
return new Promise((resolve, reject) => {
|
|
1579
|
+
(0, import_glob.default)(pattern, { root }, (err, matches) => {
|
|
1580
|
+
if (err) {
|
|
1581
|
+
reject(err);
|
|
1582
|
+
}
|
|
1583
|
+
resolve(matches.length > 0);
|
|
1584
|
+
});
|
|
1585
|
+
});
|
|
1586
|
+
}
|
|
1587
|
+
async function ensureDir(dir) {
|
|
1588
|
+
if (!import_fs2.default.existsSync(dir)) {
|
|
1589
|
+
await import_fs2.default.promises.mkdir(dir, { recursive: true });
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1333
1592
|
|
|
1334
1593
|
// src/vite/utils/server.ts
|
|
1335
1594
|
var import_net = __toESM(require("net"), 1);
|
|
1336
1595
|
var import_child_process = __toESM(require("child_process"), 1);
|
|
1337
|
-
|
|
1596
|
+
var import_dotenv = require("dotenv");
|
|
1597
|
+
var import_fs3 = __toESM(require("fs"), 1);
|
|
1598
|
+
async function parseEnv(envFile) {
|
|
1599
|
+
if (import_fs3.default.existsSync(envFile)) {
|
|
1600
|
+
const content = await import_fs3.default.promises.readFile(envFile, "utf8");
|
|
1601
|
+
return (0, import_dotenv.parse)(content);
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
function loadEnv(envFile) {
|
|
1605
|
+
(0, import_dotenv.config)({ path: envFile });
|
|
1606
|
+
}
|
|
1607
|
+
async function spawnServer(cmd, port = 0, env, cwd = process.cwd(), wait = 3e4) {
|
|
1338
1608
|
if (port <= 0) {
|
|
1339
1609
|
port = await getAvailablePort();
|
|
1340
1610
|
}
|
|
1611
|
+
if (typeof env === "string") {
|
|
1612
|
+
env = await parseEnv(env);
|
|
1613
|
+
}
|
|
1341
1614
|
const proc = import_child_process.default.spawn(cmd, {
|
|
1342
1615
|
cwd,
|
|
1343
1616
|
shell: true,
|
|
1344
1617
|
stdio: "inherit",
|
|
1345
1618
|
windowsHide: true,
|
|
1346
|
-
env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1619
|
+
env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1347
1620
|
});
|
|
1348
1621
|
const close = () => {
|
|
1349
1622
|
proc.unref();
|
|
@@ -1390,5 +1663,7 @@ function sleep(ms) {
|
|
|
1390
1663
|
0 && (module.exports = {
|
|
1391
1664
|
getAvailablePort,
|
|
1392
1665
|
isPortInUse,
|
|
1666
|
+
loadEnv,
|
|
1667
|
+
parseEnv,
|
|
1393
1668
|
spawnServer
|
|
1394
1669
|
});
|