@astroscope/node 1.2.2 → 1.4.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/README.md +21 -0
- package/dist/boot.d.ts +0 -1
- package/dist/boot.d.ts.map +1 -1
- package/dist/{construct-DgB-jR0a.d.ts → construct-BGlPfWMF.d.ts} +1 -2
- package/dist/construct-BGlPfWMF.d.ts.map +1 -0
- package/dist/csrf-middleware-entrypoint.d.ts.map +1 -1
- package/dist/dev-middleware-entrypoint.d.ts +0 -1
- package/dist/dev-middleware-entrypoint.d.ts.map +1 -1
- package/dist/{events-CUzQ2_cp.d.ts → events-u7J3ezJR.d.ts} +1 -2
- package/dist/events-u7J3ezJR.d.ts.map +1 -0
- package/dist/{excludes-DLF3A_Cf.d.ts → excludes-BDiE3eyp.d.ts} +1 -2
- package/dist/excludes-BDiE3eyp.d.ts.map +1 -0
- package/dist/excludes.d.ts +1 -1
- package/dist/health.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/events.d.ts +1 -1
- package/dist/log/index.d.ts +33 -3
- package/dist/log/index.d.ts.map +1 -1
- package/dist/log/index.js +3 -2
- package/dist/{log-CSJlKaxY.js → log-B69HEBvg.js} +2 -2
- package/dist/{log-CSJlKaxY.js.map → log-B69HEBvg.js.map} +1 -1
- package/dist/{native-mount-hhwWdLtL.js → native-mount-DjYEnO4X.js} +4 -13
- package/dist/native-mount-DjYEnO4X.js.map +1 -0
- package/dist/native.d.ts +0 -1
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js +1 -1
- package/dist/{prepare-DQEf2Bnt.js → prepare-CXZsyAVk.js} +6 -4
- package/dist/prepare-CXZsyAVk.js.map +1 -0
- package/dist/preview.d.ts +0 -1
- package/dist/preview.d.ts.map +1 -1
- package/dist/request-route-DcnZOOM4.js +92 -0
- package/dist/request-route-DcnZOOM4.js.map +1 -0
- package/dist/route-middleware-entrypoint.d.ts +3 -2
- package/dist/route-middleware-entrypoint.d.ts.map +1 -1
- package/dist/route-middleware-entrypoint.js +5 -11
- package/dist/route-middleware-entrypoint.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +23 -8
- package/dist/server.js.map +1 -1
- package/dist/types-D0uMBi2M.d.ts.map +1 -1
- package/package.json +8 -7
- package/dist/construct-DgB-jR0a.d.ts.map +0 -1
- package/dist/events-CUzQ2_cp.d.ts.map +0 -1
- package/dist/excludes-DLF3A_Cf.d.ts.map +0 -1
- package/dist/native-mount-hhwWdLtL.js.map +0 -1
- package/dist/prepare-DQEf2Bnt.js.map +0 -1
- package/dist/store-BIUF4lqk.js +0 -29
- package/dist/store-BIUF4lqk.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/dev-mode/serialize-error.ts","../src/dev-mode/scheduler.ts","../src/dev-mode/vite-env.ts","../src/dev-mode/ignored.ts","../src/dev-mode/watch.ts","../src/dev-mode/machinery.ts","../src/excludes/serialize.ts","../src/tweaks/sourcemap.ts","../src/tweaks/strip-effects.ts","../src/integration/integration.ts"],"sourcesContent":["export function serializeError(error: unknown): string {\n if (error instanceof Error) {\n return error.stack ?? error.message;\n }\n\n return JSON.stringify(error);\n}\n","import path from 'node:path';\nimport type { ViteDevServer } from 'vite';\nimport { serializeError } from './serialize-error.js';\n\ntype Logger = { info(msg: string): void; error(msg: string): void };\n\nconst FULL_RELOAD_UNKNOWN = '<unknown>';\n\n/**\n * Coordinates dev-server restarts: debounces bursts, chains a follow-up if\n * changes arrive mid-restart (vite's `ssrImport` reads disk at import time,\n * so changes during a restart would otherwise be missed), and logs once per\n * restart with what triggered it.\n *\n * One instance per integration, shared across restart-induced configureServer\n * reruns — chain coordination would be lost if recreated each time.\n */\nexport class RestartScheduler {\n private _inFlight = false;\n private _pending = false;\n private _debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private _pendingBootDeps = new Set<string>();\n private _pendingFullReloads = new Set<string>();\n // set while a restart chain is running. the gate probes it (`isRestartPending`)\n // to short-circuit requests, and awaits it (`waitForRestart`) on readiness.\n private _runPromise: Promise<void> | undefined;\n // set when a restart attempt fails\n private _lastFailure: { message: string } | undefined;\n\n constructor(\n private readonly debounceMs: number,\n private readonly logger: Logger,\n ) {}\n\n // true from the moment a change is queued until the restart completes — covers\n // the debounce window too, so requests don't slip past the gate before _run starts.\n isRestartPending(): boolean {\n return !!this._runPromise || !!this._debounceTimer || !!this._lastFailure;\n }\n\n getLastFailure(): { message: string } | undefined {\n return this._lastFailure;\n }\n\n recordFailure(message: string): void {\n this._lastFailure = { message };\n }\n\n clearFailure(): void {\n this._lastFailure = undefined;\n }\n\n schedule(server: ViteDevServer, changedPath: string): void {\n this._pendingBootDeps.add(changedPath);\n this._scheduleRun(server);\n }\n\n scheduleFullReload(server: ViteDevServer, triggeredBy?: string): void {\n this._pendingFullReloads.add(triggeredBy ?? FULL_RELOAD_UNKNOWN);\n this._scheduleRun(server);\n }\n\n /**\n * Resolves when no restart is running. Loops to handle back-to-back restarts\n * (e.g. one chain ends and a queued debounce timer immediately fires a new\n * one). Never rejects, so a failed restart still releases the gate — caller\n * proceeds against the broken state rather than hanging forever.\n */\n async waitForRestart(): Promise<void> {\n while (this._runPromise) {\n try {\n await this._runPromise;\n } catch {\n // restart failed — release anyway\n }\n }\n }\n\n private _scheduleRun(server: ViteDevServer): void {\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = undefined;\n void this._run(server);\n }, this.debounceMs);\n }\n\n private async _run(server: ViteDevServer): Promise<void> {\n if (this._inFlight) {\n // loop driving the in-flight restart will pick up the next iteration.\n this._pending = true;\n\n return;\n }\n\n this._inFlight = true;\n\n let resolveRun!: () => void;\n\n this._runPromise = new Promise<void>((resolve) => {\n resolveRun = resolve;\n });\n\n try {\n do {\n this._pending = false;\n\n const bootDeps = [...this._pendingBootDeps].sort();\n const fullReloads = [...this._pendingFullReloads].sort();\n\n this._pendingBootDeps.clear();\n this._pendingFullReloads.clear();\n\n if (bootDeps.length > 0 || fullReloads.length > 0) {\n this.logger.info(this._formatReason(server, bootDeps, fullReloads));\n }\n\n try {\n await server.restart();\n } catch (error) {\n this.logger.error(`error during dev server restart: ${serializeError(error)}`);\n }\n } while (this._pending);\n } finally {\n this._inFlight = false;\n this._runPromise = undefined;\n resolveRun();\n }\n }\n\n private _formatReason(server: ViteDevServer, bootDeps: string[], fullReloads: string[]): string {\n const root = server.config.root;\n const rel = (p: string): string => path.relative(root, p) || p;\n const parts: string[] = [];\n\n if (bootDeps.length === 1) {\n parts.push(`boot dep changed: ${rel(bootDeps[0]!)}`);\n } else if (bootDeps.length > 1) {\n parts.push(`boot deps changed (${bootDeps.length}): ${bootDeps.map(rel).join(', ')}`);\n }\n\n if (fullReloads.length > 0) {\n const named = fullReloads.filter((p) => p !== FULL_RELOAD_UNKNOWN);\n\n if (named.length === 0) {\n parts.push('vite SSR full-reload');\n } else {\n parts.push(`vite SSR full-reload (triggered by ${named.map(rel).join(', ')})`);\n }\n }\n\n return `${parts.join(' + ')} — restarting dev server`;\n }\n}\n","import type { DevEnvironment, ViteDevServer } from 'vite';\n\ntype RunnableEnv = DevEnvironment & { runner: { import: (id: string) => Promise<unknown> } };\n\n/**\n * duck-typed runnable-env check. avoids `isRunnableDevEnvironment` which relies on\n * `instanceof RunnableDevEnvironment` — that breaks when the consumer and vite host\n * resolve to different vite installs (e.g. linked packages outside the workspace).\n */\nfunction isRunnable(env: DevEnvironment | undefined): env is RunnableEnv {\n return (\n !!env &&\n typeof (env as { runner?: unknown }).runner === 'object' &&\n typeof (env as RunnableEnv).runner.import === 'function'\n );\n}\n\n/**\n * resolve a runnable dev environment — prefers `ssr`, falls back to `astro`.\n * astro 6 exposes a separate `astro` environment when `ssr` isn't runnable\n * (see astro/core/constants.ts ASTRO_VITE_ENVIRONMENT_NAMES).\n */\nfunction getRunnableEnv(server: ViteDevServer): RunnableEnv {\n const ssr = server.environments['ssr'];\n\n if (isRunnable(ssr)) return ssr;\n\n const astro = server.environments['astro'];\n\n if (isRunnable(astro)) return astro;\n\n const names = Object.keys(server.environments);\n\n throw new Error(`no runnable dev environment found — available: ${names.join(', ')}`);\n}\n\n/**\n * load a module via the Vite Environment API.\n */\nexport async function ssrImport<T = Record<string, unknown>>(server: ViteDevServer, moduleId: string): Promise<T> {\n return getRunnableEnv(server).runner.import(moduleId) as Promise<T>;\n}\n\n/**\n * return the env whose `hot` channel should receive astro-targeted events.\n * astro listens on the env that backs its middleware runner.\n */\nexport function getAstroHotEnv(server: ViteDevServer): DevEnvironment | undefined {\n const ssr = server.environments['ssr'];\n\n if (isRunnable(ssr)) return ssr;\n\n const astro = server.environments['astro'];\n\n if (isRunnable(astro)) return astro;\n\n return undefined;\n}\n","export const ignoredSuffixes = [\n // type definitions\n '.d.ts',\n '.d.mts',\n '.d.cts',\n // images\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.svg',\n '.webp',\n '.avif',\n '.ico',\n // fonts\n '.woff',\n '.woff2',\n '.ttf',\n '.otf',\n '.eot',\n // other static assets\n '.pdf',\n '.mp3',\n '.mp4',\n '.webm',\n '.ogg',\n '.wav',\n // data/config that boot typically doesn't import\n '.json',\n '.yaml',\n '.yml',\n '.toml',\n '.md',\n '.mdx',\n '.txt',\n // styles (handled by Vite's CSS HMR)\n '.css',\n '.scss',\n '.sass',\n '.less',\n];\n","import type { EventEmitter } from 'node:events';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { HotPayload, ViteDevServer } from 'vite';\nimport { GEN_HEADER, getCurrentGeneration } from './generation.js';\nimport { ignoredSuffixes } from './ignored.js';\nimport type { RestartScheduler } from './scheduler.js';\nimport { getAstroHotEnv } from './vite-env.js';\n\nconst RESTART_HTML = readFileSync(fileURLToPath(new URL('./restart-page.html', import.meta.url)), 'utf8');\n\nexport function setupBootWatch(server: ViteDevServer, entries: string[], scheduler: RestartScheduler): void {\n const entryFilePaths = entries.map((entry) => path.resolve(server.config.root, entry));\n\n const runnableEnv = getAstroHotEnv(server);\n const bootModuleGraph = runnableEnv?.moduleGraph;\n\n const collectBootDependencies = (): Set<string> => {\n const deps = new Set<string>();\n const seen = new Set<string>();\n\n for (const entryFilePath of entryFilePaths) {\n const entryModules = bootModuleGraph?.getModulesByFile(entryFilePath);\n const entryModule = entryModules ? [...entryModules][0] : undefined;\n\n if (!entryModule) continue;\n\n const visit = (mod: typeof entryModule): void => {\n if (!mod?.file || seen.has(mod.file)) return;\n\n seen.add(mod.file);\n deps.add(mod.file);\n\n for (const imp of mod.importedModules) visit(imp);\n };\n\n visit(entryModule);\n }\n\n return deps;\n };\n\n const shouldIgnore = (filePath: string): boolean => {\n const p = filePath.toLowerCase();\n\n return ignoredSuffixes.some((suffix) => p.endsWith(suffix));\n };\n\n const onWatcherEvent = (changedPath: string): void => {\n if (shouldIgnore(changedPath)) return;\n\n const bootDeps = collectBootDependencies();\n\n if (!bootDeps.has(changedPath)) return;\n\n scheduler.schedule(server, changedPath);\n };\n\n server.watcher.on('change', onWatcherEvent);\n server.watcher.on('add', onWatcherEvent);\n server.watcher.on('unlink', onWatcherEvent);\n\n // ignore full-reloads emitted during server startup (dep optimization, port retries).\n let handleFullReloads = false;\n\n if (server.httpServer) {\n server.httpServer.once('listening', () => {\n handleFullReloads = true;\n });\n } else {\n // middleware mode — no httpServer, enable immediately\n handleFullReloads = true;\n }\n\n // SSR full-reloads come through the runnable env's hot channel and clear\n // its module runner's cache — onStartup needs to run again on a fresh server.\n const outsideEmitter = (runnableEnv?.hot as { api?: { outsideEmitter?: EventEmitter } } | undefined)?.api\n ?.outsideEmitter;\n\n if (outsideEmitter) {\n outsideEmitter.on('send', (payload: HotPayload) => {\n if (!handleFullReloads) return;\n if (payload.type !== 'full-reload') return;\n\n const triggeredBy = 'triggeredBy' in payload ? (payload.triggeredBy as string) : undefined;\n\n scheduler.scheduleFullReload(server, triggeredBy);\n });\n }\n}\n\nconst READINESS_PATH = '/__astroscope_boot_ready';\n\n/**\n * Gate requests: show 503 holding page during restart, readiness probe for the reload.\n */\nexport function installBootGate(\n server: Pick<ViteDevServer, 'middlewares'>,\n scheduler: Pick<RestartScheduler, 'waitForRestart' | 'isRestartPending' | 'getLastFailure'>,\n): void {\n const middlewares = server.middlewares as unknown as {\n stack: { route: string; handle: unknown }[];\n };\n\n // must be `stack.unshift`ed to land before astro's handler\n middlewares.stack.unshift({\n route: '',\n handle: (async (\n req: { url?: string },\n res: {\n writeHead: (status: number, headers: Record<string, string>) => void;\n end: (body?: string) => void;\n headersSent?: boolean;\n },\n next: (err?: unknown) => void,\n ) => {\n // readiness probe: holding page polls this. blocks until no restart is in\n // flight, then 204 on success / 503 + JSON error if last attempt failed.\n if (req.url === READINESS_PATH) {\n await scheduler.waitForRestart();\n\n if (res.headersSent) return;\n\n const failure = scheduler.getLastFailure();\n\n if (failure) {\n res.writeHead(503, { 'cache-control': 'no-store', 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: failure.message }));\n\n return;\n }\n\n res.writeHead(204, { 'cache-control': 'no-store' });\n res.end();\n\n return;\n }\n\n if (isDevInternalPath(req.url)) {\n next();\n\n return;\n }\n\n // respond now; awaiting the restart would let vite destroy the socket mid-response.\n if (scheduler.isRestartPending()) {\n res.writeHead(503, {\n 'content-type': 'text/html; charset=utf-8',\n 'cache-control': 'no-store',\n 'retry-after': '1',\n });\n res.end(RESTART_HTML);\n\n return;\n }\n\n next();\n }) as never,\n });\n}\n\nfunction isDevInternalPath(url: string | undefined): boolean {\n if (!url) return false;\n\n return url.startsWith('/@') || url.startsWith('/__') || url.includes('/node_modules/');\n}\n\n/**\n * Stamp the current generation onto every incoming request so the runtime\n * Astro middleware can later detect whether the request belongs to a previous\n * (now torn-down) generation\n */\nexport function installGenStamp(server: Pick<ViteDevServer, 'middlewares'>): void {\n const middlewares = server.middlewares as unknown as {\n stack: { route: string; handle: unknown }[];\n };\n\n middlewares.stack.unshift({\n route: '',\n handle: ((req: { headers: Record<string, string> }, _res: unknown, next: () => void) => {\n req.headers[GEN_HEADER] = String(getCurrentGeneration());\n next();\n }) as never,\n });\n}\n","import type { AstroConfig } from 'astro';\nimport type { Plugin } from 'vite';\nimport { setBootContext } from '../lifecycle/context.js';\nimport { type BootModule, runShutdown, runStartup } from '../lifecycle/lifecycle.js';\nimport type { BootContext } from '../lifecycle/types.js';\nimport { clearNativeMounts } from '../server/native-mount.js';\nimport { incrementGeneration } from './generation.js';\nimport { RestartScheduler } from './scheduler.js';\nimport { serializeError } from './serialize-error.js';\nimport { ssrImport } from './vite-env.js';\nimport { installBootGate, installGenStamp, setupBootWatch } from './watch.js';\n\ninterface Logger {\n info(msg: string): void;\n warn(msg: string): void;\n error(msg: string): void;\n}\n\nexport interface DevMachineryOptions {\n /** boot file path relative to the project root; undefined = no boot module */\n entry: string | undefined;\n /** restart the dev server when watched dependencies change */\n watch: boolean;\n /** extra files (relative to the root) whose changes restart the dev server */\n watchEntries: string[];\n /** platform seams; runs each generation before the boot module starts */\n prepare: (importModule: <T = Record<string, unknown>>(id: string) => Promise<T>) => Promise<void>;\n logger: Logger;\n getConfig: () => AstroConfig | null;\n}\n\n/**\n * Resolve the default host and port from the Astro server config.\n * Falls back to `localhost:4321` when no config is provided.\n */\nfunction getServerDefaults(config: AstroConfig | null): { host: string; port: number } {\n return {\n host:\n typeof config?.server?.host === 'string'\n ? config.server.host\n : config?.server?.host === true\n ? '0.0.0.0'\n : 'localhost',\n port: config?.server?.port ?? 4321,\n };\n}\n\n/**\n * Build a dev-mode boot context from the running server's address,\n * falling back to Astro config defaults if the server isn't listening yet.\n */\nfunction resolveBootContext(\n server: { httpServer?: { address(): unknown } | null | undefined },\n config: AstroConfig | null,\n): BootContext {\n const addr = server.httpServer?.address();\n\n if (addr && typeof addr === 'object' && 'address' in addr && 'port' in addr) {\n const host =\n (addr as { address: string }).address === '::' || (addr as { address: string }).address === '0.0.0.0'\n ? 'localhost'\n : (addr as { address: string }).address;\n\n return { dev: true, host, port: (addr as { port: number }).port };\n }\n\n const { host, port } = getServerDefaults(config);\n\n return { dev: true, host, port };\n}\n\n/**\n * The dev-mode boot machinery: runs the platform seams and the boot lifecycle\n * per restart generation, restarts the dev server when watched dependencies\n * change, and gates requests behind a holding page during restarts.\n */\nexport function createDevMachinery(options: DevMachineryOptions): Plugin[] {\n const { entry, logger } = options;\n\n let hasStartupSucceededOnce = false;\n // run by the next configureServer before its startup so resources (ports,\n // sockets, locks) from the previous module are released first. idempotent.\n let priorShutdown: (() => Promise<void>) | undefined;\n // shared across restart-induced configureServer reruns\n const scheduler = options.watch ? new RestartScheduler(100, logger) : undefined;\n\n return [\n // gate plugin: enforce 'post' + returned-function so our `stack.unshift`\n // (in installBootGate / installGenStamp) lands at connect position 0,\n // ahead of astro's handler.\n {\n name: '@astroscope/node/dev-gate',\n enforce: 'post',\n\n configureServer(server) {\n if (!scheduler) return;\n\n return () => {\n // gen-stamp is unshifted last so it ends up at position 0:\n // every request gets a generation header before anything else,\n // including the gate's readiness probe.\n installBootGate(server, scheduler);\n installGenStamp(server);\n };\n },\n },\n\n // startup plugin: runs after all other configureServer hooks\n {\n name: '@astroscope/node/dev-startup',\n enforce: 'post',\n\n async configureServer(server) {\n incrementGeneration();\n\n // tear down the previous module first so its resources are released\n // before the new startup tries to claim them.\n if (priorShutdown) {\n await priorShutdown();\n priorShutdown = undefined;\n }\n\n const astroConfig = options.getConfig();\n const bootContext = resolveBootContext(server, astroConfig);\n let bootModule: BootModule | undefined;\n\n setBootContext(bootContext);\n\n try {\n await options.prepare((id) => ssrImport(server, id));\n\n bootModule = entry ? await ssrImport<BootModule>(server, `/${entry}`) : {};\n\n await runStartup(bootModule, bootContext);\n } catch (error) {\n logger.error(`Error running startup script: ${serializeError(error)}`);\n\n if (bootModule) {\n try {\n await runShutdown(bootModule, bootContext);\n } catch {\n // best-effort cleanup\n }\n }\n\n // restart failure: the gate can keep the holding\n // page up with an error message instead of dropping users onto a\n // half-broken old server.\n if (hasStartupSucceededOnce) {\n scheduler?.recordFailure(serializeError(error));\n\n throw error;\n }\n\n // initial failure: exit cleanly (mirrors the production server).\n process.exit(1);\n }\n\n hasStartupSucceededOnce = true;\n scheduler?.clearFailure();\n\n // capture so shutdown sees the same instance that started.\n const startedModule = bootModule;\n let shutdownDone = false;\n\n const shutdown = async (): Promise<void> => {\n if (shutdownDone) return;\n\n shutdownDone = true;\n\n try {\n await runShutdown(startedModule, resolveBootContext(server, options.getConfig()));\n } catch (error) {\n logger.error(`Error running shutdown script: ${serializeError(error)}`);\n }\n\n // the next generation's onStartup re-registers its mounts\n clearNativeMounts();\n };\n\n priorShutdown = shutdown;\n\n // sigint/sigterm path. also fires during restart but shutdown is idempotent.\n server.httpServer?.once('close', () => {\n void shutdown();\n });\n\n if (scheduler) {\n setupBootWatch(server, [...(entry ? [entry] : []), ...options.watchEntries], scheduler);\n }\n },\n },\n ];\n}\n","import type { ExcludePattern } from './excludes.js';\n\n/**\n * Serialize exclude patterns to JavaScript code for use in virtual modules.\n * Handles RegExp objects which JSON.stringify cannot serialize.\n */\nexport function serializeExcludePatterns(patterns: ExcludePattern[]): string {\n return `[${patterns.map((p) => ('pattern' in p ? `{ pattern: ${p.pattern.toString()} }` : JSON.stringify(p))).join(', ')}]`;\n}\n","import type { Plugin } from 'vite';\n\n/**\n * emit sourcemaps only for the SSR build. client bundles are left unmapped\n * so browsers can't fetch source via `//# sourceMappingURL=`.\n *\n * vite 7's `environments.ssr.build.sourcemap` looks cleaner but wholesale\n * replaces astro's SSR build defaults (including entry file naming), which\n * breaks the embedded dev boot machinery. using `isSsrBuild` keeps the\n * rest of astro's SSR config intact.\n */\nexport function ssrSourcemapPlugin(): Plugin {\n return {\n name: '@astroscope/node/tweaks/sourcemap',\n config(_config, { isSsrBuild }) {\n if (isSsrBuild) return { build: { sourcemap: true } };\n\n return {};\n },\n };\n}\n","import { Parser } from 'acorn';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\n\nconst HOOK_NAMES = new Set(['useEffect', 'useLayoutEffect', 'useInsertionEffect']);\nconst REACT_SOURCE = /^react(\\/.*)?$/;\nconst TRANSFORMABLE = /\\.(?:[mc]?[jt]sx?)$/;\nconst EMPTY_FN = '(()=>{})';\n\n/**\n * in SSR builds, react effect hooks never execute. emptying their callbacks\n * lets rolldown drop dead branches — including dynamic imports of client-only\n * libs (maplibre-gl, hls.js, etc.) — from the server bundle, which in turn\n * stops nft from tracing them at docker-image time.\n *\n * scope is deliberately narrow: first-party code only (no node_modules), only\n * in the SSR pass, and binding-aware (the React import must resolve to the\n * real react package). raw chunks where bundling has erased the binding are\n * left alone — that's NFT's domain, not ours.\n */\nexport function stripSsrEffectsPlugin(): Plugin {\n return {\n name: '@astroscope/node/tweaks/strip-effects',\n enforce: 'post',\n transform(code, id, options) {\n if (!options?.ssr) return null;\n if (id.includes('/node_modules/')) return null;\n\n const cleanId = id.split('?')[0] ?? id;\n\n if (!TRANSFORMABLE.test(cleanId)) return null;\n if (!code.includes('useEffect') && !code.includes('useLayoutEffect') && !code.includes('useInsertionEffect')) {\n return null;\n }\n\n let ast: any;\n\n try {\n ast = Parser.parse(code, {\n ecmaVersion: 'latest',\n sourceType: 'module',\n allowReturnOutsideFunction: true,\n allowAwaitOutsideFunction: true,\n allowImportExportEverywhere: true,\n allowHashBang: true,\n });\n } catch {\n return null;\n }\n\n const directHooks = new Set<string>();\n const namespaceHooks = new Set<string>();\n\n walk(ast, (node) => {\n if (node.type !== 'ImportDeclaration') return;\n\n const src = node.source?.value;\n\n if (typeof src !== 'string' || !REACT_SOURCE.test(src)) return;\n\n for (const spec of node.specifiers ?? []) {\n if (spec.type === 'ImportSpecifier') {\n const imported = spec.imported?.name ?? spec.imported?.value;\n\n if (HOOK_NAMES.has(imported)) directHooks.add(spec.local.name);\n } else if (spec.type === 'ImportDefaultSpecifier' || spec.type === 'ImportNamespaceSpecifier') {\n namespaceHooks.add(spec.local.name);\n }\n }\n });\n\n if (directHooks.size === 0 && namespaceHooks.size === 0) return null;\n\n const replacements: { start: number; end: number }[] = [];\n\n walk(ast, (node) => {\n if (node.type !== 'CallExpression' || !node.arguments?.length) return;\n\n const callee = node.callee;\n const isDirect = callee.type === 'Identifier' && directHooks.has(callee.name);\n const isMember =\n callee.type === 'MemberExpression' &&\n !callee.computed &&\n callee.object?.type === 'Identifier' &&\n namespaceHooks.has(callee.object.name) &&\n callee.property?.type === 'Identifier' &&\n HOOK_NAMES.has(callee.property.name);\n\n if (!isDirect && !isMember) return;\n\n const arg = node.arguments[0];\n\n replacements.push({ start: arg.start, end: arg.end });\n });\n\n if (replacements.length === 0) return null;\n\n const s = new MagicString(code);\n\n for (const { start, end } of replacements) {\n s.overwrite(start, end, EMPTY_FN);\n }\n\n return { code: s.toString(), map: s.generateMap({ hires: true }) };\n },\n };\n}\n\nfunction walk(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== 'object') return;\n\n if (typeof node.type === 'string') visit(node);\n\n for (const key of Object.keys(node)) {\n const v = node[key];\n\n if (Array.isArray(v)) for (const item of v) walk(item, visit);\n else if (v && typeof v === 'object') walk(v, visit);\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AstroConfig, AstroIntegration } from 'astro';\nimport { createDevMachinery } from '../dev-mode/machinery.js';\nimport { type ExcludePattern, RECOMMENDED_EXCLUDES } from '../excludes/excludes.js';\nimport { serializeExcludePatterns } from '../excludes/serialize.js';\nimport { createRequestInstrumentation } from '../observability/instrument.js';\nimport { preparePlatform } from '../platform/prepare.js';\nimport { dispatchNativeMount } from '../server/native-mount.js';\nimport { ssrSourcemapPlugin } from '../tweaks/sourcemap.js';\nimport { stripSsrEffectsPlugin } from '../tweaks/strip-effects.js';\nimport type { NodeOptions, RuntimeOptions } from '../types.js';\n\nexport const CONFIG_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/config';\nexport const BOOT_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/boot';\nexport const CSRF_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/csrf';\nexport const CONFIG_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/config-entry';\nexport const INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/instrumentation-entry';\nexport const LOG_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/log-entry';\n\nconst RESOLVED_CONFIG_VIRTUAL_MODULE_ID = `\\0${CONFIG_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_BOOT_VIRTUAL_MODULE_ID = `\\0${BOOT_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_CSRF_VIRTUAL_MODULE_ID = `\\0${CSRF_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID = `\\0${CONFIG_ENTRY_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID = `\\0${INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID = `\\0${LOG_ENTRY_VIRTUAL_MODULE_ID}`;\n\nconst SERVER_ENVIRONMENTS = ['ssr', 'prerender', 'astro'];\nconst DEFAULT_REQUEST_EXCLUDES: ExcludePattern[] = [...RECOMMENDED_EXCLUDES];\n\nfunction resolveHost(host: string | boolean | undefined): string {\n if (typeof host === 'string') return host;\n\n return host === true ? '0.0.0.0' : 'localhost';\n}\n\nfunction resolveBootEntry(root: string, entry: string | undefined): string | undefined {\n if (entry) {\n const abs = path.resolve(root, entry);\n\n if (!fs.existsSync(abs)) {\n throw new Error(`[@astroscope/node] boot entry not found: ${entry}`);\n }\n\n return abs;\n }\n\n for (const candidate of ['src/boot/index.ts', 'src/boot.ts']) {\n const abs = path.resolve(root, candidate);\n\n if (fs.existsSync(abs)) return abs;\n }\n\n return undefined;\n}\n\nfunction resolveSeam(root: string, candidate: string): string | undefined {\n const abs = path.resolve(root, candidate);\n\n return fs.existsSync(abs) ? abs : undefined;\n}\n\n/**\n * Node adapter for Astro with a first-class server entrypoint: the boot\n * lifecycle, module warmup, health probes, request logging and telemetry run\n * as plain code around `server.listen()` instead of being injected into the\n * build output.\n */\nexport default function node(options: NodeOptions = {}): AstroIntegration {\n const bootOptions = options.boot ?? {};\n const healthOptions = options.health ?? {};\n const csrfOptions = options.csrf ?? {};\n const loggingOptions = options.logging ?? {};\n const telemetryOptions = options.telemetry ?? {};\n\n const loggingExclude = loggingOptions ? (loggingOptions.exclude ?? DEFAULT_REQUEST_EXCLUDES) : [];\n const telemetryExclude = telemetryOptions ? (telemetryOptions.exclude ?? DEFAULT_REQUEST_EXCLUDES) : [];\n\n let astroConfig: AstroConfig | null = null;\n let bootEntry: string | undefined;\n let configSeam: string | undefined;\n let instrumentationSeam: string | undefined;\n let logSeam: string | undefined;\n let isDev = false;\n\n return {\n name: '@astroscope/node',\n hooks: {\n 'astro:config:setup': ({ command, config, updateConfig, addMiddleware, logger }) => {\n isDev = command === 'dev';\n\n // route enrichment first so csrf-rejected requests still carry a route\n if (loggingOptions || telemetryOptions) {\n addMiddleware({ order: 'pre', entrypoint: '@astroscope/node/route-middleware' });\n }\n\n if (csrfOptions) {\n addMiddleware({ order: 'pre', entrypoint: '@astroscope/node/csrf-middleware' });\n }\n\n const root = fileURLToPath(config.root);\n const watch = bootOptions === false ? false : (bootOptions.watch ?? true);\n\n bootEntry = bootOptions === false ? undefined : resolveBootEntry(root, bootOptions.entry);\n configSeam = resolveSeam(root, 'src/config.ts');\n instrumentationSeam = resolveSeam(root, 'src/instrumentation.ts');\n logSeam = resolveSeam(root, 'src/log.ts');\n\n const relativeSeam = (abs: string | undefined) =>\n abs ? path.relative(root, abs).split(path.sep).join('/') : undefined;\n\n const devMachinery =\n command === 'dev' && bootOptions !== false\n ? createDevMachinery({\n entry: bootEntry ? path.relative(root, bootEntry) : undefined,\n watch,\n // instrumentation runs once per process — watching it would\n // restart generations that can't re-apply it\n watchEntries: [relativeSeam(configSeam), relativeSeam(logSeam)].filter(\n (entry): entry is string => !!entry,\n ),\n prepare: (importModule) =>\n preparePlatform({\n dev: true,\n telemetry:\n telemetryOptions && telemetryOptions.dev\n ? { prometheus: telemetryOptions.prometheus ?? {} }\n : false,\n seams: {\n ...(configSeam && { config: () => importModule(`/${relativeSeam(configSeam)}`) }),\n ...(instrumentationSeam && {\n instrumentation: () => importModule(`/${relativeSeam(instrumentationSeam)}`),\n }),\n ...(logSeam && { log: () => importModule(`/${relativeSeam(logSeam)}`) }),\n },\n }),\n logger,\n getConfig: () => astroConfig,\n })\n : [];\n\n if (command === 'dev' && bootOptions !== false && watch) {\n // catches errors thrown by stale (post-shutdown) requests so\n // they don't pollute the logs during dev-server restarts.\n addMiddleware({ entrypoint: '@astroscope/node/dev-middleware', order: 'pre' });\n }\n\n updateConfig({\n build: { redirects: false },\n // opinionated defaults: no trailing slashes, behind LB\n ...(config.trailingSlash === 'ignore' && { trailingSlash: 'never' as const }),\n security: {\n // assumed to run behind LB\n ...(!config.security.allowedDomains?.length && { allowedDomains: [{}] }),\n // the embedded csrf middleware replaces the built-in origin check\n ...(csrfOptions && { checkOrigin: false }),\n },\n image: {\n endpoint: {\n route: config.image.endpoint.route ?? '_image',\n entrypoint:\n config.image.endpoint.entrypoint ??\n (command === 'dev' ? 'astro/assets/endpoint/dev' : 'astro/assets/endpoint/node'),\n },\n },\n vite: {\n plugins: [\n ...devMachinery,\n ssrSourcemapPlugin(),\n stripSsrEffectsPlugin(),\n {\n name: '@astroscope/node',\n\n configEnvironment(environmentName: string) {\n if (SERVER_ENVIRONMENTS.includes(environmentName)) {\n return { resolve: { noExternal: ['@astroscope/node'] } };\n }\n },\n\n resolveId(id: string) {\n if (id === CONFIG_VIRTUAL_MODULE_ID) return RESOLVED_CONFIG_VIRTUAL_MODULE_ID;\n if (id === BOOT_VIRTUAL_MODULE_ID) return RESOLVED_BOOT_VIRTUAL_MODULE_ID;\n if (id === CSRF_VIRTUAL_MODULE_ID) return RESOLVED_CSRF_VIRTUAL_MODULE_ID;\n if (id === CONFIG_ENTRY_VIRTUAL_MODULE_ID) return RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID;\n if (id === INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID) {\n return RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID;\n }\n if (id === LOG_ENTRY_VIRTUAL_MODULE_ID) return RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID;\n },\n\n load(id: string) {\n if (id === RESOLVED_CONFIG_VIRTUAL_MODULE_ID) {\n if (!astroConfig) throw new Error('[@astroscope/node] astro config not resolved yet');\n\n const runtimeOptions: Omit<RuntimeOptions, 'logging' | 'telemetry'> = {\n host: resolveHost(astroConfig.server.host),\n port: astroConfig.server.port ?? 4321,\n client: astroConfig.build.client.toString(),\n server: astroConfig.build.server.toString(),\n bodySizeLimit: options.bodySizeLimit ?? 1024 * 1024 * 1024,\n shutdownTimeout: options.shutdownTimeout ?? 10_000,\n health: healthOptions\n ? {\n ...(healthOptions.host !== undefined && { host: healthOptions.host }),\n ...(healthOptions.port !== undefined && { port: healthOptions.port }),\n ...(healthOptions.paths && { paths: healthOptions.paths }),\n }\n : false,\n };\n\n // exclude patterns may contain RegExp — serialized as code, not JSON\n const logging = loggingOptions\n ? `{ exclude: ${serializeExcludePatterns(loggingExclude)}, extended: ${JSON.stringify(\n loggingOptions.extended ?? false,\n )} }`\n : 'false';\n const telemetry = telemetryOptions\n ? `{ exclude: ${serializeExcludePatterns(telemetryExclude)}, prometheus: ${JSON.stringify(\n telemetryOptions.prometheus ?? {},\n )} }`\n : 'false';\n\n return `export const options = { ...${JSON.stringify(runtimeOptions)}, logging: ${logging}, telemetry: ${telemetry} };`;\n }\n\n if (id === RESOLVED_BOOT_VIRTUAL_MODULE_ID) {\n // re-export to avoid absolute path manifest leaks\n return bootEntry ? `export * from ${JSON.stringify(bootEntry)};` : 'export {};';\n }\n\n if (id === RESOLVED_CSRF_VIRTUAL_MODULE_ID) {\n return `export const excludePatterns = ${serializeExcludePatterns(csrfOptions ? (csrfOptions.exclude ?? []) : [])};`;\n }\n\n if (id === RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID) {\n // side-effect import: @entwico/zod-conf validation runs at module load\n return configSeam ? `import ${JSON.stringify(configSeam)};\\nexport {};` : 'export {};';\n }\n\n if (id === RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID) {\n return instrumentationSeam ? `export * from ${JSON.stringify(instrumentationSeam)};` : 'export {};';\n }\n\n if (id === RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID) {\n return logSeam\n ? `export { default } from ${JSON.stringify(logSeam)};`\n : 'export default undefined;';\n }\n },\n },\n ],\n },\n });\n },\n 'astro:server:setup': ({ server }) => {\n if (!isDev) return;\n\n const devLogging = loggingOptions && loggingOptions.dev;\n const devTelemetry = telemetryOptions && telemetryOptions.dev;\n\n const instrument =\n devLogging || devTelemetry\n ? createRequestInstrumentation({\n logging: devLogging ? { exclude: loggingExclude, extended: loggingOptions.extended ?? false } : false,\n telemetry: devTelemetry ? { exclude: telemetryExclude } : false,\n })\n : undefined;\n\n server.middlewares.use((req, res, next) => {\n const inner = (): void => {\n if (!dispatchNativeMount(req, res)) next();\n };\n\n if (instrument) {\n instrument(req, res, inner);\n } else {\n inner();\n }\n });\n },\n 'astro:config:done': ({ config, setAdapter }) => {\n astroConfig = config;\n\n setAdapter({\n name: '@astroscope/node',\n entrypointResolution: 'auto',\n serverEntrypoint: '@astroscope/node/server',\n previewEntrypoint: '@astroscope/node/preview',\n adapterFeatures: {\n buildOutput: 'server',\n middlewareMode: 'classic',\n },\n supportedAstroFeatures: {\n hybridOutput: 'stable',\n staticOutput: 'stable',\n serverOutput: 'stable',\n sharpImageService: 'stable',\n i18nDomains: 'experimental',\n envGetSecret: 'stable',\n },\n });\n },\n 'astro:build:done': async ({ logger }) => {\n if (!astroConfig) return;\n\n const { compressClientDir } = await import('../compress/compress.js');\n\n await compressClientDir(fileURLToPath(astroConfig.build.client), logger);\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["walk"],"sources":["../src/dev-mode/island-warmup.ts","../src/dev-mode/serialize-error.ts","../src/dev-mode/scheduler.ts","../src/dev-mode/vite-env.ts","../src/dev-mode/ignored.ts","../src/dev-mode/watch.ts","../src/dev-mode/machinery.ts","../src/excludes/serialize.ts","../src/tweaks/sourcemap.ts","../src/tweaks/strip-effects.ts","../src/integration/integration.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { parse } from '@astrojs/compiler-rs';\nimport type { Plugin, ViteDevServer } from 'vite';\n\n/**\n * Vite discovers island dependencies lazily: astro registers no client entries,\n * so a dep like radix is first seen when an island hydrates. The optimizer then\n * re-runs, bumps the `?v=` hash and every in-flight import gets a\n * \"504 Outdated Optimize Dep\" — hydration fails until the full reload.\n *\n * This plugin scans `.astro` sources for `client:*` components at config time,\n * puts their bare package imports into `optimizeDeps.include` (initial optimize\n * pass) and warms their local module graphs at server start (vite's\n * `preTransformRequests` crawls static imports recursively), so discovery\n * happens before a browser holds stale URLs.\n */\n\ninterface Logger {\n info(msg: string): void;\n debug(msg: string): void;\n}\n\nexport interface IslandImport {\n /** absolute path of the .astro file rendering the island */\n importer: string;\n /** import specifier of the hydrated component */\n specifier: string;\n}\n\ninterface AstNode {\n type: string;\n [key: string]: unknown;\n}\n\nfunction isAstNode(value: unknown): value is AstNode {\n return typeof value === 'object' && value !== null && typeof (value as AstNode).type === 'string';\n}\n\nfunction walk(node: unknown, visit: (node: AstNode) => void): void {\n if (Array.isArray(node)) {\n for (const item of node) walk(item, visit);\n\n return;\n }\n\n if (typeof node !== 'object' || node === null) return;\n\n if (isAstNode(node)) visit(node);\n\n for (const value of Object.values(node)) walk(value, visit);\n}\n\ninterface ImportDeclarationNode {\n importKind?: string | null;\n source?: { value?: unknown } | null;\n specifiers?: { importKind?: string | null; local?: { name?: unknown } | null }[] | null;\n}\n\n/** local binding name → import specifier, from the frontmatter program */\nfunction collectImports(program: unknown): Map<string, string> {\n const imports = new Map<string, string>();\n\n walk(program, (node) => {\n if (node.type !== 'ImportDeclaration') return;\n\n const decl = node as ImportDeclarationNode;\n\n if (decl.importKind === 'type') return;\n\n const specifier = typeof decl.source?.value === 'string' ? decl.source.value : undefined;\n\n if (!specifier) return;\n\n for (const spec of decl.specifiers ?? []) {\n if (spec.importKind === 'type') continue;\n\n if (typeof spec.local?.name === 'string') {\n imports.set(spec.local.name, specifier);\n }\n }\n });\n\n return imports;\n}\n\n/** the root identifier of a JSX tag: `Foo` → Foo, `Ns.Chart` → Ns */\nfunction tagRootIdentifier(name: unknown): string | undefined {\n let current = name;\n\n while (isAstNode(current) && current.type === 'JSXMemberExpression') {\n current = (current as unknown as { object?: unknown }).object;\n }\n\n if (isAstNode(current) && current.type === 'JSXIdentifier') {\n const identifier = current as unknown as { name?: unknown };\n\n return typeof identifier.name === 'string' ? identifier.name : undefined;\n }\n\n return undefined;\n}\n\nfunction hasClientDirective(attributes: unknown): boolean {\n if (!Array.isArray(attributes)) return false;\n\n return attributes.some((attr) => {\n if (!isAstNode(attr) || attr.type !== 'JSXAttribute') return false;\n\n const name = (attr as unknown as { name?: { name?: unknown } | null }).name;\n\n return typeof name?.name === 'string' && name.name.startsWith('client:');\n });\n}\n\n/**\n * Extract the import specifiers of all hydrated (`client:*`) components from\n * raw `.astro` source. Astro components can't hydrate, so `.astro` specifiers\n * are skipped; dynamic tags without a frontmatter import are invisible here.\n */\nexport function scanAstroSource(source: string): string[] {\n const { ast } = parse(source);\n const root = ast as { frontmatter?: { program?: unknown } | null; body?: unknown };\n\n const imports = collectImports(root.frontmatter?.program);\n\n if (imports.size === 0) return [];\n\n const specifiers = new Set<string>();\n\n walk(root.body, (node) => {\n if (node.type !== 'JSXOpeningElement') return;\n\n const element = node as unknown as { attributes?: unknown; name?: unknown };\n\n if (!hasClientDirective(element.attributes)) return;\n\n const rootName = tagRootIdentifier(element.name);\n\n if (!rootName || /^[a-z]/.test(rootName)) return;\n\n const specifier = imports.get(rootName);\n\n if (specifier && !specifier.endsWith('.astro')) {\n specifiers.add(specifier);\n }\n });\n\n return [...specifiers];\n}\n\n/** scan all `.astro` files under `srcDir` for hydrated components */\nexport async function scanProjectIslands(srcDir: string, logger: Logger): Promise<IslandImport[]> {\n const islands: IslandImport[] = [];\n\n let entries: fs.Dirent[];\n\n try {\n entries = await fs.promises.readdir(srcDir, { recursive: true, withFileTypes: true });\n } catch {\n return islands;\n }\n\n const files = entries\n .filter((entry) => entry.isFile() && entry.name.endsWith('.astro'))\n .map((entry) => path.join(entry.parentPath, entry.name));\n\n await Promise.all(\n files.map(async (file) => {\n try {\n const source = await fs.promises.readFile(file, 'utf8');\n\n for (const specifier of scanAstroSource(source)) {\n islands.push({ importer: file, specifier });\n }\n } catch (error) {\n // a file mid-edit or unreadable must not break the dev server\n logger.debug(`island scan skipped ${file}: ${error instanceof Error ? error.message : String(error)}`);\n }\n }),\n );\n\n return islands;\n}\n\nfunction packageNameOf(specifier: string): string {\n const segments = specifier.split('/');\n\n return specifier.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? specifier);\n}\n\n/**\n * Bare package specifiers resolvable from the project's `node_modules` — these\n * go into `optimizeDeps.include`. Anything else (relative paths, tsconfig\n * aliases, hoisted workspace deps) is resolved through vite at server start;\n * misclassification is harmless, just slightly later discovery.\n */\nexport function selectBareSpecifiers(islands: IslandImport[], root: string): string[] {\n const bare = new Set<string>();\n\n for (const { specifier } of islands) {\n if (specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('#')) continue;\n\n if (fs.existsSync(path.join(root, 'node_modules', packageNameOf(specifier)))) {\n bare.add(specifier);\n }\n }\n\n return [...bare];\n}\n\nfunction toRequestUrl(id: string, root: string): string {\n const normalized = id.split(path.sep).join('/');\n const normalizedRoot = root.split(path.sep).join('/');\n\n return normalized.startsWith(`${normalizedRoot}/`) ? normalized.slice(normalizedRoot.length) : `/@fs/${normalized}`;\n}\n\nexport interface IslandWarmupOptions {\n root: string;\n srcDir: string;\n logger: Logger;\n}\n\nexport function createIslandWarmup(options: IslandWarmupOptions): Plugin {\n const { root, srcDir, logger } = options;\n\n let islands: IslandImport[] = [];\n\n const warmIslands = async (server: ViteDevServer, batch: IslandImport[], warmed: Set<string>): Promise<void> => {\n const env = server.environments.client;\n\n await Promise.all(\n batch.map(async ({ importer, specifier }) => {\n try {\n // resolving through vite also registers still-unknown bare deps with\n // the optimizer — discovery happens now, not at hydration time\n const resolved = await env.pluginContainer.resolveId(specifier, importer);\n\n if (!resolved || resolved.external) return;\n if (resolved.id.startsWith('\\0') || resolved.id.includes('node_modules')) return;\n if (warmed.has(resolved.id)) return;\n\n warmed.add(resolved.id);\n\n await env.warmupRequest(toRequestUrl(resolved.id, root));\n } catch {\n // warmup is best-effort; a broken component surfaces on request anyway\n }\n }),\n );\n };\n\n return {\n name: '@astroscope/node/island-warmup',\n\n async config() {\n islands = await scanProjectIslands(srcDir, logger);\n\n const include = selectBareSpecifiers(islands, root);\n\n if (islands.length > 0) {\n logger.info(`warming ${islands.length} island(s), pre-optimizing ${include.length} dependenc(ies)`);\n }\n\n return include.length > 0 ? { optimizeDeps: { include } } : undefined;\n },\n\n configureServer(server) {\n const warmed = new Set<string>();\n\n // the plugin container is not initialized until the server starts\n // listening — mirror vite's own warmup timing\n if (server.httpServer) {\n server.httpServer.once('listening', () => void warmIslands(server, islands, warmed));\n } else {\n void warmIslands(server, islands, warmed);\n }\n\n // islands added mid-session get discovered at save time instead of at\n // page load; new bare deps still re-optimize, but before hydration\n const onWatcherEvent = (file: string): void => {\n if (!file.endsWith('.astro') || !file.startsWith(srcDir)) return;\n\n void fs.promises\n .readFile(file, 'utf8')\n .then((source) => {\n const batch = scanAstroSource(source).map((specifier) => ({ importer: file, specifier }));\n\n return warmIslands(server, batch, warmed);\n })\n .catch(() => {});\n };\n\n server.watcher.on('add', onWatcherEvent);\n server.watcher.on('change', onWatcherEvent);\n },\n };\n}\n","export function serializeError(error: unknown): string {\n if (error instanceof Error) {\n return error.stack ?? error.message;\n }\n\n return JSON.stringify(error);\n}\n","import path from 'node:path';\nimport type { ViteDevServer } from 'vite';\nimport { serializeError } from './serialize-error.js';\n\ntype Logger = { info(msg: string): void; error(msg: string): void };\n\nconst FULL_RELOAD_UNKNOWN = '<unknown>';\n\n/**\n * Coordinates dev-server restarts: debounces bursts, chains a follow-up if\n * changes arrive mid-restart (vite's `ssrImport` reads disk at import time,\n * so changes during a restart would otherwise be missed), and logs once per\n * restart with what triggered it.\n *\n * One instance per integration, shared across restart-induced configureServer\n * reruns — chain coordination would be lost if recreated each time.\n */\nexport class RestartScheduler {\n private _inFlight = false;\n private _pending = false;\n private _debounceTimer: ReturnType<typeof setTimeout> | undefined;\n private _pendingBootDeps = new Set<string>();\n private _pendingFullReloads = new Set<string>();\n // set while a restart chain is running. the gate probes it (`isRestartPending`)\n // to short-circuit requests, and awaits it (`waitForRestart`) on readiness.\n private _runPromise: Promise<void> | undefined;\n // set when a restart attempt fails\n private _lastFailure: { message: string } | undefined;\n\n constructor(\n private readonly debounceMs: number,\n private readonly logger: Logger,\n ) {}\n\n // true from the moment a change is queued until the restart completes — covers\n // the debounce window too, so requests don't slip past the gate before _run starts.\n isRestartPending(): boolean {\n return !!this._runPromise || !!this._debounceTimer || !!this._lastFailure;\n }\n\n getLastFailure(): { message: string } | undefined {\n return this._lastFailure;\n }\n\n recordFailure(message: string): void {\n this._lastFailure = { message };\n }\n\n clearFailure(): void {\n this._lastFailure = undefined;\n }\n\n schedule(server: ViteDevServer, changedPath: string): void {\n this._pendingBootDeps.add(changedPath);\n this._scheduleRun(server);\n }\n\n scheduleFullReload(server: ViteDevServer, triggeredBy?: string): void {\n this._pendingFullReloads.add(triggeredBy ?? FULL_RELOAD_UNKNOWN);\n this._scheduleRun(server);\n }\n\n /**\n * Resolves when no restart is running. Loops to handle back-to-back restarts\n * (e.g. one chain ends and a queued debounce timer immediately fires a new\n * one). Never rejects, so a failed restart still releases the gate — caller\n * proceeds against the broken state rather than hanging forever.\n */\n async waitForRestart(): Promise<void> {\n while (this._runPromise) {\n try {\n await this._runPromise;\n } catch {\n // restart failed — release anyway\n }\n }\n }\n\n private _scheduleRun(server: ViteDevServer): void {\n clearTimeout(this._debounceTimer);\n this._debounceTimer = setTimeout(() => {\n this._debounceTimer = undefined;\n void this._run(server);\n }, this.debounceMs);\n }\n\n private async _run(server: ViteDevServer): Promise<void> {\n if (this._inFlight) {\n // loop driving the in-flight restart will pick up the next iteration.\n this._pending = true;\n\n return;\n }\n\n this._inFlight = true;\n\n let resolveRun!: () => void;\n\n this._runPromise = new Promise<void>((resolve) => {\n resolveRun = resolve;\n });\n\n try {\n do {\n this._pending = false;\n\n const bootDeps = [...this._pendingBootDeps].sort();\n const fullReloads = [...this._pendingFullReloads].sort();\n\n this._pendingBootDeps.clear();\n this._pendingFullReloads.clear();\n\n if (bootDeps.length > 0 || fullReloads.length > 0) {\n this.logger.info(this._formatReason(server, bootDeps, fullReloads));\n }\n\n try {\n await server.restart();\n } catch (error) {\n this.logger.error(`error during dev server restart: ${serializeError(error)}`);\n }\n } while (this._pending);\n } finally {\n this._inFlight = false;\n this._runPromise = undefined;\n resolveRun();\n }\n }\n\n private _formatReason(server: ViteDevServer, bootDeps: string[], fullReloads: string[]): string {\n const root = server.config.root;\n const rel = (p: string): string => path.relative(root, p) || p;\n const parts: string[] = [];\n\n if (bootDeps.length === 1) {\n parts.push(`boot dep changed: ${rel(bootDeps[0]!)}`);\n } else if (bootDeps.length > 1) {\n parts.push(`boot deps changed (${bootDeps.length}): ${bootDeps.map(rel).join(', ')}`);\n }\n\n if (fullReloads.length > 0) {\n const named = fullReloads.filter((p) => p !== FULL_RELOAD_UNKNOWN);\n\n if (named.length === 0) {\n parts.push('vite SSR full-reload');\n } else {\n parts.push(`vite SSR full-reload (triggered by ${named.map(rel).join(', ')})`);\n }\n }\n\n return `${parts.join(' + ')} — restarting dev server`;\n }\n}\n","import type { DevEnvironment, ViteDevServer } from 'vite';\n\ntype RunnableEnv = DevEnvironment & { runner: { import: (id: string) => Promise<unknown> } };\n\n/**\n * duck-typed runnable-env check. avoids `isRunnableDevEnvironment` which relies on\n * `instanceof RunnableDevEnvironment` — that breaks when the consumer and vite host\n * resolve to different vite installs (e.g. linked packages outside the workspace).\n */\nfunction isRunnable(env: DevEnvironment | undefined): env is RunnableEnv {\n return (\n !!env &&\n typeof (env as { runner?: unknown }).runner === 'object' &&\n typeof (env as RunnableEnv).runner.import === 'function'\n );\n}\n\n/**\n * resolve a runnable dev environment — prefers `ssr`, falls back to `astro`.\n * astro 6 exposes a separate `astro` environment when `ssr` isn't runnable\n * (see astro/core/constants.ts ASTRO_VITE_ENVIRONMENT_NAMES).\n */\nfunction getRunnableEnv(server: ViteDevServer): RunnableEnv {\n const ssr = server.environments['ssr'];\n\n if (isRunnable(ssr)) return ssr;\n\n const astro = server.environments['astro'];\n\n if (isRunnable(astro)) return astro;\n\n const names = Object.keys(server.environments);\n\n throw new Error(`no runnable dev environment found — available: ${names.join(', ')}`);\n}\n\n/**\n * load a module via the Vite Environment API.\n */\nexport async function ssrImport<T = Record<string, unknown>>(server: ViteDevServer, moduleId: string): Promise<T> {\n return getRunnableEnv(server).runner.import(moduleId) as Promise<T>;\n}\n\n/**\n * return the env whose `hot` channel should receive astro-targeted events.\n * astro listens on the env that backs its middleware runner.\n */\nexport function getAstroHotEnv(server: ViteDevServer): DevEnvironment | undefined {\n const ssr = server.environments['ssr'];\n\n if (isRunnable(ssr)) return ssr;\n\n const astro = server.environments['astro'];\n\n if (isRunnable(astro)) return astro;\n\n return undefined;\n}\n","export const ignoredSuffixes = [\n // type definitions\n '.d.ts',\n '.d.mts',\n '.d.cts',\n // images\n '.png',\n '.jpg',\n '.jpeg',\n '.gif',\n '.svg',\n '.webp',\n '.avif',\n '.ico',\n // fonts\n '.woff',\n '.woff2',\n '.ttf',\n '.otf',\n '.eot',\n // other static assets\n '.pdf',\n '.mp3',\n '.mp4',\n '.webm',\n '.ogg',\n '.wav',\n // data/config that boot typically doesn't import\n '.json',\n '.yaml',\n '.yml',\n '.toml',\n '.md',\n '.mdx',\n '.txt',\n // styles (handled by Vite's CSS HMR)\n '.css',\n '.scss',\n '.sass',\n '.less',\n];\n","import type { EventEmitter } from 'node:events';\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { HotPayload, ViteDevServer } from 'vite';\nimport { GEN_HEADER, getCurrentGeneration } from './generation.js';\nimport { ignoredSuffixes } from './ignored.js';\nimport type { RestartScheduler } from './scheduler.js';\nimport { getAstroHotEnv } from './vite-env.js';\n\nconst RESTART_HTML = readFileSync(fileURLToPath(new URL('./restart-page.html', import.meta.url)), 'utf8');\n\nexport function setupBootWatch(server: ViteDevServer, entries: string[], scheduler: RestartScheduler): void {\n const entryFilePaths = entries.map((entry) => path.resolve(server.config.root, entry));\n\n const runnableEnv = getAstroHotEnv(server);\n const bootModuleGraph = runnableEnv?.moduleGraph;\n\n const collectBootDependencies = (): Set<string> => {\n const deps = new Set<string>();\n const seen = new Set<string>();\n\n for (const entryFilePath of entryFilePaths) {\n const entryModules = bootModuleGraph?.getModulesByFile(entryFilePath);\n const entryModule = entryModules ? [...entryModules][0] : undefined;\n\n if (!entryModule) continue;\n\n const visit = (mod: typeof entryModule): void => {\n if (!mod?.file || seen.has(mod.file)) return;\n\n seen.add(mod.file);\n deps.add(mod.file);\n\n for (const imp of mod.importedModules) visit(imp);\n };\n\n visit(entryModule);\n }\n\n return deps;\n };\n\n const shouldIgnore = (filePath: string): boolean => {\n const p = filePath.toLowerCase();\n\n return ignoredSuffixes.some((suffix) => p.endsWith(suffix));\n };\n\n const onWatcherEvent = (changedPath: string): void => {\n if (shouldIgnore(changedPath)) return;\n\n const bootDeps = collectBootDependencies();\n\n if (!bootDeps.has(changedPath)) return;\n\n scheduler.schedule(server, changedPath);\n };\n\n server.watcher.on('change', onWatcherEvent);\n server.watcher.on('add', onWatcherEvent);\n server.watcher.on('unlink', onWatcherEvent);\n\n // ignore full-reloads emitted during server startup (dep optimization, port retries).\n let handleFullReloads = false;\n\n if (server.httpServer) {\n server.httpServer.once('listening', () => {\n handleFullReloads = true;\n });\n } else {\n // middleware mode — no httpServer, enable immediately\n handleFullReloads = true;\n }\n\n // SSR full-reloads come through the runnable env's hot channel and clear\n // its module runner's cache — onStartup needs to run again on a fresh server.\n const outsideEmitter = (runnableEnv?.hot as { api?: { outsideEmitter?: EventEmitter } } | undefined)?.api\n ?.outsideEmitter;\n\n if (outsideEmitter) {\n outsideEmitter.on('send', (payload: HotPayload) => {\n if (!handleFullReloads) return;\n if (payload.type !== 'full-reload') return;\n\n const triggeredBy = 'triggeredBy' in payload ? (payload.triggeredBy as string) : undefined;\n\n scheduler.scheduleFullReload(server, triggeredBy);\n });\n }\n}\n\nconst READINESS_PATH = '/__astroscope_boot_ready';\n\n/**\n * Gate requests: show 503 holding page during restart, readiness probe for the reload.\n */\nexport function installBootGate(\n server: Pick<ViteDevServer, 'middlewares'>,\n scheduler: Pick<RestartScheduler, 'waitForRestart' | 'isRestartPending' | 'getLastFailure'>,\n): void {\n const middlewares = server.middlewares as unknown as {\n stack: { route: string; handle: unknown }[];\n };\n\n // must be `stack.unshift`ed to land before astro's handler\n middlewares.stack.unshift({\n route: '',\n handle: (async (\n req: { url?: string },\n res: {\n writeHead: (status: number, headers: Record<string, string>) => void;\n end: (body?: string) => void;\n headersSent?: boolean;\n },\n next: (err?: unknown) => void,\n ) => {\n // readiness probe: holding page polls this. blocks until no restart is in\n // flight, then 204 on success / 503 + JSON error if last attempt failed.\n if (req.url === READINESS_PATH) {\n await scheduler.waitForRestart();\n\n if (res.headersSent) return;\n\n const failure = scheduler.getLastFailure();\n\n if (failure) {\n res.writeHead(503, { 'cache-control': 'no-store', 'content-type': 'application/json' });\n res.end(JSON.stringify({ error: failure.message }));\n\n return;\n }\n\n res.writeHead(204, { 'cache-control': 'no-store' });\n res.end();\n\n return;\n }\n\n if (isDevInternalPath(req.url)) {\n next();\n\n return;\n }\n\n // respond now; awaiting the restart would let vite destroy the socket mid-response.\n if (scheduler.isRestartPending()) {\n res.writeHead(503, {\n 'content-type': 'text/html; charset=utf-8',\n 'cache-control': 'no-store',\n 'retry-after': '1',\n });\n res.end(RESTART_HTML);\n\n return;\n }\n\n next();\n }) as never,\n });\n}\n\nfunction isDevInternalPath(url: string | undefined): boolean {\n if (!url) return false;\n\n return url.startsWith('/@') || url.startsWith('/__') || url.includes('/node_modules/');\n}\n\n/**\n * Stamp the current generation onto every incoming request so the runtime\n * Astro middleware can later detect whether the request belongs to a previous\n * (now torn-down) generation\n */\nexport function installGenStamp(server: Pick<ViteDevServer, 'middlewares'>): void {\n const middlewares = server.middlewares as unknown as {\n stack: { route: string; handle: unknown }[];\n };\n\n middlewares.stack.unshift({\n route: '',\n handle: ((req: { headers: Record<string, string> }, _res: unknown, next: () => void) => {\n req.headers[GEN_HEADER] = String(getCurrentGeneration());\n next();\n }) as never,\n });\n}\n","import type { AstroConfig } from 'astro';\nimport type { Plugin } from 'vite';\nimport { setBootContext } from '../lifecycle/context.js';\nimport { type BootModule, runShutdown, runStartup } from '../lifecycle/lifecycle.js';\nimport type { BootContext } from '../lifecycle/types.js';\nimport { clearNativeMounts } from '../server/native-mount.js';\nimport { incrementGeneration } from './generation.js';\nimport { RestartScheduler } from './scheduler.js';\nimport { serializeError } from './serialize-error.js';\nimport { ssrImport } from './vite-env.js';\nimport { installBootGate, installGenStamp, setupBootWatch } from './watch.js';\n\ninterface Logger {\n info(msg: string): void;\n warn(msg: string): void;\n error(msg: string): void;\n}\n\nexport interface DevMachineryOptions {\n /** boot file path relative to the project root; undefined = no boot module */\n entry: string | undefined;\n /** restart the dev server when watched dependencies change */\n watch: boolean;\n /** extra files (relative to the root) whose changes restart the dev server */\n watchEntries: string[];\n /** platform seams; runs each generation before the boot module starts */\n prepare: (importModule: <T = Record<string, unknown>>(id: string) => Promise<T>) => Promise<void>;\n logger: Logger;\n getConfig: () => AstroConfig | null;\n}\n\n/**\n * Resolve the default host and port from the Astro server config.\n * Falls back to `localhost:4321` when no config is provided.\n */\nfunction getServerDefaults(config: AstroConfig | null): { host: string; port: number } {\n return {\n host:\n typeof config?.server?.host === 'string'\n ? config.server.host\n : config?.server?.host === true\n ? '0.0.0.0'\n : 'localhost',\n port: config?.server?.port ?? 4321,\n };\n}\n\n/**\n * Build a dev-mode boot context from the running server's address,\n * falling back to Astro config defaults if the server isn't listening yet.\n */\nfunction resolveBootContext(\n server: { httpServer?: { address(): unknown } | null | undefined },\n config: AstroConfig | null,\n): BootContext {\n const addr = server.httpServer?.address();\n\n if (addr && typeof addr === 'object' && 'address' in addr && 'port' in addr) {\n const host =\n (addr as { address: string }).address === '::' || (addr as { address: string }).address === '0.0.0.0'\n ? 'localhost'\n : (addr as { address: string }).address;\n\n return { dev: true, host, port: (addr as { port: number }).port };\n }\n\n const { host, port } = getServerDefaults(config);\n\n return { dev: true, host, port };\n}\n\n/**\n * The dev-mode boot machinery: runs the platform seams and the boot lifecycle\n * per restart generation, restarts the dev server when watched dependencies\n * change, and gates requests behind a holding page during restarts.\n */\nexport function createDevMachinery(options: DevMachineryOptions): Plugin[] {\n const { entry, logger } = options;\n\n let hasStartupSucceededOnce = false;\n // run by the next configureServer before its startup so resources (ports,\n // sockets, locks) from the previous module are released first. idempotent.\n let priorShutdown: (() => Promise<void>) | undefined;\n // shared across restart-induced configureServer reruns\n const scheduler = options.watch ? new RestartScheduler(100, logger) : undefined;\n\n return [\n // gate plugin: enforce 'post' + returned-function so our `stack.unshift`\n // (in installBootGate / installGenStamp) lands at connect position 0,\n // ahead of astro's handler.\n {\n name: '@astroscope/node/dev-gate',\n enforce: 'post',\n\n configureServer(server) {\n if (!scheduler) return;\n\n return () => {\n // gen-stamp is unshifted last so it ends up at position 0:\n // every request gets a generation header before anything else,\n // including the gate's readiness probe.\n installBootGate(server, scheduler);\n installGenStamp(server);\n };\n },\n },\n\n // startup plugin: runs after all other configureServer hooks\n {\n name: '@astroscope/node/dev-startup',\n enforce: 'post',\n\n async configureServer(server) {\n incrementGeneration();\n\n // tear down the previous module first so its resources are released\n // before the new startup tries to claim them.\n if (priorShutdown) {\n await priorShutdown();\n priorShutdown = undefined;\n }\n\n const astroConfig = options.getConfig();\n const bootContext = resolveBootContext(server, astroConfig);\n let bootModule: BootModule | undefined;\n\n setBootContext(bootContext);\n\n try {\n await options.prepare((id) => ssrImport(server, id));\n\n bootModule = entry ? await ssrImport<BootModule>(server, `/${entry}`) : {};\n\n await runStartup(bootModule, bootContext);\n } catch (error) {\n logger.error(`Error running startup script: ${serializeError(error)}`);\n\n if (bootModule) {\n try {\n await runShutdown(bootModule, bootContext);\n } catch {\n // best-effort cleanup\n }\n }\n\n // restart failure: the gate can keep the holding\n // page up with an error message instead of dropping users onto a\n // half-broken old server.\n if (hasStartupSucceededOnce) {\n scheduler?.recordFailure(serializeError(error));\n\n throw error;\n }\n\n // initial failure: exit cleanly (mirrors the production server).\n process.exit(1);\n }\n\n hasStartupSucceededOnce = true;\n scheduler?.clearFailure();\n\n // capture so shutdown sees the same instance that started.\n const startedModule = bootModule;\n let shutdownDone = false;\n\n const shutdown = async (): Promise<void> => {\n if (shutdownDone) return;\n\n shutdownDone = true;\n\n try {\n await runShutdown(startedModule, resolveBootContext(server, options.getConfig()));\n } catch (error) {\n logger.error(`Error running shutdown script: ${serializeError(error)}`);\n }\n\n // the next generation's onStartup re-registers its mounts\n clearNativeMounts();\n };\n\n priorShutdown = shutdown;\n\n // sigint/sigterm path. also fires during restart but shutdown is idempotent.\n server.httpServer?.once('close', () => {\n void shutdown();\n });\n\n if (scheduler) {\n setupBootWatch(server, [...(entry ? [entry] : []), ...options.watchEntries], scheduler);\n }\n },\n },\n ];\n}\n","import type { ExcludePattern } from './excludes.js';\n\n/**\n * Serialize exclude patterns to JavaScript code for use in virtual modules.\n * Handles RegExp objects which JSON.stringify cannot serialize.\n */\nexport function serializeExcludePatterns(patterns: ExcludePattern[]): string {\n return `[${patterns.map((p) => ('pattern' in p ? `{ pattern: ${p.pattern.toString()} }` : JSON.stringify(p))).join(', ')}]`;\n}\n","import type { Plugin } from 'vite';\n\n/**\n * emit sourcemaps only for the SSR build. client bundles are left unmapped\n * so browsers can't fetch source via `//# sourceMappingURL=`.\n *\n * vite 7's `environments.ssr.build.sourcemap` looks cleaner but wholesale\n * replaces astro's SSR build defaults (including entry file naming), which\n * breaks the embedded dev boot machinery. using `isSsrBuild` keeps the\n * rest of astro's SSR config intact.\n */\nexport function ssrSourcemapPlugin(): Plugin {\n return {\n name: '@astroscope/node/tweaks/sourcemap',\n config(_config, { isSsrBuild }) {\n if (isSsrBuild) return { build: { sourcemap: true } };\n\n return {};\n },\n };\n}\n","import { Parser } from 'acorn';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\n\nconst HOOK_NAMES = new Set(['useEffect', 'useLayoutEffect', 'useInsertionEffect']);\nconst REACT_SOURCE = /^react(\\/.*)?$/;\nconst TRANSFORMABLE = /\\.(?:[mc]?[jt]sx?)$/;\nconst EMPTY_FN = '(()=>{})';\n\n/**\n * in SSR builds, react effect hooks never execute. emptying their callbacks\n * lets rolldown drop dead branches — including dynamic imports of client-only\n * libs (maplibre-gl, hls.js, etc.) — from the server bundle, which in turn\n * stops nft from tracing them at docker-image time.\n *\n * scope is deliberately narrow: first-party code only (no node_modules), only\n * in the SSR pass, and binding-aware (the React import must resolve to the\n * real react package). raw chunks where bundling has erased the binding are\n * left alone — that's NFT's domain, not ours.\n */\nexport function stripSsrEffectsPlugin(): Plugin {\n return {\n name: '@astroscope/node/tweaks/strip-effects',\n enforce: 'post',\n transform(code, id, options) {\n if (!options?.ssr) return null;\n if (id.includes('/node_modules/')) return null;\n\n const cleanId = id.split('?')[0] ?? id;\n\n if (!TRANSFORMABLE.test(cleanId)) return null;\n if (!code.includes('useEffect') && !code.includes('useLayoutEffect') && !code.includes('useInsertionEffect')) {\n return null;\n }\n\n let ast: any;\n\n try {\n ast = Parser.parse(code, {\n ecmaVersion: 'latest',\n sourceType: 'module',\n allowReturnOutsideFunction: true,\n allowAwaitOutsideFunction: true,\n allowImportExportEverywhere: true,\n allowHashBang: true,\n });\n } catch {\n return null;\n }\n\n const directHooks = new Set<string>();\n const namespaceHooks = new Set<string>();\n\n walk(ast, (node) => {\n if (node.type !== 'ImportDeclaration') return;\n\n const src = node.source?.value;\n\n if (typeof src !== 'string' || !REACT_SOURCE.test(src)) return;\n\n for (const spec of node.specifiers ?? []) {\n if (spec.type === 'ImportSpecifier') {\n const imported = spec.imported?.name ?? spec.imported?.value;\n\n if (HOOK_NAMES.has(imported)) directHooks.add(spec.local.name);\n } else if (spec.type === 'ImportDefaultSpecifier' || spec.type === 'ImportNamespaceSpecifier') {\n namespaceHooks.add(spec.local.name);\n }\n }\n });\n\n if (directHooks.size === 0 && namespaceHooks.size === 0) return null;\n\n const replacements: { start: number; end: number }[] = [];\n\n walk(ast, (node) => {\n if (node.type !== 'CallExpression' || !node.arguments?.length) return;\n\n const callee = node.callee;\n const isDirect = callee.type === 'Identifier' && directHooks.has(callee.name);\n const isMember =\n callee.type === 'MemberExpression' &&\n !callee.computed &&\n callee.object?.type === 'Identifier' &&\n namespaceHooks.has(callee.object.name) &&\n callee.property?.type === 'Identifier' &&\n HOOK_NAMES.has(callee.property.name);\n\n if (!isDirect && !isMember) return;\n\n const arg = node.arguments[0];\n\n replacements.push({ start: arg.start, end: arg.end });\n });\n\n if (replacements.length === 0) return null;\n\n const s = new MagicString(code);\n\n for (const { start, end } of replacements) {\n s.overwrite(start, end, EMPTY_FN);\n }\n\n return { code: s.toString(), map: s.generateMap({ hires: true }) };\n },\n };\n}\n\nfunction walk(node: any, visit: (n: any) => void): void {\n if (!node || typeof node !== 'object') return;\n\n if (typeof node.type === 'string') visit(node);\n\n for (const key of Object.keys(node)) {\n const v = node[key];\n\n if (Array.isArray(v)) for (const item of v) walk(item, visit);\n else if (v && typeof v === 'object') walk(v, visit);\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { AstroConfig, AstroIntegration } from 'astro';\nimport { createIslandWarmup } from '../dev-mode/island-warmup.js';\nimport { createDevMachinery } from '../dev-mode/machinery.js';\nimport { type ExcludePattern, RECOMMENDED_EXCLUDES } from '../excludes/excludes.js';\nimport { serializeExcludePatterns } from '../excludes/serialize.js';\nimport { createRequestInstrumentation } from '../observability/instrument.js';\nimport { preparePlatform } from '../platform/prepare.js';\nimport { dispatchNativeMount } from '../server/native-mount.js';\nimport { ssrSourcemapPlugin } from '../tweaks/sourcemap.js';\nimport { stripSsrEffectsPlugin } from '../tweaks/strip-effects.js';\nimport type { NodeOptions, RuntimeOptions } from '../types.js';\n\nexport const CONFIG_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/config';\nexport const BOOT_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/boot';\nexport const CSRF_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/csrf';\nexport const CONFIG_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/config-entry';\nexport const INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/instrumentation-entry';\nexport const LOG_ENTRY_VIRTUAL_MODULE_ID = 'virtual:@astroscope/node/log-entry';\n\nconst RESOLVED_CONFIG_VIRTUAL_MODULE_ID = `\\0${CONFIG_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_BOOT_VIRTUAL_MODULE_ID = `\\0${BOOT_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_CSRF_VIRTUAL_MODULE_ID = `\\0${CSRF_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID = `\\0${CONFIG_ENTRY_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID = `\\0${INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID}`;\nconst RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID = `\\0${LOG_ENTRY_VIRTUAL_MODULE_ID}`;\n\nconst SERVER_ENVIRONMENTS = ['ssr', 'prerender', 'astro'];\nconst DEFAULT_REQUEST_EXCLUDES: ExcludePattern[] = [...RECOMMENDED_EXCLUDES];\n\nfunction resolveHost(host: string | boolean | undefined): string {\n if (typeof host === 'string') return host;\n\n return host === true ? '0.0.0.0' : 'localhost';\n}\n\nfunction resolveBootEntry(root: string, entry: string | undefined): string | undefined {\n if (entry) {\n const abs = path.resolve(root, entry);\n\n if (!fs.existsSync(abs)) {\n throw new Error(`[@astroscope/node] boot entry not found: ${entry}`);\n }\n\n return abs;\n }\n\n for (const candidate of ['src/boot/index.ts', 'src/boot.ts']) {\n const abs = path.resolve(root, candidate);\n\n if (fs.existsSync(abs)) return abs;\n }\n\n return undefined;\n}\n\nfunction resolveSeam(root: string, candidate: string): string | undefined {\n const abs = path.resolve(root, candidate);\n\n return fs.existsSync(abs) ? abs : undefined;\n}\n\n/**\n * Node adapter for Astro with a first-class server entrypoint: the boot\n * lifecycle, module warmup, health probes, request logging and telemetry run\n * as plain code around `server.listen()` instead of being injected into the\n * build output.\n */\nexport default function node(options: NodeOptions = {}): AstroIntegration {\n const bootOptions = options.boot ?? {};\n const healthOptions = options.health ?? {};\n const csrfOptions = options.csrf ?? {};\n const loggingOptions = options.logging ?? {};\n const telemetryOptions = options.telemetry ?? {};\n\n const loggingExclude = loggingOptions ? (loggingOptions.exclude ?? DEFAULT_REQUEST_EXCLUDES) : [];\n const telemetryExclude = telemetryOptions ? (telemetryOptions.exclude ?? DEFAULT_REQUEST_EXCLUDES) : [];\n\n let astroConfig: AstroConfig | null = null;\n let bootEntry: string | undefined;\n let configSeam: string | undefined;\n let instrumentationSeam: string | undefined;\n let logSeam: string | undefined;\n let isDev = false;\n\n return {\n name: '@astroscope/node',\n hooks: {\n 'astro:config:setup': ({ command, config, updateConfig, addMiddleware, logger }) => {\n isDev = command === 'dev';\n\n // route enrichment first so csrf-rejected requests still carry a route\n if (loggingOptions || telemetryOptions) {\n addMiddleware({ order: 'pre', entrypoint: '@astroscope/node/route-middleware' });\n }\n\n if (csrfOptions) {\n addMiddleware({ order: 'pre', entrypoint: '@astroscope/node/csrf-middleware' });\n }\n\n const root = fileURLToPath(config.root);\n const watch = bootOptions === false ? false : (bootOptions.watch ?? true);\n\n bootEntry = bootOptions === false ? undefined : resolveBootEntry(root, bootOptions.entry);\n configSeam = resolveSeam(root, 'src/config.ts');\n instrumentationSeam = resolveSeam(root, 'src/instrumentation.ts');\n logSeam = resolveSeam(root, 'src/log.ts');\n\n const relativeSeam = (abs: string | undefined) =>\n abs ? path.relative(root, abs).split(path.sep).join('/') : undefined;\n\n const devMachinery =\n command === 'dev' && bootOptions !== false\n ? createDevMachinery({\n entry: bootEntry ? path.relative(root, bootEntry) : undefined,\n watch,\n // instrumentation runs once per process — watching it would\n // restart generations that can't re-apply it\n watchEntries: [relativeSeam(configSeam), relativeSeam(logSeam)].filter(\n (entry): entry is string => !!entry,\n ),\n prepare: (importModule) =>\n preparePlatform({\n dev: true,\n telemetry:\n telemetryOptions && telemetryOptions.dev\n ? { prometheus: telemetryOptions.prometheus ?? {} }\n : false,\n seams: {\n ...(configSeam && { config: () => importModule(`/${relativeSeam(configSeam)}`) }),\n ...(instrumentationSeam && {\n instrumentation: () => importModule(`/${relativeSeam(instrumentationSeam)}`),\n }),\n ...(logSeam && { log: () => importModule(`/${relativeSeam(logSeam)}`) }),\n },\n }),\n logger,\n getConfig: () => astroConfig,\n })\n : [];\n\n if (command === 'dev' && bootOptions !== false && watch) {\n // catches errors thrown by stale (post-shutdown) requests so\n // they don't pollute the logs during dev-server restarts.\n addMiddleware({ entrypoint: '@astroscope/node/dev-middleware', order: 'pre' });\n }\n\n const islandWarmup =\n command === 'dev' ? [createIslandWarmup({ root, srcDir: fileURLToPath(config.srcDir), logger })] : [];\n\n updateConfig({\n build: { redirects: false },\n // opinionated defaults: no trailing slashes, behind LB\n ...(config.trailingSlash === 'ignore' && { trailingSlash: 'never' as const }),\n security: {\n // assumed to run behind LB\n ...(!config.security.allowedDomains?.length && { allowedDomains: [{}] }),\n // the embedded csrf middleware replaces the built-in origin check\n ...(csrfOptions && { checkOrigin: false }),\n },\n image: {\n endpoint: {\n route: config.image.endpoint.route ?? '_image',\n entrypoint:\n config.image.endpoint.entrypoint ??\n (command === 'dev' ? 'astro/assets/endpoint/dev' : 'astro/assets/endpoint/node'),\n },\n },\n vite: {\n plugins: [\n ...devMachinery,\n ...islandWarmup,\n ssrSourcemapPlugin(),\n stripSsrEffectsPlugin(),\n {\n name: '@astroscope/node',\n\n configEnvironment(environmentName: string) {\n if (SERVER_ENVIRONMENTS.includes(environmentName)) {\n return { resolve: { noExternal: ['@astroscope/node'] } };\n }\n },\n\n resolveId(id: string) {\n if (id === CONFIG_VIRTUAL_MODULE_ID) return RESOLVED_CONFIG_VIRTUAL_MODULE_ID;\n if (id === BOOT_VIRTUAL_MODULE_ID) return RESOLVED_BOOT_VIRTUAL_MODULE_ID;\n if (id === CSRF_VIRTUAL_MODULE_ID) return RESOLVED_CSRF_VIRTUAL_MODULE_ID;\n if (id === CONFIG_ENTRY_VIRTUAL_MODULE_ID) return RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID;\n if (id === INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID) {\n return RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID;\n }\n if (id === LOG_ENTRY_VIRTUAL_MODULE_ID) return RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID;\n },\n\n load(id: string) {\n if (id === RESOLVED_CONFIG_VIRTUAL_MODULE_ID) {\n if (!astroConfig) throw new Error('[@astroscope/node] astro config not resolved yet');\n\n const runtimeOptions: Omit<RuntimeOptions, 'logging' | 'telemetry'> = {\n host: resolveHost(astroConfig.server.host),\n port: astroConfig.server.port ?? 4321,\n client: astroConfig.build.client.toString(),\n server: astroConfig.build.server.toString(),\n bodySizeLimit: options.bodySizeLimit ?? 1024 * 1024 * 1024,\n shutdownTimeout: options.shutdownTimeout ?? 10_000,\n health: healthOptions\n ? {\n ...(healthOptions.host !== undefined && { host: healthOptions.host }),\n ...(healthOptions.port !== undefined && { port: healthOptions.port }),\n ...(healthOptions.paths && { paths: healthOptions.paths }),\n }\n : false,\n };\n\n // exclude patterns may contain RegExp — serialized as code, not JSON\n const logging = loggingOptions\n ? `{ exclude: ${serializeExcludePatterns(loggingExclude)}, extended: ${JSON.stringify(\n loggingOptions.extended ?? false,\n )} }`\n : 'false';\n const telemetry = telemetryOptions\n ? `{ exclude: ${serializeExcludePatterns(telemetryExclude)}, prometheus: ${JSON.stringify(\n telemetryOptions.prometheus ?? {},\n )} }`\n : 'false';\n\n return `export const options = { ...${JSON.stringify(runtimeOptions)}, logging: ${logging}, telemetry: ${telemetry} };`;\n }\n\n if (id === RESOLVED_BOOT_VIRTUAL_MODULE_ID) {\n // re-export to avoid absolute path manifest leaks\n return bootEntry ? `export * from ${JSON.stringify(bootEntry)};` : 'export {};';\n }\n\n if (id === RESOLVED_CSRF_VIRTUAL_MODULE_ID) {\n return `export const excludePatterns = ${serializeExcludePatterns(csrfOptions ? (csrfOptions.exclude ?? []) : [])};`;\n }\n\n if (id === RESOLVED_CONFIG_ENTRY_VIRTUAL_MODULE_ID) {\n // side-effect import: @entwico/zod-conf validation runs at module load\n return configSeam ? `import ${JSON.stringify(configSeam)};\\nexport {};` : 'export {};';\n }\n\n if (id === RESOLVED_INSTRUMENTATION_ENTRY_VIRTUAL_MODULE_ID) {\n return instrumentationSeam ? `export * from ${JSON.stringify(instrumentationSeam)};` : 'export {};';\n }\n\n if (id === RESOLVED_LOG_ENTRY_VIRTUAL_MODULE_ID) {\n return logSeam\n ? `export { default } from ${JSON.stringify(logSeam)};`\n : 'export default undefined;';\n }\n },\n },\n ],\n },\n });\n },\n 'astro:server:setup': ({ server }) => {\n if (!isDev) return;\n\n const devLogging = loggingOptions && loggingOptions.dev;\n const devTelemetry = telemetryOptions && telemetryOptions.dev;\n\n const instrument =\n devLogging || devTelemetry\n ? createRequestInstrumentation({\n logging: devLogging ? { exclude: loggingExclude, extended: loggingOptions.extended ?? false } : false,\n telemetry: devTelemetry ? { exclude: telemetryExclude } : false,\n })\n : undefined;\n\n server.middlewares.use((req, res, next) => {\n const inner = (): void => {\n if (!dispatchNativeMount(req, res)) next();\n };\n\n if (instrument) {\n instrument(req, res, inner);\n } else {\n inner();\n }\n });\n },\n 'astro:config:done': ({ config, setAdapter }) => {\n astroConfig = config;\n\n setAdapter({\n name: '@astroscope/node',\n entrypointResolution: 'auto',\n serverEntrypoint: '@astroscope/node/server',\n previewEntrypoint: '@astroscope/node/preview',\n adapterFeatures: {\n buildOutput: 'server',\n middlewareMode: 'classic',\n },\n supportedAstroFeatures: {\n hybridOutput: 'stable',\n staticOutput: 'stable',\n serverOutput: 'stable',\n sharpImageService: 'stable',\n i18nDomains: 'experimental',\n envGetSecret: 'stable',\n },\n });\n },\n 'astro:build:done': async ({ logger }) => {\n if (!astroConfig) return;\n\n const { compressClientDir } = await import('../compress/compress.js');\n\n await compressClientDir(fileURLToPath(astroConfig.build.client), logger);\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as on, i as off, n as BootEventName, r as emit, t as BootEventHandler } from "../events-
|
|
1
|
+
import { a as on, i as off, n as BootEventName, r as emit, t as BootEventHandler } from "../events-u7J3ezJR.js";
|
|
2
2
|
export { BootEventHandler, BootEventName, emit, off, on };
|
package/dist/log/index.d.ts
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
|
-
import { t as LoggerOptionsFactory } from "../construct-
|
|
1
|
+
import { t as LoggerOptionsFactory } from "../construct-BGlPfWMF.js";
|
|
2
2
|
import { Bindings, Bindings as Bindings$1, Logger, Logger as Logger$1, LoggerOptions } from "pino";
|
|
3
|
-
|
|
3
|
+
//#region src/observability/request-route.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Report the route that actually served the current request, overriding the one
|
|
6
|
+
* astro's routing matched.
|
|
7
|
+
*
|
|
8
|
+
* A middleware that rewrites (`next(url)`) or answers with its own response
|
|
9
|
+
* serves a request astro has no page for, so routing matches `/404` and that is
|
|
10
|
+
* what the request is logged and measured as — every such request collapsing
|
|
11
|
+
* into one `/404` bucket in the request metrics. Calling this corrects the log
|
|
12
|
+
* line, the metric and the server span name together.
|
|
13
|
+
*
|
|
14
|
+
* Pass a templated label rather than a concrete path, so metric cardinality
|
|
15
|
+
* stays bounded. No-op outside instrumented requests.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { overrideRequestRoute } from '@astroscope/node/log';
|
|
20
|
+
*
|
|
21
|
+
* export const onRequest: MiddlewareHandler = (ctx, next) => {
|
|
22
|
+
* const page = lookupPage(ctx.url.pathname);
|
|
23
|
+
*
|
|
24
|
+
* if (!page) return next();
|
|
25
|
+
*
|
|
26
|
+
* overrideRequestRoute('/cms/pages/[id]');
|
|
27
|
+
*
|
|
28
|
+
* return next(`/cms/pages/${page.id}`);
|
|
29
|
+
* };
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare function overrideRequestRoute(route: string): void;
|
|
33
|
+
//#endregion
|
|
4
34
|
//#region src/observability/log/index.d.ts
|
|
5
35
|
/**
|
|
6
36
|
* Generate a short request ID.
|
|
@@ -51,5 +81,5 @@ interface LogProxy {
|
|
|
51
81
|
*/
|
|
52
82
|
declare const log: LogProxy;
|
|
53
83
|
//#endregion
|
|
54
|
-
export { type Bindings, LogProxy, type Logger, type LoggerOptions, type LoggerOptionsFactory, generateReqId, log };
|
|
84
|
+
export { type Bindings, LogProxy, type Logger, type LoggerOptions, type LoggerOptionsFactory, generateReqId, log, overrideRequestRoute };
|
|
55
85
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/log/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/observability/log/index.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/observability/request-route.ts","../../src/observability/log/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+DgB,qBAAqB;;;;;;;iBC5CrB;;;;UAiBC;;WAEN,OAAO;;WAEP,OAAO;;WAEP,MAAM;;WAEN,MAAM;;WAEN,OAAO;;WAEP,OAAO;;EAEhB,MAAM,UAAU,aAAW;;WAElB,KAAK;;WAEL,MAAM;;;;;;;;;;;;;;;;;;;;;cAgGJ,KAAK"}
|
package/dist/log/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { t as overrideRequestRoute } from "../request-route-DcnZOOM4.js";
|
|
2
|
+
import { n as log, t as generateReqId } from "../log-B69HEBvg.js";
|
|
3
|
+
export { generateReqId, log, overrideRequestRoute };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { r as getLogStore } from "./request-route-DcnZOOM4.js";
|
|
2
2
|
import { randomUUID } from "node:crypto";
|
|
3
3
|
import pino from "pino";
|
|
4
4
|
//#region src/observability/log/index.ts
|
|
@@ -109,4 +109,4 @@ const log = createLogProxy([]);
|
|
|
109
109
|
//#endregion
|
|
110
110
|
export { log as n, generateReqId as t };
|
|
111
111
|
|
|
112
|
-
//# sourceMappingURL=log-
|
|
112
|
+
//# sourceMappingURL=log-B69HEBvg.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-
|
|
1
|
+
{"version":3,"file":"log-B69HEBvg.js","names":[],"sources":["../src/observability/log/index.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport pino, { type Bindings, type Logger } from 'pino';\nimport { type BufferedEntry, EARLY_LOG_BUFFER_CAP, type LogStore, getLogStore } from './store.js';\n\nlet fallbackLogger: Logger | undefined;\n\n/**\n * Get the current request logger, root logger, or a plain fallback instance\n * when the root logger hasn't been constructed yet.\n * @internal\n */\nfunction contextLogger(store: LogStore): Logger {\n return store.requestStorage.getStore()?.logger ?? store.root ?? (fallbackLogger ??= pino({ level: 'info' }));\n}\n\n/**\n * Generate a short request ID.\n * @internal\n */\nexport function generateReqId(): string {\n return randomUUID().slice(0, 8);\n}\n\nfunction bufferEntry(store: LogStore, level: BufferedEntry['level'], bindings: Bindings[], args: unknown[]): void {\n if (store.buffer.length >= EARLY_LOG_BUFFER_CAP) {\n store.dropped += 1;\n\n return;\n }\n\n store.buffer.push({ level, bindings, args, time: Date.now() });\n}\n\n/**\n * Log proxy interface — context-aware logging via getters.\n */\nexport interface LogProxy {\n /** Log at trace level */\n readonly trace: Logger['trace'];\n /** Log at debug level */\n readonly debug: Logger['debug'];\n /** Log at info level */\n readonly info: Logger['info'];\n /** Log at warn level */\n readonly warn: Logger['warn'];\n /** Log at error level */\n readonly error: Logger['error'];\n /** Log at fatal level */\n readonly fatal: Logger['fatal'];\n /** Create a child logger with additional bindings */\n child(bindings: Bindings): LogProxy;\n /** Access the current context's raw pino Logger */\n readonly raw: Logger;\n /** Access the root logger (no request context) */\n readonly root: Logger;\n}\n\n/**\n * Create a log proxy carrying accumulated child bindings. Before the root\n * logger is constructed, entries are buffered (with their bindings) and\n * replayed through the real logger on construction.\n */\nfunction createLogProxy(bindings: Bindings[]): LogProxy {\n const store = getLogStore();\n\n // cache the derived child against the logger it was derived from, so a\n // proxy created before construction transparently rebinds afterwards\n let cachedBase: Logger | undefined;\n let cachedChild: Logger | undefined;\n\n const resolve = (): Logger => {\n const base = contextLogger(store);\n\n if (!bindings.length) return base;\n\n if (cachedBase !== base) {\n cachedBase = base;\n cachedChild = base.child(Object.assign({}, ...bindings) as Bindings);\n }\n\n return cachedChild!;\n };\n\n const method = (level: BufferedEntry['level']) => {\n if (!store.root) {\n const record = store.requestStorage.getStore();\n\n // request-scoped loggers exist only after construction; buffer otherwise\n if (!record?.logger) {\n return (...args: unknown[]) => bufferEntry(store, level, bindings, args);\n }\n }\n\n const logger = resolve();\n\n return logger[level].bind(logger);\n };\n\n return {\n get trace() {\n return method('trace') as Logger['trace'];\n },\n get debug() {\n return method('debug') as Logger['debug'];\n },\n get info() {\n return method('info') as Logger['info'];\n },\n get warn() {\n return method('warn') as Logger['warn'];\n },\n get error() {\n return method('error') as Logger['error'];\n },\n get fatal() {\n return method('fatal') as Logger['fatal'];\n },\n child(childBindings: Bindings): LogProxy {\n return createLogProxy([...bindings, childBindings]);\n },\n get raw() {\n return resolve();\n },\n get root() {\n const base = getLogStore().root ?? (fallbackLogger ??= pino({ level: 'info' }));\n\n return bindings.length ? base.child(Object.assign({}, ...bindings) as Bindings) : base;\n },\n };\n}\n\n/**\n * Context-aware logger. Inside a request, entries carry the request bindings\n * (`reqId`, `req`); outside they go to the root logger. Entries logged before\n * the root logger is constructed (env loading, config, instrumentation) are\n * buffered and replayed once construction completes — the original timestamp\n * is kept as a `bufferedTime` field.\n *\n * @example\n * ```ts\n * import { log } from '@astroscope/node/log';\n *\n * log.info('handling request');\n * log.info({ userId: 123 }, 'user logged in');\n * log.error(err, 'operation failed');\n *\n * const dbLog = log.child({ component: 'db' });\n * dbLog.debug('executing query');\n * ```\n */\nexport const log: LogProxy = createLogProxy([]);\n\n// public surface for middleware that serves a route astro never matched\nexport { overrideRequestRoute } from '../request-route.js';\n\n// re-exported so apps don't need a direct pino dependency for typing\nexport type { Logger, LoggerOptions, Bindings } from 'pino';\n\n// contract of the src/log.ts entry seam\nexport type { LoggerOptionsFactory } from './construct.js';\n"],"mappings":";;;;AAIA,IAAI;;;;;;AAOJ,SAAS,cAAc,OAAyB;CAC9C,OAAO,MAAM,eAAe,SAAS,CAAC,EAAE,UAAU,MAAM,SAAS,mBAAmB,KAAK,EAAE,OAAO,OAAO,CAAC;AAC5G;;;;;AAMA,SAAgB,gBAAwB;CACtC,OAAO,WAAW,CAAC,CAAC,MAAM,GAAG,CAAC;AAChC;AAEA,SAAS,YAAY,OAAiB,OAA+B,UAAsB,MAAuB;CAChH,IAAI,MAAM,OAAO,UAAA,KAAgC;EAC/C,MAAM,WAAW;EAEjB;CACF;CAEA,MAAM,OAAO,KAAK;EAAE;EAAO;EAAU;EAAM,MAAM,KAAK,IAAI;CAAE,CAAC;AAC/D;;;;;;AA+BA,SAAS,eAAe,UAAgC;CACtD,MAAM,QAAQ,YAAY;CAI1B,IAAI;CACJ,IAAI;CAEJ,MAAM,gBAAwB;EAC5B,MAAM,OAAO,cAAc,KAAK;EAEhC,IAAI,CAAC,SAAS,QAAQ,OAAO;EAE7B,IAAI,eAAe,MAAM;GACvB,aAAa;GACb,cAAc,KAAK,MAAM,OAAO,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAa;EACrE;EAEA,OAAO;CACT;CAEA,MAAM,UAAU,UAAkC;EAChD,IAAI,CAAC,MAAM;OAIL,CAHW,MAAM,eAAe,SAG1B,CAAC,EAAE,QACX,QAAQ,GAAG,SAAoB,YAAY,OAAO,OAAO,UAAU,IAAI;EAAA;EAI3E,MAAM,SAAS,QAAQ;EAEvB,OAAO,OAAO,MAAM,CAAC,KAAK,MAAM;CAClC;CAEA,OAAO;EACL,IAAI,QAAQ;GACV,OAAO,OAAO,OAAO;EACvB;EACA,IAAI,QAAQ;GACV,OAAO,OAAO,OAAO;EACvB;EACA,IAAI,OAAO;GACT,OAAO,OAAO,MAAM;EACtB;EACA,IAAI,OAAO;GACT,OAAO,OAAO,MAAM;EACtB;EACA,IAAI,QAAQ;GACV,OAAO,OAAO,OAAO;EACvB;EACA,IAAI,QAAQ;GACV,OAAO,OAAO,OAAO;EACvB;EACA,MAAM,eAAmC;GACvC,OAAO,eAAe,CAAC,GAAG,UAAU,aAAa,CAAC;EACpD;EACA,IAAI,MAAM;GACR,OAAO,QAAQ;EACjB;EACA,IAAI,OAAO;GACT,MAAM,OAAO,YAAY,CAAC,CAAC,SAAS,mBAAmB,KAAK,EAAE,OAAO,OAAO,CAAC;GAE7E,OAAO,SAAS,SAAS,KAAK,MAAM,OAAO,OAAO,CAAC,GAAG,GAAG,QAAQ,CAAa,IAAI;EACpF;CACF;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,MAAgB,eAAe,CAAC,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as log } from "./log-
|
|
3
|
-
import { trace } from "@opentelemetry/api";
|
|
1
|
+
import { t as overrideRequestRoute } from "./request-route-DcnZOOM4.js";
|
|
2
|
+
import { n as log } from "./log-B69HEBvg.js";
|
|
4
3
|
//#region src/server/native-mount.ts
|
|
5
4
|
/**
|
|
6
5
|
* Native mounts: raw `(req, res)` handlers dispatched before static/astro,
|
|
@@ -93,15 +92,7 @@ function failResponse(res) {
|
|
|
93
92
|
function dispatchNativeMount(req, res) {
|
|
94
93
|
const mount = findMount(req);
|
|
95
94
|
if (!mount) return false;
|
|
96
|
-
if (mount.name)
|
|
97
|
-
const record = getRequestRecord();
|
|
98
|
-
if (record && !record.route) record.route = mount.name;
|
|
99
|
-
const span = trace.getActiveSpan();
|
|
100
|
-
if (span?.isRecording()) {
|
|
101
|
-
span.setAttribute("http.route", mount.name);
|
|
102
|
-
span.updateName(`${req.method ?? "GET"} ${mount.name}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
95
|
+
if (mount.name) overrideRequestRoute(mount.name);
|
|
105
96
|
try {
|
|
106
97
|
const result = mount.handler(req, res);
|
|
107
98
|
if (result instanceof Promise) result.catch((err) => {
|
|
@@ -117,4 +108,4 @@ function dispatchNativeMount(req, res) {
|
|
|
117
108
|
//#endregion
|
|
118
109
|
export { dispatchNativeMount as n, mountNativeHandler as r, clearNativeMounts as t };
|
|
119
110
|
|
|
120
|
-
//# sourceMappingURL=native-mount-
|
|
111
|
+
//# sourceMappingURL=native-mount-DjYEnO4X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native-mount-DjYEnO4X.js","names":[],"sources":["../src/server/native-mount.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { log } from '../observability/log/index.js';\nimport { overrideRequestRoute } from '../observability/request-route.js';\n\n/**\n * Native mounts: raw `(req, res)` handlers dispatched before static/astro,\n * for Node libraries that need the real request and response (e.g.\n * `oidc-provider`'s `callback()`). Mounted requests bypass astro middleware\n * entirely but stay inside request logging and tracing.\n *\n * Keyed on `globalThis` because registration (boot file, vite runner in dev)\n * and dispatch (server runtime) may live in different module instances.\n */\n\nconst STORE_KEY = Symbol.for('@astroscope/node/native-mounts');\n\nexport type NativeHandler = (req: IncomingMessage, res: ServerResponse) => void | Promise<void>;\n\nexport interface NativeMountMatcher {\n /** match requests whose pathname starts with this prefix */\n prefix?: string | undefined;\n\n /** predicate over the native request; evaluated when no prefix mount matches */\n match?: ((req: IncomingMessage) => boolean) | undefined;\n\n /** route label for logs, metrics and span names; defaults to the prefix */\n name?: string | undefined;\n}\n\ninterface Mount {\n prefix: string | undefined;\n match: ((req: IncomingMessage) => boolean) | undefined;\n name: string | undefined;\n handler: NativeHandler;\n}\n\ninterface Store {\n mounts: Mount[];\n}\n\nfunction getStore(): Store {\n const g = globalThis as Record<symbol, unknown>;\n let store = g[STORE_KEY] as Store | undefined;\n\n if (!store) {\n store = { mounts: [] };\n g[STORE_KEY] = store;\n }\n\n return store;\n}\n\nfunction matchesPrefix(pathname: string, prefix: string): boolean {\n if (!pathname.startsWith(prefix)) return false;\n\n const rest = pathname.slice(prefix.length);\n\n return rest === '' || rest.startsWith('/') || rest.startsWith('?');\n}\n\n/**\n * Mount a native `(req, res)` handler on the adapter's server. The handler\n * owns the response completely — matched requests never reach astro\n * middleware or rendering. Dispatch happens before static file serving, in\n * production and dev alike.\n *\n * Call from `onStartup`. Returns an unregister function; mounts still\n * registered after `onShutdown` are removed automatically.\n *\n * When several prefix mounts match, the longest prefix wins; predicate\n * mounts are consulted afterwards in registration order.\n *\n * @example\n * ```ts\n * // src/boot.ts\n * import { mountNativeHandler } from '@astroscope/node/native';\n *\n * export function onStartup() {\n * mountNativeHandler({ prefix: '/oidc', name: 'oidc' }, getOidcProvider().callback());\n * }\n * ```\n */\nexport function mountNativeHandler(matcher: NativeMountMatcher, handler: NativeHandler): () => void {\n if (!matcher.prefix && !matcher.match) {\n throw new Error('[@astroscope/node] mountNativeHandler requires a prefix or a match predicate');\n }\n\n const mount: Mount = {\n prefix: matcher.prefix,\n match: matcher.match,\n name: matcher.name ?? matcher.prefix,\n handler,\n };\n\n const store = getStore();\n\n store.mounts.push(mount);\n\n return () => {\n const index = store.mounts.indexOf(mount);\n\n if (index !== -1) store.mounts.splice(index, 1);\n };\n}\n\n/**\n * Remove every registered mount. Runs after `onShutdown` (prod) and between\n * dev generations, so re-running `onStartup` never stacks duplicates.\n */\nexport function clearNativeMounts(): void {\n getStore().mounts.length = 0;\n}\n\nfunction findMount(req: IncomingMessage): Mount | undefined {\n const url = req.url ?? '';\n const queryIndex = url.indexOf('?');\n const pathname = queryIndex === -1 ? url : url.slice(0, queryIndex);\n\n let best: Mount | undefined;\n\n for (const mount of getStore().mounts) {\n if (mount.prefix && matchesPrefix(pathname, mount.prefix)) {\n if (!best?.prefix || mount.prefix.length > best.prefix.length) {\n best = mount;\n }\n }\n }\n\n if (best) return best;\n\n return getStore().mounts.find((mount) => mount.match?.(req));\n}\n\nfunction failResponse(res: ServerResponse): void {\n if (res.writableEnded) return;\n\n if (!res.headersSent) {\n res.writeHead(500, { 'content-type': 'text/plain' });\n }\n\n res.end('Internal Server Error');\n}\n\n/**\n * Dispatch a request to a matching mount. Returns `false` when no mount\n * matches — the caller continues with static/astro handling.\n */\nexport function dispatchNativeMount(req: IncomingMessage, res: ServerResponse): boolean {\n const mount = findMount(req);\n\n if (!mount) return false;\n\n // the mount, not astro's routing, is what serves this request\n if (mount.name) {\n overrideRequestRoute(mount.name);\n }\n\n try {\n const result = mount.handler(req, res);\n\n if (result instanceof Promise) {\n result.catch((err: unknown) => {\n log.error(err instanceof Error ? { err } : { reason: err }, 'native mount handler failed');\n failResponse(res);\n });\n }\n } catch (err) {\n log.error(err instanceof Error ? { err } : { reason: err }, 'native mount handler failed');\n failResponse(res);\n }\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,YAAY,OAAO,IAAI,gCAAgC;AA0B7D,SAAS,WAAkB;CACzB,MAAM,IAAI;CACV,IAAI,QAAQ,EAAE;CAEd,IAAI,CAAC,OAAO;EACV,QAAQ,EAAE,QAAQ,CAAC,EAAE;EACrB,EAAE,aAAa;CACjB;CAEA,OAAO;AACT;AAEA,SAAS,cAAc,UAAkB,QAAyB;CAChE,IAAI,CAAC,SAAS,WAAW,MAAM,GAAG,OAAO;CAEzC,MAAM,OAAO,SAAS,MAAM,OAAO,MAAM;CAEzC,OAAO,SAAS,MAAM,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG;AACnE;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,mBAAmB,SAA6B,SAAoC;CAClG,IAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAC9B,MAAM,IAAI,MAAM,8EAA8E;CAGhG,MAAM,QAAe;EACnB,QAAQ,QAAQ;EAChB,OAAO,QAAQ;EACf,MAAM,QAAQ,QAAQ,QAAQ;EAC9B;CACF;CAEA,MAAM,QAAQ,SAAS;CAEvB,MAAM,OAAO,KAAK,KAAK;CAEvB,aAAa;EACX,MAAM,QAAQ,MAAM,OAAO,QAAQ,KAAK;EAExC,IAAI,UAAU,IAAI,MAAM,OAAO,OAAO,OAAO,CAAC;CAChD;AACF;;;;;AAMA,SAAgB,oBAA0B;CACxC,SAAS,CAAC,CAAC,OAAO,SAAS;AAC7B;AAEA,SAAS,UAAU,KAAyC;CAC1D,MAAM,MAAM,IAAI,OAAO;CACvB,MAAM,aAAa,IAAI,QAAQ,GAAG;CAClC,MAAM,WAAW,eAAe,KAAK,MAAM,IAAI,MAAM,GAAG,UAAU;CAElE,IAAI;CAEJ,KAAK,MAAM,SAAS,SAAS,CAAC,CAAC,QAC7B,IAAI,MAAM,UAAU,cAAc,UAAU,MAAM,MAAM;MAClD,CAAC,MAAM,UAAU,MAAM,OAAO,SAAS,KAAK,OAAO,QACrD,OAAO;CAAA;CAKb,IAAI,MAAM,OAAO;CAEjB,OAAO,SAAS,CAAC,CAAC,OAAO,MAAM,UAAU,MAAM,QAAQ,GAAG,CAAC;AAC7D;AAEA,SAAS,aAAa,KAA2B;CAC/C,IAAI,IAAI,eAAe;CAEvB,IAAI,CAAC,IAAI,aACP,IAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;CAGrD,IAAI,IAAI,uBAAuB;AACjC;;;;;AAMA,SAAgB,oBAAoB,KAAsB,KAA8B;CACtF,MAAM,QAAQ,UAAU,GAAG;CAE3B,IAAI,CAAC,OAAO,OAAO;CAGnB,IAAI,MAAM,MACR,qBAAqB,MAAM,IAAI;CAGjC,IAAI;EACF,MAAM,SAAS,MAAM,QAAQ,KAAK,GAAG;EAErC,IAAI,kBAAkB,SACpB,OAAO,OAAO,QAAiB;GAC7B,IAAI,MAAM,eAAe,QAAQ,EAAE,IAAI,IAAI,EAAE,QAAQ,IAAI,GAAG,6BAA6B;GACzF,aAAa,GAAG;EAClB,CAAC;CAEL,SAAS,KAAK;EACZ,IAAI,MAAM,eAAe,QAAQ,EAAE,IAAI,IAAI,EAAE,QAAQ,IAAI,GAAG,6BAA6B;EACzF,aAAa,GAAG;CAClB;CAEA,OAAO;AACT"}
|
package/dist/native.d.ts
CHANGED
package/dist/native.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","names":[],"sources":["../src/server/native-mount.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"native.d.ts","names":[],"sources":["../src/server/native-mount.ts"],"mappings":";;KAgBY,iBAAiB,KAAK,iBAAiB,KAAK,0BAA0B;UAEjE;;EAEf;;EAGA,UAAU,KAAK;;EAGf;;;;;;;;;;;;;;;;;;;;;;;;iBAwDc,mBAAmB,SAAS,oBAAoB,SAAS;;;;;iBA2BzD;;;;;iBAsCA,oBAAoB,KAAK,iBAAiB,KAAK"}
|
package/dist/native.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as dispatchNativeMount, r as mountNativeHandler, t as clearNativeMounts } from "./native-mount-
|
|
1
|
+
import { n as dispatchNativeMount, r as mountNativeHandler, t as clearNativeMounts } from "./native-mount-DjYEnO4X.js";
|
|
2
2
|
export { clearNativeMounts, dispatchNativeMount, mountNativeHandler };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { t as emit } from "./events-CgoM3Fvu.js";
|
|
2
|
-
import {
|
|
3
|
-
import { n as log, t as generateReqId } from "./log-
|
|
2
|
+
import { r as getLogStore } from "./request-route-DcnZOOM4.js";
|
|
3
|
+
import { n as log, t as generateReqId } from "./log-B69HEBvg.js";
|
|
4
4
|
import fs from "node:fs";
|
|
5
|
-
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, ValueType, context, isSpanContextValid, metrics, propagation, trace } from "@opentelemetry/api";
|
|
6
5
|
import pino from "pino";
|
|
6
|
+
import { ROOT_CONTEXT, SpanKind, SpanStatusCode, ValueType, context, isSpanContextValid, metrics, propagation, trace } from "@opentelemetry/api";
|
|
7
7
|
import { createMatcher } from "@entwico/dash/match";
|
|
8
8
|
//#region src/lifecycle/lifecycle.ts
|
|
9
9
|
async function runStartup(boot, context) {
|
|
@@ -137,7 +137,9 @@ function createRequestInstrumentation(config) {
|
|
|
137
137
|
const record = {
|
|
138
138
|
logger: requestLogger,
|
|
139
139
|
url,
|
|
140
|
+
method,
|
|
140
141
|
route: void 0,
|
|
142
|
+
routeOverride: false,
|
|
141
143
|
actionName: isAction ? pathname.slice(10).replace(/\/$/, "") : void 0
|
|
142
144
|
};
|
|
143
145
|
let span;
|
|
@@ -406,4 +408,4 @@ async function preparePlatform(options) {
|
|
|
406
408
|
//#endregion
|
|
407
409
|
export { runShutdown as a, createRequestInstrumentation as i, shutdownTelemetry as n, runStartup as o, dumpEarlyLogs as r, preparePlatform as t };
|
|
408
410
|
|
|
409
|
-
//# sourceMappingURL=prepare-
|
|
411
|
+
//# sourceMappingURL=prepare-CXZsyAVk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-CXZsyAVk.js","names":["LIB_NAME"],"sources":["../src/lifecycle/lifecycle.ts","../src/observability/telemetry/metrics.ts","../src/observability/instrument.ts","../src/observability/log/construct.ts","../src/observability/telemetry/sdk.ts","../src/platform/env.ts","../src/platform/prepare.ts"],"sourcesContent":["import { emit } from './events.js';\nimport type { BootContext } from './types.js';\n\nexport interface BootModule {\n onStartup?: ((context: BootContext) => Promise<void> | void) | undefined;\n onShutdown?: ((context: BootContext) => Promise<void> | void) | undefined;\n}\n\nexport async function runStartup(boot: BootModule, context: BootContext): Promise<void> {\n await emit('beforeOnStartup', context);\n await boot.onStartup?.(context);\n await emit('afterOnStartup', context);\n}\n\nexport async function runShutdown(boot: BootModule, context: BootContext): Promise<void> {\n try {\n await emit('beforeOnShutdown', context);\n await boot.onShutdown?.(context);\n } finally {\n await emit('afterOnShutdown', context);\n }\n}\n","import { type Histogram, type UpDownCounter, ValueType, metrics } from '@opentelemetry/api';\n\nconst LIB_NAME = '@astroscope/node';\n\n// lazy initialization so instruments bind to the SDK meter provider\nlet httpRequestDuration: Histogram | null = null;\nlet httpActiveRequests: UpDownCounter | null = null;\nlet actionDuration: Histogram | null = null;\n\nfunction getHttpRequestDuration(): Histogram {\n return (httpRequestDuration ??= metrics.getMeter(LIB_NAME).createHistogram('http.server.request.duration', {\n description: 'Duration of HTTP server requests',\n unit: 's',\n valueType: ValueType.DOUBLE,\n }));\n}\n\nfunction getHttpActiveRequests(): UpDownCounter {\n return (httpActiveRequests ??= metrics.getMeter(LIB_NAME).createUpDownCounter('http.server.active_requests', {\n description: 'Number of active HTTP server requests',\n unit: '{request}',\n valueType: ValueType.INT,\n }));\n}\n\nfunction getActionDuration(): Histogram {\n return (actionDuration ??= metrics.getMeter(LIB_NAME).createHistogram('astro.action.duration', {\n description: 'Duration of Astro action executions',\n unit: 's',\n valueType: ValueType.DOUBLE,\n }));\n}\n\n/**\n * Record the start of an HTTP request. Returns a function to call when the\n * request ends. Route is unknown at the native-handler level, so active\n * requests carry only the method.\n */\nexport function recordHttpRequestStart(method: string): () => void {\n getHttpActiveRequests().add(1, { 'http.request.method': method });\n\n return () => {\n getHttpActiveRequests().add(-1, { 'http.request.method': method });\n };\n}\n\nexport function recordHttpRequestDuration(\n attributes: { method: string; route: string | undefined; status: number },\n durationMs: number,\n): void {\n getHttpRequestDuration().record(durationMs / 1000, {\n 'http.request.method': attributes.method,\n 'http.route': attributes.route ?? '',\n 'http.response.status_code': attributes.status,\n });\n}\n\nexport function recordActionDuration(attributes: { name: string; status: number }, durationMs: number): void {\n getActionDuration().record(durationMs / 1000, {\n 'astro.action.name': attributes.name,\n 'http.response.status_code': attributes.status,\n });\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { createMatcher } from '@entwico/dash/match';\nimport { ROOT_CONTEXT, SpanKind, SpanStatusCode, context, propagation, trace } from '@opentelemetry/api';\nimport type { Logger } from 'pino';\nimport type { ExcludePattern } from '../excludes/excludes.js';\nimport { generateReqId } from './log/index.js';\nimport { type RequestRecord, getLogStore } from './log/store.js';\nimport { recordActionDuration, recordHttpRequestDuration, recordHttpRequestStart } from './telemetry/metrics.js';\n\nconst LIB_NAME = '@astroscope/node';\nconst ACTIONS_PREFIX = '/_actions/';\nconst REQUEST_ID_PATTERN = /^[\\w.-]{1,64}$/;\n\nconst roundTime = (n: number) => Math.round(n * 100) / 100;\n\nexport interface RequestLoggingConfig {\n exclude: ExcludePattern[];\n extended: boolean;\n}\n\nexport interface RequestTelemetryConfig {\n exclude: ExcludePattern[];\n}\n\nexport interface RequestInstrumentationConfig {\n logging: RequestLoggingConfig | false;\n telemetry: RequestTelemetryConfig | false;\n}\n\nfunction getClientIp(req: IncomingMessage): string | undefined {\n const forwarded = req.headers['x-forwarded-for'];\n const first = Array.isArray(forwarded) ? forwarded[0] : forwarded;\n\n return (\n first?.split(',')[0]?.trim() ??\n (req.headers['x-real-ip'] as string | undefined) ??\n (req.headers['cf-connecting-ip'] as string | undefined)\n );\n}\n\nfunction resolveReqId(req: IncomingMessage): string {\n const incoming = req.headers['x-request-id'];\n const value = Array.isArray(incoming) ? incoming[0] : incoming;\n\n return value && REQUEST_ID_PATTERN.test(value) ? value : generateReqId();\n}\n\nfunction chunkSize(chunk: unknown): number {\n if (chunk == null) return 0;\n if (ArrayBuffer.isView(chunk)) return chunk.byteLength;\n if (typeof chunk === 'string') return Buffer.byteLength(chunk);\n\n return 0;\n}\n\n/**\n * Wraps the native request/response with logging and telemetry: a request\n * logger in async context (real status, response size, aborted-vs-completed\n * on `finish`/`close`), a SERVER span with propagation extraction, and\n * request metrics. Both concerns honor their own exclude patterns; when both\n * are excluded the request passes through untouched.\n */\nexport function createRequestInstrumentation(config: RequestInstrumentationConfig) {\n const tracer = trace.getTracer(LIB_NAME);\n const store = getLogStore();\n const loggingExcluded = config.logging ? createMatcher(config.logging.exclude) : () => true;\n const telemetryExcluded = config.telemetry ? createMatcher(config.telemetry.exclude) : () => true;\n\n return (req: IncomingMessage, res: ServerResponse, inner: () => void): void => {\n const url = req.url ?? '';\n const queryIndex = url.indexOf('?');\n const pathname = queryIndex === -1 ? url : url.slice(0, queryIndex);\n const method = req.method ?? 'GET';\n\n const logging = config.logging && !loggingExcluded(pathname) ? config.logging : false;\n const telemetry = config.telemetry && !telemetryExcluded(pathname) ? config.telemetry : false;\n\n if (!logging && !telemetry) {\n inner();\n\n return;\n }\n\n const startTime = performance.now();\n const isAction = pathname.startsWith(ACTIONS_PREFIX);\n\n let requestLogger: Logger | undefined;\n\n if (logging && store.root) {\n const reqId = resolveReqId(req);\n const reqData: Record<string, unknown> = { method, url: pathname };\n\n // extended logging includes potentially sensitive data\n if (logging.extended) {\n reqData['query'] = queryIndex === -1 ? '' : url.slice(queryIndex + 1);\n reqData['headers'] = req.headers;\n reqData['remoteAddress'] = getClientIp(req) ?? req.socket.remoteAddress;\n }\n\n requestLogger = store.root.child({ reqId, req: reqData });\n\n res.setHeader('x-request-id', reqId);\n }\n\n const record: RequestRecord = {\n logger: requestLogger,\n url,\n method,\n route: undefined,\n routeOverride: false,\n actionName: isAction ? pathname.slice(ACTIONS_PREFIX.length).replace(/\\/$/, '') : undefined,\n };\n\n let span: ReturnType<typeof tracer.startSpan> | undefined;\n let firstByteSpan: ReturnType<typeof tracer.startSpan> | undefined;\n let endActiveRequest: (() => void) | undefined;\n\n if (telemetry) {\n const parentContext = propagation.extract(ROOT_CONTEXT, req.headers);\n const contentLength = req.headers['content-length'];\n const clientIp = getClientIp(req);\n const host = req.headers['host'];\n\n span = tracer.startSpan(\n isAction ? `ACTION ${record.actionName}` : method,\n {\n kind: SpanKind.SERVER,\n attributes: {\n 'http.request.method': method,\n 'url.path': pathname,\n 'url.query': queryIndex === -1 ? '' : url.slice(queryIndex + 1),\n 'url.scheme': 'http',\n 'user_agent.original': req.headers['user-agent'] ?? '',\n ...(host && { 'server.address': host }),\n ...(contentLength && { 'http.request.body.size': parseInt(contentLength) }),\n ...(clientIp && { 'client.address': clientIp }),\n },\n },\n parentContext,\n );\n\n firstByteSpan = tracer.startSpan('response:first-byte', undefined, trace.setSpan(parentContext, span));\n\n endActiveRequest = recordHttpRequestStart(method);\n }\n\n let responseSize = 0;\n let firstByteTime: number | undefined;\n\n const originalWrite = res.write.bind(res);\n const originalEnd = res.end.bind(res);\n\n const markFirstByte = (): void => {\n if (firstByteTime !== undefined) return;\n\n firstByteTime = performance.now();\n\n if (firstByteSpan) {\n firstByteSpan.setAttribute('http.response.status_code', res.statusCode);\n firstByteSpan.end();\n }\n };\n\n res.write = ((chunk: unknown, ...rest: unknown[]) => {\n markFirstByte();\n responseSize += chunkSize(chunk);\n\n return (originalWrite as (...args: unknown[]) => boolean)(chunk, ...rest);\n }) as typeof res.write;\n\n res.end = ((chunk: unknown, ...rest: unknown[]) => {\n markFirstByte();\n responseSize += chunkSize(chunk);\n\n return (originalEnd as (...args: unknown[]) => ServerResponse)(chunk, ...rest);\n }) as typeof res.end;\n\n let finalized = false;\n\n const finalize = (aborted: boolean): void => {\n if (finalized) return;\n\n finalized = true;\n\n const status = res.statusCode;\n const responseTime = performance.now() - startTime;\n const ttfb = roundTime((firstByteTime ?? performance.now()) - startTime);\n\n if (requestLogger) {\n const level = status >= 500 ? 'error' : status >= 400 ? 'warn' : 'info';\n\n requestLogger[level](\n {\n res: { statusCode: status },\n responseTime: roundTime(responseTime),\n ttfb,\n responseSize,\n ...(record.route && { route: record.route }),\n ...(aborted && { aborted: true }),\n },\n aborted ? 'request aborted' : 'request completed',\n );\n }\n\n if (firstByteSpan && firstByteTime === undefined) {\n firstByteSpan.setStatus({ code: SpanStatusCode.ERROR, message: 'request aborted' });\n firstByteSpan.end();\n }\n\n if (span) {\n span.setAttribute('http.response.status_code', status);\n span.setAttribute('http.response.body.size', responseSize);\n span.setAttribute('ttfb', ttfb);\n\n if (aborted || status >= 400) {\n span.setStatus({ code: SpanStatusCode.ERROR, message: aborted ? 'request aborted' : `HTTP ${status}` });\n } else {\n span.setStatus({ code: SpanStatusCode.OK });\n }\n\n span.end();\n }\n\n if (telemetry) {\n endActiveRequest?.();\n recordHttpRequestDuration({ method, route: record.route, status }, responseTime);\n\n if (record.actionName) {\n recordActionDuration({ name: record.actionName, status }, responseTime);\n }\n }\n };\n\n res.once('finish', () => finalize(false));\n res.once('close', () => finalize(!res.writableFinished));\n\n const run = (): void => store.requestStorage.run(record, inner);\n\n if (span) {\n context.with(trace.setSpan(context.active(), span), run);\n } else {\n run();\n }\n };\n}\n","import { isSpanContextValid, trace } from '@opentelemetry/api';\nimport pino, { type Bindings, type Logger, type LoggerOptions } from 'pino';\nimport { getLogStore } from './store.js';\n\n/**\n * Contract of the `src/log.ts` entry seam: pino logger options, or a factory\n * producing them. Never a logger instance — the platform constructs the\n * logger itself (after instrumentation, so trace correlation works).\n */\nexport type LoggerOptionsFactory = LoggerOptions | ((ctx: { dev: boolean }) => LoggerOptions | Promise<LoggerOptions>);\n\n/**\n * Compose the user mixin (if any) with platform trace correlation: when a\n * span is active, every entry carries `trace_id` / `span_id` / `trace_flags`.\n */\nfunction composeMixin(userMixin: LoggerOptions['mixin']): NonNullable<LoggerOptions['mixin']> {\n return (mergeObject, level, logger) => {\n const user = userMixin ? userMixin(mergeObject, level, logger) : {};\n const spanContext = trace.getActiveSpan()?.spanContext();\n\n if (!spanContext || !isSpanContextValid(spanContext)) return user;\n\n return {\n ...user,\n trace_id: spanContext.traceId,\n span_id: spanContext.spanId,\n trace_flags: `0${spanContext.traceFlags.toString(16)}`,\n };\n };\n}\n\n/**\n * Construct the root logger from the app's options seam and replay any logs\n * buffered before construction (original timestamps kept as `bufferedTime`).\n * In dev this runs once per generation; the buffer only exists the first time.\n */\nexport async function constructRootLogger(\n factory: LoggerOptionsFactory | undefined,\n ctx: { dev: boolean },\n): Promise<Logger> {\n const store = getLogStore();\n const options = (typeof factory === 'function' ? await factory(ctx) : factory) ?? {};\n const root = pino({ level: 'info', ...options, mixin: composeMixin(options.mixin) });\n\n store.root = root;\n\n for (const entry of store.buffer.splice(0)) {\n const bindings = entry.bindings.length ? (Object.assign({}, ...entry.bindings) as Bindings) : {};\n const target = root.child({ ...bindings, bufferedTime: new Date(entry.time).toISOString() });\n\n (target[entry.level] as (...args: unknown[]) => void)(...entry.args);\n }\n\n if (store.dropped > 0) {\n root.warn({ dropped: store.dropped }, 'early log buffer overflowed, entries dropped');\n store.dropped = 0;\n }\n\n return root;\n}\n\n/**\n * Failure path for startups that die before the logger exists: dump the\n * buffered entries to the console so no phase is silent.\n */\nexport function dumpEarlyLogs(): void {\n const store = getLogStore();\n\n if (store.root) return;\n\n for (const entry of store.buffer.splice(0)) {\n const bindings = entry.bindings.length ? Object.assign({}, ...entry.bindings) : undefined;\n\n console.error(\n new Date(entry.time).toISOString(),\n entry.level.toUpperCase(),\n ...(bindings ? [bindings] : []),\n ...entry.args,\n );\n }\n\n if (store.dropped > 0) {\n console.error(`(${store.dropped} early log entries dropped)`);\n store.dropped = 0;\n }\n}\n","import { log } from '../log/index.js';\n\n/**\n * Platform-owned telemetry bundle: NodeSDK with undici (fetch) and node\n * runtime instrumentation, host metrics, and a Prometheus reader. Trace\n * exporters are driven by standard `OTEL_*` env vars; without any of them\n * traces stay off (no failing localhost OTLP exports).\n *\n * Guarded per process (dev restarts are in-process; a re-created NodeSDK\n * would double-register instrumentations and leak the Prometheus port).\n */\n\nconst TELEMETRY_KEY = Symbol.for('@astroscope/node/telemetry');\n\ninterface TelemetryHandle {\n shutdown: () => Promise<void>;\n}\n\nexport interface TelemetrySdkOptions {\n prometheus: { host?: string | undefined; port?: number | undefined } | false;\n}\n\nfunction getHandle(): TelemetryHandle | undefined {\n return (globalThis as Record<symbol, unknown>)[TELEMETRY_KEY] as TelemetryHandle | undefined;\n}\n\nfunction defaultEnv(key: string, value: string): void {\n if (!process.env[key]) process.env[key] = value;\n}\n\nexport async function startTelemetry(options: TelemetrySdkOptions): Promise<void> {\n const g = globalThis as Record<symbol, unknown>;\n\n if (g[TELEMETRY_KEY]) return;\n\n if (process.env['OTEL_SDK_DISABLED'] === 'true') {\n log.debug('telemetry disabled via OTEL_SDK_DISABLED');\n\n return;\n }\n\n // without an explicitly configured exporter target, exporting traces to the\n // default localhost OTLP endpoint would fail on every flush\n if (!process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] && !process.env['OTEL_EXPORTER_OTLP_TRACES_ENDPOINT']) {\n defaultEnv('OTEL_TRACES_EXPORTER', 'none');\n }\n\n defaultEnv('OTEL_METRICS_EXPORTER', 'none');\n defaultEnv('OTEL_LOGS_EXPORTER', 'none');\n\n const [\n { NodeSDK },\n { UndiciInstrumentation },\n { RuntimeNodeInstrumentation },\n { PrometheusExporter },\n { HostMetrics },\n ] = await Promise.all([\n import('@opentelemetry/sdk-node'),\n import('@opentelemetry/instrumentation-undici'),\n import('@opentelemetry/instrumentation-runtime-node'),\n import('@opentelemetry/exporter-prometheus'),\n import('@opentelemetry/host-metrics'),\n ]);\n\n const prometheus = options.prometheus\n ? {\n host: process.env['OTEL_EXPORTER_PROMETHEUS_HOST'] ?? options.prometheus.host ?? '0.0.0.0',\n port: process.env['OTEL_EXPORTER_PROMETHEUS_PORT']\n ? Number(process.env['OTEL_EXPORTER_PROMETHEUS_PORT'])\n : (options.prometheus.port ?? 9464),\n }\n : false;\n\n const sdk = new NodeSDK({\n instrumentations: [new UndiciInstrumentation(), new RuntimeNodeInstrumentation()],\n ...(prometheus && { metricReaders: [new PrometheusExporter(prometheus)] }),\n });\n\n sdk.start();\n\n const hostMetrics = new HostMetrics();\n\n hostMetrics.start();\n\n g[TELEMETRY_KEY] = {\n shutdown: () => sdk.shutdown(),\n } satisfies TelemetryHandle;\n\n if (prometheus) {\n log.debug({ host: prometheus.host, port: prometheus.port }, 'prometheus metrics listening');\n }\n}\n\n/**\n * Flush and shut the SDK down. Prod-only (dev keeps the SDK for the process\n * lifetime across generations).\n */\nexport async function shutdownTelemetry(): Promise<void> {\n const handle = getHandle();\n\n if (!handle) return;\n\n delete (globalThis as Record<symbol, unknown>)[TELEMETRY_KEY];\n\n await handle.shutdown();\n}\n","import fs from 'node:fs';\nimport { log } from '../observability/log/index.js';\n\n/**\n * Platform env loading (position −1, before the config seam):\n * `CONFIG_PATH` → `./.env` → none. Existing process env vars win\n */\nexport function loadEnvFiles(): void {\n const configPath = process.env['CONFIG_PATH'];\n\n if (configPath) {\n process.loadEnvFile(configPath);\n\n log.debug({ path: configPath }, 'loaded env file from CONFIG_PATH');\n\n return;\n }\n\n if (fs.existsSync('.env')) {\n process.loadEnvFile('.env');\n log.debug({ path: '.env' }, 'loaded env file');\n\n return;\n }\n\n log.debug('no env file loaded');\n}\n","import { type LoggerOptionsFactory, constructRootLogger } from '../observability/log/construct.js';\nimport { type TelemetrySdkOptions, startTelemetry } from '../observability/telemetry/sdk.js';\nimport { loadEnvFiles } from './env.js';\n\nconst INSTRUMENTATION_KEY = Symbol.for('@astroscope/node/instrumentation');\n\nexport interface InstrumentationContext {\n dev: boolean;\n}\n\ninterface InstrumentationSeam {\n register?: ((ctx: InstrumentationContext) => void | Promise<void>) | undefined;\n}\n\ninterface LogSeam {\n default?: LoggerOptionsFactory | undefined;\n}\n\nexport interface PlatformSeams {\n /** `src/config.ts` — validation runs at import; a throw fails the startup */\n config?: (() => Promise<unknown>) | undefined;\n /** `src/instrumentation.ts` — extra instrumentation, once per process */\n instrumentation?: (() => Promise<InstrumentationSeam>) | undefined;\n /** `src/log.ts` — pino logger options (or a factory), never an instance */\n log?: (() => Promise<LogSeam>) | undefined;\n}\n\nexport interface PreparePlatformOptions {\n dev: boolean;\n telemetry: TelemetrySdkOptions | false;\n seams: PlatformSeams;\n}\n\n/**\n * The platform sequence in front of the boot lifecycle:\n * env → config → instrumentation (platform SDK + `register`, once per\n * process) → logger construction (after instrumentation, so entries carry\n * trace correlation). Prod runs it once in `startServer()`; dev re-runs it\n * per generation with the once-per-process parts guarded.\n */\nexport async function preparePlatform(options: PreparePlatformOptions): Promise<void> {\n loadEnvFiles();\n\n await options.seams.config?.();\n\n const g = globalThis as Record<symbol, unknown>;\n\n if (!g[INSTRUMENTATION_KEY]) {\n g[INSTRUMENTATION_KEY] = true;\n\n if (options.telemetry) {\n await startTelemetry(options.telemetry);\n }\n\n const instrumentation = await options.seams.instrumentation?.();\n\n await instrumentation?.register?.({ dev: options.dev });\n }\n\n const logSeam = await options.seams.log?.();\n\n await constructRootLogger(logSeam?.default, { dev: options.dev });\n}\n"],"mappings":"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"}
|