@moonsjs/vite 0.1.12 → 0.1.13

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.
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/server/shell.ts", "../src/server/node.ts", "../src/virtual-modules.ts", "../src/server/dev.ts", "../src/devtools.ts", "../src/manifest.ts"],
4
+ "sourcesContent": [
5
+ "import { MoonsError } from \"@moonsjs/core\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport type { ViteDevServer } from \"vite\";\n\nexport type Shell = (\n markup: string,\n payload: string,\n url: string,\n meta?: Record<string, unknown>,\n) => string | Promise<string>;\n\nexport const ROOT_PLACEHOLDER = '<div id=\"root\"></div>';\n\nexport const DEFAULT_TEMPLATE = [\n \"<!doctype html>\",\n '<html lang=\"id\">',\n \"<head>\",\n ' <meta charset=\"utf-8\" />',\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n \" <title>Moons</title>\",\n \"</head>\",\n \"<body>\",\n ` ${ROOT_PLACEHOLDER}`,\n ' <script type=\"module\" src=\"/src/client/main.tsx\"></script>',\n \"</body>\",\n \"</html>\",\n \"\",\n].join(\"\\n\");\n\n/** Inject markup SSR + payload devalue ke shell HTML (PRD §8.2, §17, Addendum B.1). */\nexport function injectShell(\n template: string,\n markup: string,\n payload: string,\n meta?: Record<string, unknown>,\n): string {\n if (!template.includes(ROOT_PLACEHOLDER)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n message: `shell HTML tidak memuat \\`${ROOT_PLACEHOLDER}\\``,\n details: \"index.html aplikasi wajib memuat elemen root tersebut agar SSR bisa meng-inject markup.\",\n suggestions: [\n `Tambahkan ${ROOT_PLACEHOLDER} ke index.html`,\n \"Atau hapus index.html untuk memakai shell bawaan\",\n ],\n });\n }\n const dataScript = `<script id=\"__moons_data\" type=\"application/x-moons\">${payload}</script>`;\n const withRoot = template.replace(ROOT_PLACEHOLDER, `<div id=\"root\">${markup}</div>${dataScript}`);\n return applyMeta(withRoot, meta);\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\");\n}\n\n/**\n * Terapkan meta route ke `<head>` (Addendum B.1): `<title>` + description/og.\n * Tag yang sudah ada (mis. di index.html) ditimpa; yang belum ada disisipkan\n * sebelum `</head>`.\n */\nfunction applyMeta(html: string, meta: Record<string, unknown> | undefined): string {\n if (meta === undefined) {\n return html;\n }\n let out = html;\n if (typeof meta.title === \"string\") {\n const title = `<title>${escapeHtml(meta.title)}</title>`;\n out = /<title>[\\s\\S]*?<\\/title>/.test(out)\n ? out.replace(/<title>[\\s\\S]*?<\\/title>/, title)\n : out.replace(\"</head>\", ` ${title}\\n</head>`);\n }\n\n const tags: Array<{ attr: \"name\" | \"property\"; key: string; value: unknown }> = [\n { attr: \"name\", key: \"description\", value: meta.description },\n { attr: \"property\", key: \"og:title\", value: meta.title },\n { attr: \"property\", key: \"og:description\", value: meta.description },\n ];\n for (const tag of tags) {\n if (typeof tag.value !== \"string\") {\n continue;\n }\n const rendered = `<meta ${tag.attr}=\"${tag.key}\" content=\"${escapeHtml(tag.value)}\" />`;\n const pattern = new RegExp(`<meta[^>]*${tag.attr}=\"${tag.key}\"[^>]*>`);\n out = pattern.test(out)\n ? out.replace(pattern, rendered)\n : out.replace(\"</head>\", ` ${rendered}\\n</head>`);\n }\n return out;\n}\n\n/**\n * Shell untuk dev: baca `index.html` dari disk setiap request (selalu segar)\n * lalu lewatkan ke Vite `transformIndexHtml` (inject `/@vite/client`, dsb).\n */\nexport function createDevShell(server: ViteDevServer, options: { templatePath: string }): Shell {\n return async (markup, payload, url, meta) => {\n const template = existsSync(options.templatePath)\n ? readFileSync(options.templatePath, \"utf8\")\n : DEFAULT_TEMPLATE;\n const html = injectShell(template, markup, payload, meta);\n return await server.transformIndexHtml(url, html);\n };\n}\n\n/** Shell untuk produksi: baca `dist/client/index.html` sekali dari cwd. */\nexport function createFileShell(options: { clientDir?: string } = {}): Shell {\n let cached: string | null = null;\n return async (markup, payload, _url, meta) => {\n if (cached === null) {\n const clientDir = resolve(options.clientDir ?? process.cwd(), \"dist/client\");\n const file = join(clientDir, \"index.html\");\n if (!existsSync(file)) {\n throw new MoonsError({\n code: \"E_INTERNAL\",\n file,\n message: \"`dist/client/index.html` tidak ditemukan\",\n details: \"Build client harus dijalankan sebelum server produksi dinyalakan.\",\n suggestions: [\"Jalankan `bun run build` lebih dulu\"],\n });\n }\n cached = readFileSync(file, \"utf8\");\n }\n return injectShell(cached, markup, payload, meta);\n };\n}\n",
6
+ "import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport { CLIENT_IP_HEADER } from \"@moonsjs/core\";\n\n/** Batas transport default (Addendum J.2); RPC punya batas lebih kecil dari config. */\nexport const MAX_TRANSPORT_BODY_BYTES = 32 * 1024 * 1024;\n\n/** Request tidak valid (Host/URL malformed) → dipetakan ke 400 oleh server. */\nexport class InvalidRequestError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"InvalidRequestError\";\n }\n}\n\n/** Body melebihi batas → dipetakan ke 413; pembacaan dihentikan saat melewati. */\nexport class BodyLimitError extends Error {\n readonly limit: number;\n constructor(limit: number) {\n super(`request body melebihi batas ${limit} byte`);\n this.name = \"BodyLimitError\";\n this.limit = limit;\n }\n}\n\nexport interface ToWebRequestOptions {\n /** Addendum J.1: percayai `x-forwarded-proto`/`x-forwarded-host` (default false). */\n trustProxy?: boolean;\n /** Batas pembacaan body (byte). Default: `MAX_TRANSPORT_BODY_BYTES`. */\n maxBodyBytes?: number;\n}\n\n/**\n * Rekonstruksi URL request (Addendum J.1). Tanpa `trustProxy`, origin/host\n * murni dari header `Host` (perilaku lama, kebal spoofing `x-forwarded-*`).\n * Malformed → `InvalidRequestError` (server memetakan ke 400).\n */\nexport function resolveRequestUrl(\n req: IncomingMessage,\n options: ToWebRequestOptions = {},\n): URL {\n const hostHeader = req.headers.host ?? \"localhost\";\n const trustProxy = options.trustProxy === true;\n const proto = trustProxy ? forwardedProtocol(req.headers[\"x-forwarded-proto\"]) : null;\n const forwardedHostValue = trustProxy ? forwardedHost(req.headers[\"x-forwarded-host\"]) : null;\n const host = forwardedHostValue ?? hostHeader;\n try {\n return new URL(`${proto ?? \"http\"}://${host}${req.url ?? \"/\"}`);\n } catch {\n throw new InvalidRequestError(`header Host tidak valid: ${JSON.stringify(hostHeader)}`);\n }\n}\n\n/** IP klien tepercaya (Addendum J.1): XFF (hanya bila trustProxy) → socket. */\nexport function resolveClientIp(req: IncomingMessage, trustProxy: boolean): string | null {\n if (trustProxy) {\n const forwarded = firstHeaderValue(req.headers[\"x-forwarded-for\"]);\n if (forwarded !== null && isPlausibleIp(forwarded)) {\n return normalizeIp(forwarded);\n }\n }\n const remote = req.socket?.remoteAddress ?? null;\n return remote === null ? null : normalizeIp(remote);\n}\n\n/** `::ffff:127.0.0.1` → `127.0.0.1`; buang zone id (`%eth0`). */\nfunction normalizeIp(value: string): string {\n const withoutZone = stripZoneId(value);\n return withoutZone.startsWith(\"::ffff:\") ? withoutZone.slice(7) : withoutZone;\n}\n\n/** Konversi request Node → Web `Request` (body diteruskan untuk non-GET/HEAD, §7.3 + J.1/J.2). */\nexport async function toWebRequest(\n req: IncomingMessage,\n options: ToWebRequestOptions = {},\n): Promise<Request> {\n const url = resolveRequestUrl(req, options);\n const method = req.method ?? \"GET\";\n\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined || key === \"content-length\" || key === CLIENT_IP_HEADER) {\n // content-length tidak disalin; fetch menghitung ulang dari body.\n // x-moons-client-ip selalu ditimpa nilai tepercaya di bawah.\n continue;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n headers.append(key, item);\n }\n } else {\n headers.set(key, value);\n }\n }\n\n const clientIp = resolveClientIp(req, options.trustProxy === true);\n if (clientIp !== null) {\n headers.set(CLIENT_IP_HEADER, clientIp);\n }\n\n if (method === \"GET\" || method === \"HEAD\") {\n return new Request(url, { method, headers });\n }\n\n const body = await readBody(req, options.maxBodyBytes ?? MAX_TRANSPORT_BODY_BYTES);\n // View zero-copy (bukan salinan) — Buffer selalu di atas ArrayBuffer biasa.\n const view = new Uint8Array(body.buffer as ArrayBuffer, body.byteOffset, body.byteLength);\n return new Request(url, { method, headers, body: view });\n}\n\n/**\n * Baca body dengan batas tegas (Addendum J.2): begitu melewati `maxBytes`,\n * pembacaan dihentikan (pause) dan `BodyLimitError` dilempar — tidak pernah\n * seluruh body besar masuk memori, dan hanya satu salinan buffer dibuat.\n */\nexport function readBody(req: IncomingMessage, maxBytes: number): Promise<Buffer> {\n return new Promise((resolvePromise, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n let settled = false;\n\n const fail = (error: Error): void => {\n if (settled) {\n return;\n }\n settled = true;\n req.pause();\n reject(error);\n };\n\n req.on(\"data\", (chunk: Buffer) => {\n if (settled) {\n return;\n }\n size += chunk.length;\n if (size > maxBytes) {\n fail(new BodyLimitError(maxBytes));\n return;\n }\n chunks.push(chunk);\n });\n req.on(\"end\", () => {\n if (!settled) {\n settled = true;\n resolvePromise(Buffer.concat(chunks));\n }\n });\n req.on(\"error\", (error) => fail(error));\n });\n}\n\n/** Addendum J.7: default aman runtime; `config.headers` tetap menang (cek hasHeader). */\nexport const DEFAULT_SECURITY_HEADERS: Record<string, string> = {\n \"x-content-type-options\": \"nosniff\",\n \"referrer-policy\": \"strict-origin-when-cross-origin\",\n};\n\n/** Tulis Web `Response` ke `ServerResponse` Node (streaming bila ada body). */\nexport async function sendNodeResponse(res: ServerResponse, response: Response): Promise<void> {\n res.statusCode = response.status;\n response.headers.forEach((value, key) => {\n // `set-cookie` ditangani terpisah: forEach menggabungkan nilai ganda\n // menjadi satu string (cookie kedua hilang — D.2).\n if (key === \"set-cookie\") {\n return;\n }\n res.setHeader(key, value);\n });\n const getSetCookie = (response.headers as { getSetCookie?: () => string[] }).getSetCookie;\n if (typeof getSetCookie === \"function\") {\n const cookies = getSetCookie.call(response.headers);\n if (cookies.length > 0) {\n res.setHeader(\"set-cookie\", cookies);\n }\n } else {\n const single = response.headers.get(\"set-cookie\");\n if (single !== null) {\n res.setHeader(\"set-cookie\", single);\n }\n }\n\n for (const [name, value] of Object.entries(DEFAULT_SECURITY_HEADERS)) {\n if (!res.hasHeader(name)) {\n res.setHeader(name, value);\n }\n }\n\n if (response.body === null || res.req?.method === \"HEAD\") {\n res.end();\n return;\n }\n\n // Addendum J.2: stream langsung — tidak ada `arrayBuffer()` penuh di memori.\n await pipeline(\n Readable.fromWeb(response.body as unknown as import(\"node:stream/web\").ReadableStream),\n res,\n );\n}\n\nfunction firstHeaderValue(value: string | string[] | undefined): string | null {\n if (value === undefined) {\n return null;\n }\n const raw = Array.isArray(value) ? value[0] : value;\n if (raw === undefined) {\n return null;\n }\n const first = raw.split(\",\")[0]?.trim() ?? \"\";\n return first.length === 0 ? null : first;\n}\n\nfunction forwardedProtocol(value: string | string[] | undefined): \"http\" | \"https\" | null {\n const first = firstHeaderValue(value)?.toLowerCase() ?? null;\n if (first === \"https\") {\n return \"https\";\n }\n if (first === \"http\") {\n return \"http\";\n }\n return null;\n}\n\nfunction forwardedHost(value: string | string[] | undefined): string | null {\n const first = firstHeaderValue(value);\n if (first === null || first.length === 0 || first.length > 255) {\n return null;\n }\n // hostname[:port] — tolak karakter di luar himpunan aman (spasi, CRLF, /, @, ?).\n if (!/^[A-Za-z0-9.\\-[\\]:]+$/.test(first)) {\n return null;\n }\n return first;\n}\n\nfunction isPlausibleIp(value: string): boolean {\n return value.length <= 64 && /^[0-9a-fA-F:.]+$/.test(value);\n}\n\nfunction stripZoneId(value: string): string {\n const index = value.indexOf(\"%\");\n return index === -1 ? value : value.slice(0, index);\n}\n",
7
+ "/** Nama virtual module PRD §9.4. Semua di-resolve ke id `\\0`-prefix. */\nexport const VIRTUAL_MODULES = {\n routes: \"virtual:moons/routes\",\n api: \"virtual:moons/api\",\n config: \"virtual:moons/config\",\n clientEntry: \"virtual:moons/client-entry\",\n serverEntry: \"virtual:moons/server-entry\",\n} as const;\n\nexport type VirtualModuleName = (typeof VIRTUAL_MODULES)[keyof typeof VIRTUAL_MODULES];\n\nexport function isVirtualModuleId(id: string): id is VirtualModuleName {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n return (Object.values(VIRTUAL_MODULES) as string[]).includes(clean);\n}\n\nexport function toNullPrefixed(id: VirtualModuleName): `\\0${string}` {\n return `\\0${id}`;\n}\n\nexport function fromNullPrefixed(id: string): VirtualModuleName | null {\n const clean = id.startsWith(\"\\0\") ? id.slice(1) : id;\n return isVirtualModuleId(clean) ? (clean as VirtualModuleName) : null;\n}\n",
8
+ "import type { IncomingMessage, ServerResponse } from \"node:http\";\nimport type { ViteDevServer } from \"vite\";\nimport { VIRTUAL_MODULES } from \"../virtual-modules\";\nimport type { PayloadScanOptions } from \"../payload-scan\";\nimport type { PluginRuntime } from \"./plugins\";\nimport type { Shell } from \"./shell\";\nimport { createDevShell } from \"./shell\";\nimport {\n BodyLimitError,\n InvalidRequestError,\n resolveRequestUrl,\n sendNodeResponse,\n toWebRequest,\n} from \"./node\";\nimport { DEFAULT_BODY_LIMIT_BYTES } from \"@moonsjs/core\";\nimport { emptyDevtoolsData, renderDevtoolsHtml, type DevtoolsData } from \"../devtools\";\n\ninterface DevApp {\n handler: (request: Request) => Promise<Response>;\n plugins: PluginRuntime;\n}\n\ntype DevServerEntry = {\n createDevApp: (\n shell: Shell,\n payloadScan?: import(\"../payload-scan\").PayloadScanOptions,\n ) => DevApp;\n};\n\n/**\n * Middleware SSR dev: dipasang sebelum middleware internal Vite, menangani\n * request HTML dan RPC serverFn (`/_moons/fn/*`) — modul/aset tetap Vite.\n * Handler + lifecycle plugin (Addendum B.4) diinisialisasi sekali.\n */\nexport function installDevMiddleware(\n server: ViteDevServer,\n options: {\n templatePath: string;\n payloadScan?: PayloadScanOptions;\n apiPrefix?: string;\n /** Addendum J.1: paritas dev dengan produksi (trustProxy/bodyLimitBytes). */\n trustProxy?: boolean;\n bodyLimitBytes?: number;\n /** Addendum I.4: datasource devtools overlay (dipanggil per request). */\n devtools?: () => DevtoolsData;\n },\n): void {\n let appPromise: Promise<DevApp> | null = null;\n\n const getApp = (): Promise<DevApp> => {\n if (appPromise === null) {\n appPromise = (async () => {\n const entry = (await server.ssrLoadModule(VIRTUAL_MODULES.serverEntry)) as DevServerEntry;\n const app = entry.createDevApp(createDevShell(server, options), options.payloadScan);\n await app.plugins.start();\n await app.plugins.ready();\n return app;\n })();\n }\n return appPromise;\n };\n\n server.httpServer?.once(\"close\", () => {\n void appPromise?.then((app) => app.plugins.shutdown());\n });\n\n server.middlewares.use((req, res, next) => {\n // Addendum I.4 (W4): overlay dev-only — selalu data segar per request.\n if (\n (req.method === \"GET\" || req.method === \"HEAD\") &&\n new URL(req.url ?? \"/\", \"http://localhost\").pathname === \"/__moons/devtools\"\n ) {\n try {\n const data = options.devtools?.() ?? emptyDevtoolsData();\n res.statusCode = 200;\n res.setHeader(\"content-type\", \"text/html; charset=utf-8\");\n res.end(req.method === \"HEAD\" ? undefined : renderDevtoolsHtml(data));\n } catch (error) {\n res.statusCode = 500;\n res.setHeader(\"content-type\", \"text/plain; charset=utf-8\");\n res.end(`[moons] devtools gagal dirender: ${String(error)}`);\n }\n return;\n }\n\n if (!shouldHandle(req, options.apiPrefix)) {\n next();\n return;\n }\n void handleRequest(getApp, req, res, options).catch((error: unknown) => {\n if (error instanceof InvalidRequestError) {\n res.statusCode = 400;\n res.setHeader(\"content-type\", \"text/plain; charset=utf-8\");\n res.end(\"Bad Request\");\n return;\n }\n if (error instanceof BodyLimitError) {\n res.statusCode = 413;\n res.setHeader(\"content-type\", \"text/plain; charset=utf-8\");\n res.end(\"Payload Too Large\");\n res.once(\"finish\", () => req.destroy());\n return;\n }\n next(error as Error);\n });\n });\n}\n\nasync function handleRequest(\n getApp: () => Promise<DevApp>,\n req: IncomingMessage,\n res: ServerResponse,\n options: { trustProxy?: boolean; bodyLimitBytes?: number },\n): Promise<void> {\n const app = await getApp();\n const url = resolveRequestUrl(req, { trustProxy: options.trustProxy === true });\n const isRpc = url.pathname.startsWith(\"/_moons/fn/\");\n const request = await toWebRequest(req, {\n trustProxy: options.trustProxy === true,\n ...(isRpc ? { maxBodyBytes: options.bodyLimitBytes ?? DEFAULT_BODY_LIMIT_BYTES } : {}),\n });\n const response = await app.handler(request);\n await sendNodeResponse(res, response);\n}\n\nfunction shouldHandle(req: IncomingMessage, apiPrefix: string | undefined): boolean {\n const path = new URL(req.url ?? \"/\", \"http://localhost\").pathname;\n\n // RPC serverFn (semua method): dulu hanya GET/HEAD HTML yang dirutekan,\n // sehingga `POST /_moons/fn/<hash>` jatuh ke Vite (\"Cannot POST\", 404) dan\n // serverFn tidak bisa dipakai di dev (temuan eval T2 ronde 2; decisions/0016).\n if (path.startsWith(\"/_moons/fn/\")) {\n return true;\n }\n\n // Addendum D.1: endpoint `src/api` (semua method) dirutekan ke runtime.\n if (apiPrefix !== undefined && (path === apiPrefix || path.startsWith(`${apiPrefix}/`))) {\n return true;\n }\n\n if (req.method !== \"GET\" && req.method !== \"HEAD\") {\n return false;\n }\n if (path.startsWith(\"/@\") || path.startsWith(\"/node_modules/\") || path.startsWith(\"/__\")) {\n return false;\n }\n const lastSegment = path.split(\"/\").pop() ?? \"\";\n if (lastSegment.includes(\".\")) {\n return false;\n }\n const accept = req.headers.accept ?? \"\";\n return accept.includes(\"text/html\") || accept.includes(\"*/*\");\n}\n",
9
+ "/**\n * Addendum I.4 (W4): devtools overlay dev-only — tabel route, registry\n * serverFn (hash §12), endpoint `src/api`, dan status payload-scan.\n * Renderer murni (tanpa I/O) supaya bisa diuji unit; middleware dev yang\n * menyajikannya di `/__moons/devtools`.\n */\n\nexport interface DevtoolsRoute {\n /** Path URL (bentuk PRD §6.1), mis. \"/users/:id\". */\n path: string;\n /** \"page\" | \"layout\" | \"error\" | \"404\" | \"middleware\" | \"api\". */\n kind: string;\n /** Path relatif terhadap root app (posix). */\n file: string;\n}\n\nexport interface DevtoolsFn {\n file: string;\n name: string;\n hash: string;\n}\n\nexport interface DevtoolsData {\n routes: DevtoolsRoute[];\n apiRoutes: DevtoolsRoute[];\n serverFns: DevtoolsFn[];\n /** Canary `leakTest` terpasang → payload-scan aktif (A1). */\n canary: boolean;\n version: string;\n}\n\nexport function emptyDevtoolsData(): DevtoolsData {\n return { routes: [], apiRoutes: [], serverFns: [], canary: false, version: \"\" };\n}\n\nexport function renderDevtoolsHtml(data: DevtoolsData): string {\n const rows = (items: DevtoolsRoute[]): string =>\n items.length === 0\n ? '<tr><td colspan=\"3\" class=\"muted\">(kosong)</td></tr>'\n : items\n .map(\n (item) =>\n `<tr><td><code>${esc(item.path)}</code></td><td><span class=\"kind k-${esc(item.kind)}\">${esc(item.kind)}</span></td><td class=\"muted\">${esc(item.file)}</td></tr>`,\n )\n .join(\"\\n\");\n\n const fnRows =\n data.serverFns.length === 0\n ? '<tr><td colspan=\"3\" class=\"muted\">(tidak ada serverFn)</td></tr>'\n : data.serverFns\n .map(\n (fn) =>\n `<tr><td><code>${esc(fn.hash)}</code></td><td><code>${esc(fn.name)}</code></td><td class=\"muted\">${esc(fn.file)}</td></tr>`,\n )\n .join(\"\\n\");\n\n const canary = data.canary\n ? '<span class=\"ok\">aktif</span> (canary terpasang)'\n : '<span class=\"muted\">nonaktif</span> (tanpa canary)';\n\n return `<!doctype html>\n<html lang=\"id\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>moons devtools</title>\n<style>\n :root { color-scheme: dark; }\n body { margin: 0; padding: 2rem; background: #101418; color: #e6edf3;\n font: 14px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; }\n h1 { font-size: 1.1rem; margin: 0 0 .25rem; }\n h2 { font-size: .95rem; margin: 2rem 0 .5rem; color: #9fb0c0; }\n .muted { color: #8b98a5; }\n .ok { color: #3fb950; font-weight: 600; }\n .meta { margin-bottom: 1.5rem; }\n table { border-collapse: collapse; width: 100%; max-width: 1100px; }\n th, td { text-align: left; padding: .35rem .75rem .35rem 0; border-bottom: 1px solid #1f2630; }\n th { color: #8b98a5; font-weight: 600; font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; }\n code { color: #79c0ff; }\n .kind { border: 1px solid #30363d; border-radius: 4px; padding: 0 .35rem; font-size: .8rem; }\n .k-page { color: #d2a8ff; } .k-layout { color: #7ee787; }\n .k-error { color: #ff7b72; } .k-404 { color: #ff7b72; }\n .k-middleware { color: #e3b341; } .k-api { color: #79c0ff; }\n</style>\n</head>\n<body>\n<h1>moons devtools</h1>\n<div class=\"meta muted\">@moonsjs/vite ${esc(data.version)} · dev-only · payload-scan: ${canary}</div>\n\n<h2>Routes (${data.routes.length})</h2>\n<table><thead><tr><th>path</th><th>kind</th><th>file</th></tr></thead>\n<tbody>\n${rows(data.routes)}\n</tbody></table>\n\n<h2>API (${data.apiRoutes.length})</h2>\n<table><thead><tr><th>path</th><th>kind</th><th>file</th></tr></thead>\n<tbody>\n${rows(data.apiRoutes)}\n</tbody></table>\n\n<h2>serverFn registry (${data.serverFns.length})</h2>\n<table><thead><tr><th>hash</th><th>export</th><th>file</th></tr></thead>\n<tbody>\n${fnRows}\n</tbody></table>\n</body>\n</html>\n`;\n}\n\nfunction esc(value: string): string {\n return value.replace(/[&<>\"']/g, (char) => {\n switch (char) {\n case \"&\":\n return \"&amp;\";\n case \"<\":\n return \"&lt;\";\n case \">\":\n return \"&gt;\";\n case '\"':\n return \"&quot;\";\n default:\n return \"&#39;\";\n }\n });\n}\n",
10
+ "import { findLayouts, routeKeyFromFile, type ApiRouteDefinition, type RouteDefinition } from \"@moonsjs/core\";\nimport { relative, sep } from \"node:path\";\n\nexport interface ClientManifestEntry {\n page: string;\n layouts: string[];\n}\n\n/** Key manifest untuk halaman kustom `_404` dan `_error` (§11.2). */\nexport const NOT_FOUND_ROUTE_KEY = \"__moons/404\";\nexport const ERROR_ROUTE_KEY = \"__moons/error\";\n\n/**\n * Manifest route untuk client (PRD §8.2): key = key route file\n * (routeKeyFromFile), nilai = page + layout chain dari root ke leaf.\n */\nexport function buildClientManifest(\n routes: RouteDefinition[],\n routesDir: string,\n): Record<string, ClientManifestEntry> {\n const manifest: Record<string, ClientManifestEntry> = {};\n for (const route of routes) {\n if (route.kind !== \"page\") {\n continue;\n }\n const key = routeKeyFromFile(routesDir, route.file);\n manifest[key] = {\n page: key,\n layouts: findLayouts(route, routes).map((layout) => routeKeyFromFile(routesDir, layout.file)),\n };\n }\n\n const notFound = routes.find((route) => route.kind === \"404\");\n if (notFound !== undefined) {\n manifest[NOT_FOUND_ROUTE_KEY] = { page: routeKeyFromFile(routesDir, notFound.file), layouts: [] };\n }\n const errorRoute = routes.find((route) => route.kind === \"error\");\n if (errorRoute !== undefined) {\n manifest[ERROR_ROUTE_KEY] = { page: routeKeyFromFile(routesDir, errorRoute.file), layouts: [] };\n }\n // D.3: semua boundary `_error` (termasuk bersarang) ikut manifest — payload\n // memakai key file boundary yang dipilih runtime.\n for (const route of routes) {\n if (route.kind !== \"error\") {\n continue;\n }\n const key = routeKeyFromFile(routesDir, route.file);\n manifest[key] = { page: key, layouts: [] };\n }\n\n return manifest;\n}\n\n/** `virtual:moons/api` (Addendum D.1 + D.3): tabel API + middleware + peta import(). */\nexport function renderApiModule(\n apiRoutes: ApiRouteDefinition[],\n apiMiddlewares: ReadonlyArray<{ file: string; dir: string }>,\n projectRoot: string,\n): string {\n const loadEntries = apiRoutes\n .map(\n (route) =>\n ` ${JSON.stringify(route.path)}: () => import(${JSON.stringify(rootSpecifier(projectRoot, route.file))}),`,\n )\n .join(\"\\n\");\n const middlewareEntries = apiMiddlewares\n .map(\n (middleware) =>\n ` ${JSON.stringify(middleware.file)}: () => import(${JSON.stringify(rootSpecifier(projectRoot, middleware.file))}),`,\n )\n .join(\"\\n\");\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n `export const apiRoutes = ${JSON.stringify(apiRoutes, null, 2)};`,\n `export const apiMiddlewares = ${JSON.stringify(apiMiddlewares, null, 2)};`,\n \"export const loadApi = {\",\n loadEntries,\n \"};\",\n \"export const loadApiMiddleware = {\",\n middlewareEntries,\n \"};\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Isi `virtual:moons/routes`: daftar RouteDefinition, manifest client, dan\n * peta import() dinamis per file route (specifier root-relative).\n */\nexport function renderRoutesModule(\n routes: RouteDefinition[],\n routesDir: string,\n projectRoot: string,\n): string {\n const manifest = buildClientManifest(routes, routesDir);\n\n const loadEntries = routes.map((route) => {\n const key = routeKeyFromFile(routesDir, route.file);\n return ` ${JSON.stringify(key)}: () => import(${JSON.stringify(rootSpecifier(projectRoot, route.file))}),`;\n });\n\n return [\n \"// Generated by @moons. Jangan diubah manual.\",\n `export const routes = ${JSON.stringify(routes, null, 2)};`,\n \"\",\n `export const clientManifest = ${JSON.stringify(manifest, null, 2)};`,\n \"\",\n \"export const loadRoute = {\",\n ...loadEntries,\n \"};\",\n \"\",\n ].join(\"\\n\");\n}\n\n/** Path file absolut project → specifier root-relative yang bisa di-resolve Vite. */\nexport function rootSpecifier(projectRoot: string, file: string): string {\n let rel = relative(projectRoot, file);\n rel = sep === \"/\" ? rel : rel.split(sep).join(\"/\");\n return rel.startsWith(\"/\") ? rel : `/${rel}`;\n}\n"
11
+ ],
12
+ "mappings": "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",
13
+ "debugId": "A701F30B6F40F2FB64756E2164756E21",
14
+ "names": []
15
+ }
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  VIRTUAL_MODULES,
6
6
  fromNullPrefixed,
7
7
  installDevMiddleware2
8
- } from "./index-h66m8653.js";
8
+ } from "./index-vafk4b9b.js";
9
9
  import {
10
10
  isServerFilePath2,
11
11
  isNonContractServerFile2,
@@ -18,7 +18,7 @@ import {
18
18
  checkClientModuleImports2,
19
19
  checkRouteModuleExports2,
20
20
  scanServerFiles2
21
- } from "./index-tysyk2qf.js";
21
+ } from "./index-qr2w9b24.js";
22
22
 
23
23
  // src/plugin.ts
24
24
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -161,6 +161,8 @@ function moons(options = {}) {
161
161
  let configFilePath = "";
162
162
  let routesDir = "";
163
163
  let serverOnlyPackages = [];
164
+ let trustProxy = false;
165
+ let bodyLimitBytes;
164
166
  let apiDir = "";
165
167
  let apiRoutes = [];
166
168
  let apiMiddlewares = [];
@@ -311,6 +313,8 @@ function moons(options = {}) {
311
313
  const config = validateConfig(raw, { file: configFilePath, projectRoot: root });
312
314
  routesDir = resolvePath(root, config.routesDir);
313
315
  serverOnlyPackages = config.security?.serverOnlyPackages ?? [];
316
+ trustProxy = config.security?.trustProxy === true;
317
+ bodyLimitBytes = config.security?.bodyLimitBytes;
314
318
  apiDir = resolvePath(root, config.apiDir ?? "src/api");
315
319
  if (existsSync(apiDir)) {
316
320
  apiRoutes = scanApiRoutes(apiDir);
@@ -411,6 +415,8 @@ export { clientManifest, loadRoute } from "virtual:moons/routes";
411
415
  },
412
416
  analyze: (absoluteFile) => analysisCache.get(absoluteFile) ?? analyzeFile(absoluteFile),
413
417
  apiDir,
418
+ configFile: configFilePath,
419
+ serverDir: resolvePath(root, "src/server"),
414
420
  serverOnlyPackages,
415
421
  packageCache
416
422
  });
@@ -479,7 +485,9 @@ export { clientManifest, loadRoute } from "virtual:moons/routes";
479
485
  ...options.leakTest?.canary === undefined ? {} : { canary: options.leakTest.canary },
480
486
  env: process.env
481
487
  },
482
- ...apiRoutes.length === 0 ? {} : { apiPrefix: `/${apiDir.split(/[\\/]/).filter((part) => part.length > 0).pop() ?? "api"}` }
488
+ ...apiRoutes.length === 0 ? {} : { apiPrefix: `/${apiDir.split(/[\\/]/).filter((part) => part.length > 0).pop() ?? "api"}` },
489
+ trustProxy,
490
+ ...bodyLimitBytes === undefined ? {} : { bodyLimitBytes }
483
491
  });
484
492
  server.config.logger.info("[moons] devtools: /__moons/devtools");
485
493
  },
@@ -580,7 +588,7 @@ function renderServerEntryBuild(routesDir, eagerImports, canary) {
580
588
  " onContext: (ctx) => plugins.applyExtensions(ctx),",
581
589
  "});",
582
590
  "",
583
- `startNodeServer(handler, { plugins, headers: config.headers, storage: config.isr?.storage${canary === undefined ? "" : `, canary: ${JSON.stringify(canary)}`} });`,
591
+ `startNodeServer(handler, { plugins, headers: config.headers, storage: config.isr?.storage, trustProxy: config.security?.trustProxy, bodyLimitBytes: config.security?.bodyLimitBytes${canary === undefined ? "" : `, canary: ${JSON.stringify(canary)}`} });`,
584
592
  ""
585
593
  ].join(`
586
594
  `);
@@ -639,4 +647,4 @@ export {
639
647
  moons as default
640
648
  };
641
649
 
642
- //# debugId=AC2AAB1DDF6A3D5464756E2164756E21
650
+ //# debugId=6936F5FC601D86DA64756E2164756E21
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 { relative as relativePath, resolve as resolvePath } from \"node:path\";\nimport {\n MOONS_VERSION,\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 // Addendum I.4 (W4): overlay devtools — data segar per request.\n devtools: () => {\n const toRelative = (file: string): string =>\n file.startsWith(root) ? relativePath(root, file).split(\"\\\\\").join(\"/\") : file;\n return {\n routes: [...routes]\n .sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind))\n .map((route) => ({ path: route.path, kind: route.kind, file: toRelative(route.file) })),\n apiRoutes: [...apiRoutes]\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((route) => ({ path: route.path, kind: \"api\", file: toRelative(route.file) })),\n serverFns: [...analysisCache.values()]\n .flatMap((analysis) =>\n analysis.serverFns.map((fn) => ({\n file: toRelative(analysis.file),\n name: fn.name,\n hash: fn.hash,\n })),\n )\n .sort((a, b) => a.file.localeCompare(b.file) || a.name.localeCompare(b.name)),\n canary: options.leakTest?.canary !== undefined,\n version: MOONS_VERSION,\n };\n },\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 server.config.logger.info(\"[moons] devtools: /__moons/devtools\");\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, headers: config.headers, storage: config.isr?.storage${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",
5
+ "import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createHash } from \"node:crypto\";\nimport { relative as relativePath, resolve as resolvePath } from \"node:path\";\nimport {\n MOONS_VERSION,\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 // Addendum J.1/J.2: paritas dev & produksi (paritas E7).\n let trustProxy = false;\n let bodyLimitBytes: number | undefined;\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 trustProxy = config.security?.trustProxy === true;\n bodyLimitBytes = config.security?.bodyLimitBytes;\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 configFile: configFilePath,\n serverDir: resolvePath(root, \"src/server\"),\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 // Addendum I.4 (W4): overlay devtools — data segar per request.\n devtools: () => {\n const toRelative = (file: string): string =>\n file.startsWith(root) ? relativePath(root, file).split(\"\\\\\").join(\"/\") : file;\n return {\n routes: [...routes]\n .sort((a, b) => a.path.localeCompare(b.path) || a.kind.localeCompare(b.kind))\n .map((route) => ({ path: route.path, kind: route.kind, file: toRelative(route.file) })),\n apiRoutes: [...apiRoutes]\n .sort((a, b) => a.path.localeCompare(b.path))\n .map((route) => ({ path: route.path, kind: \"api\", file: toRelative(route.file) })),\n serverFns: [...analysisCache.values()]\n .flatMap((analysis) =>\n analysis.serverFns.map((fn) => ({\n file: toRelative(analysis.file),\n name: fn.name,\n hash: fn.hash,\n })),\n )\n .sort((a, b) => a.file.localeCompare(b.file) || a.name.localeCompare(b.name)),\n canary: options.leakTest?.canary !== undefined,\n version: MOONS_VERSION,\n };\n },\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 trustProxy,\n ...(bodyLimitBytes === undefined ? {} : { bodyLimitBytes }),\n });\n server.config.logger.info(\"[moons] devtools: /__moons/devtools\");\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, headers: config.headers, storage: config.isr?.storage, trustProxy: config.security?.trustProxy, bodyLimitBytes: config.security?.bodyLimitBytes${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": "AC2AAB1DDF6A3D5464756E2164756E21",
9
+ "mappings": "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",
10
+ "debugId": "6936F5FC601D86DA64756E2164756E21",
11
11
  "names": []
12
12
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsB,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAsB3E,MAAM,WAAW,sBAAsB;IACrC,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,CA2c1E"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsB,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAsB3E,MAAM,WAAW,sBAAsB;IACrC,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,QAAQ,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAod1E"}
@@ -10,6 +10,9 @@ export declare function installDevMiddleware(server: ViteDevServer, options: {
10
10
  templatePath: string;
11
11
  payloadScan?: PayloadScanOptions;
12
12
  apiPrefix?: string;
13
+ /** Addendum J.1: paritas dev dengan produksi (trustProxy/bodyLimitBytes). */
14
+ trustProxy?: boolean;
15
+ bodyLimitBytes?: number;
13
16
  /** Addendum I.4: datasource devtools overlay (dipanggil per request). */
14
17
  devtools?: () => DevtoolsData;
15
18
  }): void;
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/server/dev.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAK1D,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAcvF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE;IACP,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,YAAY,CAAC;CAC/B,GACA,IAAI,CA+CN"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/server/dev.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAY1D,OAAO,EAAyC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAcvF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE;IACP,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,YAAY,CAAC;CAC/B,GACA,IAAI,CA4DN"}
@@ -5,10 +5,14 @@ import {
5
5
  injectShell2,
6
6
  createDevShell2,
7
7
  createFileShell2,
8
+ InvalidRequestError,
9
+ BodyLimitError,
10
+ resolveRequestUrl,
8
11
  toWebRequest2,
12
+ DEFAULT_SECURITY_HEADERS,
9
13
  sendNodeResponse2,
10
14
  installDevMiddleware2
11
- } from "../index-h66m8653.js";
15
+ } from "../index-vafk4b9b.js";
12
16
 
13
17
  // src/server/handler.ts
14
18
  import {
@@ -470,6 +474,7 @@ function warnPayloadFindings(payload, scan, warned) {
470
474
  import { existsSync, readFileSync as readFileSync2, statSync as statSync2 } from "node:fs";
471
475
  import { createServer } from "node:http";
472
476
  import { extname as extname2, join, resolve, sep } from "node:path";
477
+ import { DEFAULT_BODY_LIMIT_BYTES, MoonsError as MoonsError2 } from "@moonsjs/core";
473
478
 
474
479
  // src/server/isr.ts
475
480
  import { renameSync, writeFileSync } from "node:fs";
@@ -643,8 +648,18 @@ function startNodeServer(handler, options = {}) {
643
648
  const port = options.port ?? Number(process.env["PORT"] ?? 3000);
644
649
  const server = createServer((req, res) => {
645
650
  (async () => {
651
+ let url;
652
+ try {
653
+ url = resolveRequestUrl(req, { trustProxy: options.trustProxy === true });
654
+ } catch (error) {
655
+ if (error instanceof InvalidRequestError) {
656
+ console.warn(`[moons] ${error.message} — 400`);
657
+ respondBadRequest(res);
658
+ return;
659
+ }
660
+ throw error;
661
+ }
646
662
  try {
647
- const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
648
663
  if (req.method === "GET" || req.method === "HEAD") {
649
664
  if (options.storage !== undefined) {
650
665
  const entry = await options.storage.read(url.pathname);
@@ -659,11 +674,7 @@ function startNodeServer(handler, options = {}) {
659
674
  });
660
675
  res.statusCode = 200;
661
676
  res.setHeader("content-type", contentTypeForPathname(url.pathname));
662
- for (const [name, value] of Object.entries(options.headers ?? {})) {
663
- if (!res.hasHeader(name)) {
664
- res.setHeader(name, value);
665
- }
666
- }
677
+ applyStaticHeaders(res, url.pathname, options.headers);
667
678
  res.end(req.method === "HEAD" ? undefined : Buffer.from(entry.body));
668
679
  return;
669
680
  }
@@ -681,19 +692,39 @@ function startNodeServer(handler, options = {}) {
681
692
  const body = readFileSync2(staticFile);
682
693
  res.statusCode = 200;
683
694
  res.setHeader("content-type", MIME_TYPES[extname2(staticFile).toLowerCase()] ?? "application/octet-stream");
684
- for (const [name, value] of Object.entries(options.headers ?? {})) {
685
- if (!res.hasHeader(name)) {
686
- res.setHeader(name, value);
687
- }
688
- }
695
+ applyStaticHeaders(res, url.pathname, options.headers);
689
696
  res.end(req.method === "HEAD" ? undefined : body);
690
697
  return;
691
698
  }
692
699
  }
693
700
  }
694
- const response = await handler(await toWebRequest2(req));
701
+ const isRpc = url.pathname.startsWith("/_moons/fn/");
702
+ const rpcLimit = options.bodyLimitBytes ?? DEFAULT_BODY_LIMIT_BYTES;
703
+ if (isRpc) {
704
+ const contentLength = Number(req.headers["content-length"] ?? "0");
705
+ if (Number.isFinite(contentLength) && contentLength > rpcLimit) {
706
+ res.statusCode = 413;
707
+ res.setHeader("content-type", "text/plain; charset=utf-8");
708
+ res.end(rpcBodyTooLargeText(rpcLimit, contentLength));
709
+ res.once("finish", () => req.destroy());
710
+ return;
711
+ }
712
+ }
713
+ const request = await toWebRequest2(req, {
714
+ trustProxy: options.trustProxy === true,
715
+ ...isRpc ? { maxBodyBytes: rpcLimit } : {}
716
+ });
717
+ const response = await handler(request);
695
718
  await sendNodeResponse2(res, response);
696
719
  } catch (error) {
720
+ if (error instanceof BodyLimitError) {
721
+ const isRpc = url.pathname.startsWith("/_moons/fn/");
722
+ res.statusCode = 413;
723
+ res.setHeader("content-type", "text/plain; charset=utf-8");
724
+ res.end(isRpc ? rpcBodyTooLargeText(error.limit, null) : "Payload Too Large");
725
+ res.once("finish", () => req.destroy());
726
+ return;
727
+ }
697
728
  console.error("[moons] server error:", error);
698
729
  res.statusCode = 500;
699
730
  res.setHeader("content-type", "text/plain; charset=utf-8");
@@ -724,6 +755,38 @@ function startNodeServer(handler, options = {}) {
724
755
  }
725
756
  return server;
726
757
  }
758
+ function applyStaticHeaders(res, pathname, configured) {
759
+ for (const [name, value] of Object.entries(configured ?? {})) {
760
+ if (!res.hasHeader(name)) {
761
+ res.setHeader(name, value);
762
+ }
763
+ }
764
+ for (const [name, value] of Object.entries(DEFAULT_SECURITY_HEADERS)) {
765
+ if (!res.hasHeader(name)) {
766
+ res.setHeader(name, value);
767
+ }
768
+ }
769
+ if (pathname.startsWith("/assets/") && !res.hasHeader("cache-control")) {
770
+ res.setHeader("cache-control", "public, max-age=31536000, immutable");
771
+ }
772
+ }
773
+ function respondBadRequest(res) {
774
+ res.statusCode = 400;
775
+ res.setHeader("content-type", "text/plain; charset=utf-8");
776
+ res.end("Bad Request");
777
+ }
778
+ function rpcBodyTooLargeText(limit, size) {
779
+ const megabytes = (bytes) => (bytes / 1e6).toFixed(1);
780
+ return new MoonsError2({
781
+ code: "E_RPC_BODY_TOO_LARGE",
782
+ message: size === null ? `body melebihi limit ${megabytes(limit)} MB` : `body ${megabytes(size)} MB melebihi limit ${megabytes(limit)} MB`,
783
+ details: "Body melebihi `security.bodyLimitBytes`; pembacaan dihentikan di transport sebelum penuh.",
784
+ suggestions: [
785
+ "Kurangi ukuran payload, atau",
786
+ "Naikkan security.bodyLimitBytes jika memang perlu"
787
+ ]
788
+ }).format();
789
+ }
727
790
  function resolveStaticFile(clientDir, pathname) {
728
791
  const target = staticFileTarget(clientDir, pathname);
729
792
  return target !== null && isFile(target) ? target : null;
@@ -886,7 +949,7 @@ function createPluginRuntime(options) {
886
949
  };
887
950
  }
888
951
  // src/server/prerender.ts
889
- import { MoonsError as MoonsError2 } from "@moonsjs/core";
952
+ import { MoonsError as MoonsError3 } from "@moonsjs/core";
890
953
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
891
954
  import { dirname as dirname2, join as join2, resolve as resolve2, sep as sep2 } from "node:path";
892
955
  var PRERENDER_MANIFEST_FILE = "_moons_prerender.json";
@@ -910,7 +973,7 @@ async function runPrerender(options) {
910
973
  const revalidate = module.revalidate;
911
974
  if (revalidate !== undefined) {
912
975
  if (typeof revalidate !== "number" || !Number.isFinite(revalidate) || revalidate < 0 || prerender !== true) {
913
- throw new MoonsError2({
976
+ throw new MoonsError3({
914
977
  code: "E_ISR_INVALID",
915
978
  file: route.file,
916
979
  message: "`revalidate` tidak valid atau dipakai tanpa `prerender = true`",
@@ -1045,7 +1108,7 @@ function assertNoLeak(html, pathname, file, options, env) {
1045
1108
  return;
1046
1109
  }
1047
1110
  const labels = findings.map((finding) => finding.kind === "canary" ? "canary" : `env(${finding.label})`).join(", ");
1048
- throw new MoonsError2({
1111
+ throw new MoonsError3({
1049
1112
  code: "E_PRERENDER_LEAK",
1050
1113
  file,
1051
1114
  message: `hasil prerender \`${pathname}\` memuat ${labels}`,
@@ -1067,7 +1130,7 @@ async function resolvePathnames(route, module) {
1067
1130
  }
1068
1131
  const paths = module.paths;
1069
1132
  if (typeof paths !== "function") {
1070
- throw new MoonsError2({
1133
+ throw new MoonsError3({
1071
1134
  code: "E_PRERENDER_NO_PATHS",
1072
1135
  file: route.file,
1073
1136
  message: "route dynamic ber-`prerender = true` tanpa `export const paths`",
@@ -1140,7 +1203,7 @@ function outputFile(clientDir, pathname) {
1140
1203
  const file = resolve2(join2(clientDir, ...parts, "index.html"));
1141
1204
  const base = resolve2(clientDir);
1142
1205
  if (file !== base && !file.startsWith(base + sep2)) {
1143
- throw new MoonsError2({
1206
+ throw new MoonsError3({
1144
1207
  code: "E_PRERENDER_INVALID",
1145
1208
  message: `path prerender keluar dari direktori client (\`${pathname}\`)`,
1146
1209
  details: "Nama file harus berada di dalam `dist/client`.",
@@ -1150,7 +1213,7 @@ function outputFile(clientDir, pathname) {
1150
1213
  return file;
1151
1214
  }
1152
1215
  function prerenderError(route, message) {
1153
- return new MoonsError2({
1216
+ return new MoonsError3({
1154
1217
  code: "E_PRERENDER_INVALID",
1155
1218
  file: route.file,
1156
1219
  message,
@@ -1181,4 +1244,4 @@ export {
1181
1244
  toWebRequest2 as toWebRequest
1182
1245
  };
1183
1246
 
1184
- //# debugId=9A8636F992D1AC9F64756E2164756E21
1247
+ //# debugId=B5631AA76D21CC0A64756E2164756E21