@marko/run 0.0.1-beta5 → 0.0.1-beta7
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 +32 -32
- package/dist/adapter/default-entry.mjs +8 -5
- package/dist/adapter/index.cjs +51 -48
- package/dist/adapter/index.js +51 -48
- package/dist/adapter/middleware.cjs +50 -50
- package/dist/adapter/middleware.d.ts +2 -2
- package/dist/adapter/middleware.js +48 -45
- package/dist/adapter/polyfill.d.ts +1 -0
- package/dist/runtime/index.d.ts +7 -3
- package/dist/runtime/internal.cjs +16 -13
- package/dist/runtime/internal.d.ts +2 -2
- package/dist/runtime/internal.js +14 -11
- package/dist/runtime/router.cjs +9 -9
- package/dist/runtime/router.d.ts +3 -4
- package/dist/runtime/router.js +6 -6
- package/dist/runtime/types.d.ts +11 -9
- package/dist/vite/codegen/index.d.ts +1 -1
- package/dist/vite/index.cjs +82 -57
- package/dist/vite/index.js +82 -57
- package/package.json +2 -2
package/dist/vite/index.cjs
CHANGED
|
@@ -160,7 +160,14 @@ async function buildRoutes(walk, basePath) {
|
|
|
160
160
|
if (handler || page) {
|
|
161
161
|
const key = path3.replace(/(\$\$?)[^\/]*/g, "$1").replace(/^\/+/, "").replace(/[^a-z0-9_$\/]+/gi, "").replace(/\//g, "__") || "index";
|
|
162
162
|
if (routes.has(key)) {
|
|
163
|
-
|
|
163
|
+
const existing = routes.get(key);
|
|
164
|
+
const existingFiles = [existing.handler, existing.page].filter(Boolean).map((f) => f.filePath);
|
|
165
|
+
const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
|
|
166
|
+
throw new Error(`Duplicate routes for path ${path3} were defined. A route established by:
|
|
167
|
+
${existingFiles}
|
|
168
|
+
collides with
|
|
169
|
+
${currentFiles.join(" and ")}
|
|
170
|
+
`);
|
|
164
171
|
} else {
|
|
165
172
|
const index = nextRouteIndex++;
|
|
166
173
|
routes.set(key, {
|
|
@@ -208,14 +215,16 @@ async function buildRoutes(walk, basePath) {
|
|
|
208
215
|
const prevChildren = children;
|
|
209
216
|
const prevCurrent = current;
|
|
210
217
|
const prevIsRoot = isRoot;
|
|
211
|
-
if (name.charCodeAt(0) === 95
|
|
218
|
+
if (name.charCodeAt(0) === 95) {
|
|
212
219
|
} else {
|
|
213
220
|
if (name.charCodeAt(0) === 36) {
|
|
214
221
|
if (name.charCodeAt(1) === 36) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
222
|
+
if (name.length > 2) {
|
|
223
|
+
paramStack.push({
|
|
224
|
+
name: name.slice(2),
|
|
225
|
+
index: -1
|
|
226
|
+
});
|
|
227
|
+
}
|
|
219
228
|
} else if (name.length > 1) {
|
|
220
229
|
paramStack.push({
|
|
221
230
|
name: name.slice(1),
|
|
@@ -534,7 +543,7 @@ function renderRouteEntry(route) {
|
|
|
534
543
|
);
|
|
535
544
|
}
|
|
536
545
|
if (middleware.length) {
|
|
537
|
-
const names = middleware.map((m) => `mware
|
|
546
|
+
const names = middleware.map((m) => `mware${m.id}`);
|
|
538
547
|
imports.writeLines(
|
|
539
548
|
`import { ${names.join(
|
|
540
549
|
", "
|
|
@@ -545,9 +554,9 @@ function renderRouteEntry(route) {
|
|
|
545
554
|
writer.writeLines("");
|
|
546
555
|
const names = [];
|
|
547
556
|
for (const verb of handler.verbs) {
|
|
548
|
-
const
|
|
549
|
-
names.push(
|
|
550
|
-
writer.writeLines(`const
|
|
557
|
+
const importName = verb.toUpperCase();
|
|
558
|
+
names.push(importName);
|
|
559
|
+
writer.writeLines(`const ${verb}Handler = normalize(${importName});`);
|
|
551
560
|
}
|
|
552
561
|
imports.writeLines(
|
|
553
562
|
`import { ${names.join(", ")} } from './${handler.importPath}';`
|
|
@@ -560,7 +569,7 @@ function renderRouteEntry(route) {
|
|
|
560
569
|
}
|
|
561
570
|
if (meta) {
|
|
562
571
|
imports.writeLines(
|
|
563
|
-
`export { default as meta
|
|
572
|
+
`export { default as meta${index} } from './${meta.importPath}';`
|
|
564
573
|
);
|
|
565
574
|
}
|
|
566
575
|
for (const verb of verbs) {
|
|
@@ -591,14 +600,19 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
591
600
|
let nextName;
|
|
592
601
|
let currentName;
|
|
593
602
|
let hasBody = false;
|
|
594
|
-
writer.writeLines("")
|
|
595
|
-
|
|
596
|
-
|
|
603
|
+
writer.writeLines("");
|
|
604
|
+
if (page) {
|
|
605
|
+
writer.writeBlockStart(
|
|
606
|
+
`export async function ${verb}${index}(context, buildInput) {`
|
|
607
|
+
);
|
|
608
|
+
} else {
|
|
609
|
+
writer.writeBlockStart(`export async function ${verb}${index}(context) {`);
|
|
610
|
+
}
|
|
597
611
|
const continuations = writer.branch("cont");
|
|
598
612
|
if (page && verb === "get") {
|
|
599
613
|
currentName = "__page";
|
|
600
614
|
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
601
|
-
const name =
|
|
615
|
+
const name = `${verb}Handler`;
|
|
602
616
|
writePageResponse(continuations, currentName);
|
|
603
617
|
if (len) {
|
|
604
618
|
nextName = currentName;
|
|
@@ -616,7 +630,7 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
616
630
|
hasBody = true;
|
|
617
631
|
}
|
|
618
632
|
} else if (handler) {
|
|
619
|
-
const name =
|
|
633
|
+
const name = `${verb}Handler`;
|
|
620
634
|
currentName = `__${name}`;
|
|
621
635
|
nextName = "noContent";
|
|
622
636
|
if (len) {
|
|
@@ -632,7 +646,7 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
632
646
|
let i = len;
|
|
633
647
|
while (i--) {
|
|
634
648
|
const { id } = middleware[i];
|
|
635
|
-
const name = `mware
|
|
649
|
+
const name = `mware${id}`;
|
|
636
650
|
nextName = currentName;
|
|
637
651
|
currentName = i ? `__${name}` : "";
|
|
638
652
|
writeMiddleware(continuations, name, nextName, currentName);
|
|
@@ -648,12 +662,12 @@ function renderRouter(routes, options = {
|
|
|
648
662
|
writer.writeLines(`// @marko/run/router`);
|
|
649
663
|
const imports = writer.branch("imports");
|
|
650
664
|
imports.writeLines(
|
|
651
|
-
`import {
|
|
665
|
+
`import { NotHandled, NotMatched, createInput } from 'virtual:marko-run/internal';`
|
|
652
666
|
);
|
|
653
667
|
for (const route of routes.list) {
|
|
654
668
|
const verbs = getVerbs(route);
|
|
655
|
-
const names = verbs.map((verb) => `${verb}
|
|
656
|
-
route.meta && names.push(`meta
|
|
669
|
+
const names = verbs.map((verb) => `${verb}${route.index}`);
|
|
670
|
+
route.meta && names.push(`meta${route.index}`);
|
|
657
671
|
imports.writeLines(
|
|
658
672
|
`import { ${names.join(
|
|
659
673
|
", "
|
|
@@ -662,10 +676,16 @@ function renderRouter(routes, options = {
|
|
|
662
676
|
}
|
|
663
677
|
for (const { key } of Object.values(routes.special)) {
|
|
664
678
|
imports.writeLines(
|
|
665
|
-
`import page
|
|
679
|
+
`import page${key} from '${virtualFilePrefix}/${markoRunFilePrefix}special__${key}.marko${serverEntryQuery}';`
|
|
666
680
|
);
|
|
667
681
|
}
|
|
668
|
-
writer.writeLines(``).writeBlockStart(`function
|
|
682
|
+
writer.writeLines(``).writeBlockStart(`export function match(method, pathname) {`).writeLines(
|
|
683
|
+
`if (!pathname) {
|
|
684
|
+
pathname = '/';
|
|
685
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
686
|
+
pathname = '/' + pathname;
|
|
687
|
+
}`
|
|
688
|
+
).writeBlockStart(`switch (method.toLowerCase()) {`);
|
|
669
689
|
for (const verb of httpVerbs) {
|
|
670
690
|
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
671
691
|
if (filteredRoutes.length) {
|
|
@@ -677,16 +697,12 @@ function renderRouter(routes, options = {
|
|
|
677
697
|
}
|
|
678
698
|
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
679
699
|
writer.write(`
|
|
680
|
-
export function
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
}
|
|
686
|
-
return findRoute(method, pathname);
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
export async function invokeRoute(route, context) {
|
|
700
|
+
export async function invoke(route, request, platform, url = new URL(request.url)) {
|
|
701
|
+
const context = {
|
|
702
|
+
url,
|
|
703
|
+
request,
|
|
704
|
+
platform
|
|
705
|
+
};
|
|
690
706
|
try {
|
|
691
707
|
const buildInput = createInput(context);
|
|
692
708
|
if (route) {
|
|
@@ -696,9 +712,9 @@ export async function invokeRoute(route, context) {
|
|
|
696
712
|
const response = await route.handler(context, buildInput);
|
|
697
713
|
if (response) return response;
|
|
698
714
|
} catch (error) {
|
|
699
|
-
if (error ===
|
|
715
|
+
if (error === NotHandled) {
|
|
700
716
|
return;
|
|
701
|
-
} else if (error !==
|
|
717
|
+
} else if (error !== NotMatched) {
|
|
702
718
|
throw error;
|
|
703
719
|
}
|
|
704
720
|
}
|
|
@@ -710,7 +726,7 @@ export async function invokeRoute(route, context) {
|
|
|
710
726
|
context.meta = {};
|
|
711
727
|
}
|
|
712
728
|
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
713
|
-
return new Response(
|
|
729
|
+
return new Response(page404.stream(buildInput()), {
|
|
714
730
|
status: 404,
|
|
715
731
|
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
716
732
|
});
|
|
@@ -726,7 +742,7 @@ export async function invokeRoute(route, context) {
|
|
|
726
742
|
writer.writeBlockStart(
|
|
727
743
|
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
728
744
|
).writeBlock(
|
|
729
|
-
`return new Response(
|
|
745
|
+
`return new Response(page500.stream(buildInput({ error })), {`,
|
|
730
746
|
[
|
|
731
747
|
`status: 500,`,
|
|
732
748
|
`headers: { "content-type": "text/html;charset=UTF-8" },`
|
|
@@ -735,9 +751,9 @@ export async function invokeRoute(route, context) {
|
|
|
735
751
|
).writeBlockEnd("}");
|
|
736
752
|
}
|
|
737
753
|
writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
|
|
738
|
-
export async function
|
|
754
|
+
export async function fetch(request, platform) {
|
|
739
755
|
try {
|
|
740
|
-
const
|
|
756
|
+
const url = new URL(request.url);
|
|
741
757
|
let { pathname } = url;`);
|
|
742
758
|
switch (options.trailingSlashes) {
|
|
743
759
|
case "RedirectWithout":
|
|
@@ -769,8 +785,8 @@ export async function router(context) {
|
|
|
769
785
|
}
|
|
770
786
|
writer.write(`
|
|
771
787
|
|
|
772
|
-
const route =
|
|
773
|
-
return await
|
|
788
|
+
const route = match(request.method, pathname);
|
|
789
|
+
return await invoke(route, request, platform, url);
|
|
774
790
|
} catch (error) {
|
|
775
791
|
const message = import.meta.env.DEV
|
|
776
792
|
? \`Internal Server Error (\${error.message})\`
|
|
@@ -948,9 +964,9 @@ function renderParamsInfoType(params) {
|
|
|
948
964
|
}
|
|
949
965
|
function renderMatch(verb, route, pathIndex) {
|
|
950
966
|
var _a;
|
|
951
|
-
const handler = `${verb}
|
|
967
|
+
const handler = `${verb}${route.index}`;
|
|
952
968
|
const params = ((_a = route.params) == null ? void 0 : _a.length) ? renderParamsInfo(route.params, pathIndex) : "{}";
|
|
953
|
-
const meta = route.meta ? `meta
|
|
969
|
+
const meta = route.meta ? `meta${route.index}` : "{}";
|
|
954
970
|
return `{ handler: ${handler}, params: ${params}, meta: ${meta} }`;
|
|
955
971
|
}
|
|
956
972
|
function renderMiddleware(middleware) {
|
|
@@ -962,9 +978,9 @@ function renderMiddleware(middleware) {
|
|
|
962
978
|
imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
|
|
963
979
|
writer.writeLines("");
|
|
964
980
|
for (const { id, importPath } of middleware) {
|
|
965
|
-
const importName = `
|
|
981
|
+
const importName = `middleware${id}`;
|
|
966
982
|
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
967
|
-
writer.writeLines(`export const mware
|
|
983
|
+
writer.writeLines(`export const mware${id} = normalize(${importName});`);
|
|
968
984
|
}
|
|
969
985
|
imports.join();
|
|
970
986
|
return writer.end();
|
|
@@ -979,7 +995,7 @@ function stripTsExtension(path3) {
|
|
|
979
995
|
}
|
|
980
996
|
return path3;
|
|
981
997
|
}
|
|
982
|
-
function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
998
|
+
function renderRouteTypeInfo(routes, pathPrefix = ".", adapterTypes = "") {
|
|
983
999
|
var _a, _b;
|
|
984
1000
|
const writer = createStringWriter();
|
|
985
1001
|
writer.writeLines(
|
|
@@ -987,8 +1003,10 @@ function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
|
987
1003
|
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
988
1004
|
Do NOT manually edit this file or your changes will be lost.
|
|
989
1005
|
*/
|
|
990
|
-
|
|
991
|
-
`import type { HandlerLike, Route, RouteContext, ValidatePath, ValidateHref } from "@marko/run"
|
|
1006
|
+
`,
|
|
1007
|
+
`import type { HandlerLike, Route, RouteContext, ValidatePath, ValidateHref } from "@marko/run";`,
|
|
1008
|
+
adapterTypes,
|
|
1009
|
+
`
|
|
992
1010
|
|
|
993
1011
|
declare global {
|
|
994
1012
|
namespace MarkoRun {`
|
|
@@ -1058,7 +1076,7 @@ declare module '${pathPrefix}/${page.relativePath}' {
|
|
|
1058
1076
|
|
|
1059
1077
|
namespace MarkoRun {
|
|
1060
1078
|
type CurrentRoute = ${routeType};
|
|
1061
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1079
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1062
1080
|
}
|
|
1063
1081
|
}`);
|
|
1064
1082
|
}
|
|
@@ -1123,7 +1141,7 @@ declare module '${pathPrefix}/${file.relativePath}' {
|
|
|
1123
1141
|
|
|
1124
1142
|
namespace MarkoRun {
|
|
1125
1143
|
type CurrentRoute = ${routeTypes.join(" | ")};
|
|
1126
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1144
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1127
1145
|
}
|
|
1128
1146
|
}`);
|
|
1129
1147
|
}
|
|
@@ -1141,7 +1159,7 @@ declare module '${pathPrefix}/${route.page.relativePath}' {
|
|
|
1141
1159
|
|
|
1142
1160
|
namespace MarkoRun {
|
|
1143
1161
|
type CurrentRoute = Route;
|
|
1144
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1162
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1145
1163
|
}
|
|
1146
1164
|
}`);
|
|
1147
1165
|
}
|
|
@@ -1154,7 +1172,7 @@ function writeRouteTypeModule(writer, pathPrefix, path3, routeType) {
|
|
|
1154
1172
|
declare module '${pathPrefix}/${stripTsExtension(path3)}' {
|
|
1155
1173
|
namespace MarkoRun {
|
|
1156
1174
|
type CurrentRoute = ${routeType};
|
|
1157
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1175
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1158
1176
|
type Handler<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']> = HandlerLike<CurrentRoute>;
|
|
1159
1177
|
function route(handler: Handler): typeof handler;
|
|
1160
1178
|
function route<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']>(handler: Handler): typeof handler;
|
|
@@ -1385,7 +1403,7 @@ function markoServe(opts = {}) {
|
|
|
1385
1403
|
))) {
|
|
1386
1404
|
const filepath = import_path2.default.join(typesDir, "routes.d.ts");
|
|
1387
1405
|
const adapterTypeInfo = (adapter == null ? void 0 : adapter.writeTypeInfo) && await (adapter == null ? void 0 : adapter.writeTypeInfo());
|
|
1388
|
-
const data = renderRouteTypeInfo(routes, import_path2.default.relative(typesDir, routesDir)
|
|
1406
|
+
const data = renderRouteTypeInfo(routes, import_path2.default.relative(typesDir, routesDir), adapterTypeInfo);
|
|
1389
1407
|
if (data !== typesFile || !import_fs2.default.existsSync(filepath)) {
|
|
1390
1408
|
await ensureDir(typesDir);
|
|
1391
1409
|
await import_fs2.default.promises.writeFile(filepath, typesFile = data);
|
|
@@ -1652,8 +1670,8 @@ async function getVerbsFromFileBuild(context, filePath) {
|
|
|
1652
1670
|
if (result) {
|
|
1653
1671
|
const exportIds = getExportIdentifiers(result.ast);
|
|
1654
1672
|
for (const id of exportIds) {
|
|
1655
|
-
const verb = id
|
|
1656
|
-
if (httpVerbs.includes(verb)) {
|
|
1673
|
+
const verb = id.toLowerCase();
|
|
1674
|
+
if (id === verb.toUpperCase() && httpVerbs.includes(verb)) {
|
|
1657
1675
|
verbs.push(verb);
|
|
1658
1676
|
}
|
|
1659
1677
|
}
|
|
@@ -1664,12 +1682,19 @@ async function getVerbsFromFileDev(devServer, filePath) {
|
|
|
1664
1682
|
const verbs = [];
|
|
1665
1683
|
const result = await devServer.transformRequest(filePath, { ssr: true });
|
|
1666
1684
|
if (result && result.code) {
|
|
1667
|
-
const verbMatchReg = /__vite_ssr_exports__,\s+["'](
|
|
1685
|
+
const verbMatchReg = /__vite_ssr_exports__,\s+["'](GET|POST|PUT|DELETE)["']/gi;
|
|
1668
1686
|
let match = verbMatchReg.exec(result.code);
|
|
1669
1687
|
while (match) {
|
|
1670
|
-
const
|
|
1688
|
+
const id = match[1];
|
|
1689
|
+
const verb = id.toLowerCase();
|
|
1671
1690
|
if (httpVerbs.includes(verb)) {
|
|
1672
|
-
|
|
1691
|
+
if (id === verb.toUpperCase()) {
|
|
1692
|
+
verbs.push(verb);
|
|
1693
|
+
} else {
|
|
1694
|
+
console.warn(
|
|
1695
|
+
`Found export '${id}' in handler ${filePath} which is close to '${verb.toUpperCase()}'. Exported handlers need to be uppercase: GET, POST, PUT or DELETE.`
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1673
1698
|
}
|
|
1674
1699
|
match = verbMatchReg.exec(result.code);
|
|
1675
1700
|
}
|
package/dist/vite/index.js
CHANGED
|
@@ -123,7 +123,14 @@ async function buildRoutes(walk, basePath) {
|
|
|
123
123
|
if (handler || page) {
|
|
124
124
|
const key = path3.replace(/(\$\$?)[^\/]*/g, "$1").replace(/^\/+/, "").replace(/[^a-z0-9_$\/]+/gi, "").replace(/\//g, "__") || "index";
|
|
125
125
|
if (routes.has(key)) {
|
|
126
|
-
|
|
126
|
+
const existing = routes.get(key);
|
|
127
|
+
const existingFiles = [existing.handler, existing.page].filter(Boolean).map((f) => f.filePath);
|
|
128
|
+
const currentFiles = [handler, page].filter(Boolean).map((f) => f.filePath);
|
|
129
|
+
throw new Error(`Duplicate routes for path ${path3} were defined. A route established by:
|
|
130
|
+
${existingFiles}
|
|
131
|
+
collides with
|
|
132
|
+
${currentFiles.join(" and ")}
|
|
133
|
+
`);
|
|
127
134
|
} else {
|
|
128
135
|
const index = nextRouteIndex++;
|
|
129
136
|
routes.set(key, {
|
|
@@ -171,14 +178,16 @@ async function buildRoutes(walk, basePath) {
|
|
|
171
178
|
const prevChildren = children;
|
|
172
179
|
const prevCurrent = current;
|
|
173
180
|
const prevIsRoot = isRoot;
|
|
174
|
-
if (name.charCodeAt(0) === 95
|
|
181
|
+
if (name.charCodeAt(0) === 95) {
|
|
175
182
|
} else {
|
|
176
183
|
if (name.charCodeAt(0) === 36) {
|
|
177
184
|
if (name.charCodeAt(1) === 36) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
if (name.length > 2) {
|
|
186
|
+
paramStack.push({
|
|
187
|
+
name: name.slice(2),
|
|
188
|
+
index: -1
|
|
189
|
+
});
|
|
190
|
+
}
|
|
182
191
|
} else if (name.length > 1) {
|
|
183
192
|
paramStack.push({
|
|
184
193
|
name: name.slice(1),
|
|
@@ -497,7 +506,7 @@ function renderRouteEntry(route) {
|
|
|
497
506
|
);
|
|
498
507
|
}
|
|
499
508
|
if (middleware.length) {
|
|
500
|
-
const names = middleware.map((m) => `mware
|
|
509
|
+
const names = middleware.map((m) => `mware${m.id}`);
|
|
501
510
|
imports.writeLines(
|
|
502
511
|
`import { ${names.join(
|
|
503
512
|
", "
|
|
@@ -508,9 +517,9 @@ function renderRouteEntry(route) {
|
|
|
508
517
|
writer.writeLines("");
|
|
509
518
|
const names = [];
|
|
510
519
|
for (const verb of handler.verbs) {
|
|
511
|
-
const
|
|
512
|
-
names.push(
|
|
513
|
-
writer.writeLines(`const
|
|
520
|
+
const importName = verb.toUpperCase();
|
|
521
|
+
names.push(importName);
|
|
522
|
+
writer.writeLines(`const ${verb}Handler = normalize(${importName});`);
|
|
514
523
|
}
|
|
515
524
|
imports.writeLines(
|
|
516
525
|
`import { ${names.join(", ")} } from './${handler.importPath}';`
|
|
@@ -523,7 +532,7 @@ function renderRouteEntry(route) {
|
|
|
523
532
|
}
|
|
524
533
|
if (meta) {
|
|
525
534
|
imports.writeLines(
|
|
526
|
-
`export { default as meta
|
|
535
|
+
`export { default as meta${index} } from './${meta.importPath}';`
|
|
527
536
|
);
|
|
528
537
|
}
|
|
529
538
|
for (const verb of verbs) {
|
|
@@ -554,14 +563,19 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
554
563
|
let nextName;
|
|
555
564
|
let currentName;
|
|
556
565
|
let hasBody = false;
|
|
557
|
-
writer.writeLines("")
|
|
558
|
-
|
|
559
|
-
|
|
566
|
+
writer.writeLines("");
|
|
567
|
+
if (page) {
|
|
568
|
+
writer.writeBlockStart(
|
|
569
|
+
`export async function ${verb}${index}(context, buildInput) {`
|
|
570
|
+
);
|
|
571
|
+
} else {
|
|
572
|
+
writer.writeBlockStart(`export async function ${verb}${index}(context) {`);
|
|
573
|
+
}
|
|
560
574
|
const continuations = writer.branch("cont");
|
|
561
575
|
if (page && verb === "get") {
|
|
562
576
|
currentName = "__page";
|
|
563
577
|
if ((_a = handler == null ? void 0 : handler.verbs) == null ? void 0 : _a.includes(verb)) {
|
|
564
|
-
const name =
|
|
578
|
+
const name = `${verb}Handler`;
|
|
565
579
|
writePageResponse(continuations, currentName);
|
|
566
580
|
if (len) {
|
|
567
581
|
nextName = currentName;
|
|
@@ -579,7 +593,7 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
579
593
|
hasBody = true;
|
|
580
594
|
}
|
|
581
595
|
} else if (handler) {
|
|
582
|
-
const name =
|
|
596
|
+
const name = `${verb}Handler`;
|
|
583
597
|
currentName = `__${name}`;
|
|
584
598
|
nextName = "noContent";
|
|
585
599
|
if (len) {
|
|
@@ -595,7 +609,7 @@ function writeRouteEntryHandler(writer, route, verb) {
|
|
|
595
609
|
let i = len;
|
|
596
610
|
while (i--) {
|
|
597
611
|
const { id } = middleware[i];
|
|
598
|
-
const name = `mware
|
|
612
|
+
const name = `mware${id}`;
|
|
599
613
|
nextName = currentName;
|
|
600
614
|
currentName = i ? `__${name}` : "";
|
|
601
615
|
writeMiddleware(continuations, name, nextName, currentName);
|
|
@@ -611,12 +625,12 @@ function renderRouter(routes, options = {
|
|
|
611
625
|
writer.writeLines(`// @marko/run/router`);
|
|
612
626
|
const imports = writer.branch("imports");
|
|
613
627
|
imports.writeLines(
|
|
614
|
-
`import {
|
|
628
|
+
`import { NotHandled, NotMatched, createInput } from 'virtual:marko-run/internal';`
|
|
615
629
|
);
|
|
616
630
|
for (const route of routes.list) {
|
|
617
631
|
const verbs = getVerbs(route);
|
|
618
|
-
const names = verbs.map((verb) => `${verb}
|
|
619
|
-
route.meta && names.push(`meta
|
|
632
|
+
const names = verbs.map((verb) => `${verb}${route.index}`);
|
|
633
|
+
route.meta && names.push(`meta${route.index}`);
|
|
620
634
|
imports.writeLines(
|
|
621
635
|
`import { ${names.join(
|
|
622
636
|
", "
|
|
@@ -625,10 +639,16 @@ function renderRouter(routes, options = {
|
|
|
625
639
|
}
|
|
626
640
|
for (const { key } of Object.values(routes.special)) {
|
|
627
641
|
imports.writeLines(
|
|
628
|
-
`import page
|
|
642
|
+
`import page${key} from '${virtualFilePrefix}/${markoRunFilePrefix}special__${key}.marko${serverEntryQuery}';`
|
|
629
643
|
);
|
|
630
644
|
}
|
|
631
|
-
writer.writeLines(``).writeBlockStart(`function
|
|
645
|
+
writer.writeLines(``).writeBlockStart(`export function match(method, pathname) {`).writeLines(
|
|
646
|
+
`if (!pathname) {
|
|
647
|
+
pathname = '/';
|
|
648
|
+
} else if (pathname.charAt(0) !== '/') {
|
|
649
|
+
pathname = '/' + pathname;
|
|
650
|
+
}`
|
|
651
|
+
).writeBlockStart(`switch (method.toLowerCase()) {`);
|
|
632
652
|
for (const verb of httpVerbs) {
|
|
633
653
|
const filteredRoutes = routes.list.filter((route) => hasVerb(route, verb));
|
|
634
654
|
if (filteredRoutes.length) {
|
|
@@ -640,16 +660,12 @@ function renderRouter(routes, options = {
|
|
|
640
660
|
}
|
|
641
661
|
writer.writeBlockEnd("}").writeLines("return null;").writeBlockEnd("}");
|
|
642
662
|
writer.write(`
|
|
643
|
-
export function
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
}
|
|
649
|
-
return findRoute(method, pathname);
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
export async function invokeRoute(route, context) {
|
|
663
|
+
export async function invoke(route, request, platform, url = new URL(request.url)) {
|
|
664
|
+
const context = {
|
|
665
|
+
url,
|
|
666
|
+
request,
|
|
667
|
+
platform
|
|
668
|
+
};
|
|
653
669
|
try {
|
|
654
670
|
const buildInput = createInput(context);
|
|
655
671
|
if (route) {
|
|
@@ -659,9 +675,9 @@ export async function invokeRoute(route, context) {
|
|
|
659
675
|
const response = await route.handler(context, buildInput);
|
|
660
676
|
if (response) return response;
|
|
661
677
|
} catch (error) {
|
|
662
|
-
if (error ===
|
|
678
|
+
if (error === NotHandled) {
|
|
663
679
|
return;
|
|
664
|
-
} else if (error !==
|
|
680
|
+
} else if (error !== NotMatched) {
|
|
665
681
|
throw error;
|
|
666
682
|
}
|
|
667
683
|
}
|
|
@@ -673,7 +689,7 @@ export async function invokeRoute(route, context) {
|
|
|
673
689
|
context.meta = {};
|
|
674
690
|
}
|
|
675
691
|
if (context.request.headers.get('Accept')?.includes('text/html')) {
|
|
676
|
-
return new Response(
|
|
692
|
+
return new Response(page404.stream(buildInput()), {
|
|
677
693
|
status: 404,
|
|
678
694
|
headers: { "content-type": "text/html;charset=UTF-8" },
|
|
679
695
|
});
|
|
@@ -689,7 +705,7 @@ export async function invokeRoute(route, context) {
|
|
|
689
705
|
writer.writeBlockStart(
|
|
690
706
|
`if (context.request.headers.get('Accept')?.includes('text/html')) {`
|
|
691
707
|
).writeBlock(
|
|
692
|
-
`return new Response(
|
|
708
|
+
`return new Response(page500.stream(buildInput({ error })), {`,
|
|
693
709
|
[
|
|
694
710
|
`status: 500,`,
|
|
695
711
|
`headers: { "content-type": "text/html;charset=UTF-8" },`
|
|
@@ -698,9 +714,9 @@ export async function invokeRoute(route, context) {
|
|
|
698
714
|
).writeBlockEnd("}");
|
|
699
715
|
}
|
|
700
716
|
writer.writeLines(`throw error;`).writeBlockEnd("}").writeBlockEnd("}").write(`
|
|
701
|
-
export async function
|
|
717
|
+
export async function fetch(request, platform) {
|
|
702
718
|
try {
|
|
703
|
-
const
|
|
719
|
+
const url = new URL(request.url);
|
|
704
720
|
let { pathname } = url;`);
|
|
705
721
|
switch (options.trailingSlashes) {
|
|
706
722
|
case "RedirectWithout":
|
|
@@ -732,8 +748,8 @@ export async function router(context) {
|
|
|
732
748
|
}
|
|
733
749
|
writer.write(`
|
|
734
750
|
|
|
735
|
-
const route =
|
|
736
|
-
return await
|
|
751
|
+
const route = match(request.method, pathname);
|
|
752
|
+
return await invoke(route, request, platform, url);
|
|
737
753
|
} catch (error) {
|
|
738
754
|
const message = import.meta.env.DEV
|
|
739
755
|
? \`Internal Server Error (\${error.message})\`
|
|
@@ -911,9 +927,9 @@ function renderParamsInfoType(params) {
|
|
|
911
927
|
}
|
|
912
928
|
function renderMatch(verb, route, pathIndex) {
|
|
913
929
|
var _a;
|
|
914
|
-
const handler = `${verb}
|
|
930
|
+
const handler = `${verb}${route.index}`;
|
|
915
931
|
const params = ((_a = route.params) == null ? void 0 : _a.length) ? renderParamsInfo(route.params, pathIndex) : "{}";
|
|
916
|
-
const meta = route.meta ? `meta
|
|
932
|
+
const meta = route.meta ? `meta${route.index}` : "{}";
|
|
917
933
|
return `{ handler: ${handler}, params: ${params}, meta: ${meta} }`;
|
|
918
934
|
}
|
|
919
935
|
function renderMiddleware(middleware) {
|
|
@@ -925,9 +941,9 @@ function renderMiddleware(middleware) {
|
|
|
925
941
|
imports.writeLines(`import { normalize } from 'virtual:marko-run/internal';`);
|
|
926
942
|
writer.writeLines("");
|
|
927
943
|
for (const { id, importPath } of middleware) {
|
|
928
|
-
const importName = `
|
|
944
|
+
const importName = `middleware${id}`;
|
|
929
945
|
imports.writeLines(`import ${importName} from './${importPath}';`);
|
|
930
|
-
writer.writeLines(`export const mware
|
|
946
|
+
writer.writeLines(`export const mware${id} = normalize(${importName});`);
|
|
931
947
|
}
|
|
932
948
|
imports.join();
|
|
933
949
|
return writer.end();
|
|
@@ -942,7 +958,7 @@ function stripTsExtension(path3) {
|
|
|
942
958
|
}
|
|
943
959
|
return path3;
|
|
944
960
|
}
|
|
945
|
-
function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
961
|
+
function renderRouteTypeInfo(routes, pathPrefix = ".", adapterTypes = "") {
|
|
946
962
|
var _a, _b;
|
|
947
963
|
const writer = createStringWriter();
|
|
948
964
|
writer.writeLines(
|
|
@@ -950,8 +966,10 @@ function renderRouteTypeInfo(routes, pathPrefix = ".") {
|
|
|
950
966
|
WARNING: This file is automatically generated and any changes made to it will be overwritten without warning.
|
|
951
967
|
Do NOT manually edit this file or your changes will be lost.
|
|
952
968
|
*/
|
|
953
|
-
|
|
954
|
-
`import type { HandlerLike, Route, RouteContext, ValidatePath, ValidateHref } from "@marko/run"
|
|
969
|
+
`,
|
|
970
|
+
`import type { HandlerLike, Route, RouteContext, ValidatePath, ValidateHref } from "@marko/run";`,
|
|
971
|
+
adapterTypes,
|
|
972
|
+
`
|
|
955
973
|
|
|
956
974
|
declare global {
|
|
957
975
|
namespace MarkoRun {`
|
|
@@ -1021,7 +1039,7 @@ declare module '${pathPrefix}/${page.relativePath}' {
|
|
|
1021
1039
|
|
|
1022
1040
|
namespace MarkoRun {
|
|
1023
1041
|
type CurrentRoute = ${routeType};
|
|
1024
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1042
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1025
1043
|
}
|
|
1026
1044
|
}`);
|
|
1027
1045
|
}
|
|
@@ -1086,7 +1104,7 @@ declare module '${pathPrefix}/${file.relativePath}' {
|
|
|
1086
1104
|
|
|
1087
1105
|
namespace MarkoRun {
|
|
1088
1106
|
type CurrentRoute = ${routeTypes.join(" | ")};
|
|
1089
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1107
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1090
1108
|
}
|
|
1091
1109
|
}`);
|
|
1092
1110
|
}
|
|
@@ -1104,7 +1122,7 @@ declare module '${pathPrefix}/${route.page.relativePath}' {
|
|
|
1104
1122
|
|
|
1105
1123
|
namespace MarkoRun {
|
|
1106
1124
|
type CurrentRoute = Route;
|
|
1107
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1125
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1108
1126
|
}
|
|
1109
1127
|
}`);
|
|
1110
1128
|
}
|
|
@@ -1117,7 +1135,7 @@ function writeRouteTypeModule(writer, pathPrefix, path3, routeType) {
|
|
|
1117
1135
|
declare module '${pathPrefix}/${stripTsExtension(path3)}' {
|
|
1118
1136
|
namespace MarkoRun {
|
|
1119
1137
|
type CurrentRoute = ${routeType};
|
|
1120
|
-
type CurrentContext = RouteContext<CurrentRoute>;
|
|
1138
|
+
type CurrentContext = RouteContext<RouteContext['platform'], CurrentRoute>;
|
|
1121
1139
|
type Handler<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']> = HandlerLike<CurrentRoute>;
|
|
1122
1140
|
function route(handler: Handler): typeof handler;
|
|
1123
1141
|
function route<_Params = CurrentRoute['params'], _Meta = CurrentRoute['meta']>(handler: Handler): typeof handler;
|
|
@@ -1347,7 +1365,7 @@ function markoServe(opts = {}) {
|
|
|
1347
1365
|
))) {
|
|
1348
1366
|
const filepath = path2.join(typesDir, "routes.d.ts");
|
|
1349
1367
|
const adapterTypeInfo = (adapter == null ? void 0 : adapter.writeTypeInfo) && await (adapter == null ? void 0 : adapter.writeTypeInfo());
|
|
1350
|
-
const data = renderRouteTypeInfo(routes, path2.relative(typesDir, routesDir)
|
|
1368
|
+
const data = renderRouteTypeInfo(routes, path2.relative(typesDir, routesDir), adapterTypeInfo);
|
|
1351
1369
|
if (data !== typesFile || !fs2.existsSync(filepath)) {
|
|
1352
1370
|
await ensureDir(typesDir);
|
|
1353
1371
|
await fs2.promises.writeFile(filepath, typesFile = data);
|
|
@@ -1614,8 +1632,8 @@ async function getVerbsFromFileBuild(context, filePath) {
|
|
|
1614
1632
|
if (result) {
|
|
1615
1633
|
const exportIds = getExportIdentifiers(result.ast);
|
|
1616
1634
|
for (const id of exportIds) {
|
|
1617
|
-
const verb = id
|
|
1618
|
-
if (httpVerbs.includes(verb)) {
|
|
1635
|
+
const verb = id.toLowerCase();
|
|
1636
|
+
if (id === verb.toUpperCase() && httpVerbs.includes(verb)) {
|
|
1619
1637
|
verbs.push(verb);
|
|
1620
1638
|
}
|
|
1621
1639
|
}
|
|
@@ -1626,12 +1644,19 @@ async function getVerbsFromFileDev(devServer, filePath) {
|
|
|
1626
1644
|
const verbs = [];
|
|
1627
1645
|
const result = await devServer.transformRequest(filePath, { ssr: true });
|
|
1628
1646
|
if (result && result.code) {
|
|
1629
|
-
const verbMatchReg = /__vite_ssr_exports__,\s+["'](
|
|
1647
|
+
const verbMatchReg = /__vite_ssr_exports__,\s+["'](GET|POST|PUT|DELETE)["']/gi;
|
|
1630
1648
|
let match = verbMatchReg.exec(result.code);
|
|
1631
1649
|
while (match) {
|
|
1632
|
-
const
|
|
1650
|
+
const id = match[1];
|
|
1651
|
+
const verb = id.toLowerCase();
|
|
1633
1652
|
if (httpVerbs.includes(verb)) {
|
|
1634
|
-
|
|
1653
|
+
if (id === verb.toUpperCase()) {
|
|
1654
|
+
verbs.push(verb);
|
|
1655
|
+
} else {
|
|
1656
|
+
console.warn(
|
|
1657
|
+
`Found export '${id}' in handler ${filePath} which is close to '${verb.toUpperCase()}'. Exported handlers need to be uppercase: GET, POST, PUT or DELETE.`
|
|
1658
|
+
);
|
|
1659
|
+
}
|
|
1635
1660
|
}
|
|
1636
1661
|
match = verbMatchReg.exec(result.code);
|
|
1637
1662
|
}
|