@marko/run 0.0.1-beta1 → 0.0.1-beta3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/default-entry.mjs +9 -3
- package/dist/adapter/dev-server.d.ts +1 -1
- package/dist/adapter/index.cjs +23 -8
- package/dist/adapter/index.js +22 -7
- package/dist/adapter/middleware.cjs +200 -0
- package/dist/adapter/middleware.d.ts +59 -0
- package/dist/adapter/middleware.js +169 -0
- package/dist/cli/default.config.mjs +1 -1
- package/dist/cli/index.mjs +45 -24
- 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 +6 -6
- package/dist/runtime/router.d.ts +4 -4
- package/dist/runtime/router.js +4 -4
- package/dist/runtime/types.d.ts +31 -16
- package/dist/runtime/utils.d.ts +3 -0
- 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 +542 -275
- package/dist/vite/index.d.ts +4 -3
- package/dist/vite/index.js +539 -275
- package/dist/vite/types.d.ts +9 -7
- package/dist/vite/utils/config.d.ts +2 -2
- package/dist/vite/utils/server.d.ts +3 -1
- package/package.json +18 -6
- 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,24 @@ 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
|
console.warn(`Duplicate route for path ${path3} -- ignoring`, current);
|
|
112
127
|
} else {
|
|
113
|
-
const index =
|
|
128
|
+
const index = nextRouteIndex++;
|
|
114
129
|
routes.set(key, {
|
|
115
130
|
index,
|
|
116
131
|
key,
|
|
@@ -123,6 +138,9 @@ async function buildRoutes(walk, basePath) {
|
|
|
123
138
|
handler,
|
|
124
139
|
score: scorePath(path3, index)
|
|
125
140
|
});
|
|
141
|
+
for (const mw of middlewareStack) {
|
|
142
|
+
middleware.add(mw);
|
|
143
|
+
}
|
|
126
144
|
}
|
|
127
145
|
}
|
|
128
146
|
if (isRoot) {
|
|
@@ -158,7 +176,7 @@ async function buildRoutes(walk, basePath) {
|
|
|
158
176
|
if (name.charCodeAt(0) === 36) {
|
|
159
177
|
if (name.charCodeAt(1) === 36) {
|
|
160
178
|
paramStack.push({
|
|
161
|
-
name: name.slice(2) || "
|
|
179
|
+
name: name.slice(2) || "rest",
|
|
162
180
|
index: -1
|
|
163
181
|
});
|
|
164
182
|
} else if (name.length > 1) {
|
|
@@ -188,7 +206,8 @@ async function buildRoutes(walk, basePath) {
|
|
|
188
206
|
});
|
|
189
207
|
return {
|
|
190
208
|
list: [...routes.values()],
|
|
191
|
-
special
|
|
209
|
+
special,
|
|
210
|
+
middleware: [...middleware]
|
|
192
211
|
};
|
|
193
212
|
}
|
|
194
213
|
|
|
@@ -238,6 +257,17 @@ function createWriter(sink, options) {
|
|
|
238
257
|
let firstOpenIndex = 0;
|
|
239
258
|
const branches = [];
|
|
240
259
|
const openWriters = /* @__PURE__ */ new Map();
|
|
260
|
+
function write(data) {
|
|
261
|
+
if (!writer.__isActive) {
|
|
262
|
+
throw new Error("Cannot write to branch that has been joined");
|
|
263
|
+
}
|
|
264
|
+
if (openWriters.size) {
|
|
265
|
+
buffer += data;
|
|
266
|
+
} else {
|
|
267
|
+
sink(data);
|
|
268
|
+
}
|
|
269
|
+
return writer;
|
|
270
|
+
}
|
|
241
271
|
const writer = {
|
|
242
272
|
__isActive: true,
|
|
243
273
|
get indent() {
|
|
@@ -254,24 +284,16 @@ function createWriter(sink, options) {
|
|
|
254
284
|
}
|
|
255
285
|
}
|
|
256
286
|
},
|
|
257
|
-
write(data) {
|
|
258
|
-
if (
|
|
259
|
-
|
|
287
|
+
write(data, indent = false) {
|
|
288
|
+
if (indent && indentString) {
|
|
289
|
+
write(indentString);
|
|
260
290
|
}
|
|
261
|
-
|
|
262
|
-
buffer += data;
|
|
263
|
-
} else {
|
|
264
|
-
sink(data);
|
|
265
|
-
}
|
|
266
|
-
return writer;
|
|
291
|
+
return write(data);
|
|
267
292
|
},
|
|
268
293
|
writeLines(...lines) {
|
|
269
294
|
for (const line of lines) {
|
|
270
295
|
if (line) {
|
|
271
|
-
|
|
272
|
-
writer.write(indentString);
|
|
273
|
-
}
|
|
274
|
-
writer.write(line);
|
|
296
|
+
writer.write(line, true);
|
|
275
297
|
}
|
|
276
298
|
writer.write("\n");
|
|
277
299
|
}
|
|
@@ -418,16 +440,13 @@ function hasVerb(route, verb) {
|
|
|
418
440
|
}
|
|
419
441
|
|
|
420
442
|
// src/vite/codegen/index.ts
|
|
421
|
-
var DefaultCodegenOptions = {
|
|
422
|
-
trailingSlashes: "RedirectWithout"
|
|
423
|
-
};
|
|
424
443
|
function renderRouteTemplate(route) {
|
|
425
444
|
if (!route.page) {
|
|
426
445
|
throw new Error(`Route ${route.key} has no page to render`);
|
|
427
446
|
}
|
|
428
447
|
const writer = createStringWriter();
|
|
429
448
|
writer.writeLines(
|
|
430
|
-
`// ${virtualFilePrefix}/${
|
|
449
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.marko`
|
|
431
450
|
);
|
|
432
451
|
writer.branch("imports");
|
|
433
452
|
writer.writeLines("");
|
|
@@ -459,25 +478,47 @@ function renderRouteEntry(route) {
|
|
|
459
478
|
}
|
|
460
479
|
const writer = createStringWriter();
|
|
461
480
|
writer.writeLines(
|
|
462
|
-
`// ${virtualFilePrefix}/${
|
|
481
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.js`
|
|
463
482
|
);
|
|
464
483
|
const imports = writer.branch("imports");
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
i++;
|
|
484
|
+
const runtimeImports = [];
|
|
485
|
+
if (handler) {
|
|
486
|
+
runtimeImports.push("normalize");
|
|
469
487
|
}
|
|
470
|
-
if (
|
|
471
|
-
|
|
472
|
-
|
|
488
|
+
if (handler || middleware.length) {
|
|
489
|
+
runtimeImports.push("call");
|
|
490
|
+
}
|
|
491
|
+
if (!page || verbs.length > 1) {
|
|
492
|
+
runtimeImports.push("noContent");
|
|
493
|
+
}
|
|
494
|
+
if (runtimeImports.length) {
|
|
495
|
+
imports.writeLines(
|
|
496
|
+
`import { ${runtimeImports.join(", ")} } from '${virtualRuntimePrefix}';`
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
if (middleware.length) {
|
|
500
|
+
const names = middleware.map((m) => `mware$${m.id}`);
|
|
501
|
+
imports.writeLines(
|
|
502
|
+
`import { ${names.join(
|
|
503
|
+
", "
|
|
504
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}middleware.js';`
|
|
473
505
|
);
|
|
506
|
+
}
|
|
507
|
+
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.length) {
|
|
508
|
+
writer.writeLines("");
|
|
509
|
+
const names = [];
|
|
510
|
+
for (const verb of handler.verbs) {
|
|
511
|
+
const name = verb === "delete" ? "del" : verb;
|
|
512
|
+
names.push(name);
|
|
513
|
+
writer.writeLines(`const handler$${name} = normalize(${name});`);
|
|
514
|
+
}
|
|
474
515
|
imports.writeLines(
|
|
475
516
|
`import { ${names.join(", ")} } from './${handler.importPath}';`
|
|
476
517
|
);
|
|
477
518
|
}
|
|
478
519
|
if (page) {
|
|
479
520
|
imports.writeLines(
|
|
480
|
-
`import page from '${virtualFilePrefix}/${
|
|
521
|
+
`import page from '${virtualFilePrefix}/${markoRunFilePrefix}route__${key}.marko${serverEntryQuery}';`
|
|
481
522
|
);
|
|
482
523
|
}
|
|
483
524
|
if (meta) {
|
|
@@ -485,21 +526,27 @@ function renderRouteEntry(route) {
|
|
|
485
526
|
`export { default as meta$${index} } from './${meta.importPath}';`
|
|
486
527
|
);
|
|
487
528
|
}
|
|
488
|
-
if (!page || verbs.length > 1) {
|
|
489
|
-
writer.writeLines("").writeBlockStart(`function create204Response() {`).writeBlockStart(`return new Response(null, {`).writeLines(`status: 204`).writeBlockEnd(`})`).writeBlockEnd(`}`);
|
|
490
|
-
}
|
|
491
529
|
for (const verb of verbs) {
|
|
492
530
|
writeRouteEntryHandler(writer, route, verb);
|
|
493
531
|
}
|
|
494
532
|
return writer.end();
|
|
495
533
|
}
|
|
496
|
-
function
|
|
534
|
+
function writePageResponse(writer, wrapFn) {
|
|
497
535
|
writer.writeBlock(
|
|
498
|
-
`return new Response(page.stream(
|
|
536
|
+
`${wrapFn ? `const ${wrapFn} = () =>` : `return`} new Response(page.stream(buildInput()), {`,
|
|
499
537
|
["status: 200,", 'headers: { "content-type": "text/html;charset=UTF-8" }'],
|
|
500
538
|
"});"
|
|
501
539
|
);
|
|
502
540
|
}
|
|
541
|
+
function writeMiddleware(writer, middleware, next, wrapFn) {
|
|
542
|
+
if (wrapFn) {
|
|
543
|
+
writer.writeLines(
|
|
544
|
+
`const ${wrapFn} = () => call(${middleware}, ${next}, context);`
|
|
545
|
+
);
|
|
546
|
+
} else {
|
|
547
|
+
writer.writeLines(`return call(${middleware}, ${next}, context);`);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
503
550
|
function writeRouteEntryHandler(writer, route, verb) {
|
|
504
551
|
var _a;
|
|
505
552
|
const { key, index, page, handler, middleware } = route;
|
|
@@ -507,47 +554,38 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
507
554
|
let nextName;
|
|
508
555
|
let currentName;
|
|
509
556
|
let hasBody = false;
|
|
510
|
-
writer.writeLines("").writeBlockStart(
|
|
557
|
+
writer.writeLines("").writeBlockStart(
|
|
558
|
+
`export async function ${verb}$${index}(context, buildInput) {`
|
|
559
|
+
);
|
|
511
560
|
const continuations = writer.branch("cont");
|
|
512
561
|
if (page && verb === "get") {
|
|
513
|
-
currentName = "
|
|
562
|
+
currentName = "__page";
|
|
514
563
|
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
continuations.writeBlockEnd("}");
|
|
564
|
+
const name = `handler$${verb}`;
|
|
565
|
+
writePageResponse(continuations, currentName);
|
|
518
566
|
if (len) {
|
|
519
567
|
nextName = currentName;
|
|
520
|
-
currentName = `
|
|
521
|
-
continuations
|
|
522
|
-
`async function ${currentName}() {`,
|
|
523
|
-
[`return await handler$${verb}(ctx, ${nextName});`],
|
|
524
|
-
"}"
|
|
525
|
-
);
|
|
568
|
+
currentName = `__${name}`;
|
|
569
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
526
570
|
} else {
|
|
527
|
-
writer
|
|
571
|
+
writeMiddleware(writer, name, currentName);
|
|
528
572
|
hasBody = true;
|
|
529
573
|
}
|
|
530
574
|
} else if (len) {
|
|
531
|
-
continuations
|
|
532
|
-
writePageResponseContinuation(continuations);
|
|
533
|
-
continuations.writeBlockEnd("}");
|
|
575
|
+
writePageResponse(continuations, currentName);
|
|
534
576
|
nextName = currentName;
|
|
535
577
|
} else {
|
|
536
|
-
|
|
578
|
+
writePageResponse(continuations);
|
|
537
579
|
hasBody = true;
|
|
538
580
|
}
|
|
539
581
|
} else if (handler) {
|
|
540
|
-
|
|
582
|
+
const name = `handler$${verb}`;
|
|
583
|
+
currentName = `__${name}`;
|
|
584
|
+
nextName = "noContent";
|
|
541
585
|
if (len) {
|
|
542
|
-
continuations
|
|
543
|
-
`async function ${currentName}() {`,
|
|
544
|
-
[`return await handler$${verb}(ctx, create204Response);`],
|
|
545
|
-
"}"
|
|
546
|
-
);
|
|
586
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
547
587
|
} else {
|
|
548
|
-
writer
|
|
549
|
-
`return await handler$${verb}(ctx, create204Response);`
|
|
550
|
-
);
|
|
588
|
+
writeMiddleware(writer, name, nextName);
|
|
551
589
|
hasBody = true;
|
|
552
590
|
}
|
|
553
591
|
} else {
|
|
@@ -555,24 +593,26 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
555
593
|
}
|
|
556
594
|
if (!hasBody) {
|
|
557
595
|
let i = len;
|
|
558
|
-
while (--
|
|
596
|
+
while (i--) {
|
|
597
|
+
const { id } = middleware[i];
|
|
598
|
+
const name = `mware$${id}`;
|
|
559
599
|
nextName = currentName;
|
|
560
|
-
currentName = `
|
|
561
|
-
continuations
|
|
562
|
-
`async function ${currentName}() {`,
|
|
563
|
-
[`return await middleware$${i + 1}(ctx, ${nextName});`],
|
|
564
|
-
"}"
|
|
565
|
-
);
|
|
600
|
+
currentName = i ? `__${name}` : "";
|
|
601
|
+
writeMiddleware(continuations, name, nextName, currentName);
|
|
566
602
|
}
|
|
567
|
-
writer.writeLines(`return await middleware$1(ctx, ${currentName});`);
|
|
568
603
|
}
|
|
569
604
|
continuations.join();
|
|
570
605
|
writer.writeBlockEnd("}");
|
|
571
606
|
}
|
|
572
|
-
function renderRouter(routes, options =
|
|
607
|
+
function renderRouter(routes, options = {
|
|
608
|
+
trailingSlashes: "RedirectWithout"
|
|
609
|
+
}) {
|
|
573
610
|
const writer = createStringWriter();
|
|
574
611
|
writer.writeLines(`// @marko/run/router`);
|
|
575
612
|
const imports = writer.branch("imports");
|
|
613
|
+
imports.writeLines(
|
|
614
|
+
`import { RequestNotHandled, RequestNotMatched, createInput } from 'virtual:marko-run/internal';`
|
|
615
|
+
);
|
|
576
616
|
for (const route of routes.list) {
|
|
577
617
|
const verbs = getVerbs(route);
|
|
578
618
|
const names = verbs.map((verb) => `${verb}$${route.index}`);
|
|
@@ -580,15 +620,15 @@ function renderRouter(routes, options = DefaultCodegenOptions) {
|
|
|
580
620
|
imports.writeLines(
|
|
581
621
|
`import { ${names.join(
|
|
582
622
|
", "
|
|
583
|
-
)} } from '${virtualFilePrefix}/${
|
|
623
|
+
)} } from '${virtualFilePrefix}/${markoRunFilePrefix}route__${route.key}.js';`
|
|
584
624
|
);
|
|
585
625
|
}
|
|
586
626
|
for (const { key } of Object.values(routes.special)) {
|
|
587
627
|
imports.writeLines(
|
|
588
|
-
`import page$${key} from '${virtualFilePrefix}/${
|
|
628
|
+
`import page$${key} from '${virtualFilePrefix}/${markoRunFilePrefix}special__${key}.marko${serverEntryQuery}';`
|
|
589
629
|
);
|
|
590
630
|
}
|
|
591
|
-
writer.writeLines(
|
|
631
|
+
writer.writeLines(``).writeBlockStart(`function findRoute(method, pathname) {`).writeBlockStart(`switch (method.toLowerCase()) {`);
|
|
592
632
|
for (const verb of httpVerbs) {
|
|
593
633
|
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
594
634
|
if (filteredRoutes.length) {
|
|
@@ -598,120 +638,105 @@ function renderRouter(routes, options = DefaultCodegenOptions) {
|
|
|
598
638
|
writer.writeBlockEnd("}");
|
|
599
639
|
}
|
|
600
640
|
}
|
|
601
|
-
writer.writeBlockEnd("}").writeBlockEnd("}");
|
|
602
|
-
writer.
|
|
603
|
-
|
|
604
|
-
if (
|
|
605
|
-
|
|
641
|
+
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
642
|
+
writer.write(`
|
|
643
|
+
export function matchRoute(method, pathname) {
|
|
644
|
+
if (!pathname) {
|
|
645
|
+
pathname = '/';
|
|
646
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
647
|
+
pathname = '/' + pathname;
|
|
606
648
|
}
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
649
|
+
return findRoute(method, pathname);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
export async function invokeRoute(route, context) {
|
|
653
|
+
try {
|
|
654
|
+
const buildInput = createInput(context);
|
|
655
|
+
if (route) {
|
|
656
|
+
context.params = route.params;
|
|
657
|
+
context.meta = route.meta;
|
|
658
|
+
try {
|
|
659
|
+
const response = await route.handler(context, buildInput);
|
|
660
|
+
if (response) return response;
|
|
661
|
+
} catch (error) {
|
|
662
|
+
if (error === RequestNotHandled) {
|
|
663
|
+
return;
|
|
664
|
+
} else if (error !== RequestNotMatched) {
|
|
665
|
+
throw error;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
`).indent = 2;
|
|
669
|
+
if (routes.special[RoutableFileTypes.NotFound]) {
|
|
670
|
+
writer.write(
|
|
671
|
+
` } else {
|
|
672
|
+
context.params = {};
|
|
673
|
+
context.meta = {};
|
|
674
|
+
}
|
|
675
|
+
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
676
|
+
return new Response(page$404.stream(buildInput()), {
|
|
677
|
+
status: 404,
|
|
678
|
+
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
`
|
|
682
|
+
);
|
|
683
|
+
} else {
|
|
684
|
+
writer.writeBlockEnd("}");
|
|
628
685
|
}
|
|
629
|
-
writer.
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
writer.writeBlockStart(
|
|
633
|
-
`if (request.headers.get('Accept')?.includes('text/html')) {`
|
|
686
|
+
writer.indent--;
|
|
687
|
+
writer.writeBlockStart(`} catch (error) {`);
|
|
688
|
+
if (routes.special[RoutableFileTypes.Error]) {
|
|
689
|
+
writer.writeBlockStart(
|
|
690
|
+
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
634
691
|
).writeBlock(
|
|
635
|
-
`return new Response(page$500.stream({
|
|
692
|
+
`return new Response(page$500.stream(buildInput({ error })), {`,
|
|
636
693
|
[
|
|
637
694
|
`status: 500,`,
|
|
638
695
|
`headers: { "content-type": "text/html;charset=UTF-8" },`
|
|
639
696
|
],
|
|
640
697
|
`});`
|
|
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
|
-
}
|
|
698
|
+
).writeBlockEnd("}");
|
|
657
699
|
}
|
|
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) {
|
|
700
|
+
writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
|
|
701
|
+
export async function router(context) {
|
|
670
702
|
try {
|
|
671
|
-
const url =
|
|
672
|
-
let { pathname } = url;
|
|
673
|
-
|
|
674
|
-
if (pathname !== '/') {
|
|
675
|
-
if (pathname.endsWith('/')) {
|
|
676
|
-
pathname = pathname.replace(/\\/+$/, '');
|
|
677
|
-
`);
|
|
703
|
+
const { url, method } = context;
|
|
704
|
+
let { pathname } = url;`);
|
|
678
705
|
switch (options.trailingSlashes) {
|
|
679
706
|
case "RedirectWithout":
|
|
680
707
|
writer.write(`
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
708
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
709
|
+
url.pathname = pathname.slice(0, -1);
|
|
710
|
+
return Response.redirect(url);
|
|
711
|
+
}`);
|
|
684
712
|
break;
|
|
685
713
|
case "RedirectWith":
|
|
686
714
|
writer.write(`
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
`);
|
|
715
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
716
|
+
url.pathname = pathname + '/';
|
|
717
|
+
return Response.redirect(url);
|
|
718
|
+
}`);
|
|
691
719
|
break;
|
|
692
720
|
case "RewriteWithout":
|
|
693
721
|
writer.write(`
|
|
694
|
-
|
|
695
|
-
|
|
722
|
+
if (pathname !== '/' && pathname.endsWith('/')) {
|
|
723
|
+
url.pathname = pathname = pathname.slice(0, -1);
|
|
724
|
+
}`);
|
|
696
725
|
break;
|
|
697
726
|
case "RewriteWith":
|
|
698
727
|
writer.write(`
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
`);
|
|
728
|
+
if (pathname !== '/' && !pathname.endsWith('/')) {
|
|
729
|
+
url.pathname = pathname = pathname + '/';
|
|
730
|
+
}`);
|
|
702
731
|
break;
|
|
703
732
|
}
|
|
704
|
-
writer.write(`
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
statusText: \`Not Found (No route matched \${pathname})\`,
|
|
710
|
-
status: 404
|
|
711
|
-
});
|
|
712
|
-
} catch (err) {
|
|
733
|
+
writer.write(`
|
|
734
|
+
|
|
735
|
+
const route = matchRoute(method, pathname);
|
|
736
|
+
return await invokeRoute(route, context);
|
|
737
|
+
} catch (error) {
|
|
713
738
|
const message = import.meta.env.DEV
|
|
714
|
-
? \`Internal Server Error (\${
|
|
739
|
+
? \`Internal Server Error (\${error.message})\`
|
|
715
740
|
: "Internal Server Error";
|
|
716
741
|
|
|
717
742
|
return new Response(
|
|
@@ -719,7 +744,7 @@ export async function router(request) {
|
|
|
719
744
|
error: {
|
|
720
745
|
message,
|
|
721
746
|
stack: import.meta.env.DEV
|
|
722
|
-
? \`This will only be seen in development mode\\n\\n\${
|
|
747
|
+
? \`This will only be seen in development mode\\n\\n\${error.stack}\`
|
|
723
748
|
: ""
|
|
724
749
|
}
|
|
725
750
|
}),
|
|
@@ -732,101 +757,259 @@ export async function router(request) {
|
|
|
732
757
|
}`);
|
|
733
758
|
return writer.end();
|
|
734
759
|
}
|
|
735
|
-
function writeRouterVerb(writer, trie, verb, level = 0,
|
|
736
|
-
const {
|
|
737
|
-
|
|
738
|
-
if (level
|
|
739
|
-
|
|
740
|
-
if (
|
|
741
|
-
writer.writeLines(
|
|
742
|
-
`if (pathname === '/') return ${renderMatch(verb, value)}; // ${value.path}`
|
|
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) {
|
|
760
|
+
function writeRouterVerb(writer, trie, verb, level = 0, offset = 1) {
|
|
761
|
+
const { route, dynamic, catchAll } = trie;
|
|
762
|
+
let closeCount = 0;
|
|
763
|
+
if (level === 0) {
|
|
764
|
+
writer.writeLines(`const len = pathname.length;`);
|
|
765
|
+
if (route) {
|
|
762
766
|
writer.writeLines(
|
|
763
|
-
`if (len ===
|
|
767
|
+
`if (len === 1) return ${renderMatch(verb, route)}; // ${route.path}`
|
|
764
768
|
);
|
|
769
|
+
} else if (trie.static || dynamic) {
|
|
770
|
+
writer.writeBlockStart(`if (len > 1) {`);
|
|
771
|
+
closeCount++;
|
|
765
772
|
}
|
|
766
773
|
}
|
|
767
|
-
if (
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
774
|
+
if (trie.static || dynamic) {
|
|
775
|
+
const next = level + 1;
|
|
776
|
+
const index = `i${next}`;
|
|
777
|
+
let terminal;
|
|
778
|
+
let children;
|
|
779
|
+
writer.writeLines(`const ${index} = pathname.indexOf('/', ${offset}) + 1;`);
|
|
780
|
+
if (trie.static) {
|
|
781
|
+
for (const child of trie.static.values()) {
|
|
782
|
+
if (child.route) {
|
|
783
|
+
(terminal ?? (terminal = [])).push(child);
|
|
775
784
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
785
|
+
if (child.static || child.dynamic || child.catchAll) {
|
|
786
|
+
(children ?? (children = [])).push(child);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
791
|
+
closeCount++;
|
|
792
|
+
writer.writeBlockStart(`if (!${index} || ${index} === len) {`);
|
|
793
|
+
let value = `pathname.slice(${offset}, ${index} ? -1 : len)`;
|
|
794
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
795
|
+
const segment = `s${next}`;
|
|
796
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
797
|
+
value = segment;
|
|
798
|
+
}
|
|
799
|
+
if (terminal) {
|
|
800
|
+
const useSwitch = terminal.length > 1;
|
|
801
|
+
if (useSwitch) {
|
|
802
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
803
|
+
}
|
|
804
|
+
for (const { key, route: route2 } of terminal) {
|
|
805
|
+
if (useSwitch) {
|
|
806
|
+
writer.write(`case '${key}': `, true);
|
|
807
|
+
} else {
|
|
808
|
+
writer.write(`if (${value}.toLowerCase() === '${key}') `, true);
|
|
809
|
+
}
|
|
810
|
+
writer.write(
|
|
811
|
+
`return ${renderMatch(verb, route2)}; // ${route2.path}
|
|
812
|
+
`
|
|
813
|
+
);
|
|
780
814
|
}
|
|
815
|
+
if (useSwitch) {
|
|
816
|
+
writer.writeBlockEnd("}");
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
if (dynamic == null ? void 0 : dynamic.route) {
|
|
820
|
+
writer.writeLines(
|
|
821
|
+
`if (${value}) return ${renderMatch(verb, dynamic.route)}; // ${dynamic.route.path}`
|
|
822
|
+
);
|
|
781
823
|
}
|
|
782
824
|
}
|
|
783
|
-
if (dynamic) {
|
|
784
|
-
|
|
825
|
+
if (children || (dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
826
|
+
if (terminal || (dynamic == null ? void 0 : dynamic.route)) {
|
|
827
|
+
writer.writeBlockEnd("} else {").indent++;
|
|
828
|
+
} else {
|
|
829
|
+
writer.writeBlockStart(`if (${index} && ${index} !== len) {`);
|
|
830
|
+
closeCount++;
|
|
831
|
+
}
|
|
832
|
+
let value = `pathname.slice(${offset}, ${index} - 1)`;
|
|
833
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic)) {
|
|
834
|
+
const segment = `s${next}`;
|
|
835
|
+
writer.writeLines(`const ${segment} = ${value};`);
|
|
836
|
+
value = segment;
|
|
837
|
+
}
|
|
838
|
+
if (children) {
|
|
839
|
+
const useSwitch = children.length > 1;
|
|
840
|
+
if (useSwitch) {
|
|
841
|
+
writer.writeBlockStart(`switch (${value}.toLowerCase()) {`);
|
|
842
|
+
}
|
|
843
|
+
for (const child of children) {
|
|
844
|
+
if (useSwitch) {
|
|
845
|
+
writer.writeBlockStart(`case '${child.key}': {`);
|
|
846
|
+
} else {
|
|
847
|
+
writer.writeBlockStart(
|
|
848
|
+
`if (${value}.toLowerCase() === '${child.key}') {`
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
const nextOffset = typeof offset === "string" ? index : offset + child.key.length + 1;
|
|
852
|
+
writeRouterVerb(writer, child, verb, next, nextOffset);
|
|
853
|
+
writer.writeBlockEnd("}");
|
|
854
|
+
}
|
|
855
|
+
if (useSwitch) {
|
|
856
|
+
writer.writeBlockEnd("}");
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if ((dynamic == null ? void 0 : dynamic.static) || (dynamic == null ? void 0 : dynamic.dynamic) || (dynamic == null ? void 0 : dynamic.catchAll)) {
|
|
860
|
+
writer.writeBlockStart(`if (${value}) {`);
|
|
861
|
+
writeRouterVerb(writer, dynamic, verb, next, index);
|
|
862
|
+
writer.writeBlockEnd(`}`);
|
|
863
|
+
}
|
|
785
864
|
}
|
|
786
865
|
}
|
|
866
|
+
while (closeCount--) {
|
|
867
|
+
writer.writeBlockEnd("}");
|
|
868
|
+
}
|
|
787
869
|
if (catchAll) {
|
|
788
870
|
writer.writeLines(
|
|
789
|
-
`return ${renderMatch(verb, catchAll,
|
|
871
|
+
`return ${renderMatch(verb, catchAll, String(offset))}; // ${catchAll.path}`
|
|
790
872
|
);
|
|
791
|
-
if (level > 0) {
|
|
792
|
-
writer.indent--;
|
|
793
|
-
}
|
|
794
873
|
} else if (level === 0) {
|
|
795
|
-
writer.writeLines("return;");
|
|
796
|
-
} else if (useSwitch) {
|
|
797
|
-
writer.writeLines("break;").indent--;
|
|
798
|
-
} else {
|
|
799
|
-
writer.writeBlockEnd("}");
|
|
874
|
+
writer.writeLines("return null;");
|
|
800
875
|
}
|
|
801
876
|
}
|
|
877
|
+
function wrapPropertyName(name) {
|
|
878
|
+
return /^[^A-Za-z_$]|[^A-Za-z0-9$_]/.test(name) ? `'${name}'` : name;
|
|
879
|
+
}
|
|
802
880
|
function renderParamsInfo(params, pathIndex) {
|
|
881
|
+
if (!params.length) {
|
|
882
|
+
return "{}";
|
|
883
|
+
}
|
|
803
884
|
let result = "";
|
|
804
885
|
let catchAll = "";
|
|
805
|
-
let
|
|
886
|
+
let sep = "{";
|
|
806
887
|
for (const { name, index } of params) {
|
|
807
888
|
if (index >= 0) {
|
|
808
|
-
result +=
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
} else if (pathIndex && pathIndex >= 0) {
|
|
889
|
+
result += `${sep} ${wrapPropertyName(name)}: s${index + 1}`;
|
|
890
|
+
sep || (sep = ",");
|
|
891
|
+
} else if (pathIndex) {
|
|
812
892
|
catchAll = name;
|
|
813
893
|
}
|
|
814
894
|
}
|
|
815
895
|
if (catchAll) {
|
|
816
|
-
result +=
|
|
817
|
-
|
|
896
|
+
result += `${sep} ${wrapPropertyName(
|
|
897
|
+
catchAll
|
|
898
|
+
)}: pathname.slice(${pathIndex})`;
|
|
818
899
|
}
|
|
819
900
|
return result ? result + " }" : "{}";
|
|
820
901
|
}
|
|
821
|
-
function
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
tuple[1] = renderParamsInfo(params, pathIndex);
|
|
902
|
+
function renderParamsInfoType(params) {
|
|
903
|
+
if (!params.length) {
|
|
904
|
+
return "{}";
|
|
825
905
|
}
|
|
826
|
-
|
|
827
|
-
|
|
906
|
+
let result = "{";
|
|
907
|
+
for (const { name } of params) {
|
|
908
|
+
result += ` ${wrapPropertyName(name)}: string;`;
|
|
909
|
+
}
|
|
910
|
+
return result + " }";
|
|
911
|
+
}
|
|
912
|
+
function renderMatch(verb, route, pathIndex) {
|
|
913
|
+
var _a;
|
|
914
|
+
const handler = `${verb}$${route.index}`;
|
|
915
|
+
const params = ((_a = route.params) == null ? void 0 : _a.length) ? renderParamsInfo(route.params, pathIndex) : "{}";
|
|
916
|
+
const meta = route.meta ? `meta$${route.index}` : "{}";
|
|
917
|
+
return `{ handler: ${handler}, params: ${params}, meta: ${meta} }`;
|
|
918
|
+
}
|
|
919
|
+
function renderMiddleware(middleware) {
|
|
920
|
+
const writer = createStringWriter();
|
|
921
|
+
writer.writeLines(
|
|
922
|
+
`// ${virtualFilePrefix}/${markoRunFilePrefix}middleware.js`
|
|
923
|
+
);
|
|
924
|
+
const imports = writer.branch("imports");
|
|
925
|
+
imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
|
|
926
|
+
writer.writeLines("");
|
|
927
|
+
for (const { id, importPath } of middleware) {
|
|
928
|
+
const importName = `mware${id}`;
|
|
929
|
+
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
930
|
+
writer.writeLines(`export const mware$${id} = normalize(${importName});`);
|
|
931
|
+
}
|
|
932
|
+
imports.join();
|
|
933
|
+
return writer.end();
|
|
934
|
+
}
|
|
935
|
+
function stripTsExtension(path3) {
|
|
936
|
+
const index = path3.lastIndexOf(".");
|
|
937
|
+
if (index !== -1) {
|
|
938
|
+
const ext = path3.slice(index + 1);
|
|
939
|
+
if (ext.toLowerCase() === "ts") {
|
|
940
|
+
return path3.slice(0, index);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
return path3;
|
|
944
|
+
}
|
|
945
|
+
function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
946
|
+
const writer = createStringWriter();
|
|
947
|
+
writer.writeLines(
|
|
948
|
+
`/*
|
|
949
|
+
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
950
|
+
Do NOT manually edit this file or your changes will be lost.
|
|
951
|
+
*/
|
|
952
|
+
`,
|
|
953
|
+
`import type { HandlerLike, Route } from "@marko/run";
|
|
954
|
+
`
|
|
955
|
+
);
|
|
956
|
+
const routesWriter = writer.branch("types");
|
|
957
|
+
const middlewareRouteTypes = /* @__PURE__ */ new Map();
|
|
958
|
+
for (const route of routes.list) {
|
|
959
|
+
const { meta, handler, params, middleware } = route;
|
|
960
|
+
const routeType = `Route${route.index}`;
|
|
961
|
+
const pathType = `\`${route.path.replace(
|
|
962
|
+
/\/\$(\$?)([^\/]*)/,
|
|
963
|
+
(_, catchAll, name) => catchAll ? `/:${name || "rest"}*` : `/:${name}`
|
|
964
|
+
)}\``;
|
|
965
|
+
const paramsType = params ? renderParamsInfoType(params) : "{}";
|
|
966
|
+
let metaType = "undefined";
|
|
967
|
+
if (meta) {
|
|
968
|
+
metaType = `typeof import('${pathPrefix}/${stripTsExtension(
|
|
969
|
+
meta.relativePath
|
|
970
|
+
)}')`;
|
|
971
|
+
if (/\.(ts|js|mjs)$/.test(meta.relativePath)) {
|
|
972
|
+
metaType += `['default']`;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
if (handler) {
|
|
976
|
+
writeRouteTypeModule(writer, pathPrefix, handler.relativePath, routeType);
|
|
977
|
+
}
|
|
978
|
+
if (middleware) {
|
|
979
|
+
let i = 0;
|
|
980
|
+
for (const mw of middleware) {
|
|
981
|
+
const existing = middlewareRouteTypes.get(mw);
|
|
982
|
+
if (!existing) {
|
|
983
|
+
middlewareRouteTypes.set(mw, {
|
|
984
|
+
routeTypes: [routeType],
|
|
985
|
+
middleware: middleware.slice(0, i)
|
|
986
|
+
});
|
|
987
|
+
} else {
|
|
988
|
+
existing.routeTypes.push(routeType);
|
|
989
|
+
}
|
|
990
|
+
i++;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
routesWriter.writeLines(
|
|
994
|
+
`interface ${routeType} extends Route<${paramsType}, ${metaType}, ${pathType}> {}`
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
for (const [file, { routeTypes }] of middlewareRouteTypes) {
|
|
998
|
+
const routeType = routeTypes.length > 1 ? routeTypes.join(" | ") : routeTypes[0];
|
|
999
|
+
writeRouteTypeModule(writer, pathPrefix, file.relativePath, routeType);
|
|
1000
|
+
}
|
|
1001
|
+
return writer.end();
|
|
1002
|
+
}
|
|
1003
|
+
function writeRouteTypeModule(writer, pathPrefix, path3, routeType) {
|
|
1004
|
+
writer.writeLines(`
|
|
1005
|
+
declare module '${pathPrefix}/${stripTsExtension(path3)}' {
|
|
1006
|
+
namespace Marko {
|
|
1007
|
+
type CurrentRoute = ${routeType};
|
|
1008
|
+
type Handler<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']> = HandlerLike<CurrentRoute>;
|
|
1009
|
+
function route(handler: Handler): typeof handler;
|
|
1010
|
+
function route<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']>(handler: Handler): typeof handler;
|
|
828
1011
|
}
|
|
829
|
-
|
|
1012
|
+
}`);
|
|
830
1013
|
}
|
|
831
1014
|
|
|
832
1015
|
// src/vite/utils/ast.ts
|
|
@@ -873,7 +1056,7 @@ function getExportIdentifiers(astProgramNode) {
|
|
|
873
1056
|
import Table from "cli-table3";
|
|
874
1057
|
import kleur from "kleur";
|
|
875
1058
|
import { gzipSizeSync } from "gzip-size";
|
|
876
|
-
import
|
|
1059
|
+
import format from "human-format";
|
|
877
1060
|
var HttpVerbColors = {
|
|
878
1061
|
get: kleur.green,
|
|
879
1062
|
post: kleur.magenta,
|
|
@@ -900,7 +1083,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
900
1083
|
headings.push("Meta");
|
|
901
1084
|
colAligns.push("center");
|
|
902
1085
|
}
|
|
903
|
-
headings.push("Size");
|
|
1086
|
+
headings.push("Size/GZip");
|
|
904
1087
|
colAligns.push("right");
|
|
905
1088
|
const table = new Table({
|
|
906
1089
|
head: headings.map((title) => kleur.bold(kleur.white(title.toUpperCase()))),
|
|
@@ -931,7 +1114,7 @@ function logRoutesTable(routes, bundle) {
|
|
|
931
1114
|
row.push(entryType.join(" -> "));
|
|
932
1115
|
hasMiddleware && row.push(route.middleware.length || "");
|
|
933
1116
|
hasMeta && row.push(route.meta ? "\u2713" : "");
|
|
934
|
-
row.push(size ||
|
|
1117
|
+
row.push(size || "");
|
|
935
1118
|
table.push(row);
|
|
936
1119
|
}
|
|
937
1120
|
}
|
|
@@ -947,36 +1130,52 @@ function logRoutesTable(routes, bundle) {
|
|
|
947
1130
|
function computeRouteSize(route, bundle) {
|
|
948
1131
|
if (route.page) {
|
|
949
1132
|
for (const chunk of Object.values(bundle)) {
|
|
950
|
-
if (chunk.type === "chunk"
|
|
951
|
-
|
|
1133
|
+
if (chunk.type === "chunk") {
|
|
1134
|
+
for (const key of Object.keys(chunk.modules)) {
|
|
1135
|
+
if (key.startsWith(route.page.filePath)) {
|
|
1136
|
+
return computeChunkSize(chunk, bundle);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
952
1139
|
}
|
|
953
1140
|
}
|
|
954
1141
|
}
|
|
955
|
-
return 0;
|
|
1142
|
+
return [0, 0];
|
|
1143
|
+
}
|
|
1144
|
+
function byteSize(str) {
|
|
1145
|
+
return new Blob([str]).size;
|
|
956
1146
|
}
|
|
957
1147
|
function computeChunkSize(chunk, bundle, seen = /* @__PURE__ */ new Set()) {
|
|
958
1148
|
if (chunk.type === "asset") {
|
|
959
|
-
return
|
|
1149
|
+
return [
|
|
1150
|
+
byteSize(chunk.source),
|
|
1151
|
+
gzipSizeSync(chunk.source)
|
|
1152
|
+
];
|
|
960
1153
|
}
|
|
961
|
-
|
|
1154
|
+
const size = [byteSize(chunk.code), gzipSizeSync(chunk.code)];
|
|
962
1155
|
for (const id of chunk.imports) {
|
|
963
1156
|
if (!seen.has(id)) {
|
|
964
|
-
|
|
1157
|
+
const [bytes, compBytes] = computeChunkSize(bundle[id], bundle, seen);
|
|
1158
|
+
size[0] += bytes;
|
|
1159
|
+
size[1] += compBytes;
|
|
965
1160
|
seen.add(id);
|
|
966
1161
|
}
|
|
967
1162
|
}
|
|
968
1163
|
return size;
|
|
969
1164
|
}
|
|
970
|
-
function prettySize(
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}).
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
if (
|
|
978
|
-
|
|
979
|
-
|
|
1165
|
+
function prettySize([bytes, compBytes]) {
|
|
1166
|
+
if (bytes <= 0) {
|
|
1167
|
+
return kleur.gray("0.0 kB");
|
|
1168
|
+
}
|
|
1169
|
+
const [size, prefix] = format(bytes, { decimals: 1 }).split(/\s+/);
|
|
1170
|
+
const compSize = format(compBytes, { decimals: 1, prefix, unit: "B" });
|
|
1171
|
+
let str = kleur.white(size) + kleur.gray("/");
|
|
1172
|
+
if (compBytes < 20 * 1e3)
|
|
1173
|
+
str += kleur.green(compSize);
|
|
1174
|
+
else if (compBytes < 50 * 1e3)
|
|
1175
|
+
str += kleur.yellow(compSize);
|
|
1176
|
+
else
|
|
1177
|
+
kleur.bold(kleur.red(compSize));
|
|
1178
|
+
return str;
|
|
980
1179
|
}
|
|
981
1180
|
function prettyPath(path3) {
|
|
982
1181
|
return path3.replace(/\/\$\$(.*)$/, (_, p) => "/" + kleur.bold(kleur.dim(`*${p}`))).replace(/\/\$([^/]+)/g, (_, p) => "/" + kleur.bold(kleur.dim(`:${p}`)));
|
|
@@ -984,17 +1183,18 @@ function prettyPath(path3) {
|
|
|
984
1183
|
|
|
985
1184
|
// src/vite/utils/config.ts
|
|
986
1185
|
var KEY = "__MARKO_SERVE_OPTIONS__";
|
|
987
|
-
function
|
|
1186
|
+
function getMarkoRunOptions(viteConfig) {
|
|
988
1187
|
return viteConfig[KEY];
|
|
989
1188
|
}
|
|
990
|
-
function
|
|
1189
|
+
function setMarkoRunOptions(viteConfig, options) {
|
|
991
1190
|
viteConfig[KEY] = options;
|
|
992
1191
|
return viteConfig;
|
|
993
1192
|
}
|
|
994
1193
|
|
|
995
1194
|
// src/vite/plugin.ts
|
|
1195
|
+
import { fileURLToPath } from "url";
|
|
1196
|
+
var __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
996
1197
|
var markoExt = ".marko";
|
|
997
|
-
var markoServeFilePrefix2 = "__marko-serve__";
|
|
998
1198
|
function isMarkoFile(id) {
|
|
999
1199
|
return id.endsWith(markoExt);
|
|
1000
1200
|
}
|
|
@@ -1003,8 +1203,10 @@ function markoServe(opts = {}) {
|
|
|
1003
1203
|
let store;
|
|
1004
1204
|
let root;
|
|
1005
1205
|
let resolvedRoutesDir;
|
|
1206
|
+
let typesDir;
|
|
1006
1207
|
let isBuild = false;
|
|
1007
1208
|
let isSSRBuild = false;
|
|
1209
|
+
let tsConfigExists;
|
|
1008
1210
|
let ssrEntryFiles;
|
|
1009
1211
|
let devEntryFile;
|
|
1010
1212
|
let devServer;
|
|
@@ -1013,6 +1215,7 @@ function markoServe(opts = {}) {
|
|
|
1013
1215
|
let routeDataFilename = "routes.json";
|
|
1014
1216
|
let extractVerbs;
|
|
1015
1217
|
let resolvedConfig;
|
|
1218
|
+
let typesFile;
|
|
1016
1219
|
let isStale = true;
|
|
1017
1220
|
let isRendered = false;
|
|
1018
1221
|
const virtualFiles = /* @__PURE__ */ new Map();
|
|
@@ -1020,6 +1223,22 @@ function markoServe(opts = {}) {
|
|
|
1020
1223
|
routesBuild: 0,
|
|
1021
1224
|
routesRender: 0
|
|
1022
1225
|
};
|
|
1226
|
+
async function writeTypesFile() {
|
|
1227
|
+
if (tsConfigExists ?? (tsConfigExists = await globFileExists(
|
|
1228
|
+
root,
|
|
1229
|
+
"{.tsconfig*,tsconfig*.json}"
|
|
1230
|
+
))) {
|
|
1231
|
+
const filepath = path2.join(typesDir, "routes.d.ts");
|
|
1232
|
+
const data = renderRouteTypeInfo(
|
|
1233
|
+
routes,
|
|
1234
|
+
path2.relative(typesDir, routesDir)
|
|
1235
|
+
);
|
|
1236
|
+
if (data !== typesFile || !fs2.existsSync(filepath)) {
|
|
1237
|
+
await ensureDir(typesDir);
|
|
1238
|
+
await fs2.promises.writeFile(filepath, typesFile = data);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1023
1242
|
async function setVirtualFiles(render = false) {
|
|
1024
1243
|
for (const route of routes.list) {
|
|
1025
1244
|
if (render && route.handler) {
|
|
@@ -1032,31 +1251,37 @@ function markoServe(opts = {}) {
|
|
|
1032
1251
|
}
|
|
1033
1252
|
if (route.page) {
|
|
1034
1253
|
virtualFiles.set(
|
|
1035
|
-
path2.join(root, `${
|
|
1254
|
+
path2.join(root, `${markoRunFilePrefix}route__${route.key}.marko`),
|
|
1036
1255
|
render ? renderRouteTemplate(route) : ""
|
|
1037
1256
|
);
|
|
1038
1257
|
}
|
|
1039
1258
|
virtualFiles.set(
|
|
1040
|
-
path2.join(root, `${
|
|
1259
|
+
path2.join(root, `${markoRunFilePrefix}route__${route.key}.js`),
|
|
1041
1260
|
render ? renderRouteEntry(route) : ""
|
|
1042
1261
|
);
|
|
1043
1262
|
}
|
|
1044
1263
|
for (const route of Object.values(routes.special)) {
|
|
1045
1264
|
virtualFiles.set(
|
|
1046
|
-
path2.join(root, `${
|
|
1265
|
+
path2.join(root, `${markoRunFilePrefix}special__${route.key}.marko`),
|
|
1047
1266
|
render ? renderRouteTemplate(route) : ""
|
|
1048
1267
|
);
|
|
1049
1268
|
}
|
|
1050
1269
|
virtualFiles.set(
|
|
1051
1270
|
"@marko/run/router",
|
|
1052
|
-
render ? renderRouter(routes,
|
|
1271
|
+
render ? renderRouter(routes, {
|
|
1272
|
+
trailingSlashes: opts.trailingSlashes || "RedirectWithout"
|
|
1273
|
+
}) : ""
|
|
1274
|
+
);
|
|
1275
|
+
virtualFiles.set(
|
|
1276
|
+
path2.join(root, `${markoRunFilePrefix}middleware.js`),
|
|
1277
|
+
render ? renderMiddleware(routes.middleware) : ""
|
|
1053
1278
|
);
|
|
1054
1279
|
}
|
|
1055
1280
|
const buildVirtualFiles = single(async () => {
|
|
1056
1281
|
const startTime = performance.now();
|
|
1057
1282
|
routes = await buildRoutes(createFSWalker(resolvedRoutesDir), routesDir);
|
|
1058
1283
|
times.routesBuild = performance.now() - startTime;
|
|
1059
|
-
await setVirtualFiles(false);
|
|
1284
|
+
await Promise.all([writeTypesFile(), setVirtualFiles(false)]);
|
|
1060
1285
|
isStale = false;
|
|
1061
1286
|
isRendered = false;
|
|
1062
1287
|
});
|
|
@@ -1070,9 +1295,9 @@ function markoServe(opts = {}) {
|
|
|
1070
1295
|
{
|
|
1071
1296
|
name: "marko-run-vite:pre",
|
|
1072
1297
|
enforce: "pre",
|
|
1073
|
-
async config(
|
|
1298
|
+
async config(config2, env) {
|
|
1074
1299
|
var _a, _b, _c;
|
|
1075
|
-
const externalPluginOptions =
|
|
1300
|
+
const externalPluginOptions = getMarkoRunOptions(config2);
|
|
1076
1301
|
if (externalPluginOptions) {
|
|
1077
1302
|
opts = mergeConfig(opts, externalPluginOptions);
|
|
1078
1303
|
}
|
|
@@ -1080,13 +1305,14 @@ function markoServe(opts = {}) {
|
|
|
1080
1305
|
if (adapterOptions) {
|
|
1081
1306
|
opts = mergeConfig(opts, adapterOptions);
|
|
1082
1307
|
}
|
|
1083
|
-
root = normalizePath(
|
|
1308
|
+
root = normalizePath(config2.root || process.cwd());
|
|
1084
1309
|
store = opts.store || new FileStore(
|
|
1085
1310
|
`marko-serve-vite-${crypto.createHash("SHA1").update(root).digest("hex")}`
|
|
1086
1311
|
);
|
|
1087
1312
|
isBuild = env.command === "build";
|
|
1088
|
-
isSSRBuild = isBuild && Boolean((_b =
|
|
1313
|
+
isSSRBuild = isBuild && Boolean((_b = config2.build) == null ? void 0 : _b.ssr);
|
|
1089
1314
|
resolvedRoutesDir = path2.resolve(root, routesDir);
|
|
1315
|
+
typesDir = path2.join(root, ".marko-run");
|
|
1090
1316
|
devEntryFile = path2.join(root, "index.html");
|
|
1091
1317
|
let pluginConfig = {
|
|
1092
1318
|
logLevel: isBuild ? "warn" : void 0,
|
|
@@ -1097,18 +1323,18 @@ function markoServe(opts = {}) {
|
|
|
1097
1323
|
emptyOutDir: isSSRBuild
|
|
1098
1324
|
}
|
|
1099
1325
|
};
|
|
1100
|
-
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter,
|
|
1326
|
+
const adapterConfig = await ((_c = adapter == null ? void 0 : adapter.viteConfig) == null ? void 0 : _c.call(adapter, config2));
|
|
1101
1327
|
if (adapterConfig) {
|
|
1102
1328
|
pluginConfig = mergeConfig(pluginConfig, adapterConfig);
|
|
1103
1329
|
}
|
|
1104
|
-
return
|
|
1330
|
+
return setMarkoRunOptions(pluginConfig, opts);
|
|
1105
1331
|
},
|
|
1106
|
-
configResolved(
|
|
1107
|
-
resolvedConfig =
|
|
1332
|
+
configResolved(config2) {
|
|
1333
|
+
resolvedConfig = config2;
|
|
1108
1334
|
const {
|
|
1109
1335
|
ssr,
|
|
1110
1336
|
rollupOptions: { input }
|
|
1111
|
-
} =
|
|
1337
|
+
} = config2.build;
|
|
1112
1338
|
if (typeof ssr === "string") {
|
|
1113
1339
|
ssrEntryFiles = [ssr];
|
|
1114
1340
|
} else if (typeof input === "string") {
|
|
@@ -1139,6 +1365,7 @@ function markoServe(opts = {}) {
|
|
|
1139
1365
|
if (isStale) {
|
|
1140
1366
|
for (const id of virtualFiles.keys()) {
|
|
1141
1367
|
devServer.watcher.emit("change", id);
|
|
1368
|
+
break;
|
|
1142
1369
|
}
|
|
1143
1370
|
}
|
|
1144
1371
|
}
|
|
@@ -1168,12 +1395,18 @@ function markoServe(opts = {}) {
|
|
|
1168
1395
|
},
|
|
1169
1396
|
async resolveId(importee, importer, { ssr }) {
|
|
1170
1397
|
let resolved;
|
|
1171
|
-
if (importee.startsWith(
|
|
1398
|
+
if (importee.startsWith(virtualRuntimePrefix)) {
|
|
1399
|
+
return this.resolve(
|
|
1400
|
+
path2.resolve(__dirname, "../runtime/internal"),
|
|
1401
|
+
importer,
|
|
1402
|
+
{ skipSelf: true }
|
|
1403
|
+
);
|
|
1404
|
+
} else if (importee.startsWith(virtualFilePrefix)) {
|
|
1172
1405
|
importee = path2.resolve(
|
|
1173
1406
|
root,
|
|
1174
1407
|
importee.slice(virtualFilePrefix.length + 1)
|
|
1175
1408
|
);
|
|
1176
|
-
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${
|
|
1409
|
+
} else if (!isBuild && importer === devEntryFile && importee.startsWith(`/${markoRunFilePrefix}`)) {
|
|
1177
1410
|
importee = path2.resolve(root, "." + importee);
|
|
1178
1411
|
}
|
|
1179
1412
|
if (isStale) {
|
|
@@ -1295,20 +1528,49 @@ function single(fn) {
|
|
|
1295
1528
|
return result;
|
|
1296
1529
|
};
|
|
1297
1530
|
}
|
|
1531
|
+
async function globFileExists(root, pattern) {
|
|
1532
|
+
return new Promise((resolve, reject) => {
|
|
1533
|
+
glob(pattern, { root }, (err, matches) => {
|
|
1534
|
+
if (err) {
|
|
1535
|
+
reject(err);
|
|
1536
|
+
}
|
|
1537
|
+
resolve(matches.length > 0);
|
|
1538
|
+
});
|
|
1539
|
+
});
|
|
1540
|
+
}
|
|
1541
|
+
async function ensureDir(dir) {
|
|
1542
|
+
if (!fs2.existsSync(dir)) {
|
|
1543
|
+
await fs2.promises.mkdir(dir, { recursive: true });
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1298
1546
|
|
|
1299
1547
|
// src/vite/utils/server.ts
|
|
1300
1548
|
import net from "net";
|
|
1301
1549
|
import cp from "child_process";
|
|
1302
|
-
|
|
1550
|
+
import { parse, config } from "dotenv";
|
|
1551
|
+
import fs3 from "fs";
|
|
1552
|
+
async function parseEnv(envFile) {
|
|
1553
|
+
if (fs3.existsSync(envFile)) {
|
|
1554
|
+
const content = await fs3.promises.readFile(envFile, "utf8");
|
|
1555
|
+
return parse(content);
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
function loadEnv(envFile) {
|
|
1559
|
+
config({ path: envFile });
|
|
1560
|
+
}
|
|
1561
|
+
async function spawnServer(cmd, port = 0, env, cwd = process.cwd(), wait = 3e4) {
|
|
1303
1562
|
if (port <= 0) {
|
|
1304
1563
|
port = await getAvailablePort();
|
|
1305
1564
|
}
|
|
1565
|
+
if (typeof env === "string") {
|
|
1566
|
+
env = await parseEnv(env);
|
|
1567
|
+
}
|
|
1306
1568
|
const proc = cp.spawn(cmd, {
|
|
1307
1569
|
cwd,
|
|
1308
1570
|
shell: true,
|
|
1309
1571
|
stdio: "inherit",
|
|
1310
1572
|
windowsHide: true,
|
|
1311
|
-
env: { NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1573
|
+
env: { ...env, NODE_ENV: "development", ...process.env, PORT: `${port}` }
|
|
1312
1574
|
});
|
|
1313
1575
|
const close = () => {
|
|
1314
1576
|
proc.unref();
|
|
@@ -1355,5 +1617,7 @@ export {
|
|
|
1355
1617
|
markoServe as default,
|
|
1356
1618
|
getAvailablePort,
|
|
1357
1619
|
isPortInUse,
|
|
1620
|
+
loadEnv,
|
|
1621
|
+
parseEnv,
|
|
1358
1622
|
spawnServer
|
|
1359
1623
|
};
|