@moonsjs/vite 0.1.3 → 0.1.5
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/api.d.ts +8 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/{index-1sm9pvvd.js → index-1fnt137k.js} +106 -18
- package/dist/index-1fnt137k.js.map +14 -0
- package/dist/{index-3ec9vpek.js → index-e7qz0epf.js} +232 -24
- package/dist/index-e7qz0epf.js.map +11 -0
- package/dist/index.js +220 -19
- package/dist/index.js.map +5 -4
- package/dist/manifest.d.ts +6 -1
- package/dist/manifest.d.ts.map +1 -1
- package/dist/payload-scan.d.ts +18 -0
- package/dist/payload-scan.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/server/dev.d.ts +4 -0
- package/dist/server/dev.d.ts.map +1 -1
- package/dist/server/handler.d.ts +21 -1
- package/dist/server/handler.d.ts.map +1 -1
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +584 -28
- package/dist/server/index.js.map +10 -7
- package/dist/server/node-server.d.ts +4 -1
- package/dist/server/node-server.d.ts.map +1 -1
- package/dist/server/node.d.ts.map +1 -1
- package/dist/server/plugins.d.ts +26 -0
- package/dist/server/plugins.d.ts.map +1 -0
- package/dist/server/prerender.d.ts +28 -0
- package/dist/server/prerender.d.ts.map +1 -0
- package/dist/server/shell.d.ts +3 -3
- package/dist/server/shell.d.ts.map +1 -1
- package/dist/server/shutdown.d.ts +6 -0
- package/dist/server/shutdown.d.ts.map +1 -1
- package/dist/server/test-server.d.ts.map +1 -1
- package/dist/server-only.d.ts +57 -0
- package/dist/server-only.d.ts.map +1 -0
- package/dist/transform.d.ts +9 -1
- package/dist/transform.d.ts.map +1 -1
- package/dist/transform.js +1 -1
- package/dist/virtual-modules.d.ts +1 -0
- package/dist/virtual-modules.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +124 -0
- package/src/manifest.ts +42 -1
- package/src/payload-scan.ts +53 -0
- package/src/plugin.ts +137 -10
- package/src/server/dev.ts +48 -12
- package/src/server/handler.ts +373 -14
- package/src/server/index.ts +6 -0
- package/src/server/node-server.ts +70 -16
- package/src/server/node.ts +17 -0
- package/src/server/plugins.ts +85 -0
- package/src/server/prerender.ts +230 -0
- package/src/server/shell.ts +62 -8
- package/src/server/shutdown.ts +19 -2
- package/src/server/test-server.ts +2 -1
- package/src/server-only.ts +220 -0
- package/src/transform.ts +138 -8
- package/src/virtual-modules.ts +1 -0
- package/dist/index-1sm9pvvd.js.map +0 -14
- package/dist/index-3ec9vpek.js.map +0 -10
|
@@ -1,8 +1,124 @@
|
|
|
1
1
|
// src/transform.ts
|
|
2
|
-
import { MoonsError, computeFnHash, fnRegistryKey } from "@moonsjs/core";
|
|
2
|
+
import { MoonsError as MoonsError2, computeFnHash, fnRegistryKey } from "@moonsjs/core";
|
|
3
3
|
import { parse, parseExpression } from "@babel/parser";
|
|
4
|
-
import { existsSync, readdirSync, readFileSync, realpathSync } from "node:fs";
|
|
5
|
-
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2, realpathSync } from "node:fs";
|
|
5
|
+
import { dirname as dirname2, isAbsolute, join as join2, resolve } from "node:path";
|
|
6
|
+
|
|
7
|
+
// src/server-only.ts
|
|
8
|
+
import { MoonsError } from "@moonsjs/core";
|
|
9
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
var DEFAULT_SERVER_ONLY_PACKAGES = [
|
|
12
|
+
"pg",
|
|
13
|
+
"postgres",
|
|
14
|
+
"mysql",
|
|
15
|
+
"mysql2",
|
|
16
|
+
"sqlite3",
|
|
17
|
+
"better-sqlite3",
|
|
18
|
+
"drizzle-orm",
|
|
19
|
+
"@prisma/client",
|
|
20
|
+
"prisma",
|
|
21
|
+
"mongodb",
|
|
22
|
+
"mongoose",
|
|
23
|
+
"redis",
|
|
24
|
+
"ioredis",
|
|
25
|
+
"bcrypt",
|
|
26
|
+
"bcryptjs",
|
|
27
|
+
"argon2",
|
|
28
|
+
"jsonwebtoken",
|
|
29
|
+
"nodemailer",
|
|
30
|
+
"sharp",
|
|
31
|
+
"execa",
|
|
32
|
+
"cross-spawn",
|
|
33
|
+
"dotenv",
|
|
34
|
+
"knex",
|
|
35
|
+
"typeorm",
|
|
36
|
+
"sequelize",
|
|
37
|
+
"@libsql/client"
|
|
38
|
+
];
|
|
39
|
+
function tryReadPackageJson(dir) {
|
|
40
|
+
const candidate = join(dir, "package.json");
|
|
41
|
+
if (!existsSync(candidate)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const json = JSON.parse(readFileSync(candidate, "utf8"));
|
|
46
|
+
const moons = json.moons;
|
|
47
|
+
return {
|
|
48
|
+
dir,
|
|
49
|
+
name: typeof json.name === "string" ? json.name : "",
|
|
50
|
+
serverOnlyMarker: moons?.serverOnly === true
|
|
51
|
+
};
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function createServerOnlyClassifier(options = {}) {
|
|
57
|
+
const cache = options.cache ?? new Map;
|
|
58
|
+
const configured = new Set(options.configured ?? []);
|
|
59
|
+
const builtin = new Set(DEFAULT_SERVER_ONLY_PACKAGES);
|
|
60
|
+
const infoOf = (file) => {
|
|
61
|
+
let dir = dirname(file);
|
|
62
|
+
for (let depth = 0;depth < 64; depth += 1) {
|
|
63
|
+
if (cache.has(dir)) {
|
|
64
|
+
return cache.get(dir) ?? null;
|
|
65
|
+
}
|
|
66
|
+
const info = tryReadPackageJson(dir);
|
|
67
|
+
if (info !== null) {
|
|
68
|
+
cache.set(dir, info);
|
|
69
|
+
return info;
|
|
70
|
+
}
|
|
71
|
+
const parent = dirname(dir);
|
|
72
|
+
if (parent === dir) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
dir = parent;
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
check({ specifier: _specifier, resolvedFile, importerFile }) {
|
|
81
|
+
if (resolvedFile === null) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const info = infoOf(resolvedFile);
|
|
85
|
+
if (info === null || info.name.length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
const importer = infoOf(importerFile);
|
|
89
|
+
if (importer !== null && importer.dir === info.dir) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
if (builtin.has(info.name)) {
|
|
93
|
+
return { packageName: info.name, source: "builtin", packageDir: info.dir };
|
|
94
|
+
}
|
|
95
|
+
if (configured.has(info.name)) {
|
|
96
|
+
return { packageName: info.name, source: "config", packageDir: info.dir };
|
|
97
|
+
}
|
|
98
|
+
if (info.serverOnlyMarker) {
|
|
99
|
+
return { packageName: info.name, source: "marker", packageDir: info.dir };
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function serverOnlyImportError(input) {
|
|
106
|
+
const sourceLabel = input.source === "builtin" ? "Sumber kecocokan: daftar bawaan paket server-only framework." : input.source === "config" ? "Sumber kecocokan: `security.serverOnlyPackages` di moons.config.ts." : `Sumber kecocokan: marker \`"moons": { "serverOnly": true }\` di ${input.markerPath ?? "package.json"}.`;
|
|
107
|
+
return new MoonsError({
|
|
108
|
+
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
109
|
+
file: input.relativeFile,
|
|
110
|
+
line: input.line,
|
|
111
|
+
message: `mengimpor${input.dynamic === true ? " (dynamic)" : ""} \`${input.specifier}\` — paket server-only \`${input.packageName}\``,
|
|
112
|
+
details: `${sourceLabel}
|
|
113
|
+
Paket server-only tidak boleh masuk bundle client (PRD Addendum C).`,
|
|
114
|
+
suggestions: [
|
|
115
|
+
"Pindahkan operasi tersebut ke `*.server.ts` dan panggil lewat serverFn",
|
|
116
|
+
"Atau ganti/hapus import tersebut di modul client"
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/transform.ts
|
|
6
122
|
var SERVER_SPECIFIER = /\.server(\.(ts|tsx|js|jsx|mts|cts|mjs|cjs))?$/i;
|
|
7
123
|
var CONTRACT_SERVER_FILE = /\.server\.(ts|tsx)$/i;
|
|
8
124
|
var NON_CONTRACT_SERVER_FILE = /\.server\.(js|jsx|mts|cts|mjs|cjs)$/i;
|
|
@@ -19,12 +135,12 @@ function resolveServerSpecifierSync2(importerFile, specifier) {
|
|
|
19
135
|
if (!isServerSpecifier2(specifier)) {
|
|
20
136
|
return null;
|
|
21
137
|
}
|
|
22
|
-
const base = specifier.startsWith(".") ? resolve(
|
|
138
|
+
const base = specifier.startsWith(".") ? resolve(dirname2(importerFile), specifier) : isAbsolute(specifier) ? specifier : null;
|
|
23
139
|
if (base === null) {
|
|
24
140
|
return null;
|
|
25
141
|
}
|
|
26
142
|
for (const candidate of [base, `${base}.ts`, `${base}.tsx`]) {
|
|
27
|
-
if (
|
|
143
|
+
if (existsSync2(candidate)) {
|
|
28
144
|
return candidate;
|
|
29
145
|
}
|
|
30
146
|
}
|
|
@@ -68,6 +184,17 @@ function topLevelStatements(ast) {
|
|
|
68
184
|
const program = ast["program"];
|
|
69
185
|
return program?.body ?? [];
|
|
70
186
|
}
|
|
187
|
+
function isTypeOnlyImportExport(statement) {
|
|
188
|
+
const declarationKind = statement["importKind"] ?? statement["exportKind"];
|
|
189
|
+
if (declarationKind === "type") {
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
const specifiers = statement["specifiers"] ?? [];
|
|
193
|
+
if (specifiers.length === 0) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return specifiers.every((item) => (item["importKind"] ?? item["exportKind"]) === "type");
|
|
197
|
+
}
|
|
71
198
|
function keyName(node) {
|
|
72
199
|
const key = node;
|
|
73
200
|
if (key?.type === "Identifier") {
|
|
@@ -359,16 +486,27 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
359
486
|
if (reference.length === 0 || !localNames.has(reference)) {
|
|
360
487
|
continue;
|
|
361
488
|
}
|
|
362
|
-
throw new
|
|
489
|
+
throw new MoonsError2({
|
|
363
490
|
code: "E_SCHEMA_LOCAL_REF",
|
|
364
491
|
file: filename,
|
|
365
492
|
line: fn.line,
|
|
366
493
|
annotation: fn.name,
|
|
367
494
|
message: `schema ${kind} serverFn \`${fn.name}\` merujuk deklarasi lokal \`${reference}\``,
|
|
368
|
-
details:
|
|
495
|
+
details: `\`${reference}\` dibuang dari stub client (PRD §12.2/§12.3), sehingga nilainya \`undefined\` di browser (crash hydration).
|
|
496
|
+
|
|
497
|
+
` + `Sebelum (ditolak):
|
|
498
|
+
` + ` const ${reference} = z.object({ … }); // deklarasi lokal di file yang sama
|
|
499
|
+
` + ` export const ${fn.name} = serverFn({ ${kind}: ${reference}, … });
|
|
500
|
+
|
|
501
|
+
` + `Sesudah (pilih salah satu):
|
|
502
|
+
` + ` // a) inline schema di argumen
|
|
503
|
+
` + ` export const ${fn.name} = serverFn({ ${kind}: z.object({ … }), … });
|
|
504
|
+
` + ` // b) pindahkan deklarasi ke modul bersama yang boleh masuk client (mis. src/shared/schemas.ts)
|
|
505
|
+
` + ` import { ${reference} } from "../shared/schemas";`,
|
|
369
506
|
suggestions: [
|
|
370
|
-
|
|
371
|
-
|
|
507
|
+
`Inline schema di argumen \`serverFn({ ${kind}: … })\`, atau`,
|
|
508
|
+
`Pindahkan \`${reference}\` ke modul bersama (mis. \`src/shared/schemas.ts\`) lalu impor dari sana`,
|
|
509
|
+
"Jangan memindahkan nilai rahasia ke shared — schema harus client-safe (zod/Standard Schema)"
|
|
372
510
|
]
|
|
373
511
|
});
|
|
374
512
|
}
|
|
@@ -378,7 +516,7 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
378
516
|
for (const reExport of analysis.reExports) {
|
|
379
517
|
const target = dependencies.analyzeSpecifier(filename, reExport.source);
|
|
380
518
|
if (target === null) {
|
|
381
|
-
throw new
|
|
519
|
+
throw new MoonsError2({
|
|
382
520
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
383
521
|
file: filename,
|
|
384
522
|
message: `tidak bisa me-resolve \`${reExport.source}\` untuk re-export`,
|
|
@@ -396,7 +534,7 @@ function renderServerFnStub2(source, filename, analysis, dependencies) {
|
|
|
396
534
|
for (const specifier of analysis.exportAllFrom) {
|
|
397
535
|
const target = dependencies.analyzeSpecifier(filename, specifier);
|
|
398
536
|
if (target === null) {
|
|
399
|
-
throw new
|
|
537
|
+
throw new MoonsError2({
|
|
400
538
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
401
539
|
file: filename,
|
|
402
540
|
message: `\`export *\` dari \`${specifier}\` tidak bisa di-resolve`,
|
|
@@ -464,7 +602,7 @@ async function serverFnExportNamesAsync(analysis, analyzeSpecifier, seen = new S
|
|
|
464
602
|
return names;
|
|
465
603
|
}
|
|
466
604
|
function nonContractServerFileError2(file, projectRoot) {
|
|
467
|
-
return new
|
|
605
|
+
return new MoonsError2({
|
|
468
606
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
469
607
|
file: toRelative(projectRoot, file),
|
|
470
608
|
message: "file server memakai ekstensi di luar kontrak §12",
|
|
@@ -479,6 +617,32 @@ async function checkClientModuleImports2(context) {
|
|
|
479
617
|
const { file, code, projectRoot, resolve, analyze } = context;
|
|
480
618
|
const ast = parseModule(code, file);
|
|
481
619
|
const relativeFile = toRelative(projectRoot, file);
|
|
620
|
+
const serverOnly = createServerOnlyClassifier({
|
|
621
|
+
configured: context.serverOnlyPackages ?? [],
|
|
622
|
+
...context.packageCache === undefined ? {} : { cache: context.packageCache }
|
|
623
|
+
});
|
|
624
|
+
let apiDirReal = null;
|
|
625
|
+
if (context.apiDir !== undefined && context.apiDir.length > 0) {
|
|
626
|
+
try {
|
|
627
|
+
apiDirReal = realpathSync(context.apiDir);
|
|
628
|
+
} catch {
|
|
629
|
+
apiDirReal = context.apiDir;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
const rejectApiImport = (line, specifier, resolvedTarget) => {
|
|
633
|
+
const relApi = toRelative(projectRoot, resolvedTarget);
|
|
634
|
+
throw new MoonsError2({
|
|
635
|
+
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
636
|
+
file: relativeFile,
|
|
637
|
+
line,
|
|
638
|
+
message: `mengimpor \`${specifier}\` — \`${relApi}\` adalah modul API server-only`,
|
|
639
|
+
details: "`src/api/**` hanya berjalan di server (endpoint HTTP) dan tidak pernah masuk bundle client (PRD Addendum D.1).",
|
|
640
|
+
suggestions: [
|
|
641
|
+
"Pindahkan operasi tersebut ke `*.server.ts` dan panggil lewat serverFn",
|
|
642
|
+
"Jangan mengimpor file `src/api` dari route/komponen client"
|
|
643
|
+
]
|
|
644
|
+
});
|
|
645
|
+
};
|
|
482
646
|
const resolveSafe = async (specifier, importer) => {
|
|
483
647
|
try {
|
|
484
648
|
const result = await resolve(specifier, importer);
|
|
@@ -508,7 +672,7 @@ async function checkClientModuleImports2(context) {
|
|
|
508
672
|
return names.has(name);
|
|
509
673
|
};
|
|
510
674
|
const reject = (line, message, details) => {
|
|
511
|
-
throw new
|
|
675
|
+
throw new MoonsError2({
|
|
512
676
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
513
677
|
file: relativeFile,
|
|
514
678
|
line,
|
|
@@ -521,7 +685,7 @@ async function checkClientModuleImports2(context) {
|
|
|
521
685
|
});
|
|
522
686
|
};
|
|
523
687
|
const rejectForbidden = (line, specifier) => {
|
|
524
|
-
throw new
|
|
688
|
+
throw new MoonsError2({
|
|
525
689
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
526
690
|
file: relativeFile,
|
|
527
691
|
line,
|
|
@@ -542,10 +706,31 @@ async function checkClientModuleImports2(context) {
|
|
|
542
706
|
const rawSpecifier = sourceNode["value"];
|
|
543
707
|
const specifier = stripQuery2(rawSpecifier);
|
|
544
708
|
const line = statement.loc?.start.line ?? 1;
|
|
709
|
+
const typeOnly = isTypeOnlyImportExport(statement);
|
|
545
710
|
if (specifier.startsWith("node:") || specifier.startsWith("bun:")) {
|
|
546
711
|
rejectForbidden(line, specifier);
|
|
547
712
|
}
|
|
548
713
|
const resolvedTarget = await resolveSafe(specifier, file);
|
|
714
|
+
if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {
|
|
715
|
+
rejectApiImport(line, rawSpecifier, resolvedTarget);
|
|
716
|
+
}
|
|
717
|
+
if (!typeOnly) {
|
|
718
|
+
const match = serverOnly.check({
|
|
719
|
+
specifier,
|
|
720
|
+
resolvedFile: resolvedTarget,
|
|
721
|
+
importerFile: file
|
|
722
|
+
});
|
|
723
|
+
if (match !== null) {
|
|
724
|
+
throw serverOnlyImportError({
|
|
725
|
+
relativeFile,
|
|
726
|
+
line,
|
|
727
|
+
specifier: rawSpecifier,
|
|
728
|
+
packageName: match.packageName,
|
|
729
|
+
source: match.source,
|
|
730
|
+
...match.source === "marker" ? { markerPath: toRelative(projectRoot, join2(match.packageDir, "package.json")) } : {}
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
}
|
|
549
734
|
if (resolvedTarget !== null && isNonContractServerFile2(resolvedTarget)) {
|
|
550
735
|
throw nonContractServerFileError2(resolvedTarget, projectRoot);
|
|
551
736
|
}
|
|
@@ -611,7 +796,7 @@ async function checkClientModuleImports2(context) {
|
|
|
611
796
|
return;
|
|
612
797
|
}
|
|
613
798
|
const callText = code.slice(node.start ?? 0, node.end ?? 0).replace(/\s+/g, " ").slice(0, 80);
|
|
614
|
-
throw new
|
|
799
|
+
throw new MoonsError2({
|
|
615
800
|
code: "E_ENV_IN_CLIENT",
|
|
616
801
|
file: relativeFile,
|
|
617
802
|
line: node.loc?.start.line ?? 1,
|
|
@@ -640,6 +825,25 @@ async function checkClientModuleImports2(context) {
|
|
|
640
825
|
}
|
|
641
826
|
const specifier = stripQuery2(request.text);
|
|
642
827
|
const resolvedTarget = await resolveSafe(specifier, file);
|
|
828
|
+
if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {
|
|
829
|
+
rejectApiImport(request.node.loc?.start.line ?? 1, request.text, resolvedTarget);
|
|
830
|
+
}
|
|
831
|
+
const match = serverOnly.check({
|
|
832
|
+
specifier,
|
|
833
|
+
resolvedFile: resolvedTarget,
|
|
834
|
+
importerFile: file
|
|
835
|
+
});
|
|
836
|
+
if (match !== null) {
|
|
837
|
+
throw serverOnlyImportError({
|
|
838
|
+
relativeFile,
|
|
839
|
+
line: request.node.loc?.start.line ?? 1,
|
|
840
|
+
specifier: request.text,
|
|
841
|
+
packageName: match.packageName,
|
|
842
|
+
source: match.source,
|
|
843
|
+
dynamic: true,
|
|
844
|
+
...match.source === "marker" ? { markerPath: toRelative(projectRoot, join2(match.packageDir, "package.json")) } : {}
|
|
845
|
+
});
|
|
846
|
+
}
|
|
643
847
|
if (resolvedTarget !== null && isNonContractServerFile2(resolvedTarget)) {
|
|
644
848
|
throw nonContractServerFileError2(resolvedTarget, projectRoot);
|
|
645
849
|
}
|
|
@@ -668,7 +872,7 @@ async function checkClientModuleImports2(context) {
|
|
|
668
872
|
if (!isServerSpecifier2(pattern)) {
|
|
669
873
|
continue;
|
|
670
874
|
}
|
|
671
|
-
throw new
|
|
875
|
+
throw new MoonsError2({
|
|
672
876
|
code: "E_SERVER_IMPORT_IN_CLIENT",
|
|
673
877
|
file: relativeFile,
|
|
674
878
|
line: node.loc?.start.line ?? 1,
|
|
@@ -754,6 +958,10 @@ function toRelative(projectRoot, file) {
|
|
|
754
958
|
const relative = file.startsWith(projectRoot) ? file.slice(projectRoot.length).replace(/^[/\\]/, "") : file;
|
|
755
959
|
return relative.split("\\").join("/");
|
|
756
960
|
}
|
|
961
|
+
function isInsideDir(file, dir) {
|
|
962
|
+
const normalized = dir.endsWith("/") ? dir : `${dir}/`;
|
|
963
|
+
return file === dir || file.startsWith(normalized);
|
|
964
|
+
}
|
|
757
965
|
function checkRouteModuleExports2(context) {
|
|
758
966
|
const { file, code, routesDir, projectRoot } = context;
|
|
759
967
|
if (!file.startsWith(routesDir) || !file.endsWith(".tsx")) {
|
|
@@ -763,7 +971,7 @@ function checkRouteModuleExports2(context) {
|
|
|
763
971
|
if (base.startsWith("_") && base !== "_layout.tsx" && base !== "_error.tsx" && base !== "_404.tsx") {
|
|
764
972
|
return;
|
|
765
973
|
}
|
|
766
|
-
const allowed = base === "_layout.tsx" ? ["default", "loader"] : base === "_error.tsx" || base === "_404.tsx" ? ["default"] : ["default", "loader", "meta"];
|
|
974
|
+
const allowed = base === "_layout.tsx" ? ["default", "loader"] : base === "_error.tsx" || base === "_404.tsx" ? ["default"] : ["default", "loader", "meta", "prerender", "paths"];
|
|
767
975
|
const allowedText = `Hanya ${allowed.map((name) => `\`${name}\``).join(", ")} yang boleh di-export.`;
|
|
768
976
|
const relativeFile = toRelative(projectRoot, file);
|
|
769
977
|
const ast = parseModule(code, file);
|
|
@@ -775,7 +983,7 @@ function checkRouteModuleExports2(context) {
|
|
|
775
983
|
continue;
|
|
776
984
|
}
|
|
777
985
|
if (statement.type === "ExportAllDeclaration") {
|
|
778
|
-
throw new
|
|
986
|
+
throw new MoonsError2({
|
|
779
987
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
780
988
|
file: relativeFile,
|
|
781
989
|
line: statement.loc?.start.line ?? 1,
|
|
@@ -806,7 +1014,7 @@ function checkRouteModuleExports2(context) {
|
|
|
806
1014
|
}
|
|
807
1015
|
for (const entry of declarations) {
|
|
808
1016
|
if (!allowed.includes(entry.name)) {
|
|
809
|
-
throw new
|
|
1017
|
+
throw new MoonsError2({
|
|
810
1018
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
811
1019
|
file: relativeFile,
|
|
812
1020
|
line: entry.line,
|
|
@@ -820,7 +1028,7 @@ function checkRouteModuleExports2(context) {
|
|
|
820
1028
|
}
|
|
821
1029
|
}
|
|
822
1030
|
if (!hasDefault) {
|
|
823
|
-
throw new
|
|
1031
|
+
throw new MoonsError2({
|
|
824
1032
|
code: "E_ROUTE_EXPORT_INVALID",
|
|
825
1033
|
file: relativeFile,
|
|
826
1034
|
message: "modul route wajib mengekspor `default`",
|
|
@@ -852,9 +1060,9 @@ function scanServerFiles2(projectRoot) {
|
|
|
852
1060
|
if (excluded.has(entry.name)) {
|
|
853
1061
|
continue;
|
|
854
1062
|
}
|
|
855
|
-
walkDir(
|
|
1063
|
+
walkDir(join2(dir, entry.name));
|
|
856
1064
|
} else if (entry.isFile() && isServerFilePath2(entry.name)) {
|
|
857
|
-
result.push(
|
|
1065
|
+
result.push(join2(dir, entry.name));
|
|
858
1066
|
}
|
|
859
1067
|
}
|
|
860
1068
|
};
|
|
@@ -866,7 +1074,7 @@ function buildFnRegistry2(projectRoot, files) {
|
|
|
866
1074
|
for (const file of files) {
|
|
867
1075
|
let source;
|
|
868
1076
|
try {
|
|
869
|
-
source =
|
|
1077
|
+
source = readFileSync2(file, "utf8");
|
|
870
1078
|
} catch {
|
|
871
1079
|
continue;
|
|
872
1080
|
}
|
|
@@ -880,4 +1088,4 @@ function buildFnRegistry2(projectRoot, files) {
|
|
|
880
1088
|
|
|
881
1089
|
export { isServerFilePath2, isNonContractServerFile2, isServerSpecifier2, resolveServerSpecifierSync2, stripQuery2, analyzeServerFile2, serverFnExportNames2, renderServerFnStub2, injectServerFnMeta2, nonContractServerFileError2, checkClientModuleImports2, checkRouteModuleExports2, scanServerFiles2, buildFnRegistry2 };
|
|
882
1090
|
|
|
883
|
-
//# debugId=
|
|
1091
|
+
//# debugId=72CC55CAEBB11FDE64756E2164756E21
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/transform.ts", "../src/server-only.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { MoonsError, computeFnHash, fnRegistryKey } from \"@moonsjs/core\";\nimport { parse, parseExpression } from \"@babel/parser\";\nimport { existsSync, readdirSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport {\n createServerOnlyClassifier,\n serverOnlyImportError,\n type PackageJsonInfo,\n} from \"./server-only\";\n\n/**\n * Spec §12: analisis `.server.ts` + stub client + injeksi meta server +\n * penolakan import (E_SERVER_IMPORT_IN_CLIENT / E_FORBIDDEN_SERVER_IMPORT).\n */\n\nexport interface ServerFnInfo {\n name: string;\n hash: string;\n line: number;\n input: { start: number; end: number };\n output: { start: number; end: number };\n objectStart: number;\n}\n\nexport interface ServerFileAnalysis {\n /** Absolute path. */\n file: string;\n serverFns: ServerFnInfo[];\n /** Semua nama export top-level (langsung). */\n exportNames: string[];\n /** Pernyataan `export { X as Y } from \"./z.server\"` (untuk resolusi re-export). */\n reExports: Array<{ source: string; names: Array<{ local: string; exported: string }> }>;\n /** `export * from \"./z.server\"`. */\n exportAllFrom: string[];\n}\n\ninterface AstNode {\n type: string;\n start: number | null;\n end: number | null;\n loc?: { start: { line: number } } | null;\n [key: string]: unknown;\n}\n\nconst SERVER_SPECIFIER = /\\.server(\\.(ts|tsx|js|jsx|mts|cts|mjs|cjs))?$/i;\nconst CONTRACT_SERVER_FILE = /\\.server\\.(ts|tsx)$/i;\nconst NON_CONTRACT_SERVER_FILE = /\\.server\\.(js|jsx|mts|cts|mjs|cjs)$/i;\n\nexport function isServerFilePath(path: string): boolean {\n return CONTRACT_SERVER_FILE.test(stripQuery(path));\n}\n\n/** File server dengan ekstensi di luar kontrak §12 (tidak bisa di-stub). */\nexport function isNonContractServerFile(path: string): boolean {\n return NON_CONTRACT_SERVER_FILE.test(stripQuery(path));\n}\n\nexport function isServerSpecifier(specifier: string): boolean {\n return SERVER_SPECIFIER.test(specifier);\n}\n\n/**\n * Resolusi sinkron untuk specifier `*.server` (relatif/absolut).\n * Import alias/virtual untuk file server tidak didukung — tidak dibutuhkan app.\n */\nexport function resolveServerSpecifierSync(importerFile: string, specifier: string): string | null {\n if (!isServerSpecifier(specifier)) {\n return null;\n }\n const base = specifier.startsWith(\".\")\n ? resolve(dirname(importerFile), specifier)\n : isAbsolute(specifier)\n ? specifier\n : null;\n if (base === null) {\n return null;\n }\n for (const candidate of [base, `${base}.ts`, `${base}.tsx`]) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n return null;\n}\n\nexport function stripQuery(id: string): string {\n const queryIndex = id.indexOf(\"?\");\n return queryIndex === -1 ? id : id.slice(0, queryIndex);\n}\n\nfunction parseModule(code: string, filename: string): AstNode {\n return parse(code, {\n sourceType: \"module\",\n plugins: filename.endsWith(\".tsx\") ? [\"typescript\", \"jsx\"] : [\"typescript\"],\n errorRecovery: false,\n }) as unknown as AstNode;\n}\n\nfunction walk(\n node: unknown,\n visit: (node: AstNode, ancestors: AstNode[]) => void,\n ancestors: AstNode[] = [],\n): void {\n if (node === null || typeof node !== \"object\") {\n return;\n }\n if (Array.isArray(node)) {\n for (const item of node) {\n walk(item, visit, ancestors);\n }\n return;\n }\n const candidate = node as AstNode;\n if (typeof candidate.type !== \"string\" || typeof candidate.start !== \"number\") {\n return;\n }\n visit(candidate, ancestors);\n const nextAncestors = [...ancestors, candidate];\n for (const key of Object.keys(candidate)) {\n if (key === \"loc\" || key === \"start\" || key === \"end\" || key === \"extra\") {\n continue;\n }\n walk(candidate[key], visit, nextAncestors);\n }\n}\n\nfunction topLevelStatements(ast: AstNode): AstNode[] {\n const program = ast[\"program\"] as { body?: AstNode[] } | undefined;\n return program?.body ?? [];\n}\n\n/**\n * Type-only import/export (Addendum C.1): `import type ...`, `export type ...`,\n * atau seluruh specifier bertanda `type`. Terhapus saat kompilasi sehingga\n * dikecualikan dari gate paket server-only. `export * from` = bernilai.\n */\nfunction isTypeOnlyImportExport(statement: AstNode): boolean {\n const declarationKind = (statement[\"importKind\"] ?? statement[\"exportKind\"]) as\n | string\n | undefined;\n if (declarationKind === \"type\") {\n return true;\n }\n const specifiers = (statement[\"specifiers\"] ?? []) as AstNode[];\n if (specifiers.length === 0) {\n return false;\n }\n return specifiers.every(\n (item) => ((item[\"importKind\"] ?? item[\"exportKind\"]) as string | undefined) === \"type\",\n );\n}\n\nfunction keyName(node: unknown): string | null {\n const key = node as AstNode | undefined;\n if (key?.type === \"Identifier\") {\n return key[\"name\"] as string;\n }\n if (key?.type === \"StringLiteral\") {\n return key[\"value\"] as string;\n }\n return null;\n}\n\nfunction extractServerFnInit(init: unknown): {\n input: { start: number; end: number };\n output: { start: number; end: number };\n line: number;\n objectStart: number;\n} | null {\n const call = init as AstNode | undefined;\n if (call?.type !== \"CallExpression\") {\n return null;\n }\n const callee = call[\"callee\"] as AstNode | undefined;\n if (callee?.type !== \"Identifier\" || callee[\"name\"] !== \"serverFn\") {\n return null;\n }\n const args = (call[\"arguments\"] ?? []) as AstNode[];\n const first = args[0];\n if (first?.type !== \"ObjectExpression\") {\n return null;\n }\n\n const properties = new Map<string, AstNode>();\n for (const property of (first[\"properties\"] ?? []) as AstNode[]) {\n if (property.type !== \"ObjectProperty\") {\n continue;\n }\n const name = keyName(property[\"key\"]);\n if (name !== null) {\n properties.set(name, property);\n }\n }\n\n const input = properties.get(\"input\")?.[\"value\"] as AstNode | undefined;\n const output = properties.get(\"output\")?.[\"value\"] as AstNode | undefined;\n if (\n input?.start == null ||\n input.end == null ||\n output?.start == null ||\n output.end == null\n ) {\n return null;\n }\n\n return {\n input: { start: input.start, end: input.end },\n output: { start: output.start, end: output.end },\n line: call.loc?.start.line ?? 1,\n objectStart: first.start ?? 0,\n };\n}\n\nexport function analyzeServerFile(\n source: string,\n filename: string,\n projectRoot: string,\n): ServerFileAnalysis {\n const ast = parseModule(source, filename);\n const serverFns: ServerFnInfo[] = [];\n const exportNames: string[] = [];\n const reExports: ServerFileAnalysis[\"reExports\"] = [];\n const exportAllFrom: string[] = [];\n\n for (const statement of topLevelStatements(ast)) {\n if (statement.type === \"ExportNamedDeclaration\") {\n const declaration = statement[\"declaration\"] as AstNode | null | undefined;\n\n if (declaration?.type === \"VariableDeclaration\") {\n for (const declarator of (declaration[\"declarations\"] ?? []) as AstNode[]) {\n const id = declarator[\"id\"] as AstNode | undefined;\n if (id?.type !== \"Identifier\") {\n continue;\n }\n const name = id[\"name\"] as string;\n exportNames.push(name);\n const info = extractServerFnInit(declarator[\"init\"]);\n if (info !== null) {\n serverFns.push({\n name,\n hash: computeFnHash(projectRoot, filename, name),\n line: info.line,\n input: info.input,\n output: info.output,\n objectStart: info.objectStart,\n });\n }\n }\n } else if (declaration?.type === \"FunctionDeclaration\") {\n const id = declaration[\"id\"] as AstNode | undefined;\n if (id?.type === \"Identifier\") {\n exportNames.push(id[\"name\"] as string);\n }\n }\n\n for (const specifier of (statement[\"specifiers\"] ?? []) as AstNode[]) {\n const exported = specifier[\"exported\"] as AstNode | undefined;\n if (exported?.type === \"Identifier\") {\n exportNames.push(exported[\"name\"] as string);\n }\n }\n\n const sourceNode = statement[\"source\"] as AstNode | undefined;\n if (sourceNode?.type === \"StringLiteral\" && isServerSpecifier(sourceNode[\"value\"] as string)) {\n reExports.push({\n source: sourceNode[\"value\"] as string,\n names: ((statement[\"specifiers\"] ?? []) as AstNode[]).map((specifier) => ({\n local: ((specifier[\"local\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\",\n exported: (((specifier[\"exported\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\"),\n })),\n });\n }\n } else if (statement.type === \"ExportDefaultDeclaration\") {\n exportNames.push(\"default\");\n } else if (statement.type === \"ExportAllDeclaration\") {\n const sourceNode = statement[\"source\"] as AstNode | undefined;\n if (sourceNode?.type === \"StringLiteral\" && isServerSpecifier(sourceNode[\"value\"] as string)) {\n exportAllFrom.push(sourceNode[\"value\"] as string);\n }\n }\n }\n\n return { file: filename, serverFns, exportNames, reExports, exportAllFrom };\n}\n\n/** Nama-nama yang diekspor sebagai serverFn stub dari file (langsung atau via re-export). */\nexport function serverFnExportNames(\n analysis: ServerFileAnalysis,\n analyzeTarget: (specifier: string) => ServerFileAnalysis | null,\n seen = new Set<string>(),\n): Set<string> {\n const names = new Set(analysis.serverFns.map((fn) => fn.name));\n\n for (const reExport of analysis.reExports) {\n const target = analyzeTarget(reExport.source);\n if (target === null || seen.has(reExport.source)) {\n continue;\n }\n seen.add(reExport.source);\n const targetNames = serverFnExportNames(target, analyzeTarget, seen);\n for (const { local, exported } of reExport.names) {\n if (local === \"*\" || targetNames.has(local)) {\n names.add(exported);\n }\n }\n }\n\n for (const specifier of analysis.exportAllFrom) {\n const target = analyzeTarget(specifier);\n if (target === null || seen.has(specifier)) {\n continue;\n }\n seen.add(specifier);\n for (const name of serverFnExportNames(target, analyzeTarget, seen)) {\n names.add(name);\n }\n }\n\n return names;\n}\n\nfunction collectRetainedText(source: string, analysis: ServerFileAnalysis): string {\n return analysis.serverFns\n .map((fn) => `${source.slice(fn.input.start, fn.input.end)}\\n${source.slice(fn.output.start, fn.output.end)}`)\n .join(\"\\n\");\n}\n\nfunction isUsed(name: string, retainedText: string): boolean {\n return new RegExp(`(^|[^\\\\w$])${escapeRegExp(name)}([^\\\\w$]|$)`).test(retainedText);\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction collectPatternNames(node: AstNode | undefined, into: Set<string>): void {\n if (node === undefined) {\n return;\n }\n switch (node.type) {\n case \"Identifier\": {\n const name = node[\"name\"] as string | undefined;\n if (name !== undefined) {\n into.add(name);\n }\n return;\n }\n case \"ObjectPattern\":\n for (const property of (node[\"properties\"] ?? []) as AstNode[]) {\n collectPatternNames(\n (property.type === \"RestElement\" ? property[\"argument\"] : property[\"value\"]) as\n | AstNode\n | undefined,\n into,\n );\n }\n return;\n case \"ArrayPattern\":\n for (const element of (node[\"elements\"] ?? []) as AstNode[]) {\n collectPatternNames(element, into);\n }\n return;\n case \"AssignmentPattern\":\n collectPatternNames(node[\"left\"] as AstNode | undefined, into);\n return;\n case \"RestElement\":\n collectPatternNames(node[\"argument\"] as AstNode | undefined, into);\n return;\n default:\n return;\n }\n}\n\n/** Nama deklarasi nilai top-level (bukan import) — yang DIBUANG dari stub §12.3. */\nfunction localTopLevelNames(ast: AstNode): Set<string> {\n const names = new Set<string>();\n const declare = (decl: AstNode | null | undefined): void => {\n if (decl === undefined || decl === null) {\n return;\n }\n if (decl.type === \"VariableDeclaration\") {\n for (const declarator of (decl[\"declarations\"] ?? []) as AstNode[]) {\n collectPatternNames(declarator[\"id\"] as AstNode | undefined, names);\n }\n return;\n }\n if (decl.type === \"FunctionDeclaration\" || decl.type === \"ClassDeclaration\") {\n const name = ((decl[\"id\"] as AstNode | undefined)?.[\"name\"] as string | undefined) ?? \"\";\n if (name.length > 0) {\n names.add(name);\n }\n }\n };\n\n for (const statement of topLevelStatements(ast)) {\n if (statement.type === \"ExportNamedDeclaration\" || statement.type === \"ExportDefaultDeclaration\") {\n declare(statement[\"declaration\"] as AstNode | null | undefined);\n } else {\n declare(statement);\n }\n }\n return names;\n}\n\n/** Identifier posisi-nilai yang direferensikan di dalam ekspresi (key/member di-skip). */\nfunction referencedIdentifiers(expression: string, filename: string): Set<string> {\n const ast = parseExpression(expression, {\n plugins: filename.endsWith(\".tsx\") ? [\"typescript\", \"jsx\"] : [\"typescript\"],\n }) as unknown as AstNode;\n const names = new Set<string>();\n\n walk(ast, (node, ancestors) => {\n if (node.type !== \"Identifier\") {\n return;\n }\n const parent = ancestors[ancestors.length - 1];\n if (parent !== undefined) {\n const parentType = parent.type as string;\n const nonComputed = parent[\"computed\"] !== true;\n if (\n nonComputed &&\n (parentType === \"MemberExpression\" || parentType === \"OptionalMemberExpression\") &&\n parent[\"property\"] === node\n ) {\n return;\n }\n if (\n nonComputed &&\n (parentType === \"ObjectProperty\" ||\n parentType === \"ObjectMethod\" ||\n parentType === \"ClassProperty\" ||\n parentType === \"TSPropertySignature\") &&\n parent[\"key\"] === node\n ) {\n return;\n }\n }\n names.add((node[\"name\"] as string | undefined) ?? \"\");\n });\n\n return names;\n}\n\nexport interface StubDependencies {\n /** Resolve specifier relatif file sumber → analysis (null bila tidak bisa). */\n analyzeSpecifier: (sourceFile: string, specifier: string) => ServerFileAnalysis | null;\n}\n\nexport interface RenderStubResult {\n code: string;\n /** Specifier server file yang di-referensikan (untuk keperluan cache/diagnostik). */\n referenced: string[];\n}\n\n/**\n * Bangun stub client §12.2/§12.3 dari sumber `.server.ts`:\n * hanya import yang dipakai schema + `__moons_createStub` per serverFn.\n */\nexport function renderServerFnStub(\n source: string,\n filename: string,\n analysis: ServerFileAnalysis,\n dependencies: StubDependencies,\n): RenderStubResult {\n const ast = parseModule(source, filename);\n const retainedText = collectRetainedText(source, analysis);\n const localNames = localTopLevelNames(ast);\n const importLines: string[] = [];\n const referenced: string[] = [];\n let needsCreateStub = analysis.serverFns.length > 0;\n\n for (const statement of topLevelStatements(ast)) {\n if (statement.type !== \"ImportDeclaration\") {\n continue;\n }\n const sourceNode = statement[\"source\"] as AstNode;\n const specifier = sourceNode[\"value\"] as string;\n\n if (/^@moons\\/server(\\/|$)/.test(specifier)) {\n continue; // serverFn/env tidak dibawa ke client (§12.2)\n }\n if (specifier.startsWith(\"node:\") || specifier.startsWith(\"bun:\")) {\n continue; // import server-only dibuang\n }\n\n const specifiers = (statement[\"specifiers\"] ?? []) as AstNode[];\n const kept: AstNode[] = [];\n\n if (isServerSpecifier(specifier)) {\n referenced.push(specifier);\n for (const item of specifiers) {\n if (item.type === \"ImportDefaultSpecifier\" || item.type === \"ImportNamespaceSpecifier\") {\n continue; // default / * as dari *.server → dibuang (§12.2)\n }\n const local = ((item[\"local\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\";\n if (local.length > 0 && isUsed(local, retainedText)) {\n kept.push(item);\n }\n }\n } else {\n for (const item of specifiers) {\n const local = ((item[\"local\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\";\n if (local.length > 0 && isUsed(local, retainedText)) {\n kept.push(item);\n }\n }\n }\n\n if (kept.length === 0) {\n continue; // import tak terpakai → dipangkas (§12.3)\n }\n\n const keptText = kept\n .map((item) => source.slice(item.start ?? 0, item.end ?? 0))\n .join(\", \");\n importLines.push(`import { ${keptText} } from ${JSON.stringify(specifier)};`);\n }\n\n if (needsCreateStub) {\n importLines.push('import { __moons_createStub } from \"@moonsjs/server/client\";');\n }\n\n const exportLines: string[] = [];\n for (const fn of analysis.serverFns) {\n const input = source.slice(fn.input.start, fn.input.end);\n const output = source.slice(fn.output.start, fn.output.end);\n\n // E_SCHEMA_LOCAL_REF: deklarasi lokal dibuang dari stub, jadi referensinya\n // menjadi `undefined` di browser (crash hydration — dulu lolos build).\n for (const [kind, slice] of [\n [\"input\", input],\n [\"output\", output],\n ] as const) {\n for (const reference of referencedIdentifiers(slice, filename)) {\n if (reference.length === 0 || !localNames.has(reference)) {\n continue;\n }\n throw new MoonsError({\n code: \"E_SCHEMA_LOCAL_REF\",\n file: filename,\n line: fn.line,\n annotation: fn.name,\n message: `schema ${kind} serverFn \\`${fn.name}\\` merujuk deklarasi lokal \\`${reference}\\``,\n details:\n `\\`${reference}\\` dibuang dari stub client (PRD §12.2/§12.3), sehingga nilainya \\`undefined\\` di browser (crash hydration).\\n\\n` +\n \"Sebelum (ditolak):\\n\" +\n ` const ${reference} = z.object({ … }); // deklarasi lokal di file yang sama\\n` +\n ` export const ${fn.name} = serverFn({ ${kind}: ${reference}, … });\\n\\n` +\n \"Sesudah (pilih salah satu):\\n\" +\n ` // a) inline schema di argumen\\n` +\n ` export const ${fn.name} = serverFn({ ${kind}: z.object({ … }), … });\\n` +\n ` // b) pindahkan deklarasi ke modul bersama yang boleh masuk client (mis. src/shared/schemas.ts)\\n` +\n ` import { ${reference} } from \"../shared/schemas\";`,\n suggestions: [\n `Inline schema di argumen \\`serverFn({ ${kind}: … })\\`, atau`,\n `Pindahkan \\`${reference}\\` ke modul bersama (mis. \\`src/shared/schemas.ts\\`) lalu impor dari sana`,\n \"Jangan memindahkan nilai rahasia ke shared — schema harus client-safe (zod/Standard Schema)\",\n ],\n });\n }\n }\n\n exportLines.push(\n `export const ${fn.name} = __moons_createStub({ hash: ${JSON.stringify(fn.hash)}, input: ${input}, output: ${output} });`,\n );\n }\n\n for (const reExport of analysis.reExports) {\n const target = dependencies.analyzeSpecifier(filename, reExport.source);\n if (target === null) {\n throw new MoonsError({\n code: \"E_SERVER_IMPORT_IN_CLIENT\",\n file: filename,\n message: `tidak bisa me-resolve \\`${reExport.source}\\` untuk re-export`,\n details: \"Re-export dari `*.server.ts` harus bisa di-resolve statis (PRD §12.6).\",\n suggestions: [\"Perbaiki path re-export\", \"Hindari re-export dinamis dari file server\"],\n });\n }\n const targetNames = serverFnExportNames(target, (specifier) =>\n dependencies.analyzeSpecifier(filename, specifier),\n );\n const keptNames = reExport.names.filter(({ local }) => local !== \"\" && targetNames.has(local));\n if (keptNames.length > 0) {\n const specifiers = keptNames\n .map(({ local, exported }) => (local === exported ? local : `${local} as ${exported}`))\n .join(\", \");\n exportLines.push(`export { ${specifiers} } from ${JSON.stringify(reExport.source)};`);\n }\n }\n\n for (const specifier of analysis.exportAllFrom) {\n const target = dependencies.analyzeSpecifier(filename, specifier);\n if (target === null) {\n throw new MoonsError({\n code: \"E_SERVER_IMPORT_IN_CLIENT\",\n file: filename,\n message: `\\`export *\\` dari \\`${specifier}\\` tidak bisa di-resolve`,\n details: \"`export *` dari `*.server.ts` wajib bisa di-expand statis (PRD §12.6).\",\n suggestions: [\"Perbaiki path re-export\", \"Ganti menjadi named re-export\"],\n });\n }\n const targetNames = serverFnExportNames(target, (nested) =>\n dependencies.analyzeSpecifier(filename, nested),\n );\n if (targetNames.size > 0) {\n exportLines.push(\n `export { ${[...targetNames].join(\", \")} } from ${JSON.stringify(specifier)};`,\n );\n }\n }\n\n if (importLines.length === 0 && exportLines.length === 0) {\n return { code: \"// @moons: tidak ada serverFn yang di-export\\nexport {};\\n\", referenced };\n }\n\n return { code: `${[...importLines, \"\", ...exportLines].join(\"\\n\")}\\n`, referenced };\n}\n\n/** Inject meta §7.2 ke deklarasi serverFn (env ssr; handler tetap utuh). */\nexport function injectServerFnMeta(\n source: string,\n analysis: ServerFileAnalysis,\n projectRoot: string,\n): string {\n let output = source;\n const inserts = [...analysis.serverFns].sort((a, b) => b.objectStart - a.objectStart);\n\n for (const fn of inserts) {\n const meta =\n ` __hash: ${JSON.stringify(fn.hash)},` +\n ` __file: ${JSON.stringify(fnRegistryKey(projectRoot, analysis.file, fn.name).split(\"#\")[0] as string)},` +\n ` __line: ${fn.line},` +\n ` __exportName: ${JSON.stringify(fn.name)},`;\n const at = fn.objectStart + 1;\n output = output.slice(0, at) + meta + output.slice(at);\n }\n\n return output;\n}\n\nexport interface ClientImportCheckContext {\n /** Absolute path file yang sedang diperiksa. */\n file: string;\n code: string;\n projectRoot: string;\n /**\n * Resolve specifier dengan importer tertentu → absolute path (null bila tidak\n * ada). Boleh sinkron maupun async (plugin memakai `this.resolve`, sehingga\n * alias Vite & `tsconfig paths` ikut terperiksa — audit ronde 2).\n */\n resolve: (specifier: string, importer: string) => string | null | Promise<string | null>;\n /** Analysis untuk file server (hasil cache plugin). */\n analyze: (absoluteFile: string) => ServerFileAnalysis | null;\n /** Direktori `src/api` (absolut) — modul API server-only (Addendum D.1). */\n apiDir?: string;\n /** Paket server-only tambahan dari `security.serverOnlyPackages` (Addendum C). */\n serverOnlyPackages?: ReadonlyArray<string>;\n /** Cache package.json lintas modul (performa; dikelola plugin). */\n packageCache?: Map<string, PackageJsonInfo | null>;\n}\n\n/** Nama serverFn (langsung atau via re-export) — versi async untuk pemeriksaan resolve. */\nasync function serverFnExportNamesAsync(\n analysis: ServerFileAnalysis,\n analyzeSpecifier: (specifier: string, importer: string) => Promise<ServerFileAnalysis | null>,\n seen = new Set<string>(),\n): Promise<Set<string>> {\n const names = new Set(analysis.serverFns.map((fn) => fn.name));\n\n for (const reExport of analysis.reExports) {\n const key = `${analysis.file}\\0${reExport.source}`;\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n const target = await analyzeSpecifier(reExport.source, analysis.file);\n if (target === null) {\n continue;\n }\n const targetNames = await serverFnExportNamesAsync(target, analyzeSpecifier, seen);\n for (const { local, exported } of reExport.names) {\n if (local === \"*\" || targetNames.has(local)) {\n names.add(exported);\n }\n }\n }\n\n for (const specifier of analysis.exportAllFrom) {\n const key = `${analysis.file}\\0${specifier}`;\n if (seen.has(key)) {\n continue;\n }\n seen.add(key);\n const target = await analyzeSpecifier(specifier, analysis.file);\n if (target === null) {\n continue;\n }\n for (const name of await serverFnExportNamesAsync(target, analyzeSpecifier, seen)) {\n names.add(name);\n }\n }\n\n return names;\n}\n\nexport function nonContractServerFileError(file: string, projectRoot: string): MoonsError {\n return new MoonsError({\n code: \"E_SERVER_IMPORT_IN_CLIENT\",\n file: toRelative(projectRoot, file),\n message: \"file server memakai ekstensi di luar kontrak §12\",\n details:\n \"Transform zero-trust hanya menangani `*.server.ts`/`*.server.tsx`; file server dengan ekstensi lain tidak bisa di-stub dan tidak boleh masuk graph client.\",\n suggestions: [\n \"Ganti nama file menjadi `*.server.ts`/`*.server.tsx` dan taruh `serverFn` di dalamnya\",\n \"Atau pindahkan nilai yang dibutuhkan ke file non-server\",\n ],\n });\n}\n\n/** Periksa import modul client terhadap §12.4/§12.7/§12.8 — berbasis hasil resolve. */\nexport async function checkClientModuleImports(\n context: ClientImportCheckContext,\n): Promise<void> {\n const { file, code, projectRoot, resolve, analyze } = context;\n const ast = parseModule(code, file);\n const relativeFile = toRelative(projectRoot, file);\n // Addendum C: gate paket server-only (daftar bawaan ∪ security.serverOnlyPackages ∪ marker).\n const serverOnly = createServerOnlyClassifier({\n configured: context.serverOnlyPackages ?? [],\n ...(context.packageCache === undefined ? {} : { cache: context.packageCache }),\n });\n // Addendum D.1: `src/api/**` server-only (endpoint HTTP mentah).\n let apiDirReal: string | null = null;\n if (context.apiDir !== undefined && context.apiDir.length > 0) {\n try {\n apiDirReal = realpathSync(context.apiDir);\n } catch {\n apiDirReal = context.apiDir;\n }\n }\n\n const rejectApiImport = (line: number, specifier: string, resolvedTarget: string): never => {\n const relApi = toRelative(projectRoot, resolvedTarget);\n throw new MoonsError({\n code: \"E_FORBIDDEN_SERVER_IMPORT\",\n file: relativeFile,\n line,\n message: `mengimpor \\`${specifier}\\` — \\`${relApi}\\` adalah modul API server-only`,\n details:\n \"`src/api/**` hanya berjalan di server (endpoint HTTP) dan tidak pernah masuk bundle client (PRD Addendum D.1).\",\n suggestions: [\n \"Pindahkan operasi tersebut ke `*.server.ts` dan panggil lewat serverFn\",\n \"Jangan mengimpor file `src/api` dari route/komponen client\",\n ],\n });\n };\n\n const resolveSafe = async (specifier: string, importer: string): Promise<string | null> => {\n try {\n const result = await resolve(specifier, importer);\n if (result === null) {\n return null;\n }\n const clean = stripQuery(result);\n // Audit ronde 2: normalisasi realpath — symlink ke `*.server.ts` harus\n // tertangkap walau resolver mengembalikan path link.\n try {\n return realpathSync(clean);\n } catch {\n return clean;\n }\n } catch {\n return null;\n }\n };\n\n const analyzeResolved = async (\n specifier: string,\n importer: string,\n ): Promise<ServerFileAnalysis | null> => {\n const absolute = await resolveSafe(specifier, importer);\n return absolute === null ? null : analyze(absolute);\n };\n\n const isAllowedServerFnImport = async (\n resolvedTarget: string | null,\n specifier: string,\n name: string,\n ): Promise<boolean> => {\n const target =\n resolvedTarget === null ? await analyzeResolved(specifier, file) : analyze(resolvedTarget);\n if (target === null) {\n return false;\n }\n const names = await serverFnExportNamesAsync(target, (nested, importer) =>\n analyzeResolved(nested, importer),\n );\n return names.has(name);\n };\n\n const reject = (line: number, message: string, details: string): never => {\n throw new MoonsError({\n code: \"E_SERVER_IMPORT_IN_CLIENT\",\n file: relativeFile,\n line,\n message,\n details,\n suggestions: [\n \"Buat server function yang mengembalikan data yang dibutuhkan, atau\",\n \"Jika nilainya memang publik, definisikan ulang konstanta itu di modul yang boleh masuk client (jangan memindahkan nilai rahasia)\",\n ],\n });\n };\n\n const rejectForbidden = (line: number, specifier: string): never => {\n throw new MoonsError({\n code: \"E_FORBIDDEN_SERVER_IMPORT\",\n file: relativeFile,\n line,\n message: `mengimpor \\`${specifier}\\` di modul client`,\n details: \"Modul server-only hanya boleh di-import dari *.server.ts.\",\n suggestions: [\n \"Pindahkan operasi tersebut ke serverFn, atau\",\n \"Hapus import tersebut\",\n ],\n });\n };\n\n for (const statement of topLevelStatements(ast)) {\n if (statement.type === \"ImportDeclaration\" || statement.type === \"ExportNamedDeclaration\" || statement.type === \"ExportAllDeclaration\") {\n const sourceNode = statement[\"source\"] as AstNode | null | undefined;\n if (sourceNode?.type !== \"StringLiteral\") {\n continue;\n }\n const rawSpecifier = sourceNode[\"value\"] as string;\n // Query Vite (`?raw`, `?url`, `?inline`, dst.) dinormalisasi untuk\n // pencocokan & resolusi (audit adversarial M6).\n const specifier = stripQuery(rawSpecifier);\n const line = statement.loc?.start.line ?? 1;\n // Addendum C: type-only (`import type ...`, seluruh specifier tipe)\n // terhapus saat kompilasi → dikecualikan dari gate paket server-only.\n const typeOnly = isTypeOnlyImportExport(statement);\n\n if (specifier.startsWith(\"node:\") || specifier.startsWith(\"bun:\")) {\n rejectForbidden(line, specifier);\n }\n\n const resolvedTarget = await resolveSafe(specifier, file);\n\n // Addendum D.1: modul `src/api/**` server-only.\n if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {\n rejectApiImport(line, rawSpecifier, resolvedTarget);\n }\n\n // Addendum C: paket server-only (nama paket hasil resolve — subpath,\n // alias, tsconfig paths, symlink/workspace ikut tertangkap).\n if (!typeOnly) {\n const match = serverOnly.check({\n specifier,\n resolvedFile: resolvedTarget,\n importerFile: file,\n });\n if (match !== null) {\n throw serverOnlyImportError({\n relativeFile,\n line,\n specifier: rawSpecifier,\n packageName: match.packageName,\n source: match.source,\n ...(match.source === \"marker\"\n ? { markerPath: toRelative(projectRoot, join(match.packageDir, \"package.json\")) }\n : {}),\n });\n }\n }\n\n // Audit ronde 2: file server di luar kontrak §12 ditolak (tidak bisa di-stub).\n if (resolvedTarget !== null && isNonContractServerFile(resolvedTarget)) {\n throw nonContractServerFileError(resolvedTarget, projectRoot);\n }\n\n // Audit ronde 2: keputusan berbasis hasil resolve — menangkap alias Vite,\n // `tsconfig paths`, dan symlink (realpath) yang menunjuk `*.server.ts`.\n const serverBySpecifier = isServerSpecifier(specifier);\n const serverByResolve = resolvedTarget !== null && isServerFilePath(resolvedTarget);\n if (!serverBySpecifier && !serverByResolve) {\n continue;\n }\n\n const targetRelative =\n resolvedTarget === null ? rawSpecifier : toRelative(projectRoot, resolvedTarget);\n\n if (statement.type === \"ExportAllDeclaration\") {\n if (resolvedTarget === null) {\n reject(line, `\\`export *\\` dari \\`${targetRelative}\\` tidak bisa di-resolve`, \"Re-export dari `*.server.ts` wajib bisa di-resolve statis (PRD §12.6).\");\n }\n continue; // aman: target menjadi stub\n }\n\n const specifiers = (statement[\"specifiers\"] ?? []) as AstNode[];\n for (const item of specifiers) {\n if (item.type === \"ImportDefaultSpecifier\") {\n reject(line, `mengimpor default dari ${targetRelative}`, \"Default export dari file server tidak boleh menyeberang ke client.\");\n }\n if (item.type === \"ImportNamespaceSpecifier\") {\n reject(line, `mengimpor namespace (\\`* as\\`) dari ${targetRelative}`, \"Import namespace dari file server tidak boleh menyeberang ke client.\");\n }\n const name = ((item[\"local\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\";\n const kind = (item[\"importKind\"] as string | undefined) ?? (statement[\"importKind\"] as string | undefined);\n if (kind === \"type\") {\n reject(line, `mengimpor type \\`${name}\\` dari ${targetRelative}`, \"Import dari file server tidak diizinkan di modul client (PRD §12.4).\");\n }\n if (name.length > 0 && !(await isAllowedServerFnImport(resolvedTarget, specifier, name))) {\n reject(\n line,\n `mengimpor \\`${name}\\` dari ${targetRelative}`,\n \"Kode server tidak boleh muncul di client.\\nHanya `serverFn` yang diizinkan menyeberang.\",\n );\n }\n }\n }\n }\n\n // §12.4: pemanggilan env() di modul client (juga @moonsjs/server import env).\n const envBindings = new Set<string>();\n for (const statement of topLevelStatements(ast)) {\n if (statement.type !== \"ImportDeclaration\") {\n continue;\n }\n const sourceNode = statement[\"source\"] as AstNode | undefined;\n const specifier = sourceNode?.type === \"StringLiteral\" ? (sourceNode[\"value\"] as string) : \"\";\n if (specifier !== \"@moonsjs/server\" && !specifier.startsWith(\"@moonsjs/server/\")) {\n continue;\n }\n for (const item of (statement[\"specifiers\"] ?? []) as AstNode[]) {\n if (item.type !== \"ImportSpecifier\") {\n continue;\n }\n const imported = item[\"imported\"] as AstNode | undefined;\n const local = item[\"local\"] as AstNode | undefined;\n if (imported?.type === \"Identifier\" && imported[\"name\"] === \"env\" && local?.type === \"Identifier\") {\n envBindings.add(local[\"name\"] as string);\n }\n }\n }\n\n if (envBindings.size > 0) {\n walk(ast, (node) => {\n if (node.type !== \"CallExpression\") {\n return;\n }\n const callee = node[\"callee\"] as AstNode | undefined;\n if (callee?.type !== \"Identifier\" || !envBindings.has(callee[\"name\"] as string)) {\n return;\n }\n const callText = code\n .slice(node.start ?? 0, node.end ?? 0)\n .replace(/\\s+/g, \" \")\n .slice(0, 80);\n throw new MoonsError({\n code: \"E_ENV_IN_CLIENT\",\n file: relativeFile,\n line: node.loc?.start.line ?? 1,\n message: `memanggil \\`${callText}\\` di modul yang masuk client`,\n details: \"`env()` hanya legal di server.\",\n suggestions: [\n \"Pindahkan pemanggilan ke dalam serverFn, atau\",\n \"Gunakan import.meta.env untuk nilai publik\",\n ],\n });\n });\n }\n\n // Dynamic import (§12.7/§12.8) — literal maupun template dengan teks `.server`,\n // plus resolusi (alias/tsconfig paths/symlink) — audit ronde 2.\n const dynamicRequests: Array<{ request: DynamicImportRequest; guarded: boolean }> = [];\n walk(ast, (node, ancestors) => {\n const request = dynamicImportRequest(node);\n if (request !== null) {\n dynamicRequests.push({\n request,\n guarded: ancestors.some((ancestor) => isDevGuard(ancestor)),\n });\n }\n });\n\n for (const { request, guarded } of dynamicRequests) {\n if (guarded) {\n continue; // §12.8: branch DEV/PROD mati saat build → tidak perlu diperiksa\n }\n\n const specifier = stripQuery(request.text);\n const resolvedTarget = await resolveSafe(specifier, file);\n\n // Addendum D.1: dynamic import modul `src/api/**` juga ditolak.\n if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {\n rejectApiImport(request.node.loc?.start.line ?? 1, request.text, resolvedTarget);\n }\n\n // Addendum C: dynamic import paket server-only juga digerbang.\n const match = serverOnly.check({\n specifier,\n resolvedFile: resolvedTarget,\n importerFile: file,\n });\n if (match !== null) {\n throw serverOnlyImportError({\n relativeFile,\n line: request.node.loc?.start.line ?? 1,\n specifier: request.text,\n packageName: match.packageName,\n source: match.source,\n dynamic: true,\n ...(match.source === \"marker\"\n ? { markerPath: toRelative(projectRoot, join(match.packageDir, \"package.json\")) }\n : {}),\n });\n }\n\n if (resolvedTarget !== null && isNonContractServerFile(resolvedTarget)) {\n throw nonContractServerFileError(resolvedTarget, projectRoot);\n }\n\n const serverBySpecifier = isServerSpecifier(specifier);\n const serverByResolve = resolvedTarget !== null && isServerFilePath(resolvedTarget);\n if (!serverBySpecifier && !serverByResolve) {\n continue;\n }\n\n const targetRelative =\n resolvedTarget === null ? request.text : toRelative(projectRoot, resolvedTarget);\n reject(request.node.loc?.start.line ?? 1, `mengimpor (dynamic) \\`${request.text}\\` dari ${targetRelative}`, \"Client tidak boleh melakukan dynamic import ke `*.server.ts` (PRD §12.7).\");\n }\n\n // `import.meta.glob` yang mencakup `*.server.ts` (§12.7) — audit adversarial M6.\n walk(ast, (node) => {\n if (node.type !== \"CallExpression\") {\n return;\n }\n const callee = node[\"callee\"] as AstNode | undefined;\n if (callee?.type !== \"MemberExpression\") {\n return;\n }\n const object = callee[\"object\"] as AstNode | undefined;\n const property = callee[\"property\"] as AstNode | undefined;\n if (\n object?.type !== \"MetaProperty\" ||\n property?.type !== \"Identifier\" ||\n property[\"name\"] !== \"glob\"\n ) {\n return;\n }\n\n for (const pattern of globPatterns(((node[\"arguments\"] ?? []) as AstNode[])[0])) {\n if (!isServerSpecifier(pattern)) {\n continue;\n }\n throw new MoonsError({\n code: \"E_SERVER_IMPORT_IN_CLIENT\",\n file: relativeFile,\n line: node.loc?.start.line ?? 1,\n message: `mengimpor (glob) \\`${pattern}\\` di modul client`,\n details: \"`import.meta.glob` yang mencakup `*.server.ts` dilarang di client (PRD §12.7).\",\n suggestions: [\n \"Import statis `serverFn` dari `*.server.ts` (hanya itu yang boleh menyeberang), atau\",\n \"Pindahkan kebutuhan data ke dalam server function\",\n ],\n });\n }\n });\n}\n\ninterface DynamicImportRequest {\n /** Teks specifier literal, atau gabungan quasi template (`*` untuk ekspresi). */\n text: string;\n node: AstNode;\n}\n\n/** Dukung Babel 8 (`ImportExpression`) dan bentuk lama (`CallExpression` + callee `Import`). */\nfunction dynamicImportRequest(node: AstNode): DynamicImportRequest | null {\n let sourceNode: AstNode | null = null;\n\n if (node.type === \"ImportExpression\") {\n sourceNode = (node[\"source\"] as AstNode | undefined) ?? null;\n } else if (node.type === \"CallExpression\") {\n const callee = node[\"callee\"] as AstNode | undefined;\n if (callee?.type !== \"Import\") {\n return null;\n }\n sourceNode = ((node[\"arguments\"] ?? []) as AstNode[])[0] ?? null;\n }\n\n if (sourceNode === null) {\n return null;\n }\n if (sourceNode.type === \"StringLiteral\") {\n return { text: sourceNode[\"value\"] as string, node: sourceNode };\n }\n if (sourceNode.type === \"TemplateLiteral\") {\n const text = ((sourceNode[\"quasis\"] ?? []) as AstNode[])\n .map((quasi) => ((quasi[\"value\"] as { cooked?: string | null } | undefined)?.cooked ?? \"\"))\n .join(\"*\");\n return { text, node: sourceNode };\n }\n return null;\n}\n\nfunction globPatterns(node: AstNode | undefined): string[] { if (node?.type === \"StringLiteral\") {\n return [node[\"value\"] as string];\n }\n if (node?.type === \"ArrayExpression\") {\n return ((node[\"elements\"] ?? []) as Array<AstNode | null>)\n .filter((element): element is AstNode => element?.type === \"StringLiteral\")\n .map((element) => element[\"value\"] as string);\n }\n return [];\n}\n\nfunction isDevGuard(node: AstNode): boolean {\n if (node.type !== \"IfStatement\") {\n return false;\n }\n const test = node[\"test\"] as AstNode | undefined;\n return isImportMetaFlag(test, \"DEV\") || isNegatedImportMetaFlag(test, \"PROD\");\n}\n\nfunction isImportMetaFlag(node: AstNode | undefined, flag: string): boolean {\n const member = node;\n if (member?.type !== \"MemberExpression\") {\n return false;\n }\n const property = member[\"property\"] as AstNode | undefined;\n if (property?.type !== \"Identifier\" || property[\"name\"] !== flag) {\n return false;\n }\n const object = member[\"object\"] as AstNode | undefined;\n return isImportMetaEnv(object);\n}\n\nfunction isNegatedImportMetaFlag(node: AstNode | undefined, flag: string): boolean {\n if (node?.type !== \"UnaryExpression\" || node[\"operator\"] !== \"!\") {\n return false;\n }\n return isImportMetaFlag(node[\"argument\"] as AstNode | undefined, flag);\n}\n\nfunction isImportMetaEnv(node: AstNode | undefined): boolean {\n if (node?.type !== \"MemberExpression\") {\n return false;\n }\n const property = node[\"property\"] as AstNode | undefined;\n if (property?.type !== \"Identifier\" || property[\"name\"] !== \"env\") {\n return false;\n }\n const object = node[\"object\"] as AstNode | undefined;\n return object?.type === \"MetaProperty\";\n}\n\nfunction toRelative(projectRoot: string, file: string): string {\n const relative = file.startsWith(projectRoot)\n ? file.slice(projectRoot.length).replace(/^[/\\\\]/, \"\")\n : file;\n return relative.split(\"\\\\\").join(\"/\");\n}\n\nfunction isInsideDir(file: string, dir: string): boolean {\n const normalized = dir.endsWith(\"/\") ? dir : `${dir}/`;\n return file === dir || file.startsWith(normalized);\n}\n\nexport interface RouteExportCheckContext {\n file: string;\n code: string;\n routesDir: string;\n projectRoot: string;\n}\n\n/**\n * §11.2 + §12.4: export legal per jenis modul route.\n * page: `default|loader|meta|prerender|paths` (D.5); layout: `default|loader`;\n * `_error`/`_404`: `default`.\n */\nexport function checkRouteModuleExports(context: RouteExportCheckContext): void {\n const { file, code, routesDir, projectRoot } = context;\n if (!file.startsWith(routesDir) || !file.endsWith(\".tsx\")) {\n return;\n }\n\n const base = file.slice(file.lastIndexOf(\"/\") + 1);\n if (base.startsWith(\"_\") && base !== \"_layout.tsx\" && base !== \"_error.tsx\" && base !== \"_404.tsx\") {\n return; // bukan route (diabaikan scanner)\n }\n\n const allowed =\n base === \"_layout.tsx\"\n ? [\"default\", \"loader\"]\n : base === \"_error.tsx\" || base === \"_404.tsx\"\n ? [\"default\"]\n : [\"default\", \"loader\", \"meta\", \"prerender\", \"paths\"];\n const allowedText = `Hanya ${allowed.map((name) => `\\`${name}\\``).join(\", \")} yang boleh di-export.`;\n const relativeFile = toRelative(projectRoot, file);\n const ast = parseModule(code, file);\n\n const declarations: Array<{ name: string; line: number }> = [];\n let hasDefault = false;\n\n for (const statement of topLevelStatements(ast)) {\n if (statement.type === \"ExportDefaultDeclaration\") {\n hasDefault = true;\n continue;\n }\n\n if (statement.type === \"ExportAllDeclaration\") {\n throw new MoonsError({\n code: \"E_ROUTE_EXPORT_INVALID\",\n file: relativeFile,\n line: statement.loc?.start.line ?? 1,\n message: \"`export *` tidak diizinkan di modul route\",\n details: allowedText,\n suggestions: [\n `Pindahkan isi file ke luar ${toRelative(projectRoot, routesDir)}/, atau`,\n \"Hapus `export *` tersebut\",\n ],\n });\n }\n\n if (statement.type !== \"ExportNamedDeclaration\") {\n continue;\n }\n\n const declaration = statement[\"declaration\"] as AstNode | null | undefined;\n if (declaration !== null && declaration !== undefined) {\n for (const name of declarationNames(declaration)) {\n declarations.push({ name, line: declaration.loc?.start.line ?? 1 });\n }\n }\n\n for (const item of (statement[\"specifiers\"] ?? []) as AstNode[]) {\n const exported = item[\"exported\"] as AstNode | undefined;\n const name =\n exported?.type === \"Identifier\"\n ? (exported[\"name\"] as string)\n : exported?.type === \"StringLiteral\"\n ? (exported[\"value\"] as string)\n : null;\n if (name !== null) {\n declarations.push({ name, line: item.loc?.start.line ?? statement.loc?.start.line ?? 1 });\n }\n }\n }\n\n for (const entry of declarations) {\n if (!allowed.includes(entry.name)) {\n throw new MoonsError({\n code: \"E_ROUTE_EXPORT_INVALID\",\n file: relativeFile,\n line: entry.line,\n message: `export \\`${entry.name}\\` tidak diizinkan di modul route`,\n details: allowedText,\n suggestions: [\n `Pindahkan \\`${entry.name}\\` ke file di luar ${toRelative(projectRoot, routesDir)}/, atau`,\n \"Hapus export tersebut\",\n ],\n });\n }\n }\n\n if (!hasDefault) {\n throw new MoonsError({\n code: \"E_ROUTE_EXPORT_INVALID\",\n file: relativeFile,\n message: \"modul route wajib mengekspor `default`\",\n details: \"Setiap file route harus punya `export default` berupa komponen React (PRD §11.2).\",\n suggestions: [\"Tambahkan `export default function Page() { ... }`\"],\n });\n }\n}\n\nfunction declarationNames(declaration: AstNode): string[] {\n switch (declaration.type) {\n case \"VariableDeclaration\":\n return ((declaration[\"declarations\"] ?? []) as AstNode[])\n .map((declarator) => ((declarator[\"id\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\")\n .filter((name) => name.length > 0);\n case \"FunctionDeclaration\":\n case \"ClassDeclaration\":\n case \"TSInterfaceDeclaration\":\n case \"TSTypeAliasDeclaration\":\n case \"TSEnumDeclaration\":\n return [((declaration[\"id\"] as AstNode | undefined)?.[\"name\"] as string) ?? \"\"].filter(\n (name) => name.length > 0,\n );\n default:\n return [];\n }\n}\n\n/** Scan semua `*.server.{ts,tsx}` di bawah root (exclude direktori build/dependency). */\nexport function scanServerFiles(projectRoot: string): string[] {\n const excluded = new Set([\"node_modules\", \"dist\", \".moons\", \".git\"]);\n const result: string[] = [];\n\n const walkDir = (dir: string): void => {\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n if (excluded.has(entry.name)) {\n continue;\n }\n walkDir(join(dir, entry.name));\n } else if (entry.isFile() && isServerFilePath(entry.name)) {\n result.push(join(dir, entry.name));\n }\n }\n };\n\n walkDir(projectRoot);\n return result.sort();\n}\n\nexport interface FnRegistryJson {\n [key: string]: string;\n}\n\n/** Bangun isi `fn-registry.json` (bentuk yang dibaca §21.3). */\nexport function buildFnRegistry(projectRoot: string, files: string[]): FnRegistryJson {\n const registry: FnRegistryJson = {};\n for (const file of files) {\n let source: string;\n try {\n source = readFileSync(file, \"utf8\");\n } catch {\n continue;\n }\n const analysis = analyzeServerFile(source, file, projectRoot);\n for (const fn of analysis.serverFns) {\n registry[fnRegistryKey(projectRoot, file, fn.name)] = fn.hash;\n }\n }\n return registry;\n}\n",
|
|
6
|
+
"import { MoonsError } from \"@moonsjs/core\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Gate paket server-only (PRD Addendum C): paket npm yang tidak boleh masuk\n * graph client — di-import dari route/client/shared → build gagal.\n *\n * Daftar bawaan adalah **minimum normatif** dan TIDAK dapat dihapus app:\n * gate kebocoran tidak boleh bisa dilonggarkan (prinsip \"batas lebih ketat\n * menang\"); salah-tangkap diperbaiki lewat rilis framework.\n */\nexport const DEFAULT_SERVER_ONLY_PACKAGES: ReadonlyArray<string> = [\n \"pg\",\n \"postgres\",\n \"mysql\",\n \"mysql2\",\n \"sqlite3\",\n \"better-sqlite3\",\n \"drizzle-orm\",\n \"@prisma/client\",\n \"prisma\",\n \"mongodb\",\n \"mongoose\",\n \"redis\",\n \"ioredis\",\n \"bcrypt\",\n \"bcryptjs\",\n \"argon2\",\n \"jsonwebtoken\",\n \"nodemailer\",\n \"sharp\",\n \"execa\",\n \"cross-spawn\",\n \"dotenv\",\n \"knex\",\n \"typeorm\",\n \"sequelize\",\n \"@libsql/client\",\n];\n\nexport type ServerOnlyMatchSource = \"builtin\" | \"config\" | \"marker\";\n\nexport interface PackageJsonInfo {\n /** Direktori package (tempat package.json berada). */\n dir: string;\n name: string;\n serverOnlyMarker: boolean;\n}\n\nexport interface ServerOnlyMatch {\n packageName: string;\n source: ServerOnlyMatchSource;\n packageDir: string;\n}\n\nexport interface ServerOnlyClassifier {\n check(input: {\n specifier: string;\n resolvedFile: string | null;\n importerFile: string;\n }): ServerOnlyMatch | null;\n}\n\nexport interface ServerOnlyClassifierOptions {\n /** `security.serverOnlyPackages` — tambahan milik app (tidak menghapus bawaan). */\n configured?: ReadonlyArray<string>;\n /** Cache package.json per-direktori; bagikan lintas modul demi performa. */\n cache?: Map<string, PackageJsonInfo | null>;\n}\n\n/** Nama paket dari specifier bare (dipakai sebagai info pelengkap; pencocokan utama lewat resolve). */\nexport function packageNameFromSpecifier(specifier: string): string | null {\n if (\n specifier.length === 0 ||\n specifier.startsWith(\".\") ||\n specifier.startsWith(\"/\") ||\n specifier.startsWith(\"\\0\") ||\n specifier.includes(\":\")\n ) {\n return null;\n }\n const parts = specifier.split(\"/\");\n if (specifier.startsWith(\"@\")) {\n if (parts.length < 2 || (parts[1] ?? \"\").length === 0) {\n return null;\n }\n return `${parts[0]}/${parts[1]}`;\n }\n return parts[0] ?? null;\n}\n\n/** Baca package.json pada direktori tertentu (null bila tidak ada/gagal). */\nexport function tryReadPackageJson(dir: string): PackageJsonInfo | null {\n const candidate = join(dir, \"package.json\");\n if (!existsSync(candidate)) {\n return null;\n }\n try {\n const json = JSON.parse(readFileSync(candidate, \"utf8\")) as {\n name?: unknown;\n moons?: unknown;\n };\n const moons = json.moons as { serverOnly?: unknown } | undefined;\n return {\n dir,\n name: typeof json.name === \"string\" ? json.name : \"\",\n serverOnlyMarker: moons?.serverOnly === true,\n };\n } catch {\n return null;\n }\n}\n\n/** Baca package.json terdekat dari sebuah file absolut (menelusuri ke atas). */\nexport function readPackageJsonFrom(file: string): PackageJsonInfo | null {\n let dir = dirname(file);\n for (let depth = 0; depth < 64; depth += 1) {\n const info = tryReadPackageJson(dir);\n if (info !== null) {\n return info;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n return null;\n}\n\nexport function createServerOnlyClassifier(\n options: ServerOnlyClassifierOptions = {},\n): ServerOnlyClassifier {\n const cache = options.cache ?? new Map<string, PackageJsonInfo | null>();\n const configured = new Set(options.configured ?? []);\n const builtin = new Set(DEFAULT_SERVER_ONLY_PACKAGES);\n\n const infoOf = (file: string): PackageJsonInfo | null => {\n let dir = dirname(file);\n for (let depth = 0; depth < 64; depth += 1) {\n if (cache.has(dir)) {\n return cache.get(dir) ?? null;\n }\n const info = tryReadPackageJson(dir);\n if (info !== null) {\n cache.set(dir, info);\n return info;\n }\n // Direktori tanpa package.json: lanjut ke atas (tidak di-cache agar\n // penelusuran berikutnya tetap benar untuk subtree berbeda).\n const parent = dirname(dir);\n if (parent === dir) {\n return null;\n }\n dir = parent;\n }\n return null;\n };\n\n return {\n check({ specifier: _specifier, resolvedFile, importerFile }) {\n if (resolvedFile === null) {\n return null;\n }\n const info = infoOf(resolvedFile);\n if (info === null || info.name.length === 0) {\n return null;\n }\n // Gate menyasar dependency: import di dalam package yang sama diabaikan.\n const importer = infoOf(importerFile);\n if (importer !== null && importer.dir === info.dir) {\n return null;\n }\n if (builtin.has(info.name)) {\n return { packageName: info.name, source: \"builtin\", packageDir: info.dir };\n }\n if (configured.has(info.name)) {\n return { packageName: info.name, source: \"config\", packageDir: info.dir };\n }\n if (info.serverOnlyMarker) {\n return { packageName: info.name, source: \"marker\", packageDir: info.dir };\n }\n return null;\n },\n };\n}\n\n/**\n * Error §15 untuk import paket server-only (kode tetap\n * `E_FORBIDDEN_SERVER_IMPORT`, PRD Addendum C.3).\n */\nexport function serverOnlyImportError(input: {\n relativeFile: string;\n line: number;\n specifier: string;\n packageName: string;\n source: ServerOnlyMatchSource;\n /** Path package.json relatif project — untuk sumber kecocokan \"marker\". */\n markerPath?: string;\n dynamic?: boolean;\n}): MoonsError {\n const sourceLabel =\n input.source === \"builtin\"\n ? \"Sumber kecocokan: daftar bawaan paket server-only framework.\"\n : input.source === \"config\"\n ? \"Sumber kecocokan: `security.serverOnlyPackages` di moons.config.ts.\"\n : `Sumber kecocokan: marker \\`\"moons\": { \"serverOnly\": true }\\` di ${input.markerPath ?? \"package.json\"}.`;\n return new MoonsError({\n code: \"E_FORBIDDEN_SERVER_IMPORT\",\n file: input.relativeFile,\n line: input.line,\n message: `mengimpor${input.dynamic === true ? \" (dynamic)\" : \"\"} \\`${input.specifier}\\` — paket server-only \\`${input.packageName}\\``,\n details: `${sourceLabel}\\nPaket server-only tidak boleh masuk bundle client (PRD Addendum C).`,\n suggestions: [\n \"Pindahkan operasi tersebut ke `*.server.ts` dan panggil lewat serverFn\",\n \"Atau ganti/hapus import tersebut di modul client\",\n ],\n });\n}\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "72CC55CAEBB11FDE64756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|