@moonsjs/vite 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -589,6 +589,7 @@ function renderPrerenderEntry(routesDir, projectRoot, canary) {
589
589
  ` routesDir: ${JSON.stringify(routesDir)},`,
590
590
  " loadRoute,",
591
591
  " handler,",
592
+ " staticConfig: config,",
592
593
  ` clientDir: ${JSON.stringify(resolvePath(projectRoot, "dist/client"))},`,
593
594
  ...canary === undefined ? [] : [` canary: ${JSON.stringify(canary)},`],
594
595
  "});",
@@ -622,4 +623,4 @@ export {
622
623
  moons as default
623
624
  };
624
625
 
625
- //# debugId=858C3A2CF24FAEB764756E2164756E21
626
+ //# debugId=C19ACBFCC6A7B10A64756E2164756E21
package/dist/index.js.map CHANGED
@@ -2,11 +2,11 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/plugin.ts", "../src/api.ts", "../src/leak-check.ts"],
4
4
  "sourcesContent": [
5
- "import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n MoonsError,\n fnRegistryKey,\n generateTypes,\n scanApiMiddlewares,\n scanApiRoutes,\n scanRoutes,\n validateConfig,\n type ApiMiddlewareDefinition,\n type ApiRouteDefinition,\n type RouteDefinition,\n} from \"@moonsjs/core\";\nimport { loadConfigFromFile, type Plugin, type ViteDevServer } from \"vite\";\nimport { assertApiModuleExports, assertMiddlewareExports } from \"./api\";\nimport { findLeak } from \"./leak-check\";\nimport type { PackageJsonInfo } from \"./server-only\";\nimport { renderApiModule, renderRoutesModule, rootSpecifier } from \"./manifest\";\nimport { installDevMiddleware } from \"./server/dev\";\nimport {\n analyzeServerFile,\n checkClientModuleImports,\n checkRouteModuleExports,\n injectServerFnMeta,\n isNonContractServerFile,\n isServerFilePath,\n nonContractServerFileError,\n renderServerFnStub,\n resolveServerSpecifierSync,\n scanServerFiles,\n stripQuery,\n type ServerFileAnalysis,\n} from \"./transform\";\nimport { fromNullPrefixed, VIRTUAL_MODULES } from \"./virtual-modules\";\n\nexport interface MoonsVitePluginOptions {\n /** Default: \"moons.config.ts\". */\n configPath?: string;\n /** Hanya dipakai di CI (M2 §21). */\n leakTest?: { canary?: string };\n /** Default: root Vite. */\n projectRoot?: string;\n}\n\n/**\n * Plugin `@moonsjs/vite` (PRD §9): scan route, typegen, virtual module,\n * dev SSR middleware, build client + server.\n */\nconst CODE_FILE_PATTERN = /\\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;\n\nexport default function moons(options: MoonsVitePluginOptions = {}): Plugin {\n let root = options.projectRoot ?? process.cwd();\n let isSsrBuild = false;\n let configFilePath = \"\";\n let routesDir = \"\";\n let serverOnlyPackages: ReadonlyArray<string> = [];\n let apiDir = \"\";\n let apiRoutes: ApiRouteDefinition[] = [];\n let apiMiddlewares: ApiMiddlewareDefinition[] = [];\n /** Cache package.json untuk gate Addendum C (dibagi lintas modul). */\n const packageCache = new Map<string, PackageJsonInfo | null>(); let routes: RouteDefinition[] = [];\n let analysisCache = new Map<string, ServerFileAnalysis>();\n const stubTransformed = new Set<string>();\n\n function analyzeFile(absoluteFile: string): ServerFileAnalysis | null {\n const cached = analysisCache.get(absoluteFile);\n if (cached !== undefined) {\n return cached;\n }\n let source: string;\n try {\n source = readFileSync(absoluteFile, \"utf8\");\n } catch {\n return null;\n }\n const analysis = analyzeServerFile(source, absoluteFile, root);\n analysisCache.set(absoluteFile, analysis);\n return analysis;\n }\n\n function refreshServerFns(): void {\n const next = new Map<string, ServerFileAnalysis>();\n const registry: Record<string, string> = {};\n\n for (const file of scanServerFiles(root)) {\n let source: string;\n try {\n source = readFileSync(file, \"utf8\");\n } catch {\n continue;\n }\n const analysis = analyzeServerFile(source, file, root);\n next.set(file, analysis);\n for (const fn of analysis.serverFns) {\n registry[fnRegistryKey(root, file, fn.name)] = fn.hash;\n }\n }\n\n analysisCache = next;\n const outDir = resolvePath(root, \".moons\");\n mkdirSync(outDir, { recursive: true });\n writeFileSync(\n resolvePath(outDir, \"fn-registry.json\"),\n `${JSON.stringify(registry, null, 2)}\\n`,\n \"utf8\",\n );\n }\n\n /** Semua specifier file `.server.ts` yang punya serverFn (untuk eager import di entry server). */\n function serverFnFileSpecifiers(): string[] {\n const specifiers: string[] = [];\n for (const [file, analysis] of analysisCache) {\n if (analysis.serverFns.length > 0) {\n specifiers.push(rootSpecifier(root, file));\n }\n }\n return specifiers.sort();\n }\n\n /** Stub client §12.2 + cache §12.2.5. */\n function transformServerFileClient(code: string, id: string): string {\n const relativePath = id.startsWith(root)\n ? id.slice(root.length).split(\"\\\\\").join(\"/\")\n : id;\n const cacheKey = createHash(\"sha256\").update(`${relativePath}\\0${code}`).digest(\"hex\");\n const cacheFile = resolvePath(root, \".moons/cache\", `${cacheKey}.js`);\n\n if (existsSync(cacheFile)) {\n stubTransformed.add(id);\n return readFileSync(cacheFile, \"utf8\");\n }\n\n const analysis = analyzeFile(id);\n if (analysis === null) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file: id,\n message: \"gagal membaca file server untuk transform\",\n details: \"File `.server.ts` harus bisa dibaca saat transform.\",\n suggestions: [\"Periksa path dan izin file\"],\n });\n }\n\n const stub = renderServerFnStub(code, id, analysis, {\n analyzeSpecifier: (sourceFile, specifier) => {\n const resolved = resolveServerSpecifierSync(sourceFile, specifier);\n return resolved === null ? null : analyzeFile(resolved);\n },\n });\n\n mkdirSync(resolvePath(root, \".moons/cache\"), { recursive: true });\n writeFileSync(cacheFile, stub.code, \"utf8\");\n stubTransformed.add(id);\n return stub.code;\n }\n\n return {\n name: \"moons\",\n enforce: \"pre\",\n\n config(_config, env) {\n isSsrBuild = env.isSsrBuild === true;\n const common = {\n appType: \"custom\" as const,\n };\n\n if (isSsrBuild) {\n return {\n ...common,\n build: {\n outDir: \"dist/server\",\n emptyOutDir: true,\n // Entry nyata yang di-generate saat buildStart (Rolldown butuh file,\n // entry virtual tidak di-resolve lewat plugin container).\n // D.5: dua entry — server (index) + prerender runner.\n ssr: true,\n rollupOptions: {\n input: {\n index: \".moons/server-entry.ts\",\n prerender: \".moons/prerender-entry.ts\",\n },\n output: {\n entryFileNames: \"[name].js\",\n chunkFileNames: \"chunks/[name]-[hash].js\",\n },\n },\n },\n ssr: { noExternal: true, target: \"node\" as const },\n };\n }\n\n return {\n ...common,\n build: { outDir: \"dist/client\", emptyOutDir: true },\n // Dev SSR: paket framework WAJIB di-inline ke pipeline Vite. Sejak\n // dipublikasikan, `@moonsjs/*` adalah package node_modules biasa (bukan\n // workspace-link) sehingga default Vite mengeksternalnya; import runtime\n // (bun) menyelesaikannya lewat kondisi `bun` → `src`, sedangkan modul\n // route diselesaikan Vite → `dist` — dua instans React context →\n // \"useLoaderData dipanggil di luar render route\" (temuan eval T4;\n // docs/decisions/0015). Inline → semua konsisten lewat Vite.\n ssr: { noExternal: [/^@moonsjs\\//] },\n };\n },\n\n async configResolved(resolved) {\n root = options.projectRoot ?? resolved.root;\n configFilePath = resolvePath(root, options.configPath ?? \"moons.config.ts\");\n\n if (!existsSync(configFilePath)) {\n throw new MoonsError({\n code: \"E_CONFIG_INVALID\",\n file: configFilePath,\n message: \"`moons.config.ts` tidak ditemukan\",\n details: \"Framework membutuhkan file config di root project.\",\n suggestions: [\n \"Buat `moons.config.ts` dengan `export default defineConfig({ context: async (req) => ({}) })`\",\n ],\n });\n }\n\n let raw: unknown;\n try {\n const loaded = await loadConfigFromFile(\n { command: resolved.command, mode: resolved.mode },\n configFilePath,\n root,\n );\n raw = loaded?.config;\n } catch (error) {\n if (error instanceof MoonsError) {\n throw error;\n }\n throw new MoonsError({\n code: \"E_CONFIG_INVALID\",\n file: configFilePath,\n message: \"gagal memuat `moons.config.ts`\",\n details: error instanceof Error ? error.message : String(error),\n suggestions: [\"Periksa sintaks dan import di `moons.config.ts`\"],\n });\n }\n\n const config = validateConfig(raw, { file: configFilePath, projectRoot: root });\n routesDir = resolvePath(root, config.routesDir);\n serverOnlyPackages = config.security?.serverOnlyPackages ?? [];\n\n // Addendum D.1: scan + validasi statis modul `src/api`.\n apiDir = resolvePath(root, config.apiDir ?? \"src/api\");\n if (existsSync(apiDir)) {\n apiRoutes = scanApiRoutes(apiDir);\n for (const route of apiRoutes) {\n assertApiModuleExports(readFileSync(route.file, \"utf8\"), route.file);\n }\n apiMiddlewares = scanApiMiddlewares(apiDir);\n for (const middleware of apiMiddlewares) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n } else {\n apiRoutes = [];\n apiMiddlewares = [];\n }\n },\n\n async buildStart() {\n routes = scanRoutes(routesDir);\n // D.3: validasi statis `_middleware.ts` pohon routes.\n for (const middleware of routes.filter((route) => route.kind === \"middleware\")) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n await generateTypes({\n routesDir,\n configPath: configFilePath,\n outDir: resolvePath(root, \".moons\"),\n });\n refreshServerFns();\n if (isSsrBuild) {\n writeFileSync(\n resolvePath(root, \".moons/server-entry.ts\"),\n renderServerEntryBuild(routesDir, serverFnFileSpecifiers(), options.leakTest?.canary),\n \"utf8\",\n );\n writeFileSync(\n resolvePath(root, \".moons/prerender-entry.ts\"),\n renderPrerenderEntry(routesDir, root, options.leakTest?.canary),\n \"utf8\",\n );\n }\n },\n\n resolveId(id) {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n if ((Object.values(VIRTUAL_MODULES) as string[]).includes(clean)) {\n return `\\0${clean}`;\n }\n return undefined;\n },\n\n load(id) {\n const name = fromNullPrefixed(id);\n if (name === null) {\n return undefined;\n }\n switch (name) {\n case VIRTUAL_MODULES.routes:\n return renderRoutesModule(routes, routesDir, root);\n case VIRTUAL_MODULES.api:\n return renderApiModule(apiRoutes, apiMiddlewares, root);\n case VIRTUAL_MODULES.clientEntry:\n return '// Generated by @moons. Jangan diubah manual.\\nexport { clientManifest, loadRoute } from \"virtual:moons/routes\";\\n';\n case VIRTUAL_MODULES.config:\n return renderConfigModule(root, configFilePath);\n case VIRTUAL_MODULES.serverEntry:\n // Hanya dipakai dev (ssrLoadModule); build memakai .moons/server-entry.ts.\n return renderServerEntryDev(routesDir, serverFnFileSpecifiers());\n }\n },\n\n async transform(code, id) {\n const cleanId = stripQuery(id);\n if (cleanId.startsWith(\"\\0\") || cleanId.includes(\"/node_modules/\")) {\n return undefined;\n }\n\n const environment = environmentName(this);\n\n if (isServerFilePath(cleanId)) {\n if (environment === \"ssr\") {\n const analysis = analysisCache.get(cleanId) ?? analyzeFile(cleanId);\n if (analysis === null || analysis.serverFns.length === 0) {\n return undefined;\n }\n return injectServerFnMeta(code, analysis, root);\n }\n return transformServerFileClient(code, cleanId);\n }\n\n // Audit ronde 2: file server di luar kontrak §12 tidak bisa di-stub —\n // jangan pernah biarkan masuk graph client.\n if (environment !== \"ssr\" && isNonContractServerFile(cleanId)) {\n throw nonContractServerFileError(cleanId, root);\n }\n\n if (environment !== \"ssr\" && CODE_FILE_PATTERN.test(cleanId)) {\n if (cleanId.startsWith(routesDir) && cleanId.endsWith(\".tsx\")) {\n checkRouteModuleExports({\n file: cleanId,\n code,\n routesDir,\n projectRoot: root,\n });\n }\n await checkClientModuleImports({\n file: cleanId,\n code,\n projectRoot: root,\n // Resolusi penuh (alias Vite, tsconfig paths, symlink) — audit ronde 2.\n resolve: async (specifier, importer) => {\n try {\n const resolved = await this.resolve(specifier, importer);\n return resolved === null ? null : stripQuery(resolved.id);\n } catch {\n return null;\n }\n },\n analyze: (absoluteFile) => analysisCache.get(absoluteFile) ?? analyzeFile(absoluteFile),\n apiDir,\n serverOnlyPackages,\n packageCache,\n });\n }\n\n return undefined;\n },\n\n generateBundle(_options, bundle) {\n if (environmentName(this) === \"ssr\") {\n return;\n }\n\n const canary = options.leakTest?.canary;\n if (canary !== undefined && canary.length > 0) {\n const leak = findLeak(Object.values(bundle), canary);\n if (leak !== null) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `canary \\`${canary}\\` ditemukan di bundle client (${leak.fileName})`,\n details:\n \"Verifikasi kebocoran gagal: kode server bocor ke output client. Build dihentikan.\",\n suggestions: [\n \"Periksa transform `*.server.ts`\",\n \"Jalankan `./scripts/m2/test-leak.sh` untuk audit\",\n ],\n });\n }\n }\n\n for (const output of Object.values(bundle)) {\n if (output.type !== \"chunk\") {\n continue;\n }\n for (const moduleId of Object.keys(output.modules)) {\n const cleanId = stripQuery(moduleId);\n if (!isServerFilePath(cleanId) || stubTransformed.has(cleanId)) {\n continue;\n }\n throw new MoonsError({\n code: \"E_FORBIDDEN_SERVER_IMPORT\",\n file: cleanId,\n message: \"modul server ikut ter-bundle di client tanpa melewati transform\",\n details:\n \"Verifikasi build: setiap `*.server.ts` di bundle client wajib berupa stub RPC hasil transform.\",\n suggestions: [\n \"Pastikan transform zero-trust berjalan untuk modul ini\",\n \"Laporkan ini sebagai bug framework jika berulang\",\n ],\n });\n }\n }\n },\n\n configureServer(server) {\n installDevMiddleware(server, {\n templatePath: resolvePath(root, \"index.html\"),\n // A1: pemindaian payload SSR hanya di dev (warning), tanpa biaya di production.\n payloadScan: {\n ...(options.leakTest?.canary === undefined ? {} : { canary: options.leakTest.canary }),\n env: process.env,\n },\n // D.1: request ke prefix API (semua method) dirutekan ke runtime.\n ...(apiRoutes.length === 0\n ? {}\n : { apiPrefix: `/${apiDir.split(/[\\\\/]/).filter((part) => part.length > 0).pop() ?? \"api\"}` }),\n });\n },\n\n async handleHotUpdate(context) {\n if (isServerFilePath(context.file)) {\n refreshServerFns();\n context.server.ws.send({ type: \"full-reload\" });\n return;\n }\n\n if (context.file.startsWith(apiDir) && existsSync(apiDir)) {\n try {\n apiRoutes = scanApiRoutes(apiDir);\n for (const route of apiRoutes) {\n assertApiModuleExports(readFileSync(route.file, \"utf8\"), route.file);\n }\n apiMiddlewares = scanApiMiddlewares(apiDir);\n for (const middleware of apiMiddlewares) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n } catch (error) {\n context.server.config.logger.error(String(error));\n return;\n }\n invalidateVirtualModules(context.server);\n context.server.ws.send({ type: \"full-reload\" });\n return;\n }\n\n if (!context.file.startsWith(routesDir)) {\n return;\n }\n\n try {\n routes = scanRoutes(routesDir);\n for (const middleware of routes.filter((route) => route.kind === \"middleware\")) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n await generateTypes({\n routesDir,\n configPath: configFilePath,\n outDir: resolvePath(root, \".moons\"),\n });\n } catch (error) {\n context.server.config.logger.error(String(error));\n return;\n }\n\n invalidateVirtualModules(context.server);\n context.server.ws.send({ type: \"full-reload\" });\n },\n };\n}\n\nfunction renderConfigModule(root: string, configFilePath: string): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n `import raw from ${JSON.stringify(rootSpecifier(root, configFilePath))};`,\n 'import { validateConfig } from \"@moonsjs/core\";',\n `export default validateConfig(raw, { file: ${JSON.stringify(configFilePath)} });`,\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderServerEntryDev(routesDir: string, eagerImports: string[]): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createPluginRuntime, createRequestHandler } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n 'import { apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware } from \"virtual:moons/api\";',\n ...eagerImports.map((specifier) => `import ${JSON.stringify(specifier)};`),\n \"\",\n \"export function createDevApp(shell, payloadScan) {\",\n \" const plugins = createPluginRuntime({ config, routes, middlewares: config.middleware ?? [] });\",\n ` const handler = createRequestHandler({ routes, apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware, config, routesDir: ${JSON.stringify(routesDir)}, loadRoute, shell, onContext: (ctx) => plugins.applyExtensions(ctx), ...(payloadScan === undefined ? {} : { payloadScan }) });`,\n \" return { handler, plugins };\",\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderServerEntryBuild(\n routesDir: string,\n eagerImports: string[],\n canary: string | undefined,\n): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createFileShell, createPluginRuntime, createRequestHandler, startNodeServer } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n 'import { apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware } from \"virtual:moons/api\";',\n ...eagerImports.map((specifier) => `import ${JSON.stringify(specifier)};`),\n \"\",\n \"const plugins = createPluginRuntime({ config, routes, middlewares: config.middleware ?? [] });\",\n \"const handler = createRequestHandler({\",\n \" routes,\",\n \" apiRoutes,\",\n \" apiMiddlewares,\",\n \" loadApi,\",\n \" loadApiMiddleware,\",\n \" config,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" shell: createFileShell(),\",\n \" onContext: (ctx) => plugins.applyExtensions(ctx),\",\n \"});\",\n \"\",\n `startNodeServer(handler, { plugins${canary === undefined ? \"\" : `, canary: ${JSON.stringify(canary)}`} });`,\n \"\",\n ].join(\"\\n\");\n}\n\ninterface ModuleGraphLike {\n getModulesByFile(file: string): Iterable<{ id?: string | null }> | undefined;\n invalidateModule(module: unknown): void;\n}\n\n/** Entry D.5: runner prerender (dijalankan CLI setelah build server). */\nfunction renderPrerenderEntry(\n routesDir: string,\n projectRoot: string,\n canary: string | undefined,\n): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createFileShell, createRequestHandler, runPrerender } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n \"\",\n \"const handler = createRequestHandler({\",\n \" routes,\",\n \" config,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" shell: createFileShell(),\",\n \"});\",\n \"\",\n \"await runPrerender({\",\n \" routes,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" handler,\",\n ` clientDir: ${JSON.stringify(resolvePath(projectRoot, \"dist/client\"))},`,\n ...(canary === undefined ? [] : [` canary: ${JSON.stringify(canary)},`]),\n \"});\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction environmentName(context: unknown): string {\n const environment = (context as { environment?: { name?: string } } | undefined)?.environment;\n return environment?.name ?? \"client\";\n}\n\nfunction invalidateVirtualModules(server: ViteDevServer): void {\n const graphs: ModuleGraphLike[] = [server.moduleGraph as unknown as ModuleGraphLike];\n const environments = (server as unknown as { environments?: Record<string, { moduleGraph?: unknown }> })\n .environments;\n if (environments !== undefined) {\n for (const environment of Object.values(environments)) {\n if (environment.moduleGraph !== undefined) {\n graphs.push(environment.moduleGraph as ModuleGraphLike);\n }\n }\n }\n\n for (const graph of graphs) {\n for (const name of Object.values(VIRTUAL_MODULES)) {\n for (const module of graph.getModulesByFile(`\\0${name}`) ?? []) {\n graph.invalidateModule(module);\n }\n }\n }\n}\n",
5
+ "import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { resolve as resolvePath } from \"node:path\";\nimport {\n MoonsError,\n fnRegistryKey,\n generateTypes,\n scanApiMiddlewares,\n scanApiRoutes,\n scanRoutes,\n validateConfig,\n type ApiMiddlewareDefinition,\n type ApiRouteDefinition,\n type RouteDefinition,\n} from \"@moonsjs/core\";\nimport { loadConfigFromFile, type Plugin, type ViteDevServer } from \"vite\";\nimport { assertApiModuleExports, assertMiddlewareExports } from \"./api\";\nimport { findLeak } from \"./leak-check\";\nimport type { PackageJsonInfo } from \"./server-only\";\nimport { renderApiModule, renderRoutesModule, rootSpecifier } from \"./manifest\";\nimport { installDevMiddleware } from \"./server/dev\";\nimport {\n analyzeServerFile,\n checkClientModuleImports,\n checkRouteModuleExports,\n injectServerFnMeta,\n isNonContractServerFile,\n isServerFilePath,\n nonContractServerFileError,\n renderServerFnStub,\n resolveServerSpecifierSync,\n scanServerFiles,\n stripQuery,\n type ServerFileAnalysis,\n} from \"./transform\";\nimport { fromNullPrefixed, VIRTUAL_MODULES } from \"./virtual-modules\";\n\nexport interface MoonsVitePluginOptions {\n /** Default: \"moons.config.ts\". */\n configPath?: string;\n /** Hanya dipakai di CI (M2 §21). */\n leakTest?: { canary?: string };\n /** Default: root Vite. */\n projectRoot?: string;\n}\n\n/**\n * Plugin `@moonsjs/vite` (PRD §9): scan route, typegen, virtual module,\n * dev SSR middleware, build client + server.\n */\nconst CODE_FILE_PATTERN = /\\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/;\n\nexport default function moons(options: MoonsVitePluginOptions = {}): Plugin {\n let root = options.projectRoot ?? process.cwd();\n let isSsrBuild = false;\n let configFilePath = \"\";\n let routesDir = \"\";\n let serverOnlyPackages: ReadonlyArray<string> = [];\n let apiDir = \"\";\n let apiRoutes: ApiRouteDefinition[] = [];\n let apiMiddlewares: ApiMiddlewareDefinition[] = [];\n /** Cache package.json untuk gate Addendum C (dibagi lintas modul). */\n const packageCache = new Map<string, PackageJsonInfo | null>(); let routes: RouteDefinition[] = [];\n let analysisCache = new Map<string, ServerFileAnalysis>();\n const stubTransformed = new Set<string>();\n\n function analyzeFile(absoluteFile: string): ServerFileAnalysis | null {\n const cached = analysisCache.get(absoluteFile);\n if (cached !== undefined) {\n return cached;\n }\n let source: string;\n try {\n source = readFileSync(absoluteFile, \"utf8\");\n } catch {\n return null;\n }\n const analysis = analyzeServerFile(source, absoluteFile, root);\n analysisCache.set(absoluteFile, analysis);\n return analysis;\n }\n\n function refreshServerFns(): void {\n const next = new Map<string, ServerFileAnalysis>();\n const registry: Record<string, string> = {};\n\n for (const file of scanServerFiles(root)) {\n let source: string;\n try {\n source = readFileSync(file, \"utf8\");\n } catch {\n continue;\n }\n const analysis = analyzeServerFile(source, file, root);\n next.set(file, analysis);\n for (const fn of analysis.serverFns) {\n registry[fnRegistryKey(root, file, fn.name)] = fn.hash;\n }\n }\n\n analysisCache = next;\n const outDir = resolvePath(root, \".moons\");\n mkdirSync(outDir, { recursive: true });\n writeFileSync(\n resolvePath(outDir, \"fn-registry.json\"),\n `${JSON.stringify(registry, null, 2)}\\n`,\n \"utf8\",\n );\n }\n\n /** Semua specifier file `.server.ts` yang punya serverFn (untuk eager import di entry server). */\n function serverFnFileSpecifiers(): string[] {\n const specifiers: string[] = [];\n for (const [file, analysis] of analysisCache) {\n if (analysis.serverFns.length > 0) {\n specifiers.push(rootSpecifier(root, file));\n }\n }\n return specifiers.sort();\n }\n\n /** Stub client §12.2 + cache §12.2.5. */\n function transformServerFileClient(code: string, id: string): string {\n const relativePath = id.startsWith(root)\n ? id.slice(root.length).split(\"\\\\\").join(\"/\")\n : id;\n const cacheKey = createHash(\"sha256\").update(`${relativePath}\\0${code}`).digest(\"hex\");\n const cacheFile = resolvePath(root, \".moons/cache\", `${cacheKey}.js`);\n\n if (existsSync(cacheFile)) {\n stubTransformed.add(id);\n return readFileSync(cacheFile, \"utf8\");\n }\n\n const analysis = analyzeFile(id);\n if (analysis === null) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file: id,\n message: \"gagal membaca file server untuk transform\",\n details: \"File `.server.ts` harus bisa dibaca saat transform.\",\n suggestions: [\"Periksa path dan izin file\"],\n });\n }\n\n const stub = renderServerFnStub(code, id, analysis, {\n analyzeSpecifier: (sourceFile, specifier) => {\n const resolved = resolveServerSpecifierSync(sourceFile, specifier);\n return resolved === null ? null : analyzeFile(resolved);\n },\n });\n\n mkdirSync(resolvePath(root, \".moons/cache\"), { recursive: true });\n writeFileSync(cacheFile, stub.code, \"utf8\");\n stubTransformed.add(id);\n return stub.code;\n }\n\n return {\n name: \"moons\",\n enforce: \"pre\",\n\n config(_config, env) {\n isSsrBuild = env.isSsrBuild === true;\n const common = {\n appType: \"custom\" as const,\n };\n\n if (isSsrBuild) {\n return {\n ...common,\n build: {\n outDir: \"dist/server\",\n emptyOutDir: true,\n // Entry nyata yang di-generate saat buildStart (Rolldown butuh file,\n // entry virtual tidak di-resolve lewat plugin container).\n // D.5: dua entry — server (index) + prerender runner.\n ssr: true,\n rollupOptions: {\n input: {\n index: \".moons/server-entry.ts\",\n prerender: \".moons/prerender-entry.ts\",\n },\n output: {\n entryFileNames: \"[name].js\",\n chunkFileNames: \"chunks/[name]-[hash].js\",\n },\n },\n },\n ssr: { noExternal: true, target: \"node\" as const },\n };\n }\n\n return {\n ...common,\n build: { outDir: \"dist/client\", emptyOutDir: true },\n // Dev SSR: paket framework WAJIB di-inline ke pipeline Vite. Sejak\n // dipublikasikan, `@moonsjs/*` adalah package node_modules biasa (bukan\n // workspace-link) sehingga default Vite mengeksternalnya; import runtime\n // (bun) menyelesaikannya lewat kondisi `bun` → `src`, sedangkan modul\n // route diselesaikan Vite → `dist` — dua instans React context →\n // \"useLoaderData dipanggil di luar render route\" (temuan eval T4;\n // docs/decisions/0015). Inline → semua konsisten lewat Vite.\n ssr: { noExternal: [/^@moonsjs\\//] },\n };\n },\n\n async configResolved(resolved) {\n root = options.projectRoot ?? resolved.root;\n configFilePath = resolvePath(root, options.configPath ?? \"moons.config.ts\");\n\n if (!existsSync(configFilePath)) {\n throw new MoonsError({\n code: \"E_CONFIG_INVALID\",\n file: configFilePath,\n message: \"`moons.config.ts` tidak ditemukan\",\n details: \"Framework membutuhkan file config di root project.\",\n suggestions: [\n \"Buat `moons.config.ts` dengan `export default defineConfig({ context: async (req) => ({}) })`\",\n ],\n });\n }\n\n let raw: unknown;\n try {\n const loaded = await loadConfigFromFile(\n { command: resolved.command, mode: resolved.mode },\n configFilePath,\n root,\n );\n raw = loaded?.config;\n } catch (error) {\n if (error instanceof MoonsError) {\n throw error;\n }\n throw new MoonsError({\n code: \"E_CONFIG_INVALID\",\n file: configFilePath,\n message: \"gagal memuat `moons.config.ts`\",\n details: error instanceof Error ? error.message : String(error),\n suggestions: [\"Periksa sintaks dan import di `moons.config.ts`\"],\n });\n }\n\n const config = validateConfig(raw, { file: configFilePath, projectRoot: root });\n routesDir = resolvePath(root, config.routesDir);\n serverOnlyPackages = config.security?.serverOnlyPackages ?? [];\n\n // Addendum D.1: scan + validasi statis modul `src/api`.\n apiDir = resolvePath(root, config.apiDir ?? \"src/api\");\n if (existsSync(apiDir)) {\n apiRoutes = scanApiRoutes(apiDir);\n for (const route of apiRoutes) {\n assertApiModuleExports(readFileSync(route.file, \"utf8\"), route.file);\n }\n apiMiddlewares = scanApiMiddlewares(apiDir);\n for (const middleware of apiMiddlewares) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n } else {\n apiRoutes = [];\n apiMiddlewares = [];\n }\n },\n\n async buildStart() {\n routes = scanRoutes(routesDir);\n // D.3: validasi statis `_middleware.ts` pohon routes.\n for (const middleware of routes.filter((route) => route.kind === \"middleware\")) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n await generateTypes({\n routesDir,\n configPath: configFilePath,\n outDir: resolvePath(root, \".moons\"),\n });\n refreshServerFns();\n if (isSsrBuild) {\n writeFileSync(\n resolvePath(root, \".moons/server-entry.ts\"),\n renderServerEntryBuild(routesDir, serverFnFileSpecifiers(), options.leakTest?.canary),\n \"utf8\",\n );\n writeFileSync(\n resolvePath(root, \".moons/prerender-entry.ts\"),\n renderPrerenderEntry(routesDir, root, options.leakTest?.canary),\n \"utf8\",\n );\n }\n },\n\n resolveId(id) {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n if ((Object.values(VIRTUAL_MODULES) as string[]).includes(clean)) {\n return `\\0${clean}`;\n }\n return undefined;\n },\n\n load(id) {\n const name = fromNullPrefixed(id);\n if (name === null) {\n return undefined;\n }\n switch (name) {\n case VIRTUAL_MODULES.routes:\n return renderRoutesModule(routes, routesDir, root);\n case VIRTUAL_MODULES.api:\n return renderApiModule(apiRoutes, apiMiddlewares, root);\n case VIRTUAL_MODULES.clientEntry:\n return '// Generated by @moons. Jangan diubah manual.\\nexport { clientManifest, loadRoute } from \"virtual:moons/routes\";\\n';\n case VIRTUAL_MODULES.config:\n return renderConfigModule(root, configFilePath);\n case VIRTUAL_MODULES.serverEntry:\n // Hanya dipakai dev (ssrLoadModule); build memakai .moons/server-entry.ts.\n return renderServerEntryDev(routesDir, serverFnFileSpecifiers());\n }\n },\n\n async transform(code, id) {\n const cleanId = stripQuery(id);\n if (cleanId.startsWith(\"\\0\") || cleanId.includes(\"/node_modules/\")) {\n return undefined;\n }\n\n const environment = environmentName(this);\n\n if (isServerFilePath(cleanId)) {\n if (environment === \"ssr\") {\n const analysis = analysisCache.get(cleanId) ?? analyzeFile(cleanId);\n if (analysis === null || analysis.serverFns.length === 0) {\n return undefined;\n }\n return injectServerFnMeta(code, analysis, root);\n }\n return transformServerFileClient(code, cleanId);\n }\n\n // Audit ronde 2: file server di luar kontrak §12 tidak bisa di-stub —\n // jangan pernah biarkan masuk graph client.\n if (environment !== \"ssr\" && isNonContractServerFile(cleanId)) {\n throw nonContractServerFileError(cleanId, root);\n }\n\n if (environment !== \"ssr\" && CODE_FILE_PATTERN.test(cleanId)) {\n if (cleanId.startsWith(routesDir) && cleanId.endsWith(\".tsx\")) {\n checkRouteModuleExports({\n file: cleanId,\n code,\n routesDir,\n projectRoot: root,\n });\n }\n await checkClientModuleImports({\n file: cleanId,\n code,\n projectRoot: root,\n // Resolusi penuh (alias Vite, tsconfig paths, symlink) — audit ronde 2.\n resolve: async (specifier, importer) => {\n try {\n const resolved = await this.resolve(specifier, importer);\n return resolved === null ? null : stripQuery(resolved.id);\n } catch {\n return null;\n }\n },\n analyze: (absoluteFile) => analysisCache.get(absoluteFile) ?? analyzeFile(absoluteFile),\n apiDir,\n serverOnlyPackages,\n packageCache,\n });\n }\n\n return undefined;\n },\n\n generateBundle(_options, bundle) {\n if (environmentName(this) === \"ssr\") {\n return;\n }\n\n const canary = options.leakTest?.canary;\n if (canary !== undefined && canary.length > 0) {\n const leak = findLeak(Object.values(bundle), canary);\n if (leak !== null) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `canary \\`${canary}\\` ditemukan di bundle client (${leak.fileName})`,\n details:\n \"Verifikasi kebocoran gagal: kode server bocor ke output client. Build dihentikan.\",\n suggestions: [\n \"Periksa transform `*.server.ts`\",\n \"Jalankan `./scripts/m2/test-leak.sh` untuk audit\",\n ],\n });\n }\n }\n\n for (const output of Object.values(bundle)) {\n if (output.type !== \"chunk\") {\n continue;\n }\n for (const moduleId of Object.keys(output.modules)) {\n const cleanId = stripQuery(moduleId);\n if (!isServerFilePath(cleanId) || stubTransformed.has(cleanId)) {\n continue;\n }\n throw new MoonsError({\n code: \"E_FORBIDDEN_SERVER_IMPORT\",\n file: cleanId,\n message: \"modul server ikut ter-bundle di client tanpa melewati transform\",\n details:\n \"Verifikasi build: setiap `*.server.ts` di bundle client wajib berupa stub RPC hasil transform.\",\n suggestions: [\n \"Pastikan transform zero-trust berjalan untuk modul ini\",\n \"Laporkan ini sebagai bug framework jika berulang\",\n ],\n });\n }\n }\n },\n\n configureServer(server) {\n installDevMiddleware(server, {\n templatePath: resolvePath(root, \"index.html\"),\n // A1: pemindaian payload SSR hanya di dev (warning), tanpa biaya di production.\n payloadScan: {\n ...(options.leakTest?.canary === undefined ? {} : { canary: options.leakTest.canary }),\n env: process.env,\n },\n // D.1: request ke prefix API (semua method) dirutekan ke runtime.\n ...(apiRoutes.length === 0\n ? {}\n : { apiPrefix: `/${apiDir.split(/[\\\\/]/).filter((part) => part.length > 0).pop() ?? \"api\"}` }),\n });\n },\n\n async handleHotUpdate(context) {\n if (isServerFilePath(context.file)) {\n refreshServerFns();\n context.server.ws.send({ type: \"full-reload\" });\n return;\n }\n\n if (context.file.startsWith(apiDir) && existsSync(apiDir)) {\n try {\n apiRoutes = scanApiRoutes(apiDir);\n for (const route of apiRoutes) {\n assertApiModuleExports(readFileSync(route.file, \"utf8\"), route.file);\n }\n apiMiddlewares = scanApiMiddlewares(apiDir);\n for (const middleware of apiMiddlewares) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n } catch (error) {\n context.server.config.logger.error(String(error));\n return;\n }\n invalidateVirtualModules(context.server);\n context.server.ws.send({ type: \"full-reload\" });\n return;\n }\n\n if (!context.file.startsWith(routesDir)) {\n return;\n }\n\n try {\n routes = scanRoutes(routesDir);\n for (const middleware of routes.filter((route) => route.kind === \"middleware\")) {\n assertMiddlewareExports(readFileSync(middleware.file, \"utf8\"), middleware.file);\n }\n await generateTypes({\n routesDir,\n configPath: configFilePath,\n outDir: resolvePath(root, \".moons\"),\n });\n } catch (error) {\n context.server.config.logger.error(String(error));\n return;\n }\n\n invalidateVirtualModules(context.server);\n context.server.ws.send({ type: \"full-reload\" });\n },\n };\n}\n\nfunction renderConfigModule(root: string, configFilePath: string): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n `import raw from ${JSON.stringify(rootSpecifier(root, configFilePath))};`,\n 'import { validateConfig } from \"@moonsjs/core\";',\n `export default validateConfig(raw, { file: ${JSON.stringify(configFilePath)} });`,\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderServerEntryDev(routesDir: string, eagerImports: string[]): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createPluginRuntime, createRequestHandler } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n 'import { apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware } from \"virtual:moons/api\";',\n ...eagerImports.map((specifier) => `import ${JSON.stringify(specifier)};`),\n \"\",\n \"export function createDevApp(shell, payloadScan) {\",\n \" const plugins = createPluginRuntime({ config, routes, middlewares: config.middleware ?? [] });\",\n ` const handler = createRequestHandler({ routes, apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware, config, routesDir: ${JSON.stringify(routesDir)}, loadRoute, shell, onContext: (ctx) => plugins.applyExtensions(ctx), ...(payloadScan === undefined ? {} : { payloadScan }) });`,\n \" return { handler, plugins };\",\n \"}\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction renderServerEntryBuild(\n routesDir: string,\n eagerImports: string[],\n canary: string | undefined,\n): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createFileShell, createPluginRuntime, createRequestHandler, startNodeServer } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n 'import { apiRoutes, apiMiddlewares, loadApi, loadApiMiddleware } from \"virtual:moons/api\";',\n ...eagerImports.map((specifier) => `import ${JSON.stringify(specifier)};`),\n \"\",\n \"const plugins = createPluginRuntime({ config, routes, middlewares: config.middleware ?? [] });\",\n \"const handler = createRequestHandler({\",\n \" routes,\",\n \" apiRoutes,\",\n \" apiMiddlewares,\",\n \" loadApi,\",\n \" loadApiMiddleware,\",\n \" config,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" shell: createFileShell(),\",\n \" onContext: (ctx) => plugins.applyExtensions(ctx),\",\n \"});\",\n \"\",\n `startNodeServer(handler, { plugins${canary === undefined ? \"\" : `, canary: ${JSON.stringify(canary)}`} });`,\n \"\",\n ].join(\"\\n\");\n}\n\ninterface ModuleGraphLike {\n getModulesByFile(file: string): Iterable<{ id?: string | null }> | undefined;\n invalidateModule(module: unknown): void;\n}\n\n/** Entry D.5: runner prerender (dijalankan CLI setelah build server). */\nfunction renderPrerenderEntry(\n routesDir: string,\n projectRoot: string,\n canary: string | undefined,\n): string {\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n 'import { createFileShell, createRequestHandler, runPrerender } from \"@moonsjs/vite/server\";',\n 'import config from \"virtual:moons/config\";',\n 'import { routes, loadRoute } from \"virtual:moons/routes\";',\n \"\",\n \"const handler = createRequestHandler({\",\n \" routes,\",\n \" config,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" shell: createFileShell(),\",\n \"});\",\n \"\",\n \"await runPrerender({\",\n \" routes,\",\n ` routesDir: ${JSON.stringify(routesDir)},`,\n \" loadRoute,\",\n \" handler,\",\n \" staticConfig: config,\",\n ` clientDir: ${JSON.stringify(resolvePath(projectRoot, \"dist/client\"))},`,\n ...(canary === undefined ? [] : [` canary: ${JSON.stringify(canary)},`]),\n \"});\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction environmentName(context: unknown): string {\n const environment = (context as { environment?: { name?: string } } | undefined)?.environment;\n return environment?.name ?? \"client\";\n}\n\nfunction invalidateVirtualModules(server: ViteDevServer): void {\n const graphs: ModuleGraphLike[] = [server.moduleGraph as unknown as ModuleGraphLike];\n const environments = (server as unknown as { environments?: Record<string, { moduleGraph?: unknown }> })\n .environments;\n if (environments !== undefined) {\n for (const environment of Object.values(environments)) {\n if (environment.moduleGraph !== undefined) {\n graphs.push(environment.moduleGraph as ModuleGraphLike);\n }\n }\n }\n\n for (const graph of graphs) {\n for (const name of Object.values(VIRTUAL_MODULES)) {\n for (const module of graph.getModulesByFile(`\\0${name}`) ?? []) {\n graph.invalidateModule(module);\n }\n }\n }\n}\n",
6
6
  "import { parse } from \"@babel/parser\";\nimport { API_METHODS, MoonsError } from \"@moonsjs/core\";\n\n/**\n * Validasi statis export modul `src/api` (PRD Addendum D.1):\n * hanya handler method `GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS` sebagai fungsi;\n * `default`/export lain ditolak → `E_API_HANDLER_INVALID`.\n */\nexport function assertApiModuleExports(code: string, file: string): string[] {\n let ast: unknown;\n try {\n ast = parse(code, {\n sourceType: \"module\",\n plugins: file.endsWith(\".tsx\") ? [\"typescript\", \"jsx\"] : [\"typescript\"],\n });\n } catch {\n return []; // biarkan bundler melaporkan syntax error\n }\n\n const program = (ast as { program?: { body?: Array<Record<string, unknown>> } }).program;\n const body = program?.body ?? [];\n const methods: string[] = [];\n\n for (const statement of body) {\n if (statement[\"type\"] === \"ExportDefaultDeclaration\") {\n throw apiError(\n file,\n \"export `default` tidak didukung di modul API\",\n \"Modul `src/api` hanya mengekspor handler method bernama.\",\n [\"Ganti menjadi `export const GET = (args) => …`\", \"Hapus export default\"],\n );\n }\n if (statement[\"type\"] !== \"ExportNamedDeclaration\") {\n continue;\n }\n if (statement[\"source\"] !== undefined) {\n // re-export `export { X } from \"...\"` — nama tetap dicek di bawah.\n }\n const declaration = statement[\"declaration\"] as Record<string, unknown> | undefined;\n if (declaration !== undefined) {\n if (declaration[\"type\"] === \"VariableDeclaration\") {\n for (const declarator of (declaration[\"declarations\"] ?? []) as Array<Record<string, unknown>>) {\n const id = declarator[\"id\"] as Record<string, unknown> | undefined;\n if (id?.[\"type\"] === \"Identifier\") {\n methods.push(id[\"name\"] as string);\n }\n }\n } else if (declaration[\"type\"] === \"FunctionDeclaration\") {\n const id = declaration[\"id\"] as Record<string, unknown> | undefined;\n if (id?.[\"type\"] === \"Identifier\") {\n methods.push(id[\"name\"] as string);\n }\n }\n continue;\n }\n for (const specifier of (statement[\"specifiers\"] ?? []) as Array<Record<string, unknown>>) {\n const exported = specifier[\"exported\"] as Record<string, unknown> | undefined;\n if (exported?.[\"type\"] === \"Identifier\") {\n methods.push(exported[\"name\"] as string);\n }\n }\n }\n\n const illegal = methods.filter((name) => !API_METHODS.includes(name as never));\n if (illegal.length > 0) {\n throw apiError(\n file,\n `export \\`${illegal[0]}\\` bukan handler method yang dikenal`,\n `Handler yang legal: ${API_METHODS.join(\", \")}.`,\n [\n \"Ganti nama export menjadi salah satu method HTTP\",\n \"Pindahkan helper ke modul lain (mis. `src/server/…`)\",\n ],\n );\n }\n if (methods.length === 0) {\n throw apiError(\n file,\n \"modul API tanpa handler method\",\n `Wajib ada minimal satu dari ${API_METHODS.join(\", \")}.`,\n [`Tambahkan \\`export const GET = (args) => new Response(…)\\``],\n );\n }\n\n return methods;\n}\n\nexport function assertMiddlewareExports(code: string, file: string): void {\n let ast: unknown;\n try {\n ast = parse(code, {\n sourceType: \"module\",\n plugins: file.endsWith(\".tsx\") ? [\"typescript\", \"jsx\"] : [\"typescript\"],\n });\n } catch {\n return;\n }\n const program = (ast as { program?: { body?: Array<Record<string, unknown>> } }).program;\n const hasDefault = (program?.body ?? []).some(\n (statement) => statement[\"type\"] === \"ExportDefaultDeclaration\",\n );\n if (!hasDefault) {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file,\n message: \"`_middleware.ts` tanpa `export default`\",\n details: \"Middleware direktori mengikuti bentuk `Middleware`: `(args) => Promise<Response>`.\",\n suggestions: [\n \"Tambahkan `export default async ({ req, ctx, next }) => await next()`\",\n \"Hapus file bila tidak dipakai\",\n ],\n });\n }\n}\n\nfunction apiError(file: string, message: string, details: string, suggestions: string[]): MoonsError {\n return new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file,\n message,\n details,\n suggestions,\n });\n}\n",
7
7
  "export interface BundleOutputLike {\n type: string;\n fileName?: string;\n code?: string;\n source?: string | Uint8Array;\n}\n\n/**\n * §9.1 (`leakTest.canary`) / §10.4: cari canary pada output bundle client.\n * Dipakai `generateBundle` plugin — build gagal bila canary ditemukan.\n */\nexport function findLeak(\n outputs: Iterable<BundleOutputLike>,\n canary: string,\n decode: (source: Uint8Array) => string = defaultDecode,\n): { fileName: string } | null {\n for (const output of outputs) {\n const fileName = output.fileName ?? \"(unknown)\";\n let text = \"\";\n if (typeof output.code === \"string\") {\n text = output.code;\n } else if (typeof output.source === \"string\") {\n text = output.source;\n } else if (output.source instanceof Uint8Array) {\n text = decode(output.source);\n }\n if (text.includes(canary)) {\n return { fileName };\n }\n }\n return null;\n}\n\nfunction defaultDecode(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n"
8
8
  ],
9
- "mappings": "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",
10
- "debugId": "858C3A2CF24FAEB764756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "C19ACBFCC6A7B10A64756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/server/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAEvB,KAAK,WAAW,EAEhB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKrC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,oCAAoC;IACpC,MAAM,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,KAAK,EAAE,KAAK,CAAC;IACb;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,iEAAiE;IACjE,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACjC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,2DAA2D;IAC3D,cAAc,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC3C,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAkXzC"}
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/server/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAEvB,KAAK,WAAW,EAEhB,KAAK,eAAe,EACpB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKrC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,oCAAoC;IACpC,MAAM,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,KAAK,EAAE,KAAK,CAAC;IACb;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B;;;;OAIG;IACH,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,iEAAiE;IACjE,SAAS,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACjC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,2DAA2D;IAC3D,cAAc,CAAC,EAAE,uBAAuB,EAAE,CAAC;IAC3C,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;CAC5D;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAqazC"}
@@ -239,7 +239,7 @@ function createRequestHandler(options) {
239
239
  }
240
240
  return result;
241
241
  }
242
- return async function handler(request) {
242
+ const handleCore = async function handler(request) {
243
243
  try {
244
244
  const url = new URL(request.url);
245
245
  if (url.pathname === HEALTH_PATH) {
@@ -302,6 +302,46 @@ function createRequestHandler(options) {
302
302
  return internalErrorResponse(error);
303
303
  }
304
304
  };
305
+ const staticHeaders = Object.entries(config.headers ?? {});
306
+ const redirects = (config.redirects ?? []).map((entry) => ({
307
+ ...entry,
308
+ status: entry.status ?? 301
309
+ }));
310
+ return async function handler(request) {
311
+ const isPrerender = request.headers.get("x-moons-prerender") === "1";
312
+ const applyHeaders = (response) => {
313
+ for (const [name, value] of staticHeaders) {
314
+ if (!response.headers.has(name)) {
315
+ response.headers.set(name, value);
316
+ }
317
+ }
318
+ return response;
319
+ };
320
+ try {
321
+ if (!isPrerender && redirects.length > 0) {
322
+ const url = new URL(request.url);
323
+ const path = url.pathname.replace(/\/$/, "");
324
+ for (const entry of redirects) {
325
+ if (path === entry.from.replace(/\/$/, "")) {
326
+ const location = entry.to.startsWith("http") ? entry.to : new URL(entry.to, url.origin).toString();
327
+ return applyHeaders(new Response(null, { status: entry.status, headers: { location } }));
328
+ }
329
+ }
330
+ }
331
+ await config.hooks?.onRequest?.(request);
332
+ let response = await handleCore(request);
333
+ const replaced = await config.hooks?.onResponse?.(response, request);
334
+ if (replaced instanceof Response) {
335
+ response = replaced;
336
+ }
337
+ return applyHeaders(response);
338
+ } catch (error) {
339
+ try {
340
+ await config.hooks?.onError?.(error, request);
341
+ } catch {}
342
+ return internalErrorResponse(error);
343
+ }
344
+ };
305
345
  }
306
346
  function applyResponseMutations(response) {
307
347
  const mutations = takeResponseMutations();
@@ -766,6 +806,8 @@ import { MoonsError as MoonsError2 } from "@moonsjs/core";
766
806
  import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
767
807
  import { dirname, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
768
808
  var PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
809
+ var NOT_FOUND_SENTINEL = "/_moons/404";
810
+ var NOT_FOUND_FILE = "404.html";
769
811
  async function runPrerender(options) {
770
812
  const log = options.log ?? ((message) => console.log(message));
771
813
  const env = options.env ?? process.env;
@@ -820,23 +862,7 @@ async function runPrerender(options) {
820
862
  throw prerenderError(route, `status ${response.status} saat merender ${pathname}`);
821
863
  }
822
864
  const html = await response.text();
823
- const findings = scanPayloadForSecrets(html, {
824
- ...options.canary === undefined ? {} : { canary: options.canary },
825
- env
826
- });
827
- if (findings.length > 0) {
828
- const labels = findings.map((finding) => finding.kind === "canary" ? "canary" : `env(${finding.label})`).join(", ");
829
- throw new MoonsError2({
830
- code: "E_PRERENDER_LEAK",
831
- file: route.file,
832
- message: `hasil prerender \`${pathname}\` memuat ${labels}`,
833
- details: "HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.",
834
- suggestions: [
835
- "Jangan mengembalikan nilai env rahasia dari loader yang di-prerender",
836
- "Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time"
837
- ]
838
- });
839
- }
865
+ assertNoLeak(html, pathname, route.file, options, env);
840
866
  const file = outputFile(options.clientDir, pathname);
841
867
  mkdirSync(dirname(file), { recursive: true });
842
868
  writeFileSync2(file, html);
@@ -844,11 +870,108 @@ async function runPrerender(options) {
844
870
  written += 1;
845
871
  }
846
872
  }
873
+ const notFound = await renderStaticNotFound(options, env, log);
874
+ let wrote404 = false;
875
+ if (notFound !== null) {
876
+ writeFileSync2(join2(options.clientDir, NOT_FOUND_FILE), notFound);
877
+ wrote404 = true;
878
+ }
847
879
  writeFileSync2(join2(options.clientDir, PRERENDER_MANIFEST_FILE), `${JSON.stringify({ version: 2, entries }, null, 2)}
848
880
  `);
849
- log(`[moons] prerender selesai: ${written} file (${skipped} dilewati)`);
881
+ const emitted = emitStaticFiles(options.clientDir, options.staticConfig, entries);
882
+ const extras = [...wrote404 ? [NOT_FOUND_FILE] : [], ...emitted];
883
+ log(`[moons] prerender selesai: ${written} file${extras.length > 0 ? ` + ${extras.join(" + ")}` : ""} (${skipped} dilewati)`);
850
884
  return { written, skipped };
851
885
  }
886
+ function emitStaticFiles(clientDir, staticConfig, entries) {
887
+ if (staticConfig === undefined) {
888
+ return [];
889
+ }
890
+ const emitted = [];
891
+ const headers = Object.entries(staticConfig.headers ?? {});
892
+ if (headers.length > 0) {
893
+ const lines = ["/*", ...headers.map(([name, value]) => ` ${name}: ${value}`)];
894
+ writeFileSync2(join2(clientDir, "_headers"), `${lines.join(`
895
+ `)}
896
+ `);
897
+ emitted.push("_headers");
898
+ }
899
+ const redirects = staticConfig.redirects ?? [];
900
+ if (redirects.length > 0) {
901
+ const lines = redirects.map((entry) => `${entry.from} ${entry.to} ${entry.status ?? 301}`);
902
+ writeFileSync2(join2(clientDir, "_redirects"), `${lines.join(`
903
+ `)}
904
+ `);
905
+ emitted.push("_redirects");
906
+ }
907
+ const sitemap = staticConfig.sitemap;
908
+ if (sitemap !== undefined) {
909
+ const site = sitemap.site.replace(/\/$/, "");
910
+ const exclude = sitemap.exclude ?? [];
911
+ const paths = [...new Set(entries.map((entry) => entry.path))].filter((path) => !exclude.some((prefix) => path.startsWith(prefix))).sort();
912
+ const xml = [
913
+ '<?xml version="1.0" encoding="UTF-8"?>',
914
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
915
+ ...paths.map((path) => ` <url><loc>${site}${path === "/" ? "/" : path}</loc></url>`),
916
+ "</urlset>",
917
+ ""
918
+ ].join(`
919
+ `);
920
+ writeFileSync2(join2(clientDir, "sitemap.xml"), xml);
921
+ emitted.push("sitemap.xml");
922
+ }
923
+ const robots = staticConfig.robots;
924
+ if (robots !== undefined) {
925
+ const lines = ["User-agent: *"];
926
+ for (const path of robots.disallow ?? []) {
927
+ lines.push(`Disallow: ${path}`);
928
+ }
929
+ if ((robots.sitemap ?? true) && sitemap !== undefined) {
930
+ lines.push("", `Sitemap: ${sitemap.site.replace(/\/$/, "")}/sitemap.xml`);
931
+ }
932
+ writeFileSync2(join2(clientDir, "robots.txt"), `${lines.join(`
933
+ `)}
934
+ `);
935
+ emitted.push("robots.txt");
936
+ }
937
+ return emitted;
938
+ }
939
+ async function renderStaticNotFound(options, env, log) {
940
+ if (!options.routes.some((route) => route.kind === "404")) {
941
+ return null;
942
+ }
943
+ const response = await options.handler(new Request(`http://localhost${NOT_FOUND_SENTINEL}`, {
944
+ method: "GET",
945
+ headers: { "x-moons-prerender": "1" }
946
+ }));
947
+ if (response.status !== 404) {
948
+ log(`[moons] prerender: ${NOT_FOUND_FILE} dilewati (sentinel \`${NOT_FOUND_SENTINEL}\` → ${response.status})`);
949
+ return null;
950
+ }
951
+ const html = await response.text();
952
+ assertNoLeak(html, NOT_FOUND_SENTINEL, NOT_FOUND_FILE, options, env);
953
+ return html;
954
+ }
955
+ function assertNoLeak(html, pathname, file, options, env) {
956
+ const findings = scanPayloadForSecrets(html, {
957
+ ...options.canary === undefined ? {} : { canary: options.canary },
958
+ env
959
+ });
960
+ if (findings.length === 0) {
961
+ return;
962
+ }
963
+ const labels = findings.map((finding) => finding.kind === "canary" ? "canary" : `env(${finding.label})`).join(", ");
964
+ throw new MoonsError2({
965
+ code: "E_PRERENDER_LEAK",
966
+ file,
967
+ message: `hasil prerender \`${pathname}\` memuat ${labels}`,
968
+ details: "HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.",
969
+ suggestions: [
970
+ "Jangan mengembalikan nilai env rahasia dari loader yang di-prerender",
971
+ "Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time"
972
+ ]
973
+ });
974
+ }
852
975
  function routeKeyOf(routesDir, file) {
853
976
  const relative = file.startsWith(routesDir) ? file.slice(routesDir.length + 1) : file;
854
977
  return relative.split("\\").join("/").replace(/\.(tsx|ts)$/, "");
@@ -972,4 +1095,4 @@ export {
972
1095
  toWebRequest2 as toWebRequest
973
1096
  };
974
1097
 
975
- //# debugId=CC962AE44069459E64756E2164756E21
1098
+ //# debugId=52F0831250D554E464756E2164756E21
@@ -2,16 +2,16 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/server/handler.ts", "../src/payload-scan.ts", "../src/server/node-server.ts", "../src/server/isr.ts", "../src/server/shutdown.ts", "../src/server/test-server.ts", "../src/server/plugins.ts", "../src/server/prerender.ts"],
4
4
  "sourcesContent": [
5
- "import {\n MoonsError,\n composeMiddleware,\n findApiDirMiddlewares,\n findDirMiddlewares,\n findErrorBoundary,\n isNotFoundSignal,\n isRedirectSignal,\n resolveRoute,\n routeKeyFromFile,\n runLoaders,\n type ApiMethod,\n type ApiMiddlewareDefinition,\n type ApiRouteDefinition,\n type Middleware,\n type MoonsConfig,\n type ResolvedRoute,\n type RouteDefinition,\n type RouteModule,\n} from \"@moonsjs/core\";\nimport { encodeSsrPayload, reviveError, serializeError } from \"@moonsjs/core/serialize\";\nimport { API_METHODS, resolveApiRoute } from \"@moonsjs/core\";\nimport { renderToMarkup } from \"@moonsjs/react/ssr\";\nimport type { ClientRouteEntry, RouteModuleShape } from \"@moonsjs/react/internal\";\nimport { createRpcHandler, runWithContext, runWithRequestCache, runWithResponseCollector, takeResponseMutations } from \"@moonsjs/server\";\nimport { NOT_FOUND_ROUTE_KEY } from \"../manifest\";\nimport { scanPayloadForSecrets, type PayloadScanOptions } from \"../payload-scan\";\nimport type { Shell } from \"./shell\";\n\nconst RPC_PREFIX = \"/_moons/fn/\";\nconst HEALTH_PATH = \"/_moons/health\";\n\nexport interface RequestHandlerOptions {\n routes: RouteDefinition[];\n /** Config yang sudah divalidasi. */\n config: MoonsConfig;\n /** Direktori route absolut; dipakai untuk derivasi key stabil. */\n routesDir: string;\n /** Peta import() modul route, key = routeKeyFromFile. */\n loadRoute: Record<string, () => Promise<RouteModule>>;\n shell: Shell;\n /**\n * Dipanggil setelah `config.context` per request (Addendum B.4: extender\n * `extendContext` plugin di-merge ke ctx).\n */\n onContext?: (ctx: Ctx) => void;\n /**\n * A1: pemindaian payload SSR (dev) — peringatan sekali per label bila payload\n * memuat canary/nilai env mirip-rahasia. Production TIDAK mengisi opsi ini\n * (tanpa biaya runtime). Lihat `payload-scan.ts`.\n */\n payloadScan?: PayloadScanOptions;\n /** Endpoint API `src/api` (Addendum D.1) — hasil scan plugin. */\n apiRoutes?: ApiRouteDefinition[];\n /** Peta import() modul API, key = route.path. */\n loadApi?: Record<string, () => Promise<unknown>>;\n /** Middleware direktori pohon `src/api` (Addendum D.3). */\n apiMiddlewares?: ApiMiddlewareDefinition[];\n /** Peta import() `_middleware.ts` pohon api, key = file path. */\n loadApiMiddleware?: Record<string, () => Promise<unknown>>;\n}\n\n/**\n * Handler HTML: context → middleware global → resolve route → loader paralel\n * → render React → inject payload devalue (PRD §11.2, §14.2, §17).\n */\nexport function createRequestHandler(\n options: RequestHandlerOptions,\n): (request: Request) => Promise<Response> { const { routes, config, routesDir, loadRoute, shell } = options;\n const rpc = createRpcHandler(\n config.security === undefined ? {} : { security: config.security },\n );\n const notFoundRoute = routes.find((route) => route.kind === \"404\");\n const errorRoute = routes.find((route) => route.kind === \"error\");\n /** A1: dedupe peringatan payload (sekali per label). */\n const warnedPayloadLabels = new Set<string>();\n\n async function renderRoute(\n resolved: ResolvedRoute,\n request: Request,\n ctx: Ctx,\n ): Promise<Response> {\n const entries = [...resolved.layouts, resolved.route];\n const keys = entries.map((entry) => routeKeyFromFile(routesDir, entry.file));\n const modules = await loadModules(keys, loadRoute);\n\n const data = await runLoaders(\n entries.map((entry, index) => ({ file: keys[index] as string, module: modules[index] as RouteModule })),\n { params: resolved.params, ctx, req: request },\n );\n\n const pageKey = routeKeyFromFile(routesDir, resolved.route.file);\n const pageModule = modules[modules.length - 1] as RouteModule;\n const entry: ClientRouteEntry = { page: pageKey, layouts: keys.slice(0, -1) };\n // Addendum A.3: query string ikut ke payload agar server/client identik.\n const searchParams = Object.fromEntries(new URL(request.url).searchParams);\n // Addendum B.1: eksekusi `meta()` page (data = hasil loader page itu sendiri).\n const meta = await runRouteMeta(pageModule, data[pageKey], resolved.route.file);\n\n const markup = renderToMarkup(\n entry,\n { page: pageModule as RouteModuleShape, layouts: modules.slice(0, -1) as RouteModuleShape[] },\n resolved.params,\n data,\n searchParams,\n );\n const payload = encodeSsrPayload({\n key: pageKey,\n params: resolved.params,\n searchParams,\n data,\n ...(meta === undefined ? {} : { meta }),\n });\n\n // A1: pindai payload SSR (dev saja — `payloadScan` tidak diisi production).\n warnPayloadFindings(payload, options.payloadScan, warnedPayloadLabels);\n\n return htmlResponse(await shell(markup, payload, request.url, meta), 200);\n }\n\n /** Addendum D.1: dispatch endpoint `src/api` (405/HEAD/OPTIONS + error). */\n async function handleApiRequest(\n route: ApiRouteDefinition,\n params: Record<string, string>,\n request: Request,\n ctx: Ctx,\n ): Promise<Response> {\n const load = options.loadApi?.[route.path];\n if (load === undefined) {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: `modul API \\`${route.path}\\` tidak bisa dimuat`,\n details: \"Peta `loadApi` tidak memuat route ini (build/dev tidak sinkron).\",\n suggestions: [\"Jalankan ulang build / restart dev server\"],\n }),\n route,\n );\n }\n\n let mod: unknown;\n try {\n mod = await load();\n } catch (error) {\n return apiErrorResponse(error, route);\n }\n if (mod === null || typeof mod !== \"object\") {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: \"modul API tidak mengekspor objek handler\",\n details: `Modul \\`${route.path}\\` harus mengekspor handler method.`,\n suggestions: [\"Export `GET`/`POST`/… sebagai fungsi `(args) => Response`\"],\n }),\n route,\n );\n }\n\n const record = mod as Record<string, unknown>;\n const methods: ApiMethod[] = API_METHODS.filter(\n (method) => typeof record[method] === \"function\",\n );\n const requestMethod = request.method.toUpperCase();\n type ApiHandlerFn = (args: {\n req: Request;\n params: Record<string, string>;\n ctx: Ctx;\n }) => Response | Promise<Response>;\n let handler = record[requestMethod] as ApiHandlerFn | undefined;\n let stripBody = false;\n\n // D.7 #2: HEAD otomatis dari GET; OPTIONS otomatis → 204 + Allow.\n if (typeof handler !== \"function\" && requestMethod === \"HEAD\" && typeof record[\"GET\"] === \"function\") {\n handler = record[\"GET\"] as ApiHandlerFn;\n stripBody = true;\n }\n if (typeof handler !== \"function\") {\n if (requestMethod === \"OPTIONS\") {\n return new Response(null, { status: 204, headers: { allow: methods.join(\", \") } });\n }\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: { allow: methods.join(\", \") },\n });\n }\n\n try {\n const result = await handler({ req: request, params, ctx });\n if (!(result instanceof Response)) {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: `handler \\`${requestMethod}\\` tidak mengembalikan \\`Response\\``,\n details: \"Handler API wajib mengembalikan `new Response(...)`.\",\n suggestions: [\"Kembalikan `new Response(body, { status, headers })`\"],\n }),\n route,\n );\n }\n if (stripBody) {\n return new Response(null, { status: result.status, headers: result.headers });\n }\n return result;\n } catch (error) {\n return apiErrorResponse(error, route);\n }\n }\n\n /** §11.2: halaman `_404.tsx` kustom (standalone), fallback bawaan. */\n async function notFoundResponse(request: Request): Promise<Response> {\n if (notFoundRoute !== undefined) {\n try {\n const key = routeKeyFromFile(routesDir, notFoundRoute.file);\n const [module] = await loadModules([key], loadRoute);\n const payload = encodeSsrPayload({ key: NOT_FOUND_ROUTE_KEY, params: {}, data: {} });\n const markup = renderToMarkup(\n { page: key, layouts: [] },\n { page: module as RouteModuleShape, layouts: [] },\n {},\n {},\n );\n return htmlResponse(await shell(markup, payload, request.url), 404);\n } catch (error) {\n console.error(\"[moons] gagal merender _404 kustom:\", error);\n }\n }\n\n const payload = encodeSsrPayload({ key: \"\", params: {}, data: {} });\n const html = await shell(\n \"<h1>404</h1><p>Halaman tidak ditemukan.</p>\",\n payload,\n request.url,\n );\n return htmlResponse(html, 404);\n }\n\n /**\n * §11.2/D.3: `_error.tsx` kustom (boundary terdekat dari route; fallback\n * root). Production tidak men-serialisasi error apa pun (§16.6).\n */\n async function routeErrorResponse(\n error: unknown,\n request: Request,\n resolved?: ResolvedRoute,\n ): Promise<Response> {\n console.error(\"[moons] route error:\", error);\n\n const boundary =\n (resolved === undefined ? null : findErrorBoundary(resolved.route, routes)) ??\n errorRoute ??\n null;\n if (boundary !== null) {\n try {\n const key = routeKeyFromFile(routesDir, boundary.file);\n const [module] = await loadModules([key], loadRoute);\n const isProduction = process.env[\"NODE_ENV\"] === \"production\";\n const serialized = isProduction ? undefined : serializeError(error);\n const payload = encodeSsrPayload({\n key,\n params: {},\n data: {},\n ...(serialized === undefined ? {} : { error: serialized }),\n });\n const markup = renderToMarkup(\n { page: key, layouts: [] },\n { page: module as RouteModuleShape, layouts: [] },\n {},\n {},\n {},\n serialized === undefined ? undefined : reviveError(serialized),\n );\n return htmlResponse(await shell(markup, payload, request.url), 500);\n } catch (renderError) {\n console.error(\"[moons] gagal merender _error kustom:\", renderError);\n }\n }\n\n return internalErrorResponse(error, { log: false });\n }\n\n /** Muat middleware direktori (D.3) → `Middleware[]`; error bentuk jelas. */\n async function loadDirMiddlewares(chain: ReadonlyArray<RouteDefinition>): Promise<Middleware[]> {\n const result: Middleware[] = [];\n for (const definition of chain) {\n const key = routeKeyFromFile(routesDir, definition.file);\n const load = options.loadRoute?.[key];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"middleware direktori tidak bisa dimuat\",\n details: \"Peta `loadRoute` tidak memuat `_middleware.ts` ini.\",\n suggestions: [\"Restart dev server / jalankan ulang build\"],\n });\n }\n const module = (await load()) as { default?: unknown };\n const handler = module.default;\n if (typeof handler !== \"function\") {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"`_middleware.ts` tidak meng-export default fungsi\",\n details: \"Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.\",\n suggestions: [\"Export default `async ({ req, ctx, next }) => await next()`\"],\n });\n }\n result.push(handler as Middleware);\n }\n return result;\n }\n\n /** Muat middleware pohon `src/api` (D.3). */\n async function loadApiDirMiddlewares(\n chain: ReadonlyArray<ApiMiddlewareDefinition>,\n ): Promise<Middleware[]> {\n const result: Middleware[] = [];\n for (const definition of chain) {\n const load = options.loadApiMiddleware?.[definition.file];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"middleware API tidak bisa dimuat\",\n details: \"Peta `loadApiMiddleware` tidak memuat `_middleware.ts` ini.\",\n suggestions: [\"Restart dev server / jalankan ulang build\"],\n });\n }\n const module = (await load()) as { default?: unknown };\n if (typeof module.default !== \"function\") {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"`_middleware.ts` tidak meng-export default fungsi\",\n details: \"Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.\",\n suggestions: [\"Export default `async ({ req, ctx, next }) => await next()`\"],\n });\n }\n result.push(module.default as Middleware);\n }\n return result;\n }\n\n return async function handler(request: Request): Promise<Response> {\n try {\n const url = new URL(request.url);\n\n // §19.5: health ditangani paling awal — tetap hidup walau kode user rusak.\n if (url.pathname === HEALTH_PATH) {\n return healthResponse(request.method);\n }\n\n // `MoonsConfig.context` bertipe `unknown` (menghindari referensi sirkular\n // ke global `Ctx` — §13); kontraknya tetap `Promise<Ctx>`, jadi cast di\n // batas runtime ini. Tanpa cast, tsc app user yang memuat `@moonsjs/vite/server`\n // (mis. `createTestServer` §19.5) melihat `unknown` vs `Ctx` global app.\n const ctx = (await config.context(request)) as Ctx;\n options.onContext?.(ctx);\n // Addendum D.5: tandai request prerender build-time (aditif §13.1).\n if (request.headers.get(\"x-moons-prerender\") === \"1\") {\n (ctx as Record<string, unknown>)[\"__prerender\"] = true;\n }\n\n const respond = composeMiddleware(config.middleware ?? [], ctx, async () => {\n if (url.pathname.startsWith(RPC_PREFIX)) {\n return await rpc(request, url.pathname.slice(RPC_PREFIX.length), ctx);\n }\n // Addendum D.1: endpoint HTTP mentah `src/api` (semua method).\n if (options.apiRoutes !== undefined && options.apiRoutes.length > 0) {\n const apiMatch = resolveApiRoute(url.pathname, options.apiRoutes);\n if (apiMatch !== null) {\n // Addendum D.3: middleware direktori pohon api.\n const apiChain = findApiDirMiddlewares(\n apiMatch.route.file,\n options.apiMiddlewares ?? [],\n );\n if (apiChain.length === 0) {\n return await handleApiRequest(apiMatch.route, apiMatch.params, request, ctx);\n }\n const middlewares = await loadApiDirMiddlewares(apiChain);\n return await composeMiddleware(\n middlewares,\n ctx,\n () => handleApiRequest(apiMatch.route, apiMatch.params, request, ctx),\n { code: \"E_MIDDLEWARE_INVALID\", label: \"middleware API\" },\n )(request);\n }\n }\n const resolved = resolveRoute(url.pathname, routes);\n if (resolved === null) {\n return await notFoundResponse(request);\n }\n try {\n // Addendum D.3: middleware direktori (root→leaf) untuk page.\n const dirChain = findDirMiddlewares(resolved.route, routes);\n if (dirChain.length === 0) {\n return await renderRoute(resolved, request, ctx);\n }\n const middlewares = await loadDirMiddlewares(dirChain);\n return await composeMiddleware(\n middlewares,\n ctx,\n () => renderRoute(resolved, request, ctx),\n { code: \"E_MIDDLEWARE_INVALID\", label: \"middleware direktori\" },\n )(request);\n } catch (error) {\n // Addendum B.2: sinyal routing dari loader/meta.\n if (isRedirectSignal(error)) {\n return new Response(null, {\n status: error.status,\n headers: { location: new URL(error.to, request.url).toString() },\n });\n }\n if (isNotFoundSignal(error)) {\n return await notFoundResponse(request);\n }\n return await routeErrorResponse(error, request, resolved);\n }\n });\n\n // Addendum D.2: kolektor mutasi respons aktif selama request; helper\n // (setHeader/setCookie) menulis ke store, diterapkan ke Response akhir —\n // termasuk jalur error (mutasi yang sudah dipush tetap dihormati).\n return await runWithResponseCollector(async () => {\n let response: Response;\n try {\n response = await runWithRequestCache(() => runWithContext(ctx, () => respond(request)));\n } catch (error) {\n response = internalErrorResponse(error);\n }\n return applyResponseMutations(response);\n });\n } catch (error) {\n return internalErrorResponse(error);\n }\n };\n}\n\n/** Terapkan mutasi `setHeader`/`appendHeader`/`setCookie` ke respons (D.2). */\nfunction applyResponseMutations(response: Response): Response {\n const mutations = takeResponseMutations();\n if (mutations.length === 0) {\n return response;\n }\n const headers = new Headers(response.headers);\n for (const mutation of mutations) {\n if (mutation.kind === \"header\") {\n if (mutation.append) {\n headers.append(mutation.name, mutation.value);\n } else {\n headers.set(mutation.name, mutation.value);\n }\n } else {\n headers.append(\"set-cookie\", mutation.value);\n }\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nasync function loadModules(\n keys: string[],\n loadRoute: Record<string, () => Promise<RouteModule>>,\n): Promise<RouteModule[]> {\n return await Promise.all(\n keys.map(async (key) => {\n const load = loadRoute[key];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `modul route \\`${key}\\` tidak terdaftar`,\n details: \"Registry route tidak sinkron dengan hasil scan.\",\n suggestions: [\"Jalankan ulang `bun run build`, atau restart dev server\"],\n });\n }\n return await load();\n }),\n );\n}\n\nasync function runRouteMeta(\n pageModule: RouteModule,\n pageData: unknown,\n file: string,\n): Promise<Record<string, unknown> | undefined> {\n const meta = (pageModule as { meta?: unknown }).meta;\n if (meta === undefined) {\n return undefined;\n }\n if (typeof meta !== \"function\") {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"export `meta` harus berupa fungsi `({ data }) => RouteMeta`\",\n details: \"Bentuk `meta` mengikuti \",\n suggestions: [\n \"Ubah menjadi `export const meta = ({ data }) => ({ title: \\\"...\\\" })`\",\n \"Atau hapus export `meta`\",\n ],\n });\n }\n const result = await (meta as (args: { data: unknown }) => unknown)({ data: pageData });\n if (result === null || typeof result !== \"object\" || Array.isArray(result)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"`meta()` harus mengembalikan objek RouteMeta\",\n details: \"Nilai yang dikembalikan dipakai untuk <title>/description/og.\",\n suggestions: [\"Kembalikan objek, mis. `({ title: \\\"Halaman\\\" })`\"],\n });\n }\n return result as Record<string, unknown>;\n}\n\n/**\n * Error endpoint API (Addendum D.1): detail hanya di non-production (§16.6).\n */\nfunction apiErrorResponse(error: unknown, route: ApiRouteDefinition): Response {\n const isProduction = process.env[\"NODE_ENV\"] === \"production\";\n if (error instanceof MoonsError) {\n console.error(`[moons] API ${route.path}: ${error.format()}`);\n return new Response(isProduction ? \"Terjadi kesalahan internal.\" : error.format(), {\n status: 500,\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n });\n }\n console.error(`[moons] API ${route.path}:`, error);\n return new Response(isProduction ? \"Terjadi kesalahan internal.\" : String(error), {\n status: 500,\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n });\n}\n\nfunction internalErrorResponse(error: unknown, options: { log?: boolean } = {}): Response {\n if (options.log !== false) {\n console.error(\"[moons] request error:\", error);\n }\n\n const detail =\n process.env[\"NODE_ENV\"] !== \"production\" && error instanceof MoonsError\n ? `<pre>${escapeHtml(error.format())}</pre>`\n : \"<p>Terjadi kesalahan internal.</p>\";\n\n return htmlResponse(\n `<!doctype html><html lang=\"id\"><head><meta charset=\"utf-8\"><title>500</title></head><body><h1>500</h1>${detail}</body></html>`,\n 500,\n );\n}\n\nfunction htmlResponse(html: string, status: number): Response {\n return new Response(html, {\n status,\n headers: { \"content-type\": \"text/html; charset=utf-8\" },\n });\n}\n\n/** §19.5: `/_moons/health` → `{ ok: true }`. */\nfunction healthResponse(method: string): Response {\n const headers = { \"content-type\": \"application/json; charset=utf-8\" };\n if (method === \"GET\" || method === \"HEAD\") {\n return new Response(method === \"HEAD\" ? null : JSON.stringify({ ok: true }), {\n status: 200,\n headers,\n });\n }\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: { allow: \"GET, HEAD\" },\n });\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\");\n}\n\n/**\n * A1: peringatan dev untuk payload SSR yang memuat canary/nilai env\n * mirip-rahasia (sekali per label). Tidak pernah aktif di production karena\n * `payloadScan` hanya diisi runtime dev.\n */\nfunction warnPayloadFindings(\n payload: string,\n scan: PayloadScanOptions | undefined,\n warned: Set<string>,\n): void {\n if (scan === undefined) {\n return;\n }\n for (const finding of scanPayloadForSecrets(payload, scan)) {\n const label = finding.kind === \"canary\" ? \"canary\" : `env(${finding.label})`;\n if (warned.has(label)) {\n continue;\n }\n warned.add(label);\n console.warn(\n `[moons] peringatan dev: payload SSR memuat ${label} — jangan mengembalikan rahasia dari loader.`,\n );\n }\n}\n",
5
+ "import {\n MoonsError,\n composeMiddleware,\n findApiDirMiddlewares,\n findDirMiddlewares,\n findErrorBoundary,\n isNotFoundSignal,\n isRedirectSignal,\n resolveRoute,\n routeKeyFromFile,\n runLoaders,\n type ApiMethod,\n type ApiMiddlewareDefinition,\n type ApiRouteDefinition,\n type Middleware,\n type MoonsConfig,\n type ResolvedRoute,\n type RouteDefinition,\n type RouteModule,\n} from \"@moonsjs/core\";\nimport { encodeSsrPayload, reviveError, serializeError } from \"@moonsjs/core/serialize\";\nimport { API_METHODS, resolveApiRoute } from \"@moonsjs/core\";\nimport { renderToMarkup } from \"@moonsjs/react/ssr\";\nimport type { ClientRouteEntry, RouteModuleShape } from \"@moonsjs/react/internal\";\nimport { createRpcHandler, runWithContext, runWithRequestCache, runWithResponseCollector, takeResponseMutations } from \"@moonsjs/server\";\nimport { NOT_FOUND_ROUTE_KEY } from \"../manifest\";\nimport { scanPayloadForSecrets, type PayloadScanOptions } from \"../payload-scan\";\nimport type { Shell } from \"./shell\";\n\nconst RPC_PREFIX = \"/_moons/fn/\";\nconst HEALTH_PATH = \"/_moons/health\";\n\nexport interface RequestHandlerOptions {\n routes: RouteDefinition[];\n /** Config yang sudah divalidasi. */\n config: MoonsConfig;\n /** Direktori route absolut; dipakai untuk derivasi key stabil. */\n routesDir: string;\n /** Peta import() modul route, key = routeKeyFromFile. */\n loadRoute: Record<string, () => Promise<RouteModule>>;\n shell: Shell;\n /**\n * Dipanggil setelah `config.context` per request (Addendum B.4: extender\n * `extendContext` plugin di-merge ke ctx).\n */\n onContext?: (ctx: Ctx) => void;\n /**\n * A1: pemindaian payload SSR (dev) — peringatan sekali per label bila payload\n * memuat canary/nilai env mirip-rahasia. Production TIDAK mengisi opsi ini\n * (tanpa biaya runtime). Lihat `payload-scan.ts`.\n */\n payloadScan?: PayloadScanOptions;\n /** Endpoint API `src/api` (Addendum D.1) — hasil scan plugin. */\n apiRoutes?: ApiRouteDefinition[];\n /** Peta import() modul API, key = route.path. */\n loadApi?: Record<string, () => Promise<unknown>>;\n /** Middleware direktori pohon `src/api` (Addendum D.3). */\n apiMiddlewares?: ApiMiddlewareDefinition[];\n /** Peta import() `_middleware.ts` pohon api, key = file path. */\n loadApiMiddleware?: Record<string, () => Promise<unknown>>;\n}\n\n/**\n * Handler HTML: context → middleware global → resolve route → loader paralel\n * → render React → inject payload devalue (PRD §11.2, §14.2, §17).\n */\nexport function createRequestHandler(\n options: RequestHandlerOptions,\n): (request: Request) => Promise<Response> { const { routes, config, routesDir, loadRoute, shell } = options;\n const rpc = createRpcHandler(\n config.security === undefined ? {} : { security: config.security },\n );\n const notFoundRoute = routes.find((route) => route.kind === \"404\");\n const errorRoute = routes.find((route) => route.kind === \"error\");\n /** A1: dedupe peringatan payload (sekali per label). */\n const warnedPayloadLabels = new Set<string>();\n\n async function renderRoute(\n resolved: ResolvedRoute,\n request: Request,\n ctx: Ctx,\n ): Promise<Response> {\n const entries = [...resolved.layouts, resolved.route];\n const keys = entries.map((entry) => routeKeyFromFile(routesDir, entry.file));\n const modules = await loadModules(keys, loadRoute);\n\n const data = await runLoaders(\n entries.map((entry, index) => ({ file: keys[index] as string, module: modules[index] as RouteModule })),\n { params: resolved.params, ctx, req: request },\n );\n\n const pageKey = routeKeyFromFile(routesDir, resolved.route.file);\n const pageModule = modules[modules.length - 1] as RouteModule;\n const entry: ClientRouteEntry = { page: pageKey, layouts: keys.slice(0, -1) };\n // Addendum A.3: query string ikut ke payload agar server/client identik.\n const searchParams = Object.fromEntries(new URL(request.url).searchParams);\n // Addendum B.1: eksekusi `meta()` page (data = hasil loader page itu sendiri).\n const meta = await runRouteMeta(pageModule, data[pageKey], resolved.route.file);\n\n const markup = renderToMarkup(\n entry,\n { page: pageModule as RouteModuleShape, layouts: modules.slice(0, -1) as RouteModuleShape[] },\n resolved.params,\n data,\n searchParams,\n );\n const payload = encodeSsrPayload({\n key: pageKey,\n params: resolved.params,\n searchParams,\n data,\n ...(meta === undefined ? {} : { meta }),\n });\n\n // A1: pindai payload SSR (dev saja — `payloadScan` tidak diisi production).\n warnPayloadFindings(payload, options.payloadScan, warnedPayloadLabels);\n\n return htmlResponse(await shell(markup, payload, request.url, meta), 200);\n }\n\n /** Addendum D.1: dispatch endpoint `src/api` (405/HEAD/OPTIONS + error). */\n async function handleApiRequest(\n route: ApiRouteDefinition,\n params: Record<string, string>,\n request: Request,\n ctx: Ctx,\n ): Promise<Response> {\n const load = options.loadApi?.[route.path];\n if (load === undefined) {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: `modul API \\`${route.path}\\` tidak bisa dimuat`,\n details: \"Peta `loadApi` tidak memuat route ini (build/dev tidak sinkron).\",\n suggestions: [\"Jalankan ulang build / restart dev server\"],\n }),\n route,\n );\n }\n\n let mod: unknown;\n try {\n mod = await load();\n } catch (error) {\n return apiErrorResponse(error, route);\n }\n if (mod === null || typeof mod !== \"object\") {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: \"modul API tidak mengekspor objek handler\",\n details: `Modul \\`${route.path}\\` harus mengekspor handler method.`,\n suggestions: [\"Export `GET`/`POST`/… sebagai fungsi `(args) => Response`\"],\n }),\n route,\n );\n }\n\n const record = mod as Record<string, unknown>;\n const methods: ApiMethod[] = API_METHODS.filter(\n (method) => typeof record[method] === \"function\",\n );\n const requestMethod = request.method.toUpperCase();\n type ApiHandlerFn = (args: {\n req: Request;\n params: Record<string, string>;\n ctx: Ctx;\n }) => Response | Promise<Response>;\n let handler = record[requestMethod] as ApiHandlerFn | undefined;\n let stripBody = false;\n\n // D.7 #2: HEAD otomatis dari GET; OPTIONS otomatis → 204 + Allow.\n if (typeof handler !== \"function\" && requestMethod === \"HEAD\" && typeof record[\"GET\"] === \"function\") {\n handler = record[\"GET\"] as ApiHandlerFn;\n stripBody = true;\n }\n if (typeof handler !== \"function\") {\n if (requestMethod === \"OPTIONS\") {\n return new Response(null, { status: 204, headers: { allow: methods.join(\", \") } });\n }\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: { allow: methods.join(\", \") },\n });\n }\n\n try {\n const result = await handler({ req: request, params, ctx });\n if (!(result instanceof Response)) {\n return apiErrorResponse(\n new MoonsError({\n code: \"E_API_HANDLER_INVALID\",\n file: route.file,\n message: `handler \\`${requestMethod}\\` tidak mengembalikan \\`Response\\``,\n details: \"Handler API wajib mengembalikan `new Response(...)`.\",\n suggestions: [\"Kembalikan `new Response(body, { status, headers })`\"],\n }),\n route,\n );\n }\n if (stripBody) {\n return new Response(null, { status: result.status, headers: result.headers });\n }\n return result;\n } catch (error) {\n return apiErrorResponse(error, route);\n }\n }\n\n /** §11.2: halaman `_404.tsx` kustom (standalone), fallback bawaan. */\n async function notFoundResponse(request: Request): Promise<Response> {\n if (notFoundRoute !== undefined) {\n try {\n const key = routeKeyFromFile(routesDir, notFoundRoute.file);\n const [module] = await loadModules([key], loadRoute);\n const payload = encodeSsrPayload({ key: NOT_FOUND_ROUTE_KEY, params: {}, data: {} });\n const markup = renderToMarkup(\n { page: key, layouts: [] },\n { page: module as RouteModuleShape, layouts: [] },\n {},\n {},\n );\n return htmlResponse(await shell(markup, payload, request.url), 404);\n } catch (error) {\n console.error(\"[moons] gagal merender _404 kustom:\", error);\n }\n }\n\n const payload = encodeSsrPayload({ key: \"\", params: {}, data: {} });\n const html = await shell(\n \"<h1>404</h1><p>Halaman tidak ditemukan.</p>\",\n payload,\n request.url,\n );\n return htmlResponse(html, 404);\n }\n\n /**\n * §11.2/D.3: `_error.tsx` kustom (boundary terdekat dari route; fallback\n * root). Production tidak men-serialisasi error apa pun (§16.6).\n */\n async function routeErrorResponse(\n error: unknown,\n request: Request,\n resolved?: ResolvedRoute,\n ): Promise<Response> {\n console.error(\"[moons] route error:\", error);\n\n const boundary =\n (resolved === undefined ? null : findErrorBoundary(resolved.route, routes)) ??\n errorRoute ??\n null;\n if (boundary !== null) {\n try {\n const key = routeKeyFromFile(routesDir, boundary.file);\n const [module] = await loadModules([key], loadRoute);\n const isProduction = process.env[\"NODE_ENV\"] === \"production\";\n const serialized = isProduction ? undefined : serializeError(error);\n const payload = encodeSsrPayload({\n key,\n params: {},\n data: {},\n ...(serialized === undefined ? {} : { error: serialized }),\n });\n const markup = renderToMarkup(\n { page: key, layouts: [] },\n { page: module as RouteModuleShape, layouts: [] },\n {},\n {},\n {},\n serialized === undefined ? undefined : reviveError(serialized),\n );\n return htmlResponse(await shell(markup, payload, request.url), 500);\n } catch (renderError) {\n console.error(\"[moons] gagal merender _error kustom:\", renderError);\n }\n }\n\n return internalErrorResponse(error, { log: false });\n }\n\n /** Muat middleware direktori (D.3) → `Middleware[]`; error bentuk jelas. */\n async function loadDirMiddlewares(chain: ReadonlyArray<RouteDefinition>): Promise<Middleware[]> {\n const result: Middleware[] = [];\n for (const definition of chain) {\n const key = routeKeyFromFile(routesDir, definition.file);\n const load = options.loadRoute?.[key];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"middleware direktori tidak bisa dimuat\",\n details: \"Peta `loadRoute` tidak memuat `_middleware.ts` ini.\",\n suggestions: [\"Restart dev server / jalankan ulang build\"],\n });\n }\n const module = (await load()) as { default?: unknown };\n const handler = module.default;\n if (typeof handler !== \"function\") {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"`_middleware.ts` tidak meng-export default fungsi\",\n details: \"Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.\",\n suggestions: [\"Export default `async ({ req, ctx, next }) => await next()`\"],\n });\n }\n result.push(handler as Middleware);\n }\n return result;\n }\n\n /** Muat middleware pohon `src/api` (D.3). */\n async function loadApiDirMiddlewares(\n chain: ReadonlyArray<ApiMiddlewareDefinition>,\n ): Promise<Middleware[]> {\n const result: Middleware[] = [];\n for (const definition of chain) {\n const load = options.loadApiMiddleware?.[definition.file];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"middleware API tidak bisa dimuat\",\n details: \"Peta `loadApiMiddleware` tidak memuat `_middleware.ts` ini.\",\n suggestions: [\"Restart dev server / jalankan ulang build\"],\n });\n }\n const module = (await load()) as { default?: unknown };\n if (typeof module.default !== \"function\") {\n throw new MoonsError({\n code: \"E_MIDDLEWARE_INVALID\",\n file: definition.file,\n message: \"`_middleware.ts` tidak meng-export default fungsi\",\n details: \"Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.\",\n suggestions: [\"Export default `async ({ req, ctx, next }) => await next()`\"],\n });\n }\n result.push(module.default as Middleware);\n }\n return result;\n }\n\n const handleCore = async function handler(request: Request): Promise<Response> {\n try {\n const url = new URL(request.url);\n\n // §19.5: health ditangani paling awal — tetap hidup walau kode user rusak.\n if (url.pathname === HEALTH_PATH) {\n return healthResponse(request.method);\n }\n\n // `MoonsConfig.context` bertipe `unknown` (menghindari referensi sirkular\n // ke global `Ctx` — §13); kontraknya tetap `Promise<Ctx>`, jadi cast di\n // batas runtime ini. Tanpa cast, tsc app user yang memuat `@moonsjs/vite/server`\n // (mis. `createTestServer` §19.5) melihat `unknown` vs `Ctx` global app.\n const ctx = (await config.context(request)) as Ctx;\n options.onContext?.(ctx);\n // Addendum D.5: tandai request prerender build-time (aditif §13.1).\n if (request.headers.get(\"x-moons-prerender\") === \"1\") {\n (ctx as Record<string, unknown>)[\"__prerender\"] = true;\n }\n\n const respond = composeMiddleware(config.middleware ?? [], ctx, async () => {\n if (url.pathname.startsWith(RPC_PREFIX)) {\n return await rpc(request, url.pathname.slice(RPC_PREFIX.length), ctx);\n }\n // Addendum D.1: endpoint HTTP mentah `src/api` (semua method).\n if (options.apiRoutes !== undefined && options.apiRoutes.length > 0) {\n const apiMatch = resolveApiRoute(url.pathname, options.apiRoutes);\n if (apiMatch !== null) {\n // Addendum D.3: middleware direktori pohon api.\n const apiChain = findApiDirMiddlewares(\n apiMatch.route.file,\n options.apiMiddlewares ?? [],\n );\n if (apiChain.length === 0) {\n return await handleApiRequest(apiMatch.route, apiMatch.params, request, ctx);\n }\n const middlewares = await loadApiDirMiddlewares(apiChain);\n return await composeMiddleware(\n middlewares,\n ctx,\n () => handleApiRequest(apiMatch.route, apiMatch.params, request, ctx),\n { code: \"E_MIDDLEWARE_INVALID\", label: \"middleware API\" },\n )(request);\n }\n }\n const resolved = resolveRoute(url.pathname, routes);\n if (resolved === null) {\n return await notFoundResponse(request);\n }\n try {\n // Addendum D.3: middleware direktori (root→leaf) untuk page.\n const dirChain = findDirMiddlewares(resolved.route, routes);\n if (dirChain.length === 0) {\n return await renderRoute(resolved, request, ctx);\n }\n const middlewares = await loadDirMiddlewares(dirChain);\n return await composeMiddleware(\n middlewares,\n ctx,\n () => renderRoute(resolved, request, ctx),\n { code: \"E_MIDDLEWARE_INVALID\", label: \"middleware direktori\" },\n )(request);\n } catch (error) {\n // Addendum B.2: sinyal routing dari loader/meta.\n if (isRedirectSignal(error)) {\n return new Response(null, {\n status: error.status,\n headers: { location: new URL(error.to, request.url).toString() },\n });\n }\n if (isNotFoundSignal(error)) {\n return await notFoundResponse(request);\n }\n return await routeErrorResponse(error, request, resolved);\n }\n });\n\n // Addendum D.2: kolektor mutasi respons aktif selama request; helper\n // (setHeader/setCookie) menulis ke store, diterapkan ke Response akhir —\n // termasuk jalur error (mutasi yang sudah dipush tetap dihormati).\n return await runWithResponseCollector(async () => {\n let response: Response;\n try {\n response = await runWithRequestCache(() => runWithContext(ctx, () => respond(request)));\n } catch (error) {\n response = internalErrorResponse(error);\n }\n return applyResponseMutations(response);\n });\n } catch (error) {\n return internalErrorResponse(error);\n }\n };\n\n // Addendum H: redirect statis + hook lifecycle + header statis.\n const staticHeaders = Object.entries(config.headers ?? {});\n const redirects = (config.redirects ?? []).map((entry) => ({\n ...entry,\n status: entry.status ?? 301,\n }));\n\n return async function handler(request: Request): Promise<Response> {\n const isPrerender = request.headers.get(\"x-moons-prerender\") === \"1\";\n const applyHeaders = (response: Response): Response => {\n for (const [name, value] of staticHeaders) {\n if (!response.headers.has(name)) {\n response.headers.set(name, value);\n }\n }\n return response;\n };\n\n try {\n if (!isPrerender && redirects.length > 0) {\n const url = new URL(request.url);\n const path = url.pathname.replace(/\\/$/, \"\");\n for (const entry of redirects) {\n if (path === entry.from.replace(/\\/$/, \"\")) {\n const location = entry.to.startsWith(\"http\")\n ? entry.to\n : new URL(entry.to, url.origin).toString();\n return applyHeaders(\n new Response(null, { status: entry.status, headers: { location } }),\n );\n }\n }\n }\n\n await config.hooks?.onRequest?.(request);\n let response = await handleCore(request);\n const replaced = await config.hooks?.onResponse?.(response, request);\n if (replaced instanceof Response) {\n response = replaced;\n }\n return applyHeaders(response);\n } catch (error) {\n try {\n await config.hooks?.onError?.(error, request);\n } catch {\n // Kegagalan hook tidak boleh menutupi error asli.\n }\n return internalErrorResponse(error);\n }\n };\n}\n\n/** Terapkan mutasi `setHeader`/`appendHeader`/`setCookie` ke respons (D.2). */\nfunction applyResponseMutations(response: Response): Response {\n const mutations = takeResponseMutations();\n if (mutations.length === 0) {\n return response;\n }\n const headers = new Headers(response.headers);\n for (const mutation of mutations) {\n if (mutation.kind === \"header\") {\n if (mutation.append) {\n headers.append(mutation.name, mutation.value);\n } else {\n headers.set(mutation.name, mutation.value);\n }\n } else {\n headers.append(\"set-cookie\", mutation.value);\n }\n }\n return new Response(response.body, {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n}\n\nasync function loadModules(\n keys: string[],\n loadRoute: Record<string, () => Promise<RouteModule>>,\n): Promise<RouteModule[]> {\n return await Promise.all(\n keys.map(async (key) => {\n const load = loadRoute[key];\n if (load === undefined) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `modul route \\`${key}\\` tidak terdaftar`,\n details: \"Registry route tidak sinkron dengan hasil scan.\",\n suggestions: [\"Jalankan ulang `bun run build`, atau restart dev server\"],\n });\n }\n return await load();\n }),\n );\n}\n\nasync function runRouteMeta(\n pageModule: RouteModule,\n pageData: unknown,\n file: string,\n): Promise<Record<string, unknown> | undefined> {\n const meta = (pageModule as { meta?: unknown }).meta;\n if (meta === undefined) {\n return undefined;\n }\n if (typeof meta !== \"function\") {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"export `meta` harus berupa fungsi `({ data }) => RouteMeta`\",\n details: \"Bentuk `meta` mengikuti \",\n suggestions: [\n \"Ubah menjadi `export const meta = ({ data }) => ({ title: \\\"...\\\" })`\",\n \"Atau hapus export `meta`\",\n ],\n });\n }\n const result = await (meta as (args: { data: unknown }) => unknown)({ data: pageData });\n if (result === null || typeof result !== \"object\" || Array.isArray(result)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"`meta()` harus mengembalikan objek RouteMeta\",\n details: \"Nilai yang dikembalikan dipakai untuk <title>/description/og.\",\n suggestions: [\"Kembalikan objek, mis. `({ title: \\\"Halaman\\\" })`\"],\n });\n }\n return result as Record<string, unknown>;\n}\n\n/**\n * Error endpoint API (Addendum D.1): detail hanya di non-production (§16.6).\n */\nfunction apiErrorResponse(error: unknown, route: ApiRouteDefinition): Response {\n const isProduction = process.env[\"NODE_ENV\"] === \"production\";\n if (error instanceof MoonsError) {\n console.error(`[moons] API ${route.path}: ${error.format()}`);\n return new Response(isProduction ? \"Terjadi kesalahan internal.\" : error.format(), {\n status: 500,\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n });\n }\n console.error(`[moons] API ${route.path}:`, error);\n return new Response(isProduction ? \"Terjadi kesalahan internal.\" : String(error), {\n status: 500,\n headers: { \"content-type\": \"text/plain; charset=utf-8\" },\n });\n}\n\nfunction internalErrorResponse(error: unknown, options: { log?: boolean } = {}): Response {\n if (options.log !== false) {\n console.error(\"[moons] request error:\", error);\n }\n\n const detail =\n process.env[\"NODE_ENV\"] !== \"production\" && error instanceof MoonsError\n ? `<pre>${escapeHtml(error.format())}</pre>`\n : \"<p>Terjadi kesalahan internal.</p>\";\n\n return htmlResponse(\n `<!doctype html><html lang=\"id\"><head><meta charset=\"utf-8\"><title>500</title></head><body><h1>500</h1>${detail}</body></html>`,\n 500,\n );\n}\n\nfunction htmlResponse(html: string, status: number): Response {\n return new Response(html, {\n status,\n headers: { \"content-type\": \"text/html; charset=utf-8\" },\n });\n}\n\n/** §19.5: `/_moons/health` → `{ ok: true }`. */\nfunction healthResponse(method: string): Response {\n const headers = { \"content-type\": \"application/json; charset=utf-8\" };\n if (method === \"GET\" || method === \"HEAD\") {\n return new Response(method === \"HEAD\" ? null : JSON.stringify({ ok: true }), {\n status: 200,\n headers,\n });\n }\n return new Response(\"Method Not Allowed\", {\n status: 405,\n headers: { allow: \"GET, HEAD\" },\n });\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\");\n}\n\n/**\n * A1: peringatan dev untuk payload SSR yang memuat canary/nilai env\n * mirip-rahasia (sekali per label). Tidak pernah aktif di production karena\n * `payloadScan` hanya diisi runtime dev.\n */\nfunction warnPayloadFindings(\n payload: string,\n scan: PayloadScanOptions | undefined,\n warned: Set<string>,\n): void {\n if (scan === undefined) {\n return;\n }\n for (const finding of scanPayloadForSecrets(payload, scan)) {\n const label = finding.kind === \"canary\" ? \"canary\" : `env(${finding.label})`;\n if (warned.has(label)) {\n continue;\n }\n warned.add(label);\n console.warn(\n `[moons] peringatan dev: payload SSR memuat ${label} — jangan mengembalikan rahasia dari loader.`,\n );\n }\n}\n",
6
6
  "/**\n * Pemindaian payload SSR (nilai A1 / PRD §2): HANYA dipakai di dev sebagai\n * peringatan — tidak ada biaya runtime di production (production tidak pernah\n * memanggil fungsi ini; lihat `RequestHandlerOptions.payloadScan`).\n */\n\nexport interface PayloadScanOptions {\n /** Canary `leakTest.canary` (bila dikonfigurasi). */\n canary?: string;\n /** Lingkungan server (biasanya `process.env`). */\n env?: Record<string, string | undefined>;\n}\n\nexport interface PayloadScanFinding {\n kind: \"canary\" | \"env\";\n /** Label untuk pesan: `canary` atau nama env var. */\n label: string;\n}\n\n/**\n * Nama env yang \"mirip rahasia\" — dideteksi lewat pola nama + panjang nilai\n * minimum 12 karakter untuk menghindari false positive (keputusan pemilik).\n */\nconst SECRET_KEY_PATTERN =\n /(SECRET|TOKEN|PASSWORD|PASSWD|PRIVATE|CREDENTIAL|AUTH|API_KEY|ACCESS_KEY|SIGNING)/i;\n\nconst MIN_SECRET_LENGTH = 12;\n\nexport function scanPayloadForSecrets(\n payload: string,\n options: PayloadScanOptions = {},\n): PayloadScanFinding[] {\n const findings: PayloadScanFinding[] = [];\n\n const canary = options.canary;\n if (canary !== undefined && canary.length > 0 && payload.includes(canary)) {\n findings.push({ kind: \"canary\", label: \"canary\" });\n }\n\n for (const [key, value] of Object.entries(options.env ?? {})) {\n if (typeof value !== \"string\" || value.length < MIN_SECRET_LENGTH) {\n continue;\n }\n if (!SECRET_KEY_PATTERN.test(key) || /PUBLIC/i.test(key)) {\n continue;\n }\n if (payload.includes(value)) {\n findings.push({ kind: \"env\", label: key });\n }\n }\n\n return findings;\n}\n",
7
7
  "import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { createServer, type Server } from \"node:http\";\nimport { extname, join, resolve, sep } from \"node:path\";\nimport { revalidatePrerendered, shouldRevalidate } from \"./isr\";\nimport { sendNodeResponse, toWebRequest } from \"./node\";\nimport type { PluginRuntime } from \"./plugins\";\nimport { installGracefulShutdown } from \"./shutdown\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".js\": \"text/javascript; charset=utf-8\",\n \".mjs\": \"text/javascript; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".html\": \"text/html; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".map\": \"application/json; charset=utf-8\",\n \".ico\": \"image/x-icon\",\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".svg\": \"image/svg+xml\",\n \".webp\": \"image/webp\",\n \".avif\": \"image/avif\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n \".ttf\": \"font/ttf\",\n \".txt\": \"text/plain; charset=utf-8\",\n \".wasm\": \"application/wasm\",\n};\n\nexport interface NodeServerOptions {\n port?: number;\n clientDir?: string;\n /** Pasang handler SIGTERM/SIGINT (default true). */\n handleSignals?: boolean;\n /** Batas drain shutdown (default 10_000 ms). */\n shutdownTimeoutMs?: number;\n /** Lifecycle plugin (Addendum B.4) — onStart/onReady/onShutdown. */\n plugins?: PluginRuntime;\n /** Canary `leakTest.canary` untuk guard ISR (Addendum E.1). */\n canary?: string;\n}\n\n/**\n * Serve produksi (M1 §19.2, §18): static dari `dist/client` + handler SSR.\n * Berjalan di Bun dan Node (hanya API `node:*`).\n */\nexport function startNodeServer(\n handler: (request: Request) => Promise<Response>,\n options: NodeServerOptions = {},\n): Server {\n const clientDir = resolve(options.clientDir ?? join(process.cwd(), \"dist/client\"));\n const port = options.port ?? Number(process.env[\"PORT\"] ?? 3000);\n\n const server = createServer((req, res) => {\n void (async () => {\n try {\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`);\n\n if (req.method === \"GET\" || req.method === \"HEAD\") {\n const staticFile = resolveStaticFile(clientDir, url.pathname);\n if (staticFile !== null) {\n scheduleRevalidation(staticFile, url.pathname, handler, options, clientDir);\n const body = readFileSync(staticFile);\n res.statusCode = 200;\n res.setHeader(\"content-type\", MIME_TYPES[extname(staticFile).toLowerCase()] ?? \"application/octet-stream\");\n res.end(req.method === \"HEAD\" ? undefined : body);\n return;\n }\n }\n\n const response = await handler(await toWebRequest(req));\n await sendNodeResponse(res, response);\n } catch (error) {\n console.error(\"[moons] server error:\", error);\n res.statusCode = 500;\n res.setHeader(\"content-type\", \"text/plain; charset=utf-8\");\n res.end(\"Internal Server Error\");\n }\n })();\n });\n\n // Addendum B.4: onStart sebelum listen, onReady setelah listen.\n const listenAfterStart = (): void => {\n server.listen(port, () => {\n const address = server.address();\n const boundPort = typeof address === \"object\" && address !== null ? address.port : port;\n console.log(`[moons] server listening on http://localhost:${boundPort}`);\n void options.plugins?.ready();\n });\n };\n if (options.plugins !== undefined) {\n void options.plugins.start().then(listenAfterStart);\n } else {\n listenAfterStart();\n }\n\n if (options.handleSignals !== false) {\n const shutdown = installGracefulShutdown(server, {\n ...(options.shutdownTimeoutMs === undefined ? {} : { timeoutMs: options.shutdownTimeoutMs }),\n ...(options.plugins === undefined\n ? {}\n : { onShutdown: () => options.plugins?.shutdown() }),\n });\n // `once`: sinyal kedua memakai perilaku default (proses langsung berhenti).\n process.once(\"SIGTERM\", () => shutdown(\"SIGTERM\"));\n process.once(\"SIGINT\", () => shutdown(\"SIGINT\"));\n }\n\n return server;\n}\n\n/** Resolve file static dengan proteksi path traversal (+ manifest prerender D.5). */\nexport function resolveStaticFile(clientDir: string, pathname: string): string | null {\n let decoded: string;\n try {\n decoded = decodeURIComponent(pathname);\n } catch {\n return null;\n }\n\n // 1) File persis (aset: js/css/png/…, atau HTML yang diminta eksplisit).\n const exact = safeWithin(clientDir, `.${decoded}`);\n if (exact !== null && isFile(exact)) {\n return exact;\n }\n\n // 2) Hasil prerender: hanya path yang tercatat di manifest yang dilayani\n // statis — bukan shell `index.html` biasa (yang berarti bypass SSR).\n const normalized = decoded.length > 1 ? decoded.replace(/\\/+$/, \"\") : decoded;\n const manifest = readPrerenderManifest(clientDir);\n if (manifest.paths.has(normalized)) {\n const target = normalized === \"/\" ? \"index.html\" : `${normalized.slice(1)}/index.html`;\n const candidate = safeWithin(clientDir, `./${target}`);\n if (candidate !== null && isFile(candidate)) {\n return candidate;\n }\n }\n\n return null;\n}\n\nfunction safeWithin(clientDir: string, relative: string): string | null {\n const candidate = resolve(clientDir, relative);\n if (candidate !== clientDir && !candidate.startsWith(clientDir + sep)) {\n return null;\n }\n return candidate;\n}\n\nfunction isFile(path: string): boolean {\n return existsSync(path) && statSync(path).isFile();\n}\n\nexport interface PrerenderManifestInfo {\n paths: Set<string>;\n revalidate: Map<string, number>;\n}\n\nlet prerenderManifestCache:\n | { file: string; mtimeMs: number; info: PrerenderManifestInfo }\n | null = null;\n\nfunction readPrerenderManifest(clientDir: string): PrerenderManifestInfo {\n const file = join(clientDir, \"_moons_prerender.json\");\n const empty: PrerenderManifestInfo = { paths: new Set(), revalidate: new Map() };\n try {\n const mtimeMs = statSync(file).mtimeMs;\n if (\n prerenderManifestCache !== null &&\n prerenderManifestCache.file === file &&\n prerenderManifestCache.mtimeMs === mtimeMs\n ) {\n return prerenderManifestCache.info;\n }\n const json = JSON.parse(readFileSync(file, \"utf8\")) as {\n paths?: unknown;\n version?: unknown;\n entries?: unknown;\n };\n const paths = new Set<string>();\n const revalidate = new Map<string, number>();\n if (Array.isArray(json.paths)) {\n // Manifest v1 (D.5) — tanpa revalidate.\n for (const path of json.paths) {\n if (typeof path === \"string\") {\n paths.add(path);\n }\n }\n }\n if (Array.isArray(json.entries)) {\n // Manifest v2 (E.1).\n for (const entry of json.entries as Array<Record<string, unknown>>) {\n if (entry === null || typeof entry !== \"object\" || typeof entry[\"path\"] !== \"string\") {\n continue;\n }\n const path = entry[\"path\"] as string;\n paths.add(path);\n const seconds = entry[\"revalidate\"];\n if (typeof seconds === \"number\" && Number.isFinite(seconds) && seconds >= 0) {\n revalidate.set(path, seconds);\n }\n }\n }\n const info = { paths, revalidate };\n prerenderManifestCache = { file, mtimeMs, info };\n return info;\n } catch {\n return empty;\n }\n}\n\n/** ISR: jika file prerender kedaluwarsa, regenerasi background (SWR). */\nfunction scheduleRevalidation(\n staticFile: string,\n pathname: string,\n handler: (request: Request) => Promise<Response>,\n options: NodeServerOptions,\n clientDir: string,\n): void {\n const normalized = pathname.length > 1 ? pathname.replace(/\\/+$/, \"\") : pathname;\n const seconds = readPrerenderManifest(clientDir).revalidate.get(normalized);\n if (seconds === undefined || seconds < 0) {\n return;\n }\n let mtimeMs: number;\n try {\n mtimeMs = statSync(staticFile).mtimeMs;\n } catch {\n return;\n }\n if (!shouldRevalidate({ mtimeMs, revalidateSeconds: seconds })) {\n return;\n }\n void revalidatePrerendered({\n pathname: normalized,\n file: staticFile,\n handler,\n ...(options.canary === undefined ? {} : { canary: options.canary }),\n });\n}\n\n",
8
8
  "import { renameSync, writeFileSync } from \"node:fs\";\nimport { scanPayloadForSecrets } from \"../payload-scan\";\n\n/**\n * ISR / revalidate on-demand (PRD Addendum E.1): file prerender yang kedaluwarsa\n * disajikan apa adanya (stale-while-revalidate) sambil diregenerasi via handler\n * SSR in-process. Tulis atomik + guard kebocoran fail-closed.\n */\nexport function shouldRevalidate(input: {\n mtimeMs: number;\n revalidateSeconds: number;\n now?: number;\n}): boolean {\n const now = input.now ?? Date.now();\n return now - input.mtimeMs >= input.revalidateSeconds * 1000;\n}\n\nexport interface RevalidateOptions {\n /** Path URL ternormalisasi (mis. \"/blog/hello\"). */\n pathname: string;\n /** File HTML yang akan ditimpa. */\n file: string;\n handler: (request: Request) => Promise<Response>;\n canary?: string;\n env?: Record<string, string | undefined>;\n log?: (message: string) => void;\n}\n\nconst inflight = new Map<string, Promise<void>>();\n\n/** Regenerasi ter-dedupe per path (panggilan paralel berbagi promise). */\nexport function revalidatePrerendered(options: RevalidateOptions): Promise<void> {\n const existing = inflight.get(options.pathname);\n if (existing !== undefined) {\n return existing;\n }\n const task = runRevalidate(options).finally(() => {\n inflight.delete(options.pathname);\n });\n inflight.set(options.pathname, task);\n return task;\n}\n\nasync function runRevalidate(options: RevalidateOptions): Promise<void> {\n const log = options.log ?? ((message: string) => console.log(message));\n try {\n const response = await options.handler(\n new Request(`http://localhost${options.pathname}`, {\n method: \"GET\",\n headers: { \"x-moons-prerender\": \"1\" },\n }),\n );\n if (response.status !== 200) {\n log(`[moons] isr: lewati ${options.pathname} (status ${response.status})`);\n return;\n }\n const html = await response.text();\n const findings = scanPayloadForSecrets(html, {\n ...(options.canary === undefined ? {} : { canary: options.canary }),\n env: options.env ?? process.env,\n });\n if (findings.length > 0) {\n const labels = findings\n .map((finding) => (finding.kind === \"canary\" ? \"canary\" : `env(${finding.label})`))\n .join(\", \");\n // Fail-closed: jangan menimpa file statis dengan konten bocor.\n log(`[moons] isr: TIDAK menulis ${options.pathname} — memuat ${labels}`);\n return;\n }\n const tmp = `${options.file}.tmp-${process.pid}`;\n writeFileSync(tmp, html);\n renameSync(tmp, options.file);\n } catch (error) {\n log(`[moons] isr: gagal regenerasi ${options.pathname}: ${String(error)}`);\n }\n}\n\n/** Test helper: bersihkan dedupe in-flight. */\nexport function __resetIsrInflight(): void {\n inflight.clear();\n}\n",
9
9
  "import type { Server } from \"node:http\";\n\nexport interface ShutdownOptions {\n /** Batas drain sebelum keluar paksa (default 10_000 ms). */\n timeoutMs?: number;\n log?: (message: string) => void;\n /** Injectable untuk test; default `process.exit`. */\n exit?: (code: number) => void;\n /**\n * Dipanggil setelah drain penuh, sebelum exit (Addendum B.4: onShutdown\n * plugin). Berbagi batas waktu dengan drain; error dilaporkan, tidak\n * menggagalkan shutdown.\n */\n onShutdown?: () => void | Promise<void>;\n}\n\n/**\n * Graceful shutdown (PRD §19.5): SIGTERM/SIGINT → stop menerima koneksi baru →\n * drain request berjalan → exit 0. Melewati timeout → keluar paksa exit 1.\n *\n * Handler dipasang `once` oleh pemanggil, sehingga sinyal kedua memakai\n * perilaku default (proses langsung berhenti).\n */\nexport function installGracefulShutdown(\n server: Server,\n options: ShutdownOptions = {},\n): (signal: NodeJS.Signals) => void {\n const timeoutMs = options.timeoutMs ?? 10_000;\n const log = options.log ?? ((message: string) => console.log(message));\n const exit = options.exit ?? ((code: number) => process.exit(code));\n\n let shuttingDown = false;\n\n return (signal: NodeJS.Signals): void => {\n if (shuttingDown) {\n return;\n }\n shuttingDown = true;\n log(`[moons] menerima ${signal} — berhenti menerima koneksi, drain...`);\n\n const timer = setTimeout(() => {\n log(`[moons] drain melewati ${timeoutMs}ms — keluar paksa`);\n const closeAll = (server as { closeAllConnections?: () => void }).closeAllConnections;\n try {\n closeAll?.call(server);\n } catch {\n // abaikan: keluar paksa tetap jalan\n }\n exit(1);\n }, timeoutMs);\n timer.unref?.();\n\n try {\n (server as { closeIdleConnections?: () => void }).closeIdleConnections?.();\n } catch {\n // abaikan: fallback timeout tetap ada\n }\n\n server.close(async (error?: Error) => {\n if (error !== undefined) {\n clearTimeout(timer);\n log(`[moons] penutupan server gagal: ${error.message}`);\n exit(1);\n return;\n }\n if (options.onShutdown !== undefined) {\n // Tetap berbagi batas waktu dengan drain: timer di-ref kembali agar\n // proses tidak keluar sebelum hook selesai.\n (timer as { ref?: () => void }).ref?.();\n try {\n await options.onShutdown();\n } catch (hookError) {\n log(`[moons] onShutdown gagal: ${String(hookError)}`);\n }\n }\n clearTimeout(timer);\n log(\"[moons] shutdown selesai (drain penuh)\");\n exit(0);\n });\n };\n}\n",
10
10
  "import type { MoonsConfig, RouteDefinition, RouteModule } from \"@moonsjs/core\";\nimport { createRequestHandler } from \"./handler\";\nimport { DEFAULT_TEMPLATE, injectShell, type Shell } from \"./shell\";\n\nexport interface TestServerOptions {\n routes: RouteDefinition[];\n config: MoonsConfig;\n routesDir: string;\n loadRoute: Record<string, () => Promise<RouteModule>>;\n /** Default: shell in-memory dari `DEFAULT_TEMPLATE` (tanpa file). */\n shell?: Shell;\n}\n\nexport interface TestServer {\n handler: (request: Request) => Promise<Response>;\n /** Dispatch request langsung ke handler — tanpa port/jaringan (§19.5). */\n fetch(input: string, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Utility test in-process (PRD §19.5): jalankan handler tanpa listen port.\n * Dipakai test aplikasi user maupun test internal framework.\n */\nexport function createTestServer(\n options: TestServerOptions,\n baseUrl = \"http://localhost\",\n): TestServer {\n const shell: Shell =\n options.shell ??\n ((markup, payload, _url, meta) => injectShell(DEFAULT_TEMPLATE, markup, payload, meta));\n\n const handler = createRequestHandler({\n routes: options.routes,\n config: options.config,\n routesDir: options.routesDir,\n loadRoute: options.loadRoute,\n shell,\n });\n\n return {\n handler,\n fetch: (input: string, init?: RequestInit) =>\n handler(new Request(new URL(input, baseUrl), init)),\n };\n}\n",
11
11
  "import { MOONS_VERSION, type App, type Middleware, type MoonsConfig, type RouteDefinition } from \"@moonsjs/core\";\n\n/**\n * Eksekusi lifecycle plugin (PRD §14.4 / Addendum B.4).\n * Urutan: registrasi (addRoute per route → addMiddleware per middleware →\n * extendContext(register)) → onStart → ready/onReady → shutdown/onShutdown.\n */\nexport interface PluginRuntime {\n readonly app: App;\n /** Registrasi + `onStart` (sebelum server siap). */\n start(): Promise<void>;\n /** Tandai `app.ready = true` lalu panggil `onReady` (server siap). */\n ready(): Promise<void>;\n /** Panggil `onShutdown` (selama drain; error dilaporkan, tidak menggagalkan). */\n shutdown(): Promise<void>;\n /** Terapkan extender `extendContext` ke ctx request (dipanggil handler). */\n applyExtensions(ctx: unknown): void;\n}\n\nexport interface PluginRuntimeOptions {\n config: MoonsConfig;\n routes: RouteDefinition[];\n /** Rantai middleware final (config.middleware). */\n middlewares: Middleware[];\n log?: (message: string) => void;\n}\n\nexport function createPluginRuntime(options: PluginRuntimeOptions): PluginRuntime {\n const log = options.log ?? ((message: string) => console.warn(message));\n const plugins = options.config.plugins ?? [];\n const state = { ready: false, version: MOONS_VERSION };\n const app = state as App;\n const extensions: Array<(ctx: unknown) => unknown> = [];\n const register = (fn: (ctx: unknown) => unknown): void => {\n extensions.push(fn);\n };\n\n // Fase registrasi (sinkron): addRoute → addMiddleware → extendContext.\n for (const plugin of plugins) {\n for (const route of options.routes) {\n // Objek beku: hook bersifat observasi di v1 (lihat docs/decisions/0022).\n const frozen = Object.freeze({\n ...route,\n params: [...route.params],\n }) as RouteDefinition;\n plugin.addRoute?.(frozen);\n }\n for (const middleware of options.middlewares) {\n plugin.addMiddleware?.(middleware);\n }\n plugin.extendContext?.(register as never);\n }\n\n return {\n app,\n async start(): Promise<void> {\n for (const plugin of plugins) {\n await plugin.onStart?.(app);\n }\n },\n async ready(): Promise<void> {\n state.ready = true;\n for (const plugin of plugins) {\n await plugin.onReady?.(app);\n }\n },\n async shutdown(): Promise<void> {\n for (const plugin of plugins) {\n try {\n await plugin.onShutdown?.(app);\n } catch (error) {\n log(`[moons] plugin \\`${plugin.name}\\` gagal saat onShutdown: ${String(error)}`);\n }\n }\n },\n applyExtensions(ctx: unknown): void {\n for (const extend of extensions) {\n const result = extend(ctx);\n if (result !== null && typeof result === \"object\" && !Array.isArray(result)) {\n Object.assign(ctx as Record<string, unknown>, result);\n }\n }\n },\n };\n}\n",
12
- "import { MoonsError, type RouteDefinition, type RouteModule } from \"@moonsjs/core\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { scanPayloadForSecrets } from \"../payload-scan\";\n\n/**\n * Prerender statis (PRD Addendum D.5): render route ber-`prerender = true`\n * saat build → `dist/client/<path>/index.html` (guard: payload scan fail-mode).\n */\nexport interface PrerenderOptions {\n routes: RouteDefinition[];\n routesDir: string;\n loadRoute: Record<string, () => Promise<RouteModule>>;\n /** Handler SSR yang sudah dibuat runtime (createRequestHandler). */\n handler: (request: Request) => Promise<Response>;\n /** Tujuan file statis (biasanya `<root>/dist/client`). */\n clientDir: string;\n canary?: string;\n env?: Record<string, string | undefined>;\n log?: (message: string) => void;\n}\n\nexport interface PrerenderResult {\n written: number;\n skipped: number;\n}\n\n/**\n * Manifest path yang benar-benar di-prerender (dibaca static server agar hanya\n * file hasil prerender yang \"menang\" atas SSR — bukan shell index.html biasa).\n */\nexport const PRERENDER_MANIFEST_FILE = \"_moons_prerender.json\";\n\nexport async function runPrerender(options: PrerenderOptions): Promise<PrerenderResult> {\n const log = options.log ?? ((message: string) => console.log(message));\n const env = options.env ?? process.env;\n let written = 0;\n let skipped = 0;\n const entries: Array<{ path: string; revalidate?: number }> = [];\n\n const pages = options.routes.filter((route) => route.kind === \"page\");\n for (const route of pages) {\n const key = routeKeyOf(options.routesDir, route.file);\n const load = options.loadRoute[key];\n if (load === undefined) {\n continue;\n }\n const module = (await load()) as RouteModule;\n const prerender = module.prerender;\n const revalidate = module.revalidate;\n\n // Addendum E.1: `revalidate` hanya sah bersama `prerender`.\n if (revalidate !== undefined) {\n if (\n typeof revalidate !== \"number\" ||\n !Number.isFinite(revalidate) ||\n revalidate < 0 ||\n prerender !== true\n ) {\n throw new MoonsError({\n code: \"E_ISR_INVALID\",\n file: route.file,\n message: \"`revalidate` tidak valid atau dipakai tanpa `prerender = true`\",\n details: \"ISR berbasis file: `revalidate` (detik, number >= 0) + `prerender`.\",\n suggestions: [\n \"Gunakan angka detik, mis. `export const revalidate = 60`\",\n \"Tambahkan `export const prerender = true` pada page yang sama\",\n ],\n });\n }\n }\n\n if (prerender !== true) {\n if (prerender !== undefined && prerender !== false) {\n throw prerenderError(route, \"`prerender` harus boolean (`true`/`false`)\");\n }\n continue;\n }\n\n const pathnames = await resolvePathnames(route, module);\n for (const pathname of pathnames) {\n const response = await options.handler(\n new Request(`http://localhost${pathname}`, {\n method: \"GET\",\n headers: { \"x-moons-prerender\": \"1\" },\n }),\n );\n\n if (response.status === 404) {\n log(`[moons] prerender: lewati ${pathname} (notFound)`);\n skipped += 1;\n continue;\n }\n if (response.status >= 300 && response.status < 400) {\n throw prerenderError(route, `\\`redirect()\\` tidak didukung saat prerender (${pathname})`);\n }\n if (response.status !== 200) {\n throw prerenderError(route, `status ${response.status} saat merender ${pathname}`);\n }\n\n const html = await response.text();\n const findings = scanPayloadForSecrets(html, {\n ...(options.canary === undefined ? {} : { canary: options.canary }),\n env,\n });\n if (findings.length > 0) {\n const labels = findings\n .map((finding) => (finding.kind === \"canary\" ? \"canary\" : `env(${finding.label})`))\n .join(\", \");\n throw new MoonsError({\n code: \"E_PRERENDER_LEAK\",\n file: route.file,\n message: `hasil prerender \\`${pathname}\\` memuat ${labels}`,\n details:\n \"HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.\",\n suggestions: [\n \"Jangan mengembalikan nilai env rahasia dari loader yang di-prerender\",\n \"Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time\",\n ],\n });\n }\n\n const file = outputFile(options.clientDir, pathname);\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(file, html);\n entries.push(\n typeof revalidate === \"number\" && revalidate >= 0\n ? { path: pathname, revalidate }\n : { path: pathname },\n );\n written += 1;\n }\n }\n\n // Manifest v2 (Addendum E.1): entries + revalidate; reader tetap menerima v1.\n writeFileSync(\n join(options.clientDir, PRERENDER_MANIFEST_FILE),\n `${JSON.stringify({ version: 2, entries }, null, 2)}\\n`,\n );\n\n log(`[moons] prerender selesai: ${written} file (${skipped} dilewati)`);\n return { written, skipped };\n}\n\nfunction routeKeyOf(routesDir: string, file: string): string {\n const relative = file.startsWith(routesDir) ? file.slice(routesDir.length + 1) : file;\n return relative.split(\"\\\\\").join(\"/\").replace(/\\.(tsx|ts)$/, \"\");\n}\n\nasync function resolvePathnames(route: RouteDefinition, module: RouteModule): Promise<string[]> {\n const isDynamic = route.params.length > 0;\n if (!isDynamic) {\n return [route.path];\n }\n const paths = module.paths;\n if (typeof paths !== \"function\") {\n throw new MoonsError({\n code: \"E_PRERENDER_NO_PATHS\",\n file: route.file,\n message: \"route dynamic ber-`prerender = true` tanpa `export const paths`\",\n details: \"Prerender butuh daftar param untuk merender tiap path.\",\n suggestions: [\n 'Tambahkan `export const paths = () => [{ id: \"…\" }]`',\n \"Atau hapus `prerender` agar dirender SSR saat request\",\n ],\n });\n }\n\n const raw = await (paths as () => unknown | Promise<unknown>)();\n if (!Array.isArray(raw)) {\n throw prerenderError(route, \"`paths()` harus mengembalikan array\");\n }\n\n const expected = new Set(route.params);\n const result: string[] = [];\n for (const item of raw as unknown[]) {\n if (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n throw prerenderError(route, \"item `paths()` harus objek param string\");\n }\n const record = item as Record<string, unknown>;\n const keys = Object.keys(record);\n for (const name of expected) {\n const value = record[name];\n if (typeof value !== \"string\" || value.length === 0) {\n throw prerenderError(route, `param \\`${name}\\` wajib string non-kosong`);\n }\n }\n for (const key of keys) {\n if (!expected.has(key)) {\n throw prerenderError(route, `param \\`${key}\\` tidak ada di pola route`);\n }\n }\n result.push(buildPathname(route, record as Record<string, string>));\n }\n return result;\n}\n\nfunction buildPathname(route: RouteDefinition, params: Record<string, string>): string {\n const segments = route.path.split(\"/\").filter((segment) => segment.length > 0);\n const out: string[] = [];\n let catchallName: string | null = null;\n for (const segment of segments) {\n if (segment === \"*\") {\n catchallName = route.params[route.params.length - 1] ?? null;\n const value = catchallName === null ? \"\" : (params[catchallName] ?? \"\");\n for (const part of value.split(\"/\")) {\n if (part.length === 0) {\n continue;\n }\n out.push(encodeSegment(route, part));\n }\n continue;\n }\n if (segment.startsWith(\":\")) {\n out.push(encodeSegment(route, params[segment.slice(1)] ?? \"\"));\n continue;\n }\n out.push(segment);\n }\n return `/${out.join(\"/\")}`;\n}\n\nfunction encodeSegment(route: RouteDefinition, value: string): string {\n if (value.length === 0 || /^\\.+$/.test(value)) {\n throw prerenderError(route, `nilai param \\`${value}\\` tidak valid untuk path file`);\n }\n return encodeURIComponent(value);\n}\n\nfunction outputFile(clientDir: string, pathname: string): string {\n const parts = pathname.split(\"/\").filter((part) => part.length > 0);\n const file = resolve(join(clientDir, ...parts, \"index.html\"));\n const base = resolve(clientDir);\n if (file !== base && !file.startsWith(base + sep)) {\n throw new MoonsError({\n code: \"E_PRERENDER_INVALID\",\n message: `path prerender keluar dari direktori client (\\`${pathname}\\`)`,\n details: \"Nama file harus berada di dalam `dist/client`.\",\n suggestions: [\"Periksa nilai param `paths` — jangan memakai `..`\"],\n });\n }\n return file;\n}\n\nfunction prerenderError(route: RouteDefinition, message: string): MoonsError {\n return new MoonsError({\n code: \"E_PRERENDER_INVALID\",\n file: route.file,\n message,\n details: \"Kontrak prerender mengikuti.\",\n suggestions: [\n \"Perbaiki bentuk `paths`/param agar cocok dengan pola route\",\n \"Jangan memakai `redirect()` pada route yang di-prerender\",\n ],\n });\n}\n"
12
+ "import { MoonsError, type RouteDefinition, type RouteModule } from \"@moonsjs/core\";\nimport { mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { scanPayloadForSecrets } from \"../payload-scan\";\n\n/**\n * Prerender statis (PRD Addendum D.5): render route ber-`prerender = true`\n * saat build → `dist/client/<path>/index.html` (guard: payload scan fail-mode).\n */\n/** Addendum H: config statis yang ditulis saat prerender (deploy kit). */\nexport interface PrerenderStaticConfig {\n headers?: Record<string, string>;\n redirects?: Array<{ from: string; to: string; status?: number }>;\n sitemap?: { site: string; exclude?: string[] };\n robots?: { sitemap?: boolean; disallow?: string[] };\n}\n\nexport interface PrerenderOptions {\n routes: RouteDefinition[];\n routesDir: string;\n loadRoute: Record<string, () => Promise<RouteModule>>;\n /** Handler SSR yang sudah dibuat runtime (createRequestHandler). */\n handler: (request: Request) => Promise<Response>;\n /** Tujuan file statis (biasanya `<root>/dist/client`). */\n clientDir: string;\n canary?: string;\n env?: Record<string, string | undefined>;\n log?: (message: string) => void;\n /** Addendum H: `headers`/`redirects`/`sitemap`/`robots` dari config. */\n staticConfig?: PrerenderStaticConfig;\n}\n\nexport interface PrerenderResult {\n written: number;\n skipped: number;\n}\n\n/**\n * Manifest path yang benar-benar di-prerender (dibaca static server agar hanya\n * file hasil prerender yang \"menang\" atas SSR — bukan shell index.html biasa).\n */\nexport const PRERENDER_MANIFEST_FILE = \"_moons_prerender.json\";\n\n/**\n * Addendum G: sentinel internal untuk merender halaman 404 statis. Path ini\n * tidak pernah menjadi route publik; handler merendernya seperti request tak\n * dikenal (route `_404` atau 404 bawaan).\n */\nexport const NOT_FOUND_SENTINEL = \"/_moons/404\";\n\n/** Addendum G: nama file 404 untuk static host (konvensi Cloudflare Pages/Netlify). */\nexport const NOT_FOUND_FILE = \"404.html\";\n\nexport async function runPrerender(options: PrerenderOptions): Promise<PrerenderResult> {\n const log = options.log ?? ((message: string) => console.log(message));\n const env = options.env ?? process.env;\n let written = 0;\n let skipped = 0;\n const entries: Array<{ path: string; revalidate?: number }> = [];\n\n const pages = options.routes.filter((route) => route.kind === \"page\");\n for (const route of pages) {\n const key = routeKeyOf(options.routesDir, route.file);\n const load = options.loadRoute[key];\n if (load === undefined) {\n continue;\n }\n const module = (await load()) as RouteModule;\n const prerender = module.prerender;\n const revalidate = module.revalidate;\n\n // Addendum E.1: `revalidate` hanya sah bersama `prerender`.\n if (revalidate !== undefined) {\n if (\n typeof revalidate !== \"number\" ||\n !Number.isFinite(revalidate) ||\n revalidate < 0 ||\n prerender !== true\n ) {\n throw new MoonsError({\n code: \"E_ISR_INVALID\",\n file: route.file,\n message: \"`revalidate` tidak valid atau dipakai tanpa `prerender = true`\",\n details: \"ISR berbasis file: `revalidate` (detik, number >= 0) + `prerender`.\",\n suggestions: [\n \"Gunakan angka detik, mis. `export const revalidate = 60`\",\n \"Tambahkan `export const prerender = true` pada page yang sama\",\n ],\n });\n }\n }\n\n if (prerender !== true) {\n if (prerender !== undefined && prerender !== false) {\n throw prerenderError(route, \"`prerender` harus boolean (`true`/`false`)\");\n }\n continue;\n }\n\n const pathnames = await resolvePathnames(route, module);\n for (const pathname of pathnames) {\n const response = await options.handler(\n new Request(`http://localhost${pathname}`, {\n method: \"GET\",\n headers: { \"x-moons-prerender\": \"1\" },\n }),\n );\n\n if (response.status === 404) {\n log(`[moons] prerender: lewati ${pathname} (notFound)`);\n skipped += 1;\n continue;\n }\n if (response.status >= 300 && response.status < 400) {\n throw prerenderError(route, `\\`redirect()\\` tidak didukung saat prerender (${pathname})`);\n }\n if (response.status !== 200) {\n throw prerenderError(route, `status ${response.status} saat merender ${pathname}`);\n }\n\n const html = await response.text();\n assertNoLeak(html, pathname, route.file, options, env);\n\n const file = outputFile(options.clientDir, pathname);\n mkdirSync(dirname(file), { recursive: true });\n writeFileSync(file, html);\n entries.push(\n typeof revalidate === \"number\" && revalidate >= 0\n ? { path: pathname, revalidate }\n : { path: pathname },\n );\n written += 1;\n }\n }\n\n // Addendum G: `404.html` untuk static host, bila app punya route `_404`.\n const notFound = await renderStaticNotFound(options, env, log);\n let wrote404 = false;\n if (notFound !== null) {\n writeFileSync(join(options.clientDir, NOT_FOUND_FILE), notFound);\n wrote404 = true;\n }\n\n // Manifest v2 (Addendum E.1): entries + revalidate; reader tetap menerima v1.\n writeFileSync(\n join(options.clientDir, PRERENDER_MANIFEST_FILE),\n `${JSON.stringify({ version: 2, entries }, null, 2)}\\n`,\n );\n\n // Addendum H: deploy kit statis (headers/redirects/sitemap/robots).\n const emitted = emitStaticFiles(options.clientDir, options.staticConfig, entries);\n\n const extras = [...(wrote404 ? [NOT_FOUND_FILE] : []), ...emitted];\n log(\n `[moons] prerender selesai: ${written} file${extras.length > 0 ? ` + ${extras.join(\" + \")}` : \"\"} (${skipped} dilewati)`,\n );\n return { written, skipped };\n}\n\n/** Tulis file deploy statis dari config; mengembalikan nama file yang ditulis. */\nfunction emitStaticFiles(\n clientDir: string,\n staticConfig: PrerenderStaticConfig | undefined,\n entries: Array<{ path: string }>,\n): string[] {\n if (staticConfig === undefined) {\n return [];\n }\n const emitted: string[] = [];\n\n const headers = Object.entries(staticConfig.headers ?? {});\n if (headers.length > 0) {\n const lines = [\"/*\", ...headers.map(([name, value]) => ` ${name}: ${value}`)];\n writeFileSync(join(clientDir, \"_headers\"), `${lines.join(\"\\n\")}\\n`);\n emitted.push(\"_headers\");\n }\n\n const redirects = staticConfig.redirects ?? [];\n if (redirects.length > 0) {\n const lines = redirects.map((entry) => `${entry.from} ${entry.to} ${entry.status ?? 301}`);\n writeFileSync(join(clientDir, \"_redirects\"), `${lines.join(\"\\n\")}\\n`);\n emitted.push(\"_redirects\");\n }\n\n const sitemap = staticConfig.sitemap;\n if (sitemap !== undefined) {\n const site = sitemap.site.replace(/\\/$/, \"\");\n const exclude = sitemap.exclude ?? [];\n const paths = [...new Set(entries.map((entry) => entry.path))]\n .filter((path) => !exclude.some((prefix) => path.startsWith(prefix)))\n .sort();\n const xml = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">',\n ...paths.map((path) => ` <url><loc>${site}${path === \"/\" ? \"/\" : path}</loc></url>`),\n \"</urlset>\",\n \"\",\n ].join(\"\\n\");\n writeFileSync(join(clientDir, \"sitemap.xml\"), xml);\n emitted.push(\"sitemap.xml\");\n }\n\n const robots = staticConfig.robots;\n if (robots !== undefined) {\n const lines = [\"User-agent: *\"];\n for (const path of robots.disallow ?? []) {\n lines.push(`Disallow: ${path}`);\n }\n if ((robots.sitemap ?? true) && sitemap !== undefined) {\n lines.push(\"\", `Sitemap: ${sitemap.site.replace(/\\/$/, \"\")}/sitemap.xml`);\n }\n writeFileSync(join(clientDir, \"robots.txt\"), `${lines.join(\"\\n\")}\\n`);\n emitted.push(\"robots.txt\");\n }\n\n return emitted;\n}\n\n/**\n * Addendum G: render halaman 404 ke `dist/client/404.html` (static export).\n * Ditulis hanya bila app memiliki route `_404` dan sentinel menghasilkan 404;\n * hasilnya tetap melewati guard kebocoran (fail-mode).\n */\nasync function renderStaticNotFound(\n options: PrerenderOptions,\n env: Record<string, string | undefined>,\n log: (message: string) => void,\n): Promise<string | null> {\n if (!options.routes.some((route) => route.kind === \"404\")) {\n return null;\n }\n const response = await options.handler(\n new Request(`http://localhost${NOT_FOUND_SENTINEL}`, {\n method: \"GET\",\n headers: { \"x-moons-prerender\": \"1\" },\n }),\n );\n if (response.status !== 404) {\n log(\n `[moons] prerender: ${NOT_FOUND_FILE} dilewati (sentinel \\`${NOT_FOUND_SENTINEL}\\` → ${response.status})`,\n );\n return null;\n }\n const html = await response.text();\n assertNoLeak(html, NOT_FOUND_SENTINEL, NOT_FOUND_FILE, options, env);\n return html;\n}\n\n/** Guard kebocoran fail-mode (Addendum D.5) — dipakai halaman & 404 statis. */\nfunction assertNoLeak(\n html: string,\n pathname: string,\n file: string,\n options: PrerenderOptions,\n env: Record<string, string | undefined>,\n): void {\n const findings = scanPayloadForSecrets(html, {\n ...(options.canary === undefined ? {} : { canary: options.canary }),\n env,\n });\n if (findings.length === 0) {\n return;\n }\n const labels = findings\n .map((finding) => (finding.kind === \"canary\" ? \"canary\" : `env(${finding.label})`))\n .join(\", \");\n throw new MoonsError({\n code: \"E_PRERENDER_LEAK\",\n file,\n message: `hasil prerender \\`${pathname}\\` memuat ${labels}`,\n details: \"HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.\",\n suggestions: [\n \"Jangan mengembalikan nilai env rahasia dari loader yang di-prerender\",\n \"Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time\",\n ],\n });\n}\n\nfunction routeKeyOf(routesDir: string, file: string): string {\n const relative = file.startsWith(routesDir) ? file.slice(routesDir.length + 1) : file;\n return relative.split(\"\\\\\").join(\"/\").replace(/\\.(tsx|ts)$/, \"\");\n}\n\nasync function resolvePathnames(route: RouteDefinition, module: RouteModule): Promise<string[]> {\n const isDynamic = route.params.length > 0;\n if (!isDynamic) {\n return [route.path];\n }\n const paths = module.paths;\n if (typeof paths !== \"function\") {\n throw new MoonsError({\n code: \"E_PRERENDER_NO_PATHS\",\n file: route.file,\n message: \"route dynamic ber-`prerender = true` tanpa `export const paths`\",\n details: \"Prerender butuh daftar param untuk merender tiap path.\",\n suggestions: [\n 'Tambahkan `export const paths = () => [{ id: \"…\" }]`',\n \"Atau hapus `prerender` agar dirender SSR saat request\",\n ],\n });\n }\n\n const raw = await (paths as () => unknown | Promise<unknown>)();\n if (!Array.isArray(raw)) {\n throw prerenderError(route, \"`paths()` harus mengembalikan array\");\n }\n\n const expected = new Set(route.params);\n const result: string[] = [];\n for (const item of raw as unknown[]) {\n if (item === null || typeof item !== \"object\" || Array.isArray(item)) {\n throw prerenderError(route, \"item `paths()` harus objek param string\");\n }\n const record = item as Record<string, unknown>;\n const keys = Object.keys(record);\n for (const name of expected) {\n const value = record[name];\n if (typeof value !== \"string\" || value.length === 0) {\n throw prerenderError(route, `param \\`${name}\\` wajib string non-kosong`);\n }\n }\n for (const key of keys) {\n if (!expected.has(key)) {\n throw prerenderError(route, `param \\`${key}\\` tidak ada di pola route`);\n }\n }\n result.push(buildPathname(route, record as Record<string, string>));\n }\n return result;\n}\n\nfunction buildPathname(route: RouteDefinition, params: Record<string, string>): string {\n const segments = route.path.split(\"/\").filter((segment) => segment.length > 0);\n const out: string[] = [];\n let catchallName: string | null = null;\n for (const segment of segments) {\n if (segment === \"*\") {\n catchallName = route.params[route.params.length - 1] ?? null;\n const value = catchallName === null ? \"\" : (params[catchallName] ?? \"\");\n for (const part of value.split(\"/\")) {\n if (part.length === 0) {\n continue;\n }\n out.push(encodeSegment(route, part));\n }\n continue;\n }\n if (segment.startsWith(\":\")) {\n out.push(encodeSegment(route, params[segment.slice(1)] ?? \"\"));\n continue;\n }\n out.push(segment);\n }\n return `/${out.join(\"/\")}`;\n}\n\nfunction encodeSegment(route: RouteDefinition, value: string): string {\n if (value.length === 0 || /^\\.+$/.test(value)) {\n throw prerenderError(route, `nilai param \\`${value}\\` tidak valid untuk path file`);\n }\n return encodeURIComponent(value);\n}\n\nfunction outputFile(clientDir: string, pathname: string): string {\n const parts = pathname.split(\"/\").filter((part) => part.length > 0);\n const file = resolve(join(clientDir, ...parts, \"index.html\"));\n const base = resolve(clientDir);\n if (file !== base && !file.startsWith(base + sep)) {\n throw new MoonsError({\n code: \"E_PRERENDER_INVALID\",\n message: `path prerender keluar dari direktori client (\\`${pathname}\\`)`,\n details: \"Nama file harus berada di dalam `dist/client`.\",\n suggestions: [\"Periksa nilai param `paths` — jangan memakai `..`\"],\n });\n }\n return file;\n}\n\nfunction prerenderError(route: RouteDefinition, message: string): MoonsError {\n return new MoonsError({\n code: \"E_PRERENDER_INVALID\",\n file: route.file,\n message,\n details: \"Kontrak prerender mengikuti.\",\n suggestions: [\n \"Perbaiki bentuk `paths`/param agar cocok dengan pola route\",\n \"Jangan memakai `redirect()` pada route yang di-prerender\",\n ],\n });\n}\n"
13
13
  ],
14
- "mappings": "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",
15
- "debugId": "CC962AE44069459E64756E2164756E21",
14
+ "mappings": "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",
15
+ "debugId": "52F0831250D554E464756E2164756E21",
16
16
  "names": []
17
17
  }
@@ -3,6 +3,23 @@ import { type RouteDefinition, type RouteModule } from "@moonsjs/core";
3
3
  * Prerender statis (PRD Addendum D.5): render route ber-`prerender = true`
4
4
  * saat build → `dist/client/<path>/index.html` (guard: payload scan fail-mode).
5
5
  */
6
+ /** Addendum H: config statis yang ditulis saat prerender (deploy kit). */
7
+ export interface PrerenderStaticConfig {
8
+ headers?: Record<string, string>;
9
+ redirects?: Array<{
10
+ from: string;
11
+ to: string;
12
+ status?: number;
13
+ }>;
14
+ sitemap?: {
15
+ site: string;
16
+ exclude?: string[];
17
+ };
18
+ robots?: {
19
+ sitemap?: boolean;
20
+ disallow?: string[];
21
+ };
22
+ }
6
23
  export interface PrerenderOptions {
7
24
  routes: RouteDefinition[];
8
25
  routesDir: string;
@@ -14,6 +31,8 @@ export interface PrerenderOptions {
14
31
  canary?: string;
15
32
  env?: Record<string, string | undefined>;
16
33
  log?: (message: string) => void;
34
+ /** Addendum H: `headers`/`redirects`/`sitemap`/`robots` dari config. */
35
+ staticConfig?: PrerenderStaticConfig;
17
36
  }
18
37
  export interface PrerenderResult {
19
38
  written: number;
@@ -24,5 +43,13 @@ export interface PrerenderResult {
24
43
  * file hasil prerender yang "menang" atas SSR — bukan shell index.html biasa).
25
44
  */
26
45
  export declare const PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
46
+ /**
47
+ * Addendum G: sentinel internal untuk merender halaman 404 statis. Path ini
48
+ * tidak pernah menjadi route publik; handler merendernya seperti request tak
49
+ * dikenal (route `_404` atau 404 bawaan).
50
+ */
51
+ export declare const NOT_FOUND_SENTINEL = "/_moons/404";
52
+ /** Addendum G: nama file 404 untuk static host (konvensi Cloudflare Pages/Netlify). */
53
+ export declare const NOT_FOUND_FILE = "404.html";
27
54
  export declare function runPrerender(options: PrerenderOptions): Promise<PrerenderResult>;
28
55
  //# sourceMappingURL=prerender.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/server/prerender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAKnF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,oEAAoE;IACpE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6GtF"}
1
+ {"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/server/prerender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAKnF;;;GAGG;AACH,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC/C,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC;IACtD,oEAAoE;IACpE,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACjD,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,wEAAwE;IACxE,YAAY,CAAC,EAAE,qBAAqB,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAEhD,uFAAuF;AACvF,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAwGtF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moonsjs/vite",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
package/src/plugin.ts CHANGED
@@ -576,6 +576,7 @@ function renderPrerenderEntry(
576
576
  ` routesDir: ${JSON.stringify(routesDir)},`,
577
577
  " loadRoute,",
578
578
  " handler,",
579
+ " staticConfig: config,",
579
580
  ` clientDir: ${JSON.stringify(resolvePath(projectRoot, "dist/client"))},`,
580
581
  ...(canary === undefined ? [] : [` canary: ${JSON.stringify(canary)},`]),
581
582
  "});",
@@ -343,7 +343,7 @@ export function createRequestHandler(
343
343
  return result;
344
344
  }
345
345
 
346
- return async function handler(request: Request): Promise<Response> {
346
+ const handleCore = async function handler(request: Request): Promise<Response> {
347
347
  try {
348
348
  const url = new URL(request.url);
349
349
 
@@ -436,6 +436,57 @@ export function createRequestHandler(
436
436
  return internalErrorResponse(error);
437
437
  }
438
438
  };
439
+
440
+ // Addendum H: redirect statis + hook lifecycle + header statis.
441
+ const staticHeaders = Object.entries(config.headers ?? {});
442
+ const redirects = (config.redirects ?? []).map((entry) => ({
443
+ ...entry,
444
+ status: entry.status ?? 301,
445
+ }));
446
+
447
+ return async function handler(request: Request): Promise<Response> {
448
+ const isPrerender = request.headers.get("x-moons-prerender") === "1";
449
+ const applyHeaders = (response: Response): Response => {
450
+ for (const [name, value] of staticHeaders) {
451
+ if (!response.headers.has(name)) {
452
+ response.headers.set(name, value);
453
+ }
454
+ }
455
+ return response;
456
+ };
457
+
458
+ try {
459
+ if (!isPrerender && redirects.length > 0) {
460
+ const url = new URL(request.url);
461
+ const path = url.pathname.replace(/\/$/, "");
462
+ for (const entry of redirects) {
463
+ if (path === entry.from.replace(/\/$/, "")) {
464
+ const location = entry.to.startsWith("http")
465
+ ? entry.to
466
+ : new URL(entry.to, url.origin).toString();
467
+ return applyHeaders(
468
+ new Response(null, { status: entry.status, headers: { location } }),
469
+ );
470
+ }
471
+ }
472
+ }
473
+
474
+ await config.hooks?.onRequest?.(request);
475
+ let response = await handleCore(request);
476
+ const replaced = await config.hooks?.onResponse?.(response, request);
477
+ if (replaced instanceof Response) {
478
+ response = replaced;
479
+ }
480
+ return applyHeaders(response);
481
+ } catch (error) {
482
+ try {
483
+ await config.hooks?.onError?.(error, request);
484
+ } catch {
485
+ // Kegagalan hook tidak boleh menutupi error asli.
486
+ }
487
+ return internalErrorResponse(error);
488
+ }
489
+ };
439
490
  }
440
491
 
441
492
  /** Terapkan mutasi `setHeader`/`appendHeader`/`setCookie` ke respons (D.2). */
@@ -7,6 +7,14 @@ import { scanPayloadForSecrets } from "../payload-scan";
7
7
  * Prerender statis (PRD Addendum D.5): render route ber-`prerender = true`
8
8
  * saat build → `dist/client/<path>/index.html` (guard: payload scan fail-mode).
9
9
  */
10
+ /** Addendum H: config statis yang ditulis saat prerender (deploy kit). */
11
+ export interface PrerenderStaticConfig {
12
+ headers?: Record<string, string>;
13
+ redirects?: Array<{ from: string; to: string; status?: number }>;
14
+ sitemap?: { site: string; exclude?: string[] };
15
+ robots?: { sitemap?: boolean; disallow?: string[] };
16
+ }
17
+
10
18
  export interface PrerenderOptions {
11
19
  routes: RouteDefinition[];
12
20
  routesDir: string;
@@ -18,6 +26,8 @@ export interface PrerenderOptions {
18
26
  canary?: string;
19
27
  env?: Record<string, string | undefined>;
20
28
  log?: (message: string) => void;
29
+ /** Addendum H: `headers`/`redirects`/`sitemap`/`robots` dari config. */
30
+ staticConfig?: PrerenderStaticConfig;
21
31
  }
22
32
 
23
33
  export interface PrerenderResult {
@@ -31,6 +41,16 @@ export interface PrerenderResult {
31
41
  */
32
42
  export const PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
33
43
 
44
+ /**
45
+ * Addendum G: sentinel internal untuk merender halaman 404 statis. Path ini
46
+ * tidak pernah menjadi route publik; handler merendernya seperti request tak
47
+ * dikenal (route `_404` atau 404 bawaan).
48
+ */
49
+ export const NOT_FOUND_SENTINEL = "/_moons/404";
50
+
51
+ /** Addendum G: nama file 404 untuk static host (konvensi Cloudflare Pages/Netlify). */
52
+ export const NOT_FOUND_FILE = "404.html";
53
+
34
54
  export async function runPrerender(options: PrerenderOptions): Promise<PrerenderResult> {
35
55
  const log = options.log ?? ((message: string) => console.log(message));
36
56
  const env = options.env ?? process.env;
@@ -99,26 +119,7 @@ export async function runPrerender(options: PrerenderOptions): Promise<Prerender
99
119
  }
100
120
 
101
121
  const html = await response.text();
102
- const findings = scanPayloadForSecrets(html, {
103
- ...(options.canary === undefined ? {} : { canary: options.canary }),
104
- env,
105
- });
106
- if (findings.length > 0) {
107
- const labels = findings
108
- .map((finding) => (finding.kind === "canary" ? "canary" : `env(${finding.label})`))
109
- .join(", ");
110
- throw new MoonsError({
111
- code: "E_PRERENDER_LEAK",
112
- file: route.file,
113
- message: `hasil prerender \`${pathname}\` memuat ${labels}`,
114
- details:
115
- "HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.",
116
- suggestions: [
117
- "Jangan mengembalikan nilai env rahasia dari loader yang di-prerender",
118
- "Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time",
119
- ],
120
- });
121
- }
122
+ assertNoLeak(html, pathname, route.file, options, env);
122
123
 
123
124
  const file = outputFile(options.clientDir, pathname);
124
125
  mkdirSync(dirname(file), { recursive: true });
@@ -132,16 +133,149 @@ export async function runPrerender(options: PrerenderOptions): Promise<Prerender
132
133
  }
133
134
  }
134
135
 
136
+ // Addendum G: `404.html` untuk static host, bila app punya route `_404`.
137
+ const notFound = await renderStaticNotFound(options, env, log);
138
+ let wrote404 = false;
139
+ if (notFound !== null) {
140
+ writeFileSync(join(options.clientDir, NOT_FOUND_FILE), notFound);
141
+ wrote404 = true;
142
+ }
143
+
135
144
  // Manifest v2 (Addendum E.1): entries + revalidate; reader tetap menerima v1.
136
145
  writeFileSync(
137
146
  join(options.clientDir, PRERENDER_MANIFEST_FILE),
138
147
  `${JSON.stringify({ version: 2, entries }, null, 2)}\n`,
139
148
  );
140
149
 
141
- log(`[moons] prerender selesai: ${written} file (${skipped} dilewati)`);
150
+ // Addendum H: deploy kit statis (headers/redirects/sitemap/robots).
151
+ const emitted = emitStaticFiles(options.clientDir, options.staticConfig, entries);
152
+
153
+ const extras = [...(wrote404 ? [NOT_FOUND_FILE] : []), ...emitted];
154
+ log(
155
+ `[moons] prerender selesai: ${written} file${extras.length > 0 ? ` + ${extras.join(" + ")}` : ""} (${skipped} dilewati)`,
156
+ );
142
157
  return { written, skipped };
143
158
  }
144
159
 
160
+ /** Tulis file deploy statis dari config; mengembalikan nama file yang ditulis. */
161
+ function emitStaticFiles(
162
+ clientDir: string,
163
+ staticConfig: PrerenderStaticConfig | undefined,
164
+ entries: Array<{ path: string }>,
165
+ ): string[] {
166
+ if (staticConfig === undefined) {
167
+ return [];
168
+ }
169
+ const emitted: string[] = [];
170
+
171
+ const headers = Object.entries(staticConfig.headers ?? {});
172
+ if (headers.length > 0) {
173
+ const lines = ["/*", ...headers.map(([name, value]) => ` ${name}: ${value}`)];
174
+ writeFileSync(join(clientDir, "_headers"), `${lines.join("\n")}\n`);
175
+ emitted.push("_headers");
176
+ }
177
+
178
+ const redirects = staticConfig.redirects ?? [];
179
+ if (redirects.length > 0) {
180
+ const lines = redirects.map((entry) => `${entry.from} ${entry.to} ${entry.status ?? 301}`);
181
+ writeFileSync(join(clientDir, "_redirects"), `${lines.join("\n")}\n`);
182
+ emitted.push("_redirects");
183
+ }
184
+
185
+ const sitemap = staticConfig.sitemap;
186
+ if (sitemap !== undefined) {
187
+ const site = sitemap.site.replace(/\/$/, "");
188
+ const exclude = sitemap.exclude ?? [];
189
+ const paths = [...new Set(entries.map((entry) => entry.path))]
190
+ .filter((path) => !exclude.some((prefix) => path.startsWith(prefix)))
191
+ .sort();
192
+ const xml = [
193
+ '<?xml version="1.0" encoding="UTF-8"?>',
194
+ '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
195
+ ...paths.map((path) => ` <url><loc>${site}${path === "/" ? "/" : path}</loc></url>`),
196
+ "</urlset>",
197
+ "",
198
+ ].join("\n");
199
+ writeFileSync(join(clientDir, "sitemap.xml"), xml);
200
+ emitted.push("sitemap.xml");
201
+ }
202
+
203
+ const robots = staticConfig.robots;
204
+ if (robots !== undefined) {
205
+ const lines = ["User-agent: *"];
206
+ for (const path of robots.disallow ?? []) {
207
+ lines.push(`Disallow: ${path}`);
208
+ }
209
+ if ((robots.sitemap ?? true) && sitemap !== undefined) {
210
+ lines.push("", `Sitemap: ${sitemap.site.replace(/\/$/, "")}/sitemap.xml`);
211
+ }
212
+ writeFileSync(join(clientDir, "robots.txt"), `${lines.join("\n")}\n`);
213
+ emitted.push("robots.txt");
214
+ }
215
+
216
+ return emitted;
217
+ }
218
+
219
+ /**
220
+ * Addendum G: render halaman 404 ke `dist/client/404.html` (static export).
221
+ * Ditulis hanya bila app memiliki route `_404` dan sentinel menghasilkan 404;
222
+ * hasilnya tetap melewati guard kebocoran (fail-mode).
223
+ */
224
+ async function renderStaticNotFound(
225
+ options: PrerenderOptions,
226
+ env: Record<string, string | undefined>,
227
+ log: (message: string) => void,
228
+ ): Promise<string | null> {
229
+ if (!options.routes.some((route) => route.kind === "404")) {
230
+ return null;
231
+ }
232
+ const response = await options.handler(
233
+ new Request(`http://localhost${NOT_FOUND_SENTINEL}`, {
234
+ method: "GET",
235
+ headers: { "x-moons-prerender": "1" },
236
+ }),
237
+ );
238
+ if (response.status !== 404) {
239
+ log(
240
+ `[moons] prerender: ${NOT_FOUND_FILE} dilewati (sentinel \`${NOT_FOUND_SENTINEL}\` → ${response.status})`,
241
+ );
242
+ return null;
243
+ }
244
+ const html = await response.text();
245
+ assertNoLeak(html, NOT_FOUND_SENTINEL, NOT_FOUND_FILE, options, env);
246
+ return html;
247
+ }
248
+
249
+ /** Guard kebocoran fail-mode (Addendum D.5) — dipakai halaman & 404 statis. */
250
+ function assertNoLeak(
251
+ html: string,
252
+ pathname: string,
253
+ file: string,
254
+ options: PrerenderOptions,
255
+ env: Record<string, string | undefined>,
256
+ ): void {
257
+ const findings = scanPayloadForSecrets(html, {
258
+ ...(options.canary === undefined ? {} : { canary: options.canary }),
259
+ env,
260
+ });
261
+ if (findings.length === 0) {
262
+ return;
263
+ }
264
+ const labels = findings
265
+ .map((finding) => (finding.kind === "canary" ? "canary" : `env(${finding.label})`))
266
+ .join(", ");
267
+ throw new MoonsError({
268
+ code: "E_PRERENDER_LEAK",
269
+ file,
270
+ message: `hasil prerender \`${pathname}\` memuat ${labels}`,
271
+ details: "HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.",
272
+ suggestions: [
273
+ "Jangan mengembalikan nilai env rahasia dari loader yang di-prerender",
274
+ "Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time",
275
+ ],
276
+ });
277
+ }
278
+
145
279
  function routeKeyOf(routesDir: string, file: string): string {
146
280
  const relative = file.startsWith(routesDir) ? file.slice(routesDir.length + 1) : file;
147
281
  return relative.split("\\").join("/").replace(/\.(tsx|ts)$/, "");