@astroscope/node 3.0.0 → 3.1.0
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.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/islands-middleware-entrypoint.js +2 -2
- package/dist/islands-middleware-entrypoint.js.map +1 -1
- package/dist/islands.d.ts +1 -1
- package/dist/islands.js +1 -1
- package/dist/{route-store-neUA2nBb.d.ts → route-store-Cl3OT0-q.d.ts} +7 -3
- package/dist/{route-store-neUA2nBb.d.ts.map → route-store-Cl3OT0-q.d.ts.map} +1 -1
- package/dist/{route-store-DdxGePj2.js → route-store-DVSmOa34.js} +14 -4
- package/dist/route-store-DVSmOa34.js.map +1 -0
- package/dist/server.js +5 -2
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/route-store-DdxGePj2.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as ExcludePattern } from "./excludes-rvkVGg6B.js";
|
|
2
2
|
import "./construct-BGlPfWMF.js";
|
|
3
|
-
import { c as IslandEmitter, i as registerIslandEmitter, l as IslandInfo, s as IslandEmission, t as getRequestRouteData } from "./route-store-
|
|
3
|
+
import { c as IslandEmitter, i as registerIslandEmitter, l as IslandInfo, s as IslandEmission, t as getRequestRouteData } from "./route-store-Cl3OT0-q.js";
|
|
4
4
|
import { t as BootContext } from "./types-D0uMBi2M.js";
|
|
5
5
|
import { n as BootEventName, t as BootEventHandler } from "./events-u7J3ezJR.js";
|
|
6
6
|
import { AstroIntegration } from "astro";
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { n as getCurrentGeneration, r as incrementGeneration, t as GEN_HEADER }
|
|
|
5
5
|
import { r as RECOMMENDED_EXCLUDES, s as serializeExcludePatterns } from "./excludes-10eDopVB.js";
|
|
6
6
|
import { n as routeEntrypoints, r as stripQuery, t as collectRouteIslands } from "./route-islands-B53rE5MH.js";
|
|
7
7
|
import { i as registerIslandEmitter } from "./emitters-C20tjKLp.js";
|
|
8
|
-
import { t as getRequestRouteData } from "./route-store-
|
|
8
|
+
import { t as getRequestRouteData } from "./route-store-DVSmOa34.js";
|
|
9
9
|
import fs, { readFileSync } from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as log } from "./log-B69HEBvg.js";
|
|
2
2
|
import { t as getDocumentEmitters } from "./emitters-C20tjKLp.js";
|
|
3
|
-
import { t as getRequestRouteData } from "./route-store-
|
|
3
|
+
import { t as getRequestRouteData } from "./route-store-DVSmOa34.js";
|
|
4
4
|
import { n as installRouteIslands } from "./routes-D1o_WrJ5.js";
|
|
5
5
|
import { n as createPageTransformStream, t as createIslandsTransformer } from "./transform-Bz5z5w2Y.js";
|
|
6
6
|
import { manifest } from "virtual:@astroscope/node/islands-manifest";
|
|
@@ -21,7 +21,7 @@ function createIslandsMiddleware(manifest) {
|
|
|
21
21
|
const response = await next();
|
|
22
22
|
const emitters = getDocumentEmitters();
|
|
23
23
|
if (!manifest && emitters.length === 0) return response;
|
|
24
|
-
const route = getRequestRouteData(context
|
|
24
|
+
const route = getRequestRouteData(context);
|
|
25
25
|
if (route && route.type !== "page") return response;
|
|
26
26
|
const contentType = response.headers.get("content-type") ?? "";
|
|
27
27
|
if (!response.body || !contentType.toLowerCase().includes("text/html") || response.headers.has("content-encoding")) return response;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"islands-middleware-entrypoint.js","names":[],"sources":["../src/islands/middleware.ts","../src/islands/middleware-entrypoint.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRouteData } from '../server/route-store.js';\nimport { getDocumentEmitters } from './emitters.js';\nimport { type IslandsTransformer, createIslandsTransformer, createPageTransformStream } from './transform.js';\nimport type { IslandsManifest } from './types.js';\n\n/**\n * Streams every html page response through the delivery pipeline: the islands\n * rewriter (when a manifest exists — prod with preloading enabled) plus the\n * document emissions registered by other packages, head scripts inserted after\n * `<head>` and end scripts appended once the rewriter finished. Non-page routes\n * (an endpoint or proxy catch-all returning html), non-html responses and\n * already-encoded bodies pass through untouched. Injected bytes invalidate a\n * pre-computed length, so `content-length` is dropped — streamed responses never\n * carry one anyway.\n */\nexport function createIslandsMiddleware(manifest: IslandsManifest | null): MiddlewareHandler {\n let transformer: IslandsTransformer | undefined;\n\n return async (context, next) => {\n const response = await next();\n const emitters = getDocumentEmitters();\n\n if (!manifest && emitters.length === 0) {\n return response;\n }\n\n const route = getRequestRouteData(context
|
|
1
|
+
{"version":3,"file":"islands-middleware-entrypoint.js","names":[],"sources":["../src/islands/middleware.ts","../src/islands/middleware-entrypoint.ts"],"sourcesContent":["import type { MiddlewareHandler } from 'astro';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRouteData } from '../server/route-store.js';\nimport { getDocumentEmitters } from './emitters.js';\nimport { type IslandsTransformer, createIslandsTransformer, createPageTransformStream } from './transform.js';\nimport type { IslandsManifest } from './types.js';\n\n/**\n * Streams every html page response through the delivery pipeline: the islands\n * rewriter (when a manifest exists — prod with preloading enabled) plus the\n * document emissions registered by other packages, head scripts inserted after\n * `<head>` and end scripts appended once the rewriter finished. Non-page routes\n * (an endpoint or proxy catch-all returning html), non-html responses and\n * already-encoded bodies pass through untouched. Injected bytes invalidate a\n * pre-computed length, so `content-length` is dropped — streamed responses never\n * carry one anyway.\n */\nexport function createIslandsMiddleware(manifest: IslandsManifest | null): MiddlewareHandler {\n let transformer: IslandsTransformer | undefined;\n\n return async (context, next) => {\n const response = await next();\n const emitters = getDocumentEmitters();\n\n if (!manifest && emitters.length === 0) {\n return response;\n }\n\n const route = getRequestRouteData(context);\n\n if (route && route.type !== 'page') {\n return response;\n }\n\n const contentType = response.headers.get('content-type') ?? '';\n\n if (\n !response.body ||\n !contentType.toLowerCase().includes('text/html') ||\n response.headers.has('content-encoding')\n ) {\n return response;\n }\n\n const heads: string[] = [];\n const ends: (() => string | null)[] = [];\n\n for (const emitter of emitters) {\n try {\n const emission = emitter(context);\n\n if (emission?.head) {\n heads.push(emission.head);\n }\n\n if (emission?.end) {\n ends.push(emission.end);\n }\n } catch (error) {\n // an emitter must never break the page — its contribution is dropped\n log.error({ err: error }, 'document emitter failed');\n }\n }\n\n if (!manifest && heads.length === 0 && ends.length === 0) {\n return response;\n }\n\n if (manifest) {\n transformer ??= createIslandsTransformer(manifest);\n }\n\n const stream = createPageTransformStream({\n rewriter: transformer?.createDocumentRewriter(context),\n heads,\n ends,\n });\n\n const headers = new Headers(response.headers);\n\n headers.delete('content-length');\n\n return new Response(response.body.pipeThrough(stream), {\n status: response.status,\n statusText: response.statusText,\n headers,\n });\n };\n}\n","import { manifest } from 'virtual:@astroscope/node/islands-manifest';\nimport { createIslandsMiddleware } from './middleware.js';\nimport { installRouteIslands } from './routes.js';\n\ninstallRouteIslands(manifest);\n\nexport const onRequest = createIslandsMiddleware(manifest);\n"],"mappings":";;;;;;;;;;;;;;;;;AAiBA,SAAgB,wBAAwB,UAAqD;CAC3F,IAAI;CAEJ,OAAO,OAAO,SAAS,SAAS;EAC9B,MAAM,WAAW,MAAM,KAAK;EAC5B,MAAM,WAAW,oBAAoB;EAErC,IAAI,CAAC,YAAY,SAAS,WAAW,GACnC,OAAO;EAGT,MAAM,QAAQ,oBAAoB,OAAO;EAEzC,IAAI,SAAS,MAAM,SAAS,QAC1B,OAAO;EAGT,MAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;EAE5D,IACE,CAAC,SAAS,QACV,CAAC,YAAY,YAAY,CAAC,CAAC,SAAS,WAAW,KAC/C,SAAS,QAAQ,IAAI,kBAAkB,GAEvC,OAAO;EAGT,MAAM,QAAkB,CAAC;EACzB,MAAM,OAAgC,CAAC;EAEvC,KAAK,MAAM,WAAW,UACpB,IAAI;GACF,MAAM,WAAW,QAAQ,OAAO;GAEhC,IAAI,UAAU,MACZ,MAAM,KAAK,SAAS,IAAI;GAG1B,IAAI,UAAU,KACZ,KAAK,KAAK,SAAS,GAAG;EAE1B,SAAS,OAAO;GAEd,IAAI,MAAM,EAAE,KAAK,MAAM,GAAG,yBAAyB;EACrD;EAGF,IAAI,CAAC,YAAY,MAAM,WAAW,KAAK,KAAK,WAAW,GACrD,OAAO;EAGT,IAAI,UACF,gBAAgB,yBAAyB,QAAQ;EAGnD,MAAM,SAAS,0BAA0B;GACvC,UAAU,aAAa,uBAAuB,OAAO;GACrD;GACA;EACF,CAAC;EAED,MAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;EAE5C,QAAQ,OAAO,gBAAgB;EAE/B,OAAO,IAAI,SAAS,SAAS,KAAK,YAAY,MAAM,GAAG;GACrD,QAAQ,SAAS;GACjB,YAAY,SAAS;GACrB;EACF,CAAC;CACH;AACF;;;ACpFA,oBAAoB,QAAQ;AAE5B,MAAa,YAAY,wBAAwB,QAAQ"}
|
package/dist/islands.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as DocumentEmission, c as IslandEmitter, i as registerIslandEmitter, l as IslandInfo, n as setRequestRouteData, o as DocumentEmitter, r as registerDocumentEmitter, s as IslandEmission, t as getRequestRouteData } from "./route-store-
|
|
1
|
+
import { a as DocumentEmission, c as IslandEmitter, i as registerIslandEmitter, l as IslandInfo, n as setRequestRouteData, o as DocumentEmitter, r as registerDocumentEmitter, s as IslandEmission, t as getRequestRouteData } from "./route-store-Cl3OT0-q.js";
|
|
2
2
|
import { IntegrationResolvedRoute } from "astro";
|
|
3
3
|
import { Rolldown } from "vite";
|
|
4
4
|
//#region src/islands/routes.d.ts
|
package/dist/islands.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as routeEntrypoints, r as stripQuery, t as collectRouteIslands } from "./route-islands-B53rE5MH.js";
|
|
2
2
|
import { i as registerIslandEmitter, r as registerDocumentEmitter } from "./emitters-C20tjKLp.js";
|
|
3
|
-
import { n as setRequestRouteData, t as getRequestRouteData } from "./route-store-
|
|
3
|
+
import { n as setRequestRouteData, t as getRequestRouteData } from "./route-store-DVSmOa34.js";
|
|
4
4
|
import { t as getRouteIslands } from "./routes-D1o_WrJ5.js";
|
|
5
5
|
export { collectRouteIslands, getRequestRouteData, getRouteIslands, registerDocumentEmitter, registerIslandEmitter, routeEntrypoints, setRequestRouteData, stripQuery };
|
|
@@ -66,8 +66,12 @@ declare function registerIslandEmitter(emitter: IslandEmitter): void;
|
|
|
66
66
|
declare function registerDocumentEmitter(emitter: DocumentEmitter): void;
|
|
67
67
|
//#endregion
|
|
68
68
|
//#region src/server/route-store.d.ts
|
|
69
|
-
declare function setRequestRouteData(request: Request, routeData: RouteData): void;
|
|
70
|
-
|
|
69
|
+
declare function setRequestRouteData(request: Request, locals: object, routeData: RouteData): void;
|
|
70
|
+
/**
|
|
71
|
+
* Look the route up by the api context (survives `next(url)` rewrites) or by
|
|
72
|
+
* the request as the handler created it.
|
|
73
|
+
*/
|
|
74
|
+
declare function getRequestRouteData(key: Request | Pick<APIContext, 'locals'>): RouteData | undefined;
|
|
71
75
|
//#endregion
|
|
72
76
|
export { DocumentEmission as a, IslandEmitter as c, registerIslandEmitter as i, IslandInfo as l, setRequestRouteData as n, DocumentEmitter as o, registerDocumentEmitter as r, IslandEmission as s, getRequestRouteData as t };
|
|
73
|
-
//# sourceMappingURL=route-store-
|
|
77
|
+
//# sourceMappingURL=route-store-Cl3OT0-q.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-store-
|
|
1
|
+
{"version":3,"file":"route-store-Cl3OT0-q.d.ts","names":[],"sources":["../src/islands/types.ts","../src/islands/emitters.ts","../src/server/route-store.ts"],"mappings":";;;;;;;KA4BY;EACV;EACA;;EAEA;;EAEA;;EAEA;;;;;;;;;;;;;KAcU;EACV;EACA;EACA;;;;;;KAOU,iBAAiB,QAAQ,YAAY,UAAU,2BAA2B;;;;KAK1E;EACV;EACA;;;;;;;KAQU,mBAAmB,SAAS,eAAe;;;;;;;;iBC9CvC,sBAAsB,SAAS;;;;;;;iBAc/B,wBAAwB,SAAS;;;iBCfjC,oBAAoB,SAAS,SAAS,gBAAgB,WAAW;;;;;iBASjE,oBAAoB,KAAK,UAAU,KAAK,wBAAwB"}
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
* `Symbol.for` so the vite-runner and native module instances share it —
|
|
8
8
|
* same pattern as the log store.
|
|
9
9
|
*
|
|
10
|
+
* Stored under the request and under its `locals` object. `locals` is the
|
|
11
|
+
* one object astro hands to every middleware unchanged — `context.request`
|
|
12
|
+
* is no identity for a request, as every `next(url)` rewrite replaces it
|
|
13
|
+
* with a copy (once per nesting level of `sequence`).
|
|
14
|
+
*
|
|
10
15
|
* Absent in dev (no adapter handler) — consumers fall back to their
|
|
11
16
|
* content-type gates.
|
|
12
17
|
*/
|
|
@@ -15,13 +20,18 @@ function store() {
|
|
|
15
20
|
const scope = globalThis;
|
|
16
21
|
return scope[STORE] ??= /* @__PURE__ */ new WeakMap();
|
|
17
22
|
}
|
|
18
|
-
function setRequestRouteData(request, routeData) {
|
|
23
|
+
function setRequestRouteData(request, locals, routeData) {
|
|
19
24
|
store().set(request, routeData);
|
|
25
|
+
store().set(locals, routeData);
|
|
20
26
|
}
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Look the route up by the api context (survives `next(url)` rewrites) or by
|
|
29
|
+
* the request as the handler created it.
|
|
30
|
+
*/
|
|
31
|
+
function getRequestRouteData(key) {
|
|
32
|
+
return store().get("locals" in key ? key.locals : key);
|
|
23
33
|
}
|
|
24
34
|
//#endregion
|
|
25
35
|
export { setRequestRouteData as n, getRequestRouteData as t };
|
|
26
36
|
|
|
27
|
-
//# sourceMappingURL=route-store-
|
|
37
|
+
//# sourceMappingURL=route-store-DVSmOa34.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-store-DVSmOa34.js","names":[],"sources":["../src/server/route-store.ts"],"sourcesContent":["import type { APIContext, RouteData } from 'astro';\n\n/**\n * The route matched for a request, stashed by the server handler before\n * rendering so middleware can tell what kind of route produced a response —\n * a `.astro` page or an endpoint that happens to return html (a proxy\n * catch-all, an html-returning `.ts` route). Keyed on `globalThis` via\n * `Symbol.for` so the vite-runner and native module instances share it —\n * same pattern as the log store.\n *\n * Stored under the request and under its `locals` object. `locals` is the\n * one object astro hands to every middleware unchanged — `context.request`\n * is no identity for a request, as every `next(url)` rewrite replaces it\n * with a copy (once per nesting level of `sequence`).\n *\n * Absent in dev (no adapter handler) — consumers fall back to their\n * content-type gates.\n */\nconst STORE = Symbol.for('@astroscope/node.requestRoutes');\n\ntype Scope = { [STORE]?: WeakMap<object, RouteData> };\n\nfunction store(): WeakMap<object, RouteData> {\n const scope = globalThis as Scope;\n\n return (scope[STORE] ??= new WeakMap());\n}\n\nexport function setRequestRouteData(request: Request, locals: object, routeData: RouteData): void {\n store().set(request, routeData);\n store().set(locals, routeData);\n}\n\n/**\n * Look the route up by the api context (survives `next(url)` rewrites) or by\n * the request as the handler created it.\n */\nexport function getRequestRouteData(key: Request | Pick<APIContext, 'locals'>): RouteData | undefined {\n return store().get('locals' in key ? key.locals : key);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,MAAM,QAAQ,OAAO,IAAI,gCAAgC;AAIzD,SAAS,QAAoC;CAC3C,MAAM,QAAQ;CAEd,OAAQ,MAAM,2BAAW,IAAI,QAAQ;AACvC;AAEA,SAAgB,oBAAoB,SAAkB,QAAgB,WAA4B;CAChG,MAAM,CAAC,CAAC,IAAI,SAAS,SAAS;CAC9B,MAAM,CAAC,CAAC,IAAI,QAAQ,SAAS;AAC/B;;;;;AAMA,SAAgB,oBAAoB,KAAkE;CACpG,OAAO,MAAM,CAAC,CAAC,IAAI,YAAY,MAAM,IAAI,SAAS,GAAG;AACvD"}
|
package/dist/server.js
CHANGED
|
@@ -4,7 +4,7 @@ import { i as getRequestRecord } from "./request-route-DcnZOOM4.js";
|
|
|
4
4
|
import { n as log } from "./log-B69HEBvg.js";
|
|
5
5
|
import { n as dispatchNativeMount, t as clearNativeMounts } from "./native-mount-DjYEnO4X.js";
|
|
6
6
|
import { c as withSpan, s as startSpan } from "./telemetry-B9aziFyQ.js";
|
|
7
|
-
import { n as setRequestRouteData } from "./route-store-
|
|
7
|
+
import { n as setRequestRouteData } from "./route-store-DVSmOa34.js";
|
|
8
8
|
import { n as deactivateHealthChecks, t as activateHealthChecks } from "./store-8pnTxM1x.js";
|
|
9
9
|
import { n as MIME_TYPES, t as COMPRESSIBLE } from "./mime-C_GwZovh.js";
|
|
10
10
|
import fs, { createReadStream } from "node:fs";
|
|
@@ -160,13 +160,16 @@ function createAppHandler(app, options, client) {
|
|
|
160
160
|
}
|
|
161
161
|
const routeData = app.match(request, true);
|
|
162
162
|
const matched = routeData && !(routeData.type === "page" && routeData.prerender) ? routeData : void 0;
|
|
163
|
-
|
|
163
|
+
const locals = {};
|
|
164
|
+
if (matched) setRequestRouteData(request, locals, matched);
|
|
164
165
|
await writeResponse(matched ? await app.render(request, {
|
|
165
166
|
addCookieHeader: true,
|
|
167
|
+
locals,
|
|
166
168
|
routeData: matched,
|
|
167
169
|
prerenderedErrorPageFetch
|
|
168
170
|
}) : await app.render(request, {
|
|
169
171
|
addCookieHeader: true,
|
|
172
|
+
locals,
|
|
170
173
|
prerenderedErrorPageFetch
|
|
171
174
|
}), res);
|
|
172
175
|
};
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","names":["healthServer","server"],"sources":["../src/server/client-dir.ts","../src/server/serve-app.ts","../src/server/serve-static.ts","../src/server/server.ts"],"sourcesContent":["import path from 'node:path';\nimport url from 'node:url';\n\n/**\n * Resolve the client directory at runtime relative to the built server entry.\n *\n * The build-time client/server URLs are only valid on the build machine; in a\n * container the deploy path differs. Walk up from `import.meta.url` of the\n * bundled server code until the server directory is found, then apply the\n * build-time server→client relative path.\n */\nexport function resolveClientDir(options: { client: string; server: string }, importMetaUrl: string): string {\n const clientPath = url.fileURLToPath(new URL(options.client));\n const serverPath = url.fileURLToPath(new URL(options.server));\n const rel = path.relative(serverPath, clientPath);\n const serverFolder = path.basename(serverPath);\n\n let serverEntryFolderURL = path.dirname(importMetaUrl);\n let previous = '';\n\n while (!serverEntryFolderURL.endsWith(serverFolder)) {\n if (serverEntryFolderURL === previous) {\n throw new Error(\n `[@astroscope/node] could not find the server directory \"${serverFolder}\" by walking up from \"${importMetaUrl}\"`,\n );\n }\n\n previous = serverEntryFolderURL;\n serverEntryFolderURL = path.dirname(serverEntryFolderURL);\n }\n\n const clientURL = new URL(rel.endsWith('/') ? rel : `${rel}/`, `${serverEntryFolderURL}/entry.mjs`);\n\n return url.fileURLToPath(clientURL);\n}\n","import { createReadStream } from 'node:fs';\nimport type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from 'node:http';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type { BaseApp } from 'astro/app';\nimport { createRequestFromNodeRequest, getAbortControllerCleanup } from 'astro/app/node';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRecord } from '../observability/log/store.js';\nimport type { RuntimeOptions } from '../types.js';\nimport { setRequestRouteData } from './route-store.js';\n\nasync function readFSErrorPage(client: string, status: number): Promise<Response | undefined> {\n const filePaths = [`${status}.html`, `${status}/index.html`];\n\n for (const filePath of filePaths) {\n const fullPath = path.join(client, filePath);\n let stream: ReturnType<typeof createReadStream> | undefined;\n\n try {\n stream = createReadStream(fullPath);\n\n await new Promise<void>((resolve, reject) => {\n stream!.once('open', () => resolve());\n stream!.once('error', reject);\n });\n\n return new Response(Readable.toWeb(stream) as ReadableStream, {\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n } catch {\n stream?.destroy();\n }\n }\n\n return undefined;\n}\n\nfunction createOutgoingHttpHeaders(headers: Headers): OutgoingHttpHeaders | undefined {\n const nodeHeaders: OutgoingHttpHeaders = Object.fromEntries(headers.entries());\n\n if (Object.keys(nodeHeaders).length === 0) {\n return undefined;\n }\n\n // the entries iterator joins set-cookie values with a comma; node needs them as an array\n const cookies = headers.getSetCookie();\n\n if (cookies.length > 1) {\n nodeHeaders['set-cookie'] = cookies;\n }\n\n return nodeHeaders;\n}\n\n/**\n * Streams the web response into the node response. A render failing after the\n * first chunk cannot change the status anymore, so it is logged through the\n * request logger and marked on the request record — the completion line, the\n * span and `astro.render.failures` reflect it. On the wire it behaves like\n * astro's own writer: an `Internal server error` marker, then the socket is\n * destroyed.\n */\nexport async function writeResponse(response: Response, res: ServerResponse): Promise<void> {\n res.statusMessage = response.statusText;\n res.writeHead(response.status, createOutgoingHttpHeaders(response.headers));\n\n // astro parks the socket listener behind the request's abort signal on the node\n // request; releasing it once the response is done keeps keep-alive sockets from\n // accumulating one listener per request\n const cleanupAbort = getAbortControllerCleanup(res.req);\n\n if (cleanupAbort) {\n const runCleanup = (): void => {\n cleanupAbort();\n res.off('finish', runCleanup);\n res.off('close', runCleanup);\n };\n\n res.on('finish', runCleanup);\n res.on('close', runCleanup);\n }\n\n if (!response.body) {\n res.end();\n\n return;\n }\n\n const reader = response.body.getReader();\n\n // a client going away stops the render; on a failed stream the cancel rejects\n // with the render error, which the catch below has already reported\n res.on('close', () => {\n reader.cancel().catch(() => undefined);\n });\n\n try {\n for (let result = await reader.read(); !result.done; result = await reader.read()) {\n res.write(result.value);\n }\n\n res.end();\n } catch (err) {\n const record = getRequestRecord();\n\n if (record) {\n record.truncated = true;\n }\n\n log.error(\n {\n ...(err instanceof Error ? { err } : { reason: err }),\n ...(record?.route && { route: record.route }),\n ...(!record?.logger && { url: record?.url ?? res.req.url }),\n },\n 'render failed after the response started, response truncated',\n );\n\n res.write('Internal server error', () => {\n res.destroy(err instanceof Error ? err : undefined);\n });\n }\n}\n\n/**\n * Render on-demand routes: node req → web Request → `app.render()` → node res.\n * Prerendered pages never reach this handler (the static handler serves them);\n * requests for them landing here render the 404 route.\n */\nexport function createAppHandler(app: BaseApp, options: RuntimeOptions, client: string) {\n process.on('unhandledRejection', (reason) => {\n const requestUrl = getRequestRecord()?.url;\n\n log.error(\n {\n ...(reason instanceof Error ? { err: reason } : { reason }),\n ...(requestUrl && { url: requestUrl }),\n },\n requestUrl ? 'unhandled rejection while rendering' : 'unhandled rejection',\n );\n });\n\n const prerenderedErrorPageFetch = async (url: string): Promise<Response> => {\n const { pathname } = new URL(url);\n\n for (const status of [404, 500]) {\n if (pathname.endsWith(`/${status}.html`) || pathname.endsWith(`/${status}/index.html`)) {\n const response = await readFSErrorPage(client, status);\n\n if (response) return response;\n }\n }\n\n return new Response(null, { status: 404 });\n };\n\n const bodySizeLimit =\n options.bodySizeLimit === 0 || options.bodySizeLimit === Number.POSITIVE_INFINITY\n ? undefined\n : options.bodySizeLimit;\n\n return async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n let request: Request;\n\n try {\n request = createRequestFromNodeRequest(req, {\n allowedDomains: app.getAllowedDomains?.() ?? [],\n ...(bodySizeLimit !== undefined && { bodySizeLimit }),\n port: options.port,\n });\n } catch (err) {\n log.error(err instanceof Error ? { err, url: req.url } : { reason: err, url: req.url }, 'could not render');\n\n res.statusCode = 500;\n res.end('Internal Server Error');\n\n return;\n }\n\n const routeData = app.match(request, true);\n const matched = routeData && !(routeData.type === 'page' && routeData.prerender) ? routeData : undefined;\n\n if (matched) {\n setRequestRouteData(request, matched);\n }\n\n const response = matched\n ? await app.render(request, { addCookieHeader: true, routeData: matched, prerenderedErrorPageFetch })\n : await app.render(request, { addCookieHeader: true, prerenderedErrorPageFetch });\n\n await writeResponse(response, res);\n };\n}\n","import fs from 'node:fs';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport path from 'node:path';\nimport type { BaseApp } from 'astro/app';\nimport send from 'send';\nimport { COMPRESSIBLE, MIME_TYPES } from './mime.js';\n\nconst VARIANTS = [\n { encoding: 'br', suffix: '.br' },\n { encoding: 'gzip', suffix: '.gz' },\n] as const;\n\nfunction negotiateVariant(\n req: IncomingMessage,\n client: string,\n pathname: string,\n): { pathname: string; encoding: string } | undefined {\n const accept = req.headers['accept-encoding'];\n\n if (typeof accept !== 'string') return undefined;\n\n for (const { encoding, suffix } of VARIANTS) {\n if (!accept.includes(encoding)) continue;\n\n if (fs.existsSync(path.join(client, `${pathname}${suffix}`))) {\n return { pathname: `${pathname}${suffix}`, encoding };\n }\n }\n\n return undefined;\n}\n\nfunction hasFileExtension(pathname: string): boolean {\n const last = pathname.split('/').pop();\n\n return !!last && last.includes('.');\n}\n\nfunction prependForwardSlash(pathname: string): string {\n return pathname.startsWith('/') ? pathname : `/${pathname}`;\n}\n\nfunction isDirectory(client: string, urlPath: string): boolean {\n const filePath = path.join(client, urlPath);\n const resolved = path.resolve(filePath);\n const resolvedClient = path.resolve(client);\n\n // path traversal guard\n if (resolved !== resolvedClient && !resolved.startsWith(resolvedClient + path.sep)) {\n return false;\n }\n\n try {\n return fs.lstatSync(filePath).isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * Serve files from the client build directory, falling through to `ssr` when\n * no file matches. Handles trailing-slash redirects per the manifest config\n * and marks hashed assets as immutable.\n */\nexport function createStaticHandler(app: BaseApp, client: string) {\n return (req: IncomingMessage, res: ServerResponse, ssr: () => void): void => {\n if (!req.url) {\n ssr();\n\n return;\n }\n\n let fullUrl = req.url;\n\n if (fullUrl.includes('#')) {\n fullUrl = fullUrl.slice(0, fullUrl.indexOf('#'));\n }\n\n const [urlPath = '', urlQuery] = fullUrl.split('?');\n let fsPath = app.removeBase(urlPath);\n\n try {\n fsPath = decodeURI(fsPath);\n } catch {\n // fall through with the raw path; send() rejects malformed paths itself\n }\n\n const dir = isDirectory(client, fsPath);\n const hasSlash = urlPath.endsWith('/');\n let pathname = urlPath;\n\n switch (app.manifest.trailingSlash) {\n case 'never': {\n if (dir && urlPath !== '/' && hasSlash) {\n res.statusCode = 301;\n res.setHeader('Location', urlPath.slice(0, -1) + (urlQuery ? `?${urlQuery}` : ''));\n res.end();\n\n return;\n }\n\n if (dir && !hasSlash) {\n pathname = `${urlPath}/index.html`;\n }\n\n break;\n }\n case 'ignore': {\n if (dir && !hasSlash) {\n pathname = `${urlPath}/index.html`;\n }\n\n break;\n }\n case 'always': {\n if (!hasSlash && !hasFileExtension(urlPath) && !urlPath.startsWith('/_')) {\n res.statusCode = 301;\n res.setHeader('Location', `${urlPath}/${urlQuery ? `?${urlQuery}` : ''}`);\n res.end();\n\n return;\n }\n\n break;\n }\n }\n\n pathname = prependForwardSlash(app.removeBase(pathname));\n\n const normalizedPathname = path.posix.normalize(pathname);\n const compressible = COMPRESSIBLE.has(path.posix.extname(normalizedPathname));\n const variant = compressible ? negotiateVariant(req, client, normalizedPathname) : undefined;\n\n const stream = send(req, variant?.pathname ?? normalizedPathname, {\n root: client,\n dotfiles: normalizedPathname.startsWith('/.well-known/') ? 'allow' : 'deny',\n // with build.format 'file' or 'preserve', pages are output as `page.html`\n // instead of `page/index.html` — let send() try appending `.html`\n extensions: app.manifest.buildFormat === 'file' || app.manifest.buildFormat === 'preserve' ? ['html'] : [],\n });\n\n let forwardError = false;\n\n stream.on('error', (err: NodeJS.ErrnoException & { statusCode?: number }) => {\n if (forwardError) {\n const status = err.statusCode ?? 500;\n\n if (status >= 500) {\n console.error(err.toString());\n }\n\n res.writeHead(status);\n res.end(status >= 500 ? 'Internal server error' : '');\n\n return;\n }\n\n ssr();\n });\n\n stream.on('file', () => {\n forwardError = true;\n });\n\n // fires before the body and before conditional-GET handling, so these\n // headers also land on 304 responses\n stream.on('headers', (headersRes: ServerResponse) => {\n if (compressible) {\n headersRes.setHeader('Vary', 'Accept-Encoding');\n }\n\n if (variant) {\n headersRes.setHeader('Content-Encoding', variant.encoding);\n headersRes.setHeader(\n 'Content-Type',\n MIME_TYPES.get(path.posix.extname(normalizedPathname)) ?? 'application/octet-stream',\n );\n }\n\n if (normalizedPathname.startsWith(`/${app.manifest.assetsDir}/`)) {\n headersRes.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n }\n });\n\n stream.pipe(res);\n };\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport https from 'node:https';\nimport { defined } from '@entwico/dash';\nimport { checks, server as healthServer, probes } from '@entwico/health-probes';\nimport { SpanStatusCode } from '@opentelemetry/api';\nimport { createApp } from 'astro/app/entrypoint';\nimport { setGetEnv } from 'astro/env/setup';\n// @ts-expect-error virtual module provided by the integration\nimport { options } from 'virtual:@astroscope/node/config';\nimport { activateHealthChecks, deactivateHealthChecks } from '../health/store.js';\nimport { setBootContext } from '../lifecycle/context.js';\nimport { type BootModule, runShutdown, runStartup } from '../lifecycle/lifecycle.js';\nimport type { BootContext } from '../lifecycle/types.js';\nimport { createRequestInstrumentation } from '../observability/instrument.js';\nimport { dumpEarlyLogs } from '../observability/log/construct.js';\nimport { log } from '../observability/log/index.js';\nimport { shutdownTelemetry } from '../observability/telemetry/sdk.js';\nimport { type StartedSpan, startSpan, withSpan } from '../observability/telemetry/telemetry.js';\nimport { preparePlatform } from '../platform/prepare.js';\nimport type { RuntimeOptions } from '../types.js';\nimport { resolveClientDir } from './client-dir.js';\nimport { redirectDuplicateSlashes } from './duplicate-slashes.js';\nimport { clearNativeMounts, dispatchNativeMount } from './native-mount.js';\nimport { createAppHandler } from './serve-app.js';\nimport { createStaticHandler } from './serve-static.js';\n\nsetGetEnv((key) => process.env[key]);\n\nconst runtimeOptions = options as RuntimeOptions;\nconst app = createApp({ streaming: true });\n\nconst roundMs = (n: number) => Math.round(n * 100) / 100;\n\n/**\n * Pre-import every lazily loaded server module (pages, middleware, actions,\n * session driver) so the first request pays no import cost. Uses the\n * manifest's own loaders — exactly what the runtime calls per request.\n */\nasync function warmupModules(): Promise<void> {\n const loaders = [\n ...(app.manifest.pageMap?.values() ?? []),\n app.manifest.middleware,\n app.manifest.actions,\n app.manifest.sessionDriver,\n app.manifest.serverIslandMappings,\n ].filter(defined);\n\n const results = await Promise.allSettled(loaders.map((load) => load()));\n const failures = results.filter((result) => result.status === 'rejected');\n\n if (failures.length === 0) return;\n\n for (const failure of failures) {\n log.error(\n failure.reason instanceof Error ? { err: failure.reason } : { reason: failure.reason },\n 'warmup import failed',\n );\n }\n\n // a module that cannot even be imported would throw on its first request;\n // failing the boot turns a silently-degraded deploy into a crash the health\n // checks catch before it takes traffic\n throw new AggregateError(\n failures.map((failure) => failure.reason),\n 'warmup import failed',\n );\n}\n\n/**\n * TLS tokens from `SERVER_CERT_PATH` / `SERVER_KEY_PATH` (same contract as\n * `@astrojs/node`). Read after env loading, so the paths may come from `.env`.\n */\nfunction loadTlsOptions(): { cert: Buffer; key: Buffer } | undefined {\n const certPath = process.env['SERVER_CERT_PATH'];\n const keyPath = process.env['SERVER_KEY_PATH'];\n\n if (!certPath && !keyPath) return undefined;\n\n if (!certPath || !keyPath) {\n throw new Error('SERVER_CERT_PATH and SERVER_KEY_PATH must both be set to serve HTTPS');\n }\n\n return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };\n}\n\nexport interface ServerHandle {\n host: string;\n port: number;\n stop(): Promise<void>;\n closed(): Promise<void>;\n}\n\nexport async function startServer(overrides?: {\n host?: string | undefined;\n port?: number | undefined;\n}): Promise<ServerHandle> {\n const startedAt = performance.now();\n const host = overrides?.host ?? process.env['HOST'] ?? runtimeOptions.host;\n const port = overrides?.port ?? (process.env['PORT'] ? Number(process.env['PORT']) : runtimeOptions.port);\n const context: BootContext = { dev: false, host, port };\n const health = runtimeOptions.health;\n\n setBootContext(context);\n\n try {\n await preparePlatform({\n dev: false,\n telemetry: runtimeOptions.telemetry ? { prometheus: runtimeOptions.telemetry.prometheus } : false,\n seams: {\n config: () => import('virtual:@astroscope/node/config-entry'),\n instrumentation: () => import('virtual:@astroscope/node/instrumentation-entry'),\n log: () => import('virtual:@astroscope/node/log-entry'),\n },\n });\n } catch (err) {\n // the logger never came up — no silent phase, dump the buffer and die\n dumpEarlyLogs();\n console.error(err);\n process.exit(1);\n }\n\n if (health) {\n healthServer.start({ ...health, host: health.host ?? process.env['HEALTH_HOST'] ?? '0.0.0.0' });\n probes.live.enable();\n activateHealthChecks(checks);\n log.debug('health probes listening');\n }\n\n const startup = startSpan('startup');\n\n log.info({ host, port }, 'starting');\n\n // the boot module graph may read config at import time, so it must only be\n // evaluated after preparePlatform() has loaded env and config\n let bootModule: BootModule = {};\n let bootMs = 0;\n let warmupMs = 0;\n\n // starts in parallel with the boot startup, awaited before listen. resolves\n // to the failure (if any) instead of rejecting, so a warmup error landing\n // before the join below is never seen as an unhandled rejection\n const warmupStartedAt = performance.now();\n const warmupSpan = startSpan('warmup', { parent: startup.context });\n const warmup = warmupModules().then(\n () => {\n warmupMs = roundMs(performance.now() - warmupStartedAt);\n warmupSpan.span.end();\n\n return undefined;\n },\n (error: unknown) => {\n warmupMs = roundMs(performance.now() - warmupStartedAt);\n warmupSpan.span.setStatus({ code: SpanStatusCode.ERROR, message: 'warmup import failed' });\n warmupSpan.span.end();\n\n return error;\n },\n );\n\n const shutdownLifecycle = async (shutdownContext?: StartedSpan['context']): Promise<void> => {\n try {\n if (shutdownContext) {\n await withSpan('onShutdown', { parent: shutdownContext }, () => runShutdown(bootModule, context));\n } else {\n await runShutdown(bootModule, context);\n }\n } catch (err) {\n log.error(err instanceof Error ? { err } : { reason: err }, 'shutdown failed');\n }\n\n clearNativeMounts();\n\n if (health) {\n deactivateHealthChecks();\n\n try {\n await healthServer.stop();\n } catch (err) {\n // a startup failure can tear the health server down before it has\n // finished binding; stopping it is best-effort\n log.debug(err instanceof Error ? { err } : { reason: err }, 'health probe server stop failed');\n }\n }\n };\n\n const failStartup = async (err: unknown, message: string): Promise<never> => {\n log.error(err instanceof Error ? { err } : { reason: err }, message);\n startup.span.setStatus({ code: SpanStatusCode.ERROR, message });\n startup.span.end();\n\n await shutdownLifecycle();\n await shutdownTelemetry();\n process.exit(1);\n };\n\n try {\n const bootStartedAt = performance.now();\n\n // @ts-expect-error virtual module provided by the integration\n bootModule = (await import('virtual:@astroscope/node/boot')) as BootModule;\n\n await withSpan('boot', { parent: startup.context }, () => runStartup(bootModule, context));\n\n bootMs = roundMs(performance.now() - bootStartedAt);\n } catch (err) {\n await failStartup(err, 'startup failed');\n }\n\n const warmupError = await warmup;\n\n if (warmupError !== undefined) {\n await failStartup(warmupError, 'warmup import failed');\n }\n\n if (health) probes.startup.enable();\n\n const client = resolveClientDir(runtimeOptions, import.meta.url);\n const appHandler = createAppHandler(app, runtimeOptions, client);\n const staticHandler = createStaticHandler(app, client);\n const instrument = createRequestInstrumentation({\n logging: runtimeOptions.logging,\n telemetry: runtimeOptions.telemetry ? { exclude: runtimeOptions.telemetry.exclude } : false,\n });\n\n let tls: { cert: Buffer; key: Buffer } | undefined;\n\n try {\n tls = loadTlsOptions();\n } catch (err) {\n await failStartup(err, 'failed to load TLS options');\n }\n\n const listener: http.RequestListener = (req, res) => {\n try {\n decodeURI(req.url ?? '');\n } catch {\n res.writeHead(400);\n res.end('Bad request.');\n\n return;\n }\n\n instrument(req, res, () => {\n if (redirectDuplicateSlashes(req, res)) return;\n if (dispatchNativeMount(req, res)) return;\n\n staticHandler(req, res, () => void appHandler(req, res));\n });\n };\n\n const server = tls ? https.createServer(tls, listener) : http.createServer(listener);\n\n try {\n await withSpan('listen', { parent: startup.context }, () => {\n return new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, resolve);\n });\n });\n } catch (err) {\n await failStartup(err, `failed to listen on ${host}:${port}`);\n }\n\n if (health) probes.ready.enable();\n\n startup.span.setStatus({ code: SpanStatusCode.OK });\n startup.span.end();\n\n log.info(\n {\n host,\n port,\n ...(tls && { https: true }),\n health: !!health,\n bootMs,\n warmupMs,\n totalMs: roundMs(performance.now() - startedAt),\n },\n 'server ready',\n );\n\n let stopPromise: Promise<void> | undefined;\n let resolveClosed!: () => void;\n\n const closedPromise = new Promise<void>((resolve) => {\n resolveClosed = resolve;\n });\n\n const doStop = async (): Promise<void> => {\n if (health) probes.ready.disable();\n\n log.info('shutdown initiated');\n\n const drainStartedAt = performance.now();\n const shutdown = startSpan('shutdown');\n\n await withSpan('drain', { parent: shutdown.context }, async () => {\n const closed = new Promise<void>((resolve) => server.close(() => resolve()));\n\n server.closeIdleConnections();\n\n const forceTimer = setTimeout(() => server.closeAllConnections(), runtimeOptions.shutdownTimeout);\n\n await closed;\n\n clearTimeout(forceTimer);\n });\n\n const drainMs = roundMs(performance.now() - drainStartedAt);\n\n await shutdownLifecycle(shutdown.context);\n\n shutdown.span.end();\n\n log.info({ drainMs }, 'shutdown complete');\n\n await shutdownTelemetry();\n resolveClosed();\n };\n\n const stop = (): Promise<void> => (stopPromise ??= doStop());\n\n process.once('SIGTERM', () => void stop().then(() => process.exit(0)));\n process.once('SIGINT', () => void stop().then(() => process.exit(0)));\n\n return { host, port, stop, closed: () => closedPromise };\n}\n\nif (process.env['ASTROSCOPE_NODE_AUTOSTART'] !== 'disabled') {\n await startServer();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","names":["healthServer","server"],"sources":["../src/server/client-dir.ts","../src/server/serve-app.ts","../src/server/serve-static.ts","../src/server/server.ts"],"sourcesContent":["import path from 'node:path';\nimport url from 'node:url';\n\n/**\n * Resolve the client directory at runtime relative to the built server entry.\n *\n * The build-time client/server URLs are only valid on the build machine; in a\n * container the deploy path differs. Walk up from `import.meta.url` of the\n * bundled server code until the server directory is found, then apply the\n * build-time server→client relative path.\n */\nexport function resolveClientDir(options: { client: string; server: string }, importMetaUrl: string): string {\n const clientPath = url.fileURLToPath(new URL(options.client));\n const serverPath = url.fileURLToPath(new URL(options.server));\n const rel = path.relative(serverPath, clientPath);\n const serverFolder = path.basename(serverPath);\n\n let serverEntryFolderURL = path.dirname(importMetaUrl);\n let previous = '';\n\n while (!serverEntryFolderURL.endsWith(serverFolder)) {\n if (serverEntryFolderURL === previous) {\n throw new Error(\n `[@astroscope/node] could not find the server directory \"${serverFolder}\" by walking up from \"${importMetaUrl}\"`,\n );\n }\n\n previous = serverEntryFolderURL;\n serverEntryFolderURL = path.dirname(serverEntryFolderURL);\n }\n\n const clientURL = new URL(rel.endsWith('/') ? rel : `${rel}/`, `${serverEntryFolderURL}/entry.mjs`);\n\n return url.fileURLToPath(clientURL);\n}\n","import { createReadStream } from 'node:fs';\nimport type { IncomingMessage, OutgoingHttpHeaders, ServerResponse } from 'node:http';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\nimport type { BaseApp } from 'astro/app';\nimport { createRequestFromNodeRequest, getAbortControllerCleanup } from 'astro/app/node';\nimport { log } from '../observability/log/index.js';\nimport { getRequestRecord } from '../observability/log/store.js';\nimport type { RuntimeOptions } from '../types.js';\nimport { setRequestRouteData } from './route-store.js';\n\nasync function readFSErrorPage(client: string, status: number): Promise<Response | undefined> {\n const filePaths = [`${status}.html`, `${status}/index.html`];\n\n for (const filePath of filePaths) {\n const fullPath = path.join(client, filePath);\n let stream: ReturnType<typeof createReadStream> | undefined;\n\n try {\n stream = createReadStream(fullPath);\n\n await new Promise<void>((resolve, reject) => {\n stream!.once('open', () => resolve());\n stream!.once('error', reject);\n });\n\n return new Response(Readable.toWeb(stream) as ReadableStream, {\n headers: { 'Content-Type': 'text/html; charset=utf-8' },\n });\n } catch {\n stream?.destroy();\n }\n }\n\n return undefined;\n}\n\nfunction createOutgoingHttpHeaders(headers: Headers): OutgoingHttpHeaders | undefined {\n const nodeHeaders: OutgoingHttpHeaders = Object.fromEntries(headers.entries());\n\n if (Object.keys(nodeHeaders).length === 0) {\n return undefined;\n }\n\n // the entries iterator joins set-cookie values with a comma; node needs them as an array\n const cookies = headers.getSetCookie();\n\n if (cookies.length > 1) {\n nodeHeaders['set-cookie'] = cookies;\n }\n\n return nodeHeaders;\n}\n\n/**\n * Streams the web response into the node response. A render failing after the\n * first chunk cannot change the status anymore, so it is logged through the\n * request logger and marked on the request record — the completion line, the\n * span and `astro.render.failures` reflect it. On the wire it behaves like\n * astro's own writer: an `Internal server error` marker, then the socket is\n * destroyed.\n */\nexport async function writeResponse(response: Response, res: ServerResponse): Promise<void> {\n res.statusMessage = response.statusText;\n res.writeHead(response.status, createOutgoingHttpHeaders(response.headers));\n\n // astro parks the socket listener behind the request's abort signal on the node\n // request; releasing it once the response is done keeps keep-alive sockets from\n // accumulating one listener per request\n const cleanupAbort = getAbortControllerCleanup(res.req);\n\n if (cleanupAbort) {\n const runCleanup = (): void => {\n cleanupAbort();\n res.off('finish', runCleanup);\n res.off('close', runCleanup);\n };\n\n res.on('finish', runCleanup);\n res.on('close', runCleanup);\n }\n\n if (!response.body) {\n res.end();\n\n return;\n }\n\n const reader = response.body.getReader();\n\n // a client going away stops the render; on a failed stream the cancel rejects\n // with the render error, which the catch below has already reported\n res.on('close', () => {\n reader.cancel().catch(() => undefined);\n });\n\n try {\n for (let result = await reader.read(); !result.done; result = await reader.read()) {\n res.write(result.value);\n }\n\n res.end();\n } catch (err) {\n const record = getRequestRecord();\n\n if (record) {\n record.truncated = true;\n }\n\n log.error(\n {\n ...(err instanceof Error ? { err } : { reason: err }),\n ...(record?.route && { route: record.route }),\n ...(!record?.logger && { url: record?.url ?? res.req.url }),\n },\n 'render failed after the response started, response truncated',\n );\n\n res.write('Internal server error', () => {\n res.destroy(err instanceof Error ? err : undefined);\n });\n }\n}\n\n/**\n * Render on-demand routes: node req → web Request → `app.render()` → node res.\n * Prerendered pages never reach this handler (the static handler serves them);\n * requests for them landing here render the 404 route.\n */\nexport function createAppHandler(app: BaseApp, options: RuntimeOptions, client: string) {\n process.on('unhandledRejection', (reason) => {\n const requestUrl = getRequestRecord()?.url;\n\n log.error(\n {\n ...(reason instanceof Error ? { err: reason } : { reason }),\n ...(requestUrl && { url: requestUrl }),\n },\n requestUrl ? 'unhandled rejection while rendering' : 'unhandled rejection',\n );\n });\n\n const prerenderedErrorPageFetch = async (url: string): Promise<Response> => {\n const { pathname } = new URL(url);\n\n for (const status of [404, 500]) {\n if (pathname.endsWith(`/${status}.html`) || pathname.endsWith(`/${status}/index.html`)) {\n const response = await readFSErrorPage(client, status);\n\n if (response) return response;\n }\n }\n\n return new Response(null, { status: 404 });\n };\n\n const bodySizeLimit =\n options.bodySizeLimit === 0 || options.bodySizeLimit === Number.POSITIVE_INFINITY\n ? undefined\n : options.bodySizeLimit;\n\n return async (req: IncomingMessage, res: ServerResponse): Promise<void> => {\n let request: Request;\n\n try {\n request = createRequestFromNodeRequest(req, {\n allowedDomains: app.getAllowedDomains?.() ?? [],\n ...(bodySizeLimit !== undefined && { bodySizeLimit }),\n port: options.port,\n });\n } catch (err) {\n log.error(err instanceof Error ? { err, url: req.url } : { reason: err, url: req.url }, 'could not render');\n\n res.statusCode = 500;\n res.end('Internal Server Error');\n\n return;\n }\n\n const routeData = app.match(request, true);\n const matched = routeData && !(routeData.type === 'page' && routeData.prerender) ? routeData : undefined;\n\n // the one object astro keeps for the whole request, whatever rewrites replace `context.request` with\n const locals = {};\n\n if (matched) {\n setRequestRouteData(request, locals, matched);\n }\n\n const response = matched\n ? await app.render(request, { addCookieHeader: true, locals, routeData: matched, prerenderedErrorPageFetch })\n : await app.render(request, { addCookieHeader: true, locals, prerenderedErrorPageFetch });\n\n await writeResponse(response, res);\n };\n}\n","import fs from 'node:fs';\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport path from 'node:path';\nimport type { BaseApp } from 'astro/app';\nimport send from 'send';\nimport { COMPRESSIBLE, MIME_TYPES } from './mime.js';\n\nconst VARIANTS = [\n { encoding: 'br', suffix: '.br' },\n { encoding: 'gzip', suffix: '.gz' },\n] as const;\n\nfunction negotiateVariant(\n req: IncomingMessage,\n client: string,\n pathname: string,\n): { pathname: string; encoding: string } | undefined {\n const accept = req.headers['accept-encoding'];\n\n if (typeof accept !== 'string') return undefined;\n\n for (const { encoding, suffix } of VARIANTS) {\n if (!accept.includes(encoding)) continue;\n\n if (fs.existsSync(path.join(client, `${pathname}${suffix}`))) {\n return { pathname: `${pathname}${suffix}`, encoding };\n }\n }\n\n return undefined;\n}\n\nfunction hasFileExtension(pathname: string): boolean {\n const last = pathname.split('/').pop();\n\n return !!last && last.includes('.');\n}\n\nfunction prependForwardSlash(pathname: string): string {\n return pathname.startsWith('/') ? pathname : `/${pathname}`;\n}\n\nfunction isDirectory(client: string, urlPath: string): boolean {\n const filePath = path.join(client, urlPath);\n const resolved = path.resolve(filePath);\n const resolvedClient = path.resolve(client);\n\n // path traversal guard\n if (resolved !== resolvedClient && !resolved.startsWith(resolvedClient + path.sep)) {\n return false;\n }\n\n try {\n return fs.lstatSync(filePath).isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * Serve files from the client build directory, falling through to `ssr` when\n * no file matches. Handles trailing-slash redirects per the manifest config\n * and marks hashed assets as immutable.\n */\nexport function createStaticHandler(app: BaseApp, client: string) {\n return (req: IncomingMessage, res: ServerResponse, ssr: () => void): void => {\n if (!req.url) {\n ssr();\n\n return;\n }\n\n let fullUrl = req.url;\n\n if (fullUrl.includes('#')) {\n fullUrl = fullUrl.slice(0, fullUrl.indexOf('#'));\n }\n\n const [urlPath = '', urlQuery] = fullUrl.split('?');\n let fsPath = app.removeBase(urlPath);\n\n try {\n fsPath = decodeURI(fsPath);\n } catch {\n // fall through with the raw path; send() rejects malformed paths itself\n }\n\n const dir = isDirectory(client, fsPath);\n const hasSlash = urlPath.endsWith('/');\n let pathname = urlPath;\n\n switch (app.manifest.trailingSlash) {\n case 'never': {\n if (dir && urlPath !== '/' && hasSlash) {\n res.statusCode = 301;\n res.setHeader('Location', urlPath.slice(0, -1) + (urlQuery ? `?${urlQuery}` : ''));\n res.end();\n\n return;\n }\n\n if (dir && !hasSlash) {\n pathname = `${urlPath}/index.html`;\n }\n\n break;\n }\n case 'ignore': {\n if (dir && !hasSlash) {\n pathname = `${urlPath}/index.html`;\n }\n\n break;\n }\n case 'always': {\n if (!hasSlash && !hasFileExtension(urlPath) && !urlPath.startsWith('/_')) {\n res.statusCode = 301;\n res.setHeader('Location', `${urlPath}/${urlQuery ? `?${urlQuery}` : ''}`);\n res.end();\n\n return;\n }\n\n break;\n }\n }\n\n pathname = prependForwardSlash(app.removeBase(pathname));\n\n const normalizedPathname = path.posix.normalize(pathname);\n const compressible = COMPRESSIBLE.has(path.posix.extname(normalizedPathname));\n const variant = compressible ? negotiateVariant(req, client, normalizedPathname) : undefined;\n\n const stream = send(req, variant?.pathname ?? normalizedPathname, {\n root: client,\n dotfiles: normalizedPathname.startsWith('/.well-known/') ? 'allow' : 'deny',\n // with build.format 'file' or 'preserve', pages are output as `page.html`\n // instead of `page/index.html` — let send() try appending `.html`\n extensions: app.manifest.buildFormat === 'file' || app.manifest.buildFormat === 'preserve' ? ['html'] : [],\n });\n\n let forwardError = false;\n\n stream.on('error', (err: NodeJS.ErrnoException & { statusCode?: number }) => {\n if (forwardError) {\n const status = err.statusCode ?? 500;\n\n if (status >= 500) {\n console.error(err.toString());\n }\n\n res.writeHead(status);\n res.end(status >= 500 ? 'Internal server error' : '');\n\n return;\n }\n\n ssr();\n });\n\n stream.on('file', () => {\n forwardError = true;\n });\n\n // fires before the body and before conditional-GET handling, so these\n // headers also land on 304 responses\n stream.on('headers', (headersRes: ServerResponse) => {\n if (compressible) {\n headersRes.setHeader('Vary', 'Accept-Encoding');\n }\n\n if (variant) {\n headersRes.setHeader('Content-Encoding', variant.encoding);\n headersRes.setHeader(\n 'Content-Type',\n MIME_TYPES.get(path.posix.extname(normalizedPathname)) ?? 'application/octet-stream',\n );\n }\n\n if (normalizedPathname.startsWith(`/${app.manifest.assetsDir}/`)) {\n headersRes.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n }\n });\n\n stream.pipe(res);\n };\n}\n","import fs from 'node:fs';\nimport http from 'node:http';\nimport https from 'node:https';\nimport { defined } from '@entwico/dash';\nimport { checks, server as healthServer, probes } from '@entwico/health-probes';\nimport { SpanStatusCode } from '@opentelemetry/api';\nimport { createApp } from 'astro/app/entrypoint';\nimport { setGetEnv } from 'astro/env/setup';\n// @ts-expect-error virtual module provided by the integration\nimport { options } from 'virtual:@astroscope/node/config';\nimport { activateHealthChecks, deactivateHealthChecks } from '../health/store.js';\nimport { setBootContext } from '../lifecycle/context.js';\nimport { type BootModule, runShutdown, runStartup } from '../lifecycle/lifecycle.js';\nimport type { BootContext } from '../lifecycle/types.js';\nimport { createRequestInstrumentation } from '../observability/instrument.js';\nimport { dumpEarlyLogs } from '../observability/log/construct.js';\nimport { log } from '../observability/log/index.js';\nimport { shutdownTelemetry } from '../observability/telemetry/sdk.js';\nimport { type StartedSpan, startSpan, withSpan } from '../observability/telemetry/telemetry.js';\nimport { preparePlatform } from '../platform/prepare.js';\nimport type { RuntimeOptions } from '../types.js';\nimport { resolveClientDir } from './client-dir.js';\nimport { redirectDuplicateSlashes } from './duplicate-slashes.js';\nimport { clearNativeMounts, dispatchNativeMount } from './native-mount.js';\nimport { createAppHandler } from './serve-app.js';\nimport { createStaticHandler } from './serve-static.js';\n\nsetGetEnv((key) => process.env[key]);\n\nconst runtimeOptions = options as RuntimeOptions;\nconst app = createApp({ streaming: true });\n\nconst roundMs = (n: number) => Math.round(n * 100) / 100;\n\n/**\n * Pre-import every lazily loaded server module (pages, middleware, actions,\n * session driver) so the first request pays no import cost. Uses the\n * manifest's own loaders — exactly what the runtime calls per request.\n */\nasync function warmupModules(): Promise<void> {\n const loaders = [\n ...(app.manifest.pageMap?.values() ?? []),\n app.manifest.middleware,\n app.manifest.actions,\n app.manifest.sessionDriver,\n app.manifest.serverIslandMappings,\n ].filter(defined);\n\n const results = await Promise.allSettled(loaders.map((load) => load()));\n const failures = results.filter((result) => result.status === 'rejected');\n\n if (failures.length === 0) return;\n\n for (const failure of failures) {\n log.error(\n failure.reason instanceof Error ? { err: failure.reason } : { reason: failure.reason },\n 'warmup import failed',\n );\n }\n\n // a module that cannot even be imported would throw on its first request;\n // failing the boot turns a silently-degraded deploy into a crash the health\n // checks catch before it takes traffic\n throw new AggregateError(\n failures.map((failure) => failure.reason),\n 'warmup import failed',\n );\n}\n\n/**\n * TLS tokens from `SERVER_CERT_PATH` / `SERVER_KEY_PATH` (same contract as\n * `@astrojs/node`). Read after env loading, so the paths may come from `.env`.\n */\nfunction loadTlsOptions(): { cert: Buffer; key: Buffer } | undefined {\n const certPath = process.env['SERVER_CERT_PATH'];\n const keyPath = process.env['SERVER_KEY_PATH'];\n\n if (!certPath && !keyPath) return undefined;\n\n if (!certPath || !keyPath) {\n throw new Error('SERVER_CERT_PATH and SERVER_KEY_PATH must both be set to serve HTTPS');\n }\n\n return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };\n}\n\nexport interface ServerHandle {\n host: string;\n port: number;\n stop(): Promise<void>;\n closed(): Promise<void>;\n}\n\nexport async function startServer(overrides?: {\n host?: string | undefined;\n port?: number | undefined;\n}): Promise<ServerHandle> {\n const startedAt = performance.now();\n const host = overrides?.host ?? process.env['HOST'] ?? runtimeOptions.host;\n const port = overrides?.port ?? (process.env['PORT'] ? Number(process.env['PORT']) : runtimeOptions.port);\n const context: BootContext = { dev: false, host, port };\n const health = runtimeOptions.health;\n\n setBootContext(context);\n\n try {\n await preparePlatform({\n dev: false,\n telemetry: runtimeOptions.telemetry ? { prometheus: runtimeOptions.telemetry.prometheus } : false,\n seams: {\n config: () => import('virtual:@astroscope/node/config-entry'),\n instrumentation: () => import('virtual:@astroscope/node/instrumentation-entry'),\n log: () => import('virtual:@astroscope/node/log-entry'),\n },\n });\n } catch (err) {\n // the logger never came up — no silent phase, dump the buffer and die\n dumpEarlyLogs();\n console.error(err);\n process.exit(1);\n }\n\n if (health) {\n healthServer.start({ ...health, host: health.host ?? process.env['HEALTH_HOST'] ?? '0.0.0.0' });\n probes.live.enable();\n activateHealthChecks(checks);\n log.debug('health probes listening');\n }\n\n const startup = startSpan('startup');\n\n log.info({ host, port }, 'starting');\n\n // the boot module graph may read config at import time, so it must only be\n // evaluated after preparePlatform() has loaded env and config\n let bootModule: BootModule = {};\n let bootMs = 0;\n let warmupMs = 0;\n\n // starts in parallel with the boot startup, awaited before listen. resolves\n // to the failure (if any) instead of rejecting, so a warmup error landing\n // before the join below is never seen as an unhandled rejection\n const warmupStartedAt = performance.now();\n const warmupSpan = startSpan('warmup', { parent: startup.context });\n const warmup = warmupModules().then(\n () => {\n warmupMs = roundMs(performance.now() - warmupStartedAt);\n warmupSpan.span.end();\n\n return undefined;\n },\n (error: unknown) => {\n warmupMs = roundMs(performance.now() - warmupStartedAt);\n warmupSpan.span.setStatus({ code: SpanStatusCode.ERROR, message: 'warmup import failed' });\n warmupSpan.span.end();\n\n return error;\n },\n );\n\n const shutdownLifecycle = async (shutdownContext?: StartedSpan['context']): Promise<void> => {\n try {\n if (shutdownContext) {\n await withSpan('onShutdown', { parent: shutdownContext }, () => runShutdown(bootModule, context));\n } else {\n await runShutdown(bootModule, context);\n }\n } catch (err) {\n log.error(err instanceof Error ? { err } : { reason: err }, 'shutdown failed');\n }\n\n clearNativeMounts();\n\n if (health) {\n deactivateHealthChecks();\n\n try {\n await healthServer.stop();\n } catch (err) {\n // a startup failure can tear the health server down before it has\n // finished binding; stopping it is best-effort\n log.debug(err instanceof Error ? { err } : { reason: err }, 'health probe server stop failed');\n }\n }\n };\n\n const failStartup = async (err: unknown, message: string): Promise<never> => {\n log.error(err instanceof Error ? { err } : { reason: err }, message);\n startup.span.setStatus({ code: SpanStatusCode.ERROR, message });\n startup.span.end();\n\n await shutdownLifecycle();\n await shutdownTelemetry();\n process.exit(1);\n };\n\n try {\n const bootStartedAt = performance.now();\n\n // @ts-expect-error virtual module provided by the integration\n bootModule = (await import('virtual:@astroscope/node/boot')) as BootModule;\n\n await withSpan('boot', { parent: startup.context }, () => runStartup(bootModule, context));\n\n bootMs = roundMs(performance.now() - bootStartedAt);\n } catch (err) {\n await failStartup(err, 'startup failed');\n }\n\n const warmupError = await warmup;\n\n if (warmupError !== undefined) {\n await failStartup(warmupError, 'warmup import failed');\n }\n\n if (health) probes.startup.enable();\n\n const client = resolveClientDir(runtimeOptions, import.meta.url);\n const appHandler = createAppHandler(app, runtimeOptions, client);\n const staticHandler = createStaticHandler(app, client);\n const instrument = createRequestInstrumentation({\n logging: runtimeOptions.logging,\n telemetry: runtimeOptions.telemetry ? { exclude: runtimeOptions.telemetry.exclude } : false,\n });\n\n let tls: { cert: Buffer; key: Buffer } | undefined;\n\n try {\n tls = loadTlsOptions();\n } catch (err) {\n await failStartup(err, 'failed to load TLS options');\n }\n\n const listener: http.RequestListener = (req, res) => {\n try {\n decodeURI(req.url ?? '');\n } catch {\n res.writeHead(400);\n res.end('Bad request.');\n\n return;\n }\n\n instrument(req, res, () => {\n if (redirectDuplicateSlashes(req, res)) return;\n if (dispatchNativeMount(req, res)) return;\n\n staticHandler(req, res, () => void appHandler(req, res));\n });\n };\n\n const server = tls ? https.createServer(tls, listener) : http.createServer(listener);\n\n try {\n await withSpan('listen', { parent: startup.context }, () => {\n return new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, resolve);\n });\n });\n } catch (err) {\n await failStartup(err, `failed to listen on ${host}:${port}`);\n }\n\n if (health) probes.ready.enable();\n\n startup.span.setStatus({ code: SpanStatusCode.OK });\n startup.span.end();\n\n log.info(\n {\n host,\n port,\n ...(tls && { https: true }),\n health: !!health,\n bootMs,\n warmupMs,\n totalMs: roundMs(performance.now() - startedAt),\n },\n 'server ready',\n );\n\n let stopPromise: Promise<void> | undefined;\n let resolveClosed!: () => void;\n\n const closedPromise = new Promise<void>((resolve) => {\n resolveClosed = resolve;\n });\n\n const doStop = async (): Promise<void> => {\n if (health) probes.ready.disable();\n\n log.info('shutdown initiated');\n\n const drainStartedAt = performance.now();\n const shutdown = startSpan('shutdown');\n\n await withSpan('drain', { parent: shutdown.context }, async () => {\n const closed = new Promise<void>((resolve) => server.close(() => resolve()));\n\n server.closeIdleConnections();\n\n const forceTimer = setTimeout(() => server.closeAllConnections(), runtimeOptions.shutdownTimeout);\n\n await closed;\n\n clearTimeout(forceTimer);\n });\n\n const drainMs = roundMs(performance.now() - drainStartedAt);\n\n await shutdownLifecycle(shutdown.context);\n\n shutdown.span.end();\n\n log.info({ drainMs }, 'shutdown complete');\n\n await shutdownTelemetry();\n resolveClosed();\n };\n\n const stop = (): Promise<void> => (stopPromise ??= doStop());\n\n process.once('SIGTERM', () => void stop().then(() => process.exit(0)));\n process.once('SIGINT', () => void stop().then(() => process.exit(0)));\n\n return { host, port, stop, closed: () => closedPromise };\n}\n\nif (process.env['ASTROSCOPE_NODE_AUTOSTART'] !== 'disabled') {\n await startServer();\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astroscope/node",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "Opinionated, cloud-friendly Node adapter for Astro: boot lifecycle, health probes, request logging, telemetry, CSRF and static serving run as plain code around server.listen()",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"route-store-DdxGePj2.js","names":[],"sources":["../src/server/route-store.ts"],"sourcesContent":["import type { RouteData } from 'astro';\n\n/**\n * The route matched for a request, stashed by the server handler before\n * rendering so middleware can tell what kind of route produced a response —\n * a `.astro` page or an endpoint that happens to return html (a proxy\n * catch-all, an html-returning `.ts` route). Keyed on `globalThis` via\n * `Symbol.for` so the vite-runner and native module instances share it —\n * same pattern as the log store.\n *\n * Absent in dev (no adapter handler) — consumers fall back to their\n * content-type gates.\n */\nconst STORE = Symbol.for('@astroscope/node.requestRoutes');\n\ntype Scope = { [STORE]?: WeakMap<Request, RouteData> };\n\nfunction store(): WeakMap<Request, RouteData> {\n const scope = globalThis as Scope;\n\n return (scope[STORE] ??= new WeakMap());\n}\n\nexport function setRequestRouteData(request: Request, routeData: RouteData): void {\n store().set(request, routeData);\n}\n\nexport function getRequestRouteData(request: Request): RouteData | undefined {\n return store().get(request);\n}\n"],"mappings":";;;;;;;;;;;;AAaA,MAAM,QAAQ,OAAO,IAAI,gCAAgC;AAIzD,SAAS,QAAqC;CAC5C,MAAM,QAAQ;CAEd,OAAQ,MAAM,2BAAW,IAAI,QAAQ;AACvC;AAEA,SAAgB,oBAAoB,SAAkB,WAA4B;CAChF,MAAM,CAAC,CAAC,IAAI,SAAS,SAAS;AAChC;AAEA,SAAgB,oBAAoB,SAAyC;CAC3E,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO;AAC5B"}
|