@moonsjs/vite 0.1.17 → 0.1.18
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-v5sbd3az.js → index-1ksjfvnz.js} +18 -18
- package/dist/index-1ksjfvnz.js.map +15 -0
- package/dist/{index-snbxks72.js → index-tbph0859.js} +80 -80
- package/dist/{index-snbxks72.js.map → index-tbph0859.js.map} +4 -4
- package/dist/index.js +33 -33
- package/dist/index.js.map +4 -4
- package/dist/server/index.js +86 -86
- package/dist/server/index.js.map +9 -9
- package/dist/transform.js +1 -1
- package/package.json +1 -1
- package/src/api.ts +14 -14
- package/src/devtools.ts +5 -5
- package/src/manifest.ts +2 -2
- package/src/plugin.ts +21 -21
- package/src/server/dev.ts +1 -1
- package/src/server/handler.ts +39 -39
- package/src/server/isr.ts +5 -5
- package/src/server/node-server.ts +6 -6
- package/src/server/node.ts +2 -2
- package/src/server/plugins.ts +1 -1
- package/src/server/prerender.ts +29 -29
- package/src/server/shell.ts +8 -8
- package/src/server/shutdown.ts +5 -5
- package/src/server/storage.ts +1 -1
- package/src/server-only.ts +7 -7
- package/src/transform.ts +76 -76
- package/dist/index-v5sbd3az.js.map +0 -15
package/src/api.ts
CHANGED
|
@@ -25,9 +25,9 @@ export function assertApiModuleExports(code: string, file: string): string[] {
|
|
|
25
25
|
if (statement["type"] === "ExportDefaultDeclaration") {
|
|
26
26
|
throw apiError(
|
|
27
27
|
file,
|
|
28
|
-
"export `default`
|
|
29
|
-
"
|
|
30
|
-
["
|
|
28
|
+
"export `default` is not supported in API modules",
|
|
29
|
+
"`src/api` modules only export named method handlers.",
|
|
30
|
+
["Replace it with `export const GET = (args) => …`", "Remove the default export"],
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
if (statement["type"] !== "ExportNamedDeclaration") {
|
|
@@ -65,20 +65,20 @@ export function assertApiModuleExports(code: string, file: string): string[] {
|
|
|
65
65
|
if (illegal.length > 0) {
|
|
66
66
|
throw apiError(
|
|
67
67
|
file,
|
|
68
|
-
`export \`${illegal[0]}\`
|
|
69
|
-
`
|
|
68
|
+
`export \`${illegal[0]}\` is not a recognized method handler`,
|
|
69
|
+
`Legal handlers: ${API_METHODS.join(", ")}.`,
|
|
70
70
|
[
|
|
71
|
-
"
|
|
72
|
-
"
|
|
71
|
+
"Rename the export to one of the HTTP methods",
|
|
72
|
+
"Move helpers to another module (e.g. `src/server/…`)",
|
|
73
73
|
],
|
|
74
74
|
);
|
|
75
75
|
}
|
|
76
76
|
if (methods.length === 0) {
|
|
77
77
|
throw apiError(
|
|
78
78
|
file,
|
|
79
|
-
"
|
|
80
|
-
`
|
|
81
|
-
[`
|
|
79
|
+
"API module has no method handler",
|
|
80
|
+
`At least one of ${API_METHODS.join(", ")} is required.`,
|
|
81
|
+
["Add `export const GET = (args) => new Response(…)`"],
|
|
82
82
|
);
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -103,11 +103,11 @@ export function assertMiddlewareExports(code: string, file: string): void {
|
|
|
103
103
|
throw new MoonsError({
|
|
104
104
|
code: "E_MIDDLEWARE_INVALID",
|
|
105
105
|
file,
|
|
106
|
-
message: "`_middleware.ts`
|
|
107
|
-
details: "
|
|
106
|
+
message: "`_middleware.ts` without `export default`",
|
|
107
|
+
details: "Directory middleware follows the `Middleware` shape: `(args) => Promise<Response>`.",
|
|
108
108
|
suggestions: [
|
|
109
|
-
"
|
|
110
|
-
"
|
|
109
|
+
"Add `export default async ({ req, ctx, next }) => await next()`",
|
|
110
|
+
"Delete the file if unused",
|
|
111
111
|
],
|
|
112
112
|
});
|
|
113
113
|
}
|
package/src/devtools.ts
CHANGED
|
@@ -36,7 +36,7 @@ export function emptyDevtoolsData(): DevtoolsData {
|
|
|
36
36
|
export function renderDevtoolsHtml(data: DevtoolsData): string {
|
|
37
37
|
const rows = (items: DevtoolsRoute[]): string =>
|
|
38
38
|
items.length === 0
|
|
39
|
-
? '<tr><td colspan="3" class="muted">(
|
|
39
|
+
? '<tr><td colspan="3" class="muted">(empty)</td></tr>'
|
|
40
40
|
: items
|
|
41
41
|
.map(
|
|
42
42
|
(item) =>
|
|
@@ -46,7 +46,7 @@ export function renderDevtoolsHtml(data: DevtoolsData): string {
|
|
|
46
46
|
|
|
47
47
|
const fnRows =
|
|
48
48
|
data.serverFns.length === 0
|
|
49
|
-
? '<tr><td colspan="3" class="muted">(
|
|
49
|
+
? '<tr><td colspan="3" class="muted">(no serverFn)</td></tr>'
|
|
50
50
|
: data.serverFns
|
|
51
51
|
.map(
|
|
52
52
|
(fn) =>
|
|
@@ -55,11 +55,11 @@ export function renderDevtoolsHtml(data: DevtoolsData): string {
|
|
|
55
55
|
.join("\n");
|
|
56
56
|
|
|
57
57
|
const canary = data.canary
|
|
58
|
-
? '<span class="ok">
|
|
59
|
-
: '<span class="muted">
|
|
58
|
+
? '<span class="ok">enabled</span> (canary installed)'
|
|
59
|
+
: '<span class="muted">disabled</span> (no canary)';
|
|
60
60
|
|
|
61
61
|
return `<!doctype html>
|
|
62
|
-
<html lang="
|
|
62
|
+
<html lang="en">
|
|
63
63
|
<head>
|
|
64
64
|
<meta charset="utf-8">
|
|
65
65
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
package/src/manifest.ts
CHANGED
|
@@ -70,7 +70,7 @@ export function renderApiModule(
|
|
|
70
70
|
)
|
|
71
71
|
.join("\n");
|
|
72
72
|
return [
|
|
73
|
-
"// Generated by @moons.
|
|
73
|
+
"// Generated by @moons. Do not edit manually.",
|
|
74
74
|
`export const apiRoutes = ${JSON.stringify(apiRoutes, null, 2)};`,
|
|
75
75
|
`export const apiMiddlewares = ${JSON.stringify(apiMiddlewares, null, 2)};`,
|
|
76
76
|
"export const loadApi = {",
|
|
@@ -100,7 +100,7 @@ export function renderRoutesModule(
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
return [
|
|
103
|
-
"// Generated by @moons.
|
|
103
|
+
"// Generated by @moons. Do not edit manually.",
|
|
104
104
|
`export const routes = ${JSON.stringify(routes, null, 2)};`,
|
|
105
105
|
"",
|
|
106
106
|
`export const clientManifest = ${JSON.stringify(manifest, null, 2)};`,
|
package/src/plugin.ts
CHANGED
|
@@ -141,9 +141,9 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
141
141
|
throw new MoonsError({
|
|
142
142
|
code: "E_INTERNAL",
|
|
143
143
|
file: id,
|
|
144
|
-
message: "
|
|
145
|
-
details: "
|
|
146
|
-
suggestions: ["
|
|
144
|
+
message: "failed to read the server file for transform",
|
|
145
|
+
details: "The `.server.ts` file must be readable during transform.",
|
|
146
|
+
suggestions: ["Check the path and file permissions"],
|
|
147
147
|
});
|
|
148
148
|
}
|
|
149
149
|
|
|
@@ -217,10 +217,10 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
217
217
|
throw new MoonsError({
|
|
218
218
|
code: "E_CONFIG_INVALID",
|
|
219
219
|
file: configFilePath,
|
|
220
|
-
message: "`moons.config.ts`
|
|
221
|
-
details: "
|
|
220
|
+
message: "`moons.config.ts` not found",
|
|
221
|
+
details: "The framework requires a config file at the project root.",
|
|
222
222
|
suggestions: [
|
|
223
|
-
"
|
|
223
|
+
"Create `moons.config.ts` with `export default defineConfig({ context: async (req) => ({}) })`",
|
|
224
224
|
],
|
|
225
225
|
});
|
|
226
226
|
}
|
|
@@ -240,9 +240,9 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
240
240
|
throw new MoonsError({
|
|
241
241
|
code: "E_CONFIG_INVALID",
|
|
242
242
|
file: configFilePath,
|
|
243
|
-
message: "
|
|
243
|
+
message: "failed to load `moons.config.ts`",
|
|
244
244
|
details: error instanceof Error ? error.message : String(error),
|
|
245
|
-
suggestions: ["
|
|
245
|
+
suggestions: ["Check the syntax and imports in `moons.config.ts`"],
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
|
|
@@ -314,7 +314,7 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
314
314
|
case VIRTUAL_MODULES.api:
|
|
315
315
|
return renderApiModule(apiRoutes, apiMiddlewares, root);
|
|
316
316
|
case VIRTUAL_MODULES.clientEntry:
|
|
317
|
-
return '// Generated by @moons.
|
|
317
|
+
return '// Generated by @moons. Do not edit manually.\nexport { clientManifest, loadRoute } from "virtual:moons/routes";\n';
|
|
318
318
|
case VIRTUAL_MODULES.config:
|
|
319
319
|
return renderConfigModule(root, configFilePath);
|
|
320
320
|
case VIRTUAL_MODULES.serverEntry:
|
|
@@ -393,12 +393,12 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
393
393
|
if (leak !== null) {
|
|
394
394
|
throw new MoonsError({
|
|
395
395
|
code: "E_INTERNAL",
|
|
396
|
-
message: `canary \`${canary}\`
|
|
396
|
+
message: `canary \`${canary}\` found in the client bundle (${leak.fileName})`,
|
|
397
397
|
details:
|
|
398
|
-
"
|
|
398
|
+
"Leak verification failed: server code leaked into the client output. Build stopped.",
|
|
399
399
|
suggestions: [
|
|
400
|
-
"
|
|
401
|
-
"
|
|
400
|
+
"Check the `*.server.ts` transform",
|
|
401
|
+
"Run `./scripts/m2/test-leak.sh` to audit",
|
|
402
402
|
],
|
|
403
403
|
});
|
|
404
404
|
}
|
|
@@ -416,12 +416,12 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
416
416
|
throw new MoonsError({
|
|
417
417
|
code: "E_FORBIDDEN_SERVER_IMPORT",
|
|
418
418
|
file: cleanId,
|
|
419
|
-
message: "
|
|
419
|
+
message: "server module got bundled into the client without passing through the transform",
|
|
420
420
|
details:
|
|
421
|
-
"
|
|
421
|
+
"Build verification: every `*.server.ts` in the client bundle must be an RPC stub produced by the transform.",
|
|
422
422
|
suggestions: [
|
|
423
|
-
"
|
|
424
|
-
"
|
|
423
|
+
"Make sure the zero-trust transform runs for this module",
|
|
424
|
+
"If this repeats, report it as a framework bug",
|
|
425
425
|
],
|
|
426
426
|
});
|
|
427
427
|
}
|
|
@@ -523,7 +523,7 @@ export default function moons(options: MoonsVitePluginOptions = {}): Plugin {
|
|
|
523
523
|
|
|
524
524
|
function renderConfigModule(root: string, configFilePath: string): string {
|
|
525
525
|
return [
|
|
526
|
-
"// Generated by @moons.
|
|
526
|
+
"// Generated by @moons. Do not edit manually.",
|
|
527
527
|
`import raw from ${JSON.stringify(rootSpecifier(root, configFilePath))};`,
|
|
528
528
|
'import { validateConfig } from "@moonsjs/core";',
|
|
529
529
|
`export default validateConfig(raw, { file: ${JSON.stringify(configFilePath)} });`,
|
|
@@ -533,7 +533,7 @@ function renderConfigModule(root: string, configFilePath: string): string {
|
|
|
533
533
|
|
|
534
534
|
function renderServerEntryDev(routesDir: string, eagerImports: string[]): string {
|
|
535
535
|
return [
|
|
536
|
-
"// Generated by @moons.
|
|
536
|
+
"// Generated by @moons. Do not edit manually.",
|
|
537
537
|
'import { createPluginRuntime, createRequestHandler } from "@moonsjs/vite/server";',
|
|
538
538
|
'import config from "virtual:moons/config";',
|
|
539
539
|
'import { routes, loadRoute } from "virtual:moons/routes";',
|
|
@@ -555,7 +555,7 @@ function renderServerEntryBuild(
|
|
|
555
555
|
canary: string | undefined,
|
|
556
556
|
): string {
|
|
557
557
|
return [
|
|
558
|
-
"// Generated by @moons.
|
|
558
|
+
"// Generated by @moons. Do not edit manually.",
|
|
559
559
|
'import { createFileShell, createPluginRuntime, createRequestHandler, startNodeServer } from "@moonsjs/vite/server";',
|
|
560
560
|
'import config from "virtual:moons/config";',
|
|
561
561
|
'import { routes, loadRoute } from "virtual:moons/routes";',
|
|
@@ -593,7 +593,7 @@ function renderPrerenderEntry(
|
|
|
593
593
|
canary: string | undefined,
|
|
594
594
|
): string {
|
|
595
595
|
return [
|
|
596
|
-
"// Generated by @moons.
|
|
596
|
+
"// Generated by @moons. Do not edit manually.",
|
|
597
597
|
'import { createFileShell, createRequestHandler, runPrerender } from "@moonsjs/vite/server";',
|
|
598
598
|
'import config from "virtual:moons/config";',
|
|
599
599
|
'import { routes, loadRoute } from "virtual:moons/routes";',
|
package/src/server/dev.ts
CHANGED
|
@@ -78,7 +78,7 @@ export function installDevMiddleware(
|
|
|
78
78
|
} catch (error) {
|
|
79
79
|
res.statusCode = 500;
|
|
80
80
|
res.setHeader("content-type", "text/plain; charset=utf-8");
|
|
81
|
-
res.end(`[moons] devtools
|
|
81
|
+
res.end(`[moons] devtools failed to render: ${String(error)}`);
|
|
82
82
|
}
|
|
83
83
|
return;
|
|
84
84
|
}
|
package/src/server/handler.ts
CHANGED
|
@@ -132,9 +132,9 @@ export function createRequestHandler(
|
|
|
132
132
|
new MoonsError({
|
|
133
133
|
code: "E_API_HANDLER_INVALID",
|
|
134
134
|
file: route.file,
|
|
135
|
-
message: `
|
|
136
|
-
details: "
|
|
137
|
-
suggestions: ["
|
|
135
|
+
message: `API module \`${route.path}\` could not be loaded`,
|
|
136
|
+
details: "The `loadApi` map does not contain this route (build/dev out of sync).",
|
|
137
|
+
suggestions: ["Rebuild / restart the dev server"],
|
|
138
138
|
}),
|
|
139
139
|
route,
|
|
140
140
|
);
|
|
@@ -151,9 +151,9 @@ export function createRequestHandler(
|
|
|
151
151
|
new MoonsError({
|
|
152
152
|
code: "E_API_HANDLER_INVALID",
|
|
153
153
|
file: route.file,
|
|
154
|
-
message: "
|
|
155
|
-
details: `
|
|
156
|
-
suggestions: ["Export `GET`/`POST`/…
|
|
154
|
+
message: "API module does not export a handler object",
|
|
155
|
+
details: `Module \`${route.path}\` must export method handlers.`,
|
|
156
|
+
suggestions: ["Export `GET`/`POST`/… as `(args) => Response` functions"],
|
|
157
157
|
}),
|
|
158
158
|
route,
|
|
159
159
|
);
|
|
@@ -194,9 +194,9 @@ export function createRequestHandler(
|
|
|
194
194
|
new MoonsError({
|
|
195
195
|
code: "E_API_HANDLER_INVALID",
|
|
196
196
|
file: route.file,
|
|
197
|
-
message: `handler \`${requestMethod}\`
|
|
198
|
-
details: "
|
|
199
|
-
suggestions: ["
|
|
197
|
+
message: `handler \`${requestMethod}\` did not return a \`Response\``,
|
|
198
|
+
details: "API handlers must return `new Response(...)`.",
|
|
199
|
+
suggestions: ["Return `new Response(body, { status, headers })`"],
|
|
200
200
|
}),
|
|
201
201
|
route,
|
|
202
202
|
);
|
|
@@ -225,13 +225,13 @@ export function createRequestHandler(
|
|
|
225
225
|
);
|
|
226
226
|
return htmlResponse(await shell(markup, payload, request.url), 404);
|
|
227
227
|
} catch (error) {
|
|
228
|
-
console.error("[moons]
|
|
228
|
+
console.error("[moons] failed to render custom _404:", error);
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
const payload = encodeSsrPayload({ key: "", params: {}, data: {} });
|
|
233
233
|
const html = await shell(
|
|
234
|
-
"<h1>404</h1><p>
|
|
234
|
+
"<h1>404</h1><p>Page not found.</p>",
|
|
235
235
|
payload,
|
|
236
236
|
request.url,
|
|
237
237
|
);
|
|
@@ -275,7 +275,7 @@ export function createRequestHandler(
|
|
|
275
275
|
);
|
|
276
276
|
return htmlResponse(await shell(markup, payload, request.url), 500);
|
|
277
277
|
} catch (renderError) {
|
|
278
|
-
console.error("[moons]
|
|
278
|
+
console.error("[moons] failed to render custom _error:", renderError);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
281
|
|
|
@@ -292,9 +292,9 @@ export function createRequestHandler(
|
|
|
292
292
|
throw new MoonsError({
|
|
293
293
|
code: "E_MIDDLEWARE_INVALID",
|
|
294
294
|
file: definition.file,
|
|
295
|
-
message: "middleware
|
|
296
|
-
details: "
|
|
297
|
-
suggestions: ["Restart dev server /
|
|
295
|
+
message: "directory middleware could not be loaded",
|
|
296
|
+
details: "The `loadRoute` map does not contain this `_middleware.ts`.",
|
|
297
|
+
suggestions: ["Restart the dev server / rebuild"],
|
|
298
298
|
});
|
|
299
299
|
}
|
|
300
300
|
const module = (await load()) as { default?: unknown };
|
|
@@ -303,8 +303,8 @@ export function createRequestHandler(
|
|
|
303
303
|
throw new MoonsError({
|
|
304
304
|
code: "E_MIDDLEWARE_INVALID",
|
|
305
305
|
file: definition.file,
|
|
306
|
-
message: "`_middleware.ts`
|
|
307
|
-
details: "
|
|
306
|
+
message: "`_middleware.ts` does not default-export a function",
|
|
307
|
+
details: "Directory middleware follows the `(args) => Promise<Response>` shape.",
|
|
308
308
|
suggestions: ["Export default `async ({ req, ctx, next }) => await next()`"],
|
|
309
309
|
});
|
|
310
310
|
}
|
|
@@ -324,9 +324,9 @@ export function createRequestHandler(
|
|
|
324
324
|
throw new MoonsError({
|
|
325
325
|
code: "E_MIDDLEWARE_INVALID",
|
|
326
326
|
file: definition.file,
|
|
327
|
-
message: "middleware
|
|
328
|
-
details: "
|
|
329
|
-
suggestions: ["Restart dev server /
|
|
327
|
+
message: "API middleware could not be loaded",
|
|
328
|
+
details: "The `loadApiMiddleware` map does not contain this `_middleware.ts`.",
|
|
329
|
+
suggestions: ["Restart the dev server / rebuild"],
|
|
330
330
|
});
|
|
331
331
|
}
|
|
332
332
|
const module = (await load()) as { default?: unknown };
|
|
@@ -334,8 +334,8 @@ export function createRequestHandler(
|
|
|
334
334
|
throw new MoonsError({
|
|
335
335
|
code: "E_MIDDLEWARE_INVALID",
|
|
336
336
|
file: definition.file,
|
|
337
|
-
message: "`_middleware.ts`
|
|
338
|
-
details: "
|
|
337
|
+
message: "`_middleware.ts` does not default-export a function",
|
|
338
|
+
details: "Directory middleware follows the `(args) => Promise<Response>` shape.",
|
|
339
339
|
suggestions: ["Export default `async ({ req, ctx, next }) => await next()`"],
|
|
340
340
|
});
|
|
341
341
|
}
|
|
@@ -385,7 +385,7 @@ export function createRequestHandler(
|
|
|
385
385
|
middlewares,
|
|
386
386
|
ctx,
|
|
387
387
|
() => handleApiRequest(apiMatch.route, apiMatch.params, request, ctx),
|
|
388
|
-
{ code: "E_MIDDLEWARE_INVALID", label: "middleware
|
|
388
|
+
{ code: "E_MIDDLEWARE_INVALID", label: "API middleware" },
|
|
389
389
|
)(request);
|
|
390
390
|
}
|
|
391
391
|
}
|
|
@@ -404,7 +404,7 @@ export function createRequestHandler(
|
|
|
404
404
|
middlewares,
|
|
405
405
|
ctx,
|
|
406
406
|
() => renderRoute(resolved, request, ctx),
|
|
407
|
-
{ code: "E_MIDDLEWARE_INVALID", label: "middleware
|
|
407
|
+
{ code: "E_MIDDLEWARE_INVALID", label: "directory middleware" },
|
|
408
408
|
)(request);
|
|
409
409
|
} catch (error) {
|
|
410
410
|
// Addendum B.2: sinyal routing dari loader/meta.
|
|
@@ -538,9 +538,9 @@ async function loadModules(
|
|
|
538
538
|
if (load === undefined) {
|
|
539
539
|
throw new MoonsError({
|
|
540
540
|
code: "E_INTERNAL",
|
|
541
|
-
message: `
|
|
542
|
-
details: "
|
|
543
|
-
suggestions: ["
|
|
541
|
+
message: `route module \`${key}\` is not registered`,
|
|
542
|
+
details: "The route registry is out of sync with the scan result.",
|
|
543
|
+
suggestions: ["Run `bun run build` again, or restart the dev server"],
|
|
544
544
|
});
|
|
545
545
|
}
|
|
546
546
|
return await load();
|
|
@@ -561,11 +561,11 @@ async function runRouteMeta(
|
|
|
561
561
|
throw new MoonsError({
|
|
562
562
|
code: "E_INTERNAL",
|
|
563
563
|
file,
|
|
564
|
-
message: "export `meta`
|
|
565
|
-
details: "
|
|
564
|
+
message: "export `meta` must be a function `({ data }) => RouteMeta`",
|
|
565
|
+
details: "The `meta` shape follows `RouteMeta`.",
|
|
566
566
|
suggestions: [
|
|
567
|
-
"
|
|
568
|
-
"
|
|
567
|
+
"Change it to `export const meta = ({ data }) => ({ title: \"...\" })`",
|
|
568
|
+
"Or remove the `meta` export",
|
|
569
569
|
],
|
|
570
570
|
});
|
|
571
571
|
}
|
|
@@ -574,9 +574,9 @@ async function runRouteMeta(
|
|
|
574
574
|
throw new MoonsError({
|
|
575
575
|
code: "E_INTERNAL",
|
|
576
576
|
file,
|
|
577
|
-
message: "`meta()`
|
|
578
|
-
details: "
|
|
579
|
-
suggestions: ["
|
|
577
|
+
message: "`meta()` must return a RouteMeta object",
|
|
578
|
+
details: "The returned value is used for <title>/description/og.",
|
|
579
|
+
suggestions: ["Return an object, e.g. `({ title: \"Home\" })`"],
|
|
580
580
|
});
|
|
581
581
|
}
|
|
582
582
|
return result as Record<string, unknown>;
|
|
@@ -589,13 +589,13 @@ function apiErrorResponse(error: unknown, route: ApiRouteDefinition): Response {
|
|
|
589
589
|
const isProduction = process.env["NODE_ENV"] === "production";
|
|
590
590
|
if (error instanceof MoonsError) {
|
|
591
591
|
console.error(`[moons] API ${route.path}: ${error.format()}`);
|
|
592
|
-
return new Response(isProduction ? "
|
|
592
|
+
return new Response(isProduction ? "Internal server error." : error.format(), {
|
|
593
593
|
status: 500,
|
|
594
594
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
595
595
|
});
|
|
596
596
|
}
|
|
597
597
|
console.error(`[moons] API ${route.path}:`, error);
|
|
598
|
-
return new Response(isProduction ? "
|
|
598
|
+
return new Response(isProduction ? "Internal server error." : String(error), {
|
|
599
599
|
status: 500,
|
|
600
600
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
601
601
|
});
|
|
@@ -609,10 +609,10 @@ function internalErrorResponse(error: unknown, options: { log?: boolean } = {}):
|
|
|
609
609
|
const detail =
|
|
610
610
|
process.env["NODE_ENV"] !== "production" && error instanceof MoonsError
|
|
611
611
|
? `<pre>${escapeHtml(error.format())}</pre>`
|
|
612
|
-
: "<p>
|
|
612
|
+
: "<p>Internal server error.</p>";
|
|
613
613
|
|
|
614
614
|
return htmlResponse(
|
|
615
|
-
`<!doctype html><html lang="
|
|
615
|
+
`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>500</title></head><body><h1>500</h1>${detail}</body></html>`,
|
|
616
616
|
500,
|
|
617
617
|
);
|
|
618
618
|
}
|
|
@@ -667,7 +667,7 @@ function warnPayloadFindings(
|
|
|
667
667
|
}
|
|
668
668
|
warned.add(label);
|
|
669
669
|
console.warn(
|
|
670
|
-
`[moons]
|
|
670
|
+
`[moons] dev warning: SSR payload contains ${label} — do not return secrets from loaders.`,
|
|
671
671
|
);
|
|
672
672
|
}
|
|
673
673
|
}
|
package/src/server/isr.ts
CHANGED
|
@@ -57,7 +57,7 @@ async function runRevalidate(options: RevalidateOptions): Promise<void> {
|
|
|
57
57
|
}),
|
|
58
58
|
);
|
|
59
59
|
if (response.status !== 200) {
|
|
60
|
-
log(`[moons] isr:
|
|
60
|
+
log(`[moons] isr: skipped ${options.pathname} (status ${response.status})`);
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
const html = await response.text();
|
|
@@ -69,8 +69,8 @@ async function runRevalidate(options: RevalidateOptions): Promise<void> {
|
|
|
69
69
|
const labels = findings
|
|
70
70
|
.map((finding) => (finding.kind === "canary" ? "canary" : `env(${finding.label})`))
|
|
71
71
|
.join(", ");
|
|
72
|
-
// Fail-closed:
|
|
73
|
-
log(`[moons] isr:
|
|
72
|
+
// Fail-closed: tidak menimpa file statis dengan konten bocor.
|
|
73
|
+
log(`[moons] isr: NOT writing ${options.pathname} — contains ${labels}`);
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
76
|
if (options.storage !== undefined) {
|
|
@@ -78,14 +78,14 @@ async function runRevalidate(options: RevalidateOptions): Promise<void> {
|
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
80
|
if (options.file === undefined) {
|
|
81
|
-
log(`[moons] isr:
|
|
81
|
+
log(`[moons] isr: skipped ${options.pathname} — no destination file/storage`);
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
const tmp = `${options.file}.tmp-${process.pid}`;
|
|
85
85
|
writeFileSync(tmp, html);
|
|
86
86
|
renameSync(tmp, options.file);
|
|
87
87
|
} catch (error) {
|
|
88
|
-
log(`[moons] isr:
|
|
88
|
+
log(`[moons] isr: failed to regenerate ${options.pathname}: ${String(error)}`);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
@@ -366,13 +366,13 @@ function rpcBodyTooLargeText(limit: number, size: number | null): string {
|
|
|
366
366
|
code: "E_RPC_BODY_TOO_LARGE",
|
|
367
367
|
message:
|
|
368
368
|
size === null
|
|
369
|
-
? `body
|
|
370
|
-
: `body ${megabytes(size)} MB
|
|
369
|
+
? `body exceeds the ${megabytes(limit)} MB limit`
|
|
370
|
+
: `body ${megabytes(size)} MB exceeds the ${megabytes(limit)} MB limit`,
|
|
371
371
|
details:
|
|
372
|
-
"Body
|
|
372
|
+
"Body exceeds `security.bodyLimitBytes`; reading stops at the transport before the body is fully buffered.",
|
|
373
373
|
suggestions: [
|
|
374
|
-
"
|
|
375
|
-
"
|
|
374
|
+
"Reduce the payload size, or",
|
|
375
|
+
"Increase security.bodyLimitBytes if you really need to",
|
|
376
376
|
],
|
|
377
377
|
}).format();
|
|
378
378
|
}
|
|
@@ -524,7 +524,7 @@ function scheduleRevalidation(input: {
|
|
|
524
524
|
if (logger !== null) {
|
|
525
525
|
logger({ msg: "isr:revalidate-failed", level: "warn", path: normalized, error: message });
|
|
526
526
|
} else {
|
|
527
|
-
console.error(`[moons] isr
|
|
527
|
+
console.error(`[moons] isr regeneration failed (${normalized}): ${message}`);
|
|
528
528
|
}
|
|
529
529
|
});
|
|
530
530
|
}
|
package/src/server/node.ts
CHANGED
|
@@ -18,7 +18,7 @@ export class InvalidRequestError extends Error {
|
|
|
18
18
|
export class BodyLimitError extends Error {
|
|
19
19
|
readonly limit: number;
|
|
20
20
|
constructor(limit: number) {
|
|
21
|
-
super(`request body
|
|
21
|
+
super(`request body exceeds the ${limit} byte limit`);
|
|
22
22
|
this.name = "BodyLimitError";
|
|
23
23
|
this.limit = limit;
|
|
24
24
|
}
|
|
@@ -48,7 +48,7 @@ export function resolveRequestUrl(
|
|
|
48
48
|
try {
|
|
49
49
|
return new URL(`${proto ?? "http"}://${host}${req.url ?? "/"}`);
|
|
50
50
|
} catch {
|
|
51
|
-
throw new InvalidRequestError(`
|
|
51
|
+
throw new InvalidRequestError(`invalid Host header: ${JSON.stringify(hostHeader)}`);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
package/src/server/plugins.ts
CHANGED
|
@@ -69,7 +69,7 @@ export function createPluginRuntime(options: PluginRuntimeOptions): PluginRuntim
|
|
|
69
69
|
try {
|
|
70
70
|
await plugin.onShutdown?.(app);
|
|
71
71
|
} catch (error) {
|
|
72
|
-
log(`[moons] plugin \`${plugin.name}\`
|
|
72
|
+
log(`[moons] plugin \`${plugin.name}\` failed during onShutdown: ${String(error)}`);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
},
|