@marko/run 0.0.1-beta6 → 0.0.1-beta8
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 +227 -72
- package/dist/adapter/default-entry.mjs +8 -5
- package/dist/adapter/index.cjs +50 -46
- package/dist/adapter/index.js +50 -46
- package/dist/adapter/middleware.cjs +34 -40
- package/dist/adapter/middleware.d.ts +4 -2
- package/dist/adapter/middleware.js +33 -40
- package/dist/cli/index.mjs +2 -2
- 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 +83 -58
- package/dist/vite/index.js +83 -58
- package/package.json +3 -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,18 +697,14 @@ 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
|
-
|
|
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
|
+
};
|
|
706
|
+
const buildInput = createInput(context);
|
|
690
707
|
try {
|
|
691
|
-
const buildInput = createInput(context);
|
|
692
708
|
if (route) {
|
|
693
709
|
context.params = route.params;
|
|
694
710
|
context.meta = route.meta;
|
|
@@ -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
|
}
|