@moonsjs/vite 0.1.6 → 0.1.8
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-1fnt137k.js → index-qz9sc74p.js} +2 -2
- package/dist/{index-1fnt137k.js.map → index-qz9sc74p.js.map} +2 -2
- package/dist/{index-zs92aaz4.js → index-tysyk2qf.js} +12 -12
- package/dist/{index-zs92aaz4.js.map → index-tysyk2qf.js.map} +4 -4
- package/dist/index.js +13 -13
- package/dist/index.js.map +4 -4
- package/dist/server/index.js +58 -30
- package/dist/server/index.js.map +4 -4
- package/dist/server/prerender.d.ts +8 -0
- package/dist/server/prerender.d.ts.map +1 -1
- package/dist/transform.js +1 -1
- package/package.json +10 -3
- package/src/api.ts +4 -4
- package/src/plugin.ts +6 -6
- package/src/server/handler.ts +7 -7
- package/src/server/prerender.ts +85 -24
- package/src/server/shell.ts +1 -1
- package/src/server-only.ts +1 -1
- package/src/transform.ts +10 -10
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 (PRD §12.2).\",\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 (PRD §14.3).\",\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 §2/§9.2.8 gagal: kode server bocor ke output client. Build dihentikan.\",\n suggestions: [\n \"Periksa transform `*.server.ts` (§12)\",\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 §9.2: setiap `*.server.ts` di bundle client wajib berupa stub RPC hasil transform.\",\n suggestions: [\n \"Pastikan transform zero-trust (§12) 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",
|
|
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
|
|
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",
|
|
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": "
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "858C3A2CF24FAEB764756E2164756E21",
|
|
11
11
|
"names": []
|
|
12
12
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
toWebRequest2,
|
|
9
9
|
sendNodeResponse2,
|
|
10
10
|
installDevMiddleware2
|
|
11
|
-
} from "../index-
|
|
11
|
+
} from "../index-qz9sc74p.js";
|
|
12
12
|
|
|
13
13
|
// src/server/handler.ts
|
|
14
14
|
import {
|
|
@@ -103,7 +103,7 @@ function createRequestHandler(options) {
|
|
|
103
103
|
code: "E_API_HANDLER_INVALID",
|
|
104
104
|
file: route.file,
|
|
105
105
|
message: "modul API tidak mengekspor objek handler",
|
|
106
|
-
details: `Modul \`${route.path}\` harus mengekspor handler method
|
|
106
|
+
details: `Modul \`${route.path}\` harus mengekspor handler method.`,
|
|
107
107
|
suggestions: ["Export `GET`/`POST`/… sebagai fungsi `(args) => Response`"]
|
|
108
108
|
}), route);
|
|
109
109
|
}
|
|
@@ -132,7 +132,7 @@ function createRequestHandler(options) {
|
|
|
132
132
|
code: "E_API_HANDLER_INVALID",
|
|
133
133
|
file: route.file,
|
|
134
134
|
message: `handler \`${requestMethod}\` tidak mengembalikan \`Response\``,
|
|
135
|
-
details: "Handler API wajib mengembalikan `new Response(...)
|
|
135
|
+
details: "Handler API wajib mengembalikan `new Response(...)`.",
|
|
136
136
|
suggestions: ["Kembalikan `new Response(body, { status, headers })`"]
|
|
137
137
|
}), route);
|
|
138
138
|
}
|
|
@@ -204,7 +204,7 @@ function createRequestHandler(options) {
|
|
|
204
204
|
code: "E_MIDDLEWARE_INVALID",
|
|
205
205
|
file: definition.file,
|
|
206
206
|
message: "`_middleware.ts` tidak meng-export default fungsi",
|
|
207
|
-
details: "Middleware direktori mengikuti bentuk `(args) => Promise<Response
|
|
207
|
+
details: "Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.",
|
|
208
208
|
suggestions: ["Export default `async ({ req, ctx, next }) => await next()`"]
|
|
209
209
|
});
|
|
210
210
|
}
|
|
@@ -231,7 +231,7 @@ function createRequestHandler(options) {
|
|
|
231
231
|
code: "E_MIDDLEWARE_INVALID",
|
|
232
232
|
file: definition.file,
|
|
233
233
|
message: "`_middleware.ts` tidak meng-export default fungsi",
|
|
234
|
-
details: "Middleware direktori mengikuti bentuk `(args) => Promise<Response
|
|
234
|
+
details: "Middleware direktori mengikuti bentuk `(args) => Promise<Response>`.",
|
|
235
235
|
suggestions: ["Export default `async ({ req, ctx, next }) => await next()`"]
|
|
236
236
|
});
|
|
237
237
|
}
|
|
@@ -350,7 +350,7 @@ async function runRouteMeta(pageModule, pageData, file) {
|
|
|
350
350
|
code: "E_INTERNAL",
|
|
351
351
|
file,
|
|
352
352
|
message: "export `meta` harus berupa fungsi `({ data }) => RouteMeta`",
|
|
353
|
-
details: "Bentuk `meta` mengikuti
|
|
353
|
+
details: "Bentuk `meta` mengikuti ",
|
|
354
354
|
suggestions: [
|
|
355
355
|
'Ubah menjadi `export const meta = ({ data }) => ({ title: "..." })`',
|
|
356
356
|
"Atau hapus export `meta`"
|
|
@@ -363,7 +363,7 @@ async function runRouteMeta(pageModule, pageData, file) {
|
|
|
363
363
|
code: "E_INTERNAL",
|
|
364
364
|
file,
|
|
365
365
|
message: "`meta()` harus mengembalikan objek RouteMeta",
|
|
366
|
-
details: "Nilai yang dikembalikan dipakai untuk <title>/description/og
|
|
366
|
+
details: "Nilai yang dikembalikan dipakai untuk <title>/description/og.",
|
|
367
367
|
suggestions: ['Kembalikan objek, mis. `({ title: "Halaman" })`']
|
|
368
368
|
});
|
|
369
369
|
}
|
|
@@ -423,7 +423,7 @@ function warnPayloadFindings(payload, scan, warned) {
|
|
|
423
423
|
continue;
|
|
424
424
|
}
|
|
425
425
|
warned.add(label);
|
|
426
|
-
console.warn(`[moons] peringatan dev: payload SSR memuat ${label} — jangan mengembalikan rahasia dari loader
|
|
426
|
+
console.warn(`[moons] peringatan dev: payload SSR memuat ${label} — jangan mengembalikan rahasia dari loader.`);
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
429
|
// src/server/node-server.ts
|
|
@@ -766,6 +766,8 @@ import { MoonsError as MoonsError2 } from "@moonsjs/core";
|
|
|
766
766
|
import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
767
767
|
import { dirname, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
|
|
768
768
|
var PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
|
|
769
|
+
var NOT_FOUND_SENTINEL = "/_moons/404";
|
|
770
|
+
var NOT_FOUND_FILE = "404.html";
|
|
769
771
|
async function runPrerender(options) {
|
|
770
772
|
const log = options.log ?? ((message) => console.log(message));
|
|
771
773
|
const env = options.env ?? process.env;
|
|
@@ -788,7 +790,7 @@ async function runPrerender(options) {
|
|
|
788
790
|
code: "E_ISR_INVALID",
|
|
789
791
|
file: route.file,
|
|
790
792
|
message: "`revalidate` tidak valid atau dipakai tanpa `prerender = true`",
|
|
791
|
-
details: "ISR berbasis file: `revalidate` (detik, number >= 0) + `prerender
|
|
793
|
+
details: "ISR berbasis file: `revalidate` (detik, number >= 0) + `prerender`.",
|
|
792
794
|
suggestions: [
|
|
793
795
|
"Gunakan angka detik, mis. `export const revalidate = 60`",
|
|
794
796
|
"Tambahkan `export const prerender = true` pada page yang sama"
|
|
@@ -820,23 +822,7 @@ async function runPrerender(options) {
|
|
|
820
822
|
throw prerenderError(route, `status ${response.status} saat merender ${pathname}`);
|
|
821
823
|
}
|
|
822
824
|
const html = await response.text();
|
|
823
|
-
|
|
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 (PRD Addendum D.5).",
|
|
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
|
-
}
|
|
825
|
+
assertNoLeak(html, pathname, route.file, options, env);
|
|
840
826
|
const file = outputFile(options.clientDir, pathname);
|
|
841
827
|
mkdirSync(dirname(file), { recursive: true });
|
|
842
828
|
writeFileSync2(file, html);
|
|
@@ -844,11 +830,53 @@ async function runPrerender(options) {
|
|
|
844
830
|
written += 1;
|
|
845
831
|
}
|
|
846
832
|
}
|
|
833
|
+
const notFound = await renderStaticNotFound(options, env, log);
|
|
834
|
+
let wrote404 = false;
|
|
835
|
+
if (notFound !== null) {
|
|
836
|
+
writeFileSync2(join2(options.clientDir, NOT_FOUND_FILE), notFound);
|
|
837
|
+
wrote404 = true;
|
|
838
|
+
}
|
|
847
839
|
writeFileSync2(join2(options.clientDir, PRERENDER_MANIFEST_FILE), `${JSON.stringify({ version: 2, entries }, null, 2)}
|
|
848
840
|
`);
|
|
849
|
-
log(`[moons] prerender selesai: ${written} file (${skipped} dilewati)`);
|
|
841
|
+
log(`[moons] prerender selesai: ${written} file${wrote404 ? ` + ${NOT_FOUND_FILE}` : ""} (${skipped} dilewati)`);
|
|
850
842
|
return { written, skipped };
|
|
851
843
|
}
|
|
844
|
+
async function renderStaticNotFound(options, env, log) {
|
|
845
|
+
if (!options.routes.some((route) => route.kind === "404")) {
|
|
846
|
+
return null;
|
|
847
|
+
}
|
|
848
|
+
const response = await options.handler(new Request(`http://localhost${NOT_FOUND_SENTINEL}`, {
|
|
849
|
+
method: "GET",
|
|
850
|
+
headers: { "x-moons-prerender": "1" }
|
|
851
|
+
}));
|
|
852
|
+
if (response.status !== 404) {
|
|
853
|
+
log(`[moons] prerender: ${NOT_FOUND_FILE} dilewati (sentinel \`${NOT_FOUND_SENTINEL}\` → ${response.status})`);
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
const html = await response.text();
|
|
857
|
+
assertNoLeak(html, NOT_FOUND_SENTINEL, NOT_FOUND_FILE, options, env);
|
|
858
|
+
return html;
|
|
859
|
+
}
|
|
860
|
+
function assertNoLeak(html, pathname, file, options, env) {
|
|
861
|
+
const findings = scanPayloadForSecrets(html, {
|
|
862
|
+
...options.canary === undefined ? {} : { canary: options.canary },
|
|
863
|
+
env
|
|
864
|
+
});
|
|
865
|
+
if (findings.length === 0) {
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
const labels = findings.map((finding) => finding.kind === "canary" ? "canary" : `env(${finding.label})`).join(", ");
|
|
869
|
+
throw new MoonsError2({
|
|
870
|
+
code: "E_PRERENDER_LEAK",
|
|
871
|
+
file,
|
|
872
|
+
message: `hasil prerender \`${pathname}\` memuat ${labels}`,
|
|
873
|
+
details: "HTML statis permanen — rahasia yang ter-prerender tidak bisa ditarik kembali.",
|
|
874
|
+
suggestions: [
|
|
875
|
+
"Jangan mengembalikan nilai env rahasia dari loader yang di-prerender",
|
|
876
|
+
"Matikan `prerender` untuk route ini atau pindahkan datanya ke serverFn request-time"
|
|
877
|
+
]
|
|
878
|
+
});
|
|
879
|
+
}
|
|
852
880
|
function routeKeyOf(routesDir, file) {
|
|
853
881
|
const relative = file.startsWith(routesDir) ? file.slice(routesDir.length + 1) : file;
|
|
854
882
|
return relative.split("\\").join("/").replace(/\.(tsx|ts)$/, "");
|
|
@@ -864,7 +892,7 @@ async function resolvePathnames(route, module) {
|
|
|
864
892
|
code: "E_PRERENDER_NO_PATHS",
|
|
865
893
|
file: route.file,
|
|
866
894
|
message: "route dynamic ber-`prerender = true` tanpa `export const paths`",
|
|
867
|
-
details: "Prerender butuh daftar param untuk merender tiap path
|
|
895
|
+
details: "Prerender butuh daftar param untuk merender tiap path.",
|
|
868
896
|
suggestions: [
|
|
869
897
|
'Tambahkan `export const paths = () => [{ id: "…" }]`',
|
|
870
898
|
"Atau hapus `prerender` agar dirender SSR saat request"
|
|
@@ -947,7 +975,7 @@ function prerenderError(route, message) {
|
|
|
947
975
|
code: "E_PRERENDER_INVALID",
|
|
948
976
|
file: route.file,
|
|
949
977
|
message,
|
|
950
|
-
details: "Kontrak prerender mengikuti
|
|
978
|
+
details: "Kontrak prerender mengikuti.",
|
|
951
979
|
suggestions: [
|
|
952
980
|
"Perbaiki bentuk `paths`/param agar cocok dengan pola route",
|
|
953
981
|
"Jangan memakai `redirect()` pada route yang di-prerender"
|
|
@@ -972,4 +1000,4 @@ export {
|
|
|
972
1000
|
toWebRequest2 as toWebRequest
|
|
973
1001
|
};
|
|
974
1002
|
|
|
975
|
-
//# debugId=
|
|
1003
|
+
//# debugId=B1F16477174B55D664756E2164756E21
|