@moonsjs/vite 0.1.4 → 0.1.6

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 (52) hide show
  1. package/dist/api.d.ts +8 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/{index-33p1r65s.js → index-1fnt137k.js} +50 -5
  4. package/dist/index-1fnt137k.js.map +14 -0
  5. package/dist/{index-3ec9vpek.js → index-zs92aaz4.js} +232 -24
  6. package/dist/index-zs92aaz4.js.map +11 -0
  7. package/dist/index.js +216 -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 +3 -0
  15. package/dist/server/dev.d.ts.map +1 -1
  16. package/dist/server/handler.d.ts +16 -1
  17. package/dist/server/handler.d.ts.map +1 -1
  18. package/dist/server/index.d.ts +4 -0
  19. package/dist/server/index.d.ts.map +1 -1
  20. package/dist/server/index.js +561 -17
  21. package/dist/server/index.js.map +9 -6
  22. package/dist/server/isr.d.ts +25 -0
  23. package/dist/server/isr.d.ts.map +1 -0
  24. package/dist/server/node-server.d.ts +7 -1
  25. package/dist/server/node-server.d.ts.map +1 -1
  26. package/dist/server/node.d.ts.map +1 -1
  27. package/dist/server/prerender.d.ts +28 -0
  28. package/dist/server/prerender.d.ts.map +1 -0
  29. package/dist/server-only.d.ts +57 -0
  30. package/dist/server-only.d.ts.map +1 -0
  31. package/dist/transform.d.ts +9 -1
  32. package/dist/transform.d.ts.map +1 -1
  33. package/dist/transform.js +1 -1
  34. package/dist/virtual-modules.d.ts +1 -0
  35. package/dist/virtual-modules.d.ts.map +1 -1
  36. package/package.json +1 -1
  37. package/src/api.ts +124 -0
  38. package/src/manifest.ts +42 -1
  39. package/src/payload-scan.ts +53 -0
  40. package/src/plugin.ts +137 -10
  41. package/src/server/dev.ts +14 -5
  42. package/src/server/handler.ts +317 -13
  43. package/src/server/index.ts +4 -0
  44. package/src/server/isr.ts +81 -0
  45. package/src/server/node-server.ts +120 -7
  46. package/src/server/node.ts +17 -0
  47. package/src/server/prerender.ts +256 -0
  48. package/src/server-only.ts +220 -0
  49. package/src/transform.ts +138 -8
  50. package/src/virtual-modules.ts +1 -0
  51. package/dist/index-33p1r65s.js.map +0 -14
  52. package/dist/index-3ec9vpek.js.map +0 -10
package/src/transform.ts CHANGED
@@ -2,6 +2,11 @@ import { MoonsError, computeFnHash, fnRegistryKey } from "@moonsjs/core";
2
2
  import { parse, parseExpression } from "@babel/parser";
3
3
  import { existsSync, readdirSync, readFileSync, realpathSync } from "node:fs";
4
4
  import { dirname, isAbsolute, join, resolve } from "node:path";
5
+ import {
6
+ createServerOnlyClassifier,
7
+ serverOnlyImportError,
8
+ type PackageJsonInfo,
9
+ } from "./server-only";
5
10
 
6
11
  /**
7
12
  * Spec §12: analisis `.server.ts` + stub client + injeksi meta server +
@@ -124,6 +129,27 @@ function topLevelStatements(ast: AstNode): AstNode[] {
124
129
  return program?.body ?? [];
125
130
  }
126
131
 
132
+ /**
133
+ * Type-only import/export (Addendum C.1): `import type ...`, `export type ...`,
134
+ * atau seluruh specifier bertanda `type`. Terhapus saat kompilasi sehingga
135
+ * dikecualikan dari gate paket server-only. `export * from` = bernilai.
136
+ */
137
+ function isTypeOnlyImportExport(statement: AstNode): boolean {
138
+ const declarationKind = (statement["importKind"] ?? statement["exportKind"]) as
139
+ | string
140
+ | undefined;
141
+ if (declarationKind === "type") {
142
+ return true;
143
+ }
144
+ const specifiers = (statement["specifiers"] ?? []) as AstNode[];
145
+ if (specifiers.length === 0) {
146
+ return false;
147
+ }
148
+ return specifiers.every(
149
+ (item) => ((item["importKind"] ?? item["exportKind"]) as string | undefined) === "type",
150
+ );
151
+ }
152
+
127
153
  function keyName(node: unknown): string | null {
128
154
  const key = node as AstNode | undefined;
129
155
  if (key?.type === "Identifier") {
@@ -516,11 +542,19 @@ export function renderServerFnStub(
516
542
  annotation: fn.name,
517
543
  message: `schema ${kind} serverFn \`${fn.name}\` merujuk deklarasi lokal \`${reference}\``,
518
544
  details:
519
- "Stub client (PRD §12.2/§12.3) hanya membawa import dan ekspresi schema; " +
520
- "deklarasi lokal dibuang sehingga referensi menjadi `undefined` di browser (crash hydration).",
545
+ `\`${reference}\` dibuang dari stub client (PRD §12.2/§12.3), sehingga nilainya \`undefined\` di browser (crash hydration).\n\n` +
546
+ "Sebelum (ditolak):\n" +
547
+ ` const ${reference} = z.object({ … }); // deklarasi lokal di file yang sama\n` +
548
+ ` export const ${fn.name} = serverFn({ ${kind}: ${reference}, … });\n\n` +
549
+ "Sesudah (pilih salah satu):\n" +
550
+ ` // a) inline schema di argumen\n` +
551
+ ` export const ${fn.name} = serverFn({ ${kind}: z.object({ … }), … });\n` +
552
+ ` // b) pindahkan deklarasi ke modul bersama yang boleh masuk client (mis. src/shared/schemas.ts)\n` +
553
+ ` import { ${reference} } from "../shared/schemas";`,
521
554
  suggestions: [
522
- "Inline schema langsung di argumen `serverFn({ input, output })`, atau",
523
- "Impor schema dari modul lain (mis. `src/shared/schemas.ts`)",
555
+ `Inline schema di argumen \`serverFn({ ${kind}: … })\`, atau`,
556
+ `Pindahkan \`${reference}\` ke modul bersama (mis. \`src/shared/schemas.ts\`) lalu impor dari sana`,
557
+ "Jangan memindahkan nilai rahasia ke shared — schema harus client-safe (zod/Standard Schema)",
524
558
  ],
525
559
  });
526
560
  }
@@ -617,6 +651,12 @@ export interface ClientImportCheckContext {
617
651
  resolve: (specifier: string, importer: string) => string | null | Promise<string | null>;
618
652
  /** Analysis untuk file server (hasil cache plugin). */
619
653
  analyze: (absoluteFile: string) => ServerFileAnalysis | null;
654
+ /** Direktori `src/api` (absolut) — modul API server-only (Addendum D.1). */
655
+ apiDir?: string;
656
+ /** Paket server-only tambahan dari `security.serverOnlyPackages` (Addendum C). */
657
+ serverOnlyPackages?: ReadonlyArray<string>;
658
+ /** Cache package.json lintas modul (performa; dikelola plugin). */
659
+ packageCache?: Map<string, PackageJsonInfo | null>;
620
660
  }
621
661
 
622
662
  /** Nama serverFn (langsung atau via re-export) — versi async untuk pemeriksaan resolve. */
@@ -684,6 +724,36 @@ export async function checkClientModuleImports(
684
724
  const { file, code, projectRoot, resolve, analyze } = context;
685
725
  const ast = parseModule(code, file);
686
726
  const relativeFile = toRelative(projectRoot, file);
727
+ // Addendum C: gate paket server-only (daftar bawaan ∪ security.serverOnlyPackages ∪ marker).
728
+ const serverOnly = createServerOnlyClassifier({
729
+ configured: context.serverOnlyPackages ?? [],
730
+ ...(context.packageCache === undefined ? {} : { cache: context.packageCache }),
731
+ });
732
+ // Addendum D.1: `src/api/**` server-only (endpoint HTTP mentah).
733
+ let apiDirReal: string | null = null;
734
+ if (context.apiDir !== undefined && context.apiDir.length > 0) {
735
+ try {
736
+ apiDirReal = realpathSync(context.apiDir);
737
+ } catch {
738
+ apiDirReal = context.apiDir;
739
+ }
740
+ }
741
+
742
+ const rejectApiImport = (line: number, specifier: string, resolvedTarget: string): never => {
743
+ const relApi = toRelative(projectRoot, resolvedTarget);
744
+ throw new MoonsError({
745
+ code: "E_FORBIDDEN_SERVER_IMPORT",
746
+ file: relativeFile,
747
+ line,
748
+ message: `mengimpor \`${specifier}\` — \`${relApi}\` adalah modul API server-only`,
749
+ details:
750
+ "`src/api/**` hanya berjalan di server (endpoint HTTP) dan tidak pernah masuk bundle client (PRD Addendum D.1).",
751
+ suggestions: [
752
+ "Pindahkan operasi tersebut ke `*.server.ts` dan panggil lewat serverFn",
753
+ "Jangan mengimpor file `src/api` dari route/komponen client",
754
+ ],
755
+ });
756
+ };
687
757
 
688
758
  const resolveSafe = async (specifier: string, importer: string): Promise<string | null> => {
689
759
  try {
@@ -767,6 +837,9 @@ export async function checkClientModuleImports(
767
837
  // pencocokan & resolusi (audit adversarial M6).
768
838
  const specifier = stripQuery(rawSpecifier);
769
839
  const line = statement.loc?.start.line ?? 1;
840
+ // Addendum C: type-only (`import type ...`, seluruh specifier tipe)
841
+ // terhapus saat kompilasi → dikecualikan dari gate paket server-only.
842
+ const typeOnly = isTypeOnlyImportExport(statement);
770
843
 
771
844
  if (specifier.startsWith("node:") || specifier.startsWith("bun:")) {
772
845
  rejectForbidden(line, specifier);
@@ -774,6 +847,33 @@ export async function checkClientModuleImports(
774
847
 
775
848
  const resolvedTarget = await resolveSafe(specifier, file);
776
849
 
850
+ // Addendum D.1: modul `src/api/**` server-only.
851
+ if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {
852
+ rejectApiImport(line, rawSpecifier, resolvedTarget);
853
+ }
854
+
855
+ // Addendum C: paket server-only (nama paket hasil resolve — subpath,
856
+ // alias, tsconfig paths, symlink/workspace ikut tertangkap).
857
+ if (!typeOnly) {
858
+ const match = serverOnly.check({
859
+ specifier,
860
+ resolvedFile: resolvedTarget,
861
+ importerFile: file,
862
+ });
863
+ if (match !== null) {
864
+ throw serverOnlyImportError({
865
+ relativeFile,
866
+ line,
867
+ specifier: rawSpecifier,
868
+ packageName: match.packageName,
869
+ source: match.source,
870
+ ...(match.source === "marker"
871
+ ? { markerPath: toRelative(projectRoot, join(match.packageDir, "package.json")) }
872
+ : {}),
873
+ });
874
+ }
875
+ }
876
+
777
877
  // Audit ronde 2: file server di luar kontrak §12 ditolak (tidak bisa di-stub).
778
878
  if (resolvedTarget !== null && isNonContractServerFile(resolvedTarget)) {
779
879
  throw nonContractServerFileError(resolvedTarget, projectRoot);
@@ -892,6 +992,31 @@ export async function checkClientModuleImports(
892
992
  const specifier = stripQuery(request.text);
893
993
  const resolvedTarget = await resolveSafe(specifier, file);
894
994
 
995
+ // Addendum D.1: dynamic import modul `src/api/**` juga ditolak.
996
+ if (apiDirReal !== null && resolvedTarget !== null && isInsideDir(resolvedTarget, apiDirReal)) {
997
+ rejectApiImport(request.node.loc?.start.line ?? 1, request.text, resolvedTarget);
998
+ }
999
+
1000
+ // Addendum C: dynamic import paket server-only juga digerbang.
1001
+ const match = serverOnly.check({
1002
+ specifier,
1003
+ resolvedFile: resolvedTarget,
1004
+ importerFile: file,
1005
+ });
1006
+ if (match !== null) {
1007
+ throw serverOnlyImportError({
1008
+ relativeFile,
1009
+ line: request.node.loc?.start.line ?? 1,
1010
+ specifier: request.text,
1011
+ packageName: match.packageName,
1012
+ source: match.source,
1013
+ dynamic: true,
1014
+ ...(match.source === "marker"
1015
+ ? { markerPath: toRelative(projectRoot, join(match.packageDir, "package.json")) }
1016
+ : {}),
1017
+ });
1018
+ }
1019
+
895
1020
  if (resolvedTarget !== null && isNonContractServerFile(resolvedTarget)) {
896
1021
  throw nonContractServerFileError(resolvedTarget, projectRoot);
897
1022
  }
@@ -980,8 +1105,7 @@ function dynamicImportRequest(node: AstNode): DynamicImportRequest | null {
980
1105
  return null;
981
1106
  }
982
1107
 
983
- function globPatterns(node: AstNode | undefined): string[] {
984
- if (node?.type === "StringLiteral") {
1108
+ function globPatterns(node: AstNode | undefined): string[] { if (node?.type === "StringLiteral") {
985
1109
  return [node["value"] as string];
986
1110
  }
987
1111
  if (node?.type === "ArrayExpression") {
@@ -1039,6 +1163,11 @@ function toRelative(projectRoot: string, file: string): string {
1039
1163
  return relative.split("\\").join("/");
1040
1164
  }
1041
1165
 
1166
+ function isInsideDir(file: string, dir: string): boolean {
1167
+ const normalized = dir.endsWith("/") ? dir : `${dir}/`;
1168
+ return file === dir || file.startsWith(normalized);
1169
+ }
1170
+
1042
1171
  export interface RouteExportCheckContext {
1043
1172
  file: string;
1044
1173
  code: string;
@@ -1048,7 +1177,8 @@ export interface RouteExportCheckContext {
1048
1177
 
1049
1178
  /**
1050
1179
  * §11.2 + §12.4: export legal per jenis modul route.
1051
- * page: `default|loader|meta`; layout: `default|loader`; `_error`/`_404`: `default`.
1180
+ * page: `default|loader|meta|prerender|paths` (D.5); layout: `default|loader`;
1181
+ * `_error`/`_404`: `default`.
1052
1182
  */
1053
1183
  export function checkRouteModuleExports(context: RouteExportCheckContext): void {
1054
1184
  const { file, code, routesDir, projectRoot } = context;
@@ -1066,7 +1196,7 @@ export function checkRouteModuleExports(context: RouteExportCheckContext): void
1066
1196
  ? ["default", "loader"]
1067
1197
  : base === "_error.tsx" || base === "_404.tsx"
1068
1198
  ? ["default"]
1069
- : ["default", "loader", "meta"];
1199
+ : ["default", "loader", "meta", "prerender", "paths", "revalidate"];
1070
1200
  const allowedText = `Hanya ${allowed.map((name) => `\`${name}\``).join(", ")} yang boleh di-export.`;
1071
1201
  const relativeFile = toRelative(projectRoot, file);
1072
1202
  const ast = parseModule(code, file);
@@ -1,6 +1,7 @@
1
1
  /** Nama virtual module PRD §9.4. Semua di-resolve ke id `\0`-prefix. */
2
2
  export const VIRTUAL_MODULES = {
3
3
  routes: "virtual:moons/routes",
4
+ api: "virtual:moons/api",
4
5
  config: "virtual:moons/config",
5
6
  clientEntry: "virtual:moons/client-entry",
6
7
  serverEntry: "virtual:moons/server-entry",
@@ -1,14 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/server/shell.ts", "../src/server/node.ts", "../src/virtual-modules.ts", "../src/server/dev.ts", "../src/manifest.ts"],
4
- "sourcesContent": [
5
- "import { MoonsError } from \"@moonsjs/core\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { ViteDevServer } from \"vite\";\n\nexport type Shell = (\n markup: string,\n payload: string,\n url: string,\n meta?: Record<string, unknown>,\n) => string | Promise<string>;\n\nexport const ROOT_PLACEHOLDER = '<div id=\"root\"></div>';\n\nexport const DEFAULT_TEMPLATE = [\n \"<!doctype html>\",\n '<html lang=\"id\">',\n \"<head>\",\n ' <meta charset=\"utf-8\" />',\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n \" <title>Moons</title>\",\n \"</head>\",\n \"<body>\",\n ` ${ROOT_PLACEHOLDER}`,\n ' <script type=\"module\" src=\"/src/client/main.tsx\"></script>',\n \"</body>\",\n \"</html>\",\n \"\",\n].join(\"\\n\");\n\n/** Inject markup SSR + payload devalue ke shell HTML (PRD §8.2, §17, Addendum B.1). */\nexport function injectShell(\n template: string,\n markup: string,\n payload: string,\n meta?: Record<string, unknown>,\n): string {\n if (!template.includes(ROOT_PLACEHOLDER)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `shell HTML tidak memuat \\`${ROOT_PLACEHOLDER}\\``,\n details: \"index.html aplikasi wajib memuat elemen root tersebut agar SSR bisa meng-inject markup.\",\n suggestions: [\n `Tambahkan ${ROOT_PLACEHOLDER} ke index.html`,\n \"Atau hapus index.html untuk memakai shell bawaan\",\n ],\n });\n }\n const dataScript = `<script id=\"__moons_data\" type=\"application/x-moons\">${payload}</script>`;\n const withRoot = template.replace(ROOT_PLACEHOLDER, `<div id=\"root\">${markup}</div>${dataScript}`);\n return applyMeta(withRoot, meta);\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\");\n}\n\n/**\n * Terapkan meta route ke `<head>` (Addendum B.1): `<title>` + description/og.\n * Tag yang sudah ada (mis. di index.html) ditimpa; yang belum ada disisipkan\n * sebelum `</head>`.\n */\nfunction applyMeta(html: string, meta: Record<string, unknown> | undefined): string {\n if (meta === undefined) {\n return html;\n }\n let out = html;\n if (typeof meta.title === \"string\") {\n const title = `<title>${escapeHtml(meta.title)}</title>`;\n out = /<title>[\\s\\S]*?<\\/title>/.test(out)\n ? out.replace(/<title>[\\s\\S]*?<\\/title>/, title)\n : out.replace(\"</head>\", ` ${title}\\n</head>`);\n }\n\n const tags: Array<{ attr: \"name\" | \"property\"; key: string; value: unknown }> = [\n { attr: \"name\", key: \"description\", value: meta.description },\n { attr: \"property\", key: \"og:title\", value: meta.title },\n { attr: \"property\", key: \"og:description\", value: meta.description },\n ];\n for (const tag of tags) {\n if (typeof tag.value !== \"string\") {\n continue;\n }\n const rendered = `<meta ${tag.attr}=\"${tag.key}\" content=\"${escapeHtml(tag.value)}\" />`;\n const pattern = new RegExp(`<meta[^>]*${tag.attr}=\"${tag.key}\"[^>]*>`);\n out = pattern.test(out)\n ? out.replace(pattern, rendered)\n : out.replace(\"</head>\", ` ${rendered}\\n</head>`);\n }\n return out;\n}\n\n/**\n * Shell untuk dev: baca `index.html` dari disk setiap request (selalu segar)\n * lalu lewatkan ke Vite `transformIndexHtml` (inject `/@vite/client`, dsb).\n */\nexport function createDevShell(server: ViteDevServer, options: { templatePath: string }): Shell {\n return async (markup, payload, url, meta) => {\n const template = existsSync(options.templatePath)\n ? readFileSync(options.templatePath, \"utf8\")\n : DEFAULT_TEMPLATE;\n const html = injectShell(template, markup, payload, meta);\n return await server.transformIndexHtml(url, html);\n };\n}\n\n/** Shell untuk produksi: baca `dist/client/index.html` sekali dari cwd. */\nexport function createFileShell(options: { clientDir?: string } = {}): Shell {\n let cached: string | null = null;\n return async (markup, payload, _url, meta) => {\n if (cached === null) {\n const clientDir = resolve(options.clientDir ?? process.cwd(), \"dist/client\");\n const file = join(clientDir, \"index.html\");\n if (!existsSync(file)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"`dist/client/index.html` tidak ditemukan\",\n details: \"Build client harus dijalankan sebelum server produksi dinyalakan (PRD §18).\",\n suggestions: [\"Jalankan `bun run build` lebih dulu\"],\n });\n }\n cached = readFileSync(file, \"utf8\");\n }\n return injectShell(cached, markup, payload, meta);\n };\n}\n",
6
- "import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nconst MAX_BODY_BYTES = 32 * 1024 * 1024; // batas defensif transport; limit RPC §7.3 tetap berlaku\n\n/** Konversi request Node → Web `Request` (body diteruskan untuk non-GET/HEAD, §7.3). */\nexport async function toWebRequest(req: IncomingMessage): Promise<Request> {\n const host = req.headers.host ?? \"localhost\";\n const url = `http://${host}${req.url ?? \"/\"}`;\n const method = req.method ?? \"GET\";\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined || key === \"content-length\") {\n // content-length tidak disalin; fetch menghitung ulang dari body.\n continue;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(key, item);\n }\n } else {\n headers.set(key, value);\n }\n }\n\n if (method === \"GET\" || method === \"HEAD\") {\n return new Request(url, { method, headers });\n }\n\n const body = await readBody(req);\n return new Request(url, { method, headers, body: new Uint8Array(body) });\n}\n\nfunction readBody(req: IncomingMessage): Promise<Buffer> {\n return new Promise((resolvePromise, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n\n req.on(\"data\", (chunk: Buffer) => {\n size += chunk.length;\n if (size > MAX_BODY_BYTES) {\n req.destroy();\n reject(new Error(\"request body melebihi batas transport\"));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => resolvePromise(Buffer.concat(chunks)));\n req.on(\"error\", (error) => reject(error));\n });\n}\n\n/** Tulis Web `Response` ke `ServerResponse` Node. */\nexport async function sendNodeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n const body = Buffer.from(await response.arrayBuffer());\n res.end(body);\n}\n",
7
- "/** Nama virtual module PRD §9.4. Semua di-resolve ke id `\\0`-prefix. */\nexport const VIRTUAL_MODULES = {\n routes: \"virtual:moons/routes\",\n config: \"virtual:moons/config\",\n clientEntry: \"virtual:moons/client-entry\",\n serverEntry: \"virtual:moons/server-entry\",\n} as const;\n\nexport type VirtualModuleName = (typeof VIRTUAL_MODULES)[keyof typeof VIRTUAL_MODULES];\n\nexport function isVirtualModuleId(id: string): id is VirtualModuleName {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n return (Object.values(VIRTUAL_MODULES) as string[]).includes(clean);\n}\n\nexport function toNullPrefixed(id: VirtualModuleName): `\\0${string}` {\n return `\\0${id}`;\n}\n\nexport function fromNullPrefixed(id: string): VirtualModuleName | null {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n return isVirtualModuleId(clean) ? (clean as VirtualModuleName) : null;\n}\n",
8
- "import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ViteDevServer } from \"vite\";\nimport { VIRTUAL_MODULES } from \"../virtual-modules\";\nimport type { PluginRuntime } from \"./plugins\";\nimport type { Shell } from \"./shell\";\nimport { createDevShell } from \"./shell\";\nimport { sendNodeResponse, toWebRequest } from \"./node\";\n\ninterface DevApp {\n handler: (request: Request) => Promise<Response>;\n plugins: PluginRuntime;\n}\n\ntype DevServerEntry = {\n createDevApp: (shell: Shell) => DevApp;\n};\n\n/**\n * Middleware SSR dev: dipasang sebelum middleware internal Vite, menangani\n * request HTML dan RPC serverFn (`/_moons/fn/*`) — modul/aset tetap Vite.\n * Handler + lifecycle plugin (Addendum B.4) diinisialisasi sekali.\n */\nexport function installDevMiddleware(\n server: ViteDevServer,\n options: { templatePath: string },\n): void {\n let appPromise: Promise<DevApp> | null = null;\n\n const getApp = (): Promise<DevApp> => {\n if (appPromise === null) {\n appPromise = (async () => {\n const entry = (await server.ssrLoadModule(VIRTUAL_MODULES.serverEntry)) as DevServerEntry;\n const app = entry.createDevApp(createDevShell(server, options));\n await app.plugins.start();\n await app.plugins.ready();\n return app;\n })();\n }\n return appPromise;\n };\n\n server.httpServer?.once(\"close\", () => {\n void appPromise?.then((app) => app.plugins.shutdown());\n });\n\n server.middlewares.use((req, res, next) => {\n if (!shouldHandle(req)) {\n next();\n return;\n }\n void handleRequest(getApp, req, res).catch((error: unknown) => {\n next(error as Error);\n });\n });\n}\n\nasync function handleRequest(\n getApp: () => Promise<DevApp>,\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<void> {\n const app = await getApp();\n const response = await app.handler(await toWebRequest(req));\n await sendNodeResponse(res, response);\n}\n\nfunction shouldHandle(req: IncomingMessage): boolean {\n const path = new URL(req.url ?? \"/\", \"http://localhost\").pathname;\n\n // RPC serverFn (semua method): dulu hanya GET/HEAD HTML yang dirutekan,\n // sehingga `POST /_moons/fn/<hash>` jatuh ke Vite (\"Cannot POST\", 404) dan\n // serverFn tidak bisa dipakai di dev (temuan eval T2 ronde 2; decisions/0016).\n if (path.startsWith(\"/_moons/fn/\")) {\n return true;\n }\n\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n return false;\n }\n if (path.startsWith(\"/@\") || path.startsWith(\"/node_modules/\") || path.startsWith(\"/__\")) {\n return false;\n }\n const lastSegment = path.split(\"/\").pop() ?? \"\";\n if (lastSegment.includes(\".\")) {\n return false;\n }\n const accept = req.headers.accept ?? \"\";\n return accept.includes(\"text/html\") || accept.includes(\"*/*\");\n}\n",
9
- "import { findLayouts, routeKeyFromFile, type RouteDefinition } from \"@moonsjs/core\";\nimport { relative, sep } from \"node:path\";\n\nexport interface ClientManifestEntry {\n page: string;\n layouts: string[];\n}\n\n/** Key manifest untuk halaman kustom `_404` dan `_error` (§11.2). */\nexport const NOT_FOUND_ROUTE_KEY = \"__moons/404\";\nexport const ERROR_ROUTE_KEY = \"__moons/error\";\n\n/**\n * Manifest route untuk client (PRD §8.2): key = key route file\n * (routeKeyFromFile), nilai = page + layout chain dari root ke leaf.\n */\nexport function buildClientManifest(\n routes: RouteDefinition[],\n routesDir: string,\n): Record<string, ClientManifestEntry> {\n const manifest: Record<string, ClientManifestEntry> = {};\n for (const route of routes) {\n if (route.kind !== \"page\") {\n continue;\n }\n const key = routeKeyFromFile(routesDir, route.file);\n manifest[key] = {\n page: key,\n layouts: findLayouts(route, routes).map((layout) => routeKeyFromFile(routesDir, layout.file)),\n };\n }\n\n const notFound = routes.find((route) => route.kind === \"404\");\n if (notFound !== undefined) {\n manifest[NOT_FOUND_ROUTE_KEY] = { page: routeKeyFromFile(routesDir, notFound.file), layouts: [] };\n }\n const errorRoute = routes.find((route) => route.kind === \"error\");\n if (errorRoute !== undefined) {\n manifest[ERROR_ROUTE_KEY] = { page: routeKeyFromFile(routesDir, errorRoute.file), layouts: [] };\n }\n\n return manifest;\n}\n\n/**\n * Isi `virtual:moons/routes`: daftar RouteDefinition, manifest client, dan\n * peta import() dinamis per file route (specifier root-relative).\n */\nexport function renderRoutesModule(\n routes: RouteDefinition[],\n routesDir: string,\n projectRoot: string,\n): string {\n const manifest = buildClientManifest(routes, routesDir);\n\n const loadEntries = routes.map((route) => {\n const key = routeKeyFromFile(routesDir, route.file);\n return ` ${JSON.stringify(key)}: () => import(${JSON.stringify(rootSpecifier(projectRoot, route.file))}),`;\n });\n\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n `export const routes = ${JSON.stringify(routes, null, 2)};`,\n \"\",\n `export const clientManifest = ${JSON.stringify(manifest, null, 2)};`,\n \"\",\n \"export const loadRoute = {\",\n ...loadEntries,\n \"};\",\n \"\",\n ].join(\"\\n\");\n}\n\n/** Path file absolut project → specifier root-relative yang bisa di-resolve Vite. */\nexport function rootSpecifier(projectRoot: string, file: string): string {\n let rel = relative(projectRoot, file);\n rel = sep === \"/\" ? rel : rel.split(sep).join(\"/\");\n return rel.startsWith(\"/\") ? rel : `/${rel}`;\n}\n"
10
- ],
11
- "mappings": "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",
12
- "debugId": "F771C1CCD222FC0D64756E2164756E21",
13
- "names": []
14
- }
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/transform.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\";\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\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 \"Stub client (PRD §12.2/§12.3) hanya membawa import dan ekspresi schema; \" +\n \"deklarasi lokal dibuang sehingga referensi menjadi `undefined` di browser (crash hydration).\",\n suggestions: [\n \"Inline schema langsung di argumen `serverFn({ input, output })`, atau\",\n \"Impor schema dari modul lain (mis. `src/shared/schemas.ts`)\",\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}\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\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\n if (specifier.startsWith(\"node:\") || specifier.startsWith(\"bun:\")) {\n rejectForbidden(line, specifier);\n }\n\n const resolvedTarget = await resolveSafe(specifier, file);\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 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[] {\n 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\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`; layout: `default|loader`; `_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\"];\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
- ],
7
- "mappings": "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",
8
- "debugId": "6E8CE67B8B7578C064756E2164756E21",
9
- "names": []
10
- }