@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.
Files changed (60) hide show
  1. package/dist/api.d.ts +8 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/{index-1sm9pvvd.js → index-1fnt137k.js} +106 -18
  4. package/dist/index-1fnt137k.js.map +14 -0
  5. package/dist/{index-3ec9vpek.js → index-e7qz0epf.js} +232 -24
  6. package/dist/index-e7qz0epf.js.map +11 -0
  7. package/dist/index.js +220 -19
  8. package/dist/index.js.map +5 -4
  9. package/dist/manifest.d.ts +6 -1
  10. package/dist/manifest.d.ts.map +1 -1
  11. package/dist/payload-scan.d.ts +18 -0
  12. package/dist/payload-scan.d.ts.map +1 -0
  13. package/dist/plugin.d.ts.map +1 -1
  14. package/dist/server/dev.d.ts +4 -0
  15. package/dist/server/dev.d.ts.map +1 -1
  16. package/dist/server/handler.d.ts +21 -1
  17. package/dist/server/handler.d.ts.map +1 -1
  18. package/dist/server/index.d.ts +6 -0
  19. package/dist/server/index.d.ts.map +1 -1
  20. package/dist/server/index.js +584 -28
  21. package/dist/server/index.js.map +10 -7
  22. package/dist/server/node-server.d.ts +4 -1
  23. package/dist/server/node-server.d.ts.map +1 -1
  24. package/dist/server/node.d.ts.map +1 -1
  25. package/dist/server/plugins.d.ts +26 -0
  26. package/dist/server/plugins.d.ts.map +1 -0
  27. package/dist/server/prerender.d.ts +28 -0
  28. package/dist/server/prerender.d.ts.map +1 -0
  29. package/dist/server/shell.d.ts +3 -3
  30. package/dist/server/shell.d.ts.map +1 -1
  31. package/dist/server/shutdown.d.ts +6 -0
  32. package/dist/server/shutdown.d.ts.map +1 -1
  33. package/dist/server/test-server.d.ts.map +1 -1
  34. package/dist/server-only.d.ts +57 -0
  35. package/dist/server-only.d.ts.map +1 -0
  36. package/dist/transform.d.ts +9 -1
  37. package/dist/transform.d.ts.map +1 -1
  38. package/dist/transform.js +1 -1
  39. package/dist/virtual-modules.d.ts +1 -0
  40. package/dist/virtual-modules.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/api.ts +124 -0
  43. package/src/manifest.ts +42 -1
  44. package/src/payload-scan.ts +53 -0
  45. package/src/plugin.ts +137 -10
  46. package/src/server/dev.ts +48 -12
  47. package/src/server/handler.ts +373 -14
  48. package/src/server/index.ts +6 -0
  49. package/src/server/node-server.ts +70 -16
  50. package/src/server/node.ts +17 -0
  51. package/src/server/plugins.ts +85 -0
  52. package/src/server/prerender.ts +230 -0
  53. package/src/server/shell.ts +62 -8
  54. package/src/server/shutdown.ts +19 -2
  55. package/src/server/test-server.ts +2 -1
  56. package/src/server-only.ts +220 -0
  57. package/src/transform.ts +138 -8
  58. package/src/virtual-modules.ts +1 -0
  59. package/dist/index-1sm9pvvd.js.map +0 -14
  60. 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(dirname(importerFile), specifier) : isAbsolute(specifier) ? specifier : null;
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 (existsSync(candidate)) {
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 MoonsError({
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: "Stub client (PRD §12.2/§12.3) hanya membawa import dan ekspresi schema; " + "deklarasi lokal dibuang sehingga referensi menjadi `undefined` di browser (crash hydration).",
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
- "Inline schema langsung di argumen `serverFn({ input, output })`, atau",
371
- "Impor schema dari modul lain (mis. `src/shared/schemas.ts`)"
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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 MoonsError({
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(join(dir, entry.name));
1063
+ walkDir(join2(dir, entry.name));
856
1064
  } else if (entry.isFile() && isServerFilePath2(entry.name)) {
857
- result.push(join(dir, entry.name));
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 = readFileSync(file, "utf8");
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=6E8CE67B8B7578C064756E2164756E21
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
+ }