@moonsjs/vite 0.1.17 → 0.2.0
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/{index-v5sbd3az.js → index-0agjty3z.js} +21 -18
- package/dist/index-0agjty3z.js.map +15 -0
- package/dist/index-f8w073cm.js +30 -0
- package/dist/index-f8w073cm.js.map +10 -0
- package/dist/{index-snbxks72.js → index-tbph0859.js} +80 -80
- package/dist/{index-snbxks72.js.map → index-tbph0859.js.map} +4 -4
- package/dist/index.js +33 -33
- package/dist/index.js.map +4 -4
- package/dist/server/handler.d.ts.map +1 -1
- package/dist/server/index.js +104 -93
- package/dist/server/index.js.map +10 -10
- package/dist/server/test-server.d.ts +6 -0
- package/dist/server/test-server.d.ts.map +1 -1
- package/dist/testing-preload.d.ts +2 -0
- package/dist/testing-preload.d.ts.map +1 -0
- package/dist/testing-preload.js +10 -0
- package/dist/testing-preload.js.map +10 -0
- package/dist/testing.d.ts +11 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +13 -0
- package/dist/testing.js.map +9 -0
- package/dist/transform.js +1 -1
- package/package.json +15 -5
- package/src/api.ts +14 -14
- package/src/devtools.ts +5 -5
- package/src/manifest.ts +2 -2
- package/src/plugin.ts +21 -21
- package/src/server/dev.ts +6 -1
- package/src/server/handler.ts +69 -47
- package/src/server/isr.ts +5 -5
- package/src/server/node-server.ts +6 -6
- package/src/server/node.ts +2 -2
- package/src/server/plugins.ts +1 -1
- package/src/server/prerender.ts +29 -29
- package/src/server/shell.ts +8 -8
- package/src/server/shutdown.ts +5 -5
- package/src/server/storage.ts +1 -1
- package/src/server/test-server.ts +12 -1
- package/src/server-only.ts +7 -7
- package/src/testing-preload.ts +5 -0
- package/src/testing.ts +34 -0
- package/src/transform.ts +76 -76
- package/dist/index-v5sbd3az.js.map +0 -15
|
@@ -103,17 +103,17 @@ function createServerOnlyClassifier(options = {}) {
|
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
105
|
function serverOnlyImportError(input) {
|
|
106
|
-
const sourceLabel = input.source === "builtin" ? "
|
|
106
|
+
const sourceLabel = input.source === "builtin" ? "Match source: framework built-in server-only package list." : input.source === "config" ? "Match source: `security.serverOnlyPackages` in moons.config.ts." : `Match source: marker \`"moons": { "serverOnly": true }\` in ${input.markerPath ?? "package.json"}.`;
|
|
107
107
|
return new MoonsError({
|
|
108
108
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
109
109
|
file: input.relativeFile,
|
|
110
110
|
line: input.line,
|
|
111
|
-
message: `
|
|
111
|
+
message: `importing${input.dynamic === true ? " (dynamic)" : ""} \`${input.specifier}\` — server-only package \`${input.packageName}\``,
|
|
112
112
|
details: `${sourceLabel}
|
|
113
|
-
|
|
113
|
+
Server-only packages must not enter the client bundle.`,
|
|
114
114
|
suggestions: [
|
|
115
|
-
"
|
|
116
|
-
"
|
|
115
|
+
"Move the operation into `*.server.ts` and call it via a serverFn",
|
|
116
|
+
"Or replace/remove the import in the client module"
|
|
117
117
|
]
|
|
118
118
|
});
|
|
119
119
|
}
|
|
@@ -499,17 +499,17 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
499
499
|
file: filename,
|
|
500
500
|
line: fn.line,
|
|
501
501
|
annotation: fn.name,
|
|
502
|
-
message: `schema ${kind} serverFn \`${fn.name}\`
|
|
503
|
-
details: `\`${reference}\`
|
|
502
|
+
message: `schema ${kind} of serverFn \`${fn.name}\` references server value \`${reference}\` from \`${serverImport.specifier}\``,
|
|
503
|
+
details: `\`${reference}\` is imported from another server file and is not a serverFn — the client stub does not export it (previously a raw bundler \`MISSING_EXPORT\` error).
|
|
504
504
|
|
|
505
|
-
` + `
|
|
506
|
-
` + ` // a)
|
|
505
|
+
` + `Pick one:
|
|
506
|
+
` + ` // a) move the constant/schema to a client-safe module
|
|
507
507
|
` + ` import { ${reference} } from "../shared/schemas";
|
|
508
|
-
` + ` // b) inline
|
|
509
|
-
` + " // c)
|
|
508
|
+
` + ` // b) inline the value if it is genuinely public in the schema, or
|
|
509
|
+
` + " // c) do extra validation in the server handler without referencing server values in the schema",
|
|
510
510
|
suggestions: [
|
|
511
|
-
"
|
|
512
|
-
"
|
|
511
|
+
"Move the referenced declaration to a client-safe shared module (e.g. `src/shared/schemas.ts`)",
|
|
512
|
+
"Or do the validation in the server handler instead of the schema expression"
|
|
513
513
|
]
|
|
514
514
|
});
|
|
515
515
|
}
|
|
@@ -523,22 +523,22 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
523
523
|
file: filename,
|
|
524
524
|
line: fn.line,
|
|
525
525
|
annotation: fn.name,
|
|
526
|
-
message: `schema ${kind} serverFn \`${fn.name}\`
|
|
527
|
-
details: `\`${reference}\`
|
|
526
|
+
message: `schema ${kind} of serverFn \`${fn.name}\` references local declaration \`${reference}\``,
|
|
527
|
+
details: `\`${reference}\` is dropped from the client stub, so its value is \`undefined\` in the browser (hydration crash).
|
|
528
528
|
|
|
529
|
-
` + `
|
|
530
|
-
` + ` const ${reference} = z.object({ … }); //
|
|
529
|
+
` + `Before (rejected):
|
|
530
|
+
` + ` const ${reference} = z.object({ … }); // local declaration in the same file
|
|
531
531
|
` + ` export const ${fn.name} = serverFn({ ${kind}: ${reference}, … });
|
|
532
532
|
|
|
533
|
-
` + `
|
|
534
|
-
` + ` // a) inline schema
|
|
533
|
+
` + `After (pick one):
|
|
534
|
+
` + ` // a) inline the schema in the argument
|
|
535
535
|
` + ` export const ${fn.name} = serverFn({ ${kind}: z.object({ … }), … });
|
|
536
|
-
` + ` // b)
|
|
536
|
+
` + ` // b) move the declaration to a shared module that may enter the client (e.g. src/shared/schemas.ts)
|
|
537
537
|
` + ` import { ${reference} } from "../shared/schemas";`,
|
|
538
538
|
suggestions: [
|
|
539
|
-
`Inline schema
|
|
540
|
-
`
|
|
541
|
-
"
|
|
539
|
+
`Inline the schema in the argument \`serverFn({ ${kind}: … })\`, or`,
|
|
540
|
+
`Move \`${reference}\` to a shared module (e.g. \`src/shared/schemas.ts\`) and import it from there`,
|
|
541
|
+
"Never move secret values to shared — the schema must be client-safe (zod/Standard Schema)"
|
|
542
542
|
]
|
|
543
543
|
});
|
|
544
544
|
}
|
|
@@ -551,9 +551,9 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
551
551
|
throw new MoonsError2({
|
|
552
552
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
553
553
|
file: filename,
|
|
554
|
-
message: `
|
|
555
|
-
details: "Re-
|
|
556
|
-
suggestions: ["
|
|
554
|
+
message: `cannot resolve \`${reExport.source}\` for re-export`,
|
|
555
|
+
details: "Re-exports from `*.server.ts` must be statically resolvable.",
|
|
556
|
+
suggestions: ["Fix the re-export path", "Avoid dynamic re-exports from server files"]
|
|
557
557
|
});
|
|
558
558
|
}
|
|
559
559
|
const targetNames = serverFnExportNames2(target, (specifier) => dependencies.analyzeSpecifier(filename, specifier));
|
|
@@ -569,9 +569,9 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
569
569
|
throw new MoonsError2({
|
|
570
570
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
571
571
|
file: filename,
|
|
572
|
-
message: `\`export *\`
|
|
573
|
-
details: "`export *`
|
|
574
|
-
suggestions: ["
|
|
572
|
+
message: `\`export *\` from \`${specifier}\` cannot be resolved`,
|
|
573
|
+
details: "`export *` from `*.server.ts` must be statically expandable.",
|
|
574
|
+
suggestions: ["Fix the re-export path", "Replace it with named re-exports"]
|
|
575
575
|
});
|
|
576
576
|
}
|
|
577
577
|
const targetNames = serverFnExportNames2(target, (nested) => dependencies.analyzeSpecifier(filename, nested));
|
|
@@ -580,7 +580,7 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
582
|
if (importLines.length === 0 && exportLines.length === 0) {
|
|
583
|
-
return { code: `// @moons:
|
|
583
|
+
return { code: `// @moons: no serverFn exported
|
|
584
584
|
export {};
|
|
585
585
|
`, referenced };
|
|
586
586
|
}
|
|
@@ -637,11 +637,11 @@ function nonContractServerFileError2(file, projectRoot) {
|
|
|
637
637
|
return new MoonsError2({
|
|
638
638
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
639
639
|
file: toRelative(projectRoot, file),
|
|
640
|
-
message: "file
|
|
641
|
-
details: "
|
|
640
|
+
message: "server file uses an extension outside the `*.server.ts` contract",
|
|
641
|
+
details: "The zero-trust transform only handles `*.server.ts`/`*.server.tsx`; server files with other extensions cannot be stubbed and must not enter the client graph.",
|
|
642
642
|
suggestions: [
|
|
643
|
-
"
|
|
644
|
-
"
|
|
643
|
+
"Rename the file to `*.server.ts`/`*.server.tsx` and put the `serverFn` inside it",
|
|
644
|
+
"Or move the value you need into a non-server file"
|
|
645
645
|
]
|
|
646
646
|
});
|
|
647
647
|
}
|
|
@@ -791,11 +791,11 @@ async function checkClientModuleImports2(context) {
|
|
|
791
791
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
792
792
|
file: relativeFile,
|
|
793
793
|
line,
|
|
794
|
-
message: `
|
|
795
|
-
details: "
|
|
794
|
+
message: `importing \`${specifier}\` — \`moons.config.ts\` is a server-only module`,
|
|
795
|
+
details: "The config contains `context`/`middleware` (server code) and never enters the client bundle (Addendum J.4).",
|
|
796
796
|
suggestions: [
|
|
797
|
-
"
|
|
798
|
-
"
|
|
797
|
+
"Move the value you need into a client-safe module (e.g. `src/shared/…`)",
|
|
798
|
+
"Get the value from the server via a loader/serverFn"
|
|
799
799
|
]
|
|
800
800
|
});
|
|
801
801
|
};
|
|
@@ -804,11 +804,11 @@ async function checkClientModuleImports2(context) {
|
|
|
804
804
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
805
805
|
file: relativeFile,
|
|
806
806
|
line,
|
|
807
|
-
message: `
|
|
808
|
-
details: "
|
|
807
|
+
message: `importing \`${specifier}\` — \`${toRelative(projectRoot, resolvedTarget)}\` is inside \`src/server/**\` (server-only)`,
|
|
808
|
+
details: "The `src/server/**` directory is for server code only (Addendum J.4); the `.server.ts` suffix is not the only guarantee.",
|
|
809
809
|
suggestions: [
|
|
810
|
-
"
|
|
811
|
-
"
|
|
810
|
+
"Move client-safe code to `src/shared/`",
|
|
811
|
+
"Access the value from the server via a loader/serverFn"
|
|
812
812
|
]
|
|
813
813
|
});
|
|
814
814
|
};
|
|
@@ -818,11 +818,11 @@ async function checkClientModuleImports2(context) {
|
|
|
818
818
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
819
819
|
file: relativeFile,
|
|
820
820
|
line,
|
|
821
|
-
message: `
|
|
822
|
-
details: "`src/api/**`
|
|
821
|
+
message: `importing \`${specifier}\` — \`${relApi}\` is a server-only API module`,
|
|
822
|
+
details: "`src/api/**` only runs on the server (HTTP endpoints) and never enters the client bundle.",
|
|
823
823
|
suggestions: [
|
|
824
|
-
"
|
|
825
|
-
"
|
|
824
|
+
"Move the operation into `*.server.ts` and call it via a serverFn",
|
|
825
|
+
"Do not import `src/api` files from client routes/components"
|
|
826
826
|
]
|
|
827
827
|
});
|
|
828
828
|
};
|
|
@@ -862,8 +862,8 @@ async function checkClientModuleImports2(context) {
|
|
|
862
862
|
message,
|
|
863
863
|
details,
|
|
864
864
|
suggestions: [
|
|
865
|
-
"
|
|
866
|
-
"
|
|
865
|
+
"Create a server function that returns the data you need, or",
|
|
866
|
+
"If the value is genuinely public, redefine the constant in a client-safe module (never move secret values)"
|
|
867
867
|
]
|
|
868
868
|
});
|
|
869
869
|
};
|
|
@@ -872,11 +872,11 @@ async function checkClientModuleImports2(context) {
|
|
|
872
872
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
873
873
|
file: relativeFile,
|
|
874
874
|
line,
|
|
875
|
-
message: `
|
|
876
|
-
details: "
|
|
875
|
+
message: `importing \`${specifier}\` in a client module`,
|
|
876
|
+
details: "Server-only modules may only be imported from *.server.ts.",
|
|
877
877
|
suggestions: [
|
|
878
|
-
"
|
|
879
|
-
"
|
|
878
|
+
"Move the operation into a serverFn, or",
|
|
879
|
+
"Remove the import"
|
|
880
880
|
]
|
|
881
881
|
});
|
|
882
882
|
};
|
|
@@ -970,11 +970,11 @@ async function checkClientModuleImports2(context) {
|
|
|
970
970
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
971
971
|
file: relativeFile,
|
|
972
972
|
line,
|
|
973
|
-
message: `
|
|
974
|
-
details: `\`${toRelative(projectRoot, resolvedTarget)}\`
|
|
973
|
+
message: `importing \`${name}\` — comes from \`${toRelative(projectRoot, serverFile)}\` (via a re-export chain)`,
|
|
974
|
+
details: `\`${toRelative(projectRoot, resolvedTarget)}\` re-exports a value from a server file; ` + "the client stub does not export it (previously a raw bundler `MISSING_EXPORT` error).",
|
|
975
975
|
suggestions: [
|
|
976
|
-
"
|
|
977
|
-
"
|
|
976
|
+
"Create a server function that returns the data you need, or",
|
|
977
|
+
"Redefine the public constant in a client-safe module (never move secret values)"
|
|
978
978
|
]
|
|
979
979
|
});
|
|
980
980
|
}
|
|
@@ -985,17 +985,17 @@ async function checkClientModuleImports2(context) {
|
|
|
985
985
|
const targetRelative = resolvedTarget === null ? rawSpecifier : toRelative(projectRoot, resolvedTarget);
|
|
986
986
|
if (statement.type === "ExportAllDeclaration") {
|
|
987
987
|
if (resolvedTarget === null) {
|
|
988
|
-
reject(line, `\`export *\`
|
|
988
|
+
reject(line, `\`export *\` from \`${targetRelative}\` cannot be resolved`, "Re-exports from `*.server.ts` must be statically resolvable.");
|
|
989
989
|
}
|
|
990
990
|
continue;
|
|
991
991
|
}
|
|
992
992
|
const specifiers = statement["specifiers"] ?? [];
|
|
993
993
|
for (const item of specifiers) {
|
|
994
994
|
if (item.type === "ImportDefaultSpecifier") {
|
|
995
|
-
reject(line, `
|
|
995
|
+
reject(line, `importing the default export from ${targetRelative}`, "Default exports from a server file must not cross to the client.");
|
|
996
996
|
}
|
|
997
997
|
if (item.type === "ImportNamespaceSpecifier") {
|
|
998
|
-
reject(line, `
|
|
998
|
+
reject(line, `importing the namespace (\`* as\`) from ${targetRelative}`, "Namespace imports from a server file must not cross to the client.");
|
|
999
999
|
}
|
|
1000
1000
|
const name = item["local"]?.["name"] ?? "";
|
|
1001
1001
|
const specifierKind = item["importKind"];
|
|
@@ -1004,7 +1004,7 @@ async function checkClientModuleImports2(context) {
|
|
|
1004
1004
|
continue;
|
|
1005
1005
|
}
|
|
1006
1006
|
if (name.length > 0 && !await isAllowedServerFnImport(resolvedTarget, specifier, name)) {
|
|
1007
|
-
reject(line, `
|
|
1007
|
+
reject(line, `importing \`${name}\` from ${targetRelative}`, "Server code must not appear in the client.\nOnly `serverFn` may cross.");
|
|
1008
1008
|
}
|
|
1009
1009
|
}
|
|
1010
1010
|
}
|
|
@@ -1044,11 +1044,11 @@ async function checkClientModuleImports2(context) {
|
|
|
1044
1044
|
code: "E_ENV_IN_CLIENT",
|
|
1045
1045
|
file: relativeFile,
|
|
1046
1046
|
line: node.loc?.start.line ?? 1,
|
|
1047
|
-
message: `
|
|
1048
|
-
details: "`env()`
|
|
1047
|
+
message: `calling \`${callText}\` in a client module`,
|
|
1048
|
+
details: "`env()` is only legal on the server.",
|
|
1049
1049
|
suggestions: [
|
|
1050
|
-
"
|
|
1051
|
-
"
|
|
1050
|
+
"Move the call into a serverFn, or",
|
|
1051
|
+
"Use import.meta.env for public values"
|
|
1052
1052
|
]
|
|
1053
1053
|
});
|
|
1054
1054
|
});
|
|
@@ -1097,7 +1097,7 @@ async function checkClientModuleImports2(context) {
|
|
|
1097
1097
|
continue;
|
|
1098
1098
|
}
|
|
1099
1099
|
const targetRelative = resolvedTarget === null ? request.text : toRelative(projectRoot, resolvedTarget);
|
|
1100
|
-
reject(request.node.loc?.start.line ?? 1, `
|
|
1100
|
+
reject(request.node.loc?.start.line ?? 1, `importing (dynamic) \`${request.text}\` from ${targetRelative}`, "The client must not dynamically import `*.server.ts`.");
|
|
1101
1101
|
}
|
|
1102
1102
|
walk(ast, (node) => {
|
|
1103
1103
|
if (node.type !== "CallExpression") {
|
|
@@ -1120,11 +1120,11 @@ async function checkClientModuleImports2(context) {
|
|
|
1120
1120
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
1121
1121
|
file: relativeFile,
|
|
1122
1122
|
line: node.loc?.start.line ?? 1,
|
|
1123
|
-
message: `
|
|
1124
|
-
details: "`import.meta.glob`
|
|
1123
|
+
message: `importing (glob) \`${pattern}\` in a client module`,
|
|
1124
|
+
details: "`import.meta.glob` patterns covering `*.server.ts` are forbidden in the client.",
|
|
1125
1125
|
suggestions: [
|
|
1126
|
-
"
|
|
1127
|
-
"
|
|
1126
|
+
"Statically import the `serverFn` from `*.server.ts` (that is all that may cross), or",
|
|
1127
|
+
"Move the data requirement into a server function"
|
|
1128
1128
|
]
|
|
1129
1129
|
});
|
|
1130
1130
|
}
|
|
@@ -1216,7 +1216,7 @@ function checkRouteModuleExports2(context) {
|
|
|
1216
1216
|
return;
|
|
1217
1217
|
}
|
|
1218
1218
|
const allowed = base === "_layout.tsx" ? ["default", "loader"] : base === "_error.tsx" || base === "_404.tsx" ? ["default"] : ["default", "loader", "meta", "prerender", "paths", "revalidate"];
|
|
1219
|
-
const allowedText = `
|
|
1219
|
+
const allowedText = `Only ${allowed.map((name) => `\`${name}\``).join(", ")} may be exported.`;
|
|
1220
1220
|
const relativeFile = toRelative(projectRoot, file);
|
|
1221
1221
|
const ast = parseModule(code, file);
|
|
1222
1222
|
const declarations = [];
|
|
@@ -1231,11 +1231,11 @@ function checkRouteModuleExports2(context) {
|
|
|
1231
1231
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
1232
1232
|
file: relativeFile,
|
|
1233
1233
|
line: statement.loc?.start.line ?? 1,
|
|
1234
|
-
message: "`export *`
|
|
1234
|
+
message: "`export *` is not allowed in route modules",
|
|
1235
1235
|
details: allowedText,
|
|
1236
1236
|
suggestions: [
|
|
1237
|
-
`
|
|
1238
|
-
"
|
|
1237
|
+
`Move the file contents outside ${toRelative(projectRoot, routesDir)}/, or`,
|
|
1238
|
+
"Remove the `export *`"
|
|
1239
1239
|
]
|
|
1240
1240
|
});
|
|
1241
1241
|
}
|
|
@@ -1262,11 +1262,11 @@ function checkRouteModuleExports2(context) {
|
|
|
1262
1262
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
1263
1263
|
file: relativeFile,
|
|
1264
1264
|
line: entry.line,
|
|
1265
|
-
message: `export \`${entry.name}\`
|
|
1265
|
+
message: `export \`${entry.name}\` is not allowed in route modules`,
|
|
1266
1266
|
details: allowedText,
|
|
1267
1267
|
suggestions: [
|
|
1268
|
-
`
|
|
1269
|
-
"
|
|
1268
|
+
`Move \`${entry.name}\` to a file outside ${toRelative(projectRoot, routesDir)}/, or`,
|
|
1269
|
+
"Remove the export"
|
|
1270
1270
|
]
|
|
1271
1271
|
});
|
|
1272
1272
|
}
|
|
@@ -1275,9 +1275,9 @@ function checkRouteModuleExports2(context) {
|
|
|
1275
1275
|
throw new MoonsError2({
|
|
1276
1276
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
1277
1277
|
file: relativeFile,
|
|
1278
|
-
message: "
|
|
1279
|
-
details: "
|
|
1280
|
-
suggestions: ["
|
|
1278
|
+
message: "route module must export `default`",
|
|
1279
|
+
details: "Every route file needs an `export default` React component.",
|
|
1280
|
+
suggestions: ["Add `export default function Page() { ... }`"]
|
|
1281
1281
|
});
|
|
1282
1282
|
}
|
|
1283
1283
|
}
|
|
@@ -1332,4 +1332,4 @@ function buildFnRegistry2(projectRoot, files) {
|
|
|
1332
1332
|
|
|
1333
1333
|
export { isServerFilePath2, isNonContractServerFile2, isServerSpecifier2, resolveServerSpecifierSync2, stripQuery2, analyzeServerFile2, serverFnExportNames2, renderServerFnStub2, injectServerFnMeta2, nonContractServerFileError2, checkClientModuleImports2, checkRouteModuleExports2, scanServerFiles2, buildFnRegistry2 };
|
|
1334
1334
|
|
|
1335
|
-
//# debugId=
|
|
1335
|
+
//# debugId=B9056013E70896ED64756E2164756E21
|