@timber-js/app 0.2.0-alpha.212 → 0.2.0-alpha.213

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.
Files changed (92) hide show
  1. package/dist/_chunks/{actions-CCdnVtWm.js → actions-CEootpB1.js} +42 -7
  2. package/dist/_chunks/{actions-CCdnVtWm.js.map → actions-CEootpB1.js.map} +1 -1
  3. package/dist/_chunks/{error-boundary-DsNScGRM.js → error-boundary-9g_Lb2na.js} +3 -3
  4. package/dist/_chunks/{error-boundary-DsNScGRM.js.map → error-boundary-9g_Lb2na.js.map} +1 -1
  5. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  6. package/dist/client/browser-entry/action-queue.d.ts +1 -0
  7. package/dist/client/browser-entry/action-queue.d.ts.map +1 -1
  8. package/dist/client/browser-entry/form-state.d.ts +22 -0
  9. package/dist/client/browser-entry/form-state.d.ts.map +1 -0
  10. package/dist/client/browser-entry/hydrate.d.ts +9 -1
  11. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  12. package/dist/client/browser-entry/index.d.ts +2 -0
  13. package/dist/client/browser-entry/index.d.ts.map +1 -1
  14. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  15. package/dist/client/error-boundary.js +1 -1
  16. package/dist/client/index.d.ts +1 -0
  17. package/dist/client/index.d.ts.map +1 -1
  18. package/dist/client/index.js +90 -2
  19. package/dist/client/index.js.map +1 -1
  20. package/dist/client/internal.js +8 -7
  21. package/dist/client/internal.js.map +1 -1
  22. package/dist/client/navigation-transition.d.ts +11 -2
  23. package/dist/client/navigation-transition.d.ts.map +1 -1
  24. package/dist/client/router-effects.d.ts +7 -3
  25. package/dist/client/router-effects.d.ts.map +1 -1
  26. package/dist/client/router-pipeline.d.ts +3 -1
  27. package/dist/client/router-pipeline.d.ts.map +1 -1
  28. package/dist/client/router-types.d.ts +12 -1
  29. package/dist/client/router-types.d.ts.map +1 -1
  30. package/dist/client/router.d.ts.map +1 -1
  31. package/dist/client/use-form-field.d.ts +39 -0
  32. package/dist/client/use-form-field.d.ts.map +1 -0
  33. package/dist/config-types.d.ts +2 -1
  34. package/dist/config-types.d.ts.map +1 -1
  35. package/dist/index.js.map +1 -1
  36. package/dist/server/action-client.d.ts +11 -2
  37. package/dist/server/action-client.d.ts.map +1 -1
  38. package/dist/server/flight-scripts.d.ts +9 -0
  39. package/dist/server/flight-scripts.d.ts.map +1 -1
  40. package/dist/server/form-data.d.ts +13 -4
  41. package/dist/server/form-data.d.ts.map +1 -1
  42. package/dist/server/form-state-flight.d.ts +32 -0
  43. package/dist/server/form-state-flight.d.ts.map +1 -0
  44. package/dist/server/index.js +37 -23
  45. package/dist/server/index.js.map +1 -1
  46. package/dist/server/internal.js +1 -1
  47. package/dist/server/rsc-entry/action-dispatcher.d.ts.map +1 -1
  48. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  49. package/dist/server/rsc-entry/render-route.d.ts +2 -0
  50. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  51. package/dist/server/rsc-entry/ssr-renderer.d.ts +6 -0
  52. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  53. package/dist/server/ssr-bridge-types.d.ts +7 -5
  54. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  55. package/dist/server/ssr-entry.d.ts.map +1 -1
  56. package/dist/server/ssr-form-state.d.ts +30 -0
  57. package/dist/server/ssr-form-state.d.ts.map +1 -0
  58. package/dist/shared/form-state-flight.d.ts +36 -0
  59. package/dist/shared/form-state-flight.d.ts.map +1 -0
  60. package/docs/api/31-api-client.mdx +22 -0
  61. package/docs/api/34-api-config.mdx +1 -1
  62. package/docs/learn/08-forms-and-actions.mdx +109 -22
  63. package/package.json +1 -1
  64. package/src/client/browser-entry/action-dispatch.ts +34 -10
  65. package/src/client/browser-entry/action-queue.ts +1 -1
  66. package/src/client/browser-entry/form-state.ts +48 -0
  67. package/src/client/browser-entry/hydrate.ts +9 -18
  68. package/src/client/browser-entry/index.ts +25 -7
  69. package/src/client/browser-entry/router-init.ts +3 -2
  70. package/src/client/index.ts +1 -0
  71. package/src/client/navigation-transition.ts +13 -2
  72. package/src/client/router-effects.ts +8 -4
  73. package/src/client/router-pipeline.ts +7 -3
  74. package/src/client/router-types.ts +12 -1
  75. package/src/client/router.ts +16 -3
  76. package/src/client/use-form-field.ts +132 -0
  77. package/src/config-types.ts +2 -1
  78. package/src/server/action-client.ts +68 -53
  79. package/src/server/flight-scripts.ts +13 -0
  80. package/src/server/form-data.ts +62 -10
  81. package/src/server/form-state-flight.ts +67 -0
  82. package/src/server/rsc-entry/action-dispatcher.ts +3 -0
  83. package/src/server/rsc-entry/index.ts +1 -0
  84. package/src/server/rsc-entry/render-route.ts +16 -0
  85. package/src/server/rsc-entry/ssr-renderer.ts +12 -14
  86. package/src/server/ssr-bridge-types.ts +7 -6
  87. package/src/server/ssr-entry.ts +16 -3
  88. package/src/server/ssr-form-state.ts +58 -0
  89. package/src/shared/form-state-flight.ts +74 -0
  90. package/dist/server/form-state-embed.d.ts +0 -32
  91. package/dist/server/form-state-embed.d.ts.map +0 -1
  92. package/src/server/form-state-embed.ts +0 -63
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["intToChar"],"sources":["../src/plugins/content.ts","../src/plugins/entries.ts","../src/plugins/mdx.ts","../src/routing/manifest-codegen.ts","../src/plugins/routing.ts","../src/plugins/shims.ts","../src/fonts/paths.ts","../src/fonts/google.ts","../src/fonts/css.ts","../src/fonts/fallbacks.ts","../src/fonts/ast-walk.ts","../src/fonts/ast.ts","../src/fonts/local.ts","../src/fonts/virtual-modules.ts","../src/fonts/pipeline.ts","../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs","../../../node_modules/.pnpm/magic-string@1.4.1/node_modules/magic-string/dist/index.mjs","../src/fonts/transform.ts","../src/fonts/dev-middleware.ts","../src/fonts/bundle.ts","../src/plugins/fonts.ts","../src/server/flight-scripts.ts","../src/plugins/static-build.ts","../src/plugins/build-manifest.ts","../src/dev-tools/logs.ts","../src/dev-tools/browser-logs.ts","../src/plugins/react-prod.ts","../src/plugins/react-resolve.ts","../src/plugins/chunks.ts","../src/plugins/client-chunks.ts","../src/plugins/server-bundle.ts","../src/plugins/callsite-ast.ts","../src/plugins/cache.ts","../src/plugins/request-dep/analysis.ts","../src/plugins/request-dep/origin.ts","../src/plugins/request-dep/index.ts","../src/plugins/callsite-jsx.ts","../src/plugins/prebuilt-options-analysis.ts","../src/plugins/prebuilt-capture.ts","../src/plugins/prebuilt.ts","../src/plugins/prerender-sugar.ts","../src/plugins/cloudflare-wasm.ts","../src/plugins/rsc-assets-manifest.ts","../src/plugins/post-build.ts","../src/plugins/build-report.ts","../src/server/action-encryption.ts","../src/dev-tools/holding-server.ts","../src/server/port-resolution.ts","../src/index.ts"],"sourcesContent":["/**\n * timber-content — Vite sub-plugin for content collections.\n *\n * Wraps @content-collections/vite to provide content collection support.\n * Activates only when a content-collections.ts config file exists at the\n * project root.\n *\n * Design doc: 20-content-collections.md §\"Content Collections\"\n */\n\nimport type { Plugin, PluginOption } from 'vite';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PluginContext } from '../plugin-context.ts';\n\nconst CONFIG_FILE_NAMES = [\n 'content-collections.ts',\n 'content-collections.js',\n 'content-collections.mts',\n 'content-collections.mjs',\n];\n\n/**\n * Find the content-collections config file at the project root.\n * Returns the filename (not full path) if found, otherwise undefined.\n */\nfunction findConfigFile(root: string): string | undefined {\n for (const name of CONFIG_FILE_NAMES) {\n if (existsSync(join(root, name))) return name;\n }\n return undefined;\n}\n\n/** The name @content-collections/vite gives its plugin. */\nconst CONTENT_COLLECTIONS_PLUGIN_NAME = 'content-collections';\n\n/**\n * Whether the user's own config already registers @content-collections/vite.\n * Walks nested arrays and awaits promised plugins, the same PluginOption\n * shapes Vite flattens (and has already resolved by the time config hooks\n * run, so awaiting here costs nothing).\n */\nasync function registersContentCollections(plugins: PluginOption[] | undefined): Promise<boolean> {\n for (const option of plugins ?? []) {\n const plugin = await option;\n if (Array.isArray(plugin)) {\n if (await registersContentCollections(plugin)) return true;\n } else if (plugin && 'name' in plugin && plugin.name === CONTENT_COLLECTIONS_PLUGIN_NAME) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Create the timber-content Vite plugin.\n *\n * Delegates all content scanning, validation, code generation, and file watching\n * to @content-collections/vite. This plugin only handles detection and activation.\n */\nexport function timberContent(ctx: PluginContext): Plugin {\n let innerPlugin: Plugin | null = null;\n\n async function activate(root: string): Promise<void> {\n if (innerPlugin !== null) return;\n\n const configFile = findConfigFile(root);\n if (!configFile) return;\n\n let createPlugin: ((options?: { configPath?: string }) => Plugin) | undefined;\n try {\n const mod = await import('@content-collections/vite');\n createPlugin = (mod.default ?? mod) as typeof createPlugin;\n } catch {\n throw new Error(\n [\n '[timber] Content collections are enabled but @content-collections/vite is not installed.',\n '',\n 'Install content-collections:',\n ' pnpm add -D @content-collections/core @content-collections/vite',\n '',\n 'For MDX content, also install:',\n ' pnpm add -D @content-collections/mdx',\n '',\n 'Content collections are activated because a content-collections.ts file exists.',\n ].join('\\n')\n );\n }\n\n if (createPlugin) {\n innerPlugin = createPlugin({ configPath: configFile });\n }\n }\n\n return {\n name: 'timber-content',\n\n async config(config, env) {\n // Two registrations start two builders and two watchers that race on\n // the same cache (\"Failed to parse the cache mapping\"). The user's\n // own registration, with its options, wins.\n if (await registersContentCollections(config.plugins)) return;\n const root = config.root ?? ctx.root;\n ctx.timer.start('content-activate');\n await activate(root);\n ctx.timer.end('content-activate');\n if (!innerPlugin) return;\n if (typeof innerPlugin.config === 'function') {\n return innerPlugin.config.call(this, config, env);\n }\n },\n\n async configResolved(config) {\n if (!innerPlugin) return;\n if (typeof innerPlugin.configResolved === 'function') {\n await (innerPlugin.configResolved as (...args: unknown[]) => unknown).call(this, config);\n }\n },\n\n async buildStart(options) {\n if (!innerPlugin) return;\n if (typeof innerPlugin.buildStart === 'function') {\n await (innerPlugin.buildStart as (...args: unknown[]) => unknown).call(this, options);\n }\n },\n\n async resolveId(source: string, importer: string | undefined, options: unknown) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.resolveId === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.resolveId as any).call(this, source, importer, options);\n }\n return null;\n },\n\n async load(id: string) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.load === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.load as any).call(this, id);\n }\n return null;\n },\n\n async transform(code: string, id: string) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.transform === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.transform as any).call(this, code, id);\n }\n return null;\n },\n\n async configureServer(server) {\n // The analyze crawl child must not start content-collections'\n // file watcher — it outlives server.close() and holds the\n // process open (the child relies on process.exit to clean up).\n if (process.env.TIMBER_ANALYZE === '1') return;\n if (!innerPlugin) return;\n if (typeof innerPlugin.configureServer === 'function') {\n await (innerPlugin.configureServer as (...args: unknown[]) => unknown).call(this, server);\n }\n },\n };\n}\n","/**\n * timber-entries — Vite sub-plugin for entry virtual module resolution.\n *\n * Resolves virtual:timber-rsc-entry, virtual:timber-ssr-entry,\n * virtual:timber-browser-entry to real TypeScript files, and generates\n * virtual:timber-config as serialized runtime config.\n *\n * Entry modules are real .ts files — NOT codegen strings. The only\n * generated code is virtual:timber-config (serialized runtime config).\n *\n * Design docs: 18-build-system.md §\"Entry Generation\", §\"Virtual Modules\"\n */\n\nimport type { Plugin } from 'vite';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { existsSync } from 'node:fs';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { resolveRenderTimeoutMs } from '../server/render-timeout.ts';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// In workspace dev, __dirname is src/plugins/ and src/ is the parent.\n// In published package, entries.ts is bundled into dist/index.js so\n// __dirname is dist/ and src/ is a sibling directory.\nconst SRC_DIR = existsSync(resolve(__dirname, '..', 'server', 'rsc-entry', 'index.ts'))\n ? resolve(__dirname, '..')\n : resolve(__dirname, '..', 'src');\n\n// ─── Virtual Module IDs ──────────────────────────────────────────────────\n\nconst VIRTUAL_IDS = {\n rscEntry: 'virtual:timber-rsc-entry',\n ssrEntry: 'virtual:timber-ssr-entry',\n browserEntry: 'virtual:timber-browser-entry',\n config: 'virtual:timber-config',\n instrumentation: 'virtual:timber-instrumentation',\n cacheHandler: 'virtual:timber-cache-handler',\n} as const;\n\n/**\n * Map from virtual module IDs to their resolved file paths.\n *\n * These point to .ts source files that Vite transpiles at runtime.\n * They import virtual modules (virtual:timber-config, etc.) so they\n * cannot be pre-compiled — they must be processed by Vite's pipeline\n * with timber's plugin active. The .ts files are included in the\n * published package via the `files` field.\n */\nconst ENTRY_FILE_MAP: Record<string, string> = {\n [VIRTUAL_IDS.rscEntry]: resolve(SRC_DIR, 'server', 'rsc-entry', 'index.ts'),\n [VIRTUAL_IDS.ssrEntry]: resolve(SRC_DIR, 'server', 'ssr-entry.ts'),\n [VIRTUAL_IDS.browserEntry]: resolve(SRC_DIR, 'client', 'browser-entry', 'index.ts'),\n};\n\n/**\n * The real file behind virtual:timber-browser-entry. The client dep\n * optimizer scans it explicitly once timber sets optimizeDeps.entries\n * (see plugins/client-dep-entries.ts).\n */\nexport const BROWSER_ENTRY_FILE = ENTRY_FILE_MAP[VIRTUAL_IDS.browserEntry];\n\n/** The \\0-prefixed resolved ID for virtual:timber-config */\nconst RESOLVED_CONFIG_ID = `\\0${VIRTUAL_IDS.config}`;\n\n/** The \\0-prefixed resolved ID for virtual:timber-instrumentation */\nconst RESOLVED_INSTRUMENTATION_ID = `\\0${VIRTUAL_IDS.instrumentation}`;\n\n/** The \\0-prefixed resolved ID for virtual:timber-cache-handler */\nconst RESOLVED_CACHE_HANDLER_ID = `\\0${VIRTUAL_IDS.cacheHandler}`;\n\n/**\n * Strip the \\0 prefix from a module ID.\n *\n * The RSC plugin generates browser entry imports using already-resolved\n * \\0-prefixed IDs. Vite's import-analysis cannot resolve these.\n * See 18-build-system.md §\"Resolution Quirks\".\n */\nfunction stripNullPrefix(id: string): string {\n return id.startsWith('\\0') ? id.slice(1) : id;\n}\n\n/**\n * Strip a root directory prefix from a module ID.\n *\n * Vite prefixes virtual module IDs with the project root when resolving\n * SSR build entries. We need to handle both `virtual:timber-rsc-entry`\n * and `<root>/virtual:timber-rsc-entry`.\n * See 18-build-system.md §\"Resolution Quirks\".\n */\nfunction stripRootPrefix(id: string, root: string): string {\n if (id.startsWith(root)) {\n // Remove root + path separator\n const stripped = id.slice(root.length);\n // Handle both /virtual:... and \\virtual:... (Windows)\n if (stripped.startsWith('/') || stripped.startsWith('\\\\')) {\n return stripped.slice(1);\n }\n return stripped;\n }\n return id;\n}\n\n/**\n * Generate the virtual:timber-config module source.\n *\n * Serializes output mode and feature flags for runtime consumption.\n */\n/**\n * Extract the JSON-serializable subset of `forms` config.\n *\n * Drops function-valued `stripSensitiveFields` with a build-time warning —\n * functions cannot cross the JSON boundary to the runtime, so users must\n * configure function predicates per-action via `createActionClient` instead.\n */\nfunction serializeFormsConfig(\n forms: { stripSensitiveFields?: unknown } | undefined\n): { stripSensitiveFields?: boolean | readonly string[] } | undefined {\n if (!forms) return undefined;\n const opt = forms.stripSensitiveFields;\n if (opt === undefined) return {};\n if (typeof opt === 'boolean') return { stripSensitiveFields: opt };\n if (Array.isArray(opt)) {\n // Coerce to a string array and drop any non-string entries.\n const names = opt.filter((v): v is string => typeof v === 'string');\n return { stripSensitiveFields: names };\n }\n if (typeof opt === 'function') {\n console.warn(\n '[timber] forms.stripSensitiveFields was set to a function in timber.config.ts — ' +\n 'this is not supported at the global level (functions cannot be serialized ' +\n 'into the runtime config). Use a per-action override via ' +\n '`createActionClient({ stripSensitiveFields: (name) => ... })` instead. ' +\n 'The built-in deny-list will be used globally.'\n );\n return {};\n }\n return {};\n}\n\nfunction generateConfigModule(ctx: PluginContext): string {\n const runtimeConfig = {\n output: ctx.config.output ?? 'server',\n csrf: ctx.config.csrf ?? true,\n allowedOrigins: ctx.config.allowedOrigins,\n clientJavascript: ctx.clientJavascript,\n // Vite's resolved `base` — the deployment path prefix. The client needs\n // it to address pre-generated RSC payloads in static mode, which live\n // below the base like every other emitted file (TIM-1261).\n base: ctx.base,\n dev: ctx.dev ?? false,\n slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,\n slowRequestMs: ctx.config.slowRequestMs ?? 3000,\n topLoader: ctx.config.topLoader,\n debug: ctx.config.debug ?? false,\n serverTiming: ctx.config.serverTiming,\n renderTimeoutMs: resolveRenderTimeoutMs(ctx.config.renderTimeoutMs),\n // Auto-generated sitemap config — opt-in via timber.config.ts.\n // See design/16-metadata.md §\"Auto-generated Sitemap\"\n sitemap: ctx.config.sitemap,\n // Forms config — only the serializable subset. `stripSensitiveFields`\n // accepts boolean | string[] at the global level. Functions must be\n // configured per-action via `createActionClient({ stripSensitiveFields })`\n // because JSON.stringify would silently drop them here. See TIM-816.\n forms: serializeFormsConfig(ctx.config.forms),\n // Per-build deployment ID for version skew detection (TIM-446).\n // Null in dev mode — HMR handles code updates without full reloads.\n deploymentId: ctx.deploymentId ?? null,\n clientSegmentCache: ctx.config.clientSegmentCache ?? false,\n cache: {\n strictKeyDiscipline: ctx.config.cache?.strictKeyDiscipline ?? false,\n },\n // Browser log forwarding threshold — used by buildClientScripts to\n // decide whether /@vite/client is needed when clientJavascript is\n // disabled. See TIM-1152.\n devBrowserLogs: ctx.config.devBrowserLogs,\n // Note: project root is NOT included here — it was leaking server\n // filesystem paths to client bundles (TIM-787). Dev error pages get\n // the root through the dev server, not the runtime config.\n };\n\n return [\n '// Auto-generated runtime config — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `const config = ${JSON.stringify(runtimeConfig, null, 2)};`,\n '',\n 'export default config;',\n ].join('\\n');\n}\n\n/**\n * Detect a user convention file at both root and src/.\n *\n * Root takes precedence over src/, extension priority: .ts > .js > .mjs.\n * Used for instrumentation.ts, timber.cache.ts, and similar file conventions.\n */\nexport function detectConventionFile(root: string, basename: string): string | null {\n const extensions = ['.ts', '.js', '.mjs'];\n const dirs = [root, resolve(root, 'src')];\n for (const dir of dirs) {\n for (const ext of extensions) {\n const candidate = resolve(dir, `${basename}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n }\n return null;\n}\n\nexport function detectInstrumentationFile(root: string): string | null {\n return detectConventionFile(root, 'instrumentation');\n}\n\n/**\n * Detect the user's timber.cache file.\n *\n * This file holds runtime cache instances (cacheHandler, cdnPurge)\n * that cannot be JSON-serialized. Separating them from timber.config.ts\n * prevents the RSC build from pulling build-time deps (adapters, MDX,\n * rollup) into the runtime bundle. See TIM-1211.\n */\nexport function detectCacheFile(root: string): string | null {\n return detectConventionFile(root, 'timber.cache');\n}\n\n/**\n * Generate the virtual:timber-instrumentation module source.\n *\n * When the user's instrumentation.ts exists, generates a module that\n * dynamically imports it. When it doesn't exist, generates a module\n * that returns null. The RSC entry calls this loader at startup time.\n *\n * See design/17-logging.md §\"instrumentation.ts — The Entry Point\"\n */\nexport function generateInstrumentationModule(instrumentationPath: string | null): string {\n if (instrumentationPath) {\n return [\n '// Auto-generated instrumentation loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `export default async function loadUserInstrumentation() {`,\n ` return import(${JSON.stringify(instrumentationPath)});`,\n `}`,\n ].join('\\n');\n }\n\n return [\n '// Auto-generated instrumentation loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '// No instrumentation.ts found at project root.',\n '',\n `export default async function loadUserInstrumentation() {`,\n ` return null;`,\n `}`,\n ].join('\\n');\n}\n\n/**\n * Generate the virtual:timber-cache-handler module source.\n *\n * When the user's timber.cache.ts exists, generates a module that\n * dynamically imports it and extracts cacheHandler and cdnPurge.\n * These are class instances (e.g. RedisCacheHandler) that cannot be\n * JSON-serialized into virtual:timber-config, so they must be loaded\n * at runtime via dynamic import.\n *\n * timber.cache.ts exports: default cacheHandler, named cdnPurge.\n *\n * See TIM-1211, TIM-599.\n */\nexport function generateCacheHandlerModule(cachePath: string | null): string {\n if (cachePath) {\n return [\n '// Auto-generated cache handler loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `export default async function loadCacheHandler() {`,\n ` const mod = await import(${JSON.stringify(cachePath)});`,\n ` return mod.default ?? null;`,\n `}`,\n '',\n `export async function loadCdnPurgeHandler() {`,\n ` const mod = await import(${JSON.stringify(cachePath)});`,\n ` return mod.cdnPurge ?? null;`,\n `}`,\n ].join('\\n');\n }\n\n return [\n '// Auto-generated cache handler loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '// No timber.cache.ts found.',\n '',\n `export default async function loadCacheHandler() {`,\n ` return null;`,\n `}`,\n '',\n `export async function loadCdnPurgeHandler() {`,\n ` return null;`,\n `}`,\n ].join('\\n');\n}\n\n/**\n * Create the timber-entries Vite plugin.\n *\n * Hooks: resolveId, load\n */\nexport function timberEntries(ctx: PluginContext): Plugin {\n return {\n name: 'timber-entries',\n\n /**\n * Resolve virtual entry and config module IDs.\n *\n * Handles:\n * - virtual:timber-rsc-entry → real file path\n * - virtual:timber-ssr-entry → real file path\n * - virtual:timber-browser-entry → real file path\n * - virtual:timber-config → \\0-prefixed virtual ID\n * - \\0 prefix stripping (RSC plugin re-imports)\n * - Root prefix stripping (SSR build entries)\n */\n resolveId(id: string) {\n // Step 1: Strip \\0 prefix if present\n let cleanId = stripNullPrefix(id);\n\n // Step 2: Strip root prefix if present\n cleanId = stripRootPrefix(cleanId, ctx.root);\n\n // Check entry file map (real files)\n if (cleanId in ENTRY_FILE_MAP) {\n return ENTRY_FILE_MAP[cleanId];\n }\n\n // Check config virtual module\n if (cleanId === VIRTUAL_IDS.config) {\n return RESOLVED_CONFIG_ID;\n }\n\n // Check instrumentation virtual module\n if (cleanId === VIRTUAL_IDS.instrumentation) {\n return RESOLVED_INSTRUMENTATION_ID;\n }\n\n // Check cache handler virtual module\n if (cleanId === VIRTUAL_IDS.cacheHandler) {\n return RESOLVED_CACHE_HANDLER_ID;\n }\n\n return null;\n },\n\n /**\n * Load virtual modules: virtual:timber-config and virtual:timber-instrumentation.\n *\n * Entry files (rsc/ssr/browser) are real TypeScript files that Vite\n * processes normally. Only config and instrumentation need generated code.\n */\n load(id: string) {\n if (id === RESOLVED_CONFIG_ID) {\n return generateConfigModule(ctx);\n }\n if (id === RESOLVED_INSTRUMENTATION_ID) {\n const instrumentationPath = detectInstrumentationFile(ctx.root);\n return generateInstrumentationModule(instrumentationPath);\n }\n if (id === RESOLVED_CACHE_HANDLER_ID) {\n const cachePath = detectCacheFile(ctx.root);\n return generateCacheHandlerModule(cachePath);\n }\n return null;\n },\n\n /**\n * Rename \"rsc-entry\" chunks in the client build to \"rsc-client-entry\".\n *\n * The RSC plugin creates client reference facades named after the RSC\n * entry (virtual:timber-rsc-entry), producing chunks like \"rsc-entry-XYZ.js\"\n * in the client output. This is confusing since those chunks contain client\n * components, not server code. Renaming clarifies their purpose.\n */\n // Note: chunk renaming (rsc-entry → rsc-client-entry) was previously done\n // in generateBundle by mutating the bundle object. Rolldown does not support\n // bundle mutation in generateBundle — assignments are silently ignored, which\n // causes the renamed file to never be emitted while code references are\n // updated, breaking client hydration. The rename is purely cosmetic and has\n // been removed. The chunks keep their original \"rsc-entry\" names.\n };\n}\n","/**\n * timber-mdx — Vite sub-plugin for MDX and Markdown rendering.\n *\n * Wires vite-plugin-satteri into the Vite pipeline when MDX is activated.\n * MDX is activated when pageExtensions includes 'mdx' or 'md', or\n * when a content/ directory exists at the project root.\n *\n * Satteri is a Rust-based Markdown/MDX compiler with a native Vite plugin:\n * - `.mdx` files compile to React components (ES modules with real import\n * statements, so @vitejs/plugin-rsc client-boundary detection works).\n * - `.md` files compile to modules exporting a rendered HTML string.\n * - Frontmatter (YAML/TOML) parses natively and is emitted as a\n * `frontmatter` named export — no remark plugins needed.\n * - GFM (tables, footnotes, strikethrough, task lists) is on by default.\n *\n * Extensibility is satteri's visitor-based plugin API (defineMdastPlugin /\n * defineHastPlugin), not unified — the AST lives on the Rust side, so\n * remark/rehype plugins cannot run. See design/20-content-collections.md.\n *\n * Design doc: 20-content-collections.md §\"The timber-mdx Plugin\"\n */\n\nimport type { Plugin } from 'vite';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport type { PluginContext } from '../plugin-context.ts';\n/** MDX/markdown extensions (dotted) — the canonical list for the compiler plugin. */\nconst MDX_EXTENSIONS = new Set(['.mdx', '.md']);\n\nconst MDX_EXTENSIONS_UNDOTTED = [...MDX_EXTENSIONS].map((ext) => ext.slice(1));\n\n/**\n * Check if mdx-components.tsx (or .ts, .jsx, .js) exists at the project root\n * or in src/. Root takes precedence, matching Next.js behavior.\n * Returns the absolute path if found, otherwise undefined.\n */\nexport function findMdxComponents(root: string): string | undefined {\n const candidates = [\n 'mdx-components.tsx',\n 'mdx-components.ts',\n 'mdx-components.jsx',\n 'mdx-components.js',\n ];\n const dirs = [root, join(root, 'src')];\n for (const dir of dirs) {\n for (const name of candidates) {\n const p = join(dir, name);\n if (existsSync(p)) return p;\n }\n }\n return undefined;\n}\n\n/**\n * Determine if MDX should be activated based on config and project structure.\n */\nfunction shouldActivate(ctx: PluginContext): boolean {\n // Explicit opt-out — the escape hatch for apps that register their own\n // MDX compiler (e.g. @mdx-js/rollup for the unified pipeline) in\n // vite.config.ts. Without this, a content/ directory would force\n // activation no matter what pageExtensions says.\n if (ctx.config.mdx === false) return false;\n\n const exts = ctx.config.pageExtensions;\n if (exts && exts.some((ext) => MDX_EXTENSIONS_UNDOTTED.includes(ext))) {\n return true;\n }\n\n if (existsSync(join(ctx.root, 'content'))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Try to dynamically import a module by name, resolving from the user's\n * project root rather than from `@timber-js/app`'s own location.\n *\n * Why this matters: pnpm only hoists declared (peer) dependencies into a\n * package's resolution scope. The MDX integration's optional companions\n * — `vite-plugin-satteri` and `satteri` — are installed as direct deps of\n * the consumer (e.g. `packages/website`), not `@timber-js/app`. A bare\n * `import('vite-plugin-satteri')` from inside this file resolves against\n * `packages/timber-app/node_modules` and silently fails with\n * `ERR_MODULE_NOT_FOUND` (TIM-840).\n *\n * Resolving relative to `projectRoot` (via `createRequire`) makes the\n * lookup walk the consumer's `node_modules` tree first, which is where\n * pnpm puts the user's deps.\n *\n * Returns the default export, the module itself, or undefined if the\n * module is not installed.\n */\nasync function tryImport(name: string, projectRoot: string): Promise<unknown | undefined> {\n try {\n // Anchor resolution at the consumer's package.json so we walk their\n // node_modules tree, not @timber-js/app's. createRequire().resolve()\n // returns an absolute file path that ESM dynamic import accepts when\n // wrapped as a file:// URL.\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(name);\n const mod = await import(pathToFileURL(resolved).href);\n return mod.default ?? mod;\n } catch {\n // Fall back to a bare import — covers the rare case where the package\n // lives next to @timber-js/app (e.g. monorepo with hoisted deps).\n try {\n const mod = await import(name);\n return mod.default ?? mod;\n } catch (e) {\n console.debug(\n `[timber] optional MDX dependency '${name}' not available:`,\n e instanceof Error ? e.message : e\n );\n return undefined;\n }\n }\n}\n\n/**\n * Create the timber-mdx Vite plugin.\n *\n * Uses the transform and resolveId hooks to delegate MDX compilation\n * to vite-plugin-satteri. The inner plugin is loaded lazily on first\n * activation.\n *\n * Hooks: buildStart (loads vite-plugin-satteri), resolveId, load, transform\n */\nexport function timberMdx(ctx: PluginContext): Plugin {\n let innerPlugin: Plugin | null = null;\n\n async function activate(): Promise<void> {\n if (innerPlugin !== null || !shouldActivate(ctx)) return;\n\n // Satteri compiles .md to an HTML string, not a component — a page.md\n // route would make the renderer invoke a string as a component and\n // TypeError at request time. Fail at startup instead. Imported .md\n // files work without listing 'md' in pageExtensions.\n if (ctx.config.pageExtensions?.includes('md')) {\n throw new Error(\n [\n \"[timber] pageExtensions includes 'md', but .md route pages are not supported:\",\n 'Markdown files compile to HTML strings, not components.',\n '',\n \"Use .mdx for pages (pageExtensions: ['tsx', 'ts', 'mdx']).\",\n '.md files can still be imported as HTML strings — no pageExtensions entry needed.',\n ].join('\\n')\n );\n }\n\n const createSatteriPlugin = (await tryImport('vite-plugin-satteri', ctx.root)) as\n | ((options?: Record<string, unknown>) => Plugin)\n | undefined;\n\n if (!createSatteriPlugin) {\n throw new Error(\n [\n '[timber] MDX is enabled but vite-plugin-satteri is not installed.',\n '',\n 'Install it:',\n ' pnpm add -D vite-plugin-satteri satteri',\n '',\n 'MDX is activated because pageExtensions includes \"mdx\"/\"md\" or a content/ directory exists.',\n ].join('\\n')\n );\n }\n\n // `|| {}` (not `??`): mdx can be `false`, though shouldActivate() has\n // already bailed in that case.\n const mdxConfig = ctx.config.mdx || {};\n\n // We pass `development` explicitly (satteri otherwise infers it from\n // Vite's command via its own configResolved hook, which we don't\n // delegate) and control providerImportSource — the mdx-components.tsx\n // convention belongs to the framework, not the user config.\n const mdxOptions: Record<string, unknown> = { development: ctx.dev };\n\n const mdxComponentsPath = findMdxComponents(ctx.root);\n if (mdxComponentsPath) {\n mdxOptions.providerImportSource = mdxComponentsPath;\n }\n\n innerPlugin = createSatteriPlugin({\n mdx: mdxOptions,\n ...(mdxConfig.mdastPlugins ? { mdastPlugins: mdxConfig.mdastPlugins } : {}),\n ...(mdxConfig.hastPlugins ? { hastPlugins: mdxConfig.hastPlugins } : {}),\n ...(mdxConfig.features ? { features: mdxConfig.features } : {}),\n });\n }\n\n return {\n name: 'timber-mdx',\n // Must run before @vitejs/plugin-rsc (rsc:use-client) which tries to parse\n // all files as JS. MDX files must be compiled to JS first.\n enforce: 'pre',\n\n async buildStart(options) {\n ctx.timer.start('mdx-activate');\n await activate();\n ctx.timer.end('mdx-activate');\n if (!innerPlugin) return;\n if (typeof innerPlugin.buildStart === 'function') {\n await (innerPlugin.buildStart as (options: unknown) => void | Promise<void>).call(\n this,\n options\n );\n }\n },\n\n async resolveId(source, importer, options) {\n if (!innerPlugin) return null;\n // MDX pages are server components — only compile in the RSC environment.\n // This prevents server-only deps (e.g. bright via mdx-components) from\n // being pulled into SSR or client bundles.\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.resolveId === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.resolveId as any).call(this, source, importer, options);\n }\n return null;\n },\n\n async load(id) {\n if (!innerPlugin) return null;\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.load === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.load as any).call(this, id);\n }\n return null;\n },\n\n async transform(code, id) {\n if (!innerPlugin) return null;\n // Ids with a Vite query (?raw, ?url, ?import) are asset requests, not\n // modules to compile. vite-plugin-satteri's id regexes match them, but\n // by the time this transform runs the code is already the asset module\n // (e.g. `export default \"<file text>\"` for ?raw) — compiling that as\n // markdown corrupts it. @mdx-js/rollup matched by extname and skipped\n // queried ids; preserve that behavior.\n if (id.includes('?')) return null;\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.transform === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.transform as any).call(this, code, id);\n }\n return null;\n },\n };\n}\n","/**\n * Route manifest codegen — generates virtual module source for the route\n * manifest and the global schema loader.\n *\n * Extracted from plugins/routing.ts to keep it under the 500-line budget.\n * See design/18-build-system.md §\"Virtual Modules\".\n *\n * Task: TIM-1071 item 8\n */\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { collectInterceptionRewrites } from './interception.ts';\nimport type { RouteTree, SegmentNode, RouteFile } from './types.ts';\n\n// ── Single-file conventions ─────────────────────────────────────────────\n// Each entry maps to a node property that holds a single RouteFile.\n// Order matches the original serializeNode output for byte-identical diffs.\nconst SINGLE_FILE_KEYS = [\n 'page',\n 'layout',\n 'middleware',\n 'access',\n 'route',\n 'error',\n 'default',\n 'denied',\n] as const;\n\n// ── Record-shaped conventions ───────────────────────────────────────────\n// Each entry maps to a node property that holds Record<string, RouteFile>.\nconst RECORD_FILE_KEYS = ['statusFiles', 'jsonStatusFiles', 'metadataRoutes'] as const;\n\nconst SCHEMA_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];\n\n// ── Manifest generation ─────────────────────────────────────────────────\n\n/**\n * Generate the virtual module source for the route manifest.\n *\n * The output is a default-exported object containing the serialized route tree.\n * All file references use absolute paths (required for virtual modules).\n */\nexport function generateManifestModule(tree: RouteTree, viteRoot: string): string {\n const imports: string[] = [];\n let importIndex = 0;\n\n function addImport(file: RouteFile): string {\n const varName = `_route${importIndex++}`;\n imports.push(`const ${varName} = () => import(\"${file.filePath}\");`);\n return varName;\n }\n\n function serializeRouteFile(key: string, file: RouteFile, indent: string): string {\n const v = addImport(file);\n return `${indent}${key}: { load: ${v}, filePath: ${JSON.stringify(file.filePath)} },`;\n }\n\n function serializeRouteFileRecord(\n key: string,\n record: Record<string, RouteFile>,\n indent: string\n ): string | null {\n const entries = Object.entries(record);\n if (entries.length === 0) return null;\n const inner = entries.map(([name, file]) => {\n const v = addImport(file);\n return `${indent} ${JSON.stringify(name)}: { load: ${v}, filePath: ${JSON.stringify(file.filePath)} }`;\n });\n return `${indent}${key}: {\\n${inner.join(',\\n')}\\n${indent}},`;\n }\n\n function serializeNode(node: SegmentNode, indent: string): string {\n const nextIndent = indent + ' ';\n const parts: string[] = [];\n\n parts.push(`${nextIndent}segmentName: ${JSON.stringify(node.segmentName)},`);\n parts.push(`${nextIndent}segmentType: ${JSON.stringify(node.segmentType)},`);\n parts.push(`${nextIndent}urlPath: ${JSON.stringify(node.urlPath)},`);\n\n if (node.paramName) {\n parts.push(`${nextIndent}paramName: ${JSON.stringify(node.paramName)},`);\n }\n if (node.paramPrefix) {\n parts.push(`${nextIndent}paramPrefix: ${JSON.stringify(node.paramPrefix)},`);\n }\n if (node.paramSuffix) {\n parts.push(`${nextIndent}paramSuffix: ${JSON.stringify(node.paramSuffix)},`);\n }\n\n if (node.interceptionMarker) {\n parts.push(`${nextIndent}interceptionMarker: ${JSON.stringify(node.interceptionMarker)},`);\n }\n if (node.interceptedSegmentName) {\n parts.push(\n `${nextIndent}interceptedSegmentName: ${JSON.stringify(node.interceptedSegmentName)},`\n );\n }\n\n // Single-file conventions — table-driven to avoid copy-paste drift\n for (const key of SINGLE_FILE_KEYS) {\n const file = node[key];\n if (file) {\n parts.push(serializeRouteFile(key, file, nextIndent));\n }\n }\n\n // Read from route.ts source at scan time; the CSRF gate consults it\n // before any user module loads (design/08 §\"Per-route exemption\").\n if (node.csrfExempt) {\n parts.push(`${nextIndent}csrfExempt: true,`);\n }\n\n // Record-shaped conventions — table-driven\n for (const key of RECORD_FILE_KEYS) {\n const record = node[key];\n if (record) {\n const line = serializeRouteFileRecord(key, record, nextIndent);\n if (line) parts.push(line);\n }\n }\n\n // Children\n if (node.children.length > 0) {\n const childNodes = node.children.map((c) => serializeNode(c, nextIndent));\n parts.push(`${nextIndent}children: [\\n${childNodes.join(',\\n')}\\n${nextIndent}],`);\n } else {\n parts.push(`${nextIndent}children: [],`);\n }\n\n // Parallel slots\n const slotKeys = Object.keys(node.slots);\n if (slotKeys.length > 0) {\n const slotEntries: string[] = [];\n for (const slotName of slotKeys) {\n const slotNode = node.slots[slotName]!;\n slotEntries.push(\n `${nextIndent} ${JSON.stringify(slotName)}: ${serializeNode(slotNode, nextIndent + ' ')}`\n );\n }\n parts.push(`${nextIndent}slots: {\\n${slotEntries.join(',\\n')}\\n${nextIndent}},`);\n } else {\n parts.push(`${nextIndent}slots: {},`);\n }\n\n return `${indent}{\\n${parts.join('\\n')}\\n${indent}}`;\n }\n\n const rootSerialized = serializeNode(tree.root, ' ');\n\n let proxyLine = '';\n if (tree.proxy) {\n const v = addImport(tree.proxy);\n proxyLine = ` proxy: { load: ${v}, filePath: ${JSON.stringify(tree.proxy.filePath)} },`;\n }\n\n let globalErrorLine = '';\n if (tree.globalError) {\n const v = addImport(tree.globalError);\n globalErrorLine = ` globalError: { load: ${v}, filePath: ${JSON.stringify(tree.globalError.filePath)} },`;\n }\n\n // Serialize the rewrite objects wholesale — an explicit field list here\n // silently drops any field added to InterceptionRewrite, and the guard that\n // reads it would then fall back to matching too broadly. InterceptionRewrite\n // is plain JSON data by construction (no file references, no functions).\n const rewrites = collectInterceptionRewrites(tree.root);\n const rewritesLine =\n rewrites.length > 0 ? ` interceptionRewrites: ${JSON.stringify(rewrites)},` : '';\n\n const code = [\n '// Auto-generated route manifest — do not edit.',\n '// Generated by timber-routing plugin.',\n '',\n ...imports,\n '',\n 'const manifest = {',\n ` viteRoot: ${JSON.stringify(viteRoot)},`,\n proxyLine,\n globalErrorLine,\n rewritesLine,\n ` root: ${rootSerialized},`,\n '};',\n '',\n 'export default manifest;',\n ]\n .filter((line) => line !== undefined && line !== '')\n .join('\\n');\n\n return code;\n}\n\n// ── Schema module ───────────────────────────────────────────────────────\n\n/**\n * Generate the virtual:timber-schema module.\n *\n * When app/schema.{ts,tsx,js,jsx} exists, generates a module that\n * imports the schema and resolves its segmentParams codecs into a\n * bare-name codec map for runtime coercion.\n */\nexport function generateSchemaModule(appDir: string): string {\n let schemaPath: string | null = null;\n for (const ext of SCHEMA_EXTENSIONS) {\n const candidate = join(appDir, `schema${ext}`);\n if (existsSync(candidate)) {\n schemaPath = candidate;\n break;\n }\n }\n\n if (!schemaPath) {\n return [\n '// Auto-generated schema loader — no app/schema.ts found.',\n 'export default null;',\n ].join('\\n');\n }\n\n return [\n '// Auto-generated schema loader — do not edit.',\n '// Generated by timber-routing plugin (TIM-931).',\n '',\n `import schema from ${JSON.stringify(schemaPath)};`,\n `import { resolveSchemaCodecs } from '@timber-js/app/params';`,\n '',\n 'const globalCodecs = schema?.segmentParams',\n ' ? resolveSchemaCodecs(schema.segmentParams)',\n ' : null;',\n '',\n 'export default globalCodecs;',\n ].join('\\n');\n}\n","/**\n * timber-routing — Vite sub-plugin for route manifest generation.\n *\n * Bridges the route scanner with Vite's module graph. Scans app/ at startup,\n * watches for file changes in dev, and serves the virtual:timber-route-manifest\n * module that entry files consume.\n *\n * Design docs: 18-build-system.md §\"Virtual Modules\", 07-routing.md\n */\n\nimport type { Plugin, ViteDevServer } from 'vite';\nimport { join } from 'node:path';\nimport { scanRoutes } from '../routing/scanner.ts';\nimport { buildDirToRouteMap, type SegmentInfo } from '../routing/segment-codegen.ts';\nimport { writeRouteCodegen, flushCodegenWrites } from '../routing/codegen-write.ts';\nimport { validateSchemaAgainstRoutes } from '../routing/schema-validation.ts';\nimport { generateManifestModule, generateSchemaModule } from '../routing/manifest-codegen.ts';\nimport {\n lintConventions,\n checkAppDirExists,\n formatConventionWarnings,\n} from '../routing/convention-lint.ts';\nimport type { PluginContext } from '../plugin-context.ts';\n\nconst VIRTUAL_MODULE_ID = 'virtual:timber-route-manifest';\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n// TIM-931: Schema virtual module.\n//\n// When app/schema.ts exists, this module imports it and resolves the\n// bracket-keyed segmentParams codecs into a bare-name codec map for\n// runtime coercion. When no schema exists, exports null.\nconst SCHEMA_ID = 'virtual:timber-schema';\nconst RESOLVED_SCHEMA_ID = `\\0${SCHEMA_ID}`;\n\n// TIM-935: $segment virtual module prefix.\n// Resolved ID encodes segment info as JSON after the prefix.\n//\n// Each route directory gets a virtual module that exports the route\n// and segmentPath. `import { route, segmentPath } from './$segment'`\n// resolves to `\\0$segment:<json>`.\nconst SEGMENT_PREFIX = '\\0$segment:';\n\n/**\n * File convention names we track for changes that require manifest regeneration.\n */\nconst ROUTE_FILE_PATTERNS =\n /\\/(page|layout|middleware|access|route|error|global-error|default|denied|schema|proxy|\\d{3}|[45]xx|sitemap|robots|manifest|favicon|icon|opengraph-image|apple-icon)\\./;\n\n/**\n * Create the timber-routing Vite plugin.\n *\n * Hooks: resolveId, load, buildStart, configureServer\n */\n/**\n * Write the generated route map and the timber-env.d.ts reference file.\n *\n * Not awaited, to avoid blocking the hot path — use `flushCodegenWrites()` to\n * wait for the writes to land. Failures are logged, not thrown: a missing .d.ts\n * is a developer UX issue in dev/build, not a runtime failure. (`timber check`\n * calls `writeRouteCodegen` directly and does treat a failure as fatal.)\n */\nfunction writeCodegen(ctx: PluginContext): void {\n if (!ctx.routeTree) return;\n // The analyze crawl child only needs the route tree for\n // classification — codegen writes are fire-and-forget and can be\n // truncated by the child's process.exit, leaving partial .d.ts\n // files on disk.\n if (process.env.TIMBER_ANALYZE === '1') return;\n void writeRouteCodegen(ctx.routeTree, ctx.appDir, ctx.root).catch((err) => {\n console.warn('[timber] Failed to write codegen output:', err);\n });\n}\n\nexport function timberRouting(ctx: PluginContext): Plugin {\n /** Track warned files to avoid repeating warnings on rescan. */\n const warnedFiles = new Set<string>();\n\n /** Maps absolute filesystem directory → segment info for $segment resolution. */\n let dirToRoute: Map<string, SegmentInfo> = new Map();\n\n function rescan(): void {\n // Check app/ directory exists before scanning\n const appDirWarning = checkAppDirExists(ctx.appDir);\n if (appDirWarning) {\n const formatted = formatConventionWarnings([appDirWarning]);\n if (formatted) process.stderr.write(`${formatted}\\n`);\n // Still create an empty tree so the rest of the pipeline doesn't crash\n ctx.routeTree = {\n root: {\n segmentName: '',\n segmentType: 'static',\n urlPath: '/',\n children: [],\n slots: {},\n },\n };\n return;\n }\n\n ctx.timer.start('route-scan');\n const tree = scanRoutes(ctx.appDir, {\n pageExtensions: ctx.config.pageExtensions,\n });\n ctx.timer.end('route-scan');\n\n // Lint conventions (empty app, missing methods, missing root layout).\n // Runs on the scanned tree *before* it is published: error-level findings\n // are proven-fatal misconfigurations — the app cannot render at all — so\n // the tree must not reach codegen, the manifest, or a live dev server's\n // module graph. Fail loudly rather than let the developer discover it as\n // an unattributed React error on an unrelated page (TIM-1329). Never\n // deduplicated against `warnedFiles`: an error must not be downgraded to\n // silence by an earlier scan in the same process.\n const conventionWarnings = lintConventions(tree, ctx.appDir);\n const fatal = conventionWarnings.filter((w) => w.level === 'error');\n if (fatal.length > 0) {\n throw new Error(formatConventionWarnings(fatal, { color: false }));\n }\n\n ctx.routeTree = tree;\n dirToRoute = buildDirToRouteMap(ctx.routeTree, ctx.appDir);\n writeCodegen(ctx);\n\n // Validate schema keys against filesystem segments.\n // Warns on stale keys, bracket form mismatches, and missing keys.\n // See design/41-global-params.md §Auto-Scaffolding\n warnSchemaValidation(ctx);\n\n const newConventionWarnings = conventionWarnings.filter((w) => !warnedFiles.has(w.id));\n if (newConventionWarnings.length > 0) {\n for (const w of newConventionWarnings) warnedFiles.add(w.id);\n const formatted = formatConventionWarnings(newConventionWarnings);\n if (formatted) process.stderr.write(`${formatted}\\n`);\n }\n }\n\n return {\n name: 'timber-routing',\n\n /**\n * Resolve the virtual module ID.\n *\n * Handles:\n * - virtual:timber-route-manifest\n * - <root>/virtual:timber-route-manifest (Vite SSR build root prefix)\n * - \\0virtual:timber-route-manifest (RSC plugin re-imports)\n */\n resolveId(id: string, importer?: string) {\n // Strip \\0 prefix if present (RSC plugin generates these)\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (cleanId === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n // Handle root-prefixed resolution in SSR build\n if (cleanId.endsWith(`/${VIRTUAL_MODULE_ID}`)) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n // TIM-931: Schema virtual module\n if (cleanId === SCHEMA_ID || cleanId.endsWith(`/${SCHEMA_ID}`)) {\n return RESOLVED_SCHEMA_ID;\n }\n\n // TIM-935: $segment virtual module.\n // Resolves `import { route } from './$segment'` based on the\n // importing file's directory in the app/ tree.\n if (\n importer &&\n (cleanId === './$segment' || cleanId === './$segment.js' || cleanId === './$segment.ts')\n ) {\n // Strip \\0 prefix from importer if present\n const cleanImporter = importer.startsWith('\\0') ? importer.slice(1) : importer;\n const importerDir = cleanImporter.substring(0, cleanImporter.lastIndexOf('/'));\n const segmentInfo = dirToRoute.get(importerDir);\n if (segmentInfo !== undefined) {\n return `${SEGMENT_PREFIX}${JSON.stringify(segmentInfo)}`;\n }\n }\n\n return null;\n },\n\n /**\n * Generate the route manifest module.\n *\n * The manifest exports the route tree as a serialized data structure\n * with absolute import paths for all file references.\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_ID) {\n // If routeTree hasn't been built yet (shouldn't happen), scan now\n if (!ctx.routeTree) {\n rescan();\n }\n return generateManifestModule(ctx.routeTree!, ctx.root);\n }\n\n if (id === RESOLVED_SCHEMA_ID) {\n return generateSchemaModule(ctx.appDir);\n }\n\n // TIM-935: $segment virtual module — exports route and segmentPath.\n if (id.startsWith(SEGMENT_PREFIX)) {\n const info: SegmentInfo = JSON.parse(id.slice(SEGMENT_PREFIX.length));\n return [\n `export const ROUTE = ${JSON.stringify(info.route)};`,\n `export const SEGMENT_PATH = ${JSON.stringify(info.segmentPath)};`,\n '',\n ].join('\\n');\n }\n\n return null;\n },\n\n /**\n * Scan routes at build start.\n *\n * In dev mode, skip — configureServer runs after buildStart and will\n * do its own scan. Avoids a redundant FS traversal on cold start.\n */\n buildStart() {\n if (ctx.dev) return;\n rescan();\n },\n\n /**\n * Wait for the codegen writes started by `buildStart` before the build\n * reports done.\n *\n * `writeCodegen` runs unawaited so route scanning never blocks on disk.\n * Without this the build can finish — and the CLI can exit — while the\n * generated `.d.ts` files are still being written, leaving a project root\n * with no route types after an apparently successful build.\n */\n closeBundle() {\n return flushCodegenWrites();\n },\n\n /**\n * Set up file watcher in dev mode.\n *\n * Watches app/ for file additions/deletions/renames that affect\n * the route tree, regenerates the manifest, and invalidates\n * dependent modules via HMR.\n */\n configureServer(devServer: ViteDevServer) {\n // Initial scan (only scan point in dev — buildStart is skipped)\n rescan();\n\n // Watch the app directory\n devServer.watcher.add(ctx.appDir);\n\n /** Snapshot of the last generated manifest, used to detect structural changes. */\n let lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n\n /**\n * Rescan without letting a rejected route tree kill the dev server.\n *\n * `rescan()` throws on hard misconfigurations — duplicate conventions,\n * route collisions, a status file that is not a client component. Those\n * throws are correct at startup and in `vite build`, but here they run\n * inside a chokidar listener, where an exception is an unhandled\n * rejection that takes the process down mid-edit. Report and keep the\n * last good tree so the server stays up and the fix is one save away.\n *\n * Returns false when the scan failed, so callers skip the manifest\n * regeneration that would otherwise publish a stale tree as fresh.\n */\n /**\n * True while the last rescan is still failing.\n *\n * Recovery has to force a reload even when the manifest is byte-identical.\n * Adding a missing `'use client'` back to a status file changes no route\n * metadata, so the content-change path would send nothing and leave the\n * error overlay on screen over a page that is now fine.\n */\n let scanFailed = false;\n\n const rescanSafely = (): boolean => {\n try {\n rescan();\n if (scanFailed) {\n scanFailed = false;\n // Force the reload: see `scanFailed`.\n lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n invalidateManifest(devServer);\n }\n return true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `[timber] Route scan failed — keeping previous routes.\\n${message}\\n`\n );\n scanFailed = true;\n\n // The terminal is not the only surface that needs this. Keeping the\n // previous tree keeps the *server* alive, but it does not un-edit the\n // file: Vite still re-transforms it, so the very next render hits the\n // failure this scan just diagnosed — and the browser's version of it\n // names nothing. Put the diagnosis where the developer is looking.\n devServer.hot.send({\n type: 'error',\n err: { message, stack: '', plugin: 'timber-routing' },\n });\n return false;\n }\n };\n\n /**\n * Handle a route-significant file being added or removed.\n * Always triggers a full-reload since the route tree structure changed.\n */\n const handleStructuralChange = (filePath: string) => {\n if (!filePath.startsWith(ctx.appDir)) return;\n if (!ROUTE_FILE_PATTERNS.test(filePath)) return;\n\n if (!rescanSafely()) return;\n lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n invalidateManifest(devServer);\n };\n\n /**\n * Handle a route file's content changing.\n *\n * Most content edits (JSX changes, fixing typos) don't affect route\n * metadata — Vite's React Fast Refresh handles those via normal HMR.\n * Only rescan and full-reload when route metadata actually changed\n * (e.g., searchParams export added/removed, metadata export changed).\n */\n const handleContentChange = (filePath: string) => {\n if (!filePath.startsWith(ctx.appDir)) return;\n if (!ROUTE_FILE_PATTERNS.test(filePath)) return;\n\n if (!rescanSafely()) return;\n const newManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n if (newManifest !== lastManifest) {\n lastManifest = newManifest;\n invalidateManifest(devServer);\n }\n // Otherwise: content edit didn't change route metadata — let Vite HMR handle it\n };\n\n devServer.watcher.on('add', handleStructuralChange);\n devServer.watcher.on('unlink', handleStructuralChange);\n // Watch content changes to page files — searchParams detection depends\n // on file contents (export const searchParams), not just file presence.\n // But only full-reload when route metadata actually changes.\n devServer.watcher.on('change', handleContentChange);\n // Also watch renames (which are add+unlink) — handled by the above\n },\n };\n}\n\n/**\n * Invalidate the virtual route manifest module across all Vite environments.\n *\n * When the route tree changes, any environment that has imported the manifest\n * needs to be invalidated so the next request/transform picks up the new tree.\n */\n/** Set of warning keys we've already emitted — avoid repeating on every rescan. */\nconst _warnedKeys = new Set<string>();\n\n/**\n * Validate schema keys against the filesystem route tree.\n * Warns on stale keys, bracket form mismatches, and missing keys.\n * Uses the already-scanned route tree instead of re-scanning.\n */\nfunction warnSchemaValidation(ctx: PluginContext): void {\n if (!ctx.routeTree) return;\n const warnings = validateSchemaAgainstRoutes(ctx.routeTree, ctx.appDir);\n\n for (const w of warnings) {\n const warnKey = `${w.type}:${w.key}`;\n if (_warnedKeys.has(warnKey)) continue;\n _warnedKeys.add(warnKey);\n\n switch (w.type) {\n case 'stale-key':\n console.warn(`[timber] ${w.message}`);\n break;\n case 'bracket-mismatch':\n console.warn(`[timber] ${w.message}`);\n break;\n case 'missing-key':\n console.warn(`[timber] ${w.message}`);\n break;\n }\n }\n}\n\nfunction invalidateManifest(server: ViteDevServer): void {\n for (const envName of Object.keys(server.environments)) {\n const env = server.environments[envName];\n if (!env?.moduleGraph) continue;\n\n for (const virtualId of [RESOLVED_VIRTUAL_ID, RESOLVED_SCHEMA_ID]) {\n const mod = env.moduleGraph.getModuleById(virtualId);\n if (mod) {\n env.moduleGraph.invalidateModule(mod);\n }\n }\n\n // TIM-935: Invalidate all $segment virtual modules (prefixed \\0$segment:)\n for (const mod of env.moduleGraph.idToModuleMap.values()) {\n if (mod.id?.startsWith(SEGMENT_PREFIX)) {\n env.moduleGraph.invalidateModule(mod);\n }\n }\n }\n\n // Trigger HMR full reload — route changes are structural\n server.hot.send({ type: 'full-reload' });\n}\n","/**\n * timber-shims — Vite sub-plugin for next/* → timber shim resolution.\n *\n * Intercepts imports of next/* modules and redirects them to timber.js\n * shim implementations. This enables Next.js-compatible libraries\n * (nuqs, next-intl, etc.) to work unmodified.\n *\n * This plugin also remaps ALL @timber-js/app/* subpath imports to src/ in\n * server environments (RSC + SSR). This is required because dist/ chunks\n * are pre-built and miss Vite's RSC transforms (e.g. createContext from\n * 'react' doesn't exist in RSC's React build). It also ensures a single\n * module instance for shared mutable state. See SUBPATH_SRC_MAP and TIM-568.\n *\n * Design doc: 18-build-system.md §\"Shim Map\"\n */\n\nimport type { Plugin } from 'vite';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { EXPLICIT_MARKERS, markerFor, poisonPillSource } from '../analyze/poison-rules.ts';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// Detect whether we're running from source (src/plugins/) or dist (dist/).\n// From src/plugins/: go up 2 levels to package root.\n// From dist/: go up 1 level to package root.\n// When Rollup bundles into dist/index.js, __dirname is dist/, not src/plugins/.\nconst PKG_ROOT = __dirname.endsWith('plugins')\n ? resolve(__dirname, '..', '..')\n : resolve(__dirname, '..');\nconst SHIMS_DIR = resolve(PKG_ROOT, 'src', 'shims');\n\n/**\n * The server-only marker's virtual ID, needed directly by the\n * `#server-only-guard` resolution branch below. All poison-pill rules\n * (specifiers, virtual IDs, error messages, environment policy) live in\n * analyze/poison-rules.ts — the single source of truth shared with the\n * `timber graph` reporter (design/47 §3).\n */\nconst SERVER_ONLY_VIRTUAL = markerFor('server-only').virtualId;\n\n/**\n * Map from @timber-js/app/<subpath> to relative src/ file paths.\n *\n * Used by the catch-all resolveId rule to remap subpath imports to src/\n * in server environments. When adding a new subpath export to package.json,\n * add it here too — tests/shims-drift.test.ts enumerates package.json\n * exports and fails if an entry is missing. See TIM-568.\n *\n * Exported for the drift test.\n */\nexport const SUBPATH_SRC_MAP: Record<string, string> = {\n 'cache': 'cache/index.ts',\n 'codec': 'codec.ts',\n 'cookies': 'cookies/index.ts',\n 'params': 'params/index.ts',\n 'search-params': 'search-params/index.ts',\n\n 'cache/stores/memory': 'cache/stores/memory.ts',\n 'cache/stores/redis': 'cache/stores/redis.ts',\n 'cache/stores/cloudflare-kv': 'cache/stores/cloudflare-kv.ts',\n 'cache/stores/vercel': 'cache/stores/vercel.ts',\n\n 'cdn': 'cdn/index.ts',\n 'cdn/cloudflare': 'cdn/cloudflare-purge.ts',\n 'cdn/cloudflare-workers': 'cdn/workers-cache-purge.ts',\n 'cdn/fastly': 'cdn/fastly-purge.ts',\n\n 'adapters/cloudflare': 'adapters/cloudflare.ts',\n 'adapters/cloudflare/cache': 'adapters/cloudflare-kv-cache.ts',\n 'adapters/cloudflare/dev': 'adapters/cloudflare-dev.ts',\n 'adapters/nitro': 'adapters/nitro.ts',\n 'adapters/types': 'adapters/types.ts',\n};\n\n/**\n * Runtime value exports of @timber-js/app/server, stubbed in the client\n * (browser) environment so a stray client-side import fails with a clear\n * call-time error instead of a confusing bundler error.\n *\n * Must stay in sync with the actual runtime exports of server/index.ts —\n * tests/shims-drift.test.ts compares this list against\n * Object.keys(import('../server/index.ts')) and fails on drift.\n * Type-only exports (DenyOptions, AccessContext, …) are erased at runtime\n * and must NOT appear here.\n */\nexport const SERVER_STUB_EXPORTS: readonly string[] = [\n // request-context\n 'getHeaders',\n 'getSegmentParams',\n // cookie-context\n 'getCookieJar',\n // primitives\n 'deny',\n 'redirect',\n 'redirectExternal',\n 'RedirectType',\n 'waitUntil',\n // action-client\n 'createActionClient',\n 'ActionError',\n 'validated',\n // form-data\n 'coerce',\n 'parseFormData',\n // revalidation\n 'revalidatePath',\n 'revalidateTag',\n // tracing\n 'getTraceId',\n 'getSpanId',\n 'withSpan',\n 'addSpanEvent',\n];\n\n/**\n * Map from next/* import specifiers to shim file paths.\n *\n * The shim map is a separate data structure (not embedded in the plugin)\n * per the task's approach constraints.\n */\nconst SHIM_MAP: Record<string, string> = {\n 'next/link': resolve(SHIMS_DIR, 'link.ts'),\n 'next/image': resolve(SHIMS_DIR, 'image.ts'),\n 'next/navigation': resolve(SHIMS_DIR, 'navigation.ts'),\n 'next/headers': resolve(SHIMS_DIR, 'headers.ts'),\n // next/font/* and @timber-js/app/fonts/* redirect to the timber-fonts\n // virtual modules. The fonts plugin's load hook serves the actual module\n // code. The package.json exports point to shim stubs for non-Vite contexts\n // (tsc, tests), but in Vite the virtual module takes priority via this map.\n 'next/font/google': '\\0@timber/fonts/google',\n 'next/font/local': '\\0@timber/fonts/local',\n '@timber-js/app/fonts/google': '\\0@timber/fonts/google',\n '@timber-js/app/fonts/local': '\\0@timber/fonts/local',\n};\n\n/**\n * Strip .js extension from an import specifier.\n *\n * Libraries like nuqs import `next/navigation.js` with an explicit\n * extension. We strip it before matching against the shim map.\n */\nfunction stripJsExtension(id: string): string {\n return id.endsWith('.js') ? id.slice(0, -3) : id;\n}\n\n/**\n * Read the Vite environment name from a plugin hook's `this` context.\n *\n * Duck-typed because the hook context type doesn't expose `environment`\n * in a way that survives our Plugin typing — see Vite's Environment API.\n */\nfunction envName(hookCtx: unknown): string | undefined {\n return (hookCtx as { environment?: { name?: string } }).environment?.name;\n}\n\n/**\n * Create the timber-shims Vite plugin.\n *\n * Hooks: resolveId, load\n */\nexport function timberShims(_ctx: PluginContext): Plugin {\n return {\n name: 'timber-shims',\n // Must run before Vite's built-in resolution so that server-only/client-only\n // poison pills are intercepted even when imported from node_modules deps\n // (e.g. bright, next-intl). Without this, the dep optimizer resolves to the\n // real CJS package which throws at runtime in the SSR environment.\n enforce: 'pre',\n\n /**\n * Resolve next/* imports to shim files.\n *\n * Resolution order:\n * 1. Check server-only / client-only poison pill packages\n * 2. Strip .js extension from the import specifier\n * 3. Check next/* shim map\n * 4. Return null (pass through) for everything else\n *\n * In server environments (RSC + SSR), @timber-js/app/* subpath imports\n * are remapped to src/ via SUBPATH_SRC_MAP and the explicit branches\n * below — dist/ chunks miss Vite's RSC transforms and would duplicate\n * mutable module state (see TIM-568 and the rationale comments below).\n *\n * In the client (browser) environment, imports resolve to dist/ via\n * package.json exports — except @timber-js/app/client (remapped to src/\n * to share module instances with browser-entry) and @timber-js/app/server,\n * which returns a virtual stub: server code must never be bundled into\n * the browser.\n */\n resolveId(id: string) {\n // Poison pill packages — resolve to virtual modules handled by load()\n for (const marker of EXPLICIT_MARKERS) {\n if (id === marker.specifier) return marker.virtualId;\n }\n\n const cleanId = stripJsExtension(id);\n\n // Check next/* shim map.\n // next/navigation resolves per environment (TIM-1420):\n // RSC → navigation-rsc.ts (throwing stubs — no useContext)\n // SSR → navigation.ts (real hooks + server functions)\n // client → navigation-client.ts (real hooks, no server imports)\n if (cleanId in SHIM_MAP) {\n if (cleanId === 'next/navigation') {\n const env = envName(this);\n if (env === 'client') return resolve(SHIMS_DIR, 'navigation-client.ts');\n if (env === 'rsc') return resolve(SHIMS_DIR, 'navigation-rsc.ts');\n }\n return SHIM_MAP[cleanId];\n }\n\n // ── @timber-js/app/* → src/ resolution in server environments ──\n //\n // All @timber-js/app/* subpath imports are remapped to src/ in server\n // environments (RSC + SSR). This is required for two reasons:\n //\n // 1. RSC correctness: dist/ chunks eagerly import from 'react' (e.g.\n // createContext in segment-context) which doesn't exist in RSC's\n // React build. Vite's RSC plugin only transforms src/ files —\n // dist/ chunks are pre-built and served as-is.\n //\n // 2. Module singleton correctness: framework internals use relative\n // imports that resolve within src/. If user code resolved to dist/\n // while framework code resolved to src/, mutable module-level state\n // (ALS refs, registered callbacks) would be duplicated. By remapping\n // all @timber-js/app/* to src/, everything shares one module graph.\n //\n // Exception: @timber-js/app/client in RSC resolves to dist/ where\n // 'use client' is preserved for client boundary detection.\n //\n // In the client (browser) environment, all imports resolve to dist/\n // via package.json exports (no remapping needed).\n\n // ── #imports resolution for package-internal modules ─────────────\n //\n // #server-internal and #client-internal are Node package imports\n // (package.json \"imports\" field). They are only resolvable from\n // within this package — external consumers get module-not-found.\n //\n // In Vite, we intercept them here to resolve to src/ for dev/build\n // correctness (same rationale as the @timber-js/app/* remap above).\n if (cleanId === '#server-only-guard') {\n const env = envName(this);\n if (env === 'client') {\n return SERVER_ONLY_VIRTUAL;\n }\n return resolve(PKG_ROOT, 'src', 'server', 'server-only-guard-noop.js');\n }\n\n if (cleanId === '#server-internal') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n return resolve(PKG_ROOT, 'src', 'server', 'internal.ts');\n }\n\n if (cleanId === '#client-internal') {\n // Always resolve to src/ — all environments (RSC, SSR, client)\n // use src/ for framework internals. In the client env, this\n // ensures browser-entry and @timber-js/app/client share the\n // same module graph (both resolve to src/).\n return resolve(PKG_ROOT, 'src', 'client', 'internal.ts');\n }\n\n if (cleanId === '#routing') {\n return resolve(PKG_ROOT, 'src', 'routing', 'index.ts');\n }\n\n // Legacy aliases — vitest and monorepo configs may still reference\n // the old @timber-js/app/server/internal and @timber-js/app/client/internal\n // specifiers via resolve.alias. When those aliases resolve to the\n // absolute src/ path, they bypass this plugin entirely. But if the\n // specifier reaches us unresolved (e.g., in a Vite build without\n // aliases), handle it the same way as the #imports above.\n if (cleanId === '@timber-js/app/server/internal') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n return resolve(PKG_ROOT, 'src', 'server', 'internal.ts');\n }\n\n if (cleanId === '@timber-js/app/client/internal') {\n // Same as #client-internal above — always resolve to src/.\n return resolve(PKG_ROOT, 'src', 'client', 'internal.ts');\n }\n\n if (cleanId === '@timber-js/app/server') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n // RSC + SSR: remap to src/\n return resolve(PKG_ROOT, 'src', 'server', 'index.ts');\n }\n\n // Alias hardening: monorepo dev configs (tests/shared-vite-config.ts,\n // packages/website) alias @timber-js/app/server to the absolute\n // src/server path for vitest compatibility. Vite's resolve.alias runs\n // before every plugin, so the bare-specifier branch above never sees\n // the import in those apps — the real server barrel (and its\n // AsyncLocalStorage) would be bundled into the browser. Catch the\n // already-aliased absolute path here and return the same stub.\n if (\n cleanId === resolve(PKG_ROOT, 'src', 'server', 'index.ts') ||\n cleanId === resolve(PKG_ROOT, 'src', 'server', 'internal.ts')\n ) {\n if (envName(this) === 'client') {\n return '\\0timber:server-empty';\n }\n }\n\n if (cleanId === '@timber-js/app/client') {\n const env = envName(this);\n // RSC: return null — needs dist/ for 'use client' boundary detection.\n // SSR + Client: resolve to src/ so that browser-entry (which uses\n // relative imports from src/) and user code (which uses the bare\n // specifier @timber-js/app/client) share the same module instances.\n // Without this, state.ts is loaded twice (src/ and dist/) and\n // setGlobalRouter() writes to one copy while getRouterOrNull()\n // reads from the other (always null).\n if (env === 'ssr' || env === 'client') {\n return resolve(PKG_ROOT, 'src', 'client', 'index.ts');\n }\n return null;\n }\n\n // Catch-all: remap any other @timber-js/app/<subpath> to src/\n // in non-client environments (RSC + SSR).\n if (cleanId.startsWith('@timber-js/app/') && cleanId !== '@timber-js/app/package.json') {\n const env = envName(this);\n if (env !== 'client') {\n const subpath = cleanId.slice('@timber-js/app/'.length);\n const srcPath = SUBPATH_SRC_MAP[subpath];\n if (srcPath) {\n return resolve(PKG_ROOT, 'src', srcPath);\n }\n }\n }\n\n return null;\n },\n\n /**\n * Serve virtual modules for server-only / client-only poison pills.\n *\n * In the correct environment, the module is a no-op (empty export).\n * In the wrong environment, it throws a build-time error message that\n * clearly identifies the boundary violation.\n */\n load(id: string) {\n const env = envName(this);\n\n // Poison pill bodies — a top-level throw in the wrong environment,\n // a no-op in the right one. Behavior (which environments throw, and\n // the exact message) is defined entirely by poison-rules.ts.\n for (const marker of EXPLICIT_MARKERS) {\n if (id === marker.virtualId) return poisonPillSource(marker, env);\n }\n\n // Error module for @timber-js/app/server in client environment.\n // Server modules must never be bundled into the browser — if this\n // module is reached, there is a broken import chain that needs fixing.\n if (id === '\\0timber:server-empty') {\n // Export named stubs instead of throwing at evaluation time.\n // Throwing at eval breaks the module system — the browser can't\n // resolve named imports like `import { deny } from '...'`.\n // Instead, each stub throws at call time with a clear message.\n // The export names are generated from SERVER_STUB_EXPORTS so the\n // list cannot drift from server/index.ts (drift test enforced).\n // RedirectType is a plain const object on the server, so it is\n // mirrored as one here — libraries read RedirectType.push as a value.\n const stubExports = SERVER_STUB_EXPORTS.map((name) =>\n name === 'RedirectType'\n ? `export const RedirectType = { push: 'push', replace: 'replace' };`\n : `export const ${name} = stub;`\n ).join('\\n');\n return `\nconst msg = \"[timber] @timber-js/app/server was imported from client code. \" +\n \"Server modules (headers, cookies, redirect, deny, etc.) cannot be used in client components. \" +\n \"If you need these APIs, move the import to a server component or middleware.\";\nfunction stub() { throw new Error(msg); }\n${stubExports}\n`;\n }\n },\n };\n}\n","/**\n * Shared path/URL helpers for the timber-fonts pipeline.\n *\n * Two concerns live here:\n *\n * - `fontUrlPrefix` — the public URL prefix for font binaries, derived\n * from Vite's resolved `base`. Every URL the pipeline emits (@font-face\n * src, manifest hrefs, dev middleware matching) must go through this so\n * apps deployed under a non-root base (`base: '/my-app/'`) resolve\n * fonts correctly. Emitted *file* locations are not base-prefixed —\n * only URLs are.\n *\n * - `fontOutputBasename` / `hashedFontBasename` — basename derivation for\n * local font sources. Paths are absolutized with `resolve()`, which\n * produces backslash separators on Windows, so `split('/').pop()` is\n * not safe. `path.win32.basename` handles both separators.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { win32 } from 'node:path';\n\n/** Directory (relative to the build output / URL root) holding font binaries. */\nexport const FONT_OUTPUT_DIR = '_timber/fonts';\n\n/**\n * Build the URL prefix for font binaries from Vite's resolved `base`.\n *\n * `fontUrlPrefix('/')` → `/_timber/fonts`\n * `fontUrlPrefix('/my-app/')` → `/my-app/_timber/fonts`\n */\nexport function fontUrlPrefix(base = '/'): string {\n const normalized = base.endsWith('/') ? base : `${base}/`;\n return `${normalized}${FONT_OUTPUT_DIR}`;\n}\n\n/**\n * Derive the output basename for a local font source path.\n *\n * Uses `path.win32.basename` because it splits on both `/` and `\\`,\n * handling absolute paths produced by `resolve()` on any platform.\n */\nexport function fontOutputBasename(srcPath: string): string {\n return win32.basename(srcPath);\n}\n\n/**\n * Derive the content-hashed output basename for a local font source.\n *\n * `hashedFontBasename('C:\\\\fonts\\\\MyFont-Bold.woff2', 'a1b2c3d4')`\n * → `MyFont-Bold-a1b2c3d4.woff2`\n */\nexport function hashedFontBasename(srcPath: string, hash: string): string {\n const basename = fontOutputBasename(srcPath);\n const ext = win32.extname(basename);\n const stem = ext ? basename.slice(0, -ext.length) : basename;\n return `${stem}-${hash}${ext}`;\n}\n","/**\n * Google Fonts download, caching, and dev CDN fallback.\n *\n * At build time (production only):\n * 1. Queries Google Fonts CSS API v2 for font metadata and file URLs\n * 2. Downloads woff2 font files\n * 3. Caches them in node_modules/.cache/timber-fonts/\n * 4. Content-hashes filenames for cache busting\n * 5. Emits font files into the build output via generateBundle\n *\n * In dev mode:\n * - Generates @font-face rules pointing to Google Fonts CDN\n * - No downloads, no caching\n *\n * Design doc: 24-fonts.md §\"Step 2: Font Download & Subsetting\"\n */\n\nimport { createHash } from 'node:crypto';\nimport { readFile, writeFile, mkdir, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ExtractedFont, FontFaceDescriptor } from './types.ts';\nimport { fontUrlPrefix } from './paths.ts';\n\n/**\n * Extract a recognizable error code (ETIMEDOUT, ENOTFOUND, etc.) from a\n * network error's cause chain. Node's undici-based `fetch` wraps the\n * system error inside `cause` (sometimes as an AggregateError).\n */\nfunction extractNetworkErrorCode(err: unknown): string | undefined {\n if (!(err instanceof Error)) return undefined;\n const code = (err as NodeJS.ErrnoException).code;\n if (code) return code;\n const cause = (err as { cause?: unknown }).cause;\n if (cause instanceof AggregateError) {\n for (const inner of cause.errors) {\n const innerCode = (inner as NodeJS.ErrnoException).code;\n if (innerCode) return innerCode;\n }\n }\n if (cause instanceof Error) {\n return (cause as NodeJS.ErrnoException).code;\n }\n return undefined;\n}\n\nconst MAX_RETRIES = 3;\nconst MIN_TIMEOUT_MS = 100;\n\nasync function retry<T>(fn: () => Promise<T>): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (attempt < MAX_RETRIES) {\n const delay = MIN_TIMEOUT_MS * 2 ** attempt;\n console.error(\n `${err instanceof Error ? err.message : String(err)}\\n\\nRetrying ${attempt + 1}/${MAX_RETRIES}...`\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n}\n\n/** Google Fonts CSS API v2 base URL. */\nconst GOOGLE_FONTS_API = 'https://fonts.googleapis.com/css2';\n\n/**\n * User-Agent string that requests woff2 format from Google Fonts API.\n * Google serves different formats based on user-agent.\n */\nconst WOFF2_USER_AGENT =\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';\n\n/** Default cache directory for downloaded font files. */\nconst DEFAULT_CACHE_DIR = 'node_modules/.cache/timber-fonts';\n\n/** A parsed @font-face block from the Google Fonts CSS response. */\nexport interface GoogleFontFace {\n family: string;\n weight: string;\n style: string;\n /** The remote URL to the font file. */\n url: string;\n /** The unicode-range from the CSS (e.g. `U+0000-00FF, U+0131`). */\n unicodeRange: string;\n /** Subset label extracted from the CSS comment (e.g. `latin`, `cyrillic`). */\n subset: string;\n}\n\n/** A downloaded and cached font file, ready for build output. */\nexport interface CachedFont {\n /** The original parsed face data. */\n face: GoogleFontFace;\n /** Content-hashed filename (e.g. `inter-latin-400-normal-abc123.woff2`). */\n hashedFilename: string;\n /** Absolute path to the cached file. */\n cachePath: string;\n /** Raw font file bytes. */\n data: Buffer;\n}\n\n/**\n * Build the Google Fonts CSS API v2 URL for a given font config.\n *\n * Example output:\n * https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap&subset=latin\n */\nexport function buildGoogleFontsUrl(font: ExtractedFont): string {\n const family = font.family.replace(/\\s+/g, '+');\n\n // Build axis spec: wght for weights, ital for italic styles\n const hasItalic = font.styles.includes('italic');\n const weights = font.weights.map(Number).sort((a, b) => a - b);\n\n let axisSpec: string;\n if (hasItalic && weights.length > 0) {\n // ital,wght@0,400;0,700;1,400;1,700\n const pairs: string[] = [];\n for (const ital of [0, 1]) {\n if (ital === 1 && !hasItalic) continue;\n if (ital === 0 && font.styles.length === 1 && font.styles[0] === 'italic') continue;\n for (const w of weights) {\n pairs.push(`${ital},${w}`);\n }\n }\n axisSpec = `ital,wght@${pairs.join(';')}`;\n } else if (weights.length > 0) {\n axisSpec = `wght@${weights.join(';')}`;\n } else {\n axisSpec = '';\n }\n\n const familyParam = axisSpec ? `${family}:${axisSpec}` : family;\n\n // Build URL manually — URLSearchParams encodes +, :, @, ; which\n // the Google Fonts CSS API v2 requires as literal characters.\n const parts = [`family=${familyParam}`];\n if (font.display) parts.push(`display=${font.display}`);\n\n return `${GOOGLE_FONTS_API}?${parts.join('&')}`;\n}\n\n/**\n * Fetch the CSS from Google Fonts API and parse out @font-face blocks.\n *\n * The API returns CSS with subset comments like:\n * ```\n * /* latin * /\n * @font-face { ... }\n * ```\n *\n * We parse each block to extract the font URL, unicode-range, and subset label.\n */\nexport async function fetchGoogleFontsCss(url: string): Promise<GoogleFontFace[]> {\n const css = await retry(async () => {\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { 'User-Agent': WOFF2_USER_AGENT },\n });\n } catch (err) {\n const code = extractNetworkErrorCode(err);\n throw new Error(\n `[timber] Failed to fetch Google Fonts CSS from ${url}` +\n (code ? ` (${code})` : '') +\n `. Build requires internet access for font optimization.` +\n ` If building offline, set TIMBER_SKIP_FONTS=1 to skip font downloading.`\n );\n }\n\n if (!response.ok) {\n throw new Error(\n `Google Fonts API returned ${response.status}: ${response.statusText} for ${url}`\n );\n }\n\n return response.text();\n });\n\n return parseGoogleFontsCss(css);\n}\n\n/**\n * Parse the CSS response from Google Fonts API into structured font face data.\n *\n * Handles the Google Fonts CSS format with subset comments and @font-face blocks.\n */\nexport function parseGoogleFontsCss(css: string): GoogleFontFace[] {\n const faces: GoogleFontFace[] = [];\n\n // Match subset comments followed by @font-face blocks\n const blockPattern = /\\/\\*\\s*([a-z0-9-]+)\\s*\\*\\/\\s*@font-face\\s*\\{([^}]+)\\}/g;\n\n let match;\n while ((match = blockPattern.exec(css)) !== null) {\n const subset = match[1];\n const block = match[2];\n\n const familyMatch = block.match(/font-family:\\s*'([^']+)'/);\n const weightMatch = block.match(/font-weight:\\s*(\\d+)/);\n const styleMatch = block.match(/font-style:\\s*(\\w+)/);\n const urlMatch = block.match(/url\\(([^)]+)\\)\\s*format\\('woff2'\\)/);\n const rangeMatch = block.match(/unicode-range:\\s*([^;]+)/);\n\n if (familyMatch && urlMatch) {\n faces.push({\n family: familyMatch[1],\n weight: weightMatch?.[1] ?? '400',\n style: styleMatch?.[1] ?? 'normal',\n url: urlMatch[1],\n unicodeRange: rangeMatch?.[1]?.trim() ?? '',\n subset,\n });\n }\n }\n\n return faces;\n}\n\n/**\n * Filter parsed font faces to only the requested subsets.\n */\nexport function filterBySubsets(faces: GoogleFontFace[], subsets: string[]): GoogleFontFace[] {\n if (subsets.length === 0) return faces;\n const subsetSet = new Set(subsets);\n return faces.filter((f) => subsetSet.has(f.subset));\n}\n\n/**\n * Generate a content hash for font data.\n * Returns the first 8 hex chars of the SHA-256 hash.\n */\nexport function contentHash(data: Buffer): string {\n return createHash('sha256').update(data).digest('hex').slice(0, 8);\n}\n\n/**\n * Generate a content-hashed filename for a font face.\n *\n * Format: `<family>-<subset>-<weight>-<style>-<hash>.woff2`\n * Example: `inter-latin-400-normal-abc12345.woff2`\n */\nexport function hashedFontFilename(face: GoogleFontFace, data: Buffer): string {\n const slug = face.family.toLowerCase().replace(/\\s+/g, '-');\n const hash = contentHash(data);\n return `${slug}-${face.subset}-${face.weight}-${face.style}-${hash}.woff2`;\n}\n\n/**\n * Build the cache key for a font face.\n * Used to check if a font has already been downloaded.\n */\nexport function cacheKey(face: GoogleFontFace): string {\n const slug = face.family.toLowerCase().replace(/\\s+/g, '-');\n return `${slug}-${face.subset}-${face.weight}-${face.style}`;\n}\n\n/**\n * Download a single font file from its URL.\n */\nexport async function downloadFontFile(url: string): Promise<Buffer> {\n return retry(async () => {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n const code = extractNetworkErrorCode(err);\n throw new Error(\n `[timber] Failed to download font file from ${url}` +\n (code ? ` (${code})` : '') +\n `. Build requires internet access for font optimization.` +\n ` If building offline, set TIMBER_SKIP_FONTS=1 to skip font downloading.`\n );\n }\n if (!response.ok) {\n throw new Error(`Failed to download font from ${url}: ${response.status}`);\n }\n return Buffer.from(await response.arrayBuffer());\n });\n}\n\n/**\n * Download and cache all font files for a set of extracted Google fonts.\n *\n * - Checks the local cache first (node_modules/.cache/timber-fonts/)\n * - Downloads missing fonts from Google Fonts CDN\n * - Writes downloaded fonts to cache\n * - Returns CachedFont entries with content-hashed filenames\n */\nexport async function downloadAndCacheFonts(\n fonts: ExtractedFont[],\n projectRoot: string\n): Promise<CachedFont[]> {\n const cacheDir = join(projectRoot, DEFAULT_CACHE_DIR);\n await mkdir(cacheDir, { recursive: true });\n\n const googleFonts = fonts.filter((f) => f.provider === 'google');\n const cached: CachedFont[] = [];\n\n for (const font of googleFonts) {\n const apiUrl = buildGoogleFontsUrl(font);\n let faces: GoogleFontFace[];\n try {\n faces = await fetchGoogleFontsCss(apiUrl);\n } catch (err) {\n throw new Error(\n `[timber] Failed to download font '${font.family}': ${err instanceof Error ? err.message : String(err)}`\n );\n }\n const filtered = filterBySubsets(faces, font.subsets);\n\n for (const face of filtered) {\n const key = cacheKey(face);\n const metaPath = join(cacheDir, `${key}.meta.json`);\n const dataPath = join(cacheDir, `${key}.woff2`);\n\n let data: Buffer;\n let filename: string;\n\n // Check cache\n const cacheHit = await isCacheHit(metaPath, dataPath);\n if (cacheHit) {\n data = await readFile(dataPath);\n const meta = JSON.parse(await readFile(metaPath, 'utf-8'));\n filename = meta.hashedFilename;\n } else {\n // Download and cache\n data = await downloadFontFile(face.url);\n filename = hashedFontFilename(face, data);\n\n await writeFile(dataPath, data);\n await writeFile(metaPath, JSON.stringify({ hashedFilename: filename, url: face.url }));\n }\n\n cached.push({ face, hashedFilename: filename, cachePath: dataPath, data });\n }\n }\n\n return cached;\n}\n\n/**\n * Check if both the meta and data files exist in the cache.\n */\nasync function isCacheHit(metaPath: string, dataPath: string): Promise<boolean> {\n try {\n await stat(metaPath);\n await stat(dataPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate @font-face descriptors for cached (production) Google Fonts.\n *\n * Each CachedFont gets a FontFaceDescriptor pointing to the\n * content-hashed URL under `<base>_timber/fonts/`. The `urlPrefix` comes\n * from `fontUrlPrefix(viteBase)` so apps deployed under a non-root base\n * resolve fonts correctly.\n */\nexport function generateProductionFontFaces(\n cachedFonts: CachedFont[],\n display: string,\n urlPrefix = fontUrlPrefix()\n): FontFaceDescriptor[] {\n return cachedFonts.map((cf) => ({\n family: cf.face.family,\n src: `url('${urlPrefix}/${cf.hashedFilename}') format('woff2')`,\n weight: cf.face.weight,\n style: cf.face.style,\n display,\n unicodeRange: cf.face.unicodeRange,\n }));\n}\n\n/**\n * Generate @font-face descriptors for dev mode (CDN-pointing).\n *\n * In dev mode, we query the Google Fonts API but use the CDN URLs\n * directly instead of downloading. This avoids the download/cache\n * step during `vite dev`.\n */\nexport function generateDevFontFaces(\n faces: GoogleFontFace[],\n display: string\n): FontFaceDescriptor[] {\n return faces.map((face) => ({\n family: face.family,\n src: `url('${face.url}') format('woff2')`,\n weight: face.weight,\n style: face.style,\n display,\n unicodeRange: face.unicodeRange,\n }));\n}\n\n/**\n * Resolve dev-mode font faces for an extracted font.\n *\n * Fetches the CSS from Google Fonts API and returns FontFaceDescriptors\n * pointing to CDN URLs. No files are downloaded.\n */\nexport async function resolveDevFontFaces(font: ExtractedFont): Promise<FontFaceDescriptor[]> {\n const apiUrl = buildGoogleFontsUrl(font);\n const faces = await fetchGoogleFontsCss(apiUrl);\n const filtered = filterBySubsets(faces, font.subsets);\n return generateDevFontFaces(filtered, font.display);\n}\n","/**\n * @font-face CSS generation.\n *\n * Generates CSS strings from font face descriptors. Used by both\n * Google and local font providers.\n *\n * Design doc: 24-fonts.md §\"Step 3: @font-face Generation\"\n */\n\nimport type { FontFaceDescriptor } from './types.ts';\n\n/**\n * Generate a single `@font-face` CSS rule from a descriptor.\n */\nexport function generateFontFace(desc: FontFaceDescriptor): string {\n const lines: string[] = [];\n lines.push('@font-face {');\n lines.push(` font-family: '${desc.family}';`);\n lines.push(` src: ${desc.src};`);\n if (desc.weight) lines.push(` font-weight: ${desc.weight};`);\n if (desc.style) lines.push(` font-style: ${desc.style};`);\n if (desc.display) lines.push(` font-display: ${desc.display};`);\n if (desc.unicodeRange) lines.push(` unicode-range: ${desc.unicodeRange};`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Generate multiple `@font-face` rules from an array of descriptors.\n */\nexport function generateFontFaces(descriptors: FontFaceDescriptor[]): string {\n return descriptors.map(generateFontFace).join('\\n\\n');\n}\n\n/**\n * Generate a scoped CSS class that sets a CSS custom property for the font.\n *\n * Example output:\n * ```css\n * .timber-font-inter {\n * --font-sans: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * }\n * ```\n */\nexport function generateVariableClass(\n className: string,\n variable: string,\n fontFamily: string\n): string {\n return `.${className} {\\n ${variable}: ${fontFamily};\\n font-family: ${fontFamily};\\n}`;\n}\n\n/**\n * Generate a scoped CSS class that applies font-family directly.\n *\n * Used when no `variable` is specified — the className applies\n * the font-family inline instead of through a CSS custom property.\n *\n * Example output:\n * ```css\n * .timber-font-inter {\n * font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * }\n * ```\n */\nexport function generateFontFamilyClass(className: string, fontFamily: string): string {\n return `.${className} {\\n font-family: ${fontFamily};\\n}`;\n}\n","/**\n * Size-adjusted fallback font generation.\n *\n * Generates `@font-face` declarations for fallback fonts with\n * `size-adjust`, `ascent-override`, `descent-override`, and\n * `line-gap-override` to match custom font metrics and eliminate CLS.\n *\n * Design doc: 24-fonts.md §\"Step 4: Size-Adjusted Fallbacks\"\n */\n\n/**\n * Font metrics for size-adjusted fallback calculation.\n *\n * Values are percentages used in CSS override descriptors.\n */\ninterface FallbackMetrics {\n /** The local() system font to use as base. */\n fallbackFont: string;\n /** size-adjust percentage (e.g. 107.64). */\n sizeAdjust: number;\n /** ascent-override percentage (e.g. 90.49). */\n ascentOverride: number;\n /** descent-override percentage (e.g. 22.48). */\n descentOverride: number;\n /** line-gap-override percentage (e.g. 0). */\n lineGapOverride: number;\n}\n\n/**\n * Lookup table for commonly used Google Fonts.\n *\n * Metrics sourced from fontaine / @capsizecss/metrics.\n * Keyed by lowercase font family name.\n */\nconst FALLBACK_METRICS: Record<string, FallbackMetrics> = {\n 'inter': {\n fallbackFont: 'Arial',\n sizeAdjust: 107.64,\n ascentOverride: 90.49,\n descentOverride: 22.48,\n lineGapOverride: 0,\n },\n 'roboto': {\n fallbackFont: 'Arial',\n sizeAdjust: 100.3,\n ascentOverride: 92.77,\n descentOverride: 24.41,\n lineGapOverride: 0,\n },\n 'open sans': {\n fallbackFont: 'Arial',\n sizeAdjust: 105.48,\n ascentOverride: 101.03,\n descentOverride: 27.47,\n lineGapOverride: 0,\n },\n 'lato': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.5,\n ascentOverride: 100.22,\n descentOverride: 21.16,\n lineGapOverride: 0,\n },\n 'montserrat': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.17,\n ascentOverride: 85.13,\n descentOverride: 22.07,\n lineGapOverride: 0,\n },\n 'poppins': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.76,\n ascentOverride: 96.31,\n descentOverride: 32.1,\n lineGapOverride: 0,\n },\n 'roboto mono': {\n fallbackFont: 'Courier New',\n sizeAdjust: 109.29,\n ascentOverride: 87.79,\n descentOverride: 23.1,\n lineGapOverride: 0,\n },\n 'jetbrains mono': {\n fallbackFont: 'Courier New',\n sizeAdjust: 112.7,\n ascentOverride: 89.53,\n descentOverride: 24.21,\n lineGapOverride: 0,\n },\n 'source code pro': {\n fallbackFont: 'Courier New',\n sizeAdjust: 106.13,\n ascentOverride: 93.47,\n descentOverride: 26.01,\n lineGapOverride: 0,\n },\n 'fira code': {\n fallbackFont: 'Courier New',\n sizeAdjust: 112.96,\n ascentOverride: 86.87,\n descentOverride: 26.34,\n lineGapOverride: 0,\n },\n 'nunito': {\n fallbackFont: 'Arial',\n sizeAdjust: 103.62,\n ascentOverride: 99.45,\n descentOverride: 34.8,\n lineGapOverride: 0,\n },\n 'playfair display': {\n fallbackFont: 'Georgia',\n sizeAdjust: 110.72,\n ascentOverride: 84.44,\n descentOverride: 23.56,\n lineGapOverride: 0,\n },\n 'merriweather': {\n fallbackFont: 'Georgia',\n sizeAdjust: 107.66,\n ascentOverride: 91.93,\n descentOverride: 27.6,\n lineGapOverride: 0,\n },\n 'raleway': {\n fallbackFont: 'Arial',\n sizeAdjust: 107.74,\n ascentOverride: 94.19,\n descentOverride: 26.76,\n lineGapOverride: 0,\n },\n};\n\n/**\n * Known serif font families (lowercase).\n * Used for generic family detection when the name doesn't contain \"serif\".\n */\nconst SERIF_FAMILIES = new Set([\n 'playfair display',\n 'merriweather',\n 'lora',\n 'georgia',\n 'garamond',\n 'eb garamond',\n 'crimson text',\n 'libre baskerville',\n 'source serif pro',\n 'source serif 4',\n 'dm serif display',\n 'dm serif text',\n 'noto serif',\n 'pt serif',\n 'bitter',\n 'domine',\n 'cormorant',\n 'cormorant garamond',\n]);\n\nexport function getGenericFamily(family: string): string {\n const lc = family.toLowerCase();\n if (lc.includes('mono') || lc.includes('code')) return 'monospace';\n if ((lc.includes('serif') && !lc.includes('sans')) || SERIF_FAMILIES.has(lc)) {\n return 'serif';\n }\n return 'sans-serif';\n}\n\n/**\n * Generate the full CSS for a size-adjusted fallback font.\n *\n * This produces a complete @font-face block with override descriptors\n * that FontFaceDescriptor doesn't natively support.\n */\nexport function generateFallbackCss(family: string): string | null {\n const metrics = FALLBACK_METRICS[family.toLowerCase()];\n if (!metrics) return null;\n\n const fallbackFamily = `${family} Fallback`;\n\n const lines = [\n '@font-face {',\n ` font-family: '${fallbackFamily}';`,\n ` src: local('${metrics.fallbackFont}');`,\n ` size-adjust: ${metrics.sizeAdjust}%;`,\n ` ascent-override: ${metrics.ascentOverride}%;`,\n ` descent-override: ${metrics.descentOverride}%;`,\n ` line-gap-override: ${metrics.lineGapOverride}%;`,\n '}',\n ];\n\n return lines.join('\\n');\n}\n\n/**\n * Check whether fallback metrics are available for a font family.\n */\nexport function hasFallbackMetrics(family: string): boolean {\n return family.toLowerCase() in FALLBACK_METRICS;\n}\n\n/**\n * Build the full font stack string for a font, including its\n * size-adjusted fallback and a generic family.\n *\n * Example: `'Inter', 'Inter Fallback', system-ui, sans-serif`\n */\nexport function buildFontStack(family: string): string {\n const generic = getGenericFamily(family);\n const hasMetrics = hasFallbackMetrics(family);\n\n const parts = [`'${family}'`];\n if (hasMetrics) parts.push(`'${family} Fallback'`);\n\n // Add system-ui for sans-serif fonts, ui-monospace for mono\n if (generic === 'monospace') {\n parts.push('ui-monospace');\n } else if (generic === 'sans-serif') {\n parts.push('system-ui');\n }\n parts.push(generic);\n\n return parts.join(', ');\n}\n","/**\n * Generic AST node types and recursive walkers for font static analysis.\n *\n * `ast.ts` owns parsing, config extraction, and call-site discovery; this\n * module owns the recursive walks that police where font bindings may be\n * used (dynamic configs, nested scopes, unconsumed references). Split out\n * to keep `ast.ts` under the 500-code-line limit (design/18-build-system.md).\n *\n * Design doc: 24-fonts.md §\"Step 1: Static Analysis\"\n */\n\n// ── AST node types (minimal subset of estree) ────────────────────────────────\n\nexport interface AstNode {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface IdentifierNode extends AstNode {\n type: 'Identifier';\n name: string;\n}\n\nexport interface PositionedNode extends AstNode {\n start: number;\n end: number;\n}\n\n/** A flagged reference/usage for build-error reporting. */\nexport interface FlaggedUsage {\n name: string;\n line: number;\n column: number;\n}\n\n// ── Offset → line/column helper ──────────────────────────────────────────────\n\n/** Convert a 0-based byte offset into a 1-based line and 0-based column. */\nexport function offsetToLineColumn(\n source: string,\n offset: number\n): { line: number; column: number } {\n let line = 1;\n let lastNewline = -1;\n for (let i = 0; i < offset; i++) {\n if (source[i] === '\\n') {\n line++;\n lastNewline = i;\n }\n }\n return { line, column: offset - lastNewline - 1 };\n}\n\n// ── Shared recursion plumbing ────────────────────────────────────────────────\n\n/**\n * Invoke `visit` on every direct child AST node of `node` (array elements\n * and object-valued properties with a `type` field).\n */\nexport function walkChildNodes(node: AstNode, visit: (child: AstNode) => void): void {\n for (const key of Object.keys(node)) {\n if (key === 'type') continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && (item as AstNode).type) {\n visit(item as AstNode);\n }\n }\n } else if (child && typeof child === 'object' && (child as AstNode).type) {\n visit(child as AstNode);\n }\n }\n}\n\n// ── Walkers ──────────────────────────────────────────────────────────────────\n\n/**\n * Recursively walk the AST looking for CallExpression nodes where\n * the callee is one of the imported font names and the first argument\n * is not an ObjectExpression (i.e. it's dynamic).\n */\nexport function walkForDynamicCalls(\n node: AstNode,\n names: ReadonlySet<string>,\n source: string\n): string | null {\n if (!node || typeof node !== 'object') return null;\n\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode;\n if (callee.type === 'Identifier' && names.has((callee as IdentifierNode).name)) {\n const args = node.arguments as AstNode[];\n if (args.length > 0 && args[0].type !== 'ObjectExpression') {\n // Extract the argument source text\n const argStart = (args[0] as PositionedNode).start;\n const argEnd = (args[0] as PositionedNode).end;\n const argText = source.slice(argStart, argEnd);\n const calleeName = (callee as IdentifierNode).name;\n return `${calleeName}(${argText})`;\n }\n }\n }\n\n let result: string | null = null;\n walkChildNodes(node, (child) => {\n if (!result) result = walkForDynamicCalls(child, names, source);\n });\n return result;\n}\n\n/**\n * Node types that introduce a nested scope — any font call inside is an\n * error (font calls must be module-level, same constraint as Next.js).\n * Module scope so it isn't rebuilt on every recursive walk call.\n */\nconst NESTED_SCOPE_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n 'IfStatement',\n 'ForStatement',\n 'ForInStatement',\n 'ForOfStatement',\n 'WhileStatement',\n 'DoWhileStatement',\n 'SwitchStatement',\n 'TryStatement',\n 'BlockStatement',\n 'ClassDeclaration',\n 'ClassExpression',\n]);\n\n/**\n * Recursively walk an AST node looking for font CallExpressions in nested\n * scopes (function bodies, if-blocks, loops, etc.). Font calls must be\n * module-level; nested calls are collected as errors.\n *\n * `isNested` tracks whether we've descended past the top-level statement.\n * Top-level VariableDeclarations and ExpressionStatements are already\n * handled by the main loop in `findFontCallSites`, so we only flag calls\n * found deeper.\n */\nexport function walkForNestedFontCalls(\n node: AstNode,\n bindingNames: ReadonlyMap<string, unknown>,\n source: string,\n out: FlaggedUsage[],\n isNested: boolean\n): void {\n if (!node || typeof node !== 'object') return;\n\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode;\n if (\n isNested &&\n callee.type === 'Identifier' &&\n bindingNames.has((callee as IdentifierNode).name)\n ) {\n const pos = offsetToLineColumn(source, (node as PositionedNode).start);\n out.push({ name: (callee as IdentifierNode).name, line: pos.line, column: pos.column });\n return; // Don't recurse into this call's children\n }\n }\n\n const enterNested = isNested || NESTED_SCOPE_TYPES.has(node.type);\n walkChildNodes(node, (child) =>\n walkForNestedFontCalls(child, bindingNames, source, out, enterNested)\n );\n}\n\n/**\n * Recursively walk an AST node looking for references to font bindings\n * that were not consumed by a recognized call site.\n *\n * Skips:\n * - recognized CallExpressions (the transform rewrites them wholesale)\n * - TS type-position nodes (erased at runtime)\n * - non-computed member properties (`obj.Inter` doesn't reference the binding)\n * - non-computed object keys (`{ Inter: 1 }` doesn't reference the binding)\n * - export aliases (`export { inter as Inter }` — only `local` is a reference)\n */\nexport function walkForUnconsumedReferences(\n node: AstNode,\n bindingNames: ReadonlyMap<string, unknown>,\n consumedCallStarts: ReadonlySet<number>,\n source: string,\n out: FlaggedUsage[]\n): void {\n if (!node || typeof node !== 'object') return;\n if (node.type === 'ImportDeclaration' || node.type.startsWith('TS')) return;\n\n if (node.type === 'Identifier') {\n const name = (node as IdentifierNode).name;\n if (bindingNames.has(name)) {\n const pos = offsetToLineColumn(source, (node as PositionedNode).start);\n out.push({ name, line: pos.line, column: pos.column });\n }\n return;\n }\n\n if (node.type === 'CallExpression' && consumedCallStarts.has((node as PositionedNode).start)) {\n return; // The whole call (callee + config object) is rewritten.\n }\n\n if (node.type === 'MemberExpression' && !(node as { computed?: boolean }).computed) {\n const object = (node as { object?: AstNode }).object;\n if (object) {\n walkForUnconsumedReferences(object, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n if (node.type === 'Property' && !(node as { computed?: boolean }).computed) {\n const value = (node as { value?: AstNode }).value;\n if (value) {\n walkForUnconsumedReferences(value, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n if (node.type === 'ExportSpecifier') {\n // Only `local` references a module binding. `exported` is just the\n // public name — `export { inter as Inter }` must not flag `Inter`.\n const local = (node as { local?: AstNode }).local;\n if (local) {\n walkForUnconsumedReferences(local, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n walkChildNodes(node, (child) =>\n walkForUnconsumedReferences(child, bindingNames, consumedCallStarts, source, out)\n );\n}\n","/**\n * AST utilities for extracting static font configs from source code.\n * Uses OXC via Vite's `parseAst` — handles JS/JSX/TS/TSX natively.\n *\n * Provides two tiers of API:\n *\n * 1. **Source-text helpers** (`extractFontConfigAst`, `extractLocalFontConfigAst`,\n * `detectDynamicFontCallAst`) — parse a snippet and return extracted config.\n * Still used by tests and callers that have only a string.\n *\n * 2. **AST-node helpers** (`extractGoogleFontConfigFromNode`,\n * `extractLocalFontConfigFromNode`, `findFontCallSites`) — operate on\n * nodes from an already-parsed Program so the transform hook can share\n * one parse with all analysis steps.\n *\n * Design doc: 24-fonts.md §\"Step 1: Static Analysis\"\n */\n\nimport { parseAst as viteParseAst } from 'vite';\nimport type { GoogleFontConfig } from './types.ts';\nimport type { LocalFontConfig, LocalFontSrc } from './types.ts';\nimport type { AstNode, IdentifierNode, PositionedNode, FlaggedUsage } from './ast-walk.ts';\nimport {\n offsetToLineColumn,\n walkForDynamicCalls,\n walkForNestedFontCalls,\n walkForUnconsumedReferences,\n} from './ast-walk.ts';\n\nexport type { FlaggedUsage } from './ast-walk.ts';\n\n// ── AST node types (font-config-specific, on top of ast-walk.ts's base) ──────\n\ninterface LiteralNode extends AstNode {\n type: 'Literal';\n value: string | number | boolean | null;\n}\n\ninterface ArrayExpressionNode extends AstNode {\n type: 'ArrayExpression';\n elements: AstNode[];\n}\n\ninterface ObjectExpressionNode extends AstNode {\n type: 'ObjectExpression';\n properties: PropertyNode[];\n}\n\ninterface PropertyNode extends AstNode {\n type: 'Property';\n key: AstNode & { name?: string; value?: string | number };\n value: AstNode;\n}\n\n// ── Core AST extraction helpers ──────────────────────────────────────────────\n\n/**\n * Parse a JavaScript expression string into an AST node.\n *\n * Wraps the expression in parens so OXC (via vite.parseAst) treats it as an expression statement.\n * Returns null if parsing fails.\n */\nfunction parseExpression(source: string): AstNode | null {\n try {\n const ast = viteParseAst(`(${source})`, { lang: 'tsx' }) as unknown as {\n body: Array<{ expression: AstNode }>;\n };\n return ast.body[0]?.expression ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract a static string value from an AST node.\n * Returns undefined if the node is not a string literal.\n */\nfunction extractString(node: AstNode): string | undefined {\n if (node.type === 'Literal' && typeof (node as LiteralNode).value === 'string') {\n return (node as LiteralNode).value as string;\n }\n return undefined;\n}\n\n/**\n * Extract a static boolean value from an AST node.\n * Returns undefined if the node is not a boolean literal.\n */\nfunction extractBoolean(node: AstNode): boolean | undefined {\n if (node.type === 'Literal' && typeof (node as LiteralNode).value === 'boolean') {\n return (node as LiteralNode).value as boolean;\n }\n return undefined;\n}\n\n/**\n * Extract a string array from an AST ArrayExpression node.\n * Returns undefined if any element is not a string literal.\n */\nfunction extractStringArray(node: AstNode): string[] | undefined {\n if (node.type !== 'ArrayExpression') return undefined;\n const arr = node as ArrayExpressionNode;\n const result: string[] = [];\n for (const elem of arr.elements) {\n const s = extractString(elem);\n if (s === undefined) return undefined;\n result.push(s);\n }\n return result;\n}\n\n/**\n * Get the key name from a Property node.\n */\nfunction getPropertyKey(prop: PropertyNode): string | undefined {\n if (prop.key.type === 'Identifier') {\n return (prop.key as IdentifierNode).name;\n }\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return prop.key.value;\n }\n return undefined;\n}\n\n/**\n * Build a map of property name → value node from an ObjectExpression.\n */\nfunction objectProperties(node: ObjectExpressionNode): Map<string, AstNode> {\n const map = new Map<string, AstNode>();\n for (const prop of node.properties) {\n // Skip spread elements or computed keys\n if (prop.type !== 'Property') continue;\n const key = getPropertyKey(prop);\n if (key) map.set(key, prop.value);\n }\n return map;\n}\n\n// ── Google font config extraction ────────────────────────────────────────────\n\n/**\n * Extract a GoogleFontConfig from the source text of a font function call's\n * object argument.\n *\n * The `callSource` should be the text of the call's argument list including\n * parens, e.g. `({ subsets: ['latin'], weight: '400' })`.\n *\n * Returns null if parsing or extraction fails.\n */\nexport function extractFontConfigAst(callSource: string): GoogleFontConfig | null {\n const node = parseExpression(callSource);\n if (!node || node.type !== 'ObjectExpression') return null;\n return extractGoogleConfig(node as ObjectExpressionNode);\n}\n\n// ── Local font config extraction ─────────────────────────────────────────────\n\n/**\n * Extract a single LocalFontSrc entry from an ObjectExpression AST node.\n */\nfunction extractLocalFontSrcEntry(node: AstNode): LocalFontSrc | null {\n if (node.type !== 'ObjectExpression') return null;\n const props = objectProperties(node as ObjectExpressionNode);\n\n const pathNode = props.get('path');\n if (!pathNode) return null;\n const path = extractString(pathNode);\n if (path === undefined) return null;\n\n const entry: LocalFontSrc = { path };\n\n const weightNode = props.get('weight');\n if (weightNode) {\n const w = extractString(weightNode);\n if (w !== undefined) entry.weight = w;\n }\n\n const styleNode = props.get('style');\n if (styleNode) {\n const s = extractString(styleNode);\n if (s !== undefined) entry.style = s;\n }\n\n return entry;\n}\n\n/**\n * Extract a LocalFontConfig from the source text of a localFont() call's\n * object argument.\n *\n * Returns null if parsing or extraction fails.\n */\nexport function extractLocalFontConfigAst(callSource: string): LocalFontConfig | null {\n const node = parseExpression(callSource);\n if (!node || node.type !== 'ObjectExpression') return null;\n return extractLocalConfig(node as ObjectExpressionNode);\n}\n\n// ── Dynamic call detection ───────────────────────────────────────────────────\n\n/**\n * Detect if source code contains dynamic/computed font function calls\n * that cannot be statically analyzed.\n *\n * Uses OXC (via vite.parseAst) to parse the full source and inspect CallExpression nodes.\n * Returns the offending expression string if found, null if all calls are static.\n */\nexport function detectDynamicFontCallAst(source: string, importedNames: string[]): string | null {\n if (importedNames.length === 0) return null;\n\n let ast;\n try {\n ast = viteParseAst(source, { lang: 'tsx' }) as unknown as { body: AstNode[] };\n } catch {\n // If we can't parse the source at all, fall back to no detection\n return null;\n }\n\n const nameSet = new Set(importedNames);\n return walkForDynamicCalls(ast as unknown as AstNode, nameSet, source);\n}\n\n// ── AST-node-level config extraction ─────────────────────────────────────────\n//\n// These work on an already-parsed ObjectExpression node so the transform\n// hook can share one OXC (via vite.parseAst) parse of the full source file with all analysis\n// steps (TIM-827).\n\n/**\n * Extract a GoogleFontConfig from an ObjectExpression AST node.\n *\n * This is the node-level equivalent of `extractFontConfigAst` — it skips\n * the parse step because the caller already has a parsed Program.\n */\nexport function extractGoogleFontConfigFromNode(node: AstNode): GoogleFontConfig | null {\n if (node.type !== 'ObjectExpression') return null;\n return extractGoogleConfig(node as ObjectExpressionNode);\n}\n\n/**\n * Extract a LocalFontConfig from an ObjectExpression AST node.\n */\nexport function extractLocalFontConfigFromNode(node: AstNode): LocalFontConfig | null {\n if (node.type !== 'ObjectExpression') return null;\n return extractLocalConfig(node as ObjectExpressionNode);\n}\n\n/** Shared implementation for GoogleFontConfig extraction from an object node. */\nfunction extractGoogleConfig(objNode: ObjectExpressionNode): GoogleFontConfig {\n const props = objectProperties(objNode);\n const config: GoogleFontConfig = {};\n\n const subsetsNode = props.get('subsets');\n if (subsetsNode) {\n const arr = extractStringArray(subsetsNode);\n if (arr) config.subsets = arr;\n }\n\n const weightNode = props.get('weight');\n if (weightNode) {\n const arr = extractStringArray(weightNode);\n if (arr) {\n config.weight = arr;\n } else {\n const s = extractString(weightNode);\n if (s !== undefined) config.weight = s;\n }\n }\n\n const displayNode = props.get('display');\n if (displayNode) {\n const s = extractString(displayNode);\n if (s !== undefined) config.display = s as GoogleFontConfig['display'];\n }\n\n const variableNode = props.get('variable');\n if (variableNode) {\n const s = extractString(variableNode);\n if (s !== undefined) config.variable = s;\n }\n\n const styleNode = props.get('style');\n if (styleNode) {\n const arr = extractStringArray(styleNode);\n if (arr) {\n config.style = arr;\n } else {\n const s = extractString(styleNode);\n if (s !== undefined) config.style = s;\n }\n }\n\n const preloadNode = props.get('preload');\n if (preloadNode) {\n const b = extractBoolean(preloadNode);\n if (b !== undefined) config.preload = b;\n }\n\n return config;\n}\n\n/** Shared implementation for LocalFontConfig extraction from an object node. */\nfunction extractLocalConfig(objNode: ObjectExpressionNode): LocalFontConfig | null {\n const props = objectProperties(objNode);\n\n const displayNode = props.get('display');\n const display = displayNode\n ? (extractString(displayNode) as LocalFontConfig['display'])\n : undefined;\n\n const variableNode = props.get('variable');\n const variable = variableNode ? extractString(variableNode) : undefined;\n\n const familyNode = props.get('family');\n const family = familyNode ? extractString(familyNode) : undefined;\n\n const srcNode = props.get('src');\n if (!srcNode) return null;\n\n const srcString = extractString(srcNode);\n if (srcString !== undefined) {\n return { src: srcString, display, variable, family };\n }\n\n if (srcNode.type === 'ArrayExpression') {\n const arr = srcNode as ArrayExpressionNode;\n const entries: LocalFontSrc[] = [];\n for (const elem of arr.elements) {\n const entry = extractLocalFontSrcEntry(elem);\n if (!entry) return null;\n entries.push(entry);\n }\n if (entries.length === 0) return null;\n return { src: entries, display, variable, family };\n }\n\n return null;\n}\n\n// ── Font module specifiers ───────────────────────────────────────────────────\n\nconst GOOGLE_FONT_SOURCES = new Set([\n '@timber/fonts/google',\n '@timber-js/app/fonts/google',\n 'next/font/google',\n]);\n\nconst LOCAL_FONT_SOURCES = new Set([\n '@timber/fonts/local',\n '@timber-js/app/fonts/local',\n 'next/font/local',\n]);\n\n// ── Parsed source types ──────────────────────────────────────────────────────\n\n/** A font import binding discovered from an ImportDeclaration. */\nexport interface FontBinding {\n /** The local name used in the module (after `as`, if present). */\n localName: string;\n /**\n * The original exported name (before `as`). For Google fonts this is\n * the PascalCase_With_Underscores name that maps to the family. For\n * local fonts (`default` import), this is `'default'`.\n */\n importedName: string;\n /** `'google'` or `'local'`. */\n provider: 'google' | 'local';\n /** The AST node of the ImportDeclaration (for removal via magic-string). */\n importNode: AstNode & { start: number; end: number };\n}\n\n/** A font function call site discovered from a CallExpression. */\nexport interface FontCallSite {\n /** The binding that this call references. */\n binding: FontBinding;\n /**\n * The variable name this call is assigned to, if the call appears in a\n * VariableDeclarator. `null` for bare expression statements.\n */\n assignedName: string | null;\n /** The first argument AST node (expected to be an ObjectExpression). */\n configNode: AstNode;\n /**\n * The outermost AST node to replace. For a VariableDeclaration with a\n * single declarator this is the full declaration; for a bare expression\n * statement it is the ExpressionStatement. The transform replaces\n * `source[replaceStart..replaceEnd]`.\n */\n replaceStart: number;\n replaceEnd: number;\n /** Line number (1-based) of the call for error messages. */\n line: number;\n /** Column (0-based) of the call for error messages. */\n column: number;\n}\n\n/** Result of `findFontCallSites` — everything the transform needs. */\nexport interface FontAnalysis {\n bindings: FontBinding[];\n callSites: FontCallSite[];\n /**\n * Import nodes that should be removed (deduplicated). Only imports that\n * produced at least one font binding are listed — removing an import\n * whose bindings the transform doesn't rewrite (e.g. a namespace\n * import) would leave dangling references behind.\n */\n importNodesToRemove: Array<{ start: number; end: number }>;\n /** First dynamic call expression text, or `null`. */\n dynamicCall: string | null;\n /**\n * Font calls found in nested scopes (functions, if-blocks, etc.).\n * These are errors — font calls must be module-level.\n */\n nestedCalls: FlaggedUsage[];\n /**\n * Namespace imports of font modules (`import * as fonts from ...`).\n * These are errors — the transform cannot rewrite `fonts.Inter(...)`\n * member calls, so the fonts would silently never load.\n */\n namespaceImports: FlaggedUsage[];\n /**\n * References to font bindings that were not consumed by a recognized\n * call site (`export default Inter({...})`, object-literal nesting,\n * member access on the call result, aliasing, re-exports). These are\n * errors — the import is removed, so any leftover reference would be a\n * silent runtime ReferenceError.\n */\n unsupportedUsages: FlaggedUsage[];\n}\n\ninterface ImportDeclarationNode extends PositionedNode {\n type: 'ImportDeclaration';\n source: LiteralNode & { value: string };\n specifiers: Array<\n PositionedNode & {\n type: string;\n local: IdentifierNode;\n imported?: IdentifierNode;\n }\n >;\n}\n\ninterface CallExpressionNode extends PositionedNode {\n type: 'CallExpression';\n callee: AstNode;\n arguments: PositionedNode[];\n}\n\ninterface VariableDeclaratorNode extends PositionedNode {\n type: 'VariableDeclarator';\n id: PositionedNode;\n init: PositionedNode | null;\n}\n\ninterface VariableDeclarationNode extends PositionedNode {\n type: 'VariableDeclaration';\n declarations: VariableDeclaratorNode[];\n}\n\ninterface ExpressionStatementNode extends PositionedNode {\n type: 'ExpressionStatement';\n expression: PositionedNode;\n}\n\ninterface ExportNamedDeclarationNode extends PositionedNode {\n type: 'ExportNamedDeclaration';\n declaration: VariableDeclarationNode | ExpressionStatementNode | null;\n}\n\n// ── Type guards for AST narrowing ────────────────────────────────────────────\n//\n// OXC's parsed nodes all share the base `PositionedNode` shape with\n// `type: string`. TypeScript can't narrow a union that includes a\n// `string`-typed catch-all, so we use explicit type guards instead of\n// bare `.type ===` checks.\n\nfunction isImportDeclaration(node: PositionedNode): node is ImportDeclarationNode {\n return node.type === 'ImportDeclaration';\n}\n\nfunction isVariableDeclaration(node: PositionedNode): node is VariableDeclarationNode {\n return node.type === 'VariableDeclaration';\n}\n\nfunction isExpressionStatement(node: PositionedNode): node is ExpressionStatementNode {\n return node.type === 'ExpressionStatement';\n}\n\nfunction isExportNamedDeclaration(node: PositionedNode): node is ExportNamedDeclarationNode {\n return node.type === 'ExportNamedDeclaration';\n}\n\nfunction isCallExpression(node: PositionedNode): node is CallExpressionNode {\n return node.type === 'CallExpression';\n}\n\nfunction isIdentifier(node: AstNode): node is IdentifierNode {\n return node.type === 'Identifier';\n}\n\ninterface ProgramNode extends PositionedNode {\n type: 'Program';\n body: PositionedNode[];\n}\n\n/**\n * Parse a full source file and find all font imports and call sites.\n *\n * Returns `null` if the source has no font-related imports.\n */\nexport function findFontCallSites(source: string): FontAnalysis | null {\n let program: ProgramNode;\n try {\n program = viteParseAst(source, { lang: 'tsx' }) as unknown as ProgramNode;\n } catch {\n return null;\n }\n\n // Step 1: Find all font import declarations and build the bindings list.\n const bindings: FontBinding[] = [];\n const importNodesToRemove: Array<{ start: number; end: number }> = [];\n const namespaceImports: FlaggedUsage[] = [];\n\n for (const stmt of program.body) {\n if (!isImportDeclaration(stmt)) continue;\n const importDecl = stmt;\n const specSource = importDecl.source.value;\n\n let provider: 'google' | 'local' | null = null;\n if (GOOGLE_FONT_SOURCES.has(specSource)) provider = 'google';\n else if (LOCAL_FONT_SOURCES.has(specSource)) provider = 'local';\n if (!provider) continue;\n\n let producedBinding = false;\n for (const spec of importDecl.specifiers) {\n if (spec.type === 'ImportSpecifier' && provider === 'google') {\n producedBinding = true;\n bindings.push({\n localName: spec.local.name,\n importedName: spec.imported?.name ?? spec.local.name,\n provider,\n importNode: importDecl,\n });\n } else if (spec.type === 'ImportDefaultSpecifier' && provider === 'local') {\n producedBinding = true;\n bindings.push({\n localName: spec.local.name,\n importedName: 'default',\n provider,\n importNode: importDecl,\n });\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // `import * as fonts from ...` cannot be rewritten — the transform\n // only matches direct identifier calls, so `fonts.Inter(...)` would\n // silently fall through to the runtime fallback module and never\n // load a real font. Collected as a build error.\n const pos = offsetToLineColumn(source, spec.start);\n namespaceImports.push({ name: spec.local.name, line: pos.line, column: pos.column });\n }\n }\n\n // Only remove imports whose bindings the transform actually rewrites.\n // Removing an import that produced no binding (namespace imports,\n // default imports of the google module) would orphan its references.\n if (producedBinding) {\n importNodesToRemove.push({ start: stmt.start, end: stmt.end });\n }\n }\n\n if (bindings.length === 0 && namespaceImports.length === 0) return null;\n\n // Step 2: Walk the AST for CallExpression nodes whose callee is a font binding.\n const bindingsByName = new Map(bindings.map((b) => [b.localName, b]));\n const callSites: FontCallSite[] = [];\n // Start offsets of recognized (and dynamic-flagged) CallExpressions, so\n // the unsupported-reference walk in step 4 can skip them.\n const consumedCallStarts = new Set<number>();\n let dynamicCall: string | null = null;\n\n for (const stmt of program.body) {\n // Unwrap `export const roboto = Roboto(...)` — the AST wraps the\n // VariableDeclaration inside an ExportNamedDeclaration node.\n const effectiveStmt =\n isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;\n\n // VariableDeclaration: `const inter = Inter({ ... })`\n if (isVariableDeclaration(effectiveStmt)) {\n for (const declarator of effectiveStmt.declarations) {\n if (!declarator.init) continue;\n if (!isCallExpression(declarator.init)) continue;\n const call = declarator.init;\n const site = matchCallExpression(call, bindingsByName, source);\n if (!site) continue;\n\n if (site === 'dynamic') {\n consumedCallStarts.add(call.start);\n if (!dynamicCall && isIdentifier(call.callee)) {\n const argStart = call.arguments[0].start;\n const argEnd = call.arguments[0].end;\n dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;\n }\n continue;\n }\n\n const assignedName = isIdentifier(declarator.id) ? declarator.id.name : null;\n\n const { line, column } = offsetToLineColumn(source, call.start);\n consumedCallStarts.add(call.start);\n callSites.push({\n binding: site.binding,\n assignedName,\n configNode: site.configNode,\n replaceStart: call.start,\n replaceEnd: call.end,\n line,\n column,\n });\n }\n }\n\n // ExpressionStatement: `Inter({ ... })` as a bare call\n if (isExpressionStatement(effectiveStmt)) {\n if (isCallExpression(effectiveStmt.expression)) {\n const call = effectiveStmt.expression;\n const site = matchCallExpression(call, bindingsByName, source);\n if (site && site !== 'dynamic') {\n const { line, column } = offsetToLineColumn(source, call.start);\n consumedCallStarts.add(call.start);\n callSites.push({\n binding: site.binding,\n assignedName: null,\n configNode: site.configNode,\n replaceStart: effectiveStmt.start,\n replaceEnd: effectiveStmt.end,\n line,\n column,\n });\n } else if (site === 'dynamic') {\n consumedCallStarts.add(call.start);\n if (!dynamicCall && isIdentifier(call.callee)) {\n const argStart = call.arguments[0].start;\n const argEnd = call.arguments[0].end;\n dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;\n }\n }\n }\n }\n }\n\n // Step 3: Walk nested scopes to find font calls that aren't module-level.\n // Font calls must be at module scope (same constraint as Next.js).\n // If the import is removed but a nested call remains, it's a ReferenceError.\n const nestedCalls: FlaggedUsage[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration') continue;\n walkForNestedFontCalls(stmt as AstNode, bindingsByName, source, nestedCalls, false);\n }\n\n // Step 4: Walk for references to font bindings that were not consumed by\n // a recognized call site. The transform removes the import declarations,\n // so any leftover reference (`export default Inter({...})`, object-literal\n // nesting, `Inter({...}).className`, `const f = Inter`, `export { Inter }`)\n // would become a silent runtime ReferenceError. Collected as build errors.\n const unsupportedUsages: FlaggedUsage[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration') continue;\n walkForUnconsumedReferences(\n stmt as AstNode,\n bindingsByName,\n consumedCallStarts,\n source,\n unsupportedUsages\n );\n }\n\n return {\n bindings,\n callSites,\n importNodesToRemove,\n dynamicCall,\n nestedCalls,\n namespaceImports,\n unsupportedUsages,\n };\n}\n\n/**\n * Match a CallExpression against the font bindings map.\n *\n * Returns the binding + config node if the call is a static font call,\n * `'dynamic'` if it's a font call with a non-object argument, or `null`\n * if the callee doesn't match any font binding.\n */\nfunction matchCallExpression(\n call: CallExpressionNode,\n bindings: Map<string, FontBinding>,\n _source: string\n): { binding: FontBinding; configNode: AstNode } | 'dynamic' | null {\n if (!isIdentifier(call.callee)) return null;\n const calleeName = call.callee.name;\n const binding = bindings.get(calleeName);\n if (!binding) return null;\n\n const args = call.arguments;\n if (args.length === 0 || args[0].type !== 'ObjectExpression') {\n return 'dynamic';\n }\n\n return { binding, configNode: args[0] };\n}\n","/**\n * Local font processing for the timber-fonts pipeline.\n *\n * Handles:\n * - Resolving font file paths relative to the importing module\n * - Normalizing single-string `src` to array form\n * - Generating @font-face descriptors for each weight/style variant\n *\n * Does NOT handle:\n * - Font format conversion (serve whatever the user provides)\n * - Font subsetting (user's responsibility for local fonts)\n *\n * Design doc: 24-fonts.md §\"Local Fonts\"\n */\n\nimport { resolve, dirname, extname } from 'node:path';\nimport type { LocalFontConfig, LocalFontSrc, FontFaceDescriptor, ExtractedFont } from './types.ts';\nimport { buildFontStack } from './fallbacks.ts';\nimport { extractLocalFontConfigAst } from './ast.ts';\nimport { fontOutputBasename, fontUrlPrefix } from './paths.ts';\n\n/**\n * Infer the font format from a file extension.\n *\n * Returns the CSS `format()` value for `@font-face` src descriptors.\n */\nexport function inferFontFormat(filePath: string): string {\n const ext = extname(filePath).toLowerCase();\n switch (ext) {\n case '.woff2':\n return 'woff2';\n case '.woff':\n return 'woff';\n case '.ttf':\n return 'truetype';\n case '.otf':\n return 'opentype';\n case '.eot':\n return 'embedded-opentype';\n default:\n return 'woff2';\n }\n}\n\n/**\n * Normalize `src` config to an array of LocalFontSrc entries.\n *\n * When `src` is a single string, it becomes a single entry with\n * default weight '400' and style 'normal'.\n */\nexport function normalizeSrc(src: string | LocalFontSrc[]): LocalFontSrc[] {\n if (typeof src === 'string') {\n return [{ path: src, weight: '400', style: 'normal' }];\n }\n return src.map((entry) => ({\n path: entry.path,\n weight: entry.weight ?? '400',\n style: entry.style ?? 'normal',\n }));\n}\n\n/**\n * Resolve font file paths relative to the importing module's directory.\n *\n * Takes the importer's file path and the normalized src entries,\n * returns new entries with absolute resolved paths.\n */\nexport function resolveLocalFontPaths(\n importerPath: string,\n sources: LocalFontSrc[]\n): LocalFontSrc[] {\n const importerDir = dirname(importerPath);\n return sources.map((entry) => ({\n ...entry,\n path: resolve(importerDir, entry.path),\n }));\n}\n\n/**\n * Generate a deterministic font family name from the file path\n * when no explicit `family` is provided.\n *\n * Uses the filename without extension, e.g. \"MyFont-Regular.woff2\" → \"MyFont-Regular\".\n * For multi-weight sources, uses the first file's name stem.\n */\nexport function generateFamilyName(sources: LocalFontSrc[]): string {\n if (sources.length === 0) return 'Local Font';\n const firstPath = sources[0].path;\n const basename = fontOutputBasename(firstPath);\n // Remove extension and weight/style suffixes for a cleaner family name\n const stem = basename.replace(/\\.[^.]+$/, '');\n // Strip common weight/style suffixes to get the family root\n const family = stem.replace(\n /[-_]?(Regular|Bold|Italic|Light|Medium|SemiBold|ExtraBold|Thin|Black|Heavy)$/i,\n ''\n );\n return family || stem;\n}\n\n/**\n * Generate @font-face descriptors for local font sources.\n *\n * Each source entry produces one @font-face rule. The `src` descriptor\n * uses a `url()` pointing to the served path under `<base>_timber/fonts/`.\n * The `urlPrefix` defaults to `fontUrlPrefix()` (root base) — pass\n * `fontUrlPrefix(viteBase)` so non-root deployments resolve correctly.\n */\nexport function generateLocalFontFaces(\n family: string,\n sources: LocalFontSrc[],\n display: string,\n urlPrefix = fontUrlPrefix()\n): FontFaceDescriptor[] {\n return sources.map((entry) => {\n const format = inferFontFormat(entry.path);\n const filename = entry.hashedBasename ?? fontOutputBasename(entry.path);\n return {\n family,\n src: `url('${urlPrefix}/${filename}') format('${format}')`,\n weight: entry.weight,\n style: entry.style,\n display,\n };\n });\n}\n\n/**\n * Build the className for a local font, following the same convention\n * as Google fonts: `timber-font-<lowercase-hyphenated-family>`.\n */\nexport function localFontClassName(family: string): string {\n return `timber-font-${family.toLowerCase().replace(/\\s+/g, '-')}`;\n}\n\n/**\n * Process a local font config into an ExtractedFont.\n *\n * This is the main entry point called by the fonts plugin's transform hook\n * when it encounters a `localFont()` call.\n */\nexport function processLocalFont(config: LocalFontConfig, importerPath: string): ExtractedFont {\n const sources = normalizeSrc(config.src);\n const resolvedSources = resolveLocalFontPaths(importerPath, sources);\n const family = config.family ?? generateFamilyName(sources);\n const display = config.display ?? 'swap';\n const className = localFontClassName(family);\n const fontStack = buildFontStack(family);\n\n const weights = [...new Set(resolvedSources.map((s) => s.weight ?? '400'))];\n const styles = [...new Set(resolvedSources.map((s) => s.style ?? 'normal'))];\n\n return {\n id: `local-${family.toLowerCase().replace(/\\s+/g, '-')}-${weights.join(',')}-${styles.join(',')}`,\n family,\n provider: 'local',\n weights,\n styles,\n subsets: [],\n display,\n variable: config.variable,\n localSources: resolvedSources,\n importer: importerPath,\n className,\n fontFamily: fontStack,\n };\n}\n\n/**\n * Extract a LocalFontConfig from a static `localFont()` call source.\n *\n * Parses patterns like:\n * localFont({ src: './fonts/MyFont.woff2', display: 'swap', variable: '--font-custom' })\n * localFont({ src: [{ path: './a.woff2', weight: '400' }, { path: './b.woff2', weight: '700' }] })\n *\n * Returns null if the call cannot be statically analyzed.\n *\n * Uses OXC (via vite.parseAst) AST parsing for robust handling of comments, trailing commas,\n * and multi-line configs.\n */\nexport function extractLocalFontConfig(callSource: string): LocalFontConfig | null {\n return extractLocalFontConfigAst(callSource);\n}\n","/**\n * Virtual module source generators for the timber-fonts plugin.\n *\n * The plugin exposes three virtual modules:\n *\n * - `@timber/fonts/google` — exports Google font loader functions. The\n * transform hook replaces actual call sites with static `FontResult`\n * objects, so this module is only loaded as a fallback (e.g. when the\n * transform hook hasn't run yet, or when an unknown font is referenced\n * via the default export proxy).\n * - `@timber/fonts/local` — exports `localFont()` as a fallback default.\n * - `virtual:timber-font-css/<hash>.css` — per-importer CSS module that\n * holds the combined `@font-face` + fallback + class CSS for every\n * font registered under that importer. The transform hook injects a\n * side-effect `import 'virtual:timber-font-css/<hash>.css'` into each\n * file that calls a font function, so Vite's CSS pipeline picks it up\n * like any other CSS asset. @vitejs/plugin-rsc's `collectCss` walks\n * the RSC module graph, finds the virtual module, and injects a\n * `<link rel=\"stylesheet\" data-rsc-css-href=...>` via React Float —\n * the same machinery component CSS rides on (TIM-828).\n *\n * The `.css` suffix is load-bearing: Vite's `isCSSRequest` regex matches\n * on file extension, so keeping it in the virtual id is how we tell\n * Vite's CSS pipeline (dev HMR + build asset emission) that this\n * module is CSS. The old `virtual:timber-font-css-register` side-effect\n * module, `globalThis.__timber_font_css` channel, and inline `<style>`\n * tag in the RSC entry were all removed in TIM-828.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { createHash } from 'node:crypto';\nimport type { ExtractedFont } from './types.ts';\n\nexport const VIRTUAL_GOOGLE = '@timber/fonts/google';\nexport const VIRTUAL_LOCAL = '@timber/fonts/local';\nexport const RESOLVED_GOOGLE = '\\0@timber/fonts/google';\nexport const RESOLVED_LOCAL = '\\0@timber/fonts/local';\n\n/**\n * Prefix used for the per-importer virtual CSS modules. The full id is\n * `virtual:timber-font-css/<hash>.css` where `<hash>` is a short SHA-256\n * digest of the importer path. We encode the hash (not the path itself)\n * so the id stays filesystem-safe and opaque to downstream consumers.\n */\nexport const VIRTUAL_FONT_CSS_PREFIX = 'virtual:timber-font-css/';\nexport const VIRTUAL_FONT_CSS_SUFFIX = '.css';\nexport const RESOLVED_FONT_CSS_PREFIX = '\\0' + VIRTUAL_FONT_CSS_PREFIX;\n\n/**\n * In-memory map from the short hash used in virtual module ids back to\n * the absolute importer path. Populated by `virtualFontCssIdFor()` when\n * the transform hook registers an importer and read by the plugin's\n * `load` hook when Vite asks for the CSS content.\n *\n * Scoped to a single `FontPipeline` instance to avoid cross-plugin-\n * instance collisions during multi-build pipelines.\n */\nfunction stripIdDecorations(id: string): string {\n const bare = id.startsWith('\\0') ? id.slice(1) : id;\n const qIdx = bare.indexOf('?');\n return qIdx === -1 ? bare : bare.slice(0, qIdx);\n}\n\nexport class VirtualFontCssIdMap {\n private readonly map = new Map<string, string>();\n\n /**\n * Return a stable virtual module id for `importer`. Calling this twice\n * with the same importer returns the same id. Registering under an\n * existing hash is idempotent.\n */\n idFor(importer: string): string {\n const hash = createHash('sha256').update(importer).digest('hex').slice(0, 16);\n this.map.set(hash, importer);\n return `${VIRTUAL_FONT_CSS_PREFIX}${hash}${VIRTUAL_FONT_CSS_SUFFIX}`;\n }\n\n /** Decode the importer from a resolved (or unresolved) virtual css id. */\n importerFor(id: string): string | undefined {\n const body = stripIdDecorations(id);\n if (!body.startsWith(VIRTUAL_FONT_CSS_PREFIX)) return undefined;\n if (!body.endsWith(VIRTUAL_FONT_CSS_SUFFIX)) return undefined;\n const hash = body.slice(\n VIRTUAL_FONT_CSS_PREFIX.length,\n body.length - VIRTUAL_FONT_CSS_SUFFIX.length\n );\n return this.map.get(hash);\n }\n\n /** True if `id` is any form of the virtual font css module. */\n matches(id: string): boolean {\n const body = stripIdDecorations(id);\n return body.startsWith(VIRTUAL_FONT_CSS_PREFIX) && body.endsWith(VIRTUAL_FONT_CSS_SUFFIX);\n }\n\n /** Drop every registered mapping. Used by tests. */\n clear(): void {\n this.map.clear();\n }\n}\n\n/**\n * Convert a font family name to a PascalCase export name.\n * e.g. \"JetBrains Mono\" → \"JetBrains_Mono\"\n */\nfunction familyToExportName(family: string): string {\n return family.replace(/\\s+/g, '_');\n}\n\n/**\n * Generate the virtual module source for `@timber/fonts/google`.\n *\n * The transform hook replaces real call sites at build time, so this\n * module only matters as a runtime fallback. We export a Proxy default\n * that handles any font name plus named exports for known families\n * (for tree-shaking).\n */\nexport function generateGoogleVirtualModule(fonts: Iterable<ExtractedFont>): string {\n const families = new Set<string>();\n for (const font of fonts) {\n if (font.provider === 'google') families.add(font.family);\n }\n\n const lines = [\n '// Auto-generated virtual module: @timber/fonts/google',\n '// Each export is a font loader function that returns a FontResult.',\n '',\n 'function createFontResult(family, config) {',\n ' return {',\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n ' className: `timber-font-${family.toLowerCase().replace(/\\\\s+/g, \"-\")}`,',\n ' style: { fontFamily: family },',\n ' variable: config?.variable,',\n ' };',\n '}',\n '',\n 'export default new Proxy({}, {',\n ' get(_, prop) {',\n ' if (typeof prop === \"string\") {',\n ' return (config) => createFontResult(prop.replace(/_/g, \" \"), config);',\n ' }',\n ' }',\n '});',\n ];\n\n for (const family of families) {\n const exportName = familyToExportName(family);\n lines.push('');\n lines.push(`export function ${exportName}(config) {`);\n lines.push(` return createFontResult('${family}', config);`);\n lines.push('}');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Generate the virtual module source for `@timber/fonts/local`.\n *\n * Like the google virtual module, this is a runtime fallback. The\n * transform hook normally replaces `localFont(...)` calls with static\n * `FontResult` objects at build time.\n */\nexport function generateLocalVirtualModule(): string {\n return [\n '// Auto-generated virtual module: @timber/fonts/local',\n '',\n 'export default function localFont(config) {',\n ' const family = config?.family || \"Local Font\";',\n ' return {',\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n ' className: `timber-font-${family.toLowerCase().replace(/\\\\s+/g, \"-\")}`,',\n ' style: { fontFamily: family },',\n ' variable: config?.variable,',\n ' };',\n '}',\n ].join('\\n');\n}\n","/**\n * FontPipeline — owns all per-font state for the timber-fonts plugin.\n *\n * Before TIM-829, font state was spread across three parallel mutable maps:\n *\n * - `registry: Map<string, ExtractedFont>`\n * - `googleFontFacesMap: Map<string, FontFaceDescriptor[]>`\n * - `cachedFonts: CachedFont[]`\n *\n * Every plugin hook had to remember which map(s) it owned and which it\n * read. The TIM-824 bug existed because `transform` could write to\n * `registry` multiple times for the same `(importer, family)` pair without\n * a corresponding cleanup of the entries that `buildStart` / `load` would\n * later use. The fix in TIM-824 added prune calls in `transform` for the\n * registry, but the parallel maps still had the same hazard latent in\n * them: any future code path that ran `buildStart`-equivalent logic on\n * HMR could re-introduce a stale-entry leak in a different map.\n *\n * TIM-829 collapses the three maps into a single `Map<string, FontEntry>`\n * keyed by font ID. Mutation goes through a small set of methods that\n * maintain the core invariant: **every piece of state belonging to a font\n * lives on its `FontEntry`, and `pruneFor` removes the entry along with\n * everything attached to it in one call.** No code path inside the plugin\n * touches the underlying map directly.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { ExtractedFont, FontEntry, FontFaceDescriptor } from './types.ts';\nimport type { CachedFont } from './google.ts';\nimport { contentHash } from './google.ts';\nimport { generateVariableClass, generateFontFamilyClass, generateFontFaces } from './css.ts';\nimport { generateFallbackCss } from './fallbacks.ts';\nimport { generateLocalFontFaces } from './local.ts';\nimport { hashedFontBasename, fontUrlPrefix } from './paths.ts';\nimport { VirtualFontCssIdMap } from './virtual-modules.ts';\n\nexport class FontPipeline {\n /**\n * The single per-font store. Keyed by `FontEntry.id` (which is itself\n * derived from `family + weights + styles + subsets + display`, so any\n * config change produces a new key).\n *\n * Marked `readonly` so the field reference can never be reassigned, but\n * the map contents are mutable through the methods below.\n */\n private readonly _entries = new Map<string, FontEntry>();\n\n /** When true, local font sources are content-hashed at registration time. */\n private readonly _hashOnRegister: boolean;\n\n /**\n * Vite's resolved `base`. Set from the plugin's `configResolved` hook so\n * every @font-face URL the pipeline renders carries the prefix.\n */\n private _base = '/';\n\n constructor(opts?: { hashOnRegister?: boolean }) {\n this._hashOnRegister = opts?.hashOnRegister ?? false;\n }\n\n /** Set Vite's resolved `base` (from `configResolved`). */\n setBase(base: string): void {\n this._base = base;\n }\n\n /**\n * Per-importer virtual CSS module id registry. Populated by the\n * transform hook when it inlines a font function call, read by the\n * plugin's `load` hook when Vite asks for the module's CSS source.\n *\n * Lives on the pipeline (rather than a module-level singleton) so\n * multiple parallel plugin instances — e.g. in the test suite — cannot\n * collide on the hash-to-importer map. Also makes `clear()` reset the\n * id map alongside the font entries so test fixtures start clean.\n */\n readonly cssIdMap = new VirtualFontCssIdMap();\n\n // ── Read-only accessors ─────────────────────────────────────────────────\n\n /** Number of registered fonts. */\n size(): number {\n return this._entries.size;\n }\n\n /** Iterate every entry as a `FontEntry` (with `faces` / `cachedFiles`). */\n entries(): IterableIterator<FontEntry> {\n return this._entries.values();\n }\n\n /** Iterate every entry typed as the narrower `ExtractedFont` shape. */\n fonts(): IterableIterator<ExtractedFont> {\n return this._entries.values();\n }\n\n /** Iterate every Google-provider entry. */\n *googleFonts(): IterableIterator<FontEntry> {\n for (const entry of this._entries.values()) {\n if (entry.provider === 'google') yield entry;\n }\n }\n\n /** Lookup an entry by font ID. */\n getEntry(id: string): FontEntry | undefined {\n return this._entries.get(id);\n }\n\n /**\n * True if `attachFaces()` has been called for `fontId` — even with an\n * empty array. This intentionally treats an empty resolution as\n * \"already processed\" so the dev `load()` path doesn't keep retrying\n * `resolveDevFontFaces()` on every request when Google returns no\n * matching faces for the requested subset(s). Mirrors the previous\n * `Map.has()` semantics this method replaced. (Codex review on PR #596.)\n *\n * Failures inside `resolveDevFontFaces` do not call `attachFaces` at\n * all, so they correctly stay retryable on the next request — see the\n * TIM-636 comment in `plugins/fonts.ts`.\n */\n hasFaces(fontId: string): boolean {\n const entry = this._entries.get(fontId);\n return entry?.faces !== undefined;\n }\n\n /**\n * True if `attachCachedFiles()` has been called for `fontId` — even\n * with an empty array. Same presence-vs-content rationale as\n * `hasFaces`: an empty resolution is a deterministic outcome, not a\n * \"not yet processed\" signal.\n */\n hasCachedFiles(fontId: string): boolean {\n const entry = this._entries.get(fontId);\n return entry?.cachedFiles !== undefined;\n }\n\n // ── Mutators ────────────────────────────────────────────────────────────\n\n /**\n * Register an extracted font under its content-derived ID.\n *\n * If an entry with the same ID already exists it is replaced wholesale,\n * dropping any previously-attached `faces` and `cachedFiles`. Callers\n * must call `pruneFor(importer, family)` first to ensure that any\n * previous registration from the same `(importer, family)` pair has been\n * dropped (TIM-824).\n */\n register(extracted: ExtractedFont): void {\n // Wholesale replace — never merge faces/cachedFiles from a previous\n // registration. Re-registration with the same ID always represents the\n // newest authoritative config and must start from a clean slate.\n const entry: FontEntry = { ...extracted };\n if (this._hashOnRegister && entry.provider === 'local' && entry.localSources) {\n for (const src of entry.localSources) {\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) continue;\n const data = readFileSync(absolutePath);\n src.hashedBasename = hashedFontBasename(src.path, contentHash(data));\n }\n }\n this._entries.set(entry.id, entry);\n }\n\n /** Attach pre-resolved `@font-face` descriptors to a font entry. */\n attachFaces(fontId: string, faces: FontFaceDescriptor[]): void {\n const entry = this._entries.get(fontId);\n if (!entry) {\n throw new Error(\n `[timber-fonts] attachFaces: no font entry registered for id \"${fontId}\". ` +\n `Call register() first.`\n );\n }\n entry.faces = faces;\n }\n\n /** Attach downloaded Google Font binaries to a font entry. */\n attachCachedFiles(fontId: string, files: CachedFont[]): void {\n const entry = this._entries.get(fontId);\n if (!entry) {\n throw new Error(\n `[timber-fonts] attachCachedFiles: no font entry registered for id \"${fontId}\". ` +\n `Call register() first.`\n );\n }\n entry.cachedFiles = files;\n }\n\n /**\n * Drop every registry entry that originated from `importer` and shares\n * `family` (case-insensitive), **along with all of its attached state**.\n *\n * This is the single chokepoint that guarantees stale `@font-face`\n * descriptors and orphaned cached binaries cannot leak across HMR edits.\n * Because every piece of per-font state lives on the `FontEntry`,\n * deleting the entry from the underlying map drops everything in one\n * operation — no parallel maps to keep in sync.\n *\n * See TIM-824 (the original prune fix) and TIM-829 (single-store\n * refactor that made this guarantee structural).\n */\n pruneFor(importer: string, family: string): void {\n const familyKey = family.toLowerCase();\n for (const [id, entry] of this._entries) {\n if (entry.importer === importer && entry.family.toLowerCase() === familyKey) {\n this._entries.delete(id);\n }\n }\n }\n\n /** True if at least one entry is registered under `importer`. */\n hasImporter(importer: string): boolean {\n for (const entry of this._entries.values()) {\n if (entry.importer === importer) return true;\n }\n return false;\n }\n\n /**\n * Drop **every** registry entry that originated from `importer`,\n * regardless of family.\n *\n * Called at the start of the transform hook before re-registering the\n * current extraction set. This handles the cases `pruneFor` misses:\n *\n * - **Family rename** (Inter → Roboto): the old family's entries are\n * cleared because we prune by importer, not by (importer, family).\n * - **Font call deleted**: the old entries are cleared even though no\n * new call provides a family to prune against.\n *\n * Other importers' fonts are untouched.\n *\n * See TIM-1087.\n */\n pruneImporter(importer: string): void {\n for (const [id, entry] of this._entries) {\n if (entry.importer === importer) {\n this._entries.delete(id);\n }\n }\n }\n\n /** Drop every registered font. Used by tests and rebuild flows. */\n clear(): void {\n this._entries.clear();\n this.cssIdMap.clear();\n }\n\n // ── Derived views ───────────────────────────────────────────────────────\n\n /**\n * Iterate every cached Google Font binary across all registered entries,\n * deduplicated by `hashedFilename`. Multiple entries that share the same\n * family hold references to the same `CachedFont` objects, so this\n * iterator yields each unique binary exactly once.\n */\n *uniqueCachedFiles(): IterableIterator<CachedFont> {\n const seen = new Set<string>();\n for (const entry of this._entries.values()) {\n if (!entry.cachedFiles) continue;\n for (const cf of entry.cachedFiles) {\n if (seen.has(cf.hashedFilename)) continue;\n seen.add(cf.hashedFilename);\n yield cf;\n }\n }\n }\n\n /**\n * Generate the combined CSS output for every registered font.\n *\n * Includes `@font-face` rules for local and Google fonts, fallback\n * `@font-face` rules, and scoped class rules. Google fonts use the\n * `faces` attached via `attachFaces()` (in `buildStart` for production\n * or lazily in `load` for dev).\n */\n getCss(): string {\n const urlPrefix = fontUrlPrefix(this._base);\n const cssParts: string[] = [];\n for (const entry of this._entries.values()) {\n cssParts.push(renderEntryCss(entry, urlPrefix));\n }\n return cssParts.join('\\n\\n');\n }\n\n /**\n * Render the combined CSS for every font registered from a specific\n * importer file. This is the anchor point for the per-importer virtual\n * CSS module (`virtual:timber-font-css/<hash>.css`) that the transform\n * hook injects as a side-effect import.\n *\n * Scoping by importer means two concurrent requests rendering different\n * routes cannot see each other's font CSS: each importer's virtual\n * module only contains CSS for fonts that module registered. It also\n * means Vite's CSS HMR can surgically reload just the affected importer\n * when a single file changes, rather than rebuilding one giant blob.\n *\n * Returns an empty string when no fonts are registered under `importer`.\n * The empty string is semantically equivalent to \"no CSS\" — Vite's CSS\n * pipeline handles it as a valid empty CSS module.\n */\n getCssForSegment(importer: string): string {\n const urlPrefix = fontUrlPrefix(this._base);\n const cssParts: string[] = [];\n for (const entry of this._entries.values()) {\n if (entry.importer !== importer) continue;\n cssParts.push(renderEntryCss(entry, urlPrefix));\n }\n return cssParts.join('\\n\\n');\n }\n}\n\n/**\n * Render the combined CSS for a single font entry.\n *\n * Reads `faces` straight off the entry. Private to this module — the only\n * public way to render a `FontEntry`'s CSS is through `FontPipeline.getCss()`.\n */\nfunction renderEntryCss(entry: FontEntry, urlPrefix: string): string {\n const cssParts: string[] = [];\n\n if (entry.provider === 'local' && entry.localSources) {\n const faces = generateLocalFontFaces(\n entry.family,\n entry.localSources,\n entry.display,\n urlPrefix\n );\n const faceCss = generateFontFaces(faces);\n if (faceCss) cssParts.push(faceCss);\n }\n\n if (entry.provider === 'google' && entry.faces && entry.faces.length > 0) {\n const faceCss = generateFontFaces(entry.faces);\n if (faceCss) cssParts.push(faceCss);\n }\n\n const fallbackCss = generateFallbackCss(entry.family);\n if (fallbackCss) cssParts.push(fallbackCss);\n\n if (entry.variable) {\n cssParts.push(generateVariableClass(entry.className, entry.variable, entry.fontFamily));\n } else {\n cssParts.push(generateFontFamilyClass(entry.className, entry.fontFamily));\n }\n\n return cssParts.join('\\n\\n');\n}\n","// src/vlq.ts\nvar comma = \",\".charCodeAt(0);\nvar semicolon = \";\".charCodeAt(0);\nvar chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nvar intToChar = new Uint8Array(64);\nvar charToInt = new Uint8Array(128);\nfor (let i = 0; i < chars.length; i++) {\n const c = chars.charCodeAt(i);\n intToChar[i] = c;\n charToInt[c] = i;\n}\nfunction decodeInteger(reader) {\n let value = 0;\n let shift = 0;\n let integer = 0;\n do {\n const c = reader.next();\n integer = charToInt[c];\n value |= (integer & 31) << shift;\n shift += 5;\n } while (integer & 32);\n return value;\n}\nfunction decodeSign(num) {\n return num & 1 ? -2147483648 | -(num >>> 1) : num >>> 1;\n}\nfunction encodeInteger(builder, num) {\n do {\n let clamped = num & 31;\n num >>>= 5;\n if (num > 0) clamped |= 32;\n builder.write(intToChar[clamped]);\n } while (num > 0);\n}\nfunction encodeSign(num) {\n return num < 0 ? -num << 1 | 1 : num << 1;\n}\nfunction hasMoreVlq(reader, max) {\n if (reader.pos >= max) return false;\n return reader.peek() !== comma;\n}\n\n// src/strings.ts\nvar bufLength = 1024 * 16;\nvar td = typeof TextDecoder !== \"undefined\" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== \"undefined\" ? {\n decode(buf) {\n const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);\n return out.toString();\n }\n} : {\n decode(buf) {\n let out = \"\";\n for (let i = 0; i < buf.length; i++) {\n out += String.fromCharCode(buf[i]);\n }\n return out;\n }\n};\nvar StringWriter = class {\n constructor() {\n this.pos = 0;\n this.out = \"\";\n this.buffer = new Uint8Array(bufLength);\n }\n write(v) {\n const { buffer } = this;\n buffer[this.pos++] = v;\n if (this.pos === bufLength) {\n this.out += td.decode(buffer);\n this.pos = 0;\n }\n }\n flush() {\n const { buffer, out, pos } = this;\n return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;\n }\n};\nvar StringReader = class {\n constructor(buffer) {\n this.pos = 0;\n this.buffer = buffer;\n }\n next() {\n return this.buffer.charCodeAt(this.pos++);\n }\n peek() {\n return this.buffer.charCodeAt(this.pos);\n }\n indexOf(char) {\n const { buffer, pos } = this;\n const idx = buffer.indexOf(char, pos);\n return idx === -1 ? buffer.length : idx;\n }\n};\n\n// src/scopes.ts\nvar EMPTY = [];\nfunction decodeOriginalScopes(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const scopes = [];\n const stack = [];\n let line = 0;\n for (; reader.pos < length; reader.pos++) {\n line += decodeSign(decodeInteger(reader));\n const column = decodeSign(decodeInteger(reader));\n if (!hasMoreVlq(reader, length)) {\n const last = stack.pop();\n last[2] = line;\n last[3] = column;\n continue;\n }\n const kind = decodeSign(decodeInteger(reader));\n const fields = decodeSign(decodeInteger(reader));\n const hasName = fields & 1;\n const scope = hasName ? [line, column, 0, 0, kind, decodeSign(decodeInteger(reader))] : [line, column, 0, 0, kind];\n let vars = EMPTY;\n if (hasMoreVlq(reader, length)) {\n vars = [];\n do {\n const varsIndex = decodeSign(decodeInteger(reader));\n vars.push(varsIndex);\n } while (hasMoreVlq(reader, length));\n }\n scope.vars = vars;\n scopes.push(scope);\n stack.push(scope);\n }\n return scopes;\n}\nfunction encodeOriginalScopes(scopes) {\n const writer = new StringWriter();\n for (let i = 0; i < scopes.length; ) {\n i = _encodeOriginalScopes(scopes, i, writer, [0]);\n }\n return writer.flush();\n}\nfunction _encodeOriginalScopes(scopes, index, writer, state) {\n const scope = scopes[index];\n const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;\n if (index > 0) writer.write(comma);\n encodeInteger(writer, encodeSign(startLine - state[0]));\n state[0] = startLine;\n encodeInteger(writer, encodeSign(startColumn));\n encodeInteger(writer, encodeSign(kind));\n const fields = scope.length === 6 ? 1 : 0;\n encodeInteger(writer, encodeSign(fields));\n if (scope.length === 6) encodeInteger(writer, encodeSign(scope[5]));\n for (const v of vars) {\n encodeInteger(writer, encodeSign(v));\n }\n for (index++; index < scopes.length; ) {\n const next = scopes[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeOriginalScopes(scopes, index, writer, state);\n }\n writer.write(comma);\n encodeInteger(writer, encodeSign(endLine - state[0]));\n state[0] = endLine;\n encodeInteger(writer, encodeSign(endColumn));\n return index;\n}\nfunction decodeGeneratedRanges(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const ranges = [];\n const stack = [];\n let genLine = 0;\n let definitionSourcesIndex = 0;\n let definitionScopeIndex = 0;\n let callsiteSourcesIndex = 0;\n let callsiteLine = 0;\n let callsiteColumn = 0;\n let bindingLine = 0;\n let bindingColumn = 0;\n do {\n const semi = reader.indexOf(\";\");\n let genColumn = 0;\n for (; reader.pos < semi; reader.pos++) {\n genColumn += decodeSign(decodeInteger(reader));\n if (!hasMoreVlq(reader, semi)) {\n const last = stack.pop();\n last[2] = genLine;\n last[3] = genColumn;\n continue;\n }\n const fields = decodeSign(decodeInteger(reader));\n const hasDefinition = fields & 1;\n const hasCallsite = fields & 2;\n const hasScope = fields & 4;\n let callsite = null;\n let bindings = EMPTY;\n let range;\n if (hasDefinition) {\n const defSourcesIndex = definitionSourcesIndex + decodeSign(decodeInteger(reader));\n definitionScopeIndex = decodeSign(decodeInteger(reader)) + (definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0);\n definitionSourcesIndex = defSourcesIndex;\n range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];\n } else {\n range = [genLine, genColumn, 0, 0];\n }\n range.isScope = !!hasScope;\n if (hasCallsite) {\n const prevCsi = callsiteSourcesIndex;\n const prevLine = callsiteLine;\n callsiteSourcesIndex += decodeSign(decodeInteger(reader));\n const sameSource = prevCsi === callsiteSourcesIndex;\n callsiteLine = (sameSource ? callsiteLine : 0) + decodeSign(decodeInteger(reader));\n callsiteColumn = (sameSource && prevLine === callsiteLine ? callsiteColumn : 0) + decodeSign(decodeInteger(reader));\n callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];\n }\n range.callsite = callsite;\n if (hasMoreVlq(reader, semi)) {\n bindings = [];\n do {\n bindingLine = genLine;\n bindingColumn = genColumn;\n const expressionsCount = decodeSign(decodeInteger(reader));\n let expressionRanges;\n if (expressionsCount < -1) {\n expressionRanges = [[decodeSign(decodeInteger(reader))]];\n for (let i = -1; i > expressionsCount; i--) {\n const prevBl = bindingLine;\n bindingLine += decodeSign(decodeInteger(reader));\n bindingColumn = (bindingLine === prevBl ? bindingColumn : 0) + decodeSign(decodeInteger(reader));\n const expression = decodeSign(decodeInteger(reader));\n expressionRanges.push([expression, bindingLine, bindingColumn]);\n }\n } else {\n expressionRanges = [[expressionsCount]];\n }\n bindings.push(expressionRanges);\n } while (hasMoreVlq(reader, semi));\n }\n range.bindings = bindings;\n ranges.push(range);\n stack.push(range);\n }\n genLine++;\n reader.pos = semi + 1;\n } while (reader.pos < length);\n return ranges;\n}\nfunction encodeGeneratedRanges(ranges) {\n if (ranges.length === 0) return \"\";\n const writer = new StringWriter();\n for (let i = 0; i < ranges.length; ) {\n i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);\n }\n return writer.flush();\n}\nfunction _encodeGeneratedRanges(ranges, index, writer, state) {\n const range = ranges[index];\n const {\n 0: startLine,\n 1: startColumn,\n 2: endLine,\n 3: endColumn,\n isScope,\n callsite,\n bindings\n } = range;\n if (state[0] < startLine) {\n catchupLine(writer, state[0], startLine);\n state[0] = startLine;\n state[1] = 0;\n } else if (index > 0) {\n writer.write(comma);\n }\n encodeInteger(writer, encodeSign(range[1] - state[1]));\n state[1] = range[1];\n const fields = (range.length === 6 ? 1 : 0) | (callsite ? 2 : 0) | (isScope ? 4 : 0);\n encodeInteger(writer, encodeSign(fields));\n if (range.length === 6) {\n const { 4: sourcesIndex, 5: scopesIndex } = range;\n if (sourcesIndex !== state[2]) {\n state[3] = 0;\n }\n encodeInteger(writer, encodeSign(sourcesIndex - state[2]));\n state[2] = sourcesIndex;\n encodeInteger(writer, encodeSign(scopesIndex - state[3]));\n state[3] = scopesIndex;\n }\n if (callsite) {\n const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;\n if (sourcesIndex !== state[4]) {\n state[5] = 0;\n state[6] = 0;\n } else if (callLine !== state[5]) {\n state[6] = 0;\n }\n encodeInteger(writer, encodeSign(sourcesIndex - state[4]));\n state[4] = sourcesIndex;\n encodeInteger(writer, encodeSign(callLine - state[5]));\n state[5] = callLine;\n encodeInteger(writer, encodeSign(callColumn - state[6]));\n state[6] = callColumn;\n }\n if (bindings) {\n for (const binding of bindings) {\n if (binding.length > 1) encodeInteger(writer, encodeSign(-binding.length));\n const expression = binding[0][0];\n encodeInteger(writer, encodeSign(expression));\n let bindingStartLine = startLine;\n let bindingStartColumn = startColumn;\n for (let i = 1; i < binding.length; i++) {\n const expRange = binding[i];\n encodeInteger(writer, encodeSign(expRange[1] - bindingStartLine));\n bindingStartLine = expRange[1];\n encodeInteger(writer, encodeSign(expRange[2] - bindingStartColumn));\n bindingStartColumn = expRange[2];\n encodeInteger(writer, encodeSign(expRange[0]));\n }\n }\n }\n for (index++; index < ranges.length; ) {\n const next = ranges[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeGeneratedRanges(ranges, index, writer, state);\n }\n if (state[0] < endLine) {\n catchupLine(writer, state[0], endLine);\n state[0] = endLine;\n state[1] = 0;\n } else {\n writer.write(comma);\n }\n encodeInteger(writer, encodeSign(endColumn - state[1]));\n state[1] = endColumn;\n return index;\n}\nfunction catchupLine(writer, lastLine, line) {\n do {\n writer.write(semicolon);\n } while (++lastLine < line);\n}\n\n// src/range-mappings.ts\nfunction decodeRangeMappings(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const rangeMappings = [];\n do {\n const semi = reader.indexOf(\";\");\n const indices = [];\n let index = 0;\n while (reader.pos < semi) {\n index += decodeInteger(reader);\n indices.push(index);\n }\n rangeMappings.push(indices);\n reader.pos = semi + 1;\n } while (reader.pos <= length);\n return rangeMappings;\n}\nfunction encodeRangeMappings(decoded) {\n if (decoded.length === 0) return \"\";\n const writer = new StringWriter();\n for (let i = 0; i < decoded.length; i++) {\n const indices = decoded[i];\n if (i > 0) writer.write(semicolon);\n let index = 0;\n for (let j = 0; j < indices.length; j++) {\n const offset = indices[j];\n encodeInteger(writer, offset - index);\n index = offset;\n }\n }\n return writer.flush();\n}\n\n// src/sourcemap-codec.ts\nfunction decode(mappings) {\n const { length } = mappings;\n const reader = new StringReader(mappings);\n const decoded = [];\n let genColumn = 0;\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n do {\n const semi = reader.indexOf(\";\");\n const line = [];\n let sorted = true;\n let lastCol = 0;\n genColumn = 0;\n while (reader.pos < semi) {\n let seg;\n genColumn += decodeSign(decodeInteger(reader));\n if (genColumn < lastCol) sorted = false;\n lastCol = genColumn;\n if (hasMoreVlq(reader, semi)) {\n sourcesIndex += decodeSign(decodeInteger(reader));\n sourceLine += decodeSign(decodeInteger(reader));\n sourceColumn += decodeSign(decodeInteger(reader));\n if (hasMoreVlq(reader, semi)) {\n namesIndex += decodeSign(decodeInteger(reader));\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];\n } else {\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];\n }\n } else {\n seg = [genColumn];\n }\n line.push(seg);\n reader.pos++;\n }\n if (!sorted) sort(line);\n decoded.push(line);\n reader.pos = semi + 1;\n } while (reader.pos <= length);\n return decoded;\n}\nfunction sort(line) {\n line.sort(sortComparator);\n}\nfunction sortComparator(a, b) {\n return a[0] - b[0];\n}\nfunction encode(decoded) {\n const writer = new StringWriter();\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n for (let i = 0; i < decoded.length; i++) {\n const line = decoded[i];\n if (i > 0) writer.write(semicolon);\n if (line.length === 0) continue;\n let genColumn = 0;\n for (let j = 0; j < line.length; j++) {\n const segment = line[j];\n if (j > 0) writer.write(comma);\n encodeInteger(writer, encodeSign(segment[0] - genColumn));\n genColumn = segment[0];\n if (segment.length === 1) continue;\n encodeInteger(writer, encodeSign(segment[1] - sourcesIndex));\n encodeInteger(writer, encodeSign(segment[2] - sourceLine));\n encodeInteger(writer, encodeSign(segment[3] - sourceColumn));\n sourcesIndex = segment[1];\n sourceLine = segment[2];\n sourceColumn = segment[3];\n if (segment.length === 4) continue;\n encodeInteger(writer, encodeSign(segment[4] - namesIndex));\n namesIndex = segment[4];\n }\n }\n return writer.flush();\n}\nexport {\n decode,\n decodeGeneratedRanges,\n decodeOriginalScopes,\n decodeRangeMappings,\n encode,\n encodeGeneratedRanges,\n encodeOriginalScopes,\n encodeRangeMappings\n};\n//# sourceMappingURL=sourcemap-codec.mjs.map\n","import { encode, encodeRangeMappings } from \"@jridgewell/sourcemap-codec\";\n//#region src/BitSet.ts\nvar BitSet = class BitSet {\n\tconstructor(arg) {\n\t\tthis.bits = arg instanceof BitSet ? arg.bits.slice() : [];\n\t}\n\tadd(n) {\n\t\tthis.bits[n >> 5] |= 1 << (n & 31);\n\t}\n\thas(n) {\n\t\treturn !!(this.bits[n >> 5] & 1 << (n & 31));\n\t}\n};\n//#endregion\n//#region src/Chunk.ts\nvar Chunk = class Chunk {\n\tconstructor(start, end, content) {\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.original = content;\n\t\tthis.intro = \"\";\n\t\tthis.outro = \"\";\n\t\tthis.content = content;\n\t\tthis.storeName = false;\n\t\tthis.edited = false;\n\t\tthis.previous = null;\n\t\tthis.next = null;\n\t}\n\tappendLeft(content) {\n\t\tthis.outro += content;\n\t}\n\tappendRight(content) {\n\t\tthis.intro = this.intro + content;\n\t}\n\tclone() {\n\t\tconst chunk = new Chunk(this.start, this.end, this.original);\n\t\tchunk.intro = this.intro;\n\t\tchunk.outro = this.outro;\n\t\tchunk.content = this.content;\n\t\tchunk.storeName = this.storeName;\n\t\tchunk.edited = this.edited;\n\t\treturn chunk;\n\t}\n\tcontains(index) {\n\t\treturn this.start < index && index < this.end;\n\t}\n\teachNext(fn) {\n\t\tfn(this);\n\t\tlet chunk = this.next;\n\t\twhile (chunk) {\n\t\t\tfn(chunk);\n\t\t\tchunk = chunk.next;\n\t\t}\n\t}\n\teachPrevious(fn) {\n\t\tfn(this);\n\t\tlet chunk = this.previous;\n\t\twhile (chunk) {\n\t\t\tfn(chunk);\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t}\n\tedit(content, storeName, contentOnly) {\n\t\tthis.content = content;\n\t\tif (!contentOnly) {\n\t\t\tthis.intro = \"\";\n\t\t\tthis.outro = \"\";\n\t\t}\n\t\tthis.storeName = storeName;\n\t\tthis.edited = true;\n\t\treturn this;\n\t}\n\tprependLeft(content) {\n\t\tthis.outro = content + this.outro;\n\t}\n\tprependRight(content) {\n\t\tthis.intro = content + this.intro;\n\t}\n\treset() {\n\t\tthis.intro = \"\";\n\t\tthis.outro = \"\";\n\t\tif (this.edited) {\n\t\t\tthis.content = this.original;\n\t\t\tthis.storeName = false;\n\t\t\tthis.edited = false;\n\t\t}\n\t}\n\tsplit(index) {\n\t\tconst sliceIndex = index - this.start;\n\t\tconst originalBefore = this.original.slice(0, sliceIndex);\n\t\tconst originalAfter = this.original.slice(sliceIndex);\n\t\tthis.original = originalBefore;\n\t\tconst newChunk = new Chunk(index, this.end, originalAfter);\n\t\tnewChunk.outro = this.outro;\n\t\tthis.outro = \"\";\n\t\tthis.end = index;\n\t\tif (this.edited) {\n\t\t\tnewChunk.edit(\"\", false);\n\t\t\tthis.content = \"\";\n\t\t} else this.content = originalBefore;\n\t\tnewChunk.next = this.next;\n\t\tif (newChunk.next) newChunk.next.previous = newChunk;\n\t\tnewChunk.previous = this;\n\t\tthis.next = newChunk;\n\t\treturn newChunk;\n\t}\n\ttoString() {\n\t\treturn this.intro + this.content + this.outro;\n\t}\n\ttrimEnd(rx) {\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\tif (this.outro.length) return true;\n\t\tconst trimmed = this.content.replace(rx, \"\");\n\t\tif (trimmed.length) {\n\t\t\tif (trimmed !== this.content) {\n\t\t\t\tif (this.edited) this.edit(trimmed, this.storeName, true);\n\t\t\t\telse this.split(this.start + trimmed.length).edit(\"\", void 0, true);\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tthis.edit(\"\", void 0, true);\n\t\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\t\tif (this.intro.length) return true;\n\t\t}\n\t}\n\ttrimStart(rx) {\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (this.intro.length) return true;\n\t\tconst trimmed = this.content.replace(rx, \"\");\n\t\tif (trimmed.length) {\n\t\t\tif (trimmed !== this.content) {\n\t\t\t\tif (this.edited) this.edit(trimmed, this.storeName, true);\n\t\t\t\telse {\n\t\t\t\t\tthis.split(this.end - trimmed.length);\n\t\t\t\t\tthis.edit(\"\", void 0, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tthis.edit(\"\", void 0, true);\n\t\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\t\tif (this.outro.length) return true;\n\t\t}\n\t}\n};\n//#endregion\n//#region src/MagicStringError.ts\n/**\n* The single error type thrown by MagicString.\n*\n* Every message is prefixed with `[MagicString]` so its source is obvious at a\n* glance, and is kept short and consistent in tone.\n*/\nvar MagicStringError = class extends Error {\n\tname = \"MagicStringError\";\n\tconstructor(message, options) {\n\t\tsuper(`[MagicString] ${message}`, options);\n\t}\n};\n//#endregion\n//#region src/SourceMap.ts\nfunction getBtoa() {\n\t/* v8 ignore next -- environment fallback, unreachable when `btoa` is present */\n\tif (typeof globalThis !== \"undefined\" && typeof globalThis.btoa === \"function\") return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));\n\tconst buffer = globalThis[\"Buffer\"];\n\tif (buffer) return (str) => buffer.from(str, \"utf-8\").toString(\"base64\");\n\treturn () => {\n\t\tthrow new MagicStringError(\"unsupported environment: `btoa` or `Buffer` is required\");\n\t};\n\t/* v8 ignore stop */\n}\nconst btoa = /* #__PURE__ */ getBtoa();\nvar SourceMap = class {\n\tconstructor(properties) {\n\t\tthis.version = 3;\n\t\tthis.file = properties.file;\n\t\tthis.sources = properties.sources;\n\t\tthis.sourcesContent = properties.sourcesContent;\n\t\tthis.names = properties.names;\n\t\tthis.mappings = typeof properties.mappings === \"string\" ? properties.mappings : encode(properties.mappings);\n\t\tif (typeof properties.x_google_ignoreList !== \"undefined\") this.x_google_ignoreList = properties.x_google_ignoreList;\n\t\tif (typeof properties.debugId !== \"undefined\") this.debugId = properties.debugId;\n\t\tif (typeof properties.rangeMappings !== \"undefined\") {\n\t\t\tlet shouldOutputRangeMapping = false;\n\t\t\tfor (const line of properties.rangeMappings) if (line.length !== 0) {\n\t\t\t\tshouldOutputRangeMapping = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (shouldOutputRangeMapping) this.rangeMappings = encodeRangeMappings(properties.rangeMappings);\n\t\t}\n\t}\n\t/**\n\t* Returns the equivalent of `JSON.stringify(map)`\n\t*/\n\ttoString() {\n\t\treturn JSON.stringify(this);\n\t}\n\t/**\n\t* Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:\n\t* `generateMap(options?: SourceMapOptions): SourceMap;`\n\t*/\n\ttoUrl() {\n\t\treturn `data:application/json;charset=utf-8;base64,${btoa(this.toString())}`;\n\t}\n};\n//#endregion\n//#region src/utils/getLocator.ts\nfunction getLocator(source) {\n\tconst lineOffsets = [0];\n\tfor (let i = source.indexOf(\"\\n\"); i !== -1; i = source.indexOf(\"\\n\", i + 1)) lineOffsets.push(i + 1);\n\treturn function locate(index) {\n\t\tlet i = 0;\n\t\tlet j = lineOffsets.length;\n\t\twhile (i < j) {\n\t\t\tconst m = i + j >> 1;\n\t\t\tif (index < lineOffsets[m]) j = m;\n\t\t\telse i = m + 1;\n\t\t}\n\t\tconst line = i - 1;\n\t\treturn {\n\t\t\tline,\n\t\t\tcolumn: index - lineOffsets[line]\n\t\t};\n\t};\n}\n//#endregion\n//#region src/utils/getRelativePath.ts\nfunction getRelativePath(from, to) {\n\tconst fromParts = from.split(/[/\\\\]/);\n\tconst toParts = to.split(/[/\\\\]/);\n\tfromParts.pop();\n\twhile (fromParts[0] === toParts[0]) {\n\t\tfromParts.shift();\n\t\ttoParts.shift();\n\t}\n\tif (fromParts.length) {\n\t\tlet i = fromParts.length;\n\t\twhile (i--) fromParts[i] = \"..\";\n\t}\n\treturn fromParts.concat(toParts).join(\"/\");\n}\n//#endregion\n//#region src/utils/guessIndent.ts\nfunction guessIndent(code) {\n\tconst lines = code.split(\"\\n\");\n\tconst tabbed = lines.filter((line) => /^\\t+/.test(line));\n\tconst spaced = lines.filter((line) => /^ {2,}/.test(line));\n\tif (tabbed.length === 0 && spaced.length === 0) return null;\n\tif (tabbed.length >= spaced.length) return \"\t\";\n\tconst min = spaced.reduce((previous, current) => {\n\t\tconst numSpaces = /^ +/.exec(current)[0].length;\n\t\treturn Math.min(numSpaces, previous);\n\t}, Infinity);\n\treturn \" \".repeat(min);\n}\n//#endregion\n//#region src/utils/isObject.ts\nconst toString = Object.prototype.toString;\nfunction isObject(thing) {\n\treturn toString.call(thing) === \"[object Object]\";\n}\nconst BASE64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nconst intToChar = /* #__PURE__ */ (() => {\n\tconst chars = /* @__PURE__ */ new Uint8Array(64);\n\tfor (let i = 0; i < 64; i++) chars[i] = BASE64_CHARS.charCodeAt(i);\n\treturn chars;\n})();\nconst COMMA = 44;\nconst SEMICOLON = 59;\nconst BUFFER_SIZE = 16384;\nconst FLUSH_THRESHOLD = 16348;\nconst scratch = /* #__PURE__ */ new Uint8Array(BUFFER_SIZE);\nfunction writeVlq(pos, num) {\n\tnum = num < 0 ? -num << 1 | 1 : num << 1;\n\tdo {\n\t\tlet clamped = num & 31;\n\t\tnum >>>= 5;\n\t\tif (num > 0) clamped |= 32;\n\t\tscratch[pos++] = intToChar[clamped];\n\t} while (num > 0);\n\treturn pos;\n}\nconst decoder = /* #__PURE__ */ new TextDecoder();\nvar MappingsEncoder = class {\n\tconstructor() {\n\t\tthis.out = \"\";\n\t\tthis.pos = 0;\n\t\tthis.lines = [];\n\t\tthis.buffered = 0;\n\t\tthis.needsComma = false;\n\t\tthis.prevGenColumn = 0;\n\t\tthis.prevSourceIndex = 0;\n\t\tthis.prevSourceLine = 0;\n\t\tthis.prevSourceColumn = 0;\n\t\tthis.prevNameIndex = 0;\n\t}\n\tendLine(segments) {\n\t\tthis.lines.push(segments);\n\t\tthis.buffered += segments.length + 1;\n\t\tif (this.buffered >= 4096) this.drain(null);\n\t}\n\tsegments(segments) {\n\t\tthis.drain(segments);\n\t}\n\tfinish(segments) {\n\t\tthis.drain(segments);\n\t\tthis.flush();\n\t\treturn this.out;\n\t}\n\tdrain(trailing) {\n\t\tconst lines = this.lines;\n\t\tconst lineCount = lines.length;\n\t\tfor (let l = 0; l <= lineCount; l++) {\n\t\t\tconst line = l < lineCount ? lines[l] : trailing;\n\t\t\tif (line === null) break;\n\t\t\tfor (let i = 0; i < line.length; i++) {\n\t\t\t\tif (this.pos > FLUSH_THRESHOLD) this.flush();\n\t\t\t\tconst segment = line[i];\n\t\t\t\tif (this.needsComma) scratch[this.pos++] = COMMA;\n\t\t\t\tthis.needsComma = true;\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[0] - this.prevGenColumn);\n\t\t\t\tthis.prevGenColumn = segment[0];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[1] - this.prevSourceIndex);\n\t\t\t\tthis.prevSourceIndex = segment[1];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[2] - this.prevSourceLine);\n\t\t\t\tthis.prevSourceLine = segment[2];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[3] - this.prevSourceColumn);\n\t\t\t\tthis.prevSourceColumn = segment[3];\n\t\t\t\tif (segment.length === 5) {\n\t\t\t\t\tthis.pos = writeVlq(this.pos, segment[4] - this.prevNameIndex);\n\t\t\t\t\tthis.prevNameIndex = segment[4];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (l < lineCount) {\n\t\t\t\tif (this.pos > FLUSH_THRESHOLD) this.flush();\n\t\t\t\tscratch[this.pos++] = SEMICOLON;\n\t\t\t\tthis.needsComma = false;\n\t\t\t\tthis.prevGenColumn = 0;\n\t\t\t}\n\t\t}\n\t\tlines.length = 0;\n\t\tthis.buffered = 0;\n\t\tthis.flush();\n\t}\n\tflush() {\n\t\tthis.out += decoder.decode(scratch.subarray(0, this.pos));\n\t\tthis.pos = 0;\n\t}\n};\n//#endregion\n//#region src/utils/Mappings.ts\nconst NEWLINE_CHAR$1 = 10;\nfunction isWordCode(code) {\n\treturn code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95;\n}\nvar Mappings = class {\n\tconstructor(hires, encoder = null) {\n\t\tthis.hires = hires;\n\t\tthis.generatedCodeLine = 0;\n\t\tthis.generatedCodeColumn = 0;\n\t\tthis.raw = [];\n\t\tthis.rawSegments = this.raw[this.generatedCodeLine] = [];\n\t\tthis.rawRangeMappings = [];\n\t\tthis.rawRangeMappingsIndices = this.rawRangeMappings[this.generatedCodeLine] = [];\n\t\tthis.encoder = encoder;\n\t}\n\tnextLine() {\n\t\tif (this.encoder === null) {\n\t\t\tthis.generatedCodeLine += 1;\n\t\t\tthis.raw[this.generatedCodeLine] = this.rawSegments = [];\n\t\t} else {\n\t\t\tthis.encoder.endLine(this.rawSegments);\n\t\t\tthis.rawSegments = [];\n\t\t\tthis.generatedCodeLine += 1;\n\t\t}\n\t\tthis.generatedCodeColumn = 0;\n\t\tthis.rawRangeMappings[this.generatedCodeLine] = this.rawRangeMappingsIndices = [];\n\t}\n\taddEdit(sourceIndex, content, loc, nameIndex) {\n\t\tif (content.length) {\n\t\t\tconst contentLengthMinusOne = content.length - 1;\n\t\t\tlet contentLineEnd = content.indexOf(\"\\n\", 0);\n\t\t\tlet previousContentLineEnd = -1;\n\t\t\twhile (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {\n\t\t\t\tconst segment = [\n\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\tsourceIndex,\n\t\t\t\t\tloc.line,\n\t\t\t\t\tloc.column\n\t\t\t\t];\n\t\t\t\tif (nameIndex >= 0) segment.push(nameIndex);\n\t\t\t\tthis.rawSegments.push(segment);\n\t\t\t\tthis.nextLine();\n\t\t\t\tpreviousContentLineEnd = contentLineEnd;\n\t\t\t\tcontentLineEnd = content.indexOf(\"\\n\", contentLineEnd + 1);\n\t\t\t}\n\t\t\tconst segment = [\n\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\tsourceIndex,\n\t\t\t\tloc.line,\n\t\t\t\tloc.column\n\t\t\t];\n\t\t\tif (nameIndex >= 0) segment.push(nameIndex);\n\t\t\tthis.rawSegments.push(segment);\n\t\t\tthis.advance(content.slice(previousContentLineEnd + 1));\n\t\t}\n\t}\n\taddUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {\n\t\tconst end = chunk.end;\n\t\tlet i = chunk.start;\n\t\tif (this.hires) {\n\t\t\tconst boundary = this.hires === \"boundary\";\n\t\t\tconst experimentalRange = this.hires === \"experimental-range\";\n\t\t\tconst encoder = experimentalRange ? null : this.encoder;\n\t\t\tlet charInHiresBoundary = false;\n\t\t\twhile (i < end) {\n\t\t\t\tif (encoder !== null && this.rawSegments.length >= 4096) {\n\t\t\t\t\tencoder.segments(this.rawSegments);\n\t\t\t\t\tthis.rawSegments.length = 0;\n\t\t\t\t}\n\t\t\t\tif (experimentalRange && i + 1 >= end) this.rawSegments.push([\n\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\tsourceIndex,\n\t\t\t\t\tloc.line,\n\t\t\t\t\tloc.column\n\t\t\t\t]);\n\t\t\t\tconst code = original.charCodeAt(i);\n\t\t\t\tif (code === NEWLINE_CHAR$1) {\n\t\t\t\t\tloc.line += 1;\n\t\t\t\t\tloc.column = 0;\n\t\t\t\t\tthis.nextLine();\n\t\t\t\t\tcharInHiresBoundary = false;\n\t\t\t\t} else {\n\t\t\t\t\tif (boundary) {\n\t\t\t\t\t\tif (isWordCode(code)) {\n\t\t\t\t\t\t\tif (!charInHiresBoundary) {\n\t\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\tcharInHiresBoundary = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tcharInHiresBoundary = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (experimentalRange) {\n\t\t\t\t\t\tif (i === chunk.start) {\n\t\t\t\t\t\t\tthis.rawRangeMappingsIndices.push(this.rawSegments.length);\n\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else this.rawSegments.push([\n\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\tloc.column\n\t\t\t\t\t]);\n\t\t\t\t\tloc.column += 1;\n\t\t\t\t\tthis.generatedCodeColumn += 1;\n\t\t\t\t}\n\t\t\t\ti += 1;\n\t\t\t}\n\t\t} else {\n\t\t\tconst bits = sourcemapLocations.bits;\n\t\t\twhile (i < end) {\n\t\t\t\tlet newline = original.indexOf(\"\\n\", i);\n\t\t\t\tif (newline === -1 || newline > end) newline = end;\n\t\t\t\tif (newline > i) {\n\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\tloc.column\n\t\t\t\t\t]);\n\t\t\t\t\tfor (let w = i + 1 >> 5, last = newline - 1 >> 5; w <= last; w++) {\n\t\t\t\t\t\tlet word = bits[w];\n\t\t\t\t\t\tif (!word) continue;\n\t\t\t\t\t\tconst base = w << 5;\n\t\t\t\t\t\twhile (word) {\n\t\t\t\t\t\t\tconst lowest = word & -word;\n\t\t\t\t\t\t\tconst index = base + 31 - Math.clz32(lowest);\n\t\t\t\t\t\t\tif (index > i && index < newline) {\n\t\t\t\t\t\t\t\tconst offset = index - i;\n\t\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\t\tthis.generatedCodeColumn + offset,\n\t\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\t\tloc.column + offset\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tword ^= lowest;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tloc.column += newline - i;\n\t\t\t\t\tthis.generatedCodeColumn += newline - i;\n\t\t\t\t}\n\t\t\t\tif (newline === end) break;\n\t\t\t\tloc.line += 1;\n\t\t\t\tloc.column = 0;\n\t\t\t\tthis.nextLine();\n\t\t\t\ti = newline + 1;\n\t\t\t}\n\t\t}\n\t}\n\tadvance(str) {\n\t\tif (!str) return;\n\t\tconst lastNewline = str.lastIndexOf(\"\\n\");\n\t\tfor (let i = str.indexOf(\"\\n\"); i !== -1; i = str.indexOf(\"\\n\", i + 1)) this.nextLine();\n\t\tthis.generatedCodeColumn += str.length - lastNewline - 1;\n\t}\n};\n//#endregion\n//#region src/MagicString.ts\nconst n = \"\\n\";\nconst NEWLINE_CHAR = \"\\n\".charCodeAt(0);\nconst CR_CHAR = \"\\r\".charCodeAt(0);\nconst warned = {\n\tinsertLeft: false,\n\tinsertRight: false,\n\tstoreName: false\n};\n/**\n* Expands the `$` substitution patterns that `String.prototype.replace` accepts\n* in a string replacement.\n* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter\n*\n* `captures` holds the capture groups in order, so `captures[0]` is `$1`.\n* `namedCaptures` is `undefined` when the pattern has no named groups, and\n* `$<name>` is then literal text - which is also the case for a string search\n* value, where there are no groups of either kind.\n*/\nfunction expandReplacement(replacement, matched, position, str, captures, namedCaptures) {\n\tif (!replacement.includes(\"$\")) return replacement;\n\tlet result = \"\";\n\tlet index = 0;\n\twhile (index < replacement.length) {\n\t\tconst dollar = replacement.indexOf(\"$\", index);\n\t\tif (dollar === -1) {\n\t\t\tresult += replacement.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\tresult += replacement.slice(index, dollar);\n\t\tconst char = replacement[dollar + 1];\n\t\tlet expansion = \"$\";\n\t\tlet consumed = 1;\n\t\tif (char === \"$\") consumed = 2;\n\t\telse if (char === \"&\") {\n\t\t\texpansion = matched;\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"`\") {\n\t\t\texpansion = str.slice(0, position);\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"'\") {\n\t\t\texpansion = str.slice(position + matched.length);\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"<\" && namedCaptures !== void 0) {\n\t\t\tconst close = replacement.indexOf(\">\", dollar + 2);\n\t\t\tif (close !== -1) {\n\t\t\t\texpansion = namedCaptures[replacement.slice(dollar + 2, close)] ?? \"\";\n\t\t\t\tconsumed = close + 1 - dollar;\n\t\t\t}\n\t\t} else if (char >= \"0\" && char <= \"9\") {\n\t\t\tconst second = replacement[dollar + 2];\n\t\t\tconst double = second >= \"0\" && second <= \"9\" ? Number(char + second) : NaN;\n\t\t\tconst single = Number(char);\n\t\t\tif (double >= 1 && double <= captures.length) {\n\t\t\t\texpansion = captures[double - 1] ?? \"\";\n\t\t\t\tconsumed = 3;\n\t\t\t} else if (single >= 1 && single <= captures.length) {\n\t\t\t\texpansion = captures[single - 1] ?? \"\";\n\t\t\t\tconsumed = 2;\n\t\t\t}\n\t\t}\n\t\tresult += expansion;\n\t\tindex = dollar + consumed;\n\t}\n\treturn result;\n}\nvar MagicString = class MagicString {\n\tconstructor(string, options = {}) {\n\t\tconst chunk = new Chunk(0, string.length, string);\n\t\tObject.defineProperties(this, {\n\t\t\toriginal: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: string\n\t\t\t},\n\t\t\toutro: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: \"\"\n\t\t\t},\n\t\t\tintro: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: \"\"\n\t\t\t},\n\t\t\tfirstChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tlastChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tlastSearchedChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tbyStart: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: /* @__PURE__ */ new Map([[0, chunk]])\n\t\t\t},\n\t\t\tbyEnd: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: /* @__PURE__ */ new Map([[string.length, chunk]])\n\t\t\t},\n\t\t\tfilename: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.filename\n\t\t\t},\n\t\t\tindentExclusionRanges: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.indentExclusionRanges\n\t\t\t},\n\t\t\tsourcemapLocations: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: new BitSet()\n\t\t\t},\n\t\t\tstoredNames: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: {}\n\t\t\t},\n\t\t\tindentStr: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: void 0\n\t\t\t},\n\t\t\tignoreList: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.ignoreList\n\t\t\t},\n\t\t\toffset: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.offset || 0\n\t\t\t},\n\t\t\thasMovedChunks: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: false\n\t\t\t}\n\t\t});\n\t}\n\t/**\n\t* Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.\n\t*/\n\taddSourcemapLocation(char) {\n\t\tthis.sourcemapLocations.add(char);\n\t}\n\t/**\n\t* Appends the specified content to the end of the string.\n\t*/\n\tappend(content) {\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis.outro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Appends the specified content at the index in the original string.\n\t* If a range *ending* with index is subsequently moved, the insert will be moved with it.\n\t* See also `s.prependLeft(...)`.\n\t*/\n\tappendLeft(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byEnd.get(index);\n\t\tif (chunk) chunk.appendLeft(content);\n\t\telse this.intro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Appends the specified content at the index in the original string.\n\t* If a range *starting* with index is subsequently moved, the insert will be moved with it.\n\t* See also `s.prependRight(...)`.\n\t*/\n\tappendRight(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byStart.get(index);\n\t\tif (chunk) chunk.appendRight(content);\n\t\telse this.outro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Does what you'd expect.\n\t*/\n\tclone() {\n\t\tconst cloned = new MagicString(this.original, {\n\t\t\tfilename: this.filename,\n\t\t\tignoreList: this.ignoreList,\n\t\t\toffset: this.offset\n\t\t});\n\t\tlet originalChunk = this.firstChunk;\n\t\tlet clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();\n\t\twhile (originalChunk) {\n\t\t\tcloned.byStart.set(clonedChunk.start, clonedChunk);\n\t\t\tcloned.byEnd.set(clonedChunk.end, clonedChunk);\n\t\t\tconst nextOriginalChunk = originalChunk.next;\n\t\t\tconst nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();\n\t\t\tif (nextClonedChunk) {\n\t\t\t\tclonedChunk.next = nextClonedChunk;\n\t\t\t\tnextClonedChunk.previous = clonedChunk;\n\t\t\t\tclonedChunk = nextClonedChunk;\n\t\t\t}\n\t\t\toriginalChunk = nextOriginalChunk;\n\t\t}\n\t\tcloned.lastChunk = clonedChunk;\n\t\tif (this.indentExclusionRanges) cloned.indentExclusionRanges = this.indentExclusionRanges.slice();\n\t\tcloned.sourcemapLocations = new BitSet(this.sourcemapLocations);\n\t\tcloned.storedNames = { ...this.storedNames };\n\t\tcloned.intro = this.intro;\n\t\tcloned.outro = this.outro;\n\t\tcloned.hasMovedChunks = this.hasMovedChunks;\n\t\treturn cloned;\n\t}\n\t/**\n\t* Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.\n\t* Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.\n\t*/\n\tgenerateDecodedMap(options) {\n\t\toptions = options || {};\n\t\tconst mappings = new Mappings(options.hires);\n\t\tconst names = this._generateMappings(mappings);\n\t\treturn {\n\t\t\t...this._mapProperties(options, names),\n\t\t\tmappings: mappings.raw,\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t};\n\t}\n\t/**\n\t* Generates a version 3 sourcemap.\n\t*/\n\tgenerateMap(options) {\n\t\toptions = options || {};\n\t\tconst encoder = new MappingsEncoder();\n\t\tconst mappings = new Mappings(options.hires, encoder);\n\t\tconst names = this._generateMappings(mappings);\n\t\treturn new SourceMap({\n\t\t\t...this._mapProperties(options, names),\n\t\t\tmappings: encoder.finish(mappings.rawSegments),\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t});\n\t}\n\t/** @internal */\n\t_generateMappings(mappings) {\n\t\tconst sourceIndex = 0;\n\t\tconst names = Object.keys(this.storedNames);\n\t\tconst locate = getLocator(this.original);\n\t\tif (this.intro) mappings.advance(this.intro);\n\t\tthis.firstChunk.eachNext((chunk) => {\n\t\t\tconst loc = locate(chunk.start);\n\t\t\tif (chunk.intro.length) mappings.advance(chunk.intro);\n\t\t\tif (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);\n\t\t\telse mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);\n\t\t\tif (chunk.outro.length) mappings.advance(chunk.outro);\n\t\t});\n\t\tif (this.outro) mappings.advance(this.outro);\n\t\treturn names;\n\t}\n\t/** @internal */\n\t_mapProperties(options, names) {\n\t\treturn {\n\t\t\tfile: options.file ? options.file.split(/[/\\\\]/).pop() : void 0,\n\t\t\tsources: [options.source ? getRelativePath(options.file || \"\", options.source) : options.file || \"\"],\n\t\t\tsourcesContent: options.includeContent ? [this.original] : void 0,\n\t\t\tnames,\n\t\t\tx_google_ignoreList: this.ignoreList ? [0] : void 0\n\t\t};\n\t}\n\t/** @internal */\n\t_ensureindentStr() {\n\t\tif (this.indentStr === void 0) this.indentStr = guessIndent(this.original);\n\t}\n\t/** @internal */\n\t_getRawIndentString() {\n\t\tthis._ensureindentStr();\n\t\treturn this.indentStr;\n\t}\n\tgetIndentString() {\n\t\tthis._ensureindentStr();\n\t\treturn this.indentStr === null ? \"\t\" : this.indentStr;\n\t}\n\tindent(indentStr, options) {\n\t\tconst pattern = /^[^\\r\\n]/gm;\n\t\tif (isObject(indentStr)) {\n\t\t\toptions = indentStr;\n\t\t\tindentStr = void 0;\n\t\t}\n\t\tif (indentStr === void 0) {\n\t\t\tthis._ensureindentStr();\n\t\t\tindentStr = this.indentStr || \"\t\";\n\t\t}\n\t\tif (indentStr === \"\") return this;\n\t\tconst resolvedIndentStr = indentStr;\n\t\toptions = options || {};\n\t\tconst isExcluded = {};\n\t\tif (options.exclude) (typeof options.exclude[0] === \"number\" ? [options.exclude] : options.exclude).forEach((exclusion) => {\n\t\t\tfor (let i = exclusion[0]; i < exclusion[1]; i += 1) isExcluded[i] = true;\n\t\t});\n\t\tlet shouldIndentNextCharacter = options.indentStart !== false;\n\t\tconst indentPiece = (str) => {\n\t\t\tif (str === \"\") return str;\n\t\t\tconst indented = str.replace(pattern, (match, offset) => offset > 0 || shouldIndentNextCharacter ? `${resolvedIndentStr}${match}` : match);\n\t\t\tshouldIndentNextCharacter = str[str.length - 1] === \"\\n\";\n\t\t\treturn indented;\n\t\t};\n\t\tthis.intro = indentPiece(this.intro);\n\t\tlet charIndex = 0;\n\t\tlet chunk = this.firstChunk;\n\t\tconst indentAt = (index) => {\n\t\t\tshouldIndentNextCharacter = false;\n\t\t\tif (index === chunk.start) chunk.appendRight(resolvedIndentStr);\n\t\t\telse {\n\t\t\t\tthis._splitChunk(chunk, index);\n\t\t\t\tchunk = chunk.next;\n\t\t\t\tchunk.prependRight(resolvedIndentStr);\n\t\t\t}\n\t\t};\n\t\twhile (chunk) {\n\t\t\tconst end = chunk.end;\n\t\t\tif (!isExcluded[chunk.start]) chunk.intro = indentPiece(chunk.intro);\n\t\t\tif (chunk.edited) {\n\t\t\t\tif (!isExcluded[charIndex]) chunk.content = indentPiece(chunk.content);\n\t\t\t} else if (options.exclude) {\n\t\t\t\tcharIndex = chunk.start;\n\t\t\t\twhile (charIndex < end) {\n\t\t\t\t\tif (!isExcluded[charIndex]) {\n\t\t\t\t\t\tconst char = this.original.charCodeAt(charIndex);\n\t\t\t\t\t\tif (char === NEWLINE_CHAR) shouldIndentNextCharacter = true;\n\t\t\t\t\t\telse if (char !== CR_CHAR && shouldIndentNextCharacter) indentAt(charIndex);\n\t\t\t\t\t}\n\t\t\t\t\tcharIndex += 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcharIndex = chunk.start;\n\t\t\t\twhile (charIndex < end) {\n\t\t\t\t\tif (!shouldIndentNextCharacter) {\n\t\t\t\t\t\tconst nextLine = this.original.indexOf(n, charIndex);\n\t\t\t\t\t\tif (nextLine === -1 || nextLine >= end) break;\n\t\t\t\t\t\tshouldIndentNextCharacter = true;\n\t\t\t\t\t\tcharIndex = nextLine + 1;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst char = this.original.charCodeAt(charIndex);\n\t\t\t\t\tif (char === NEWLINE_CHAR || char === CR_CHAR) {\n\t\t\t\t\t\tcharIndex += 1;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tindentAt(charIndex);\n\t\t\t\t\tcharIndex += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isExcluded[chunk.end - 1]) chunk.outro = indentPiece(chunk.outro);\n\t\t\tcharIndex = chunk.end;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tthis.outro = indentPiece(this.outro);\n\t\treturn this;\n\t}\n\t/** @internal */\n\tinsert() {\n\t\tthrow new MagicStringError(\"insert() is deprecated, use appendLeft() or prependRight()\");\n\t}\n\t/** @internal */\n\tinsertLeft(index, content) {\n\t\tif (!warned.insertLeft) {\n\t\t\tconsole.warn(\"magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead\");\n\t\t\twarned.insertLeft = true;\n\t\t}\n\t\treturn this.appendLeft(index, content);\n\t}\n\t/** @internal */\n\tinsertRight(index, content) {\n\t\tif (!warned.insertRight) {\n\t\t\tconsole.warn(\"magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead\");\n\t\t\twarned.insertRight = true;\n\t\t}\n\t\treturn this.prependRight(index, content);\n\t}\n\t/**\n\t* Moves the characters from `start` and `end` to `index`.\n\t*\n\t* `affinity` controls where the range is anchored at `index`. With the\n\t* default `'right'`, it is inserted before the content that starts at `index`;\n\t* with `'left'`, it is inserted after the content that ends at `index`. The\n\t* two differ only when other content has already been moved to that boundary,\n\t* mirroring the `appendLeft`/`appendRight` distinction.\n\t*/\n\tmove(start, end, index, affinity = \"right\") {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tindex = index + this.offset;\n\t\tif (start === end) return this;\n\t\tif (index >= start && index <= end) throw new MagicStringError(\"cannot move a selection inside itself\");\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tthis._split(index);\n\t\tconst first = this.byStart.get(start);\n\t\tconst last = this.byEnd.get(end);\n\t\tif (this.hasMovedChunks) {\n\t\t\tlet cursor = first;\n\t\t\twhile (cursor !== last) {\n\t\t\t\tcursor = cursor.next;\n\t\t\t\tif (!cursor || cursor.start < start || cursor.end > end) throw new MagicStringError(`cannot move ${start} to ${end} because an earlier move split that range`);\n\t\t\t}\n\t\t}\n\t\tconst oldLeft = first.previous;\n\t\tconst oldRight = last.next;\n\t\tlet newLeft;\n\t\tlet newRight;\n\t\tif (affinity === \"left\") {\n\t\t\tnewLeft = this.byEnd.get(index) ?? null;\n\t\t\tif (!newLeft) {\n\t\t\t\tif (first === this.firstChunk) return this;\n\t\t\t\tnewRight = this.firstChunk;\n\t\t\t} else {\n\t\t\t\tif (newLeft.next === first) return this;\n\t\t\t\tnewRight = newLeft.next;\n\t\t\t}\n\t\t} else {\n\t\t\tnewRight = this.byStart.get(index) ?? null;\n\t\t\tif (!newRight) {\n\t\t\t\tif (last === this.lastChunk) return this;\n\t\t\t\tnewLeft = this.lastChunk;\n\t\t\t} else {\n\t\t\t\tif (newRight.previous === last) return this;\n\t\t\t\tnewLeft = newRight.previous;\n\t\t\t}\n\t\t}\n\t\tif (oldLeft) oldLeft.next = oldRight;\n\t\tif (oldRight) oldRight.previous = oldLeft;\n\t\tif (newLeft) newLeft.next = first;\n\t\tif (newRight) newRight.previous = last;\n\t\tif (!first.previous) this.firstChunk = last.next;\n\t\tif (!last.next) {\n\t\t\tthis.lastChunk = first.previous;\n\t\t\tthis.lastChunk.next = null;\n\t\t}\n\t\tfirst.previous = newLeft;\n\t\tlast.next = newRight || null;\n\t\tif (!newLeft) this.firstChunk = first;\n\t\tif (!newRight) this.lastChunk = last;\n\t\tthis.hasMovedChunks = true;\n\t\treturn this;\n\t}\n\t/**\n\t* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in\n\t* that range. The same restrictions as `s.remove()` apply.\n\t*\n\t* The fourth argument is optional. It can have a storeName property - if true, the original name will be stored\n\t* for later inclusion in a sourcemap's names array - and a contentOnly property which determines whether only\n\t* the content is overwritten, or anything that was appended/prepended to the range as well.\n\t*\n\t* It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.\n\t*/\n\toverwrite(start, end, content, options) {\n\t\tconst optionObject = typeof options === \"object\" && options ? options : {};\n\t\treturn this.update(start, end, content, {\n\t\t\t...optionObject,\n\t\t\toverwrite: !optionObject.contentOnly\n\t\t});\n\t}\n\t/**\n\t* Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.\n\t*\n\t* The fourth argument is optional. It can have a storeName property - if true, the original name will be stored\n\t* for later inclusion in a sourcemap's names array - and an overwrite property which determines whether only\n\t* the content is overwritten, or anything that was appended/prepended to the range as well.\n\t*/\n\tupdate(start, end, content, options) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start < 0) throw new MagicStringError(`start ${start} is out of bounds`);\n\t\tif (end > this.original.length) throw new MagicStringError(`end ${end} is out of bounds`);\n\t\tif (start === end) throw new MagicStringError(`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tif (options === true) {\n\t\t\tif (!warned.storeName) {\n\t\t\t\tconsole.warn(\"The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string\");\n\t\t\t\twarned.storeName = true;\n\t\t\t}\n\t\t\toptions = { storeName: true };\n\t\t}\n\t\tconst optionObject = typeof options === \"object\" && options ? options : {};\n\t\tconst storeName = optionObject.storeName || false;\n\t\tconst overwrite = optionObject.overwrite || false;\n\t\tif (storeName) {\n\t\t\tconst original = this.original.slice(start, end);\n\t\t\tObject.defineProperty(this.storedNames, original, {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: true,\n\t\t\t\tenumerable: true\n\t\t\t});\n\t\t}\n\t\tconst first = this.byStart.get(start);\n\t\tconst last = this.byEnd.get(end);\n\t\t/* v8 ignore else -- unreachable: a valid start/end always yields a `first` chunk */\n\t\tif (first) {\n\t\t\tlet chunk = first;\n\t\t\twhile (chunk !== last) {\n\t\t\t\tif (chunk.next !== this.byStart.get(chunk.end)) throw new MagicStringError(\"cannot overwrite across a split point\");\n\t\t\t\tchunk = chunk.next;\n\t\t\t\tchunk.edit(\"\", false);\n\t\t\t}\n\t\t\tfirst.edit(content, storeName, !overwrite);\n\t\t} else {\n\t\t\tconst newChunk = new Chunk(start, end, \"\").edit(content, storeName);\n\t\t\tlast.next = newChunk;\n\t\t\tnewChunk.previous = last;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Prepends the string with the specified content.\n\t*/\n\tprepend(content) {\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis.intro = content + this.intro;\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index\n\t*/\n\tprependLeft(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byEnd.get(index);\n\t\tif (chunk) chunk.prependLeft(content);\n\t\telse this.intro = content + this.intro;\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`\n\t*/\n\tprependRight(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byStart.get(index);\n\t\tif (chunk) chunk.prependRight(content);\n\t\telse this.outro = content + this.outro;\n\t\treturn this;\n\t}\n\t/**\n\t* Removes the characters from `start` to `end` (of the original string, **not** the generated string).\n\t* Content appended or prepended at positions strictly inside the range is removed with it, while\n\t* content attached at `start` or `end` is preserved — use `s.overwrite(start, end, '')` to remove\n\t* the range including its edge inserts.\n\t* Removing the same content twice, or making removals that partially overlap, will cause an error.\n\t*/\n\tremove(start, end) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start === end) return this;\n\t\tif (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tlet chunk = this.byStart.get(start);\n\t\twhile (chunk) {\n\t\t\tif (chunk.start > start) chunk.intro = \"\";\n\t\t\tif (chunk.end < end) chunk.outro = \"\";\n\t\t\tchunk.edit(\"\", false, true);\n\t\t\tchunk = end > chunk.end ? this.byStart.get(chunk.end) : null;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).\n\t*/\n\treset(start, end) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start === end) return this;\n\t\tif (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tlet chunk = this.byStart.get(start);\n\t\twhile (chunk) {\n\t\t\tchunk.reset();\n\t\t\tchunk = end > chunk.end ? this.byStart.get(chunk.end) : null;\n\t\t}\n\t\treturn this;\n\t}\n\tlastChar() {\n\t\tif (this.outro.length) return this.outro[this.outro.length - 1];\n\t\tlet chunk = this.lastChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];\n\t\t\tif (chunk.content.length) return chunk.content[chunk.content.length - 1];\n\t\t\tif (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t\tif (this.intro.length) return this.intro[this.intro.length - 1];\n\t\treturn \"\";\n\t}\n\tlastLine() {\n\t\tlet lineIndex = this.outro.lastIndexOf(n);\n\t\tif (lineIndex !== -1) return this.outro.substr(lineIndex + 1);\n\t\tlet lineStr = this.outro;\n\t\tlet chunk = this.lastChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.outro.length > 0) {\n\t\t\t\tlineIndex = chunk.outro.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.outro + lineStr;\n\t\t\t}\n\t\t\tif (chunk.content.length > 0) {\n\t\t\t\tlineIndex = chunk.content.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.content + lineStr;\n\t\t\t}\n\t\t\tif (chunk.intro.length > 0) {\n\t\t\t\tlineIndex = chunk.intro.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.intro + lineStr;\n\t\t\t}\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t\tlineIndex = this.intro.lastIndexOf(n);\n\t\tif (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;\n\t\treturn this.intro + lineStr;\n\t}\n\t/**\n\t* Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.\n\t* Throws error if the indices are for characters that were already removed.\n\t*/\n\tslice(start = 0, end = this.original.length - this.offset) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tlet result = \"\";\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk && (chunk.start > start || chunk.end <= start)) {\n\t\t\tif (chunk.start < end && chunk.end >= end || end === 0 && chunk.start === 0) return result;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tif (chunk && chunk.edited && chunk.start !== start) throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`);\n\t\tconst startChunk = chunk;\n\t\twhile (chunk) {\n\t\t\tif (end === 0 && chunk.start === 0) break;\n\t\t\tif (chunk.intro && (startChunk !== chunk || chunk.start === start)) result += chunk.intro;\n\t\t\tconst containsEnd = chunk.start < end && chunk.end >= end;\n\t\t\tif (containsEnd && chunk.edited && chunk.end !== end) throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`);\n\t\t\tconst sliceStart = startChunk === chunk ? start - chunk.start : 0;\n\t\t\tconst sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;\n\t\t\tresult += chunk.content.slice(sliceStart, sliceEnd);\n\t\t\tif (chunk.outro && (!containsEnd || chunk.end === end)) result += chunk.outro;\n\t\t\tif (containsEnd) break;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.\n\t*/\n\tsnip(start, end) {\n\t\tconst clone = this.clone();\n\t\tclone.remove(0, start);\n\t\tclone.remove(end, clone.original.length);\n\t\treturn clone;\n\t}\n\t/** @internal */\n\t_split(index) {\n\t\tif (this.byStart.get(index) || this.byEnd.get(index)) return;\n\t\tlet chunk = this.lastSearchedChunk;\n\t\tlet previousChunk = chunk;\n\t\tconst searchForward = index > chunk.end;\n\t\twhile (chunk) {\n\t\t\tif (chunk.contains(index)) return this._splitChunk(chunk, index);\n\t\t\tchunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);\n\t\t\tif (chunk === previousChunk) return;\n\t\t\tpreviousChunk = chunk;\n\t\t}\n\t}\n\t/** @internal */\n\t_splitChunk(chunk, index) {\n\t\tif (chunk.edited && chunk.content.length) {\n\t\t\tconst loc = getLocator(this.original)(index);\n\t\t\tthrow new MagicStringError(`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – \"${chunk.original}\")`);\n\t\t}\n\t\tconst newChunk = chunk.split(index);\n\t\tthis.byEnd.set(index, chunk);\n\t\tthis.byStart.set(index, newChunk);\n\t\tthis.byEnd.set(newChunk.end, newChunk);\n\t\tif (chunk === this.lastChunk) this.lastChunk = newChunk;\n\t\tthis.lastSearchedChunk = chunk;\n\t\treturn true;\n\t}\n\t/**\n\t* Returns the generated string.\n\t*/\n\ttoString() {\n\t\tlet str = this.intro;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tstr += chunk.toString();\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn str + this.outro;\n\t}\n\t/**\n\t* Returns true if the resulting source is empty (disregarding white space).\n\t*/\n\tisEmpty() {\n\t\tif (this.intro.length && this.intro.trim()) return false;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tif (this.outro.length && this.outro.trim()) return false;\n\t\treturn true;\n\t}\n\tlength() {\n\t\tlet chunk = this.firstChunk;\n\t\tlet length = 0;\n\t\twhile (chunk) {\n\t\t\tlength += chunk.intro.length + chunk.content.length + chunk.outro.length;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn length;\n\t}\n\t/**\n\t* Removes empty lines from the start and end.\n\t*/\n\ttrimLines() {\n\t\treturn this.trim(\"[\\\\r\\\\n]\");\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the start and end.\n\t*/\n\ttrim(charType) {\n\t\treturn this.trimStart(charType).trimEnd(charType);\n\t}\n\t/** @internal */\n\ttrimEndAborted(charType) {\n\t\tconst rx = new RegExp(`${charType || \"\\\\s\"}+$`);\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\tif (this.outro.length) return true;\n\t\tlet chunk = this.lastChunk;\n\t\tdo {\n\t\t\tconst end = chunk.end;\n\t\t\tconst aborted = chunk.trimEnd(rx);\n\t\t\tif (chunk.end !== end) {\n\t\t\t\tif (this.lastChunk === chunk) this.lastChunk = chunk.next;\n\t\t\t\tthis.byEnd.set(chunk.end, chunk);\n\t\t\t\tthis.byStart.set(chunk.next.start, chunk.next);\n\t\t\t\tthis.byEnd.set(chunk.next.end, chunk.next);\n\t\t\t}\n\t\t\tif (aborted) return true;\n\t\t\tchunk = chunk.previous;\n\t\t} while (chunk);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\treturn this.intro.length > 0;\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the end.\n\t*/\n\ttrimEnd(charType) {\n\t\tthis.trimEndAborted(charType);\n\t\treturn this;\n\t}\n\t/** @internal */\n\ttrimStartAborted(charType) {\n\t\tconst rx = new RegExp(`^${charType || \"\\\\s\"}+`);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (this.intro.length) return true;\n\t\tlet chunk = this.firstChunk;\n\t\tdo {\n\t\t\tconst end = chunk.end;\n\t\t\tconst aborted = chunk.trimStart(rx);\n\t\t\tif (chunk.end !== end) {\n\t\t\t\tif (chunk === this.lastChunk) this.lastChunk = chunk.next;\n\t\t\t\tthis.byEnd.set(chunk.end, chunk);\n\t\t\t\tthis.byStart.set(chunk.next.start, chunk.next);\n\t\t\t\tthis.byEnd.set(chunk.next.end, chunk.next);\n\t\t\t}\n\t\t\tif (aborted) return true;\n\t\t\tchunk = chunk.next;\n\t\t} while (chunk);\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\treturn this.outro.length > 0;\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the start.\n\t*/\n\ttrimStart(charType) {\n\t\tthis.trimStartAborted(charType);\n\t\treturn this;\n\t}\n\t/**\n\t* Indicates if the string has been changed.\n\t*/\n\thasChanged() {\n\t\tif (this.intro || this.outro) return true;\n\t\tlet outputIndex = 0;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.intro || chunk.outro) return true;\n\t\t\tif (!chunk.edited && chunk.start === outputIndex) outputIndex = chunk.end;\n\t\t\telse {\n\t\t\t\tif (!this.original.startsWith(chunk.content, outputIndex)) return true;\n\t\t\t\toutputIndex += chunk.content.length;\n\t\t\t}\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn outputIndex !== this.original.length;\n\t}\n\t/**\n\t* Whether the original range [start, end) has had any of its characters\n\t* removed. `replace`/`replaceAll` search `original`, so a match can land on\n\t* text that is no longer in the output - overwriting it would resurrect the\n\t* removed characters, so such matches are skipped instead.\n\t*\n\t* @internal\n\t*/\n\t_hasRemovedContent(start, end) {\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.content === \"\" && chunk.start < end && chunk.end > start) return true;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn false;\n\t}\n\t/** @internal */\n\t_replaceRegexp(searchValue, replacement) {\n\t\tfunction getReplacement(match, str) {\n\t\t\tif (typeof replacement === \"string\") return expandReplacement(replacement, match[0], match.index, str, match.slice(1), match.groups);\n\t\t\telse return match.groups === void 0 ? replacement(match[0], ...match.slice(1), match.index, str) : replacement(match[0], ...match.slice(1), match.index, str, match.groups);\n\t\t}\n\t\tconst replaceMatch = (match) => {\n\t\t\t/* v8 ignore next 2 -- `match.index` is always defined for matches from `matchAll` */\n\t\t\tif (match.index == null) return false;\n\t\t\tif (this._hasRemovedContent(match.index, match.index + match[0].length)) return false;\n\t\t\tconst replacement = getReplacement(match, this.original);\n\t\t\tif (replacement === match[0]) return true;\n\t\t\tif (match[0].length === 0) this.appendRight(match.index, replacement);\n\t\t\telse this.overwrite(match.index, match.index + match[0].length, replacement);\n\t\t\treturn true;\n\t\t};\n\t\tif (searchValue.global) {\n\t\t\tsearchValue.lastIndex = 0;\n\t\t\tfor (const match of this.original.matchAll(searchValue)) replaceMatch(match);\n\t\t} else {\n\t\t\tconst match = this.original.match(searchValue);\n\t\t\tif (match && !replaceMatch(match)) {\n\t\t\t\tconst global = new RegExp(searchValue.source, `${searchValue.flags}g`);\n\t\t\t\tfor (const next of this.original.matchAll(global)) if (replaceMatch(next)) break;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\t/** @internal */\n\t_replaceString(string, replacement) {\n\t\tconst { original } = this;\n\t\tlet index = original.indexOf(string);\n\t\twhile (index !== -1) {\n\t\t\tif (this._hasRemovedContent(index, index + string.length)) {\n\t\t\t\tindex = original.indexOf(string, index + string.length);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof replacement === \"function\") replacement = replacement(string, index, original);\n\t\t\telse replacement = expandReplacement(replacement, string, index, original, [], void 0);\n\t\t\tif (string !== replacement) {\n\t\t\t\tif (string.length === 0) this.appendRight(index, replacement);\n\t\t\t\telse this.overwrite(index, index + string.length, replacement);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* String replacement with RegExp or string.\n\t*/\n\treplace(searchValue, replacement) {\n\t\tif (typeof searchValue === \"string\") return this._replaceString(searchValue, replacement);\n\t\treturn this._replaceRegexp(searchValue, replacement);\n\t}\n\t/** @internal */\n\t_replaceAllString(string, replacement) {\n\t\tconst { original } = this;\n\t\tconst stringLength = string.length;\n\t\tif (stringLength === 0) {\n\t\t\tfor (let index = 0; index <= original.length; index += 1) {\n\t\t\t\tconst _replacement = typeof replacement === \"function\" ? replacement(\"\", index, original) : expandReplacement(replacement, \"\", index, original, [], void 0);\n\t\t\t\tif (_replacement !== \"\") this.appendRight(index, _replacement);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tfor (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {\n\t\t\tif (this._hasRemovedContent(index, index + stringLength)) continue;\n\t\t\tconst previous = original.slice(index, index + stringLength);\n\t\t\tconst _replacement = typeof replacement === \"function\" ? replacement(previous, index, original) : expandReplacement(replacement, previous, index, original, [], void 0);\n\t\t\tif (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.replace`, but replace all matched strings instead of just one.\n\t*/\n\treplaceAll(searchValue, replacement) {\n\t\tif (typeof searchValue === \"string\") return this._replaceAllString(searchValue, replacement);\n\t\tif (!searchValue.global) throw new MagicStringError(\"replaceAll() requires a global RegExp\");\n\t\treturn this._replaceRegexp(searchValue, replacement);\n\t}\n};\n//#endregion\n//#region src/Bundle.ts\nconst hasOwnProp = Object.prototype.hasOwnProperty;\nvar Bundle = class Bundle {\n\tconstructor(options = {}) {\n\t\tthis.intro = options.intro || \"\";\n\t\tthis.separator = options.separator !== void 0 ? options.separator : \"\\n\";\n\t\tthis.sources = [];\n\t\tthis.uniqueSources = [];\n\t\tthis.uniqueSourceIndexByFilename = {};\n\t}\n\t/**\n\t* Adds the specified source to the bundle, which can either be a `MagicString` object directly,\n\t* or an options object that holds a magic string `content` property and optionally provides\n\t* a `filename` for the source within the bundle, as well as an optional `ignoreList` hint\n\t* (which defaults to `false`). The `filename` is used when constructing the source map for the\n\t* bundle, to identify this `source` in the source map's `sources` field. The `ignoreList` hint\n\t* is used to populate the `x_google_ignoreList` extension field in the source map, which is a\n\t* mechanism for tools to signal to debuggers that certain sources should be ignored by default\n\t* (depending on user preferences).\n\t*/\n\taddSource(source) {\n\t\tif (source instanceof MagicString) return this.addSource({\n\t\t\tcontent: source,\n\t\t\tfilename: source.filename,\n\t\t\tseparator: this.separator\n\t\t});\n\t\tif (!isObject(source) || !source.content) throw new MagicStringError(\"addSource() requires a `content` property that is a MagicString\");\n\t\t[\n\t\t\t\"filename\",\n\t\t\t\"ignoreList\",\n\t\t\t\"indentExclusionRanges\",\n\t\t\t\"separator\"\n\t\t].forEach((option) => {\n\t\t\tif (!hasOwnProp.call(source, option)) source[option] = source.content[option];\n\t\t});\n\t\tif (source.separator === void 0) source.separator = this.separator;\n\t\tif (source.filename) {\n\t\t\tif (!hasOwnProp.call(this.uniqueSourceIndexByFilename, source.filename)) {\n\t\t\t\tthis.uniqueSourceIndexByFilename[source.filename] = this.uniqueSources.length;\n\t\t\t\tthis.uniqueSources.push({\n\t\t\t\t\tfilename: source.filename,\n\t\t\t\t\tcontent: source.content.original\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst uniqueSource = this.uniqueSources[this.uniqueSourceIndexByFilename[source.filename]];\n\t\t\t\tif (source.content.original !== uniqueSource.content) throw new MagicStringError(`duplicate filename \"${source.filename}\" with different content, use unique filenames`);\n\t\t\t}\n\t\t}\n\t\tthis.sources.push(source);\n\t\treturn this;\n\t}\n\tappend(str, options) {\n\t\tthis.addSource({\n\t\t\tcontent: new MagicString(str),\n\t\t\tseparator: options && options.separator || \"\"\n\t\t});\n\t\treturn this;\n\t}\n\tclone() {\n\t\tconst bundle = new Bundle({\n\t\t\tintro: this.intro,\n\t\t\tseparator: this.separator\n\t\t});\n\t\tthis.sources.forEach((source) => {\n\t\t\tbundle.addSource({\n\t\t\t\tfilename: source.filename,\n\t\t\t\tcontent: source.content.clone(),\n\t\t\t\tignoreList: source.ignoreList,\n\t\t\t\tindentExclusionRanges: source.indentExclusionRanges,\n\t\t\t\tseparator: source.separator\n\t\t\t});\n\t\t});\n\t\treturn bundle;\n\t}\n\t/**\n\t* Flattens the bundle into a single `MagicString`, so the concatenated result can be\n\t* processed further with the full `MagicString` API. The returned string's `original`\n\t* is the concatenation of every source's `original`, and all existing edits, inserts,\n\t* intros, outros and separators are preserved as inserted content, so its `toString()`\n\t* equals the bundle's `toString()` and its sourcemap maps back to that combined original.\n\t*\n\t* Because a `MagicString` maps to a single source, per-source `filename`s are not carried\n\t* over; generate the bundle's map before flattening if you need the multi-source mapping.\n\t*/\n\ttoMagicString() {\n\t\tconst combined = new MagicString(this.sources.map((source) => source.content.original).join(\"\"));\n\t\tlet offset = 0;\n\t\tlet pending = this.intro;\n\t\tlet first = null;\n\t\tlet last = null;\n\t\tconst byStart = /* @__PURE__ */ new Map();\n\t\tconst byEnd = /* @__PURE__ */ new Map();\n\t\tlet hasMovedChunks = false;\n\t\tthis.sources.forEach((source, i) => {\n\t\t\tconst magicString = source.content;\n\t\t\tconst separator = i > 0 ? source.separator !== void 0 ? source.separator : this.separator : \"\";\n\t\t\tif (magicString.original.length === 0) {\n\t\t\t\tpending += separator + magicString.toString();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending += separator + magicString.intro;\n\t\t\tlet sourceFirst = null;\n\t\t\tlet previous = null;\n\t\t\tlet originalChunk = magicString.firstChunk;\n\t\t\twhile (originalChunk) {\n\t\t\t\tconst chunk = originalChunk.clone();\n\t\t\t\tchunk.start += offset;\n\t\t\t\tchunk.end += offset;\n\t\t\t\tchunk.previous = previous;\n\t\t\t\tchunk.next = null;\n\t\t\t\tif (previous) previous.next = chunk;\n\t\t\t\tbyStart.set(chunk.start, chunk);\n\t\t\t\tbyEnd.set(chunk.end, chunk);\n\t\t\t\tsourceFirst ??= chunk;\n\t\t\t\tprevious = chunk;\n\t\t\t\toriginalChunk = originalChunk.next;\n\t\t\t}\n\t\t\tconst sourceLast = previous;\n\t\t\tsourceFirst.intro = pending + sourceFirst.intro;\n\t\t\tpending = \"\";\n\t\t\tsourceLast.outro += magicString.outro;\n\t\t\tif (last) {\n\t\t\t\tlast.next = sourceFirst;\n\t\t\t\tsourceFirst.previous = last;\n\t\t\t} else first = sourceFirst;\n\t\t\tlast = sourceLast;\n\t\t\tfor (let index = 0; index < magicString.original.length; index += 1) if (magicString.sourcemapLocations.has(index)) combined.sourcemapLocations.add(index + offset);\n\t\t\tObject.keys(magicString.storedNames).forEach((name) => {\n\t\t\t\tObject.defineProperty(combined.storedNames, name, {\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: true,\n\t\t\t\t\tenumerable: true\n\t\t\t\t});\n\t\t\t});\n\t\t\tif (magicString.hasMovedChunks) hasMovedChunks = true;\n\t\t\toffset += magicString.original.length;\n\t\t});\n\t\tif (!first) {\n\t\t\tcombined.intro = pending;\n\t\t\treturn combined;\n\t\t}\n\t\tif (pending) last.outro += pending;\n\t\tcombined.firstChunk = first;\n\t\tcombined.lastChunk = last;\n\t\tcombined.lastSearchedChunk = first;\n\t\tcombined.byStart = byStart;\n\t\tcombined.byEnd = byEnd;\n\t\tcombined.hasMovedChunks = hasMovedChunks;\n\t\treturn combined;\n\t}\n\tgenerateDecodedMap(options = {}) {\n\t\tconst mappings = new Mappings(options.hires);\n\t\tconst { names, x_google_ignoreList } = this._generateMappings(mappings);\n\t\treturn {\n\t\t\t...this._mapProperties(options, names, x_google_ignoreList),\n\t\t\tmappings: mappings.raw,\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t};\n\t}\n\tgenerateMap(options = {}) {\n\t\tconst encoder = new MappingsEncoder();\n\t\tconst mappings = new Mappings(options.hires, encoder);\n\t\tconst { names, x_google_ignoreList } = this._generateMappings(mappings);\n\t\treturn new SourceMap({\n\t\t\t...this._mapProperties(options, names, x_google_ignoreList),\n\t\t\tmappings: encoder.finish(mappings.rawSegments),\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t});\n\t}\n\t/** @internal */\n\t_generateMappings(mappings) {\n\t\tconst names = [];\n\t\tlet x_google_ignoreList;\n\t\tthis.sources.forEach((source) => {\n\t\t\tObject.keys(source.content.storedNames).forEach((name) => {\n\t\t\t\tif (!names.includes(name)) names.push(name);\n\t\t\t});\n\t\t});\n\t\tif (this.intro) mappings.advance(this.intro);\n\t\tthis.sources.forEach((source, i) => {\n\t\t\tif (i > 0)\n /* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tmappings.advance(source.separator !== void 0 ? source.separator : this.separator);\n\t\t\tconst sourceIndex = source.filename ? this.uniqueSourceIndexByFilename[source.filename] : -1;\n\t\t\tconst magicString = source.content;\n\t\t\tconst locate = getLocator(magicString.original);\n\t\t\tif (magicString.intro) mappings.advance(magicString.intro);\n\t\t\tmagicString.firstChunk.eachNext((chunk) => {\n\t\t\t\tconst loc = locate(chunk.start);\n\t\t\t\tif (chunk.intro.length) mappings.advance(chunk.intro);\n\t\t\t\tif (source.filename) {\n\t\t\t\t\tif (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);\n\t\t\t\t\telse mappings.addUneditedChunk(sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations);\n\t\t\t\t} else mappings.advance(chunk.content);\n\t\t\t\tif (chunk.outro.length) mappings.advance(chunk.outro);\n\t\t\t});\n\t\t\tif (magicString.outro) mappings.advance(magicString.outro);\n\t\t\tif (source.ignoreList && sourceIndex !== -1) {\n\t\t\t\tif (x_google_ignoreList === void 0) x_google_ignoreList = [];\n\t\t\t\tx_google_ignoreList.push(sourceIndex);\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\tnames,\n\t\t\tx_google_ignoreList\n\t\t};\n\t}\n\t/** @internal */\n\t_mapProperties(options, names, x_google_ignoreList) {\n\t\treturn {\n\t\t\tfile: options.file ? options.file.split(/[/\\\\]/).pop() : void 0,\n\t\t\tsources: this.uniqueSources.map((source) => {\n\t\t\t\treturn options.file ? getRelativePath(options.file, source.filename) : source.filename;\n\t\t\t}),\n\t\t\tsourcesContent: this.uniqueSources.map((source) => {\n\t\t\t\treturn (typeof options.includeContent === \"function\" ? options.includeContent(source) : options.includeContent) ? source.content : null;\n\t\t\t}),\n\t\t\tnames,\n\t\t\tx_google_ignoreList\n\t\t};\n\t}\n\tgetIndentString() {\n\t\tconst indentStringCounts = {};\n\t\tthis.sources.forEach((source) => {\n\t\t\tconst indentStr = source.content._getRawIndentString();\n\t\t\tif (indentStr === null) return;\n\t\t\tif (!indentStringCounts[indentStr]) indentStringCounts[indentStr] = 0;\n\t\t\tindentStringCounts[indentStr] += 1;\n\t\t});\n\t\treturn Object.keys(indentStringCounts).sort((a, b) => {\n\t\t\treturn indentStringCounts[b] - indentStringCounts[a];\n\t\t})[0] || \"\t\";\n\t}\n\tindent(indentStr) {\n\t\tif (!arguments.length) indentStr = this.getIndentString();\n\t\tif (indentStr === \"\") return this;\n\t\tlet trailingNewline = !this.intro || this.intro.slice(-1) === \"\\n\";\n\t\tthis.sources.forEach((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\tconst indentStart = trailingNewline || i > 0 && /\\r?\\n$/.test(separator);\n\t\t\tsource.content.indent(indentStr, {\n\t\t\t\texclude: source.indentExclusionRanges,\n\t\t\t\tindentStart\n\t\t\t});\n\t\t\ttrailingNewline = source.content.lastChar() === \"\\n\";\n\t\t});\n\t\tif (this.intro) this.intro = indentStr + this.intro.replace(/^[^\\n]/gm, (match, index) => {\n\t\t\treturn index > 0 ? indentStr + match : match;\n\t\t});\n\t\treturn this;\n\t}\n\tprepend(str) {\n\t\tthis.intro = str + this.intro;\n\t\treturn this;\n\t}\n\ttoString() {\n\t\tconst body = this.sources.map((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn (i > 0 ? separator : \"\") + source.content.toString();\n\t\t}).join(\"\");\n\t\treturn this.intro + body;\n\t}\n\tisEmpty() {\n\t\tif (this.intro.length && this.intro.trim()) return false;\n\t\tif (this.sources.some((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn i > 0 && separator.trim() !== \"\" || !source.content.isEmpty();\n\t\t})) return false;\n\t\treturn true;\n\t}\n\tlength() {\n\t\treturn this.sources.reduce((length, source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn length + (i > 0 ? separator.length : 0) + source.content.toString().length;\n\t\t}, this.intro.length);\n\t}\n\ttrimLines() {\n\t\treturn this.trim(\"[\\\\r\\\\n]\");\n\t}\n\ttrim(charType) {\n\t\treturn this.trimStart(charType).trimEnd(charType);\n\t}\n\ttrimStart(charType) {\n\t\tconst rx = new RegExp(`^${charType || \"\\\\s\"}+`);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (!this.intro) for (let i = 0; i < this.sources.length; i += 1) {\n\t\t\tconst source = this.sources[i];\n\t\t\tif (i > 0) {\n\t\t\t\tsource.separator = (source.separator !== void 0 ? source.separator : this.separator).replace(rx, \"\");\n\t\t\t\tif (source.separator) break;\n\t\t\t}\n\t\t\tif (source.content.trimStartAborted(charType)) break;\n\t\t}\n\t\treturn this;\n\t}\n\ttrimEnd(charType) {\n\t\tconst rx = new RegExp(`${charType || \"\\\\s\"}+$`);\n\t\tfor (let i = this.sources.length - 1; i >= 0; i -= 1) {\n\t\t\tconst source = this.sources[i];\n\t\t\tif (source.content.trimEndAborted(charType)) return this;\n\t\t\tif (i > 0) {\n\t\t\t\tsource.separator = (source.separator !== void 0 ? source.separator : this.separator).replace(rx, \"\");\n\t\t\t\tif (source.separator) return this;\n\t\t\t}\n\t\t}\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\treturn this;\n\t}\n};\n//#endregion\nexport { Bundle, MagicString, MagicString as default, MagicStringError, SourceMap };\n","/**\n * Transform-hook logic for the timber-fonts plugin.\n *\n * Scans source files for font function calls (`Inter({...})`,\n * `localFont({...})`), validates that they are statically analysable,\n * registers the extracted fonts in the `FontPipeline`, and rewrites the\n * call sites to static `FontResult` literals so the runtime never has to\n * evaluate the font function.\n *\n * Uses a single OXC (via vite.parseAst) parse of the source file (via `findFontCallSites`)\n * and magic-string for precise source rewrites with source maps.\n *\n * Design doc: 24-fonts.md\n */\n\nimport MagicString from 'magic-string';\nimport type { ExtractedFont, GoogleFontConfig } from './types.ts';\nimport { buildFontStack } from './fallbacks.ts';\nimport { processLocalFont } from './local.ts';\nimport {\n extractFontConfigAst,\n detectDynamicFontCallAst,\n findFontCallSites,\n extractGoogleFontConfigFromNode,\n extractLocalFontConfigFromNode,\n} from './ast.ts';\nimport type { FontPipeline } from './pipeline.ts';\n\n/**\n * Convert a font family name to a scoped class name.\n * e.g. \"JetBrains Mono\" → \"timber-font-jetbrains-mono\"\n */\nfunction familyToClassName(family: string): string {\n return `timber-font-${family.toLowerCase().replace(/\\s+/g, '-')}`;\n}\n\n/** Normalize a string or string array to an array (default `['400']`). */\nfunction normalizeWeightArray(value: string | string[] | undefined): string[] {\n if (!value) return ['400'];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Normalize style to an array (default `['normal']`). */\nfunction normalizeStyleArray(value: string | string[] | undefined): string[] {\n if (!value) return ['normal'];\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * Generate a unique font ID from family + config hash.\n *\n * The ID intentionally includes every property that affects the rendered\n * `@font-face` output (`weight`, `style`, `subsets`, `display`) so that an\n * HMR edit changing any of those produces a new ID and the registry is\n * forced to re-emit fresh CSS.\n */\nexport function generateFontId(family: string, config: GoogleFontConfig): string {\n const weights = normalizeWeightArray(config.weight);\n const styles = normalizeStyleArray(config.style);\n const subsets = config.subsets ?? ['latin'];\n const display = config.display ?? 'swap';\n return `${family.toLowerCase()}-${weights.join(',')}-${styles.join(',')}-${subsets.join(',')}-${display}`;\n}\n\n/**\n * Extract static font config from a font function call source.\n *\n * Returns `null` if the call cannot be statically analysed.\n */\nexport function extractFontConfig(callSource: string): GoogleFontConfig | null {\n return extractFontConfigAst(callSource);\n}\n\n/**\n * Detect dynamic/computed font function calls that cannot be statically\n * analysed. Returns the offending expression text, or `null` if all calls\n * are static.\n */\nexport function detectDynamicFontCall(source: string, importedNames: string[]): string | null {\n return detectDynamicFontCallAst(source, importedNames);\n}\n\n// ── Regex-free import/family parsing (thin wrappers over AST) ────────────────\n//\n// These keep the public surface stable. They use `findFontCallSites`\n// internally so they agree with the transform on what counts as an import.\n\n/**\n * Parse the local names imported from `@timber/fonts/google` /\n * `next/font/google`. e.g. `import { Inter, JetBrains_Mono as Mono }` →\n * `['Inter', 'Mono']`.\n */\nexport function parseGoogleFontImports(source: string): string[] {\n const analysis = findFontCallSites(source);\n if (!analysis) return [];\n return analysis.bindings.filter((b) => b.provider === 'google').map((b) => b.localName);\n}\n\n/**\n * Parse Google font imports into a `localName → familyName` map.\n *\n * e.g. `import { JetBrains_Mono as Mono }` → `{ Mono: 'JetBrains Mono' }`.\n * The original (pre-`as`) name is converted from PascalCase-with-underscores\n * to the human-readable family name by replacing `_` with a space.\n */\nexport function parseGoogleFontFamilies(source: string): Map<string, string> {\n const analysis = findFontCallSites(source);\n const families = new Map<string, string>();\n if (!analysis) return families;\n for (const b of analysis.bindings) {\n if (b.provider !== 'google') continue;\n const family = b.importedName.replace(/_/g, ' ');\n families.set(b.localName, family);\n }\n return families;\n}\n\n/**\n * Parse the local name used for the default import of `@timber/fonts/local`.\n *\n * Handles either spelling and arbitrary local names:\n * import localFont from '@timber/fonts/local'\n * import myLoader from 'next/font/local'\n */\nexport function parseLocalFontImportName(source: string): string | null {\n const analysis = findFontCallSites(source);\n if (!analysis) return null;\n const localBinding = analysis.bindings.find((b) => b.provider === 'local');\n return localBinding?.localName ?? null;\n}\n\n/** Build the static `FontResult` literal we substitute for a font call. */\nfunction buildFontResultLiteral(extracted: ExtractedFont): string {\n return extracted.variable\n ? `{ className: \"${extracted.className}\", style: { fontFamily: \"${extracted.fontFamily}\" }, variable: \"${extracted.variable}\" }`\n : `{ className: \"${extracted.className}\", style: { fontFamily: \"${extracted.fontFamily}\" } }`;\n}\n\n/** Type for the Vite plugin's `this.error` callback. */\ntype EmitError = (msg: string) => never;\n\n/**\n * Run the timber-fonts transform pass on a single source file.\n *\n * Parses the source once with OXC (via vite.parseAst), walks the AST to find font imports\n * and call sites, then uses magic-string to rewrite call sites to static\n * `FontResult` literals and strip the import declarations. Returns a\n * source map alongside the transformed code.\n *\n * Returns `null` if the file does not import from any font virtual module.\n *\n * Pre-filtering (extension allow-list, node_modules exclusion, and code\n * substring checks) is handled by Vite 8's rolldown-native `transform.filter`\n * in the plugin hook definition (plugins/fonts.ts). See TIM-840, TIM-1147.\n */\nexport function runFontsTransform(\n code: string,\n id: string,\n pipeline: FontPipeline,\n emitError: EmitError\n): { code: string; map: ReturnType<MagicString['generateMap']> } | null {\n // Single parse + AST walk.\n const analysis = findFontCallSites(code);\n if (!analysis) return null;\n\n // Bail on dynamic calls.\n if (analysis.dynamicCall) {\n emitError(\n `Font function calls must be statically analyzable. ` +\n `Found dynamic call: ${analysis.dynamicCall}. ` +\n `Pass a literal object with string/array values instead.`\n );\n }\n\n // Bail on nested font calls (must be module-level).\n if (analysis.nestedCalls.length > 0) {\n const first = analysis.nestedCalls[0];\n emitError(\n `Font function \\`${first.name}()\\` must be called at module scope. ` +\n `Found nested call at line ${first.line}, column ${first.column}. ` +\n `Move the call to the top level of the module.`\n );\n }\n\n // Bail on namespace imports of font modules — the transform cannot\n // rewrite `fonts.Inter(...)` member calls, so the font would silently\n // never load.\n if (analysis.namespaceImports.length > 0) {\n const first = analysis.namespaceImports[0];\n emitError(\n `Namespace imports of font modules are not supported ` +\n `(\\`* as ${first.name}\\` at line ${first.line}, column ${first.column}). ` +\n `Use a named import instead: \\`import { Inter } from 'next/font/google'\\`.`\n );\n }\n\n // Bail on font binding references the transform cannot rewrite\n // (`export default Inter({...})`, object-literal nesting, member access\n // on the call result, aliasing, re-exports). The import declaration is\n // removed, so leaving these would be a silent runtime ReferenceError.\n if (analysis.unsupportedUsages.length > 0) {\n const first = analysis.unsupportedUsages[0];\n emitError(\n `Unsupported usage of font function \\`${first.name}\\` at ` +\n `line ${first.line}, column ${first.column}. ` +\n `A font call must be \\`const x = Font({...})\\` at module scope ` +\n `(export const is fine). The call result cannot be nested in other ` +\n `expressions, and the imported font function cannot be aliased or re-exported.`\n );\n }\n\n if (analysis.callSites.length === 0 && analysis.bindings.length === 0) return null;\n\n const s = new MagicString(code);\n\n // Extract and validate all call sites before mutating the pipeline.\n // If any extraction fails (emitError throws), the pipeline is untouched\n // so the previous valid CSS stays intact (TIM-1087).\n const pending: { extracted: ExtractedFont; site: (typeof analysis.callSites)[0] }[] = [];\n\n for (const site of analysis.callSites) {\n if (site.binding.provider === 'google') {\n const family = site.binding.importedName.replace(/_/g, ' ');\n\n const config = extractGoogleFontConfigFromNode(site.configNode);\n if (!config) {\n emitError(\n `Could not statically analyze font config for ${family} ` +\n `at line ${site.line}, column ${site.column}. ` +\n `Ensure all config values are string literals or arrays of string literals.`\n );\n }\n\n const fontId = generateFontId(family, config!);\n const className = familyToClassName(family);\n const fontStack = buildFontStack(family);\n const display = config!.display ?? 'swap';\n\n pending.push({\n site,\n extracted: {\n id: fontId,\n family,\n provider: 'google',\n weights: normalizeWeightArray(config!.weight),\n styles: normalizeStyleArray(config!.style),\n subsets: config!.subsets ?? ['latin'],\n display,\n variable: config!.variable,\n className,\n fontFamily: fontStack,\n importer: id,\n },\n });\n } else {\n // local font\n const config = extractLocalFontConfigFromNode(site.configNode);\n if (!config) {\n emitError(\n `Could not statically analyze local font config ` +\n `at line ${site.line}, column ${site.column}. ` +\n `Ensure src is a string or array of { path, weight?, style? } objects.`\n );\n }\n\n pending.push({ site, extracted: processLocalFont(config!, id) });\n }\n }\n\n // All extractions succeeded — now prune stale entries and register.\n // Handles family renames and deleted font calls (TIM-1087).\n pipeline.pruneImporter(id);\n for (const { extracted, site } of pending) {\n pipeline.register(extracted);\n s.overwrite(site.replaceStart, site.replaceEnd, buildFontResultLiteral(extracted));\n }\n\n // Remove font import declarations. Use a Set to avoid double-removing\n // when multiple bindings come from the same ImportDeclaration.\n const removedRanges = new Set<string>();\n for (const imp of analysis.importNodesToRemove) {\n const key = `${imp.start}:${imp.end}`;\n if (removedRanges.has(key)) continue;\n removedRanges.add(key);\n\n // Also remove the trailing newline if present.\n let end = imp.end;\n if (code[end] === '\\n') end++;\n else if (code[end] === '\\r' && code[end + 1] === '\\n') end += 2;\n // Also remove a trailing semicolon before the newline.\n if (code[imp.end] === ';') {\n end = imp.end + 1;\n if (code[end] === '\\n') end++;\n else if (code[end] === '\\r' && code[end + 1] === '\\n') end += 2;\n }\n s.remove(imp.start, end);\n }\n\n if (!s.hasChanged()) return null;\n\n // Inject a side-effect import for the per-importer virtual CSS module.\n if (pipeline.size() > 0) {\n const virtualCssId = pipeline.cssIdMap.idFor(id);\n s.prepend(`import '${virtualCssId}';\\n`);\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: true }),\n };\n}\n","/**\n * Dev-mode middleware that serves local font binaries under\n * `/_timber/fonts/<basename>`.\n *\n * Only files registered in the FontPipeline are served, and only by\n * basename — directory traversal and path separators in the requested\n * filename are rejected up front. Font CSS is no longer served here; it\n * goes through Vite's CSS pipeline via virtual modules.\n *\n * Design doc: 24-fonts.md\n */\n\nimport type { ViteDevServer } from 'vite';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { FontPipeline } from './pipeline.ts';\nimport { fontOutputBasename, fontUrlPrefix } from './paths.ts';\n\nconst FONT_MIME_TYPES: Record<string, string> = {\n woff2: 'font/woff2',\n woff: 'font/woff',\n ttf: 'font/ttf',\n otf: 'font/otf',\n eot: 'application/vnd.ms-fontopen',\n};\n\n/**\n * Wire the timber-fonts dev middleware onto a Vite dev server.\n *\n * Returns synchronously after registering the middleware. The pipeline is\n * captured by reference so that fonts registered after `configureServer`\n * runs (during transform) are still resolvable.\n */\nexport function installFontDevMiddleware(\n server: ViteDevServer,\n pipeline: FontPipeline,\n base = '/'\n): void {\n const urlPrefix = `${fontUrlPrefix(base)}/`;\n server.middlewares.use((req, res, next) => {\n const url = req.url;\n if (!url || !url.startsWith(urlPrefix)) return next();\n\n const requestedFilename = url.slice(urlPrefix.length);\n // Reject path traversal attempts and any subdirectory access. We only\n // serve flat basenames out of the registry.\n if (requestedFilename.includes('..') || requestedFilename.includes('/')) {\n res.statusCode = 400;\n res.end('Bad request');\n return;\n }\n\n // Find the matching font file in the registry. We iterate every local\n // font's source list and match by basename. The set is small (one per\n // localFont() call) so this is cheap.\n for (const font of pipeline.fonts()) {\n if (font.provider !== 'local' || !font.localSources) continue;\n for (const src of font.localSources) {\n const basename = fontOutputBasename(src.path);\n if (basename !== requestedFilename && src.hashedBasename !== requestedFilename) continue;\n\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) {\n res.statusCode = 404;\n res.end('Not found');\n return;\n }\n const data = readFileSync(absolutePath);\n const ext = absolutePath.split('.').pop()?.toLowerCase();\n res.setHeader('Content-Type', FONT_MIME_TYPES[ext ?? ''] ?? 'application/octet-stream');\n // Dev URLs are raw (unhashed) basenames — `immutable` is only\n // justified by content hashing (design/24-fonts.md). `no-cache`\n // keeps responses revalidatable so edited fonts update without a\n // hard refresh. Production binaries are content-hashed and served\n // immutable by the platform, not this middleware.\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.end(data);\n return;\n }\n }\n\n next();\n });\n}\n","/**\n * Build-output emission for the timber-fonts plugin.\n *\n * Splits the `generateBundle` hook into pure helpers so the plugin shell\n * can stay focused on Vite wiring. The functions here are deliberately\n * Rollup-agnostic — they take an `EmitFile` callback so the plugin can\n * pass `this.emitFile` from the `generateBundle` context.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { ManifestFontEntry, BuildManifest } from '../server/build-manifest.ts';\nimport { fontOutputBasename, fontUrlPrefix, FONT_OUTPUT_DIR } from './paths.ts';\n\n/**\n * Minimal shape of the asset descriptor accepted by Rollup's `emitFile`.\n * Declared inline rather than importing from `rollup` to keep `bundle.ts`\n * Rollup-agnostic and avoid pulling the type into the build graph.\n */\ninterface EmittedAsset {\n type: 'asset';\n fileName: string;\n source: string | Uint8Array;\n}\nimport type { FontPipeline } from './pipeline.ts';\nimport type { CachedFont } from './google.ts';\nimport { inferFontFormat } from './local.ts';\n\ntype EmitFile = (asset: EmittedAsset) => string;\ntype EmitWarning = (msg: string) => void;\n\n/** Group cached Google Font binaries by lowercase family name. */\nexport function groupCachedFontsByFamily(\n cachedFonts: readonly CachedFont[]\n): Map<string, CachedFont[]> {\n const cachedByFamily = new Map<string, CachedFont[]>();\n for (const cf of cachedFonts) {\n const key = cf.face.family.toLowerCase();\n const arr = cachedByFamily.get(key) ?? [];\n arr.push(cf);\n cachedByFamily.set(key, arr);\n }\n return cachedByFamily;\n}\n\n/**\n * Emit cached Google Font binaries and local font files into the build\n * output under `_timber/fonts/`. Local files missing on disk produce a\n * warning rather than an error so the build still succeeds.\n *\n * Cached Google Font binaries are deduplicated by `hashedFilename` so\n * each unique file is written exactly once even when multiple font\n * entries share a family (and therefore share `CachedFont` references).\n */\nexport function emitFontAssets(\n pipeline: FontPipeline,\n emitFile: EmitFile,\n warn: EmitWarning\n): void {\n // Cached Google Font binaries (content-hashed, deduped by filename)\n for (const cf of pipeline.uniqueCachedFiles()) {\n emitFile({\n type: 'asset',\n fileName: `${FONT_OUTPUT_DIR}/${cf.hashedFilename}`,\n source: cf.data,\n });\n }\n\n // Local font files (content-hashed for immutable caching)\n for (const font of pipeline.fonts()) {\n if (font.provider !== 'local' || !font.localSources) continue;\n for (const src of font.localSources) {\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) {\n warn(`Local font file not found: ${absolutePath}`);\n continue;\n }\n const filename = src.hashedBasename ?? fontOutputBasename(src.path);\n const data = readFileSync(absolutePath);\n emitFile({\n type: 'asset',\n fileName: `${FONT_OUTPUT_DIR}/${filename}`,\n source: data,\n });\n }\n }\n}\n\n/**\n * Populate `buildManifest.fonts` with `ManifestFontEntry[]` keyed by the\n * absolute importer path. This matches the runtime route manifest's\n * `filePath` values (which are absolute) and is consistent with how\n * `buildManifest.css` keys work after TIM-1014.\n *\n * All font binaries use content-hashed filenames for immutable caching.\n * Hrefs are prefixed with Vite's resolved `base` so they match the URLs\n * the platform serves the emitted binaries under.\n */\nexport function writeFontManifest(\n pipeline: FontPipeline,\n buildManifest: BuildManifest,\n base = '/'\n): void {\n const urlPrefix = fontUrlPrefix(base);\n const fontsByImporter = new Map<string, ManifestFontEntry[]>();\n\n for (const entry of pipeline.entries()) {\n const manifestEntries = fontsByImporter.get(entry.importer) ?? [];\n\n if (entry.provider === 'local' && entry.localSources) {\n for (const src of entry.localSources) {\n const filename = src.hashedBasename ?? fontOutputBasename(src.path);\n const format = inferFontFormat(src.path);\n manifestEntries.push({\n href: `${urlPrefix}/${filename}`,\n format,\n crossOrigin: 'anonymous',\n });\n }\n } else if (entry.cachedFiles) {\n for (const cf of entry.cachedFiles) {\n manifestEntries.push({\n href: `${urlPrefix}/${cf.hashedFilename}`,\n format: 'woff2',\n crossOrigin: 'anonymous',\n });\n }\n }\n\n fontsByImporter.set(entry.importer, manifestEntries);\n }\n\n for (const [importer, entries] of fontsByImporter) {\n buildManifest.fonts[importer] = entries;\n }\n}\n","/**\n * timber-fonts — Vite sub-plugin shell for build-time font processing.\n *\n * This file is intentionally thin: it wires the Vite plugin hooks to the\n * pipeline + per-concern modules under `../fonts/`. All real logic lives\n * in:\n *\n * - `../fonts/pipeline.ts` — `FontPipeline` (state, mutators)\n * - `../fonts/transform.ts` — transform-hook logic, parsing helpers\n * - `../fonts/dev-middleware.ts` — dev font binary server\n * - `../fonts/virtual-modules.ts` — virtual module ID constants + source\n *\n * The public exports below are the stable API that the test suite and\n * other parts of the framework import. Anything new should be added to\n * one of the per-concern modules and re-exported here only if external\n * consumers need it.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { parseAst } from 'vite';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport {\n downloadAndCacheFonts,\n generateProductionFontFaces,\n resolveDevFontFaces,\n} from '../fonts/google.ts';\nimport { FONT_OUTPUT_DIR, fontUrlPrefix } from '../fonts/paths.ts';\nimport { FontPipeline } from '../fonts/pipeline.ts';\nimport { runFontsTransform } from '../fonts/transform.ts';\nimport { installFontDevMiddleware } from '../fonts/dev-middleware.ts';\nimport { emitFontAssets, writeFontManifest, groupCachedFontsByFamily } from '../fonts/bundle.ts';\nimport {\n RESOLVED_GOOGLE,\n RESOLVED_LOCAL,\n VIRTUAL_GOOGLE,\n VIRTUAL_LOCAL,\n generateGoogleVirtualModule,\n generateLocalVirtualModule,\n} from '../fonts/virtual-modules.ts';\n\n// ── Public re-exports ────────────────────────────────────────────────────\n//\n// These exports are part of the stable surface area imported by tests and\n// downstream consumers. Do NOT change their names or signatures without\n// updating every caller. New helpers should be added to the per-concern\n// module first and re-exported here only if external code needs them.\n\nexport { FontPipeline } from '../fonts/pipeline.ts';\nexport {\n generateFontId,\n extractFontConfig,\n detectDynamicFontCall,\n parseGoogleFontImports,\n parseGoogleFontFamilies,\n parseLocalFontImportName,\n} from '../fonts/transform.ts';\n\n/**\n * What the post-build phase asks of the font plugin (plugins/post-build.ts).\n * Called after every environment has been built, so the font entries are\n * complete — no environment's `generateBundle` has to run after the build\n * manifest exists.\n */\nexport interface FontsBuildStep {\n /** Write this build's font entries into the build manifest. */\n contributeManifest(manifest: BuildManifest): void;\n /**\n * Directories of the client bundle this build filled with content-hashed\n * font binaries — `[FONT_OUTPUT_DIR]` when any were emitted, else none.\n */\n immutableDirs(): string[];\n}\n\n/**\n * Create the timber-fonts Vite plugin.\n */\nexport function timberFonts(ctx: PluginContext): Plugin & { api: FontsBuildStep } {\n const pipeline = new FontPipeline({ hashOnRegister: !ctx.dev });\n /** Whether the client environment emitted a binary this build. */\n let emittedToClient = false;\n\n return {\n name: 'timber-fonts',\n\n api: {\n contributeManifest: (manifest) => writeFontManifest(pipeline, manifest, ctx.base),\n immutableDirs: () => (emittedToClient ? [FONT_OUTPUT_DIR] : []),\n },\n\n /**\n * Push Vite's resolved `base` into the pipeline so every font URL it\n * emits (@font-face src, manifest hrefs, dev middleware matching)\n * carries the prefix. Emitted file locations are unaffected — only URLs.\n *\n * `config.base` is read here rather than `ctx.base`: this plugin is\n * `enforce: 'pre'`, so its configResolved runs before timber-root-sync\n * populates `ctx.base`. Every *later* hook reads `ctx.base` — the single\n * copy (TIM-1261).\n */\n configResolved(config: ResolvedConfig) {\n pipeline.setBase(config.base);\n\n // Font binaries are emitted in generateBundle, after Vite's CSS\n // url() resolution runs. The warnings are benign — suppress them.\n const originalWarnOnce = config.logger.warnOnce.bind(config.logger);\n config.logger.warnOnce = (msg, options) => {\n if (msg.includes('_timber/fonts/') && msg.includes(\"didn't resolve at build time\")) return;\n originalWarnOnce(msg, options);\n };\n },\n\n /**\n * `enforce: 'pre'` is load-bearing for the font CSS pipeline (TIM-828).\n *\n * The transform hook injects a side-effect\n * `import 'virtual:timber-font-css/<hash>.css'` into every file that\n * registers a font. @vitejs/plugin-rsc's `rsc:rsc-css-export-transform`\n * later inspects each server component's source for CSS imports and\n * wraps the default export in `import.meta.viteRsc.loadCss(...)` so\n * the matched virtual CSS module ends up `preinit`'d as\n * `<link rel=\"stylesheet\" data-rsc-css-href=...>`.\n *\n * If timber-fonts ran in normal order it would inject the CSS import\n * *after* plugin-rsc had already scanned the source, and the font CSS\n * would be silently dropped from the rendered HTML. Running in the\n * `pre` slot guarantees our injected import is visible to plugin-rsc's\n * later CSS-export scan.\n */\n enforce: 'pre',\n\n /**\n * Resolve `@timber/fonts/google`, `@timber/fonts/local`, and the\n * per-importer `virtual:timber-font-css/<hash>.css` modules injected\n * by the transform hook.\n *\n * Strips the `\\0` prefix added by the RSC plugin's re-imports and the\n * absolute root prefix added by SSR build entries before comparing\n * against the public IDs. The `.css` suffix on font-css ids is\n * preserved so Vite's CSS pipeline (`isCSSRequest`) recognises the\n * resolved id as CSS.\n */\n resolveId(id: string) {\n let cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n const qIdx = cleanId.indexOf('?');\n const query = qIdx !== -1 ? cleanId.slice(qIdx) : '';\n if (qIdx !== -1) cleanId = cleanId.slice(0, qIdx);\n if (cleanId.startsWith(ctx.root)) {\n const stripped = cleanId.slice(ctx.root.length);\n if (stripped.startsWith('/') || stripped.startsWith('\\\\')) {\n cleanId = stripped.slice(1);\n } else {\n cleanId = stripped;\n }\n }\n\n if (cleanId === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;\n if (cleanId === VIRTUAL_LOCAL) return RESOLVED_LOCAL;\n // Preserve query suffix (notably `?direct`) on the resolved CSS id.\n // Vite's transform middleware appends `?direct` when the browser\n // fetches the URL as a `<link rel=\"stylesheet\">`, and the CSS plugin\n // only skips its JS-wrapping step when `isDirectCSSRequest(id)` sees\n // that query on the resolved id. Dropping it here caused virtual\n // font CSS to be served as Vite's HMR JS shim, leaving the\n // `<link>`-loaded stylesheet empty (TIM-937 follow-up).\n if (pipeline.cssIdMap.matches(cleanId)) return '\\0' + cleanId + query;\n return null;\n },\n\n /**\n * Return generated source for font virtual modules.\n *\n * The per-importer `virtual:timber-font-css/<hash>.css` modules\n * return the combined font CSS for the specific importer that\n * registered them. Vite's CSS pipeline handles injection from here:\n * in dev the module rides the CSS HMR channel; in production it is\n * emitted as a real CSS asset and @vitejs/plugin-rsc's `collectCss`\n * walks the RSC module graph to find it.\n *\n * Google `@font-face` descriptors are resolved lazily here (both\n * dev and production) because `load` runs after `transform` has\n * registered the font. `buildStart` runs before any transforms,\n * so fonts aren't in the pipeline yet when it fires for the first\n * environment.\n */\n async load(id: string) {\n if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(pipeline.fonts());\n if (id === RESOLVED_LOCAL) return generateLocalVirtualModule();\n\n if (pipeline.cssIdMap.matches(id)) {\n const importer = pipeline.cssIdMap.importerFor(id);\n if (!importer) {\n return '';\n }\n\n // The analyze crawl only needs import edges, not actual font\n // CSS. Return an empty stylesheet so transforms resolve\n // without triggering network fetches or cache writes.\n if (process.env.TIMBER_ANALYZE === '1') {\n return '';\n }\n\n const skipFonts = process.env.TIMBER_SKIP_FONTS === '1';\n\n for (const font of pipeline.googleFonts()) {\n if (font.importer !== importer) continue;\n if (pipeline.hasFaces(font.id)) continue;\n if (skipFonts && !ctx.dev) {\n console.warn(`[timber-fonts] Skipping font \"${font.family}\" (TIMBER_SKIP_FONTS=1)`);\n continue;\n }\n try {\n if (ctx.dev) {\n const faces = await resolveDevFontFaces(font);\n pipeline.attachFaces(font.id, faces);\n } else {\n const cached = await downloadAndCacheFonts([font], ctx.root);\n const byFamily = groupCachedFontsByFamily(cached);\n const familyCached = byFamily.get(font.family.toLowerCase()) ?? [];\n pipeline.attachCachedFiles(font.id, familyCached);\n pipeline.attachFaces(\n font.id,\n generateProductionFontFaces(familyCached, font.display, fontUrlPrefix(ctx.base))\n );\n }\n } catch (e) {\n if (!ctx.dev) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n console.warn(\n `[timber-fonts] Failed to resolve Google font \"${font.family}\": ${msg}. Will retry on next request.`\n );\n }\n }\n\n return pipeline.getCssForSegment(importer);\n }\n return null;\n },\n\n /**\n * Serve local font files in dev mode under `/_timber/fonts/<basename>`.\n * Font CSS goes through Vite's CSS pipeline (virtual modules), not\n * this middleware.\n */\n configureServer(server: ViteDevServer) {\n installFontDevMiddleware(server, pipeline, ctx.base);\n },\n\n /**\n * No-op. Font downloading and face attachment happen lazily in `load()`\n * because `buildStart` runs before `transform` — fonts aren't registered\n * in the pipeline yet when this fires for the first environment.\n *\n * Local font hashing is handled at registration time by the pipeline\n * (when `hashOnRegister` is set) so hashed filenames are available\n * before the virtual CSS `load()` hook runs.\n */\n buildStart() {},\n\n /**\n * Prune stale font entries when a module that previously imported fonts\n * no longer contains any font import. The transform hook's `filter.code`\n * skips such modules, so without this hook the old entries would persist\n * until dev restart. See TIM-1087.\n */\n async hotUpdate({ type, file, read }) {\n if (!pipeline.hasImporter(file)) return;\n if (type === 'delete') {\n pipeline.pruneImporter(file);\n return;\n }\n const code = await read();\n const hasFontImport =\n code.includes('@timber/fonts/') ||\n code.includes('@timber-js/app/fonts/') ||\n code.includes('next/font/');\n if (hasFontImport) return;\n // Only prune if the new source parses successfully. A syntax error\n // means the HMR update will fail and the old module stays active —\n // pruning would leave it without font CSS until the next valid save.\n try {\n parseAst(code, { lang: 'tsx' });\n } catch {\n return;\n }\n pipeline.pruneImporter(file);\n },\n\n /**\n * Scan source files for font function calls and extract static config.\n *\n * Delegates to `runFontsTransform`. Errors raised through the\n * `this.error` callback are surfaced as Vite plugin errors.\n *\n * The `filter` option uses Vite 8's rolldown-native hook filters to\n * skip non-JS/TS files and files that don't mention any font module\n * before crossing into JS — replacing the hand-rolled pre-filter that\n * was previously inside `runFontsTransform` (TIM-840, TIM-1147).\n */\n transform: {\n filter: {\n id: {\n include: /^[^?]*\\.(?:js|jsx|ts|tsx|mjs|cjs|mts|cts)(?:\\?|$)/,\n exclude: /(?:^\\0|(?:^|\\/)node_modules\\/)/,\n },\n code: ['@timber/fonts/', '@timber-js/app/fonts/', 'next/font/'],\n },\n handler(code: string, id: string) {\n return runFontsTransform(code, id, pipeline, (msg) => this.error(msg));\n },\n },\n\n /**\n * Emit font binaries.\n *\n * All font binaries (Google and local) use content-hashed filenames\n * for immutable caching. Font CSS is handled by Vite's CSS pipeline\n * via virtual modules — we only emit binaries here. Manifest entries are\n * written by the post-build phase through `api.contributeManifest`.\n */\n generateBundle() {\n let emitted = 0;\n emitFontAssets(\n pipeline,\n (asset) => {\n emitted++;\n return this.emitFile(asset);\n },\n (msg) => this.warn(msg)\n );\n if (this.environment?.name === 'client') emittedToClient = emitted > 0;\n },\n };\n}\n","/**\n * Shared Flight data script generation.\n *\n * Both html-injectors.ts (Web Streams / dev) and node-stream-transforms.ts\n * (Node streams / production) use this module to generate inline `<script>`\n * tags for RSC Flight data injection.\n *\n * The init script goes in `<head>` as part of the HTML shell (guaranteed\n * to execute before any streaming chunk scripts). Push scripts are emitted\n * as RSC chunks arrive during streaming.\n *\n * Every generator takes the request's CSP nonce (from `getCspNonce()`)\n * so the tags run under a nonce-based `script-src` (TIM-1414).\n *\n * See design/02-rendering-pipeline.md, LOCAL-415\n */\n\nimport { nonceAttr } from './render-utils.ts';\n\n// ─── JSON Escaping ────────────────────────────────────────────────────────\n\n/**\n * Escape a JSON string for safe embedding inside an HTML `<script>` tag.\n *\n * Prevents XSS via `</script>` injection and handles Unicode line/paragraph\n * separators that are valid JSON but invalid in JS string literals (pre-ES2019).\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n// ─── Script Generation ────────────────────────────────────────────────────\n\n/** The global variable name used for Flight data on the client. */\nconst FLIGHT_VAR = 'self.__timber_f';\n\n/**\n * Generate the init script that creates the Flight data array.\n *\n * This MUST be included in `<head>` (via headHtml) so it executes before\n * any streaming chunk scripts arrive in `<body>`. The array is created\n * unconditionally — no `||[]` guard needed in push scripts.\n *\n * Also emits the bootstrap signal [0] which tells the client that\n * Flight data is active for this page.\n */\nexport function flightInitScript(nonce?: string): string {\n return `<script${nonceAttr(nonce)}>${FLIGHT_VAR}=[${htmlEscapeJsonString(JSON.stringify([0]))}]</script>`;\n}\n\n/**\n * Generate a push script for a Flight data chunk.\n *\n * Normally the init script runs first (it's in `<head>`), so\n * `self.__timber_f` already exists. However, shell-less status pages\n * (e.g. standalone error pages) may have no `<head>` tag, so the init script\n * never runs. The `||[]` guard ensures the array is created on first\n * push if needed, preventing a TypeError. See TIM-559.\n */\nexport function flightChunkScript(data: string, nonce?: string): string {\n const escaped = htmlEscapeJsonString(JSON.stringify([1, data]));\n return `<script${nonceAttr(nonce)}>(${FLIGHT_VAR}=${FLIGHT_VAR}||[]).push(${escaped})</script>`;\n}\n","/**\n * timber-static-build — Vite sub-plugin for static output mode.\n *\n * When `output: 'static'` is set in timber.config.ts:\n * 1. The plugin validates that no dynamic APIs (getCookies(), getHeaders())\n * are used\n * 2. `runStaticGeneration`, the static generation step of the post-build\n * phase (plugins/post-build.ts), renders all routes to static HTML + RSC\n * flight files\n *\n * Design doc: design/11-platform.md §\"static output mode\"\n */\n\nimport type { Plugin } from 'vite';\nimport { mkdir, readdir, readFile, writeFile, rename, rm, stat } from 'node:fs/promises';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { dirname, extname, isAbsolute, join, resolve, relative } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { writeFileAtomic } from '../utils/write-file-atomic.ts';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { DirectoryArtifact } from '../adapters/types.ts';\nimport type {\n StaticGenerationOptions,\n StaticGenerationSummary,\n StaticPageEntry,\n StaticRedirectEntry,\n} from '../server/static-generator.ts';\nimport { isRelativeBase, normalizeBasePath, withBasePath } from '../shared/base-path.ts';\nimport type { RscManifest, RscManifestEntry } from '../shared/rsc-manifest.ts';\nimport { htmlEscapeJsonString } from '../server/flight-scripts.ts';\nimport { RSC_PAYLOAD_DIR, rscPayloadPath } from '../shared/rsc-payload-path.ts';\nimport { REDIRECTS_FILE, RESERVED_OUTPUT_PATHS } from '../shared/static-platform-files.ts';\nimport {\n detectFsIdentity,\n fsKey,\n EXACT_FS_IDENTITY,\n type FsIdentity,\n} from '../adapters/fs-identity.ts';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * A single entry in the RSC manifest injected into static HTML.\n * Maps an unhashed `/_rsc/*.rsc` path to its hashed URL, with\n * optional route params inlined to avoid a sidecar fetch.\n */\n// Declared in shared/rsc-manifest.ts so the client that reads this manifest and\n// the build that writes it cannot drift. Re-exported for existing importers.\nexport type { RscManifestEntry, RscManifest } from '../shared/rsc-manifest.ts';\n\nexport interface StaticValidationError {\n type: 'dynamic-api';\n file: string;\n message: string;\n line?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Detection: dynamic APIs (getCookies, getHeaders, and legacy cookies/headers)\n// ---------------------------------------------------------------------------\n\n/**\n * Patterns that indicate dynamic per-request API usage.\n * These are build errors in static mode because there is no request at build time.\n *\n * We detect both import-level and call-level usage.\n */\nconst DYNAMIC_API_PATTERNS: Array<{ pattern: RegExp; name: string }> = [\n { pattern: /\\bgetCookieJar\\s*\\(/, name: 'getCookieJar()' },\n { pattern: /\\bgetHeaders\\s*\\(/, name: 'getHeaders()' },\n { pattern: /\\bcookies\\s*\\(/, name: 'cookies()' },\n { pattern: /\\bheaders\\s*\\(/, name: 'headers()' },\n];\n\n/**\n * Detect usage of dynamic per-request APIs (getCookies(), getHeaders())\n * that cannot work at build time in static mode.\n *\n * Returns an array of validation errors.\n */\nexport function detectDynamicApis(code: string, fileId: string): StaticValidationError[] {\n const errors: StaticValidationError[] = [];\n\n for (const { pattern, name } of DYNAMIC_API_PATTERNS) {\n if (pattern.test(code)) {\n // Find the line number of the first match\n const lines = code.split('\\n');\n let line: number | undefined;\n for (let i = 0; i < lines.length; i++) {\n if (pattern.test(lines[i])) {\n line = i + 1;\n break;\n }\n }\n\n errors.push({\n type: 'dynamic-api',\n file: fileId,\n message:\n `${name} cannot be used in static mode — there is no request at build time. ` +\n `Remove the ${name} call or switch to output: 'server'.`,\n line,\n });\n }\n }\n\n return errors;\n}\n\n// ---------------------------------------------------------------------------\n// Redirect rules\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a `_redirects` file from collected redirect entries.\n * Uses the Cloudflare Pages / Netlify format: `/from /to statusCode`\n *\n * Both sides are base-prefixed (TIM-1274). `from` is matched by the host\n * against the request path and `to` is served to the browser as a `Location`,\n * so both are deployed-URL space while `StaticRedirectEntry` carries route\n * space — under `base: '/repo/'`, a rule `/old /new 301` would match nothing\n * and, if it did, would send the browser off the deployment.\n *\n * An off-origin `to` is left alone: `redirectExternal()` produces an absolute\n * URL, and a protocol-relative one addresses another host too. Neither is a\n * path on this deployment, so neither takes the prefix.\n *\n * @param base Normalized deployment base (see `shared/base-path.ts`).\n * @internal Exported for testing.\n */\nexport function generateRedirectsFile(redirects: StaticRedirectEntry[], base: string): string {\n const target = (to: string) =>\n to.startsWith('/') && !to.startsWith('//') ? withBasePath(base, to) : to;\n const lines = redirects.map((r) => `${withBasePath(base, r.from)} ${target(r.to)} ${r.status}`);\n return lines.join('\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// File output helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Determine the output file path for a static page entry.\n *\n * Pages: /about → about/index.html, / → index.html\n * RSC: /about → _rsc/about/index.rsc, / → _rsc/index.rsc\n * API: /feed.xml → feed.xml, /api/data → api/data\n *\n * The RSC shape mirrors the HTML shape for the reason the HTML shape has it:\n * a route gets a directory and the artifact is the `index` inside it, so the\n * mapping is injective. See `shared/rsc-payload-path.ts` (TIM-1266).\n */\nexport function staticOutputPath(entry: StaticPageEntry): string {\n const urlPath = entry.urlPath === '/' ? '' : entry.urlPath;\n\n if (entry.kind === 'rsc') {\n // Route space is `/…`; the static output path is relative to the output\n // directory, so drop the leading slash.\n return rscPayloadPath(entry.urlPath).slice(1);\n }\n\n if (entry.kind === 'api') {\n // API routes use their URL path directly. If no extension, fall\n // back to the path as-is (static host serves based on content type).\n return urlPath.startsWith('/') ? urlPath.slice(1) : urlPath || 'index';\n }\n\n // HTML pages\n if (!urlPath) return 'index.html';\n // Synthetic 404 entry from static generation — must be 404.html at the\n // root so static hosts (GitHub Pages, Cloudflare Pages, Netlify) serve\n // it automatically for unmatched URLs. Uses an internal urlPath to avoid\n // colliding with a real /404 page route.\n if (urlPath === '/_timber_not_found') return '404.html';\n return `${urlPath.startsWith('/') ? urlPath.slice(1) : urlPath}/index.html`;\n}\n\n// ---------------------------------------------------------------------------\n// Output path collisions (TIM-1266)\n// ---------------------------------------------------------------------------\n\n/**\n * Records which entry claimed each output path and reports second claims.\n *\n * Two entries landing on one path is not a rendering failure — both render\n * fine — so nothing downstream notices. The file is written twice, the second\n * write wins, and the deployment serves one route's bytes at another route's\n * URL with the same content type and the same shape (TIM-1266).\n *\n * The naming rules are injective by construction (a route path is a directory\n * and the artifact is the `index` inside it), so a collision here means either\n * two entries were enumerated for one URL or a route reached a path the\n * framework reserves for itself (`404.html`). Both are build errors: there is\n * no correct file to write.\n *\n * Two entries can also be unwritable together without claiming the same\n * string: one wants a file where the other wants a directory (`about` from an\n * API route, `about/index.html` from a page). The filesystem does refuse that\n * one — `EISDIR` on the rename, `ENOTDIR` on the mkdir, depending on which\n * lands second — but an errno names a path, and in the rename case the path\n * it names is the write's temp file. Reported here instead, so the message says which\n * two routes.\n *\n * Collisions are **collected, not thrown**. `onEntry` runs inside the\n * generator, whose RSC branch treats a throw as \"this payload is unavailable,\n * SPA navigation falls back to a full load\" and swallows it — which for a\n * collision is the wrong end state, since the two payloads are still\n * ambiguous. The caller raises them once generation is done.\n *\n * @internal Exported for testing.\n */\nexport class StaticOutputPaths {\n private readonly claimed = new Map<string, StaticPageEntry>();\n /** Every ancestor directory of a claimed path, mapped to its claimant. */\n private readonly directories = new Map<string, StaticPageEntry>();\n private readonly collisions: string[] = [];\n\n /**\n * @param identity How the output filesystem decides two paths name one\n * file, from `detectFsIdentity`. The guard predicts whether two writes\n * land on one file, which is a property of the filesystem — so it is\n * asked, not assumed. Folding unconditionally would reject `/Foo` beside\n * `/foo` on Linux, where both are perfectly servable files.\n */\n private readonly identity: FsIdentity;\n\n constructor(identity: FsIdentity = EXACT_FS_IDENTITY) {\n this.identity = identity;\n }\n\n /** The identity under which the filesystem will compare this path. */\n private key(relPath: string): string {\n return fsKey(relPath, this.identity);\n }\n\n /**\n * Claim `relPath` for `entry`. Returns false when the path cannot be\n * written alongside an earlier claim, in which case the caller must not\n * write the file — the losing entry is recorded and the build fails at\n * the end.\n */\n claim(relPath: string, entry: StaticPageEntry): boolean {\n // Folded like every other comparison here: on a case-insensitive\n // filesystem a route rendering to `_HEADERS` is the same file the\n // adapter is about to write, so a case-sensitive match would wave it\n // through into the overwrite this reservation exists to stop.\n if (RESERVED_OUTPUT_PATHS.some((name) => this.key(name) === this.key(relPath))) {\n this.collisions.push(\n ` - ${relPath}: reserved — the framework writes this file itself, ` +\n `and ${entry.kind} for ${entry.urlPath} would be overwritten by it`\n );\n return false;\n }\n\n const key = this.key(relPath);\n const conflict =\n this.claimed.get(key) ??\n // This entry wants a file where an earlier one wants a directory…\n this.directories.get(key) ??\n // …or a directory where an earlier one wants a file.\n ancestors(relPath).reduce<StaticPageEntry | undefined>(\n (found, dir) => found ?? this.claimed.get(this.key(dir)),\n undefined\n );\n\n if (conflict) {\n this.collisions.push(\n ` - ${relPath}: ${conflict.kind} for ${conflict.urlPath} and ${entry.kind} for ${entry.urlPath}`\n );\n return false;\n }\n\n this.claimed.set(key, entry);\n for (const dir of ancestors(relPath)) {\n const dirKey = this.key(dir);\n if (!this.directories.has(dirKey)) this.directories.set(dirKey, entry);\n }\n return true;\n }\n\n /** Throw if any two entries could not both be written. */\n assertNoCollisions(): void {\n if (this.collisions.length === 0) return;\n throw new Error(\n `[timber] Static generation: ${this.collisions.length} output path collision(s) — ` +\n `two entries write the same path and one would silently overwrite the other. ` +\n `Rename or remove one route in each pair:\\n${this.collisions.join('\\n')}`\n );\n }\n}\n\n/** Every directory an output path sits under, outermost first. */\nfunction ancestors(relPath: string): string[] {\n const parts = relPath.split('/');\n parts.pop();\n return parts.map((_, i) => parts.slice(0, i + 1).join('/'));\n}\n\n/**\n * Writes generated entries into the static output directory, one file per\n * entry, refusing any write that would land on a path another entry holds.\n *\n * @internal Exported for testing.\n */\nexport class StaticSiteWriter {\n /** Content-Type per URL path for extensionless API routes (TIM-1241). */\n readonly contentTypes: Record<string, string> = {};\n private readonly paths: StaticOutputPaths;\n\n private readonly staticDir: string;\n\n constructor(staticDir: string, identity: FsIdentity = EXACT_FS_IDENTITY) {\n this.staticDir = staticDir;\n this.paths = new StaticOutputPaths(identity);\n }\n\n async write(entry: StaticPageEntry): Promise<void> {\n const relPath = staticOutputPath(entry);\n const fullPath = resolve(this.staticDir, relPath);\n\n // Reject path traversal: generated params with \"../\" could escape\n // the output directory and overwrite build artifacts.\n //\n // Tested on the first *segment*, not on the prefix. A slug is arbitrary\n // application data, and `..draft` is an ordinary directory name whose\n // relative path merely begins with two dots — a prefix test failed the\n // build on it. `isAbsolute` covers the case `relative()` gives up on and\n // returns an absolute path for: a different Windows drive, where the\n // round-trip check below compares equal and would let it through.\n const rel = relative(this.staticDir, fullPath);\n const firstSegment = rel.split(/[\\\\/]/)[0];\n if (firstSegment === '..' || isAbsolute(rel) || resolve(this.staticDir, rel) !== fullPath) {\n throw new Error(\n `[timber] Static generation: output path \"${relPath}\" escapes the ` +\n `static output directory — check generateStaticSegmentParams for ` +\n `path traversal characters in ${entry.urlPath}`\n );\n }\n\n // Claim the *normalized* path, not the one `staticOutputPath` built. Two\n // distinct strings can name one file — a generated param carrying `..`\n // makes `_rsc/a/../b/index.rsc` and `_rsc/b/index.rsc` different keys for\n // the same write, which is the collision this check exists to stop. The\n // traversal guard above only rejects escapes; it lets an in-bounds detour\n // through.\n //\n // A losing claim is not written: the build is about to fail, and\n // clobbering the winner would make the failure state worse than the one\n // being reported.\n if (!this.paths.claim(rel.replace(/\\\\/g, '/'), entry)) return;\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFileAtomic(fullPath, entry.body);\n\n // Track Content-Type for extensionless API routes so adapters\n // can write per-path Content-Type rules in _headers. TIM-1241.\n if (entry.kind === 'api' && !extname(relPath) && entry.contentType) {\n this.contentTypes[entry.urlPath] = entry.contentType;\n }\n }\n\n /** Throw if any two entries could not both be written. */\n assertNoCollisions(): void {\n this.paths.assertNoCollisions();\n }\n}\n\n/**\n * Remove artifacts a generation pass produces only *conditionally*, so none\n * of them can survive from an earlier build into this one.\n *\n * Pages are not in this set: every page is rewritten each pass, and a page\n * whose route was deleted is a different problem (a stale file nothing links\n * to) from the one here.\n *\n * - `_rsc/` because the files are content-hashed. Left in place, a previous\n * build's already-hashed payload gets hashed again and accumulates.\n * - `_redirects` because it is written only when this pass found redirects.\n * A build whose redirects were removed would otherwise ship the previous\n * build's rules — and would break the merge exemption in\n * `shared/static-platform-files.ts`, which lets the pre-rendered copy\n * overwrite `public/_redirects` on the grounds that it *contains* it. That\n * holds only for a file the current pass produced (TIM-1266).\n *\n * @internal Exported for testing.\n */\nexport async function cleanConditionalArtifacts(staticDir: string): Promise<void> {\n await rm(join(staticDir, RSC_PAYLOAD_DIR), { recursive: true, force: true }).catch(() => {});\n await rm(join(staticDir, REDIRECTS_FILE), { force: true }).catch(() => {});\n}\n\n// ---------------------------------------------------------------------------\n// Static generation orchestration (runs after Vite build)\n// ---------------------------------------------------------------------------\n\ninterface StaticGenerateModule {\n __timber_generateStaticSite?: (\n options: StaticGenerationOptions\n ) => Promise<StaticGenerationSummary>;\n}\n\n/**\n * A port as Node actually hands it over: `unref()` is a Node addition the DOM\n * lib type does not declare. Optional rather than asserted, so a runtime whose\n * `MessageChannel` has no such method is simply skipped instead of throwing.\n */\ntype ReleasablePort = MessagePort & { unref?: () => void };\n\n/**\n * Run `fn` with `MessageChannel` instrumented, then stop every channel opened\n * while it ran from holding the process open.\n *\n * Static generation is the only build pass that renders **HTML** in the build\n * process: it imports the built app bundle and drives the full SSR pipeline\n * through it. React's scheduler opens a `MessageChannel` at module scope in\n * that bundle (`scheduler`'s DOM build) and never closes it, and a ref'd\n * `MessagePort` keeps Node's event loop alive on its own — so `timber build`\n * finished the site, printed its summary, and then hung forever. Server-mode\n * builds are unaffected because nothing there renders through react-dom.\n *\n * `unref()` is the whole fix: it leaves the port working and only drops the\n * \"keep the process alive\" property. It is applied **after** `fn` resolves, so\n * a render in flight can never be cut short by the process exiting under it —\n * an unref'd port would let Node exit while the scheduler still had a\n * continuation queued, which is a silently truncated page rather than a hang.\n *\n * Nothing renders after this pass. If that ever changes, the release has to\n * move to the end of whatever renders last.\n *\n * @internal Exported for testing.\n */\nexport async function withSchedulerPortsReleased<T>(fn: () => Promise<T>): Promise<T> {\n const opened: ReleasablePort[] = [];\n const OriginalMessageChannel = globalThis.MessageChannel;\n\n globalThis.MessageChannel = class extends OriginalMessageChannel {\n constructor() {\n super();\n opened.push(this.port1, this.port2);\n }\n };\n\n try {\n return await fn();\n } finally {\n globalThis.MessageChannel = OriginalMessageChannel;\n for (const port of opened) port.unref?.();\n }\n}\n\n/** The pre-rendered site a static generation pass wrote. */\nexport interface StaticSite {\n pages: DirectoryArtifact;\n /** Content-Type per URL path for extensionless API outputs (TIM-1241). */\n contentTypes: Record<string, string>;\n /** `[RSC_PAYLOAD_DIR]` when payloads were written and content-hashed, else none. */\n immutableDirs: string[];\n}\n\n/**\n * Load the built RSC entry and run the static generation pass — the static\n * generation step of the post-build phase (plugins/post-build.ts).\n *\n * The build manifest it renders with is already final: the phase merged the\n * RSC assets manifest into it and published it before this step. Unlike\n * prebuilt capture, this needs the FULL pipeline handler, so\n * __TIMBER_CAPTURE_MODE__ must be false.\n *\n * Returns the site only once it is complete, so an adapter is never handed a\n * directory a failed pass left half-written — a failure throws instead.\n */\nexport async function runStaticGeneration(ctx: PluginContext, rscDir: string): Promise<StaticSite> {\n const entryPath = join(rscDir, 'index.js');\n warnUnusableBase(ctx);\n\n // Ensure capture mode is off — we need the full handler.\n (globalThis as Record<string, unknown>).__TIMBER_CAPTURE_MODE__ = false;\n\n console.log('[timber] Static generation: building site…');\n\n const staticDir = join(ctx.buildDir, 'static-pages');\n await cleanConditionalArtifacts(staticDir);\n await mkdir(staticDir, { recursive: true });\n\n const sitemapConfig = ctx.config.sitemap;\n const autoSitemapEnabled = Boolean(sitemapConfig?.enabled && sitemapConfig?.baseUrl);\n\n const writer = new StaticSiteWriter(staticDir, await detectFsIdentity(staticDir));\n // Route params are not collected here any more. They used to be lifted off\n // the generated entry's response headers and inlined into the manifest,\n // because a `.rsc` file carries no headers and the manifest was the only\n // channel a static SPA navigation had (TIM-1255, TIM-1285). The params are\n // now inside the payload itself — a field on its root row — so the `.rsc`\n // file carries them and there is nothing to lift (TIM-1294).\n\n // The app bundle is imported and rendered inside this wrapper, and only\n // inside it: everything it opens to schedule React work is released on the\n // way out so the build process can exit.\n const summary = await withSchedulerPortsReleased(async () => {\n let mod: StaticGenerateModule;\n try {\n const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;\n mod = (await import(/* @vite-ignore */ entryUrl)) as StaticGenerateModule;\n } catch (error) {\n // A missing entry lands here too: the import is the existence check.\n throw new Error(\n `[timber] Static generation: failed to load the built RSC entry (${entryPath}). ` +\n `The full request handler must initialize for static rendering.`,\n { cause: error }\n );\n }\n\n const generate = mod.__timber_generateStaticSite;\n if (typeof generate !== 'function') {\n throw new Error(\n `[timber] Static generation: built RSC entry does not export ` +\n `__timber_generateStaticSite — rebuild from a clean build directory`\n );\n }\n\n return generate({\n autoSitemapEnabled,\n renderTimeoutMs: ctx.config.renderTimeoutMs,\n onEntry: (entry: StaticPageEntry) => writer.write(entry),\n });\n });\n\n const totalUrls = summary.rendered + summary.errors.length;\n console.log(\n `[timber] Static generation: rendered ${summary.rendered}/${totalUrls} entries.` +\n (summary.errors.length > 0 ? ` ${summary.errors.length} failed.` : '') +\n (summary.redirects.length > 0 ? ` ${summary.redirects.length} redirect(s).` : '')\n );\n\n // Warnings are non-fatal but must not be buried in the per-entry log stream —\n // they name a degraded artifact the developer is about to deploy (TIM-1258).\n for (const warning of summary.warnings) {\n console.warn(`[timber] Static generation warning: ${warning}`);\n }\n\n if (summary.errors.length > 0) {\n const details = summary.errors.map((e) => ` - ${e.urlPath}: ${e.message}`).join('\\n');\n throw new Error(`[timber] Static generation failed:\\n${details}`);\n }\n\n // Raised after the render errors above: a collision means the site is\n // ambiguous, not that a page failed, and the message names both routes.\n writer.assertNoCollisions();\n\n // Hash RSC flight payloads for immutable caching (TIM-1254).\n // Renames _rsc/*.rsc → _rsc/*-<hash>.rsc and injects a manifest\n // into each HTML file so the client can resolve hashed URLs.\n // Skip when client JS is disabled — no SPA navigation, no RSC fetches,\n // and injecting a <script> tag would violate the no-JS contract.\n const immutableDirs: string[] = [];\n if (!ctx.clientJavascript.disabled) {\n const rscManifest = await hashRscPayloads(staticDir);\n if (Object.keys(rscManifest).length > 0) {\n immutableDirs.push(RSC_PAYLOAD_DIR);\n await injectRscManifestIntoHtml(staticDir, rscManifest);\n console.log(\n `[timber] Static generation: hashed ${Object.keys(rscManifest).length} RSC flight payloads`\n );\n }\n }\n\n // Write _redirects file for platform redirect rules (Cloudflare Pages,\n // Netlify, etc.). Format: /from /to status. See TIM-1245.\n if (summary.redirects.length > 0) {\n const generated = generateRedirectsFile(summary.redirects, normalizeBasePath(ctx.base));\n const redirectsPath = join(staticDir, REDIRECTS_FILE);\n\n // Merge with user-authored _redirects if present. TIM-1249.\n const userRedirects = await readUserRedirects(ctx.root);\n if (userRedirects !== null) {\n await writeFileAtomic(redirectsPath, generated + '\\n' + userRedirects);\n console.log(\n `[timber] Static generation: wrote _redirects with ${summary.redirects.length} ` +\n `generated rule(s), merged with user-authored _redirects`\n );\n } else {\n await writeFileAtomic(redirectsPath, generated);\n console.log(\n `[timber] Static generation: wrote _redirects with ${summary.redirects.length} rule(s)`\n );\n }\n }\n\n // Content types travel with the site because they describe it: a static\n // host cannot infer the type of an extensionless API output (TIM-1241).\n return { pages: { path: staticDir }, contentTypes: writer.contentTypes, immutableDirs };\n}\n\n// ---------------------------------------------------------------------------\n// Base path validation (TIM-1261)\n// ---------------------------------------------------------------------------\n\n/**\n * Warn when Vite's `base` is document-relative (`'./'`) in static mode.\n *\n * Payload URLs are addressed from the deployment root plus the base prefix.\n * A relative base gives no prefix to compute (see shared/base-path.ts), so\n * `/_rsc/about.rsc` is requested at the domain root — correct only when the\n * site is served from there. The build still succeeds: relative bases work\n * fine for assets, and for a root-served site nothing is wrong. The warning\n * exists so a sub-path deployment does not silently degrade to a hard\n * navigation on every link.\n *\n * Skipped when client JS is disabled — there is no SPA navigation and no\n * payload fetch to mis-address.\n *\n * @internal Exported for testing.\n */\nexport function warnUnusableBase(ctx: PluginContext): void {\n if (ctx.clientJavascript.disabled) return;\n if (!isRelativeBase(ctx.base)) return;\n console.warn(\n `[timber] Static mode: base is \"${ctx.base}\", which is document-relative. ` +\n `RSC payload URLs are addressed from the domain root, so client-side ` +\n `navigation will fall back to a full page load if the site is served ` +\n `from a sub-path. Use an absolute base (e.g. base: '/repo/') to deploy ` +\n `under a sub-path. See design/11-platform.md.`\n );\n}\n\n// ---------------------------------------------------------------------------\n// RSC flight payload hashing (TIM-1254)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a short content hash for immutable caching.\n * Uses 8 chars of base64url-encoded SHA-256, matching Vite's asset hash style.\n */\nexport function contentHash(data: Buffer | Uint8Array): string {\n return createHash('sha256').update(data).digest('base64url').slice(0, 8);\n}\n\n/**\n * Walk a directory recursively and return all file paths.\n */\nasync function walkDir(dir: string): Promise<string[]> {\n const results: string[] = [];\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await walkDir(full)));\n } else {\n results.push(full);\n }\n }\n return results;\n}\n\n/**\n * Hash all RSC flight payloads in `_rsc/`, rename them with content\n * hashes, and build a manifest with optional inlined route params.\n *\n * Before: `_rsc/index.rsc`, `_rsc/about.rsc`\n * After: `_rsc/index-B7YxEKdN.rsc`, `_rsc/about-C8ZzFLfO.rsc`\n *\n * The manifest maps the original `_rsc/` URL to an entry object:\n * `{\"/_rsc/index.rsc\":{\"url\":\"/_rsc/index-B7YxEKdN.rsc\"}, ...}`\n *\n * Keys and URLs are **route-space**: root-relative, never carrying Vite's\n * `base`. The client applies the base once, at fetch time\n * (`client/rsc-fetch.ts` → `toStaticRscUrl`), so the generated site stays\n * relocatable and the base has exactly one expression at runtime rather\n * than two that must agree. See TIM-1261.\n *\n * Route params (from `routeParams`) are inlined into the manifest\n * entry, eliminating the need for .params.json sidecar files. TIM-1255.\n *\n * Injected into HTML as:\n * `<script>window.__TIMBER_RSC_MANIFEST__={...}</script>`\n *\n * @internal Exported for testing.\n */\nexport async function hashRscPayloads(staticDir: string): Promise<RscManifest> {\n const rscDir = join(staticDir, RSC_PAYLOAD_DIR);\n const files = await walkDir(rscDir);\n const manifest: RscManifest = {};\n\n for (const filePath of files) {\n if (!filePath.endsWith('.rsc')) continue;\n\n const content = await readFile(filePath);\n const hash = contentHash(content);\n const rel = relative(staticDir, filePath).replace(/\\\\/g, '/');\n\n const base = filePath.slice(0, -'.rsc'.length);\n const hashedPath = `${base}-${hash}.rsc`;\n\n await rename(filePath, hashedPath);\n\n const hashedRel = relative(staticDir, hashedPath).replace(/\\\\/g, '/');\n const key = `/${rel}`;\n manifest[key] = { url: `/${hashedRel}` };\n }\n\n return manifest;\n}\n\n/**\n * Inject the RSC manifest into all HTML files as a `<script>` tag\n * before `</head>`. This lets the client resolve hashed RSC URLs\n * without an extra network request.\n *\n * @internal Exported for testing.\n */\nexport async function injectRscManifestIntoHtml(\n staticDir: string,\n manifest: RscManifest\n): Promise<void> {\n const allFiles = await walkDir(staticDir);\n const htmlFiles = allFiles.filter((f) => f.endsWith('.html'));\n const escapedJson = htmlEscapeJsonString(JSON.stringify(manifest));\n const scriptTag = `<script>window.__TIMBER_RSC_MANIFEST__=${escapedJson}</script>`;\n\n for (const htmlFile of htmlFiles) {\n let html = await readFile(htmlFile, 'utf-8');\n // Insert before </head> so it's available before any client JS runs\n const headClose = html.indexOf('</head>');\n if (headClose !== -1) {\n html = html.slice(0, headClose) + scriptTag + html.slice(headClose);\n } else {\n // Fallback: prepend to body\n html = scriptTag + html;\n }\n await writeFile(htmlFile, html);\n }\n}\n\n// ---------------------------------------------------------------------------\n// User-authored _redirects merge (TIM-1249)\n// ---------------------------------------------------------------------------\n\n/**\n * Read a user-authored `_redirects` file from the project's `public/`\n * directory. Returns `null` if no file exists.\n *\n * @internal Exported for testing.\n */\nexport async function readUserRedirects(root: string): Promise<string | null> {\n const candidates = [join(root, 'public', REDIRECTS_FILE)];\n for (const path of candidates) {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n // File doesn't exist — try next\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Vite Plugin\n// ---------------------------------------------------------------------------\n\n/**\n * Create the timber-static-build Vite plugin.\n *\n * Only active when output: 'static' is configured. Validates source files\n * for static mode violations; rendering the site is `runStaticGeneration`,\n * which the post-build phase calls.\n */\nexport function timberStaticBuild(ctx: PluginContext): Plugin {\n return {\n name: 'timber-static-build',\n\n /**\n * Validate source files during transform.\n *\n * In static mode, we check every app/ file for:\n * - Dynamic API usage (getCookies(), getHeaders()) → build error\n */\n transform(code: string, id: string) {\n // Read ctx.config lazily inside the hook — not at plugin construction\n // time — so file-based config from timber.config.ts is respected.\n // See TIM-451.\n const isStatic = ctx.config.output === 'static';\n\n // Only active in static mode\n if (!isStatic) return null;\n\n // Skip node_modules\n if (id.includes('node_modules')) return null;\n\n // Only check files in the app directory\n if (!id.includes('/app/') && !id.startsWith('app/')) return null;\n\n // Only check JS/TS files\n if (!/\\.[jt]sx?$/.test(id)) return null;\n\n const errors = detectDynamicApis(code, id);\n\n if (errors.length > 0) {\n // Format all errors into a single build error message\n const messages = errors.map(\n (e) =>\n `[timber] Static mode error in ${e.file}${e.line ? `:${e.line}` : ''}: ${e.message}`\n );\n\n this.error(messages.join('\\n\\n'));\n }\n\n return null;\n },\n };\n}\n","/**\n * timber-build-manifest — Vite sub-plugin for build asset manifest generation.\n *\n * Provides `virtual:timber-build-manifest` which exports a BuildManifest\n * mapping route segment file paths to their CSS, JS, and modulepreload\n * output chunks.\n *\n * - Dev mode: exports an empty manifest (Vite HMR handles CSS/JS).\n * - Build mode: virtual module reads from globalThis.__TIMBER_BUILD_MANIFEST__\n * at runtime. The actual manifest data is injected by the adapter via a\n * _timber-manifest-init.js module that runs before the RSC handler.\n *\n * The generateBundle hook (client env only) extracts CSS/JS/modulepreload\n * data from the Rollup bundle and populates ctx.buildManifest.\n *\n * Design docs: 18-build-system.md §\"Build Manifest\", 02-rendering-pipeline.md §\"Early Hints\"\n */\n\nimport { randomUUID, createHash } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { EMPTY_BUILD_MANIFEST, type BuildManifest } from '../server/build-manifest.ts';\nimport type { SegmentNode, RouteFile } from '../routing/types.ts';\nimport { isDynamicMetadataExtension } from '../server/metadata-routes.ts';\n\n// Rollup types used by generateBundle hook — imported from vite which re-exports them.\n// We define minimal interfaces here to avoid a direct 'rollup' dependency.\ninterface OutputChunk {\n type: 'chunk';\n fileName: string;\n facadeModuleId: string | null;\n imports: string[];\n name: string;\n code: string;\n viteMetadata?: { importedCss?: Set<string> };\n modules?: Record<string, { code: string | null; renderedLength: number }>;\n}\n\ninterface OutputAsset {\n type: 'asset';\n fileName: string;\n}\n\ntype OutputBundle = Record<string, OutputChunk | OutputAsset>;\n\nconst VIRTUAL_MODULE_ID = 'virtual:timber-build-manifest';\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n/**\n * Vite's manifest.json entry shape (subset we need).\n * See https://vite.dev/guide/backend-integration.html\n */\ninterface ViteManifestEntry {\n file: string;\n css?: string[];\n imports?: string[];\n}\n\n/**\n * Parse Vite's .vite/manifest.json into a BuildManifest.\n *\n * Walks each entry and collects:\n * - `css`: CSS output URLs per input file (transitive CSS included by Vite)\n * - `js`: Hashed JS chunk URL per input file\n * - `modulepreload`: Transitive JS dependency URLs per input file\n *\n * Keys are input file paths (relative to project root).\n */\nexport function parseViteManifest(\n viteManifest: Record<string, ViteManifestEntry>,\n base: string\n): BuildManifest {\n const css: Record<string, string[]> = {};\n const js: Record<string, string> = {};\n const modulepreload: Record<string, string[]> = {};\n\n for (const [inputPath, entry] of Object.entries(viteManifest)) {\n // JS chunk mapping\n js[inputPath] = base + entry.file;\n\n // CSS mapping\n if (entry.css && entry.css.length > 0) {\n css[inputPath] = entry.css.map((cssPath) => base + cssPath);\n }\n\n // Collect transitive JS dependencies for modulepreload\n modulepreload[inputPath] = collectTransitiveDeps(inputPath, viteManifest, base);\n }\n\n return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };\n}\n\n/**\n * Recursively collect transitive JS dependency URLs for an entry.\n *\n * Walks the `imports` graph in Vite's manifest, resolving each import\n * key to its output `file` URL. Deduplicates to avoid cycles and\n * redundant preloads.\n */\nfunction collectTransitiveDeps(\n entryKey: string,\n manifest: Record<string, ViteManifestEntry>,\n base: string\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n\n function walk(key: string) {\n const entry = manifest[key];\n if (!entry?.imports) return;\n\n for (const importKey of entry.imports) {\n if (seen.has(importKey)) continue;\n seen.add(importKey);\n\n const dep = manifest[importKey];\n if (dep) {\n result.push(base + dep.file);\n walk(importKey);\n }\n }\n }\n\n walk(entryKey);\n return result;\n}\n\n/**\n * Build a BuildManifest from a Rollup output bundle.\n *\n * Unlike parseViteManifest (which reads Vite's manifest.json), this\n * works directly with the Rollup bundle output. This is necessary because\n * the RSC plugin doesn't produce a standard Vite manifest.json.\n *\n * Walks each chunk in the bundle and collects:\n * - `css`: CSS files imported by each chunk (via viteMetadata.importedCss)\n * - `js`: The output filename for each chunk with a facadeModuleId\n * - `modulepreload`: Transitive JS imports for each entry chunk\n *\n * Keys are input file paths relative to root.\n */\nexport function buildManifestFromBundle(\n bundle: OutputBundle,\n base: string,\n root: string\n): BuildManifest {\n const css: Record<string, string[]> = {};\n const js: Record<string, string> = {};\n const modulepreload: Record<string, string[]> = {};\n\n // Build a map of chunk fileName → chunk for transitive dep resolution\n const chunksByFileName = new Map<string, OutputChunk>();\n for (const item of Object.values(bundle) as (OutputChunk | OutputAsset)[]) {\n if (item.type === 'chunk') {\n chunksByFileName.set(item.fileName, item);\n }\n }\n\n for (const item of Object.values(bundle) as (OutputChunk | OutputAsset)[]) {\n if (item.type !== 'chunk') continue;\n\n const chunk = item;\n if (!chunk.facadeModuleId) continue;\n\n // Convert absolute facadeModuleId to root-relative path\n let inputPath = chunk.facadeModuleId;\n if (inputPath.startsWith(root)) {\n inputPath = inputPath.slice(root.length + 1);\n }\n\n // JS chunk mapping\n js[inputPath] = base + chunk.fileName;\n\n // CSS mapping via viteMetadata\n const viteMetadata = chunk.viteMetadata;\n if (viteMetadata?.importedCss && viteMetadata.importedCss.size > 0) {\n css[inputPath] = Array.from(viteMetadata.importedCss).map((cssFile) => base + cssFile);\n }\n\n // Collect transitive JS dependencies for modulepreload\n const deps = collectTransitiveBundleDeps(chunk, chunksByFileName, base);\n if (deps.length > 0) {\n modulepreload[inputPath] = deps;\n }\n }\n\n return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };\n}\n\n/**\n * Recursively collect transitive JS dependency URLs from a bundle chunk.\n */\nfunction collectTransitiveBundleDeps(\n chunk: OutputChunk,\n chunksByFileName: Map<string, OutputChunk>,\n base: string\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n\n function walk(imports: string[]) {\n for (const importFileName of imports) {\n if (seen.has(importFileName)) continue;\n seen.add(importFileName);\n\n result.push(base + importFileName);\n const dep = chunksByFileName.get(importFileName);\n if (dep) {\n walk(dep.imports);\n }\n }\n }\n\n walk(chunk.imports);\n return result;\n}\n\n/**\n * Walk the route tree and compute short content hashes for metadata route files\n * (opengraph-image, icon, apple-icon) used for cache-busting\n * the auto-linked URLs in <head>.\n */\nfunction computeMetadataRouteHashes(node: SegmentNode<RouteFile>): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n if (node.metadataRoutes) {\n for (const [baseName, file] of Object.entries(node.metadataRoutes)) {\n if (!isDynamicMetadataExtension(baseName, file.extension)) {\n // For static files, hash the file content\n try {\n const content = readFileSync(file.filePath);\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n hashes[file.filePath] = hash;\n } catch {\n // File unreadable — skip hash, DEV_NONCE fallback applies\n }\n } else {\n // For dynamic files (.ts/.tsx), hash the source file as a reasonable\n // approximation — the output depends on runtime data too, but the\n // source change is the best build-time signal we have.\n try {\n const content = readFileSync(file.filePath);\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n hashes[file.filePath] = hash;\n } catch {\n // File unreadable — skip\n }\n }\n }\n }\n\n for (const child of node.children) {\n Object.assign(hashes, computeMetadataRouteHashes(child));\n }\n for (const slot of Object.values(node.slots)) {\n Object.assign(hashes, computeMetadataRouteHashes(slot));\n }\n\n return hashes;\n}\n\n// Regex to extract client reference hash keys from registerClientReference calls.\n// Matches: registerClientReference(..., \"abc123def456\", \"ExportName\")\nconst CLIENT_REF_KEY_RE = /registerClientReference\\([^,]+,\\s*\"([0-9a-f]{12})\"/g;\n\n/**\n * Collect all route file paths (layout, page) from the route tree.\n */\nfunction collectRouteFilePaths(node: SegmentNode<RouteFile>): string[] {\n const paths: string[] = [];\n if (node.layout) paths.push(node.layout.filePath);\n if (node.page) paths.push(node.page.filePath);\n for (const child of node.children) paths.push(...collectRouteFilePaths(child));\n for (const slot of Object.values(node.slots)) paths.push(...collectRouteFilePaths(slot));\n return paths;\n}\n\n/**\n * Scan RSC bundle chunks to find which modules contain registerClientReference\n * calls, and extract the reference hash keys from each.\n */\nfunction buildClientRefIndex(bundle: OutputBundle): Map<string, string[]> {\n const index = new Map<string, string[]>();\n for (const item of Object.values(bundle)) {\n if (item.type !== 'chunk' || !item.modules) continue;\n for (const [moduleId, mod] of Object.entries(item.modules)) {\n if (!mod.code) continue;\n const keys: string[] = [];\n for (const match of mod.code.matchAll(CLIENT_REF_KEY_RE)) {\n keys.push(match[1]);\n }\n if (keys.length > 0) {\n index.set(moduleId, keys);\n }\n }\n }\n return index;\n}\n\n/** Rollup getModuleInfo shape (subset). */\ninterface ModuleInfo {\n importedIds: string[];\n}\n\n/**\n * Walk a module's transitive imports to collect all client reference\n * keys reachable from it.\n */\nfunction walkModuleImports(\n moduleId: string,\n clientRefIndex: Map<string, string[]>,\n visited: Set<string>,\n result: Set<string>,\n getModuleInfo: (id: string) => ModuleInfo | null\n): void {\n if (visited.has(moduleId)) return;\n visited.add(moduleId);\n\n const refKeys = clientRefIndex.get(moduleId);\n if (refKeys) {\n for (const key of refKeys) result.add(key);\n }\n\n const info = getModuleInfo(moduleId);\n if (!info) return;\n for (const importedId of info.importedIds) {\n walkModuleImports(importedId, clientRefIndex, visited, result, getModuleInfo);\n }\n}\n\n/**\n * Create the timber-build-manifest Vite plugin.\n *\n * Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)\n */\nexport function timberBuildManifest(ctx: PluginContext): Plugin {\n let isDev = false;\n\n return {\n name: 'timber-build-manifest',\n\n configResolved(config: ResolvedConfig) {\n isDev = config.command === 'serve';\n\n // Generate a per-build deployment ID early so virtual:timber-config\n // can serialize it during the load hook (which runs before generateBundle).\n // A random UUID is used instead of a content hash — determinism provides\n // no real benefit here since you almost never redeploy identical code,\n // and a random ID avoids the timing problem where the content hash was\n // only available after generateBundle (TIM-452).\n if (!isDev && !ctx.deploymentId) {\n ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);\n }\n },\n\n resolveId(id: string) {\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (cleanId === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n if (cleanId.endsWith(`/${VIRTUAL_MODULE_ID}`)) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n return null;\n },\n\n load(id: string) {\n if (id !== RESOLVED_VIRTUAL_ID) return null;\n\n // Serialized, not restated: an empty manifest is described once, in\n // server/build-manifest.ts. Both branches below emitted their own object\n // literal and had already drifted apart — see EMPTY_BUILD_MANIFEST.\n const empty = JSON.stringify(EMPTY_BUILD_MANIFEST);\n\n // In dev mode, return empty manifest — Vite HMR handles CSS.\n if (isDev) {\n return [\n '// Auto-generated build manifest — do not edit.',\n '// Dev mode: empty manifest (Vite HMR handles CSS/JS).',\n '',\n `const manifest = ${empty};`,\n '',\n 'export default manifest;',\n ].join('\\n');\n }\n\n // In production, read from globalThis at runtime.\n // The adapter writes a _timber-manifest-init.js that sets this global\n // before the RSC handler imports this module. ESM evaluation order\n // guarantees the global is set by the time this code runs.\n //\n // The literal is only reached when the global is unset — an app built\n // with no adapter, which writes no init module. It is NOT the map the\n // build computed; that lives in _timber-manifest-init.js (TIM-1300).\n return [\n '// Auto-generated build manifest — do not edit.',\n '// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',\n '// The object below is only the fallback for when that global is unset —',\n '// the real manifest, including the requestDep map, is in that init module.',\n '',\n `const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? ${empty};`,\n '',\n 'export default manifest;',\n ].join('\\n');\n },\n\n // Extract manifest data from the client bundle only.\n // The RSC plugin runs builds in order: RSC → client → SSR.\n // We only want client env data (CSS assets, client JS chunks).\n generateBundle(_options, bundle) {\n if (isDev) return;\n\n const envName = (this as { environment?: { name: string } }).environment?.name;\n\n // RSC environment: walk the module graph to find which client\n // references each route file transitively imports. Store the\n // mapping in ctx so the post-build phase can cross-reference\n // with clientReferenceDeps to populate per-route modulepreloads.\n if (envName === 'rsc' && ctx.routeTree) {\n const clientRefIndex = buildClientRefIndex(bundle);\n if (clientRefIndex.size > 0) {\n const routeFiles = collectRouteFilePaths(ctx.routeTree.root);\n const routeClientRefKeys = new Map<string, Set<string>>();\n\n const getInfo = (id: string) =>\n (this as { getModuleInfo?: (id: string) => ModuleInfo | null }).getModuleInfo?.(id) ??\n null;\n\n for (const filePath of routeFiles) {\n const refKeys = new Set<string>();\n walkModuleImports(filePath, clientRefIndex, new Set(), refKeys, getInfo);\n if (refKeys.size > 0) {\n routeClientRefKeys.set(filePath, refKeys);\n }\n }\n\n if (routeClientRefKeys.size > 0) {\n ctx.routeClientRefKeys = routeClientRefKeys;\n }\n }\n }\n\n if (envName === 'client') {\n ctx.buildManifest = buildManifestFromBundle(bundle, ctx.base, ctx.root);\n\n // Compute cache-busting hashes for metadata route files\n if (ctx.routeTree) {\n ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);\n }\n\n // Attach the static request-dependency map from the request-dep\n // plugin, computed in the RSC `buildEnd` hook. The RSC environment is\n // built before the client one, so the field is populated by now.\n //\n // Absent means the RSC `buildEnd` never ran — a broken plugin pipeline,\n // not an app without segments, which produces `{}`. Serializing that as\n // an empty map is indistinguishable at runtime from an analysis that\n // found nothing (`server/request-dep.ts` answers `true` for any absent\n // key either way), so every segment and slot silently stops being a\n // skip candidate and slot caching is off with nothing to show for it.\n // Fail the build instead (TIM-1300).\n if (ctx.requestDepMap === undefined) {\n throw new Error(\n '[timber] Build manifest: the request-dependency map was never computed. ' +\n \"The RSC environment's buildEnd hook did not run before the client build, \" +\n 'so no segment or slot could be skipped on client navigation. This is a ' +\n 'plugin pipeline bug — timber-request-dep must run in the rsc environment.'\n );\n }\n ctx.buildManifest.requestDep = ctx.requestDepMap;\n\n // When client JavaScript is disabled, strip JS chunks from the bundle\n // so Rollup never writes them to disk. CSS assets are preserved —\n // they're still needed for server-rendered HTML. The JS references\n // in the manifest are stripped once, by the post-build phase, after\n // it has merged in everything else (plugins/post-build.ts).\n if (ctx.clientJavascript.disabled) {\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type === 'chunk') {\n delete bundle[fileName];\n }\n }\n }\n }\n },\n };\n}\n","/**\n * timber-dev-logs — Pipes server console output to the browser console in dev.\n *\n * Patches `console.log/warn/error/debug/info` on the server side and\n * forwards messages to connected browsers via Vite's HMR WebSocket.\n * The browser entry replays them in the browser console with the\n * correct log level and a \"[server]\" prefix.\n *\n * Dev-only: this plugin only runs during `vite dev` (apply: 'serve').\n * No runtime overhead in production.\n *\n * Design docs: 18-build-system.md §\"Dev Server\", 02-rendering-pipeline.md\n */\n\nimport type { Plugin, ViteDevServer, Logger } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\n// ─── Original Console Snapshot ──────────────────────────────────────────\n\n/**\n * Snapshot of the original console methods, captured at module load time\n * (before any patching). Used as Vite's `customLogger` console so that\n * forwardConsole output bypasses our patch entirely — eliminating the\n * server→browser→server forwarding loop without string matching.\n */\nexport const originalConsole: Pick<Console, 'log' | 'warn' | 'error' | 'debug' | 'info'> = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n};\n\n/**\n * Wrap a Vite Logger so its output methods route through `originalConsole`\n * instead of the global (potentially patched) console. This prevents the\n * server→browser→server forwarding loop even when the user supplies their\n * own `customLogger` that internally calls console methods.\n */\nexport function wrapLoggerWithOriginalConsole(logger: Logger): Logger {\n // Swap all patched console methods to originals during any logger call,\n // since user loggers may call any combination of console methods internally.\n function withOriginals<T>(fn: () => T): T {\n const saved = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n info: console.info,\n };\n console.log = originalConsole.log;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.debug = originalConsole.debug;\n console.info = originalConsole.info;\n try {\n return fn();\n } finally {\n console.log = saved.log;\n console.warn = saved.warn;\n console.error = saved.error;\n console.debug = saved.debug;\n console.info = saved.info;\n }\n }\n\n return {\n get hasWarned() {\n return logger.hasWarned;\n },\n set hasWarned(v) {\n logger.hasWarned = v;\n },\n info(msg, opts) {\n withOriginals(() => logger.info(msg, opts));\n },\n warn(msg, opts) {\n withOriginals(() => logger.warn(msg, opts));\n },\n warnOnce(msg, opts) {\n withOriginals(() => logger.warnOnce(msg, opts));\n },\n error(msg, opts) {\n withOriginals(() => logger.error(msg, opts));\n },\n clearScreen(type) {\n logger.clearScreen(type);\n },\n hasErrorLogged(error) {\n return logger.hasErrorLogged(error);\n },\n };\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/** Log levels that are patched and forwarded. */\nexport type ServerLogLevel = 'log' | 'warn' | 'error' | 'debug' | 'info';\n\nconst LOG_LEVELS: ServerLogLevel[] = ['log', 'warn', 'error', 'debug', 'info'];\n\n/** Payload sent over Vite's HMR WebSocket. */\nexport interface ServerLogPayload {\n level: ServerLogLevel;\n args: unknown[];\n /** Server-side source location (file:line:col) if available. */\n location: string | null;\n /** Timestamp in ms (Date.now()) */\n timestamp: number;\n}\n\n// ─── Serialization ───────────────────────────────────────────────────────\n\n/** Patterns that look like env vars or secrets — these are redacted. */\nconst SENSITIVE_PATTERNS =\n /(?:^|[^a-z])(?:SECRET|TOKEN|PASSWORD|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL|SESSION_SECRET)(?:[^a-z]|$)/i;\n\n/**\n * Serialize a console argument for transmission over WebSocket.\n *\n * Handles: strings, numbers, booleans, null, undefined, arrays, plain\n * objects, Errors, Dates, RegExps, and falls back to String() for others.\n *\n * Redacts values that match sensitive patterns to avoid leaking secrets.\n */\nfunction serializeArg(arg: unknown, depth = 0): unknown {\n if (depth > 5) return '[...]';\n\n if (arg === null) return null;\n if (arg === undefined) return '[undefined]';\n\n switch (typeof arg) {\n case 'string':\n if (SENSITIVE_PATTERNS.test(arg)) return '[REDACTED]';\n return arg;\n case 'number':\n case 'boolean':\n return arg;\n case 'bigint':\n return `${arg}n`;\n case 'symbol':\n return arg.toString();\n case 'function':\n return `[Function: ${arg.name || 'anonymous'}]`;\n case 'object':\n break;\n default:\n return String(arg);\n }\n\n // Error\n if (arg instanceof Error) {\n return {\n __type: 'Error',\n name: arg.name,\n message: arg.message,\n stack: arg.stack ?? null,\n };\n }\n\n // Date\n if (arg instanceof Date) {\n return arg.toISOString();\n }\n\n // RegExp\n if (arg instanceof RegExp) {\n return arg.toString();\n }\n\n // Array\n if (Array.isArray(arg)) {\n return arg.map((item) => serializeArg(item, depth + 1));\n }\n\n // Map\n if (arg instanceof Map) {\n const entries: Record<string, unknown> = {};\n for (const [key, value] of arg) {\n entries[String(key)] = serializeArg(value, depth + 1);\n }\n return { __type: 'Map', entries };\n }\n\n // Set\n if (arg instanceof Set) {\n return { __type: 'Set', values: [...arg].map((v) => serializeArg(v, depth + 1)) };\n }\n\n // Plain object\n if (Object.getPrototypeOf(arg) === Object.prototype || Object.getPrototypeOf(arg) === null) {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(arg as Record<string, unknown>)) {\n if (SENSITIVE_PATTERNS.test(key)) {\n result[key] = '[REDACTED]';\n } else {\n result[key] = serializeArg(value, depth + 1);\n }\n }\n return result;\n }\n\n // Fallback — use toString or constructor name\n try {\n return `[${(arg as object).constructor?.name ?? 'Object'}]`;\n } catch {\n return '[Object]';\n }\n}\n\n// ─── Source Location ─────────────────────────────────────────────────────\n\n/**\n * Extract the caller's source location from an Error stack trace.\n *\n * Walks the stack to find the first frame that isn't inside this file\n * or Node internals. Returns \"file:line:col\" or null.\n */\nfunction extractCallerLocation(projectRoot: string): string | null {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return null;\n\n const lines = stack.split('\\n');\n // Skip first line (\"Error\") and frames inside this module\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n // Skip our own patching frames\n if (line.includes('dev-tools/logs')) continue;\n // Skip node internals\n if (line.includes('node:') || line.includes('node_modules')) continue;\n\n // Extract file path from \"at ... (file:line:col)\" or \"at file:line:col\"\n const match = line.match(/\\((.+?):(\\d+):(\\d+)\\)/) ?? line.match(/at (.+?):(\\d+):(\\d+)/);\n if (match) {\n let filePath = match[1];\n // Make path relative to project root for readability\n if (filePath.startsWith(projectRoot)) {\n filePath = filePath.slice(projectRoot.length + 1);\n }\n return `${filePath}:${match[2]}:${match[3]}`;\n }\n }\n return null;\n}\n\n// ─── Framework-Internal Detection ────────────────────────────────────────\n\n/**\n * Check if the calling code is from timber's internal plugin/adapter plumbing.\n *\n * Only filters logs from `plugins/` and `adapters/` directories — these are\n * framework operational noise (request summaries, codegen warnings, adapter\n * setup). Logs from `server/` are preserved because they surface user errors\n * (render errors, action errors, route handler errors, etc.).\n *\n * Handles both monorepo paths (timber-app/src/plugins/) and installed\n * package paths (@timber-js/app/dist/plugins/).\n */\nexport function isFrameworkInternalCaller(): boolean {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return false;\n\n const lines = stack.split('\\n');\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n // Skip our own patching frames\n if (line.includes('dev-tools/logs')) continue;\n // Skip node internals (but NOT node_modules — we need to inspect those)\n if (line.includes('node:')) continue;\n\n // Check if this first real frame is inside timber's own source\n const isTimberPath = line.includes('timber-app/') || line.includes('@timber-js/app/');\n if (!isTimberPath) return false;\n\n // Only filter plugin and adapter internals, not server/ runtime code\n // which surfaces user errors (render errors, action errors, etc.)\n return line.includes('/plugins/') || line.includes('/adapters/');\n }\n return false;\n}\n\n// ─── Console Patching ────────────────────────────────────────────────────\n\n/**\n * Patch console methods to forward logs to the browser via HMR WebSocket.\n *\n * Each patched method:\n * 1. Calls the original console method (server terminal still works)\n * 2. Serializes arguments for JSON transport\n * 3. Sends via server.hot.send() — dropped if no clients connected\n */\nfunction patchConsole(server: ViteDevServer, projectRoot: string): () => void {\n const prevConsole = new Map<ServerLogLevel, (...args: unknown[]) => void>();\n // Per-level guard so a console.warn inside a console.error handler isn't\n // suppressed — only same-level synchronous re-entrancy is blocked.\n const patchingLevel = new Set<ServerLogLevel>();\n\n for (const level of LOG_LEVELS) {\n prevConsole.set(level, console[level].bind(console));\n\n console[level] = (...args: unknown[]) => {\n // Same-level re-entrancy guard: if prevConsole's wrapper calls back\n // into console[level], just pass through without forwarding.\n if (patchingLevel.has(level)) {\n prevConsole.get(level)!(...args);\n return;\n }\n\n patchingLevel.add(level);\n try {\n // Call the previous console method first — guarantees terminal output\n // even if serialization or forwarding fails downstream. If prevConsole\n // throws, the error propagates (not swallowed) but patchingLevel is\n // still cleaned up by the outer finally.\n prevConsole.get(level)!(...args);\n\n // Skip framework-internal logs (plugins/, adapters/) from browser forwarding.\n if (isFrameworkInternalCaller()) return;\n\n try {\n const payload: ServerLogPayload = {\n level,\n args: args.map((arg) => serializeArg(arg)),\n location: extractCallerLocation(projectRoot),\n timestamp: Date.now(),\n };\n\n server.hot.send('timber:server-log', payload);\n } catch (e) {\n originalConsole.debug(\n '[timber] server log forwarding failed:',\n e instanceof Error ? e.message : e\n );\n }\n } finally {\n patchingLevel.delete(level);\n }\n };\n }\n\n // Return a cleanup function to restore the previous console methods\n return () => {\n for (const [level, prev] of prevConsole) {\n console[level] = prev;\n }\n };\n}\n\n// ─── Plugin ──────────────────────────────────────────────────────────────\n\n/**\n * Create the timber-dev-logs Vite plugin.\n *\n * Patches console methods when the dev server starts and restores them\n * when the server closes. Only active during `vite dev`.\n */\nexport function timberDevLogs(_ctx: PluginContext): Plugin {\n let cleanup: (() => void) | null = null;\n\n return {\n name: 'timber-dev-logs',\n apply: 'serve',\n\n configureServer(server: ViteDevServer) {\n cleanup = patchConsole(server, _ctx.root);\n\n // Restore console on server close\n server.httpServer?.on('close', () => {\n cleanup?.();\n cleanup = null;\n });\n },\n };\n}\n","/**\n * Browser log forwarding — maps timber's devBrowserLogs config to Vite 8's\n * server.forwardConsole option.\n *\n * Vite 8 ships built-in browser→terminal console forwarding via\n * server.forwardConsole, which patches console methods in /@vite/client\n * and prints forwarded output server-side. This replaces timber's custom\n * client-side interception script and HMR WebSocket transport.\n *\n * Client error forwarding (overlay echo, digest filtering, componentStack)\n * remains in browser-dev.ts — Vite's forwardConsole only logs to terminal\n * and has no client-side filter hook. See TIM-1152.\n *\n * See design/21-dev-server.md §\"Browser Log Forwarding\"\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/** Log levels forwarded from the browser. */\nexport type BrowserLogLevel = 'error' | 'warn' | 'info';\n\n/** Configuration value for devBrowserLogs in timber.config.ts. */\nexport type DevBrowserLogsConfig = BrowserLogLevel | 'none' | undefined;\n\n// ─── Vite Config Mapping ─────────────────────────────────────────────────\n\n/**\n * Map timber's devBrowserLogs threshold to Vite 8's server.forwardConsole.\n *\n * Vite defaults forwardConsole OFF for non-agent dev; timber enables it\n * based on the configured threshold (default: 'warn'). The threshold acts\n * as a minimum severity — 'warn' forwards errors + warnings, 'info'\n * forwards everything, 'error' forwards only errors, 'none' disables.\n *\n * Vite's unhandledErrors is explicitly disabled — timber's own\n * setupClientErrorForwarding (browser-dev.ts) already catches window\n * error/unhandledrejection, filters framework control-flow signals\n * (redirect/deny digests) and page-unload aborts (TIM-838), and\n * echoes errors to the Vite overlay. Enabling Vite's unhandledErrors\n * would duplicate terminal output for normal errors and reintroduce\n * unfiltered noise for framework signals.\n */\nexport function resolveForwardConsole(\n threshold: DevBrowserLogsConfig\n): boolean | { unhandledErrors: boolean; logLevels: string[] } {\n const resolved = threshold ?? 'warn';\n if (resolved === 'none') return false;\n\n const logLevels: string[] = [];\n if (resolved === 'info') logLevels.push('info', 'warn', 'error');\n else if (resolved === 'warn') logLevels.push('warn', 'error');\n else logLevels.push('error');\n\n return { unhandledErrors: false, logLevels };\n}\n","import type { Plugin } from 'vite';\n\n/**\n * Redirect React's CJS development bundles to production bundles.\n *\n * React packages use a runtime `process.env.NODE_ENV` check in their CJS\n * entry points to conditionally require either `*.development.js` or\n * `*.production.js`. Rollup's CJS plugin resolves both branches statically\n * before the `define` replacement can eliminate the dead branch, causing\n * development React code to be included in production builds.\n *\n * This plugin intercepts `resolveId` and rewrites any `*.development.js`\n * import under `react/cjs/`, `react-dom/cjs/`, or `scheduler/cjs/` to\n * its `*.production.js` counterpart.\n *\n * Only active in production builds. Has no effect in dev mode.\n */\nexport function timberReactProd(): Plugin {\n let isProd = false;\n\n return {\n name: 'timber-react-prod',\n enforce: 'pre',\n configResolved(config) {\n isProd = config.command === 'build' && config.mode === 'production';\n },\n resolveId: {\n order: 'pre',\n async handler(source, importer, options) {\n if (!isProd) return;\n\n // Match: react/cjs/*.development.js, react-dom/cjs/*.development.js, scheduler/cjs/*.development.js\n if (!source.includes('.development.')) return;\n\n const resolved = await this.resolve(source, importer, {\n ...options,\n skipSelf: true,\n });\n if (!resolved) return;\n\n // Only rewrite paths inside react/react-dom/scheduler/react-server-dom CJS directories\n if (\n !resolved.id.includes('/react/cjs/') &&\n !resolved.id.includes('/react-dom/cjs/') &&\n !resolved.id.includes('/scheduler/cjs/') &&\n !resolved.id.includes('/react-server-dom/cjs/')\n ) {\n return;\n }\n\n const prodId = resolved.id.replace('.development.', '.production.');\n return { ...resolved, id: prodId };\n },\n },\n };\n}\n","/**\n * timber-react-resolve — Deduplicate React across timber and user project.\n *\n * Without this plugin, pnpm's strict isolation can install two physical\n * copies of React when the user's pinned version differs from timber's\n * peer dep. Timber's 47 bare `from 'react'` imports resolve to one copy\n * while react-dom uses the other — causing \"Invalid hook call\" hydration\n * crashes with no indication of the real cause.\n *\n * The fix: inject `resolve.dedupe` entries so Vite always resolves React\n * packages from the project root. Unlike `resolve.alias`, `dedupe`\n * preserves Vite's per-environment export conditions — the RSC\n * environment still gets the `react-server` build, SSR gets the SSR\n * build, and the browser gets the browser build. The deduplication\n * happens at the package level, not the file level.\n *\n * A `configResolved` check detects version mismatches between timber's\n * resolved React and the project's React, and logs an actionable error.\n *\n * Design doc: 18-build-system.md §\"Module Resolution\"\n * Task: TIM-1520\n */\n\nimport { createRequire } from 'node:module';\nimport { dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Plugin } from 'vite';\n\n/**\n * React packages to deduplicate. Vite's `resolve.dedupe` extracts the\n * base package name (via `deepImportRE`) before checking, so subpath\n * specifiers like `react/jsx-runtime` are covered by the base `react`\n * entry — listing them separately has no effect.\n */\nexport const REACT_DEDUPE_PACKAGES = ['react', 'react-dom'] as const;\n\n// ANSI escape codes — match config-validation.ts style\nconst RED = '\\x1b[31m';\nconst BOLD = '\\x1b[1m';\nconst DIM = '\\x1b[2m';\nconst RESET = '\\x1b[0m';\n\n/**\n * Read the version from a package's package.json given a resolve root.\n */\nfunction readPackageVersion(packageName: string, resolveRoot: string): string | null {\n try {\n const req = createRequire(`${resolveRoot}/package.json`);\n const pkgJsonPath = req.resolve(`${packageName}/package.json`);\n const pkg = req(pkgJsonPath) as { version?: string };\n return pkg.version ?? null;\n } catch {\n return null;\n }\n}\n\nexport interface ReactVersionMismatch {\n specifier: string;\n timberVersion: string;\n projectVersion: string;\n}\n\n/**\n * Check whether timber's React and the user project's React resolve to\n * the same version. Returns mismatches if any.\n */\nexport function detectReactMismatch(projectRoot: string): ReactVersionMismatch[] {\n const mismatches: ReactVersionMismatch[] = [];\n const timberRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n\n for (const pkg of ['react', 'react-dom'] as const) {\n const timberVersion = readPackageVersion(pkg, timberRoot);\n const projectVersion = readPackageVersion(pkg, projectRoot);\n\n if (timberVersion && projectVersion && timberVersion !== projectVersion) {\n mismatches.push({ specifier: pkg, timberVersion, projectVersion });\n }\n }\n\n return mismatches;\n}\n\n/**\n * Format React version mismatches as an actionable warning.\n */\nexport function formatReactMismatch(mismatches: ReactVersionMismatch[]): string {\n if (mismatches.length === 0) return '';\n\n const lines: string[] = [];\n lines.push(\n `${RED}${BOLD}[timber]${RESET} ${RED}React version mismatch detected — this causes silent hydration crashes${RESET}`\n );\n lines.push('');\n for (const m of mismatches) {\n lines.push(\n ` ${RED}✗${RESET} ${m.specifier}: timber has ${BOLD}${m.timberVersion}${RESET}, project has ${BOLD}${m.projectVersion}${RESET}`\n );\n }\n lines.push('');\n lines.push(\n ` ${DIM}This typically causes \"Invalid hook call\" errors because two copies of${RESET}`\n );\n lines.push(` ${DIM}React are loaded. timber's resolve.dedupe should handle this, but${RESET}`);\n lines.push(\n ` ${DIM}if you see hook errors, ensure your React version satisfies timber's peer dep.${RESET}`\n );\n lines.push('');\n lines.push(` ${DIM}Fix: update React in your project to match —${RESET}`);\n lines.push(\n ` ${BOLD}pnpm add react@${mismatches[0].timberVersion} react-dom@${mismatches[0].timberVersion}${RESET}`\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Create the timber-react-resolve Vite plugin.\n */\nexport function timberReactResolve(): Plugin {\n return {\n name: 'timber-react-resolve',\n enforce: 'pre',\n\n config(userConfig) {\n // Merge with any existing dedupe entries the user may have set.\n const existing = userConfig.resolve?.dedupe ?? [];\n const merged = [...existing];\n\n for (const pkg of REACT_DEDUPE_PACKAGES) {\n if (!merged.includes(pkg)) {\n merged.push(pkg);\n }\n }\n\n return {\n resolve: {\n dedupe: merged,\n },\n };\n },\n\n configResolved(resolved) {\n const mismatches = detectReactMismatch(resolved.root);\n if (mismatches.length > 0) {\n process.stderr.write(`${formatReactMismatch(mismatches)}\\n\\n`);\n }\n },\n };\n}\n","/**\n * timber-chunks — Vite sub-plugin for client chunk configuration.\n *\n * Previously implemented a 5-tier cache strategy (vendor-react, vendor-timber,\n * vendor-app, shared-app, shared-client) via manualChunks. This was removed\n * in LOCAL-337 because the cache-tier separation added HTTP requests,\n * complicated the architecture, and caused module duplication across chunks\n * that required globalThis + Symbol.for workarounds.\n *\n * Current strategy: let Rolldown handle natural code splitting.\n * Output is typically:\n * - 1 main bundle (React + timber runtime + shared app code + user vendors)\n * - Per-route chunks (page/layout components, only when route-specific)\n * - rolldown-runtime (Rolldown's own output, unavoidable)\n *\n * Additionally, this plugin builds a facade ancestry map during the RSC\n * build so that `clientChunkGroup` can reclassify `shared:` client\n * references that are only consumed by a single route boundary.\n * See TIM-1107, design/27-chunking-strategy.md.\n *\n * Design docs: 27-chunking-strategy.md\n */\n\nimport type { Plugin, Rollup } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\n/**\n * Check if a module is part of the timber framework runtime.\n *\n * Matches both monorepo paths (packages/timber-app/...) and consumer\n * project paths (node_modules/@timber-js/app/...) so identification\n * is consistent regardless of how timber is installed.\n *\n * Exported for use in tests (singleton-audit, etc.).\n */\nexport function isTimberRuntime(id: string): boolean {\n return (\n id.includes('/timber-app/') ||\n id.includes('/@timber-js/app/') ||\n id.includes('react-server-dom') ||\n id.includes('@vitejs/plugin-rsc')\n );\n}\n\ntype OutputChunk = Rollup.OutputChunk;\n\n/**\n * Build a map from absolute module IDs in non-facade RSC chunks to the\n * absolute facade module paths that transitively import them.\n *\n * Used by `clientChunkGroup` to reclassify `shared:` client references\n * that are only consumed by a single route boundary (TIM-1107).\n */\nfunction buildFacadeAncestryMap(bundle: Rollup.OutputBundle): Map<string, string[]> {\n const chunks = new Map<string, OutputChunk>();\n for (const [file, asset] of Object.entries(bundle)) {\n if (asset.type === 'chunk') chunks.set(file, asset);\n }\n\n // Reverse import graph: which chunks import this chunk file?\n const importedBy = new Map<string, string[]>();\n for (const [file, chunk] of chunks) {\n for (const imp of chunk.imports) {\n let parents = importedBy.get(imp);\n if (!parents) {\n parents = [];\n importedBy.set(imp, parents);\n }\n parents.push(file);\n }\n }\n\n // Trace upward from a chunk to find all facade modules that consume it\n function facadeAncestors(file: string, visited: Set<string>): string[] {\n if (visited.has(file)) return [];\n visited.add(file);\n const chunk = chunks.get(file);\n if (!chunk) return [];\n if (chunk.facadeModuleId) return [chunk.facadeModuleId];\n const parents = importedBy.get(file) ?? [];\n const result: string[] = [];\n for (const p of parents) {\n for (const f of facadeAncestors(p, visited)) result.push(f);\n }\n return result;\n }\n\n const moduleToFacades = new Map<string, string[]>();\n for (const [file, chunk] of chunks) {\n if (chunk.facadeModuleId) continue;\n const facades = facadeAncestors(file, new Set());\n if (facades.length === 0) continue;\n // Deduplicate facades\n const unique = [...new Set(facades)];\n for (const modId of chunk.moduleIds) {\n moduleToFacades.set(modId, unique);\n }\n }\n\n return moduleToFacades;\n}\n\n/**\n * Create the timber-chunks Vite plugin.\n *\n * Rolldown's default splitting produces the desired output (one main\n * bundle + per-route chunks). This plugin's main job is building the\n * facade ancestry map during the RSC build so `clientChunkGroup` can\n * reclassify shared client references to their correct route boundary.\n *\n * NOTE: Ideally we'd use Rolldown's `format: 'app'` (module registry format)\n * which guarantees single-copy module semantics like webpack/Turbopack.\n * However, `format: 'app'` is not yet implemented in Rolldown rc.10.\n * Until it ships, singleton state in navigation-context.ts uses\n * globalThis + Symbol.for as a cross-chunk safety net.\n *\n * Design docs: 27-chunking-strategy.md\n */\nexport function timberChunks(ctx: PluginContext): Plugin {\n return {\n name: 'timber-chunks',\n generateBundle(_options, bundle) {\n if (this.environment?.name !== 'rsc') return;\n ctx.sharedModuleFacades = buildFacadeAncestryMap(bundle);\n },\n };\n}\n","/**\n * Client chunk grouping strategy for @vitejs/plugin-rsc.\n *\n * Groups client reference modules by the **consuming route's** layout boundary\n * (derived from `meta.serverChunk`), not by the module's own file location.\n * This ensures components in shared directories (e.g. `components/`) land in\n * the chunk of the route that uses them, not in a single catch-all chunk.\n *\n * For `shared:` modules (client references in non-facade RSC chunks), the\n * function consults a facade ancestry map built during the RSC build. If all\n * consuming facades belong to the same route boundary, the module is\n * reclassified to that boundary instead of falling through to `client-shared`.\n *\n * See design/27-chunking-strategy.md, TIM-440, TIM-499, TIM-1104, TIM-1107.\n */\n\nimport { relative } from 'node:path';\n\n/**\n * Check whether a root-relative path lives under the app directory,\n * and if so return the first non-group route segment.\n *\n * `appPrefix` is the root-relative app directory with a trailing slash\n * (e.g. \"app/\" or \"src/app/\"), computed once from the resolved appDir\n * and root. Matching uses `startsWith` — no ambiguity.\n *\n * Returns:\n * { inApp: false } — path is not under app/\n * { inApp: true, segment: null } — root of app/ (e.g. app/layout.tsx)\n * { inApp: true, segment: \"dashboard\" } — nested route boundary\n */\nfunction findAppBoundary(\n path: string,\n appPrefix: string\n): { inApp: false } | { inApp: true; segment: string | null } {\n const relPath = path.replace(/\\\\/g, '/');\n if (!relPath.startsWith(appPrefix)) return { inApp: false };\n\n const withinApp = relPath.slice(appPrefix.length);\n const segments = withinApp.split('/');\n\n for (const seg of segments) {\n if (seg.includes('.')) break;\n if (seg.startsWith('(') && seg.endsWith(')')) continue;\n return { inApp: true, segment: seg };\n }\n\n return { inApp: true, segment: null };\n}\n\n/**\n * Check if a string is a bare import specifier (package name, not a path).\n * Bare specifiers don't start with `.`, `/`, or contain `:/`.\n */\nfunction isBareSpecifier(id: string): boolean {\n return !id.startsWith('.') && !id.startsWith('/') && !id.includes(':/');\n}\n\n/**\n * Look up facade ancestors for a module ID, handling bare package specifiers.\n *\n * The facade ancestry map is keyed by absolute resolved paths (from Rollup's\n * moduleIds), but the RSC plugin passes bare package names (e.g. 'streamdown')\n * as meta.id for npm package client references (TIM-1108). When a direct\n * lookup misses and the id is a bare specifier, scan map keys for a matching\n * node_modules path.\n */\nfunction lookupFacades(\n id: string,\n sharedModuleFacades: Map<string, string[]>\n): string[] | undefined {\n const direct = sharedModuleFacades.get(id);\n if (direct) return direct;\n\n if (!isBareSpecifier(id)) return undefined;\n\n // Bare specifier: match against node_modules/<name>/ in map keys.\n // Scoped packages use @scope/name, unscoped use just name.\n // A package may have multiple module IDs in the RSC bundle (e.g. main\n // entry + re-exported submodules), so aggregate facades from all matches.\n const needle = `/node_modules/${id}/`;\n let merged: string[] | undefined;\n for (const [key, facades] of sharedModuleFacades) {\n if (key.includes(needle)) {\n if (!merged) merged = [...facades];\n else merged.push(...facades);\n }\n }\n return merged;\n}\n\n/**\n * For a `shared:` client reference, check the facade ancestry map to\n * see if all consuming facades belong to the same route boundary.\n * Returns the boundary segment name, or null if the module is\n * genuinely shared across multiple boundaries.\n */\nfunction reclassifySharedModule(\n meta: { id: string; normalizedId: string },\n appPrefix: string,\n root: string,\n sharedModuleFacades: Map<string, string[]>\n): string | null {\n const facades = lookupFacades(meta.id, sharedModuleFacades);\n if (!facades || facades.length === 0) return null;\n\n const boundaries = new Set<string>();\n for (const facade of facades) {\n const relFacade = relative(root, facade).replace(/\\\\/g, '/');\n const result = findAppBoundary(relFacade, appPrefix);\n if (result.inApp && result.segment) {\n boundaries.add(result.segment);\n } else if (result.inApp) {\n // Root-level facade — module is used at root, keep shared\n return null;\n } else {\n // Facade outside app/ (e.g. src/posts/foo.mdx) — can't derive a\n // safe common boundary, so keep shared to avoid pulling outside-app\n // deps into a route chunk they don't belong to.\n return null;\n }\n }\n\n if (boundaries.size === 1) return [...boundaries][0];\n return null;\n}\n\n/**\n * Derive a chunk group name for a client reference module.\n *\n * Always derives the group from the **consuming route** (`serverChunk`'s\n * facade path), not from the module's own file location. This prevents\n * components in shared directories (e.g. `app/components/`, `src/lib/`)\n * from collapsing into a single chunk when they're only used by one route.\n *\n * For `shared:` modules (non-facade RSC chunks), consults the facade\n * ancestry map to reclassify modules that are only consumed by a single\n * route boundary. This prevents large dependencies from polluting\n * `client-shared` when they're route-scoped (TIM-1107).\n *\n * Examples:\n * - `facade:app/dashboard/settings/page.tsx` → `\"client-dashboard\"`\n * - `facade:app/(group-a)/group-page-a/page.tsx` → `\"client-group-page-a\"`\n * - `facade:app/layout.tsx` (root layout) → `\"client-shared\"`\n * - `shared:...` (shared across chunks) → reclassified or `\"client-shared\"`\n */\nexport function clientChunkGroup(\n meta: { id: string; normalizedId: string; serverChunk: string },\n appDir: string,\n root: string,\n sharedModuleFacades?: Map<string, string[]>\n): string {\n const { serverChunk } = meta;\n\n // Compute the root-relative app directory prefix once. Both normalizedId\n // and serverChunk paths from the RSC plugin are root-relative (via\n // path.relative(root, absoluteId)), so this prefix matches exactly —\n // no ambiguity with content directories that happen to share a name.\n const appPrefix = relative(root, appDir).replace(/\\\\/g, '/') + '/';\n\n if (serverChunk.startsWith('shared:')) {\n if (sharedModuleFacades) {\n const boundary = reclassifySharedModule(meta, appPrefix, root, sharedModuleFacades);\n if (boundary) return `client-${boundary}`;\n }\n return 'client-shared';\n }\n\n // Derive the group from the serverChunk's facade path — the RSC entry\n // point that references this client module. This groups by the consuming\n // route's layout boundary, not the module's own file location (TIM-1104).\n if (serverChunk.startsWith('facade:')) {\n const facadePath = serverChunk.slice('facade:'.length).replace(/\\\\/g, '/');\n const facadeResult = findAppBoundary(facadePath, appPrefix);\n if (facadeResult.inApp && facadeResult.segment) return `client-${facadeResult.segment}`;\n if (facadeResult.inApp) return 'client-shared';\n\n // Facade is outside app/ (e.g. src/posts/foo.mdx via import.meta.glob).\n // Derive a chunk name from the full facade path to keep these isolated.\n const facadeName = facadePath.replace(/\\.[^.]+$/, '').replace(/\\//g, '-');\n if (facadeName) return `client-${facadeName}`;\n }\n\n return 'client-shared';\n}\n","/**\n * timber-server-bundle — Bundle all dependencies for server environments.\n *\n * In production builds, sets `resolve.noExternal: true` for the rsc and ssr\n * environments. This ensures all npm dependencies are bundled into the output,\n * which is required for platforms like Cloudflare Workers that don't have\n * access to node_modules at runtime.\n *\n * In dev mode, Vite's default externalization is preserved for fast HMR.\n *\n * Design docs: design/11-platform.md, design/25-production-deployments.md\n */\n\nimport { builtinModules } from 'node:module';\nimport type { Plugin } from 'vite';\nimport { EXPLICIT_MARKERS } from '../analyze/poison-rules.ts';\n\n// The poison-pill marker packages (server-only, client-only) must never be\n// externalized — they have to reach the timber-shims resolveId hook so it\n// can substitute the poison virtual modules. Derived from poison-rules.ts\n// so the list cannot drift from what shims.ts intercepts.\nconst POISON_MARKER_SPECIFIERS = EXPLICIT_MARKERS.map((m) => m.specifier);\n\n// Every Node built-in as both bare (`stream`) and prefixed (`node:stream`).\n// Available at runtime on all targets (Node natively, Workers via nodejs_compat).\n// Listing explicitly silences Vite's \"Automatically externalized\" warnings.\nconst NODE_BUILTINS: string[] = builtinModules.flatMap((m) => [m, `node:${m}`]);\n\n// Packages that must never be bundled into the runtime server environments.\n// With `noExternal: true`, rolldown follows all transitive imports. These\n// are build-time-only tools that have no runtime use in a server bundle.\n//\n// The primary leak path (TIM-988) — `virtual:timber-cache-handler` importing\n// `timber.config.ts` and pulling in adapter/MDX deps — was eliminated by\n// TIM-1211: the cache handler virtual module now imports `timber.cache.ts`\n// instead. These externals are retained as defense-in-depth.\n//\n// Cloudflare runtime modules (cloudflare:workers, cloudflare:sockets, etc.)\n// available at runtime on Workers but must not be bundled.\nconst CLOUDFLARE_BUILTINS = [\n 'cloudflare:workers',\n 'cloudflare:sockets',\n 'cloudflare:email',\n 'cloudflare:workflows',\n];\n\nconst BUILD_ONLY_EXTERNALS: string[] = [\n ...NODE_BUILTINS,\n ...CLOUDFLARE_BUILTINS,\n 'vite',\n 'nitro',\n 'rollup',\n 'vite-plugin-satteri',\n 'satteri',\n 'fsevents',\n 'chokidar',\n];\n\nexport function timberServerBundle(): Plugin[] {\n const bundlePlugin: Plugin = {\n name: 'timber-server-bundle',\n\n config(_cfg, { command }) {\n // In dev mode, Vite externalizes node_modules by default for fast HMR.\n // But server-only/client-only must NOT be externalized — they need to\n // go through the timber-shims plugin so it can replace them with no-op\n // virtual modules. Without this, deps like `bright` that import\n // `server-only` get the real CJS package loaded via Node's require(),\n // which throws in the SSR environment.\n if (command === 'serve') {\n // In dev, Vite externalizes node_modules and loads them via Node's\n // native require(). This causes two problems:\n //\n // 1. Poison-pill packages: deps that import `server-only` (like `bright`)\n // hit the real CJS package which throws in the SSR environment.\n //\n // 2. Dual React instances: deps with React hooks (nuqs, etc.) are\n // externalized and loaded via Node.js, getting their own copy of\n // React. Meanwhile, SSR's renderToReadableStream uses Vite's\n // dep-optimized React. Two React instances = dispatcher mismatch,\n // causing \"Invalid hook call\" / \"Cannot read properties of null\n // (reading 'useId')\" errors. See LOCAL-297.\n //\n // We force these packages to be non-external so they go through\n // Vite's module pipeline, which deduplicates React correctly.\n return {\n environments: {\n rsc: {\n resolve: {\n noExternal: [...POISON_MARKER_SPECIFIERS],\n },\n },\n ssr: {\n resolve: {\n noExternal: [...POISON_MARKER_SPECIFIERS, 'nuqs'],\n },\n },\n },\n };\n }\n\n // Bundle all dependencies in server environments for production.\n // Without this, bare imports like 'nuqs/adapters/custom' are left\n // as external imports in the output, which fails on platforms\n // without node_modules (Cloudflare Workers, edge runtimes).\n // Define process.env.NODE_ENV in server environments so that\n // dead-code branches (dev-only tracing, React dev checks) are\n // eliminated by Rollup's tree-shaking. Without this, the runtime\n // check falls through on platforms where process.env is empty\n // (e.g. Cloudflare Workers), causing dev code to run in production.\n // Define process.env.NODE_ENV so dev-only React code is tree-shaken.\n // TIMBER_DEBUG is intentionally NOT defined here — it must remain a\n // runtime check so `isDebug()` in server/debug.ts can read it at\n // request time. See TIM-365.\n const serverDefine = {\n 'process.env.NODE_ENV': JSON.stringify('production'),\n };\n\n return {\n // Target webworker so Rolldown doesn't emit createRequire(import.meta.url)\n // shims that fail in Cloudflare Workers where import.meta.url is undefined\n // for non-entry modules. See design/11-platform.md.\n ssr: { target: 'webworker' },\n environments: {\n rsc: {\n resolve: { noExternal: true, external: BUILD_ONLY_EXTERNALS },\n build: { rolldownOptions: { external: [/^cloudflare:/] } },\n define: serverDefine,\n },\n ssr: {\n resolve: { noExternal: true, external: BUILD_ONLY_EXTERNALS },\n build: { rolldownOptions: { external: [/^cloudflare:/] } },\n define: serverDefine,\n },\n },\n };\n },\n };\n\n // Fix Rolldown's broken `__esmMin` lazy initializers in server bundles.\n //\n // Rolldown wraps ESM module initialization in `__esmMin` lazy functions.\n // For packages with `sideEffects: false` (e.g. nuqs), Rolldown drops\n // the variable assignment of the init function — so the module's React\n // imports, context creation, etc. never execute.\n //\n // The fix: patch `__esmMin` to eagerly *attempt* each init, but fall\n // back to lazy retry on failure. This handles two failure modes:\n //\n // 1. Forward references (e.g. Zod v4): `init_iso` calls `init_schemas`\n // which hasn't been defined yet. Eager execution fails silently, but\n // when the function is called lazily later, all dependencies are\n // available and the retry succeeds (and caches).\n //\n // 2. Optional peer dep shims (e.g. @emotion/is-prop-valid for\n // framer-motion): Vite generates shims that throw for missing\n // optional deps. The eager attempt swallows the throw; the lazy call\n // PROPAGATES it so the consuming package's try/catch handles it.\n //\n // The key: only the eager attempt swallows errors. Once the helper is\n // returned, lazy calls use the original Rolldown semantics — a throwing\n // init propagates to the caller (and clears `fn`, matching upstream).\n // On success, `fn` is set to 0 so subsequent calls are no-ops.\n const esmInitFixPlugin: Plugin = {\n name: 'timber-esm-init-fix',\n applyToEnvironment(environment) {\n return environment.name === 'rsc' || environment.name === 'ssr';\n },\n renderChunk(code) {\n const lazy = 'var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);';\n if (!code.includes(lazy)) return null;\n\n // Eager-with-retry: attempt init immediately, swallowing failures\n // (forward refs aren't defined yet). After the eager attempt, flip\n // to lazy mode where errors propagate to the caller — consumers'\n // try/catch (framer-motion's optional @emotion dep) must see them.\n const eager = [\n 'var __esmMin = (fn, res) => {',\n ' var eager = 1;',\n ' var l = () => {',\n ' if (fn) { if (eager) { try { res = fn(); fn = 0; } catch(e) {} } else { res = fn(fn = 0); } }',\n ' return res;',\n ' };',\n ' l();',\n ' eager = 0;',\n ' return l;',\n '};',\n ].join(' ');\n\n return { code: code.replace(lazy, eager), map: null };\n },\n };\n\n // Fix Rolldown's `createRequire(import.meta.url)` CJS interop shim for\n // Cloudflare Workers. Rolldown emits this for CJS dependencies (e.g.\n // @opentelemetry/context-async-hooks) that use `require()`. On Workers,\n // `import.meta.url` is `undefined` for non-entry modules, causing:\n // TypeError: The argument 'path' must be a file URL object, a file URL\n // string, or an absolute path string. Received 'undefined'\n //\n // The fix: provide a fallback URL when `import.meta.url` is undefined.\n // The actual URL doesn't matter — `createRequire` only needs it for\n // resolving relative paths, but the only `__require()` calls are for\n // Node built-ins (events, async_hooks) which resolve from any base.\n //\n // The top-level `ssr: { target: 'webworker' }` was supposed to prevent\n // this, but it doesn't propagate to custom environments (rsc) in Vite's\n // Environment API. See LOCAL-405.\n const createRequireFixPlugin: Plugin = {\n name: 'timber-create-require-fix',\n applyToEnvironment(environment) {\n return environment.name === 'rsc' || environment.name === 'ssr';\n },\n renderChunk(code) {\n const pattern = 'createRequire(import.meta.url)';\n if (!code.includes(pattern)) return null;\n\n return {\n code: code.replace(pattern, 'createRequire(import.meta.url || \"file:///app\")'),\n map: null,\n };\n },\n };\n\n return [bundlePlugin, esmInitFixPlugin, createRequireFixPlugin];\n}\n","/**\n * Shared AST helpers for callsite-ID transforms.\n *\n * Both timber-cache-transform (plugins/cache.ts) and timber-prebuilt\n * (plugins/prebuilt.ts) detect calls on bindings imported from the cache\n * module and stamp them with content-derived stable IDs. The node shapes,\n * import-binding resolution, recursive call walk, and ID derivation are\n * identical — only the callee shape and rewrite differ per plugin.\n *\n * See TIM-997, TIM-1053, design/06-caching.md §\"Cache Key Security\".\n */\n\nimport { fnv1aHash } from '../cache/fast-hash.ts';\n\n/** Module specifiers whose bindings the transforms track. */\nexport const CACHE_MODULE_SOURCES = new Set(['@timber-js/app/cache', 'timber/cache']);\n\nexport interface PositionedNode {\n type: string;\n start: number;\n end: number;\n [key: string]: unknown;\n}\n\nexport interface IdentifierNode extends PositionedNode {\n type: 'Identifier';\n name: string;\n}\n\nexport interface ImportDeclarationNode extends PositionedNode {\n type: 'ImportDeclaration';\n source: { value: string };\n specifiers: Array<\n PositionedNode & {\n type: string;\n local: IdentifierNode;\n imported?: IdentifierNode;\n }\n >;\n}\n\nexport interface CallExpressionNode extends PositionedNode {\n type: 'CallExpression';\n callee: PositionedNode;\n arguments: PositionedNode[];\n}\n\nexport interface MemberExpressionNode extends PositionedNode {\n type: 'MemberExpression';\n object: PositionedNode;\n property: PositionedNode;\n computed: boolean;\n}\n\nexport interface ProgramNode extends PositionedNode {\n type: 'Program';\n body: PositionedNode[];\n}\n\nexport interface ImportBindings {\n /** Local names bound to the named import (`import { cache as c }`). */\n named: Set<string>;\n /** Local names of namespace imports (`import * as ns`) of a tracked module. */\n namespaces: Set<string>;\n}\n\n/**\n * Find the local binding name(s) for `importedName` imported from one of\n * `sources` — both named imports (including aliases) and namespace imports\n * (TIM-1054).\n */\nexport function findImportBindings(\n program: ProgramNode,\n sources: ReadonlySet<string>,\n importedName: string\n): ImportBindings {\n const named = new Set<string>();\n const namespaces = new Set<string>();\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const decl = stmt as unknown as ImportDeclarationNode;\n if (!sources.has(decl.source.value)) continue;\n for (const spec of decl.specifiers) {\n if (spec.type === 'ImportNamespaceSpecifier') {\n namespaces.add(spec.local.name);\n continue;\n }\n if (spec.type !== 'ImportSpecifier') continue;\n const specImportedName = spec.imported?.name ?? spec.local.name;\n if (specImportedName === importedName) {\n named.add(spec.local.name);\n }\n }\n }\n return { named, namespaces };\n}\n\n/** Extract all bound identifier names from a parameter/binding pattern. */\nfunction collectPatternNames(node: PositionedNode, out: Set<string>): void {\n switch (node.type) {\n case 'Identifier':\n out.add((node as IdentifierNode).name);\n break;\n case 'AssignmentPattern':\n collectPatternNames(node.left as PositionedNode, out);\n break;\n case 'RestElement':\n collectPatternNames(node.argument as PositionedNode, out);\n break;\n case 'ArrayPattern':\n for (const el of (node.elements as (PositionedNode | null)[] | undefined) ?? []) {\n if (el) collectPatternNames(el, out);\n }\n break;\n case 'ObjectPattern':\n for (const prop of (node.properties as PositionedNode[] | undefined) ?? []) {\n if (prop.type === 'RestElement') {\n collectPatternNames(prop, out);\n } else {\n collectPatternNames(prop.value as PositionedNode, out);\n }\n }\n break;\n case 'TSParameterProperty':\n // TS constructor parameter properties: `constructor(private cache)`\n if (node.parameter) collectPatternNames(node.parameter as PositionedNode, out);\n break;\n }\n}\n\n/** Return the intersection of param names with `tracked`, or null if none. */\nfunction shadowedParamNames(\n params: PositionedNode[] | undefined,\n tracked: ReadonlySet<string>\n): Set<string> | null {\n if (!params) return null;\n const names = new Set<string>();\n for (const p of params) collectPatternNames(p, names);\n const hit = new Set<string>();\n for (const n of names) {\n if (tracked.has(n)) hit.add(n);\n }\n return hit.size > 0 ? hit : null;\n}\n\n/**\n * Collect names declared by `VariableDeclaration`, `FunctionDeclaration`,\n * and `ClassDeclaration` in a statement list. Only scans direct children\n * (not nested blocks). For-loop bindings are NOT included — they are\n * scoped to the loop statement and handled separately in\n * `collectShadowRanges` (codex review round 4 on PR #876).\n */\nfunction collectLexicalDeclNames(stmts: PositionedNode[], out: Set<string>): void {\n for (const stmt of stmts) {\n if (stmt.type === 'VariableDeclaration') {\n for (const decl of (stmt.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n } else if (stmt.type === 'FunctionDeclaration' || stmt.type === 'ClassDeclaration') {\n if (stmt.id && (stmt.id as PositionedNode).type === 'Identifier') {\n out.add((stmt.id as IdentifierNode).name);\n }\n }\n }\n}\n\n/**\n * Extract binding names from a for-loop's init/left clause, but ONLY for\n * `const`/`let` (block-scoped). `var` bindings hoist to the enclosing\n * function and are handled by `collectVarDeclNames` instead (codex review\n * round 5 on PR #876).\n */\nfunction collectForLoopBlockBindingNames(loop: PositionedNode, out: Set<string>): void {\n const init = (loop.init ?? loop.left) as PositionedNode | undefined;\n if (init?.type === 'VariableDeclaration' && init.kind !== 'var') {\n for (const decl of (init.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n}\n\n/**\n * Recursively collect `var` declaration names from a statement tree.\n * `var` hoists to the enclosing function regardless of block nesting,\n * so we must scan nested blocks, loops, switch cases, etc.\n */\nfunction collectVarDeclNames(stmts: PositionedNode[], out: Set<string>): void {\n for (const stmt of stmts) {\n if (stmt.type === 'VariableDeclaration' && stmt.kind === 'var') {\n for (const decl of (stmt.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n // Recurse into blocks, loops, if/else, switch, etc.\n if (stmt.type === 'BlockStatement' || stmt.type === 'StaticBlock') {\n collectVarDeclNames((stmt.body as PositionedNode[] | undefined) ?? [], out);\n } else if (stmt.type === 'IfStatement') {\n if (stmt.consequent) collectVarDeclNames([stmt.consequent as PositionedNode], out);\n if (stmt.alternate) collectVarDeclNames([stmt.alternate as PositionedNode], out);\n } else if (stmt.type === 'SwitchStatement') {\n for (const c of (stmt.cases as PositionedNode[] | undefined) ?? []) {\n collectVarDeclNames((c.consequent as PositionedNode[] | undefined) ?? [], out);\n }\n } else if (\n stmt.type === 'ForStatement' ||\n stmt.type === 'ForInStatement' ||\n stmt.type === 'ForOfStatement' ||\n stmt.type === 'WhileStatement' ||\n stmt.type === 'DoWhileStatement'\n ) {\n const init = (stmt.init ?? stmt.left) as PositionedNode | undefined;\n if (init?.type === 'VariableDeclaration' && init.kind === 'var') {\n for (const decl of (init.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n if (stmt.body) collectVarDeclNames([stmt.body as PositionedNode], out);\n } else if (stmt.type === 'WithStatement' || stmt.type === 'LabeledStatement') {\n if (stmt.body) collectVarDeclNames([stmt.body as PositionedNode], out);\n } else if (stmt.type === 'TryStatement') {\n if (stmt.block) collectVarDeclNames([stmt.block as PositionedNode], out);\n const handler = stmt.handler as PositionedNode | undefined;\n if (handler?.body) collectVarDeclNames([handler.body as PositionedNode], out);\n if (stmt.finalizer) collectVarDeclNames([stmt.finalizer as PositionedNode], out);\n }\n }\n}\n\nexport interface ShadowRange {\n start: number;\n end: number;\n /** Which tracked binding names are shadowed in this range. */\n names: ReadonlySet<string>;\n}\n\n/**\n * Collect byte ranges where any name in `tracked` is shadowed by a\n * function/arrow parameter, catch clause binding, or lexical declaration\n * (`const`/`let`/`var`, `function`, `class`, for-loop binding). Calls\n * inside these ranges must NOT be rewritten — the name resolves to the\n * local binding, not the import (TIM-1141).\n *\n * Each range records WHICH names are shadowed so the consumer can skip\n * only calls to the shadowed name, not unrelated imports (codex review\n * on PR #876).\n *\n * When a scope shadows some-but-not-all tracked names, the walker\n * continues descending to find inner scopes that shadow remaining names\n * (codex review round 2 on PR #876).\n */\nexport function collectShadowRanges(\n node: PositionedNode,\n tracked: ReadonlySet<string>,\n ranges: ShadowRange[]\n): void {\n if (tracked.size === 0) return;\n\n const isFn =\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression';\n\n let remainingTracked = tracked;\n\n // ── Function/arrow parameters + named function expression id ───────\n if (isFn) {\n const paramNames = new Set<string>();\n for (const p of (node.params as PositionedNode[] | undefined) ?? []) {\n collectPatternNames(p, paramNames);\n }\n // Named function expressions: `const w = function cache() { ... }`\n // — the name is in scope inside the body (codex review round 5).\n if (node.type === 'FunctionExpression' && node.id) {\n const fnId = node.id as PositionedNode;\n if (fnId.type === 'Identifier') paramNames.add((fnId as IdentifierNode).name);\n }\n const shadowed = new Set<string>();\n for (const n of paramNames) {\n if (tracked.has(n)) shadowed.add(n);\n }\n if (shadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: shadowed });\n if (shadowed.size === tracked.size) return;\n remainingTracked = new Set([...tracked].filter((n) => !shadowed.has(n)));\n }\n }\n\n // ── Catch clause binding ───────────────────────────────────────────\n if (node.type === 'CatchClause') {\n const param = node.param as PositionedNode | undefined;\n if (param) {\n const shadowed = shadowedParamNames([param], tracked);\n if (shadowed) {\n ranges.push({ start: node.start, end: node.end, names: shadowed });\n if (shadowed.size === tracked.size) return;\n remainingTracked = new Set([...tracked].filter((n) => !shadowed.has(n)));\n }\n }\n }\n\n // ── Named class expressions ───────────────────────────────────────\n // `const C = class cache { ... }` — the class name is in scope inside\n // the class body (codex review round 6 on PR #876).\n if (node.type === 'ClassExpression' && node.id) {\n const clsId = node.id as PositionedNode;\n if (clsId.type === 'Identifier' && remainingTracked.has((clsId as IdentifierNode).name)) {\n const names = new Set([(clsId as IdentifierNode).name]);\n ranges.push({ start: node.start, end: node.end, names });\n if (names.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !names.has(n)));\n }\n }\n\n // ── For-loop bindings (scoped to the loop, not the enclosing body) ─\n // `for (const cache of items) { ... }` shadows `cache` only inside\n // the loop statement, not in the rest of the function. Codex review\n // round 4 on PR #876.\n if (\n node.type === 'ForStatement' ||\n node.type === 'ForInStatement' ||\n node.type === 'ForOfStatement'\n ) {\n const loopNames = new Set<string>();\n collectForLoopBlockBindingNames(node, loopNames);\n const loopShadowed = new Set<string>();\n for (const n of loopNames) {\n if (remainingTracked.has(n)) loopShadowed.add(n);\n }\n if (loopShadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: loopShadowed });\n if (loopShadowed.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !loopShadowed.has(n)));\n }\n }\n\n // ── Lexical declarations in function/block/switch bodies ────────────\n // `const cache = ...`, `function cache() {}`, `class cache {}` inside\n // a function body, block, or switch shadow the tracked name for the\n // enclosing scope. `var` hoists to the enclosing function — scanned\n // recursively. Codex review rounds 3 & 5 on PR #876.\n const isScope =\n isFn ||\n node.type === 'BlockStatement' ||\n node.type === 'SwitchStatement' ||\n node.type === 'StaticBlock';\n if (isScope) {\n let bodyStmts: PositionedNode[] | null = null;\n if (isFn) {\n const body = node.body as PositionedNode | undefined;\n if (body?.type === 'BlockStatement') {\n bodyStmts = (body.body as PositionedNode[] | undefined) ?? null;\n }\n } else if (node.type === 'SwitchStatement') {\n // Switch cases: declarations in unbraced cases are scoped to the switch block\n const caseStmts: PositionedNode[] = [];\n for (const c of (node.cases as PositionedNode[] | undefined) ?? []) {\n for (const s of (c.consequent as PositionedNode[] | undefined) ?? []) {\n caseStmts.push(s);\n }\n }\n bodyStmts = caseStmts;\n } else {\n bodyStmts = (node.body as PositionedNode[] | undefined) ?? null;\n }\n if (bodyStmts) {\n const declNames = new Set<string>();\n collectLexicalDeclNames(bodyStmts, declNames);\n // For function scopes, also collect hoisted `var` declarations\n // from the entire body tree (var hoists past blocks).\n if (isFn) {\n collectVarDeclNames(bodyStmts, declNames);\n }\n const lexShadowed = new Set<string>();\n for (const n of declNames) {\n if (remainingTracked.has(n)) lexShadowed.add(n);\n }\n if (lexShadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: lexShadowed });\n if (lexShadowed.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !lexShadowed.has(n)));\n }\n }\n }\n\n // ── Recurse into children ──────────────────────────────────────────\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n collectShadowRanges(item as PositionedNode, remainingTracked, ranges);\n }\n }\n } else if (typeof (val as PositionedNode).type === 'string') {\n collectShadowRanges(val as PositionedNode, remainingTracked, ranges);\n }\n }\n }\n}\n\n/**\n * Recursively walk AST nodes collecting call expressions accepted by\n * `matches`. Calls are typically at module scope, but calls inside\n * functions/blocks are handled for completeness.\n *\n * Consumers that match by binding NAME should pair this with\n * `collectShadowRanges` to filter out calls in scopes where the tracked\n * name is shadowed (TIM-1141). The prebuilt transform avoids the class\n * entirely by allowlisting top-level declarator positions\n * (plugins/prebuilt.ts).\n */\nexport function findCallSites(\n node: PositionedNode,\n matches: (call: CallExpressionNode) => boolean,\n results: CallExpressionNode[]\n): void {\n if (node.type === 'CallExpression') {\n const call = node as unknown as CallExpressionNode;\n if (matches(call)) {\n results.push(call);\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n findCallSites(item as PositionedNode, matches, results);\n }\n }\n } else if (typeof (val as PositionedNode).type === 'string') {\n findCallSites(val as PositionedNode, matches, results);\n }\n }\n }\n}\n\n/**\n * Generate a stable callsite ID from a module path, a kind discriminator\n * ('cache' | 'component'), the source text of the enclosing top-level\n * statement, the source text of the call expression, and an occurrence index\n * among fully byte-identical (statement, call) pairs in the same file.\n *\n * The ID is deterministic and:\n * - Stable across cold starts AND across builds/deploys for unchanged calls —\n * inserting, deleting, or reordering other calls does not affect it\n * - Unique across different modules (relPath component)\n * - Unique across distinct calls within a module (statement + span hashes),\n * with fully identical duplicates disambiguated by source-order occurrence\n * - Fresh when the wrapped fn, opts, or enclosing statement change, which\n * intentionally invalidates the old persisted entries\n *\n * The enclosing-statement text is included so that byte-identical calls in\n * different scopes — e.g. two factory helpers with identical call spans —\n * get distinct, insertion-stable IDs. See plugins/cache.ts header for the\n * full derivation rationale (TIM-1053).\n */\nexport function generateStableCallsiteId(\n relativeModulePath: string,\n kind: string,\n statementText: string,\n callSpanText: string,\n occurrence: number\n): string {\n return fnv1aHash(\n `${relativeModulePath}:${kind}:${fnv1aHash(statementText)}:${fnv1aHash(callSpanText)}:${occurrence}`\n );\n}\n","/**\n * timber-cache-transform — Vite plugin that injects stable callsite IDs\n * into `cache.data()` calls imported from `@timber-js/app/cache`.\n *\n * Detected callsite forms (TIM-1054):\n * - named imports, including aliases: `import { cache as c }` + `c.data(fn, opts)`\n * - namespace imports: `import * as ns` + `ns.cache.data(fn, opts)`\n * Forms a per-module transform cannot trace — local variable aliases\n * (`const c = cache`), user re-export wrapper modules, computed access\n * (`cache['data']`) — fall back to the runtime fnId derived from\n * fnv1a(fn.toString()) (see cache/timber-cache.ts), which is deterministic\n * across instances and cold starts of the same build. Without either\n * mechanism, an ordinal counter would collide across instances with a shared\n * CacheHandler (Redis/KV) — cache key poisoning, serving one route's cached\n * data to another.\n *\n * The plugin transforms:\n * cache.data(fn, opts) → cache.data(fn, opts, \"stable-id\")\n * ns.cache.data(fn, opts) → ns.cache.data(fn, opts, \"stable-id\")\n *\n * where stable-id =\n * fnv1a(relPath + \":cache:\" + fnv1a(stmtText) + \":\" + fnv1a(callSpanText) + \":\" + occurrence)\n *\n * stmtText is the source text of the enclosing *top-level statement* and\n * callSpanText is the source text of the cache(...) call expression itself.\n *\n * The ID is derived from the *content* of the call, not its ordinal position\n * in the file. A position-based index (the original TIM-997 scheme) was stable\n * within one build but shifted across builds: inserting, deleting, or\n * reordering a cache() call changed the index of every call below it, so with\n * a persistent shared CacheHandler (Redis/KV) a new function could inherit\n * another function's old ID and serve its persisted data — cross-deploy cache\n * poisoning (TIM-1053). Content hashing makes IDs immune to reordering and\n * unrelated edits, while a changed call gets a fresh ID — which is exactly\n * when invalidation is wanted.\n *\n * The enclosing-statement text is included so that byte-identical cache.data()\n * calls in different scopes — e.g. two factory helpers that each `return\n * cache.data(fn, { ttl: 60 })` — get distinct, insertion-stable IDs: their\n * enclosing declarations differ by name/body even when the call spans are\n * identical. Without it, a source-order occurrence counter alone would shift\n * when an identical span is inserted above, reassigning IDs across deploys.\n * Calls that are byte-identical INCLUDING their enclosing top-level statement\n * are disambiguated by a source-order occurrence index. That residue is safe:\n * identical top-level declarations are a redeclaration error, so fully\n * identical (statement, call) pairs can only be expression statements\n * referencing the same bindings — the same function, where an ID swap is\n * harmless.\n *\n * AST helpers and the ID derivation are shared with timber-prebuilt\n * (plugins/prebuilt.ts) via plugins/callsite-ast.ts.\n *\n * See TIM-997, TIM-1053, design/06-caching.md §\"Cache Key Security\".\n */\n\nimport { relative } from 'node:path';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport {\n CACHE_MODULE_SOURCES,\n collectShadowRanges,\n findCallSites,\n findImportBindings,\n generateStableCallsiteId,\n} from './callsite-ast.ts';\nimport type {\n CallExpressionNode,\n IdentifierNode,\n ImportBindings,\n MemberExpressionNode,\n PositionedNode,\n ProgramNode,\n ShadowRange,\n} from './callsite-ast.ts';\n\n/**\n * Is this callee a `cache.data(...)` call? Matches two forms:\n * - Named import: `cache.data(fn, opts)` where `cache` is the imported binding\n * - Namespace import: `ns.cache.data(fn, opts)` where `ns` is the namespace\n * Computed access (`cache['data']`) is deliberately not matched; it falls back\n * to the runtime fnId derivation.\n */\nfunction isCacheDataCallee(callee: PositionedNode, bindings: ImportBindings): boolean {\n if (callee.type !== 'MemberExpression') return false;\n const member = callee as unknown as MemberExpressionNode;\n if (member.computed) return false;\n if (member.property.type !== 'Identifier' || (member.property as IdentifierNode).name !== 'data')\n return false;\n\n const obj = member.object;\n // Named import: `cache.data(...)` — obj is the imported `cache` identifier\n if (obj.type === 'Identifier') {\n return bindings.named.has((obj as IdentifierNode).name);\n }\n // Namespace import: `ns.cache.data(...)` — obj is `ns.cache`\n if (obj.type === 'MemberExpression') {\n const outer = obj as unknown as MemberExpressionNode;\n return (\n !outer.computed &&\n outer.object.type === 'Identifier' &&\n bindings.namespaces.has((outer.object as IdentifierNode).name) &&\n outer.property.type === 'Identifier' &&\n (outer.property as IdentifierNode).name === 'cache'\n );\n }\n return false;\n}\n\n/**\n * Extract the local binding name that a cache.data callee resolves to — the\n * `cache` identifier for named imports, or the namespace object for `ns.cache.data()`.\n */\nfunction calleeBindingName(callee: PositionedNode, bindings: ImportBindings): string | null {\n if (callee.type !== 'MemberExpression') return null;\n const member = callee as unknown as MemberExpressionNode;\n const obj = member.object;\n // Named import: `cache.data(...)` — binding is `cache`\n if (obj.type === 'Identifier') {\n const name = (obj as IdentifierNode).name;\n return bindings.named.has(name) ? name : null;\n }\n // Namespace import: `ns.cache.data(...)` — binding is `ns`\n if (obj.type === 'MemberExpression') {\n const outer = obj as unknown as MemberExpressionNode;\n if (outer.object.type === 'Identifier') {\n const name = (outer.object as IdentifierNode).name;\n return bindings.namespaces.has(name) ? name : null;\n }\n }\n return null;\n}\n\n/**\n * Generate a stable callsite ID for a cache() call. See callsite-ast.ts for\n * the derivation properties.\n */\nfunction generateStableId(\n relativeModulePath: string,\n statementText: string,\n callSpanText: string,\n occurrence: number\n): string {\n return generateStableCallsiteId(\n relativeModulePath,\n 'cache',\n statementText,\n callSpanText,\n occurrence\n );\n}\n\nexport function timberCacheTransform(ctx: PluginContext): Plugin {\n return {\n name: 'timber-cache-transform',\n\n transform(code, id) {\n if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;\n // Skip node_modules (don't transform third-party code)\n if (id.includes('node_modules')) return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(code);\n } catch {\n return;\n }\n\n const cacheBindings = findImportBindings(program, CACHE_MODULE_SOURCES, 'cache');\n if (cacheBindings.named.size === 0 && cacheBindings.namespaces.size === 0) return;\n\n // Collect byte ranges where tracked binding names are shadowed by\n // function/arrow parameters or catch bindings (TIM-1141). Calls inside\n // these ranges are NOT rewritten — they fall back to the runtime fnId.\n const trackedNames = new Set([...cacheBindings.named, ...cacheBindings.namespaces]);\n const shadowRanges: ShadowRange[] = [];\n collectShadowRanges(program, trackedNames, shadowRanges);\n\n // Check whether the specific binding name a callee resolves to is\n // shadowed at the call position. Only that name is blocked — other\n // tracked imports from the same module remain valid (codex review\n // on PR #876).\n const isCalleeShadowed = (call: CallExpressionNode): boolean => {\n const name = calleeBindingName(call.callee, cacheBindings);\n if (!name) return false;\n return shadowRanges.some(\n (r) => call.start >= r.start && call.start < r.end && r.names.has(name)\n );\n };\n\n // Collect call sites per top-level statement so each call carries its\n // enclosing statement's source text into the ID hash.\n const callSites: Array<{ call: CallExpressionNode; stmt: PositionedNode }> = [];\n for (const stmt of program.body) {\n const calls: CallExpressionNode[] = [];\n findCallSites(\n stmt,\n (call) =>\n call.arguments.length === 2 &&\n isCacheDataCallee(call.callee, cacheBindings) &&\n !isCalleeShadowed(call),\n calls\n );\n for (const call of calls) callSites.push({ call, stmt });\n }\n if (callSites.length === 0) return;\n\n // Sort by position in file so occurrence indices among byte-identical\n // (statement, call) pairs are assigned in deterministic source order\n callSites.sort((a, b) => a.call.start - b.call.start);\n\n const root = ctx.root || process.cwd();\n const relPath = relative(root, id);\n const s = new MagicString(code);\n const occurrences = new Map<string, number>();\n\n for (const { call, stmt } of callSites) {\n const stmtText = code.slice(stmt.start, stmt.end);\n const spanText = code.slice(call.start, call.end);\n const dupKey = stmtText + String.fromCharCode(0) + spanText;\n const occurrence = occurrences.get(dupKey) ?? 0;\n occurrences.set(dupKey, occurrence + 1);\n const stableId = generateStableId(relPath, stmtText, spanText, occurrence);\n // Insert the stable ID as the 3rd argument directly after the last\n // argument — NOT before the closing ')'. The call may already have a\n // trailing comma after the options argument (Prettier v3 default for\n // multiline calls); inserting before ')' would emit `,, \"id\"`, a\n // parse error (TIM-1021). A trailing comma after the inserted\n // argument remains valid JS.\n const lastArg = call.arguments[call.arguments.length - 1];\n s.appendLeft(lastArg.end, `, \"${stableId}\"`);\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n };\n}\n\n// Exported for testing\nexport { generateStableId };\n","/**\n * Per-module syntactic facts for request-dependency analysis.\n *\n * This module is deliberately dumb: it records *what the source says*, with no\n * knowledge of which specifiers or names are interesting. Every judgement —\n * \"is this an accessor\", \"is this a definition object\" — lives in `origin.ts`,\n * which resolves a binding to the module it actually came from.\n *\n * That split is the point. The previous shape asked each module in isolation\n * \"do you import `getSearchParams` from `@timber-js/app/server` and call it\",\n * which any indirection defeats: a barrel re-export, a namespace import, a\n * factory reached through the app's own `_lib`. Each of those was a separate\n * hole and each was found separately (TIM-1291). Recording bindings and edges\n * here, and resolving them across the graph there, closes the family instead of\n * its members.\n *\n * See design/19-client-navigation.md §\"Why the slot comparison ignores the query\".\n */\n\nimport type {\n ProgramNode,\n PositionedNode,\n IdentifierNode,\n CallExpressionNode,\n MemberExpressionNode,\n} from '../callsite-ast.ts';\n\n/**\n * One module-graph edge introduced by an `import` or `export … from`.\n *\n * `imported` is the name as it exists in the *source* module: an export name,\n * `'default'`, or `'*'` for a namespace/star form.\n */\nexport interface ImportEdge {\n source: string;\n imported: string;\n}\n\n/** The callee of `const x = f()` / `const x = ns.f()`. */\nexport type CalleeRef =\n | { kind: 'local'; name: string }\n | { kind: 'member'; object: string; property: string };\n\nexport interface ModuleFacts {\n /** Local name → the edge that bound it (`import { a as b } from 'x'`). */\n importedBindings: Map<string, ImportEdge>;\n /** Exported name → edge, for `export { a as b } from 'x'`. */\n reExports: Map<string, ImportEdge>;\n /** Sources of anonymous `export * from 'x'`, in source order. */\n starReExports: string[];\n /** Exported name → local name, for `export { x }`, `export const x = …`. */\n localExports: Map<string, string>;\n /** Local variable name → the callee that produced its value. */\n factoryCalls: Map<string, CalleeRef>;\n /** Local names invoked directly: `f()`. */\n calledLocals: Set<string>;\n /** `ns.f()` → `ns` → `{ f }`. */\n calledMembers: Map<string, Set<string>>;\n /** Base identifier of a `.get()` chain: `x.get()`, `x().get()`, `x.p.get()`. */\n getterLocals: Set<string>;\n /** `ns.defs.get()` → `ns` → `{ defs }`. */\n getterMembers: Map<string, Set<string>>;\n /** Every name the module *body* mentions — import/export clauses excluded. */\n referencedLocals: Set<string>;\n /** Specifier → resolved module id, filled by the plugin via `this.resolve`. */\n resolvedSources: Map<string, string>;\n /** Specifiers that failed to resolve — treated as request-dependent. */\n unresolvedSources: Set<string>;\n}\n\n/** `export default` has no local name of its own; this stands in for one. */\nexport const DEFAULT_EXPORT = 'default';\n\nexport function createModuleFacts(): ModuleFacts {\n return {\n importedBindings: new Map(),\n reExports: new Map(),\n starReExports: [],\n localExports: new Map(),\n factoryCalls: new Map(),\n calledLocals: new Set(),\n calledMembers: new Map(),\n getterLocals: new Set(),\n getterMembers: new Map(),\n referencedLocals: new Set(),\n resolvedSources: new Map(),\n unresolvedSources: new Set(),\n };\n}\n\n/**\n * Specifiers the origin walk can actually reach, so the plugin resolves those\n * and not every import in the file.\n *\n * A re-export edge is always reachable — a downstream module can ask for any\n * name it forwards. An `import` edge is reachable through any local name the\n * module body mentions, or that it re-exports.\n *\n * The name set must be **the same one the taint rules consult**. Deriving it\n * from the call shapes instead (called, `.get()`d, member-called, minted from)\n * left `read(filters)` — a definition passed as an argument — with its\n * specifier unresolved, so the origin walk reported it inert and the page read\n * as request-independent. Two hand-maintained lists of \"names that matter\" is\n * one list too many; this is the one, and `referencedLocals` is a superset of\n * every call shape by construction, since each of them is an identifier the\n * walk visits. (Codex review round 1 on PR #991.)\n */\nexport function usedSources(facts: ModuleFacts): Set<string> {\n const sources = new Set<string>(facts.starReExports);\n for (const edge of facts.reExports.values()) sources.add(edge.source);\n\n for (const local of facts.referencedLocals) {\n const edge = facts.importedBindings.get(local);\n if (edge) sources.add(edge.source);\n }\n for (const local of facts.localExports.values()) {\n const edge = facts.importedBindings.get(local);\n if (edge) sources.add(edge.source);\n }\n return sources;\n}\n\n/**\n * True when the module cannot affect any answer, so its facts need not be kept.\n *\n * Every judgement bottoms out at a module edge: a call site resolves through\n * `importedBindings`, a chain link through `reExports` / `starReExports`. A\n * module with none of those can only ever resolve to `none` — its exports lead\n * to locals that lead nowhere — which is exactly what a *missing* entry\n * produces. Dropping it is behaviour-preserving and keeps the dev-time map from\n * holding an entry for every leaf module in the graph.\n */\nexport function contributesNothing(facts: ModuleFacts): boolean {\n return (\n facts.importedBindings.size === 0 &&\n facts.reExports.size === 0 &&\n facts.starReExports.length === 0\n );\n}\n\nfunction addToMapSet(map: Map<string, Set<string>>, key: string, value: string): void {\n const existing = map.get(key);\n if (existing) existing.add(value);\n else map.set(key, new Set([value]));\n}\n\n// ─── Declaration collection ──────────────────────────────────────────────\n\n/**\n * A module-export name slot: `Identifier`, or the string-literal form ESTree\n * allows (`export { x as \"a-b\" } from './m'`) — a valid export name that is not\n * a valid identifier.\n */\ntype NameNode = PositionedNode | undefined;\n\ninterface SpecifierNode extends PositionedNode {\n local?: NameNode;\n imported?: NameNode;\n exported?: NameNode;\n}\n\nfunction nameOf(node: NameNode): string | null {\n if (!node) return null;\n if (node.type === 'Identifier') return (node as IdentifierNode).name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return null;\n}\n\n/**\n * `import type { … }` needs no handling here. Vite's TypeScript transform is a\n * core plugin and runs before this one, so types are already erased by the time\n * the analysis parses — and the parser it runs on is JavaScript-only, so\n * unerased TypeScript would throw rather than be silently misread.\n * `tests/request-dep-plugin.test.ts` pins the resulting property through the\n * real pipeline: a type-only accessor import is not request-dependent.\n */\nfunction collectImportDeclaration(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n if (typeof source !== 'string') return;\n for (const spec of (stmt.specifiers as SpecifierNode[] | undefined) ?? []) {\n const local = nameOf(spec.local);\n if (!local) continue;\n if (spec.type === 'ImportNamespaceSpecifier') {\n facts.importedBindings.set(local, { source, imported: '*' });\n } else if (spec.type === 'ImportDefaultSpecifier') {\n facts.importedBindings.set(local, { source, imported: DEFAULT_EXPORT });\n } else if (spec.type === 'ImportSpecifier') {\n facts.importedBindings.set(local, { source, imported: nameOf(spec.imported) ?? local });\n }\n }\n}\n\nfunction collectDeclaredNames(decl: PositionedNode, out: Set<string>): void {\n if (decl.type === 'VariableDeclaration') {\n for (const d of (decl.declarations as PositionedNode[] | undefined) ?? []) {\n const id = d.id as PositionedNode | undefined;\n if (id?.type === 'Identifier') out.add((id as IdentifierNode).name);\n }\n } else if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {\n const id = decl.id as PositionedNode | undefined;\n if (id?.type === 'Identifier') out.add((id as IdentifierNode).name);\n }\n}\n\nfunction collectExportNamed(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n const specifiers = (stmt.specifiers as SpecifierNode[] | undefined) ?? [];\n\n if (typeof source === 'string') {\n // `export { a as b } from './m'` — `local` names the export in './m'.\n for (const spec of specifiers) {\n const imported = nameOf(spec.imported) ?? nameOf(spec.local);\n const exported = nameOf(spec.exported);\n if (imported && exported) facts.reExports.set(exported, { source, imported });\n }\n return;\n }\n\n // `export { x }` / `export { x as y }` — `local` is a binding in this module.\n for (const spec of specifiers) {\n const local = nameOf(spec.local);\n const exported = nameOf(spec.exported);\n if (local && exported) facts.localExports.set(exported, local);\n }\n\n // `export const x = …`, `export function f() {}`\n const declaration = stmt.declaration as PositionedNode | undefined;\n if (declaration) {\n const names = new Set<string>();\n collectDeclaredNames(declaration, names);\n for (const name of names) facts.localExports.set(name, name);\n }\n}\n\nfunction collectExportAll(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n if (typeof source !== 'string') return;\n const exported = nameOf(stmt.exported as NameNode);\n if (exported) {\n // `export * as ns from './m'` — a namespace object under one name.\n facts.reExports.set(exported, { source, imported: '*' });\n } else {\n facts.starReExports.push(source);\n }\n}\n\nfunction collectExportDefault(stmt: PositionedNode, facts: ModuleFacts): void {\n const declaration = stmt.declaration as PositionedNode | undefined;\n if (!declaration) return;\n facts.localExports.set(DEFAULT_EXPORT, DEFAULT_EXPORT);\n if (declaration.type === 'Identifier') {\n // `export default x` — alias the default onto the existing binding.\n facts.localExports.set(DEFAULT_EXPORT, (declaration as IdentifierNode).name);\n } else if (declaration.type === 'CallExpression') {\n const ref = calleeRef(declaration as unknown as CallExpressionNode);\n if (ref) facts.factoryCalls.set(DEFAULT_EXPORT, ref);\n }\n}\n\n// ─── Expression collection ───────────────────────────────────────────────\n\nfunction calleeRef(call: CallExpressionNode): CalleeRef | null {\n const callee = call.callee;\n if (callee.type === 'Identifier') {\n return { kind: 'local', name: (callee as IdentifierNode).name };\n }\n if (callee.type === 'MemberExpression') {\n const member = callee as MemberExpressionNode;\n if (\n !member.computed &&\n member.object.type === 'Identifier' &&\n member.property.type === 'Identifier'\n ) {\n return {\n kind: 'member',\n object: (member.object as IdentifierNode).name,\n property: (member.property as IdentifierNode).name,\n };\n }\n }\n return null;\n}\n\n/**\n * Walk down a `.get()` receiver to the identifier it is ultimately rooted in,\n * along with the first property accessed on that identifier.\n *\n * `x.get()` → `x`, no property. `x(a).get()` → `x`. `ns.defs.get()` → `ns`\n * plus `defs`, which is both the namespace-member shape and the\n * `cookies.theme.get()` shape — the resolver tries the base binding and the\n * member, so one walk covers both.\n */\nfunction chainRoot(node: PositionedNode): { base: string; property: string | null } | null {\n let current = node;\n let property: string | null = null;\n for (;;) {\n if (current.type === 'Identifier') {\n return { base: (current as IdentifierNode).name, property };\n }\n if (current.type === 'MemberExpression') {\n const member = current as MemberExpressionNode;\n if (!member.computed && member.property.type === 'Identifier') {\n property = (member.property as IdentifierNode).name;\n } else {\n property = null;\n }\n current = member.object;\n continue;\n }\n if (current.type === 'CallExpression') {\n property = null;\n current = (current as CallExpressionNode).callee;\n continue;\n }\n return null;\n }\n}\n\nfunction collectExpression(node: PositionedNode, facts: ModuleFacts): void {\n if (node.type === 'VariableDeclarator') {\n const id = node.id as PositionedNode | undefined;\n const init = node.init as PositionedNode | undefined;\n if (id?.type === 'Identifier' && init?.type === 'CallExpression') {\n const ref = calleeRef(init as unknown as CallExpressionNode);\n if (ref) facts.factoryCalls.set((id as IdentifierNode).name, ref);\n }\n return;\n }\n\n if (node.type !== 'CallExpression') return;\n const call = node as unknown as CallExpressionNode;\n const callee = call.callee;\n\n if (callee.type === 'Identifier') {\n facts.calledLocals.add((callee as IdentifierNode).name);\n return;\n }\n if (callee.type !== 'MemberExpression') return;\n const member = callee as MemberExpressionNode;\n if (member.computed || member.property.type !== 'Identifier') return;\n const propertyName = (member.property as IdentifierNode).name;\n\n if (propertyName === 'get') {\n const root = chainRoot(member.object);\n if (root) {\n facts.getterLocals.add(root.base);\n if (root.property) addToMapSet(facts.getterMembers, root.base, root.property);\n }\n return;\n }\n if (member.object.type === 'Identifier') {\n addToMapSet(facts.calledMembers, (member.object as IdentifierNode).name, propertyName);\n }\n}\n\n/**\n * Statements whose whole subtree is an import/export *clause* rather than code.\n *\n * The walk skips them so `referencedLocals` means \"the module body mentions\n * this name\". Without the skip every imported name would count as referenced,\n * and a pure barrel — which mentions its names only in the clauses — would be\n * indistinguishable from a module that uses them.\n */\nfunction isClauseOnly(node: PositionedNode): boolean {\n if (node.type === 'ImportDeclaration' || node.type === 'ExportAllDeclaration') return true;\n if (node.type === 'ExportNamedDeclaration') return !node.declaration;\n // `export default someBinding` forwards; `export default f()` is code.\n if (node.type === 'ExportDefaultDeclaration') {\n return (node.declaration as PositionedNode | undefined)?.type === 'Identifier';\n }\n return false;\n}\n\n/**\n * Keys holding *binding* positions rather than references: the name being\n * declared, not a mention of one.\n *\n * `referencedLocals` must exclude these or `export const filters =\n * defineSearchParams({})` would count as referencing `filters`, and possession\n * would then taint every definition module — and through it every page that\n * imports one, whether or not it reads the request. Skipping only these keys\n * keeps a shadowing parameter's *body* uses as references, which over-reports\n * in the safe direction.\n */\nconst BINDING_KEYS: Readonly<Record<string, readonly string[]>> = {\n VariableDeclarator: ['id'],\n FunctionDeclaration: ['id', 'params'],\n FunctionExpression: ['id', 'params'],\n ArrowFunctionExpression: ['params'],\n ClassDeclaration: ['id'],\n ClassExpression: ['id'],\n CatchClause: ['param'],\n};\n\nfunction walk(node: PositionedNode, facts: ModuleFacts): void {\n if (isClauseOnly(node)) return;\n if (node.type === 'Identifier') facts.referencedLocals.add((node as IdentifierNode).name);\n collectExpression(node, facts);\n const bindingKeys = BINDING_KEYS[node.type];\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n if (bindingKeys?.includes(key)) continue;\n const value = node[key];\n if (!value || typeof value !== 'object') continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n walk(item as PositionedNode, facts);\n }\n }\n } else if (typeof (value as PositionedNode).type === 'string') {\n walk(value as PositionedNode, facts);\n }\n }\n}\n\n/**\n * Record every binding, module edge, and call shape in one module.\n *\n * Names are recorded without scope analysis, so a parameter that shadows an\n * imported name is credited to the import. That direction is deliberate: a\n * needlessly request-dependent segment costs a re-render, a wrongly static one\n * serves stale content.\n */\nexport function analyzeModule(program: ProgramNode): ModuleFacts {\n const facts = createModuleFacts();\n\n for (const stmt of program.body) {\n switch (stmt.type) {\n case 'ImportDeclaration':\n collectImportDeclaration(stmt, facts);\n break;\n case 'ExportNamedDeclaration':\n collectExportNamed(stmt, facts);\n break;\n case 'ExportAllDeclaration':\n collectExportAll(stmt, facts);\n break;\n case 'ExportDefaultDeclaration':\n collectExportDefault(stmt, facts);\n break;\n }\n }\n\n walk(program, facts);\n return facts;\n}\n","/**\n * Binding-origin resolution across the module graph.\n *\n * Given a local name at a call site, walk import and re-export edges until the\n * binding lands somewhere that can be classified: a framework request accessor,\n * a definition factory, a definition object minted by one, or nothing of\n * interest. The walk is what makes the analysis indifferent to how the app\n * organises its own code — a barrel, an alias, a namespace import, and a\n * re-export chain five hops deep all reach the same origin (TIM-1291).\n *\n * The asymmetry that governs every judgement here: over-reporting costs a\n * re-render, under-reporting serves stale content to a client that cached a\n * slot whose render varies with the query. So an edge we cannot follow resolves\n * to `unknown`, and `unknown` counts as request-dependent.\n *\n * See design/19-client-navigation.md §\"Why the slot comparison ignores the query\".\n */\n\nimport type { CalleeRef, ImportEdge, ModuleFacts } from './analysis.ts';\n\n// ─── What counts as a request accessor ───────────────────────────────────\n\nconst ACCESSOR_SOURCES = new Set(['@timber-js/app/server', 'next/headers', 'next/headers.js']);\n\nconst ACCESSOR_NAMES = new Set([\n 'getHeaders',\n 'getHeader',\n 'getSearchParams',\n 'getCookieJar',\n 'getCookie',\n // next/headers shim names\n 'headers',\n 'cookies',\n]);\n\nconst DEFINITION_FACTORY_SOURCES = new Set([\n '@timber-js/app/search-params',\n '@timber-js/app/cookies',\n]);\n\nconst DEFINITION_FACTORY_NAMES = new Set(['defineSearchParams', 'defineCookie']);\n\n/** Every specifier the classifier recognises without resolving it. */\nexport const FRAMEWORK_SOURCES: ReadonlySet<string> = new Set([\n ...ACCESSOR_SOURCES,\n ...DEFINITION_FACTORY_SOURCES,\n]);\n\n// ─── Origins ─────────────────────────────────────────────────────────────\n\nexport type Origin =\n /** A request accessor: `getSearchParams`, `cookies`, … */\n | { kind: 'accessor' }\n /** A definition factory: `defineSearchParams`, `defineCookie`. */\n | { kind: 'factory' }\n /** A value minted by a definition factory — `.get()` on it reads the request. */\n | { kind: 'definition' }\n /** A namespace object for a framework module (`import * as h from 'next/headers'`). */\n | { kind: 'framework-namespace'; source: string }\n /** A namespace object for an app module. */\n | { kind: 'namespace'; moduleId: string }\n /** An edge that could not be followed. Treated as request-dependent. */\n | { kind: 'unknown' }\n /** Resolved, and not interesting. */\n | { kind: 'none' };\n\nconst NONE: Origin = { kind: 'none' };\nconst UNKNOWN: Origin = { kind: 'unknown' };\n\n/**\n * Classify an edge that points at a framework module, without resolving it.\n *\n * Returns `null` when the specifier is not a framework source, which is the\n * signal to keep walking. Both name sets are consulted for either source so a\n * specifier that grows a second role does not silently stop matching.\n */\nfunction classifySpecifier(source: string, imported: string): Origin | null {\n const isAccessorSource = ACCESSOR_SOURCES.has(source);\n const isFactorySource = DEFINITION_FACTORY_SOURCES.has(source);\n if (!isAccessorSource && !isFactorySource) return null;\n if (imported === '*') return { kind: 'framework-namespace', source };\n if (isAccessorSource && ACCESSOR_NAMES.has(imported)) return { kind: 'accessor' };\n if (isFactorySource && DEFINITION_FACTORY_NAMES.has(imported)) return { kind: 'factory' };\n return NONE;\n}\n\n/** An origin whose *call* reads the request. */\nfunction callReadsRequest(origin: Origin): boolean {\n return origin.kind === 'accessor' || origin.kind === 'unknown';\n}\n\n/** An origin whose `.get()` reads the request. */\nfunction getterReadsRequest(origin: Origin): boolean {\n return origin.kind === 'definition' || origin.kind === 'unknown';\n}\n\n// ─── Resolver ────────────────────────────────────────────────────────────\n\nexport interface OriginResolver {\n /** Does this module itself read the request? */\n isTainted(moduleId: string): boolean;\n /** Does this module hold a definition factory binding? */\n isDefinitionModule(moduleId: string): boolean;\n /** Does this module call `.get()` on a binding it imported? */\n callsGetterOnImport(moduleId: string): boolean;\n}\n\nexport function createOriginResolver(factsMap: ReadonlyMap<string, ModuleFacts>): OriginResolver {\n /**\n * Cycle guard. A `(module, export)` pair already being resolved contributes\n * `none`: anything it could reach is reachable on the path still unwinding.\n */\n const resolving = new Map<string, Set<string>>();\n\n function enter(moduleId: string, name: string): boolean {\n const names = resolving.get(moduleId);\n if (!names) {\n resolving.set(moduleId, new Set([name]));\n return true;\n }\n if (names.has(name)) return false;\n names.add(name);\n return true;\n }\n\n function leave(moduleId: string, name: string): void {\n resolving.get(moduleId)?.delete(name);\n }\n\n /** Follow one `import`/`export … from` edge out of `moduleId`. */\n function resolveEdge(moduleId: string, edge: ImportEdge): Origin {\n const classified = classifySpecifier(edge.source, edge.imported);\n if (classified) return classified;\n\n const facts = factsMap.get(moduleId);\n const targetId = facts?.resolvedSources.get(edge.source);\n if (!targetId) {\n // An unresolvable specifier is an edge we cannot follow, not an absence\n // of one. A specifier the plugin never tried to resolve (module not\n // analysed) lands here too, and both take the conservative branch.\n return facts?.unresolvedSources.has(edge.source) ? UNKNOWN : NONE;\n }\n if (edge.imported === '*') return { kind: 'namespace', moduleId: targetId };\n return resolveExport(targetId, edge.imported);\n }\n\n /** What does `moduleId` export under `name`? */\n function resolveExport(moduleId: string, name: string): Origin {\n const facts = factsMap.get(moduleId);\n if (!facts) return NONE;\n if (!enter(moduleId, `export:${name}`)) return NONE;\n try {\n const reExport = facts.reExports.get(name);\n if (reExport) return resolveEdge(moduleId, reExport);\n\n const local = facts.localExports.get(name);\n if (local !== undefined) return resolveLocal(moduleId, local);\n\n // `export * from './m'` does not name what it forwards, so every star\n // source is a candidate. Ambiguity is resolved conservatively: the first\n // source that classifies as anything wins.\n for (const source of facts.starReExports) {\n const viaStar = resolveEdge(moduleId, { source, imported: name });\n if (viaStar.kind !== 'none') return viaStar;\n }\n return NONE;\n } finally {\n leave(moduleId, `export:${name}`);\n }\n }\n\n /** What is the local binding `name` in `moduleId`? */\n function resolveLocal(moduleId: string, name: string): Origin {\n const facts = factsMap.get(moduleId);\n if (!facts) return NONE;\n if (!enter(moduleId, `local:${name}`)) return NONE;\n try {\n const imported = facts.importedBindings.get(name);\n if (imported) return resolveEdge(moduleId, imported);\n\n const factoryCall = facts.factoryCalls.get(name);\n if (factoryCall) {\n // `const filters = defineSearchParams(…)` — the *result* is a\n // definition, and `.get()` on it reads the request.\n const callee = resolveCallee(moduleId, factoryCall);\n if (callee.kind === 'factory') return { kind: 'definition' };\n if (callee.kind === 'unknown') return UNKNOWN;\n }\n return NONE;\n } finally {\n leave(moduleId, `local:${name}`);\n }\n }\n\n function resolveCallee(moduleId: string, ref: CalleeRef): Origin {\n if (ref.kind === 'local') return resolveLocal(moduleId, ref.name);\n return resolveMember(moduleId, ref.object, ref.property);\n }\n\n /** `ns.name` where `ns` is a local binding in `moduleId`. */\n function resolveMember(moduleId: string, object: string, name: string): Origin {\n const base = resolveLocal(moduleId, object);\n if (base.kind === 'framework-namespace') {\n return classifySpecifier(base.source, name) ?? NONE;\n }\n if (base.kind === 'namespace') return resolveExport(base.moduleId, name);\n if (base.kind === 'unknown') return UNKNOWN;\n return NONE;\n }\n\n const taintCache = new Map<string, boolean>();\n\n function computeTainted(moduleId: string, facts: ModuleFacts): boolean {\n for (const local of facts.calledLocals) {\n if (callReadsRequest(resolveLocal(moduleId, local))) return true;\n }\n for (const [object, members] of facts.calledMembers) {\n for (const member of members) {\n if (callReadsRequest(resolveMember(moduleId, object, member))) return true;\n }\n }\n for (const local of facts.getterLocals) {\n if (getterReadsRequest(resolveLocal(moduleId, local))) return true;\n }\n for (const [object, members] of facts.getterMembers) {\n for (const member of members) {\n if (getterReadsRequest(resolveMember(moduleId, object, member))) return true;\n }\n }\n return holdsRequestBinding(moduleId, facts);\n }\n\n /**\n * Possession, not use: a module that binds a request accessor or a definition\n * value under a local name is request-dependent whether or not the call is\n * one this analysis can see.\n *\n * The call-shape rules above only find a read that happens through the\n * binding itself. A value can leave the binding first — `const read = flag ?\n * getSearchParams : noop`, `const { get } = filters`, a prop handed to a\n * helper — and every one of those is a fresh way to be missed, which is the\n * shape of bug this ticket exists to stop enumerating. Nothing distinguishes\n * those from an honest unused import except intent, so importing the accessor\n * at all is treated as reading it.\n *\n * The rule is scoped by *reference*, not by export shape, and that scoping is\n * what keeps it from being useless: `import { getSearchParams } from\n * '@timber-js/app/server'; export { getSearchParams }` is a barrel whose body\n * never mentions the name, and tainting it would taint every page that\n * imports anything from that barrel. The forwarded name stays resolvable\n * through `resolveExport`, so the page that actually calls it is still caught\n * one hop later, in the module that uses it.\n *\n * Scoping on \"the module only forwards it\" would have been the natural\n * phrasing and is wrong: a barrel can forward a name *and* use it\n * (`export { getSearchParams }` beside `const read = flag ? getSearchParams\n * : noop`), and that module is exactly the one this rule exists to catch.\n * `referencedLocals` excludes import/export clauses and nothing else, so\n * forwarding is exempt only when it is all the module does with the name.\n *\n * `unknown` is deliberately not included: an unresolvable specifier taints\n * only when something is actually called or read on it, or every module with\n * one broken import would go request-dependent.\n */\n function holdsRequestBinding(moduleId: string, facts: ModuleFacts): boolean {\n for (const local of facts.referencedLocals) {\n const origin = resolveLocal(moduleId, local);\n if (origin.kind === 'accessor' || origin.kind === 'definition') return true;\n }\n return false;\n }\n\n return {\n isTainted(moduleId) {\n const cached = taintCache.get(moduleId);\n if (cached !== undefined) return cached;\n const facts = factsMap.get(moduleId);\n const result = facts ? computeTainted(moduleId, facts) : false;\n taintCache.set(moduleId, result);\n return result;\n },\n\n isDefinitionModule(moduleId) {\n const facts = factsMap.get(moduleId);\n if (!facts) return false;\n for (const edge of facts.importedBindings.values()) {\n const origin = resolveEdge(moduleId, edge);\n if (origin.kind === 'factory') return true;\n // `import * as sp from '@timber-js/app/search-params'` — the factory is\n // behind a member access, so the whole namespace counts.\n if (\n origin.kind === 'framework-namespace' &&\n DEFINITION_FACTORY_SOURCES.has(origin.source)\n ) {\n return true;\n }\n }\n return false;\n },\n\n callsGetterOnImport(moduleId) {\n const facts = factsMap.get(moduleId);\n if (!facts) return false;\n for (const local of facts.getterLocals) {\n if (facts.importedBindings.has(local)) return true;\n }\n return false;\n },\n };\n}\n","/**\n * timber-request-dep — Static module-graph analysis for request-dependency.\n *\n * Replaces runtime ALS-based taint tracking with a build/dev-time computed\n * map: segment entry file → statically request-dependent?\n *\n * A segment/slot is request-dependent iff any module reachable from its\n * layout/page/default in the RSC module graph (stopping at client-reference\n * boundaries) reads the request: it calls a request accessor (`getHeaders`,\n * `getSearchParams`, `cookies`, …) or calls `.get()` on a value minted by\n * `defineSearchParams` / `defineCookie`.\n *\n * \"Calls a request accessor\" is decided by resolving the call site's binding\n * back through import and re-export edges (`origin.ts`), not by matching the\n * calling module's own import declarations. That distinction is the whole\n * ticket: a barrel, an alias, or a namespace import used to make a page that\n * reads the query look static, and a static slot is cached and skipped on a\n * query-only navigation — serving stale content (TIM-1273, TIM-1291).\n *\n * This is deterministic, covers children/barrels/node_modules/Suspense-\n * deferred code, and is computed before any byte is flushed.\n *\n * See design/19-client-navigation.md §\"X-Timber-State-Tree Header\"\n */\n\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../../plugin-context.ts';\nimport type { ProgramNode } from '../callsite-ast.ts';\nimport { analyzeModule, usedSources, contributesNothing, type ModuleFacts } from './analysis.ts';\nimport { createOriginResolver, FRAMEWORK_SOURCES } from './origin.ts';\n\nexport type { ModuleFacts } from './analysis.ts';\nexport { analyzeModule, usedSources } from './analysis.ts';\nexport { createOriginResolver } from './origin.ts';\n\n// ─── Framework module detection ─────────────────────────────────────────\n\nexport function isFrameworkModule(id: string): boolean {\n return (\n /[\\\\/]node_modules[\\\\/]@timber-js[\\\\/]app[\\\\/]/.test(id) ||\n /[\\\\/]packages[\\\\/]timber-app[\\\\/]src[\\\\/]/.test(id)\n );\n}\n\n// ─── Pre-filter ──────────────────────────────────────────────────────────\n\n/**\n * Cheap gate before parsing.\n *\n * This used to be a substring match on the accessor and factory names, which\n * was sound only for the analysis it served: when a call site had to name the\n * framework binding in its own import declaration, a module with no such name\n * could not be a call site. Resolving bindings across the graph removes that\n * guarantee — with\n *\n * // _lib/index.ts\n * export { getSearchParams as query } from '@timber-js/app/server';\n * // page.tsx\n * import { query } from './_lib';\n * export default function Page() { return query(); }\n *\n * the page contains no accessor name, no `.get(`, and no re-export syntax, and\n * skipping it would have put the rename right back where the barrel was. So the\n * gate is now structural: a module matters if it has any module-level binding\n * to follow. What it skips is source with no `import` and no `export` at all —\n * data blobs, generated constants, side-effect scripts — none of which can name\n * a framework binding or forward one.\n */\nfunction hasModuleBindings(code: string): boolean {\n return code.includes('import') || code.includes('export');\n}\n\n// ─── Module graph reachability ───────────────────────────────────────────\n\nexport interface ReachabilityInput {\n factsMap: ReadonlyMap<string, ModuleFacts>;\n getImports: (id: string) => string[];\n /**\n * Does the graph this walk runs over contain this module at all?\n *\n * Only the entry needs asking. Every other id the walk visits comes out of\n * `getImports`, which enumerates edges the graph already resolved, so those\n * are known by construction. The entry comes from outside — the route\n * manifest's `filePath`, produced by the scanner from the filesystem — and\n * nothing guarantees it is spelled the way the graph spells it, or that the\n * module has been pulled through the pipeline yet.\n */\n isKnownModule: (id: string) => boolean;\n}\n\n/**\n * Walk the module graph from an entry, returning true if any module reachable\n * from it reads the request.\n *\n * Two passes, and the second is a deliberately blunt backstop:\n *\n * 1. **Binding origins.** For each reachable module, resolve every call site's\n * binding to its origin. This is precise and indifferent to indirection.\n * 2. **Definition reachability.** A module that calls `.get()` on *something*\n * it imported, with a module holding a definition factory reachable behind\n * that import, counts too. The origin walk cannot see through a value that\n * is computed rather than bound — `getFilterCookie(key).get()`, where the\n * helper returns a definition — and this pass can.\n *\n * The second pass over-reports by construction, which is the safe direction: a\n * needlessly request-dependent segment costs a re-render, a wrongly static one\n * serves stale content.\n *\n * An entry the graph does not contain is an edge we failed to walk, not the\n * absence of one — the same rule an unresolvable specifier gets. Without the\n * check it reads as an entry with no imports and no facts, and both passes fall\n * through to `false`: confidently request-INdependent, for a module nothing\n * ever looked at. In the build that answer is worse than no answer, because it\n * is written into `requestDep` as a definite `false` and the runtime's own\n * \"absent key → conservative\" fallback never fires.\n */\nexport function isReachableTaintSource(entryId: string, input: ReachabilityInput): boolean {\n const { factsMap, getImports, isKnownModule } = input;\n if (!isKnownModule(entryId)) return true;\n const resolver = createOriginResolver(factsMap);\n\n const visited = new Set<string>();\n const stack = [entryId];\n\n while (stack.length > 0) {\n const id = stack.pop()!;\n if (visited.has(id)) continue;\n visited.add(id);\n\n if (resolver.isTainted(id)) return true;\n\n for (const imp of getImports(id)) {\n // Stop at client boundaries — 'use client' modules in the RSC graph\n // resolve to generated proxy stubs with no further imports.\n // Also stop at virtual modules (they're framework internals).\n if (!imp.startsWith('\\0') && !visited.has(imp)) {\n stack.push(imp);\n }\n }\n }\n\n const reachesDefinition = makeDefinitionReachability(resolver.isDefinitionModule, getImports);\n for (const id of visited) {\n if (!resolver.callsGetterOnImport(id)) continue;\n if (reachesDefinition(id)) return true;\n }\n\n return false;\n}\n\n/**\n * \"Can a definition module be reached from this module's imports?\", memoized\n * across the queries one entry makes.\n *\n * Walks the graph rather than testing direct imports, because `export … from`\n * is an ordinary module edge and a barrel is the common way an app shares one\n * `defineSearchParams` across routes.\n *\n * Cycles terminate on the memo seeded with `false`; a module already being\n * resolved contributes nothing, which is correct — anything it could reach is\n * reachable on the path that is still unwinding.\n */\nfunction makeDefinitionReachability(\n isDefinitionModule: (id: string) => boolean,\n getImports: (id: string) => string[]\n): (id: string) => boolean {\n const cache = new Map<string, boolean>();\n\n return function reaches(id: string): boolean {\n const cached = cache.get(id);\n if (cached !== undefined) return cached;\n cache.set(id, false); // cycle guard: assume false while resolving\n\n let result = false;\n for (const imp of getImports(id)) {\n if (imp.startsWith('\\0')) continue;\n if (isDefinitionModule(imp) || reaches(imp)) {\n result = true;\n break;\n }\n }\n cache.set(id, result);\n return result;\n };\n}\n\n// ─── Plugin ──────────────────────────────────────────────────────────────\n\nconst BRIDGE_KEY = Symbol.for('timber:request-dep');\n\ninterface ResolvePluginContext {\n parse(code: string): ProgramNode;\n resolve(source: string, importer: string): Promise<{ id: string } | null>;\n}\n\n/**\n * Resolve every specifier the module has an edge to, so the origin walk can\n * follow them later without a module graph.\n *\n * Framework specifiers are classified by name and never resolved — that is what\n * keeps the terminal check independent of how `@timber-js/app` happens to be\n * installed. A specifier that fails to resolve is recorded as unresolved rather\n * than dropped, so the walk can take the conservative branch on it.\n */\nasync function resolveEdgeSources(\n pluginCtx: ResolvePluginContext,\n facts: ModuleFacts,\n importer: string\n): Promise<void> {\n for (const source of usedSources(facts)) {\n if (FRAMEWORK_SOURCES.has(source)) continue;\n try {\n const resolved = await pluginCtx.resolve(source, importer);\n if (resolved?.id) facts.resolvedSources.set(source, resolved.id);\n else facts.unresolvedSources.add(source);\n } catch {\n facts.unresolvedSources.add(source);\n }\n }\n}\n\nexport function timberRequestDep(ctx: PluginContext): Plugin {\n const factsMap = new Map<string, ModuleFacts>();\n const cache = new Map<string, boolean>();\n\n return {\n name: 'timber-request-dep',\n // Only run in RSC environment — that's where server components render.\n applyToEnvironment(env) {\n return env.name === 'rsc';\n },\n\n async transform(code, id) {\n // Skip non-JS (include .mdx/.md — compiled to JS by timber-mdx before this runs)\n if (!/\\.[mc]?[jt]sx?$/.test(id) && !/\\.mdx?$/.test(id)) return;\n // Skip virtual modules\n if (id.startsWith('\\0') || id.startsWith('virtual:')) return;\n // Skip framework modules — their internal accessor calls (e.g.,\n // getCookieJar in define-cookie.ts) are implementation details.\n // In dev they're externalized and never reach transform; in prod\n // they would cause false positives (any module importing defineCookie\n // would be tainted). Analysis relies on user-code call patterns.\n if (isFrameworkModule(id)) return;\n // Cheap structural gate\n if (!hasModuleBindings(code)) return;\n\n const pluginCtx = this as unknown as ResolvePluginContext;\n const facts = analyzeModule(pluginCtx.parse(code));\n if (contributesNothing(facts)) {\n factsMap.delete(id);\n return undefined;\n }\n await resolveEdgeSources(pluginCtx, facts, id);\n factsMap.set(id, facts);\n\n // No code transform needed — this is analysis only.\n return undefined;\n },\n\n configureServer(server) {\n // Register the bridge so runtime can query request-dep status.\n const resolver = (filePath: string): boolean => {\n if (cache.has(filePath)) return cache.get(filePath)!;\n\n const rscEnv = server.environments?.rsc;\n if (!rscEnv?.moduleGraph) {\n return true; // Unknown → conservative\n }\n\n const getImports = (moduleId: string): string[] => {\n const mod = rscEnv.moduleGraph.getModuleById(moduleId);\n if (!mod) return [];\n const result: string[] = [];\n for (const imp of mod.importedModules) {\n if (imp.id) result.push(imp.id);\n }\n return result;\n };\n\n const isKnownModule = (moduleId: string): boolean =>\n rscEnv.moduleGraph.getModuleById(moduleId) !== undefined;\n\n const result = isReachableTaintSource(filePath, { factsMap, getImports, isKnownModule });\n\n // Do not memoize the conservative answer for an entry the graph has\n // not seen. Dev loads modules on demand, so \"unknown\" is a statement\n // about *now*, and the cache is only invalidated by file events —\n // caching it would pin the segment request-dependent for the rest of\n // the session even after the module is pulled in.\n if (isKnownModule(filePath)) cache.set(filePath, result);\n return result;\n };\n\n (globalThis as Record<symbol, unknown>)[BRIDGE_KEY] = resolver;\n\n // Clear cache on file changes\n const clearCache = () => cache.clear();\n server.watcher.on('change', clearCache);\n server.watcher.on('add', clearCache);\n server.watcher.on('unlink', clearCache);\n },\n\n buildEnd() {\n // Prod: compute the full map and register on globalThis for the\n // build manifest plugin to pick up.\n if (ctx.dev) return;\n\n const getModuleInfo = (\n this as unknown as {\n getModuleInfo: (\n id: string\n ) => { importedIds?: string[]; dynamicallyImportedIds?: string[] } | null;\n }\n ).getModuleInfo;\n\n const getImports = (moduleId: string): string[] => {\n const info = getModuleInfo(moduleId);\n if (!info) return [];\n return [...(info.importedIds ?? []), ...(info.dynamicallyImportedIds ?? [])];\n };\n\n // `!= null` rather than `!== null`: the declared return type is\n // `… | null`, but a bundler that hands back `undefined` for an unknown\n // id would otherwise read as \"known\" and put us right back on the\n // confidently-wrong `false`.\n const isKnownModule = (moduleId: string): boolean => getModuleInfo(moduleId) != null;\n\n const requestDepMap: Record<string, boolean> = {};\n\n // Walk the route tree to find all segment entry files\n if (ctx.routeTree) {\n walkSegmentTree(ctx.routeTree.root as unknown as WalkableNode, (filePath: string) => {\n requestDepMap[filePath] = isReachableTaintSource(filePath, {\n factsMap,\n getImports,\n isKnownModule,\n });\n });\n }\n\n // Store on ctx for build-manifest plugin to serialize into the manifest.\n // Prod runtime reads from __TIMBER_BUILD_MANIFEST__.requestDep.\n //\n // Assigned unconditionally, including when there is no route tree to\n // walk: the field's presence is what tells the build-manifest plugin the\n // analysis ran at all, so leaving it undefined on the empty-tree path\n // would report \"the RSC environment never analysed anything\" for an app\n // that genuinely has no segments.\n ctx.requestDepMap = requestDepMap;\n },\n };\n}\n\ninterface WalkableNode {\n layout?: { filePath: string };\n page?: { filePath: string };\n default?: { filePath: string };\n children?: unknown[];\n slots?: Record<string, unknown>;\n}\n\nfunction walkSegmentTree(node: WalkableNode, fn: (filePath: string) => void): void {\n if (node.layout) fn(node.layout.filePath);\n if (node.page) fn(node.page.filePath);\n if (node.default) fn((node.default as { filePath: string }).filePath);\n if (node.children) {\n for (const child of node.children) {\n walkSegmentTree(child as typeof node, fn);\n }\n }\n if (node.slots) {\n for (const slot of Object.values(node.slots)) {\n walkSegmentTree(slot as typeof node, fn);\n }\n }\n}\n","/**\n * JSX call-site props extraction for prebuilt components (TIM-1142).\n *\n * At build time, the timber-prebuilt transform captures the exact props\n * from each JSX usage site of a cache.component binding so the post-build\n * capture pass can prerender entries for each distinct prop set. Only\n * statically analyzable props (JSON-safe literals, arrays, and plain\n * objects) are captured; dynamic/computed props bail — those call sites\n * fall back to live rendering per design/44 §Props Derivation.\n *\n * See design/44-render-at-build-time.md §Props Derivation at Build Time.\n */\n\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { IdentifierNode, PositionedNode, ProgramNode } from './callsite-ast.ts';\n\ninterface JSXElementNode extends PositionedNode {\n type: 'JSXElement';\n openingElement: {\n type: 'JSXOpeningElement';\n name: PositionedNode;\n attributes: PositionedNode[];\n };\n}\n\ninterface JSXAttributeNode extends PositionedNode {\n type: 'JSXAttribute';\n name: { type: string; name?: string };\n value: PositionedNode | null;\n}\n\ninterface JSXExpressionContainerNode extends PositionedNode {\n type: 'JSXExpressionContainer';\n expression: PositionedNode;\n}\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/**\n * Try to extract a static JSON-safe value from an AST expression node.\n * Returns `undefined` (not null — null is a valid JSON value) when the\n * expression is dynamic/computed and cannot be captured statically.\n */\nfunction tryExtractStaticValue(node: PositionedNode): JsonValue | undefined {\n if (node.type === 'Literal') {\n const val = (node as { value?: unknown }).value;\n if (\n val === null ||\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n return val as JsonValue;\n }\n return undefined; // regex or bigint literal\n }\n if (node.type === 'UnaryExpression') {\n const unary = node as unknown as { operator: string; argument: PositionedNode };\n if (unary.operator === '-' && unary.argument.type === 'Literal') {\n const val = (unary.argument as { value?: unknown }).value;\n if (typeof val === 'number') return -val;\n }\n return undefined;\n }\n if (node.type === 'TemplateLiteral') {\n const tpl = node as unknown as {\n quasis: { value: { cooked: string } }[];\n expressions: unknown[];\n };\n if (tpl.expressions.length === 0) return tpl.quasis[0]?.value.cooked ?? undefined;\n return undefined;\n }\n if (node.type === 'ArrayExpression') {\n const elements = (node as unknown as { elements: (PositionedNode | null)[] }).elements;\n const arr: JsonValue[] = [];\n for (const el of elements) {\n if (el === null) return undefined; // sparse\n const val = tryExtractStaticValue(el);\n if (val === undefined) return undefined;\n arr.push(val);\n }\n return arr;\n }\n if (node.type === 'ObjectExpression') {\n const properties = (node as unknown as { properties: PositionedNode[] }).properties;\n const obj: Record<string, JsonValue> = {};\n for (const prop of properties) {\n if (prop.type === 'SpreadElement') return undefined;\n if (prop.type !== 'Property') return undefined;\n const p = prop as unknown as {\n computed?: boolean;\n key: PositionedNode & { name?: string; value?: unknown };\n value: PositionedNode;\n };\n if (p.computed) return undefined;\n const keyName =\n p.key.type === 'Identifier'\n ? p.key.name\n : p.key.type === 'Literal'\n ? String(p.key.value)\n : undefined;\n if (keyName === undefined) return undefined;\n const val = tryExtractStaticValue(p.value);\n if (val === undefined) return undefined;\n obj[keyName] = val;\n }\n return obj;\n }\n return undefined;\n}\n\n/**\n * Extract static props from a JSX element's attributes. Returns null if\n * any attribute is dynamic (spread, computed expression, JSX element, etc.)\n * — the component must fall back to dynamic rendering for that call site.\n */\nexport function extractStaticJsxProps(\n attributes: PositionedNode[]\n): Record<string, JsonValue> | null {\n const props: Record<string, JsonValue> = {};\n for (const attr of attributes) {\n if (attr.type === 'JSXSpreadAttribute') return null;\n if (attr.type !== 'JSXAttribute') return null;\n const jsxAttr = attr as unknown as JSXAttributeNode;\n const name = jsxAttr.name?.name;\n if (!name) return null;\n // React strips key and ref before passing to component props — including\n // them would produce cache entries unaddressable at request time.\n if (name === 'key' || name === 'ref') continue;\n if (jsxAttr.value === null) {\n props[name] = true;\n continue;\n }\n if (jsxAttr.value.type === 'Literal') {\n const val = tryExtractStaticValue(jsxAttr.value);\n if (val === undefined) return null;\n props[name] = val;\n continue;\n }\n if (jsxAttr.value.type === 'JSXExpressionContainer') {\n const container = jsxAttr.value as unknown as JSXExpressionContainerNode;\n const val = tryExtractStaticValue(container.expression);\n if (val === undefined) return null;\n props[name] = val;\n continue;\n }\n return null;\n }\n return props;\n}\n\n/**\n * Walk an AST tree and collect JSX usages of the given binding names,\n * returning the static props for each usage. Returns a map of\n * bindingName → array of static prop objects (or null for dynamic props).\n */\nexport function collectJsxUsages(\n program: ProgramNode,\n bindingNames: Set<string>\n): Map<string, Array<Record<string, JsonValue> | null>> {\n const result = new Map<string, Array<Record<string, JsonValue> | null>>();\n const walk = (node: unknown) => {\n if (!node || typeof node !== 'object') return;\n const n = node as PositionedNode;\n if (n.type === 'JSXElement') {\n const jsx = n as unknown as JSXElementNode;\n const tagName = jsx.openingElement.name;\n if (tagName.type === 'JSXIdentifier') {\n const name = (tagName as IdentifierNode).name;\n if (bindingNames.has(name)) {\n // Children become props.children at runtime — if the element has\n // children we can't capture the full props shape statically, so\n // treat it as a dynamic call site (bail to null).\n const children = (jsx as unknown as { children?: unknown[] }).children ?? [];\n const hasChildren =\n children.length > 0 &&\n children.some((c: unknown) => {\n const child = c as PositionedNode;\n if (child.type === 'JSXText') {\n // Whitespace-only text nodes are not passed as children\n return (child as unknown as { value: string }).value.trim().length > 0;\n }\n return true;\n });\n const props = hasChildren ? null : extractStaticJsxProps(jsx.openingElement.attributes);\n const usages = result.get(name) ?? [];\n usages.push(props);\n result.set(name, usages);\n }\n }\n }\n for (const value of Object.values(n)) {\n if (Array.isArray(value)) {\n for (const item of value) walk(item);\n } else if (value && typeof value === 'object' && 'type' in value) {\n walk(value);\n }\n }\n };\n for (const stmt of program.body) walk(stmt);\n return result;\n}\n\n/**\n * Deep stable JSON stringification with recursively sorted keys.\n * `JSON.stringify` with an array replacer only includes listed keys at\n * ALL nesting levels, so `{config:{theme:'dark'}}` and\n * `{config:{theme:'light'}}` would both serialize as `{\"config\":{}}`.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return '[' + value.map(stableStringify).join(',') + ']';\n const obj = value as Record<string, unknown>;\n const parts = Object.keys(obj)\n .sort()\n .map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k]));\n return '{' + parts.join(',') + '}';\n}\n\n/**\n * Add a distinct props object to the call-site-props map for a component,\n * deduplicating by deep JSON value (recursively sorted keys).\n */\nexport function recordCallSiteProps(\n ctx: PluginContext,\n componentId: string,\n props: Record<string, JsonValue>\n): void {\n ctx.prebuiltCallSiteProps ??= new Map();\n const existing = ctx.prebuiltCallSiteProps.get(componentId) ?? [];\n const canonical = stableStringify(props);\n const isDuplicate = existing.some((p) => stableStringify(p) === canonical);\n if (!isDuplicate) {\n existing.push(props);\n ctx.prebuiltCallSiteProps.set(componentId, existing);\n }\n}\n","/**\n * Static analysis of `cache.component(fn, options)` option literals for\n * the timber-prebuilt transform: can this call site's options put the\n * component in the prerender tier?\n *\n * Runtime-tier call sites must do NO build work — recording them would\n * make the post-build hook import the built RSC entry (running production\n * startup) and load route modules for routes that have nothing to\n * prerender (codex P2 on PR #836). The analysis is conservative in one\n * direction only: over-inclusion costs a wasted entry load (the capture\n * pass re-checks the real options at runtime and skips), under-inclusion\n * would silently skip prerendering.\n */\n\nimport type { CallExpressionNode, PositionedNode } from './callsite-ast.ts';\n\nconst EXPRESSION_WRAPPER_TYPES = new Set([\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'ParenthesizedExpression',\n]);\n\n/** Unwrap TS expression wrappers (`as`, `satisfies`, `!`, parens). */\nexport function unwrapExpression(node: PositionedNode): PositionedNode {\n let current = node;\n while (EXPRESSION_WRAPPER_TYPES.has(current.type) && current.expression) {\n current = current.expression as PositionedNode;\n }\n return current;\n}\n\ninterface ObjectPropertyNode extends PositionedNode {\n type: 'Property';\n computed?: boolean;\n key: PositionedNode & { name?: string; value?: unknown };\n value: PositionedNode & { value?: unknown };\n}\n\n/** Three-state static knowledge about a property's runtime effect. */\ntype Tri = 'yes' | 'no' | 'unknown';\n\n/**\n * Statically classify a `slots` value node against resolveSlotNames'\n * runtime rules (server/prebuilt/slots.ts):\n *\n * - `yes` — certainly an ACTIVE shape: dense, non-empty array literal of\n * non-empty string literals.\n * - `no` — certainly NOT active (absent/empty/malformed): registration\n * falls back to non-slot semantics with `prerender` preserved.\n * - `unknown` — identifiers, spreads, holes, non-literal elements.\n */\nfunction classifySlotsValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'ArrayExpression') {\n const elements = ((value as unknown as { elements: (PositionedNode | null)[] }).elements ??\n []) as (PositionedNode | null)[];\n if (elements.length === 0) return 'no'; // empty → kind 'none'\n let allValidStrings = true;\n for (const el of elements) {\n if (el === null) return 'no'; // hole → sparse → malformed at runtime\n if (el.type === 'SpreadElement') return 'unknown';\n const entry = unwrapExpression(el) as { type: string; value?: unknown };\n if (entry.type !== 'Literal') {\n allValidStrings = false; // could still be a valid string at runtime\n continue;\n }\n if (typeof entry.value !== 'string' || entry.value.length === 0) {\n return 'no'; // a non-string/empty literal is malformed regardless of the rest\n }\n }\n return allValidStrings ? 'yes' : 'unknown';\n }\n if (value.type === 'Literal') return 'no'; // null / primitive → malformed → disabled\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') {\n return 'no'; // absent\n }\n return 'unknown';\n}\n\n/** Statically classify whether a `ttl` value gives a runtime lifetime (`ttl !== undefined`). */\nfunction classifyTtlValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'Literal') return 'yes'; // any literal (number, null, …) !== undefined\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') return 'no';\n return 'unknown';\n}\n\n/** Statically classify whether a `tags` value gives a runtime lifetime (`tags != null`). */\nfunction classifyTagsValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'ArrayExpression') return 'yes';\n if (value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression') return 'yes';\n if (value.type === 'Literal') {\n return (value as { value?: unknown }).value === null ? 'no' : 'yes';\n }\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') return 'no';\n return 'unknown';\n}\n\n/**\n * Can this call site's options put the component in the prerender tier?\n * The answer is static only when the options argument is an object\n * literal:\n *\n * - literal with `prerender: true` → yes\n * - literal with `prerender: false`/absent → no (spread-free)\n * - literal with statically ACTIVE `slots` + certain runtime lifetime\n * → no — registration strips `prerender` for active slot components\n * (TIM-1173), so attributing the callsite would make the post-build\n * hook import the RSC entry and enumerate route params for entries\n * the capture pass then skips (codex P2 on PR #890)\n * - anything else (identifier, spread, non-literal values)\n * → conservatively yes — the capture pass re-checks at runtime\n *\n * Properties walk in source order with last-write-wins, mirroring\n * object-literal evaluation: `{ prerender: false, ...opts }` may end up\n * prerenderable (the spread can override), while `{ ...opts,\n * prerender: false }` is statically false (codex P2 on PR #836).\n * Computed keys are treated like spreads — they may evaluate to any of\n * the tracked names.\n */\nexport function mayPrerender(call: CallExpressionNode): boolean {\n if (call.arguments.length < 2) return false; // no options → no lifetime → never prerender\n const options = unwrapExpression(call.arguments[1] as PositionedNode);\n if (options.type !== 'ObjectExpression') return true;\n const properties = (options as unknown as { properties: PositionedNode[] }).properties ?? [];\n\n type Verdict = 'absent' | 'true' | 'false' | 'unknown';\n let verdict: Verdict = 'absent';\n let slotsActive: Tri = 'no'; // absent slots are certainly not active\n let ttl: Tri = 'no';\n let tags: Tri = 'no';\n\n for (const prop of properties) {\n if (prop.type === 'SpreadElement' || (prop as ObjectPropertyNode).computed) {\n // A spread/computed key may write ANY of the tracked options.\n verdict = 'unknown';\n slotsActive = 'unknown';\n ttl = 'unknown';\n tags = 'unknown';\n continue;\n }\n if (prop.type !== 'Property') continue;\n const property = prop as ObjectPropertyNode;\n const keyName =\n property.key.type === 'Identifier'\n ? property.key.name\n : property.key.type === 'Literal'\n ? String(property.key.value)\n : undefined;\n if (keyName === 'prerender') {\n const value = unwrapExpression(property.value);\n if (value.type === 'Literal') {\n verdict = (value as { value?: unknown }).value === true ? 'true' : 'false';\n } else {\n verdict = 'unknown'; // `prerender: flag` — not statically known\n }\n } else if (keyName === 'slots') {\n slotsActive = classifySlotsValue(property.value);\n } else if (keyName === 'ttl') {\n ttl = classifyTtlValue(property.value);\n } else if (keyName === 'tags') {\n tags = classifyTagsValue(property.value);\n }\n }\n\n if (verdict !== 'true' && verdict !== 'unknown') return false;\n // Active slots + certain runtime lifetime → registration strips\n // prerender, so the callsite is certainly runtime-tier. Any uncertainty\n // (slots or lifetime not statically known) keeps the conservative\n // attribution.\n if (slotsActive === 'yes' && (ttl === 'yes' || tags === 'yes')) return false;\n return true;\n}\n","/**\n * Post-build prebuilt capture — Node-side orchestration (TIM-1119).\n *\n * Runs as the capture step of the post-build phase (plugins/post-build.ts),\n * after Vite's 5-step build sequence and the manifest finalization step. Imports the BUILT `rsc/index.js` (the bundle carries\n * the react-server condition resolved at build time, so a plain dynamic\n * import works) and calls its `__timber_capturePrebuilt` export — the\n * capture itself must run inside the bundle's module graph, where the\n * component registry and flight renderer live. See\n * server/prebuilt-builder.ts and design/44-render-at-build-time.md\n * §Build Phase.\n *\n * This side owns PERSISTENCE: each captured payload is written to\n * `.timber/dist/prebuilt/<componentId>/<cacheKey>.flight` atomically\n * (temp file + rename — a crashed build never leaves a torn artifact\n * under its final name), and `manifest.json` is written last, only after\n * every payload it references is fully on disk. Keeping node:fs on the\n * plugin side keeps it out of the server bundle, which must also run on\n * Cloudflare Workers.\n *\n * NOTE: importing the built entry runs the app's production startup —\n * instrumentation.ts register() and the configured cache handler load\n * inside the build process. That is by design (prebuilt components may\n * call timber.cache), and it only happens when the app actually declares\n * prebuilt components.\n */\n\nimport { mkdir, rm } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { writeFileAtomic } from '../utils/write-file-atomic.ts';\n\nimport type { DirectoryArtifact } from '../adapters/types.ts';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { CaptureOptions, CaptureSummary, CapturedEntry } from '../server/prebuilt-builder.ts';\nimport type { PrebuiltManifest } from '../server/prebuilt/payload-source.ts';\n\n// ─── Artifact writer ──────────────────────────────────────────────────────\n\n/**\n * Both patterns are framework-generated (plugins/prebuilt.ts assigns IDs,\n * server/prebuilt/cache-key.ts hashes keys), so a mismatch is a framework\n * bug or a tampered registry — either way it must never reach a path join.\n */\nconst COMPONENT_ID_RE = /^[a-z0-9]+_[0-9a-f]{16}$/;\nconst CACHE_KEY_RE = /^[0-9a-f]{16}$/;\n\nexport interface PrebuiltArtifactWriter {\n write(entry: CapturedEntry): Promise<void>;\n /** Write manifest.json (if any entries exist). Returns the entry count. */\n finalize(): Promise<number>;\n}\n\n/**\n * Create the writer for `.timber/dist/prebuilt/`. Storage layout per\n * design/44 §Storage: one directory per component ID, one `.flight` file\n * per cache key, one manifest.json mapping componentId + key → file +\n * metadata.\n */\nexport function createPrebuiltArtifactWriter(prebuiltDir: string): PrebuiltArtifactWriter {\n const manifest: PrebuiltManifest = {};\n const buildTimestamp = Date.now();\n let count = 0;\n\n return {\n async write(entry: CapturedEntry): Promise<void> {\n if (!COMPONENT_ID_RE.test(entry.componentId) || !CACHE_KEY_RE.test(entry.cacheKey)) {\n throw new Error(\n `[timber] prebuilt artifact writer received a malformed identity ` +\n `(componentId: ${JSON.stringify(entry.componentId)}, cacheKey: ` +\n `${JSON.stringify(entry.cacheKey)}) — refusing to write`\n );\n }\n const relativeFile = `${entry.componentId}/${entry.cacheKey}.flight`;\n const path = join(prebuiltDir, relativeFile);\n await mkdir(dirname(path), { recursive: true });\n await writeFileAtomic(path, entry.bytes);\n\n manifest[entry.componentId] ??= { entries: {} };\n if (entry.paramIndependent) manifest[entry.componentId].paramIndependent = true;\n manifest[entry.componentId].entries[entry.cacheKey] = {\n params: entry.params,\n file: relativeFile,\n bytes: entry.bytes.byteLength,\n buildTimestamp,\n ...(entry.tags ? { tags: entry.tags } : {}),\n };\n count++;\n },\n\n async finalize(): Promise<number> {\n if (count === 0) return 0;\n await writeFileAtomic(\n join(prebuiltDir, 'manifest.json'),\n JSON.stringify(manifest, null, 2) + '\\n'\n );\n return count;\n },\n };\n}\n\n/** What a capture pass produced. */\nexport interface PrebuiltCaptureResult {\n summary: CaptureSummary;\n /** The payload directory — present only when the pass wrote a payload. */\n artifact?: DirectoryArtifact;\n}\n\n/**\n * Remove any `prebuilt/` output left by a previous build in this\n * directory (watch mode, `emptyOutDir: false`). A stale manifest would\n * make adapters ship payloads from an OLD build — reviving them serves\n * outdated content with that build's chunk references instead of the\n * intended miss → live render. Runs unconditionally at the start of the\n * capture step, BEFORE the capture decision: a build whose app no\n * longer declares any prebuilt components must also shed the artifacts\n * (codex P2 on PR #836).\n */\nexport async function cleanPrebuiltDir(buildDir: string): Promise<void> {\n await rm(join(buildDir, 'prebuilt'), { recursive: true, force: true });\n}\n\n// ─── Capture orchestration ────────────────────────────────────────────────\n\n/** Shape of the built RSC entry's capture export. */\ninterface CaptureModule {\n __timber_capturePrebuilt?: (options: CaptureOptions) => Promise<CaptureSummary>;\n}\n\n/**\n * Load the built RSC entry and run the capture pass. Throws (failing the\n * build) on infrastructure errors — missing/unloadable entry — and on\n * dynamic-context hard errors (cookies()/headers() in a prerendered\n * component). Per-entry data errors skip-and-report per design/44\n * §Build-Phase Error Handling.\n */\nexport async function runPrebuiltCapture(\n ctx: PluginContext,\n rscDir: string\n): Promise<PrebuiltCaptureResult> {\n const routeComponents = ctx.routePrebuiltComponents;\n if (!routeComponents || routeComponents.size === 0) {\n return { summary: { captured: 0, skipped: [], hardErrors: [], nestingWarnings: 0 } };\n }\n const entryPath = join(rscDir, 'index.js');\n\n // The build manifest global the bundle reads is published by the\n // post-build phase before this step runs (plugins/post-build.ts).\n const g = globalThis as Record<string, unknown>;\n\n console.log('[timber] cache.component: capturing prebuilt flight payloads…');\n\n // Tell the RSC entry to skip createRequestHandler — the capture pass\n // only needs __timber_capturePrebuilt + the route manifest. Running the\n // full production startup (instrumentation, cache handler, CDN purge,\n // OTEL tracing, route matchers) is wasted work that can take 100+ seconds\n // on large apps.\n g.__TIMBER_CAPTURE_MODE__ = true;\n\n let mod: CaptureModule;\n try {\n // Cache-busting query: in a long-lived build process (vite build\n // --watch), a bare file URL would return the FIRST build's module from\n // the ESM cache — stale code and a stale (already-walked) registry.\n const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;\n mod = (await import(/* @vite-ignore */ entryUrl)) as CaptureModule;\n } catch (error) {\n // A missing entry lands here too: the import is the existence check.\n throw new Error(\n `[timber] prebuilt capture: failed to load the built RSC entry (${entryPath}). ` +\n `The capture pass runs the production server module inside the build process — ` +\n `its startup must succeed for prerendering to work.`,\n { cause: error }\n );\n }\n const capture = mod.__timber_capturePrebuilt;\n if (typeof capture !== 'function') {\n throw new Error(\n `[timber] prebuilt capture: built RSC entry does not export __timber_capturePrebuilt — ` +\n `the build output predates this framework version; rebuild from a clean .timber/dist`\n );\n }\n\n const prebuiltDir = join(ctx.buildDir, 'prebuilt');\n const writer = createPrebuiltArtifactWriter(prebuiltDir);\n const summary = await capture({\n fileComponentMap: Object.fromEntries(routeComponents),\n callSiteProps: ctx.prebuiltCallSiteProps\n ? Object.fromEntries(ctx.prebuiltCallSiteProps)\n : undefined,\n lazyChunks: ctx.prebuiltLazyChunks ? Object.fromEntries(ctx.prebuiltLazyChunks) : undefined,\n onEntry: (entry) => writer.write(entry),\n });\n\n if (summary.hardErrors.length > 0) {\n const details = summary.hardErrors.map((issue) => ` - ${issue.message}`).join('\\n');\n throw new Error(\n `[timber] prebuilt capture failed: ${summary.hardErrors.length} component(s) read ` +\n `per-request context at build time:\\n${details}`\n );\n }\n\n // The manifest is written only when a payload was, so this is the one\n // point that knows whether prebuilt/ is a product of this build.\n const written = await writer.finalize();\n\n const total = summary.captured + summary.skipped.length;\n console.log(\n `[timber] Prebuilt ${summary.captured}/${total} entries.` +\n (summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : '')\n );\n return written > 0 ? { summary, artifact: { path: prebuiltDir } } : { summary };\n}\n","/**\n * timber-prebuilt — Vite plugin that detects `cache.component(...)` call\n * sites and rewrites them to `__prebuilt(stableId, component, options)`.\n *\n * `timber.cache.component(Component, { prerender: true })` is a build-time\n * transform, not a runtime function (design/44-render-at-build-time.md\n * §Registration, surface API renamed by design/45-cache-lifetimes.md). The\n * rewrite registers the component in the server-side prebuilt registry under\n * a stable ID that keys its cached flight payloads.\n *\n * Detected callsite forms (mirrors timber-cache-transform, TIM-1054):\n * - named imports, including aliases:\n * `import { cache } from '@timber-js/app/cache'` + `cache.component(fn, opts)`\n * - namespace imports:\n * `import * as timber` + `timber.cache.component(fn, opts)`\n * Computed access (`cache['component']`) is deliberately not matched — the\n * untransformed call reaches the runtime `cache.component` fallback\n * (cache/cache-api.ts), which warns once and renders dynamically.\n *\n * Matching is an ALLOWLIST of module-scope positions: the direct initializer\n * of a top-level variable declarator (including exported ones) and a\n * top-level `export default cache.component(...)`, with TS expression\n * wrappers (`as`, `satisfies`, `!`) unwrapped. Nothing else is walked — no\n * function/class/loop bodies, no params, no call arguments. Two reasons:\n * (1) `__prebuilt` must register exactly once at module load time; the\n * post-build capture pass walks the registry after loading modules, so a\n * call inside a function registers too late to ever be prebuilt, and a call\n * in a loop would re-register per iteration. (2) Name-based callee matching\n * is only shadow-proof in these positions — nested scopes can rebind `cache`\n * (`function render(cache) {...}`, `for (const cache of caches) ...`), and\n * rewriting those would corrupt user code; a top-level declarator initializer\n * cannot see a shadow of an import binding (redeclaration error). Calls in\n * other positions fall back to the runtime path like other untraceable forms.\n *\n * The rewrite per mode:\n * production: cache.component(fn, opts) → __prebuilt(\"<id>\", fn, opts)\n * dev: cache.component(fn, opts) → __prebuiltDev(\"<name>\", fn, opts)\n *\n * with `import { __prebuilt } from '#server-internal'` prepended. In dev the\n * wrapper is a no-op that logs once per component and renders dynamically —\n * no caching, no markers (design/44 §Dev Mode).\n *\n * Component identity: `<name>_<hash16>`, e.g. `blogbody_a1b2c3d4e5f6a7b8`.\n * The name prefix is the declaring variable's name (lowercased, for legible\n * manifest keys and log lines); the hash is the same content-derived callsite\n * scheme as the data cache transform (callsite-ast.ts) — deterministic across\n * builds for unchanged calls, immune to inserting/reordering other calls, and\n * fresh when the component or its options change. Component cache entries are\n * per-deploy (design/45 §Per-deploy namespacing) so cross-deploy ID reuse is\n * not a poisoning vector, but content-derived IDs keep prebuilt artifacts\n * addressable across incremental edits for free.\n *\n * The transform is skipped in the client environment: server components never\n * execute there, and `#server-internal` resolves to an empty stub in the\n * client bundle (plugins/shims.ts).\n *\n * See TIM-1118, design/44-render-at-build-time.md, design/45-cache-lifetimes.md.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode } from '../routing/types.ts';\nimport {\n CACHE_MODULE_SOURCES,\n findImportBindings,\n generateStableCallsiteId,\n} from './callsite-ast.ts';\nimport { collectJsxUsages, recordCallSiteProps } from './callsite-jsx.ts';\nimport { mayPrerender, unwrapExpression } from './prebuilt-options-analysis.ts';\nimport { cleanPrebuiltDir, runPrebuiltCapture } from './prebuilt-capture.ts';\nimport type { PrebuiltCaptureResult } from './prebuilt-capture.ts';\nimport type {\n CallExpressionNode,\n IdentifierNode,\n ImportBindings,\n MemberExpressionNode,\n PositionedNode,\n ProgramNode,\n} from './callsite-ast.ts';\n\n/**\n * Is this callee `cache.component` (named import, aliases included) or\n * `ns.cache.component` (namespace import)? Computed access is not matched.\n */\nfunction isCacheComponentCallee(callee: PositionedNode, bindings: ImportBindings): boolean {\n if (callee.type !== 'MemberExpression') return false;\n const member = callee as unknown as MemberExpressionNode;\n if (\n member.computed ||\n member.property.type !== 'Identifier' ||\n (member.property as IdentifierNode).name !== 'component'\n ) {\n return false;\n }\n // cache.component — object is a named-import binding of `cache`\n if (member.object.type === 'Identifier') {\n return bindings.named.has((member.object as IdentifierNode).name);\n }\n // ns.cache.component — object is `ns.cache` on a namespace import\n if (member.object.type === 'MemberExpression') {\n const inner = member.object as unknown as MemberExpressionNode;\n return (\n !inner.computed &&\n inner.object.type === 'Identifier' &&\n bindings.namespaces.has((inner.object as IdentifierNode).name) &&\n inner.property.type === 'Identifier' &&\n (inner.property as IdentifierNode).name === 'cache'\n );\n }\n return false;\n}\n\ninterface VariableDeclaratorNode extends PositionedNode {\n type: 'VariableDeclarator';\n id: PositionedNode;\n init?: PositionedNode | null;\n}\n\n/**\n * Offset where an injected import may be inserted: after the directive\n * prologue ('use server', 'use strict', ...). Prepending at offset 0 would\n * demote a leading directive to a plain expression statement — silently\n * disabling it.\n */\nfunction importInsertionOffset(program: ProgramNode): number {\n for (const stmt of program.body) {\n const isDirective =\n stmt.type === 'ExpressionStatement' &&\n typeof (stmt as { directive?: unknown }).directive === 'string';\n if (!isDirective) return stmt.start;\n }\n // All statements are directives — no call sites can exist, but be safe.\n return program.body.length > 0 ? program.body[program.body.length - 1].end : 0;\n}\n\ninterface CandidateSite {\n call: CallExpressionNode;\n stmt: PositionedNode;\n displayName: string;\n}\n\n/**\n * Collect matching call sites from the allowlisted module-scope positions:\n * top-level (possibly exported) variable declarator initializers and\n * `export default` expressions. Returned in source order. The display name\n * is the declaring variable's name, or 'Component' for default exports.\n */\nfunction collectModuleScopeSites(program: ProgramNode, bindings: ImportBindings): CandidateSite[] {\n const isMatch = (node: PositionedNode): node is CallExpressionNode =>\n node.type === 'CallExpression' &&\n (node as unknown as CallExpressionNode).arguments.length >= 1 &&\n (node as unknown as CallExpressionNode).arguments.length <= 2 &&\n isCacheComponentCallee((node as unknown as CallExpressionNode).callee, bindings);\n\n const sites: CandidateSite[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ExportDefaultDeclaration' && stmt.declaration) {\n const call = unwrapExpression(stmt.declaration as PositionedNode);\n if (isMatch(call)) sites.push({ call, stmt, displayName: 'Component' });\n continue;\n }\n let decl = stmt;\n if (stmt.type === 'ExportNamedDeclaration' && stmt.declaration) {\n decl = stmt.declaration as PositionedNode;\n }\n if (decl.type !== 'VariableDeclaration' || !Array.isArray(decl.declarations)) continue;\n for (const d of decl.declarations as VariableDeclaratorNode[]) {\n if (!d.init) continue;\n const call = unwrapExpression(d.init as PositionedNode);\n if (!isMatch(call)) continue;\n const displayName = d.id.type === 'Identifier' ? (d.id as IdentifierNode).name : 'Component';\n sites.push({ call, stmt, displayName });\n }\n }\n return sites;\n}\n\n/**\n * Generate the stable component ID for a cache.component() call site:\n * `<sanitized-name>_<content-hash16>`. Exported for testing.\n */\nexport function generatePrebuiltId(\n relativeModulePath: string,\n statementText: string,\n callSpanText: string,\n occurrence: number,\n displayName: string\n): string {\n const prefix = displayName.toLowerCase().replace(/[^a-z0-9]/g, '') || 'component';\n const hash = generateStableCallsiteId(\n relativeModulePath,\n 'component',\n statementText,\n callSpanText,\n occurrence\n );\n return `${prefix}_${hash}`;\n}\n\n// ─── Route → component attribution (module-graph walk) ────────────────────\n\n/** Rollup getModuleInfo shape (subset — static + dynamic imports). */\nexport interface PrebuiltModuleInfo {\n importedIds: string[];\n dynamicallyImportedIds?: string[];\n}\n\n/**\n * Collect the prebuilt component IDs transitively reachable from a route\n * file, following static AND dynamic imports. Same pattern as the\n * client-reference walk in build-manifest.ts; dynamic imports are included\n * because a dynamically-imported module still registers its components\n * when it eventually loads — attribution over-approximating registration\n * is handled at capture time (an attributed-but-unregistered component is\n * reported and skipped).\n */\nexport function collectReachablePrebuiltComponents(\n entryModuleId: string,\n moduleComponents: Map<string, string[]>,\n getModuleInfo: (id: string) => PrebuiltModuleInfo | null\n): string[] {\n const visited = new Set<string>();\n const result = new Set<string>();\n const stack = [entryModuleId];\n while (stack.length > 0) {\n const moduleId = stack.pop()!;\n if (visited.has(moduleId)) continue;\n visited.add(moduleId);\n const ids = moduleComponents.get(moduleId);\n if (ids) for (const id of ids) result.add(id);\n const info = getModuleInfo(moduleId);\n if (!info) continue;\n for (const imported of info.importedIds) stack.push(imported);\n for (const imported of info.dynamicallyImportedIds ?? []) stack.push(imported);\n }\n return Array.from(result);\n}\n\n/**\n * Collect page and layout file paths from the scanned route tree — the\n * walk roots for attribution. Slots and intercepting/private segments are\n * excluded, mirroring the capture pass's route walk\n * (server/prebuilt-builder.ts §collectCandidateRoutes).\n */\nfunction collectPageAndLayoutFiles(root: SegmentNode): string[] {\n const files: string[] = [];\n const walk = (node: SegmentNode) => {\n if (node.segmentType === 'intercepting' || node.segmentType === 'private') return;\n if (node.page) files.push(node.page.filePath);\n if (node.layout) files.push(node.layout.filePath);\n for (const child of node.children) walk(child);\n };\n walk(root);\n return files;\n}\n\n// Sentinel key for default-export component IDs in the binding map.\n// Uses \\0 prefix so it can never collide with a real JS export name\n// (TIM-1187: 'Component'/'default' leaked into the named-import namespace).\nconst DEFAULT_SENTINEL = '\\0default';\n\nasync function collectCrossModuleProps(\n ctx: PluginContext,\n bindingNames: ReadonlyMap<string, ReadonlyMap<string, string>>,\n moduleId: string,\n getInfo: (id: string) => PrebuiltModuleInfo | null,\n resolve: (source: string, importer: string) => Promise<string | null>\n): Promise<void> {\n const info = getInfo(moduleId);\n if (!info) return;\n\n const declaringImports = info.importedIds.filter((id) => bindingNames.has(id) && id !== moduleId);\n if (declaringImports.length === 0) return;\n\n // Collect exported binding names from reachable declaring modules.\n // Skip sentinel keys — they are per-module and handled in the default\n // import branch below. Only real export names go into the merged map.\n const exportNameToId = new Map<string, string>();\n const collisions = new Set<string>();\n for (const declId of declaringImports) {\n const map = bindingNames.get(declId)!;\n for (const [name, compId] of map) {\n if (name === DEFAULT_SENTINEL) continue;\n if (exportNameToId.has(name)) collisions.add(name);\n exportNameToId.set(name, compId);\n }\n }\n for (const name of collisions) exportNameToId.delete(name);\n\n let source: string | null = null;\n const extInfo = getInfo(moduleId) as unknown as { code?: string | null };\n if (extInfo && typeof extInfo.code === 'string') {\n source = extInfo.code;\n } else {\n try {\n source = readFileSync(moduleId, 'utf8');\n } catch {\n return;\n }\n }\n if (!source) return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(source);\n } catch {\n return;\n }\n\n const declaringSet = new Set(declaringImports);\n const localToComponentId = new Map<string, string>();\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const importDecl = stmt as unknown as {\n source: { value: string };\n specifiers: Array<{\n type: string;\n local: { name: string };\n imported?: { name: string };\n }>;\n };\n for (const spec of importDecl.specifiers) {\n if (spec.type === 'ImportSpecifier') {\n const exportedName = spec.imported?.name ?? spec.local.name;\n // `import { default as X }` is parsed as an ImportSpecifier\n // with imported.name === 'default' — route through the same\n // per-source sentinel lookup as ImportDefaultSpecifier.\n if (exportedName === 'default') {\n const resolvedId = await resolve(importDecl.source.value, moduleId);\n if (resolvedId && declaringSet.has(resolvedId)) {\n const map = bindingNames.get(resolvedId)!;\n const compId = map.get(DEFAULT_SENTINEL);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n } else {\n const compId = exportNameToId.get(exportedName);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n } else if (spec.type === 'ImportDefaultSpecifier') {\n const resolvedId = await resolve(importDecl.source.value, moduleId);\n if (resolvedId && declaringSet.has(resolvedId)) {\n const map = bindingNames.get(resolvedId)!;\n const compId = map.get(DEFAULT_SENTINEL);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n }\n }\n }\n if (localToComponentId.size === 0) return;\n\n const usages = collectJsxUsages(program, new Set(localToComponentId.keys()));\n for (const [localName, propsList] of usages) {\n const componentId = localToComponentId.get(localName);\n if (!componentId) continue;\n for (const props of propsList) {\n if (props === null) continue;\n recordCallSiteProps(ctx, componentId, props);\n }\n }\n}\n\n/**\n * What the post-build phase asks of the prebuilt plugin (plugins/post-build.ts).\n */\nexport interface PrebuiltBuildStep {\n /**\n * Run the capture pass against the built RSC bundle in `rscDir`. Always\n * removes the previous build's `prebuilt/` first — even when this build\n * captures nothing, a stale manifest must never ship. Returns null when\n * there was nothing to capture: no prerender call site is reachable from a\n * route, or `output: 'static'` already renders everything at build time.\n */\n capture(rscDir: string): Promise<PrebuiltCaptureResult | null>;\n}\n\nexport function timberPrebuilt(ctx: PluginContext): Plugin & { api: PrebuiltBuildStep } {\n /**\n * Module ID → prerender-capable component IDs declared in it. Recorded by\n * the RSC transform, read by the RSC `generateBundle` module-graph walk\n * that computes `ctx.routePrebuiltComponents`. Build only.\n */\n const moduleComponents = new Map<string, string[]>();\n /**\n * Module ID → variable name → component ID, for the prebuilt components\n * that module declares. Read at `generateBundle` time to trace imports in\n * other modules back to component IDs (cross-module call-site props).\n */\n const bindingNames = new Map<string, Map<string, string>>();\n\n return {\n name: 'timber-prebuilt',\n\n api: {\n async capture(rscDir) {\n await cleanPrebuiltDir(ctx.buildDir);\n if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return null;\n if (ctx.config.output === 'static') {\n // design/44 §output: 'static' — everything already renders at\n // build time there; the wrapper is a no-op, not an error.\n console.log(\n `[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`\n );\n return null;\n }\n return runPrebuiltCapture(ctx, rscDir);\n },\n },\n\n transform(code, id) {\n // Drop this module's stale attribution first — in a long-lived\n // `vite build --watch` process the plugin context outlives builds,\n // and an edit that removes a module's prerender call sites must\n // remove its recorded IDs even when this transform exits early\n // below (codex P2 on PR #836). Re-recorded at the bottom if the\n // edited module still has prerender-capable call sites.\n if (!ctx.dev && this?.environment?.name === 'rsc') {\n moduleComponents.delete(id);\n bindingNames.delete(id);\n }\n if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;\n // Skip node_modules (don't transform third-party code)\n if (id.includes('node_modules')) return;\n // Skip the client environment — server components never execute there\n // and #server-internal resolves to an empty stub.\n if (this?.environment?.name === 'client') return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(code);\n } catch {\n return;\n }\n\n const bindings = findImportBindings(program, CACHE_MODULE_SOURCES, 'cache');\n if (bindings.named.size === 0 && bindings.namespaces.size === 0) return;\n\n // Allowlisted module-scope positions only — each site carries its\n // enclosing statement's source text (into the ID hash) and the\n // declaring variable's name (display name). Already in source order.\n const callSites = collectModuleScopeSites(program, bindings);\n if (callSites.length === 0) return;\n\n const root = ctx.root || process.cwd();\n const relPath = relative(root, id);\n const s = new MagicString(code);\n const occurrences = new Map<string, number>();\n const wrapperName = ctx.dev ? '__prebuiltDev' : '__prebuilt';\n const componentIds: string[] = [];\n\n for (const { call, stmt, displayName } of callSites) {\n const stmtText = code.slice(stmt.start, stmt.end);\n const spanText = code.slice(call.start, call.end);\n // Byte-identical (statement, call) pairs are only possible via `var`\n // redeclaration; the occurrence index keeps their IDs distinct.\n const dupKey = stmtText + String.fromCharCode(0) + spanText;\n const occurrence = occurrences.get(dupKey) ?? 0;\n occurrences.set(dupKey, occurrence + 1);\n\n // Production gets the stable ID (keys build artifacts and cache\n // entries); dev gets the display name (only used for the one-time\n // \"rendering dynamically\" log).\n const firstArg = ctx.dev\n ? displayName\n : generatePrebuiltId(relPath, stmtText, spanText, occurrence, displayName);\n // Only prerender-capable call sites feed the capture attribution —\n // runtime-tier components (ttl/tags only) must do no build work.\n if (!ctx.dev && mayPrerender(call)) componentIds.push(firstArg);\n\n s.overwrite(call.callee.start, call.callee.end, wrapperName);\n s.appendLeft(call.arguments[0].start, `${JSON.stringify(firstArg)}, `);\n }\n\n // Record this module's component IDs for the RSC generateBundle\n // module-graph walk (route → component attribution, TIM-1119).\n if (!ctx.dev && componentIds.length > 0 && this?.environment?.name === 'rsc') {\n moduleComponents.set(id, componentIds);\n\n // Record binding name → component ID mapping for cross-module\n // prop detection at generateBundle time (TIM-1142).\n const bindingMap = new Map<string, string>();\n let componentIdIdx = 0;\n for (const { call, stmt, displayName } of callSites) {\n if (!ctx.dev && mayPrerender(call)) {\n const compId = componentIds[componentIdIdx++];\n // Direct `export default cache.component(...)` produces\n // displayName 'Component' from an ExportDefaultDeclaration —\n // a synthetic name, not a real export. Store only the sentinel\n // key. A variable literally named `Component` (from a\n // VariableDeclarator) is a real binding and stored as-is.\n if (stmt.type === 'ExportDefaultDeclaration') {\n bindingMap.set(DEFAULT_SENTINEL, compId);\n } else {\n bindingMap.set(displayName, compId);\n }\n }\n }\n // Detect default re-exports that reference a declared binding\n // and add a sentinel alias so cross-module default imports can\n // resolve the component ID. Handles both `export default X` and\n // `export { X as default }` (TIM-1189).\n for (const stmt of program.body) {\n if (\n stmt.type === 'ExportDefaultDeclaration' &&\n stmt.declaration &&\n (stmt.declaration as PositionedNode).type === 'Identifier'\n ) {\n const name = (stmt.declaration as PositionedNode as unknown as IdentifierNode).name;\n if (bindingMap.has(name) && !bindingMap.has(DEFAULT_SENTINEL)) {\n bindingMap.set(DEFAULT_SENTINEL, bindingMap.get(name)!);\n }\n }\n if (stmt.type === 'ExportNamedDeclaration' && Array.isArray(stmt.specifiers)) {\n for (const spec of stmt.specifiers as Array<{\n local: IdentifierNode;\n exported: IdentifierNode;\n }>) {\n if (spec.exported.name === 'default') {\n const compId = bindingMap.get(spec.local.name);\n if (compId && !bindingMap.has(DEFAULT_SENTINEL)) {\n bindingMap.set(DEFAULT_SENTINEL, compId);\n }\n }\n }\n }\n }\n\n if (bindingMap.size > 0) {\n bindingNames.set(id, bindingMap);\n }\n\n // Same-module JSX usages: if a prebuilt component is declared AND\n // used (<BlogBody variant=\"full\" />) in the same module, capture\n // its static call-site props here (TIM-1142, design/44 §Props).\n // Exclude sentinel keys — they are not real JSX element names.\n const declaredBindings = new Set(\n [...bindingMap.keys()].filter((k) => k !== DEFAULT_SENTINEL)\n );\n if (declaredBindings.size > 0) {\n const usages = collectJsxUsages(program, declaredBindings);\n for (const [bindingName, propsList] of usages) {\n const compId = bindingMap.get(bindingName);\n if (!compId) continue;\n for (const props of propsList) {\n if (props === null) {\n // Dynamic props at this call site — warn at build time,\n // this usage will always render live (design/44 §Props\n // Derivation limitation).\n continue;\n }\n recordCallSiteProps(ctx, compId, props);\n }\n }\n }\n }\n\n s.appendLeft(\n importInsertionOffset(program),\n `import { ${wrapperName} } from '#server-internal';\\n`\n );\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n\n /**\n * RSC environment, production: walk each route file's module graph to\n * attribute prebuilt components to the routes that can render them.\n * The graph walk (rather than load-order registry deltas) is what makes\n * SHARED components work — a component imported by several routes is\n * captured under every importing route's param combos.\n */\n async generateBundle(\n _options?: unknown,\n bundle?: Record<\n string,\n { type: string; modules?: Record<string, unknown>; fileName?: string }\n >\n ) {\n if (ctx.dev) return;\n if (this?.environment?.name !== 'rsc') return;\n ctx.routePrebuiltComponents = undefined;\n ctx.prebuiltLazyChunks = undefined;\n if (moduleComponents.size === 0 || !ctx.routeTree) return;\n\n const self = this as unknown as {\n getModuleInfo?: (id: string) => PrebuiltModuleInfo | null;\n resolve?: (\n source: string,\n importer: string,\n opts?: unknown\n ) => Promise<{ id: string } | null>;\n };\n const getInfo = (id: string) => self.getModuleInfo?.(id) ?? null;\n const resolveFn = async (source: string, importer: string): Promise<string | null> => {\n const result = await self.resolve?.(source, importer);\n return result?.id ?? null;\n };\n\n const routeComponents = new Map<string, string[]>();\n for (const filePath of collectPageAndLayoutFiles(ctx.routeTree.root)) {\n const ids = collectReachablePrebuiltComponents(filePath, moduleComponents, getInfo);\n if (ids.length > 0) routeComponents.set(filePath, ids);\n }\n if (routeComponents.size > 0) {\n ctx.routePrebuiltComponents = routeComponents;\n\n // Build a map of componentId → chunk fileName for declaring\n // modules that aren't route files themselves (behind dynamic\n // imports like import.meta.glob). The capture pass imports these\n // chunks to trigger cache.component() registration.\n if (bundle) {\n const routeFileSet = new Set(routeComponents.keys());\n const lazyChunks = new Map<string, string>();\n for (const [moduleId, componentIds] of moduleComponents) {\n if (routeFileSet.has(moduleId)) continue;\n for (const [, chunk] of Object.entries(bundle)) {\n if (chunk.type !== 'chunk' || !chunk.modules) continue;\n if (moduleId in chunk.modules) {\n for (const id of componentIds) lazyChunks.set(id, chunk.fileName!);\n break;\n }\n }\n }\n if (lazyChunks.size > 0) ctx.prebuiltLazyChunks = lazyChunks;\n }\n\n // Cross-module call-site prop detection (TIM-1142): walk the\n // module graph from each route file and scan ALL reachable modules\n // for JSX usages of prebuilt components — not just the route files\n // themselves. A component used in a helper (page → Shell → <BlogBody>)\n // must have its props captured from wherever the JSX lives.\n if (bindingNames.size > 0) {\n const scannedModules = new Set<string>();\n for (const filePath of routeComponents.keys()) {\n const visited = new Set<string>();\n const stack = [filePath];\n while (stack.length > 0) {\n const modId = stack.pop()!;\n if (visited.has(modId)) continue;\n visited.add(modId);\n if (!scannedModules.has(modId)) {\n scannedModules.add(modId);\n await collectCrossModuleProps(ctx, bindingNames, modId, getInfo, resolveFn);\n }\n const modInfo = getInfo(modId);\n if (!modInfo) continue;\n for (const imp of modInfo.importedIds) stack.push(imp);\n for (const imp of modInfo.dynamicallyImportedIds ?? []) stack.push(imp);\n }\n }\n }\n } else {\n // Call sites were transformed but none are reachable from any route\n // file — either they live behind slots (not modeled) or the graph\n // walk's module IDs diverged from the route tree's file paths. Say\n // so loudly: the alternative is prerender silently doing nothing.\n console.warn(\n `[timber] cache.component: ${moduleComponents.size} module(s) declare prebuilt ` +\n `components, but none are reachable from any page or layout — no payloads ` +\n `will be prerendered`\n );\n }\n },\n };\n}\n","/**\n * timber-prerender-sugar — Vite plugin that desugars `export const prerender`\n * on page and layout files into `cache.component(...)` wrappers.\n *\n * Design doc: design/45-cache-lifetimes.md §\"Route-Level Static\" and\n * §\"Layout Propagation\".\n *\n * `export const prerender = true` on a page is pure sugar: it desugars to\n * wrapping the page's default export in `timber.cache.component(Component,\n * { prerender: true })`. Layout propagation cascades a layout's\n * `export const prerender` to descendant pages via most-specific-wins:\n * walk the segment tree from leaf to root, first explicit value wins.\n *\n * Layout declarations are propagation policy only. Layouts receive the real\n * descendant React element as `children` to preserve the server-layout\n * containment boundary, so their props are not cache-keyable and the layout\n * itself must not be registered for capture.\n *\n * This transform runs BEFORE timber-prebuilt so the generated\n * `cache.component(...)` call is picked up by the callsite rewrite.\n */\n\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode, RouteFile } from '../routing/types.ts';\nimport { getPrerenderExport, type PrerenderExportValue } from '../routing/export-detect.ts';\n\ninterface AstNode {\n type: string;\n start: number;\n end: number;\n name?: string;\n declaration?: AstNode;\n id?: AstNode & { name?: string };\n expression?: AstNode;\n}\n\n/**\n * Walk the segment tree and resolve the effective prerender value for\n * every page. Returns a map from page file path to resolved value.\n *\n * **Pages:** walk from leaf toward root; first explicit `export const prerender`\n * wins (page > nearest layout > ... > root layout). If none, dynamic.\n *\n * **Layouts:** declarations propagate to descendant pages but layouts are not\n * included in the result. Their real React-element `children` preserve secure\n * containment and deliberately make child-independent layout caching invalid.\n */\nexport function resolvePagePrerender(root: SegmentNode): Map<string, PrerenderExportValue> {\n const result = new Map<string, PrerenderExportValue>();\n\n function walk(node: SegmentNode, ancestorStack: PrerenderExportValue[]) {\n if (node.segmentType === 'intercepting' || node.segmentType === 'private') return;\n\n // Check this segment's layout for a prerender export\n const layoutValue = node.layout ? getPrerenderExport(node.layout.filePath) : undefined;\n const stack = layoutValue !== undefined ? [layoutValue, ...ancestorStack] : ancestorStack;\n\n if (node.page) {\n const pageValue = getPrerenderExport(node.page.filePath);\n // Page's own value takes priority; otherwise use nearest ancestor\n const resolved = pageValue !== undefined ? pageValue : stack[0];\n // Only record if the resolved value is truthy (prerender: true or options object)\n // prerender: false explicitly opts out\n if (resolved !== undefined && resolved !== false) {\n result.set(node.page.filePath, resolved);\n }\n }\n\n for (const child of node.children) walk(child, stack);\n for (const slot of Object.values(node.slots)) walk(slot, stack);\n }\n\n walk(root, []);\n return result;\n}\n\n/**\n * Build the `cache.component` options source text from a resolved value.\n */\nfunction buildOptionsSource(value: PrerenderExportValue): string {\n if (value === true) return '{ prerender: true }';\n if (typeof value === 'object') {\n const parts = ['prerender: true'];\n if (value.ttl !== undefined) parts.push(`ttl: ${value.ttl}`);\n if (value.tags !== undefined) parts.push(`tags: ${JSON.stringify(value.tags)}`);\n return `{ ${parts.join(', ')} }`;\n }\n return '{ prerender: true }';\n}\n\n/**\n * Find the default export in the AST and return info needed for the rewrite.\n */\ninterface DefaultExportInfo {\n kind: 'declaration' | 'expression' | 'identifier';\n node: AstNode;\n name?: string;\n /** For `export { X as default, Y }` — position of the default specifier. */\n specifierIndex?: number;\n specifierCount?: number;\n specifierStart?: number;\n specifierEnd?: number;\n}\n\nfunction findDefaultExport(program: { body: AstNode[] }, source: string): DefaultExportInfo | null {\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportDefaultDeclaration' || !stmt.declaration) continue;\n const decl = stmt.declaration;\n\n // export default function Name(...) { ... }\n // export default class Name { ... }\n if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {\n const name = decl.id?.name;\n if (name) return { kind: 'declaration', node: stmt, name };\n // Anonymous function/class — treat as expression\n return { kind: 'expression', node: stmt };\n }\n\n // export default SomeIdentifier\n if (decl.type === 'Identifier') {\n return { kind: 'identifier', node: stmt, name: decl.name };\n }\n\n // export default <expression>\n return { kind: 'expression', node: stmt };\n }\n\n // Check for `export { X as default }` (not re-exports from other modules)\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportNamedDeclaration') continue;\n // Skip re-exports: `export { X as default } from './other'`\n if ((stmt as any).source) continue;\n const specifiers = (stmt as any).specifiers as\n | Array<{\n type: string;\n start: number;\n end: number;\n local?: { name: string };\n exported?: { name: string };\n }>\n | undefined;\n if (!specifiers) continue;\n for (let i = 0; i < specifiers.length; i++) {\n const spec = specifiers[i];\n if (spec.exported?.name === 'default' && spec.local?.name && spec.local.name !== 'default') {\n return {\n kind: 'identifier' as const,\n node: stmt,\n name: spec.local.name,\n specifierIndex: i,\n specifierCount: specifiers.length,\n specifierStart: spec.start,\n specifierEnd: spec.end,\n };\n }\n }\n }\n\n return null;\n}\n\nexport function timberPrerenderSugar(ctx: PluginContext): Plugin {\n let resolvedPages: Map<string, PrerenderExportValue> | null = null;\n\n function ensureResolved() {\n if (resolvedPages) return;\n if (!ctx.routeTree) {\n resolvedPages = new Map();\n return;\n }\n resolvedPages = resolvePagePrerender(ctx.routeTree.root);\n }\n\n return {\n name: 'timber-prerender-sugar',\n\n buildStart() {\n // Reset on each build (watch mode rebuilds)\n resolvedPages = null;\n },\n\n transform(code, id) {\n // Only process in RSC environment (same gate as prebuilt.ts)\n if (this?.environment?.name === 'client') return;\n // Skip node_modules\n if (id.includes('node_modules')) return;\n\n ensureResolved();\n if (!resolvedPages || resolvedPages.size === 0) return;\n\n const value = resolvedPages.get(id);\n if (!value) return;\n\n // This page has a resolved prerender value — wrap its default export\n let program: { body: AstNode[] };\n try {\n program = ctx.parseCached!.parse(code) as unknown as { body: AstNode[] };\n } catch {\n return;\n }\n\n const defaultExport = findDefaultExport(program, code);\n if (!defaultExport) {\n // Warn if the file has a prerender export but no wrappable default export\n // (e.g. `export { default } from './impl'` — a re-export we can't rewrite).\n if (value) {\n const relPath = id.replace(ctx.root + '/', '');\n console.warn(\n `[timber] ${relPath}: export const prerender is declared but the default ` +\n `export cannot be wrapped (re-export or missing). The prerender declaration ` +\n `will be ignored for this file.`\n );\n }\n return;\n }\n\n // Skip if the default export is already a cache.component(...) call —\n // avoid double-wrapping. Only check the default export itself, not the\n // whole file (a page may use cache.component for child components).\n if (defaultExport.kind === 'expression' && defaultExport.node.declaration) {\n const declText = code.slice(\n defaultExport.node.declaration.start,\n defaultExport.node.declaration.end\n );\n if (declText.includes('.component(')) return;\n }\n\n const s = new MagicString(code);\n const optionsSource = buildOptionsSource(value);\n\n // Add the cache import at the top (after directives)\n const importAlias = '__timber_prerender_cache__';\n let insertOffset = 0;\n for (const stmt of program.body) {\n const isDirective =\n stmt.type === 'ExpressionStatement' && typeof (stmt as any).directive === 'string';\n if (!isDirective) {\n insertOffset = stmt.start;\n break;\n }\n }\n s.appendLeft(\n insertOffset,\n `import { cache as ${importAlias} } from '@timber-js/app/cache';\\n`\n );\n\n switch (defaultExport.kind) {\n case 'declaration': {\n // `export default function Name() { ... }`\n // → `function Name() { ... }` + `export default cache.component(Name, opts)`\n const declStart = defaultExport.node.declaration!.start;\n // Remove `export default ` prefix\n s.overwrite(defaultExport.node.start, declStart, '');\n // Append the wrapped export at the end\n s.append(\n `\\nexport default ${importAlias}.component(${defaultExport.name}, ${optionsSource});\\n`\n );\n break;\n }\n case 'identifier': {\n if (defaultExport.specifierCount !== undefined && defaultExport.specifierCount > 1) {\n // Multi-specifier: `export { Page as default, generateStaticSegmentParams }`\n // Remove only the default specifier + surrounding comma, keep others.\n const specStart = defaultExport.specifierStart!;\n const specEnd = defaultExport.specifierEnd!;\n const idx = defaultExport.specifierIndex!;\n // Remove the specifier and a comma (trailing if first, leading otherwise)\n if (idx === 0) {\n // First specifier: remove text up to (but not including) the next specifier start\n const nextSpec = (defaultExport.node as any).specifiers?.[1];\n if (nextSpec) s.remove(specStart, nextSpec.start);\n } else {\n // Not first: remove from end of previous specifier to this specifier's end\n const prevSpec = (defaultExport.node as any).specifiers?.[idx - 1];\n if (prevSpec) s.remove(prevSpec.end, specEnd);\n }\n // Append the wrapped default export separately\n s.appendLeft(\n defaultExport.node.end,\n `\\nexport default ${importAlias}.component(${defaultExport.name}, ${optionsSource});`\n );\n } else {\n // `export default MyPage` or `export { MyPage as default }` (sole specifier)\n // → `export default cache.component(MyPage, opts)`\n s.overwrite(\n defaultExport.node.start,\n defaultExport.node.end,\n `export default ${importAlias}.component(${defaultExport.name}, ${optionsSource});`\n );\n }\n break;\n }\n case 'expression': {\n // `export default () => <div/>` or `export default async function() { ... }`\n // → `const __default = ...; export default cache.component(__default, opts)`\n const decl = defaultExport.node.declaration!;\n s.overwrite(defaultExport.node.start, decl.start, 'const __timber_default_page__ = ');\n // Ensure trailing semicolon\n const afterExpr = code.charAt(defaultExport.node.end - 1) === ';' ? '' : ';';\n s.appendLeft(\n defaultExport.node.end,\n `${afterExpr}\\nexport default ${importAlias}.component(__timber_default_page__, ${optionsSource});`\n );\n break;\n }\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n };\n}\n","/**\n * timber-cloudflare-wasm — Handle WASM modules for Cloudflare Workers builds.\n *\n * Cloudflare Workers can natively import `.wasm` files as compiled\n * WebAssembly.Module. But Rolldown can't load `.wasm` files at build time.\n *\n * This plugin bridges the gap:\n * 1. Adds the `workerd` resolve condition so libraries like @takumi-rs/wasm\n * resolve to their Cloudflare-native entry (bare `.wasm` import)\n * 2. Externalizes `.wasm` imports so Rolldown skips them\n * 3. Copies the WASM files to the build output so wrangler can find them\n *\n * Only active for Cloudflare adapter production builds — every hook bails\n * unless `isCloudflareBuild` was set in configResolved. In dev and non-CF\n * builds, `.wasm` imports are left to Vite's own handling (?init / ?url or\n * a clear build error), never silently externalized.\n */\n\nimport { basename, resolve, dirname } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { copyFile, mkdir, readFile } from 'node:fs/promises';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\nfunction isCloudflareAdapter(ctx: PluginContext): boolean {\n const adapter = ctx.config.adapter as { name?: string } | undefined;\n return adapter?.name === 'cloudflare';\n}\n\nexport function timberCloudflareWasm(ctx: PluginContext): Plugin[] {\n // Resolved WASM files, keyed by absolute source path so two files that\n // share a basename (e.g. lib_bg.wasm from two packages) don't collide.\n // The value is the unique output basename used for the external import\n // specifier and the copy destination.\n const wasmFiles = new Map<string, string>();\n const usedBasenames = new Set<string>();\n let isCloudflareBuild = false;\n\n const plugin: Plugin = {\n name: 'timber-cloudflare-wasm',\n\n configResolved(resolved: ResolvedConfig) {\n if (resolved.command !== 'build') return;\n if (!isCloudflareAdapter(ctx)) return;\n isCloudflareBuild = true;\n\n // Prepend `workerd` to resolve conditions for server environments\n // so @takumi-rs/wasm/auto resolves to the Cloudflare-native entry\n // (bare WASM import) instead of the Vite entry (?url + fetch).\n // Must happen in configResolved because the RSC plugin sets its own\n // conditions during config — merging via config() would lose them.\n for (const envName of ['rsc', 'ssr']) {\n const env = resolved.environments[envName];\n if (!env) continue;\n const conditions = env.resolve.conditions;\n if (!conditions.includes('workerd')) {\n conditions.unshift('workerd');\n }\n }\n },\n\n // Strip /* @vite-ignore */ from @takumi-rs/wasm dynamic imports so\n // Rolldown bundles them instead of leaving bare specifiers that fail\n // at runtime on Cloudflare Workers (no node_modules).\n transform(code, id) {\n if (!isCloudflareBuild) return;\n if (!id.includes('takumi')) return;\n const stripped = code.replaceAll(\n /\\/\\*\\s*@vite-ignore\\s*\\*\\/\\s*\\n\\s*\"@takumi-rs\\/wasm\"/g,\n '\"@takumi-rs/wasm\"'\n );\n if (stripped !== code) return stripped;\n },\n\n resolveId: {\n order: 'pre',\n async handler(source, importer) {\n if (!isCloudflareBuild) return;\n if (!source.endsWith('.wasm')) return;\n\n let absolutePath: string;\n if (source.startsWith('.') && importer) {\n absolutePath = resolve(dirname(importer), source);\n } else {\n return;\n }\n\n let outputName = wasmFiles.get(absolutePath);\n if (!outputName) {\n outputName = basename(absolutePath);\n if (usedBasenames.has(outputName)) {\n // Another wasm file already claimed this basename — disambiguate\n // with a short content hash so both files land in the output.\n const hash = createHash('sha256')\n .update(await readFile(absolutePath))\n .digest('hex')\n .slice(0, 8);\n outputName = outputName.replace(/\\.wasm$/, `.${hash}.wasm`);\n }\n usedBasenames.add(outputName);\n wasmFiles.set(absolutePath, outputName);\n }\n\n return { id: './' + outputName, external: true };\n },\n },\n\n async writeBundle(options, bundle) {\n if (!isCloudflareBuild) return;\n if (wasmFiles.size === 0) return;\n\n const outDir = options.dir;\n if (!outDir) return;\n\n // Find which output chunks reference WASM files and copy the WASM\n // to the same directory so the relative imports resolve correctly.\n const targetDirs = new Set<string>();\n for (const chunk of Object.values(bundle)) {\n if (chunk.type !== 'chunk') continue;\n for (const outputName of wasmFiles.values()) {\n if (chunk.code.includes(outputName)) {\n targetDirs.add(dirname(resolve(outDir, chunk.fileName)));\n }\n }\n }\n\n if (targetDirs.size === 0) return;\n\n const copies: Promise<void>[] = [];\n for (const dir of targetDirs) {\n await mkdir(dir, { recursive: true });\n for (const [absolutePath, outputName] of wasmFiles) {\n copies.push(copyFile(absolutePath, resolve(dir, outputName)));\n }\n }\n await Promise.all(copies);\n },\n };\n\n return [plugin];\n}\n","/**\n * The RSC plugin's assets manifest (`__vite_rsc_assets_manifest.js`) — read\n * into the build manifest, and stripped of JavaScript when client JS is off.\n *\n * The RSC plugin writes the file to rsc/ and ssr/ as a standalone file, not\n * a Rollup chunk, so no `generateBundle` can intercept it; both operations\n * work on the written files. Both run once, from the post-build phase's\n * manifest finalization step (plugins/post-build.ts), before anything\n * imports the built bundle.\n *\n * Design doc: 18-build-system.md §\"Post-Build Phase\"\n */\n\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport { swallow } from '../server/logger.ts';\n\n/**\n * Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first\n * (fast path for plain-string manifests); falls back to a dynamic import()\n * for manifests that contain runtime expressions from renderBuiltUrl.\n * Returns null if both paths fail.\n */\nasync function parseRscManifest(\n manifestPath: string,\n content: string\n): Promise<Record<string, unknown> | null> {\n const jsonStr = content.replace(/^export default\\s*/, '').replace(/;?\\s*$/, '');\n try {\n return JSON.parse(jsonStr);\n } catch {\n // Not strict JSON — manifest likely contains renderBuiltUrl runtime\n // expressions. Fall back to evaluating the module directly.\n }\n\n // When renderBuiltUrl's runtime expressions reference external helpers\n // not defined in the manifest file, this import will fail. That's an\n // inherent limitation: runtime-computed URLs can't be resolved at build\n // time for <link> tag injection. The warning below provides observability.\n try {\n const url = pathToFileURL(manifestPath).href;\n const mod = await import(`${url}?t=${Date.now()}`);\n return mod.default ?? null;\n } catch (err) {\n swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: 'warn' });\n return null;\n }\n}\n\n/**\n * Replace all `\"js\": [...]` array contents with `\"js\": []` using balanced\n * bracket matching. Handles nested brackets from runtime expressions like\n * `__rbu(\"path/to/[slug]/file.js\")`.\n */\nfunction clearJsArrays(src: string): string {\n const pattern = /\"js\"\\s*:\\s*\\[/g;\n let result = '';\n let lastEnd = 0;\n let match: RegExpExecArray | null;\n\n while ((match = pattern.exec(src)) !== null) {\n const arrayStart = match.index + match[0].length;\n let depth = 1;\n let i = arrayStart;\n while (i < src.length && depth > 0) {\n if (src[i] === '[') depth++;\n else if (src[i] === ']') depth--;\n i++;\n }\n result += src.slice(lastEnd, match.index) + '\"js\": []';\n lastEnd = i;\n }\n result += src.slice(lastEnd);\n return result;\n}\n\n/**\n * Replace `\"bootstrapScriptContent\": <value>` with an empty string. The\n * value may be a JS expression (e.g., concatenation with runtime helpers),\n * not a simple string literal. Scans forward from the colon, tracking\n * balanced parens and brackets, and stops at the next unbalanced `,` or `}`.\n */\nfunction clearBootstrapScriptContent(src: string): string {\n const key = '\"bootstrapScriptContent\"';\n const idx = src.indexOf(key);\n if (idx === -1) return src;\n\n // Find the colon after the key\n const colonIdx = src.indexOf(':', idx + key.length);\n if (colonIdx === -1) return src;\n\n // Skip whitespace after colon\n let valStart = colonIdx + 1;\n while (valStart < src.length && /\\s/.test(src[valStart])) valStart++;\n\n // Scan forward to find the end of the value expression\n let i = valStart;\n let depth = 0;\n let inString = false;\n let stringChar = '';\n\n while (i < src.length) {\n const ch = src[i];\n if (inString) {\n if (ch === '\\\\') {\n i += 2;\n continue;\n }\n if (ch === stringChar) inString = false;\n } else {\n if (ch === '\"' || ch === \"'\") {\n inString = true;\n stringChar = ch;\n } else if (ch === '(' || ch === '[') {\n depth++;\n } else if (ch === ')' || ch === ']') {\n depth--;\n } else if (depth === 0 && (ch === ',' || ch === '}' || ch === '\\n')) {\n break;\n }\n }\n i++;\n }\n\n return src.slice(0, idx) + '\"bootstrapScriptContent\": \"\"' + src.slice(i);\n}\n\n/**\n * Read the RSC plugin's assets manifest and merge per-route CSS and\n * per-route JS modulepreloads into the build manifest.\n *\n * CSS: `serverResources` maps server component paths to CSS URLs.\n * JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.\n * Combined with `routeClientRefKeys` (from the RSC generateBundle\n * module graph walk) to produce per-route modulepreload entries.\n */\nexport async function mergeRscAssetsManifest(\n rscDir: string,\n root: string,\n buildManifest: BuildManifest,\n routeClientRefKeys?: Map<string, Set<string>>\n): Promise<void> {\n const manifestPath = join(rscDir, '__vite_rsc_assets_manifest.js');\n let content: string;\n try {\n content = await readFile(manifestPath, 'utf-8');\n } catch {\n return;\n }\n\n const manifest = await parseRscManifest(manifestPath, content);\n if (!manifest) return;\n\n // Merge serverResources CSS into buildManifest.css.\n // Keys in serverResources are root-relative (e.g., \"app/layout.tsx\" or\n // \"src/app/layout.tsx\"). Convert to absolute paths to match the runtime\n // route manifest's filePath values.\n const serverResources = manifest.serverResources as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (serverResources) {\n for (const [relativePath, deps] of Object.entries(serverResources)) {\n if (deps.css && deps.css.length > 0) {\n const absolutePath = join(root, relativePath);\n buildManifest.css[absolutePath] = deps.css;\n }\n }\n }\n\n // Build per-route modulepreload entries from routeClientRefKeys +\n // clientReferenceDeps. Each route file's transitive client reference\n // keys (captured during RSC generateBundle) are mapped to their JS\n // chunk URLs via clientReferenceDeps.\n if (routeClientRefKeys && routeClientRefKeys.size > 0) {\n const clientReferenceDeps = manifest.clientReferenceDeps as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (clientReferenceDeps) {\n for (const [filePath, refKeys] of routeClientRefKeys) {\n const jsUrls = new Set<string>();\n for (const key of refKeys) {\n const deps = clientReferenceDeps[key];\n if (deps?.js) {\n for (const url of deps.js) jsUrls.add(url);\n }\n }\n if (jsUrls.size > 0) {\n buildManifest.modulepreload[filePath] = Array.from(jsUrls);\n }\n }\n }\n }\n}\n\n/**\n * Strip JS references from the RSC plugin's assets manifest files.\n *\n * The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/\n * as standalone files (not Rollup chunks), so generateBundle can't\n * intercept them. This rewrites the files on disk after all builds\n * complete but before the adapter copies them to the output directory.\n */\nexport async function stripJsFromRscAssetsManifests(serverDirs: string[]): Promise<void> {\n const paths = serverDirs.map((dir) => join(dir, '__vite_rsc_assets_manifest.js'));\n\n for (const path of paths) {\n let content: string;\n try {\n content = await readFile(path, 'utf-8');\n } catch {\n continue;\n }\n\n // Try JSON.parse to check if we can safely re-serialize\n const jsonStr = content.replace(/^export default\\s*/, '').replace(/;?\\s*$/, '');\n let isStrictJson = true;\n let manifest: Record<string, unknown> | null = null;\n try {\n manifest = JSON.parse(jsonStr);\n } catch {\n isStrictJson = false;\n }\n\n if (!isStrictJson) {\n // Manifest contains renderBuiltUrl runtime expressions — cannot\n // safely re-serialize with JSON.stringify. Use targeted text\n // transforms to clear JS arrays and bootstrapScriptContent.\n let rewritten = content;\n rewritten = clearJsArrays(rewritten);\n rewritten = clearBootstrapScriptContent(rewritten);\n await writeFile(path, rewritten);\n continue;\n }\n\n // Clear JS from clientReferenceDeps — preserves CSS\n const deps = manifest?.clientReferenceDeps as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (deps) {\n for (const entry of Object.values(deps)) {\n entry.js = [];\n }\n }\n\n if (manifest) manifest.bootstrapScriptContent = '';\n\n await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\\n`);\n }\n}\n","/**\n * timber-post-build — the post-build phase, as one ordered handler.\n *\n * Everything timber does after Vite has built the three environments runs\n * here, in this order, each step handed what the previous one returned:\n *\n * 1. finalize the build manifest — font entries, the RSC assets manifest\n * merged in once, JavaScript stripped once when client JS is disabled\n * 2. prebuilt capture (cache.component prerender payloads, design/44)\n * 3. static generation (output: 'static', design/11)\n * 4. the build report\n * 5. assemble `BuildArtifacts` and call the adapter's `buildOutput`\n *\n * One `buildApp` hook with `order: 'post'` — so Vite runs the RSC plugin's\n * buildApp, which orchestrates every environment build and writes the\n * assets manifests, first. The order above is this function's, not the\n * plugin array's, and no step reads another's result off the shared\n * context: sibling plugins contribute through the typed steps they expose\n * (`FontsBuildStep`, `PrebuiltBuildStep`, `BuildReportStep`), which\n * `timber()` hands to this plugin directly.\n *\n * Design docs: 18-build-system.md §\"Post-Build Phase\", 11-platform.md\n * §\"Build Artifacts\", 49-explicit-subsystem-boundaries.md §B\n */\n\nimport type { Plugin, Rollup } from 'vite';\nimport { readdir } from 'node:fs/promises';\nimport { join, relative, resolve } from 'node:path';\nimport { adapterConfig, contextAdapter, type PluginContext } from '../plugin-context.ts';\nimport type { BuildArtifacts, DirectoryArtifact } from '../adapters/types.ts';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport type { FontsBuildStep } from './fonts.ts';\nimport type { PrebuiltBuildStep } from './prebuilt.ts';\nimport type { BuildReportStep } from './build-report.ts';\nimport { runStaticGeneration, type StaticSite } from './static-build.ts';\nimport { mergeRscAssetsManifest, stripJsFromRscAssetsManifests } from './rsc-assets-manifest.ts';\n\n/** The Vite environments whose output adapters consume. */\nconst ARTIFACT_ENVIRONMENTS = ['client', 'rsc', 'ssr'] as const;\ntype ArtifactEnvironment = (typeof ARTIFACT_ENVIRONMENTS)[number];\n\nfunction isArtifactEnvironment(name: string): name is ArtifactEnvironment {\n return (ARTIFACT_ENVIRONMENTS as readonly string[]).includes(name);\n}\n\n/** Each environment's output directory, as its own `writeBundle` recorded it. */\nexport type EnvironmentOutputs = Partial<Record<ArtifactEnvironment, DirectoryArtifact>>;\n\n/** The steps sibling plugins own. */\nexport interface PostBuildSteps {\n fonts: FontsBuildStep;\n prebuilt: PrebuiltBuildStep;\n report: BuildReportStep;\n}\n\nexport function timberPostBuild(ctx: PluginContext, steps: PostBuildSteps): Plugin {\n const environments: EnvironmentOutputs = {};\n /** What the client environment's bundle wrote, from its `writeBundle`. */\n let clientOutput: ClientOutput = { assetsDir: '', emitted: new Set() };\n\n return {\n name: 'timber-post-build',\n\n // Record each environment's output directory as it is written, so the\n // phase learns what exists from the build rather than by probing for\n // it. The RSC plugin's scan builds run with `write: false` and never\n // reach this hook; only the real bundles do.\n writeBundle(options, bundle) {\n if (ctx.dev) return;\n const env = this.environment;\n if (!isArtifactEnvironment(env.name)) return;\n environments[env.name] = { path: resolve(env.config.root, env.config.build.outDir) };\n if (env.name === 'client') {\n clientOutput = {\n assetsDir: hashedAssetsDir(env.config.build.assetsDir, options),\n emitted: new Set(Object.keys(bundle)),\n };\n }\n },\n\n buildApp: {\n order: 'post' as const,\n async handler() {\n if (ctx.dev) return;\n await runPostBuild(ctx, steps, environments, clientOutput);\n },\n },\n };\n}\n\n/**\n * The client bundle's assets directory, in the artifacts' form (no leading\n * or trailing slash) — or `''` when its files are not all content-hashed.\n *\n * `assetsDir` names where Vite writes; it is the naming patterns that decide\n * whether a file name carries a hash. Vite's defaults do\n * (`<assetsDir>/[name]-[hash].js`), but an app can set\n * `assetFileNames: 'static/[name][extname]'`, and marking that directory\n * immutable would pin a changed image under an unchanged URL for a year. A\n * pattern given as a function cannot be inspected, so it counts as unhashed:\n * those files fall back to the revalidating per-file rule.\n *\n * @internal Exported for testing.\n */\nexport function hashedAssetsDir(\n assetsDir: string,\n output: Pick<\n Rollup.NormalizedOutputOptions,\n 'entryFileNames' | 'chunkFileNames' | 'assetFileNames'\n >\n): string {\n const dir = assetsDir.replace(/^\\/+|\\/+$/g, '');\n const patterns = [output.entryFileNames, output.chunkFileNames, output.assetFileNames];\n const hashed = patterns.every((p) => typeof p === 'string' && p.includes('[hash'));\n return hashed ? dir : '';\n}\n\n/** The client bundle as its own `writeBundle` saw it. */\ninterface ClientOutput {\n /** From `hashedAssetsDir` — `''` when the naming patterns are not all hashed. */\n assetsDir: string;\n /** Every file name the bundle emitted, relative to the client output directory. */\n emitted: ReadonlySet<string>;\n}\n\n/**\n * Keep only the directories whose every file the client bundle emitted.\n *\n * A producer knows it hashes what *it* writes, not what else lands beside it:\n * Vite copies `public/` into the client output verbatim, so `public/assets/logo.png`\n * sits in `assets/` under a stable name, and `public/_rsc/…` would sit among\n * the hashed payloads. A directory holding any file the bundle did not emit\n * is not content-hashed as a whole, and marking it immutable would pin that\n * file for a year — so it is dropped, and its files take the per-file rule.\n *\n * @internal Exported for testing.\n */\nexport async function onlyEmittedDirs(\n clientDir: string,\n dirs: readonly string[],\n emitted: ReadonlySet<string>\n): Promise<string[]> {\n const kept: string[] = [];\n for (const dir of dirs) {\n const root = join(clientDir, dir);\n const entries = await readdir(root, { recursive: true, withFileTypes: true }).catch(() => []);\n const foreign = entries.some(\n (entry) =>\n entry.isFile() &&\n !emitted.has(relative(clientDir, join(entry.parentPath, entry.name)).replace(/\\\\/g, '/'))\n );\n if (!foreign) kept.push(dir);\n }\n return kept;\n}\n\nasync function runPostBuild(\n ctx: PluginContext,\n steps: PostBuildSteps,\n environments: EnvironmentOutputs,\n clientOutput: ClientOutput\n): Promise<void> {\n const output = ctx.config.output ?? 'server';\n const rsc = requireEnvironment(environments, 'rsc');\n const ssr = requireEnvironment(environments, 'ssr');\n\n // 1. The manifest is complete before anything renders with it. Published\n // for the steps that import the built bundle in this process — the same\n // value `manifestInit` carries to production. Assigned, never `??=`: a\n // second build in one process must not render with the first one's.\n const manifest = await finalizeBuildManifest(ctx, steps.fonts, rsc, ssr);\n if (manifest) Reflect.set(globalThis, '__TIMBER_BUILD_MANIFEST__', manifest);\n\n // 2–3. Each writes its own output and returns what it wrote.\n const prebuilt = await steps.prebuilt.capture(rsc.path);\n const site = output === 'static' ? await runStaticGeneration(ctx, rsc.path) : undefined;\n\n // 4.\n steps.report.print(prebuilt);\n\n // 5.\n const adapter = contextAdapter(ctx);\n if (!adapter || typeof adapter.buildOutput !== 'function') return;\n\n await adapter.buildOutput(\n adapterConfig(ctx),\n assembleBuildArtifacts({\n output,\n outputDir: ctx.buildDir,\n environments,\n immutableDirs: await onlyEmittedDirs(\n requireEnvironment(environments, 'client').path,\n [\n ...(clientOutput.assetsDir ? [clientOutput.assetsDir] : []),\n ...steps.fonts.immutableDirs(),\n ...(site?.immutableDirs ?? []),\n ],\n clientOutput.emitted\n ),\n prebuilt: prebuilt?.artifact,\n site,\n manifestInit: manifest ? serializeManifestInit(manifest) : undefined,\n })\n );\n}\n\nfunction requireEnvironment(\n environments: EnvironmentOutputs,\n name: ArtifactEnvironment\n): DirectoryArtifact {\n const artifact = environments[name];\n if (!artifact) {\n throw new Error(`[timber] Build output: the ${name} environment wrote no bundle`);\n }\n return artifact;\n}\n\n/**\n * Step 1: bring the build manifest to its final shape, once.\n *\n * `timber-build-manifest` creates it from the client bundle; this adds what\n * only exists once every environment is built — the font entries and the\n * per-route CSS and modulepreloads in the RSC plugin's assets manifest —\n * and then, when client JavaScript is disabled, removes every JavaScript\n * reference, from the manifest and from the assets manifests on disk. The\n * manifest's `js` / `modulepreload` are cleared after the merge has written\n * into them, so nothing the merge adds survives.\n *\n * Returns null only when no client bundle produced a manifest.\n *\n * @internal Exported for testing.\n */\nexport async function finalizeBuildManifest(\n ctx: PluginContext,\n fonts: FontsBuildStep,\n rsc: DirectoryArtifact,\n ssr: DirectoryArtifact\n): Promise<BuildManifest | null> {\n const manifest = ctx.buildManifest;\n if (manifest) {\n fonts.contributeManifest(manifest);\n // Per-route CSS and client reference JS, for <link rel=\"stylesheet\">\n // and <link rel=\"modulepreload\"> on server component routes (TIM-1014).\n await mergeRscAssetsManifest(rsc.path, ctx.root, manifest, ctx.routeClientRefKeys);\n }\n if (ctx.clientJavascript.disabled) {\n // Those files are not served, so hints for them are useless.\n if (manifest) {\n manifest.js = {};\n manifest.modulepreload = {};\n }\n await stripJsFromRscAssetsManifests([rsc.path, ssr.path]);\n }\n return manifest;\n}\n\n/**\n * The build manifest as a JS module that sets the global. Adapters write\n * it as `_timber-manifest-init.js` (or prepend it to the entry) and\n * evaluate it before the RSC handler, so `virtual:timber-build-manifest`\n * finds it.\n */\nfunction serializeManifestInit(manifest: BuildManifest): string {\n return `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\\n`;\n}\n\n/**\n * Dedupe the producers' directories and drop any that sits inside another.\n *\n * Two producers can name overlapping directories — a custom `assetsDir` of\n * `_timber` beside the fonts' `_timber/fonts`. Cloudflare and Netlify apply\n * every matching `_headers` rule, so emitting both would send two\n * `Cache-Control` values for one file; the outer directory already covers\n * the inner one.\n */\nfunction canonicalImmutableDirs(dirs: readonly string[]): string[] {\n const unique = [...new Set(dirs)];\n return unique.filter(\n (dir) => !unique.some((other) => other !== dir && dir.startsWith(`${other}/`))\n );\n}\n\n/**\n * Assemble the adapter's view of the build from what each step returned.\n *\n * Not a validator: every field is copied from the phase that produced it.\n * The throws are the states the union cannot represent — a Vite environment\n * that wrote no bundle, a static build with no site. Each means an earlier\n * phase failed without failing the build, and a deploy missing its SSR\n * bundle fails on the first request rather than here.\n *\n * @internal Exported for testing.\n */\nexport function assembleBuildArtifacts(input: {\n output: 'server' | 'static';\n outputDir: string;\n environments: EnvironmentOutputs;\n immutableDirs: readonly string[];\n prebuilt?: DirectoryArtifact;\n site?: StaticSite;\n manifestInit?: string;\n}): BuildArtifacts {\n const { output, outputDir, environments } = input;\n const client = requireEnvironment(environments, 'client');\n const immutableDirs = canonicalImmutableDirs(input.immutableDirs);\n\n if (output === 'static') {\n if (!input.site) {\n throw new Error(\n \"[timber] Build output: output is 'static' but static generation recorded no site\"\n );\n }\n const { pages, contentTypes } = input.site;\n return { output, outputDir, client, immutableDirs, pages, contentTypes };\n }\n\n return {\n output,\n outputDir,\n client,\n immutableDirs,\n rsc: requireEnvironment(environments, 'rsc'),\n ssr: requireEnvironment(environments, 'ssr'),\n prebuilt: input.prebuilt,\n manifestInit: input.manifestInit,\n };\n}\n","/**\n * timber-build-report — Post-build route summary table.\n *\n * After a production build, logs a per-route table showing:\n * - Route type (○ static, λ dynamic, ƒ function)\n * - Route-specific client JS size\n * - First-load JS size (gzip) — route-specific + shared chunks\n *\n * Only active during production builds. Sizes are computed from the\n * already-generated Vite client bundle — no extra analysis passes.\n *\n * Design docs: 18-build-system.md §\"Build Pipeline\", 07-routing.md\n * Task: TIM-287\n */\n\nimport { readFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { gzipSync } from 'node:zlib';\nimport type { Plugin, Logger } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode, RouteTree } from '../routing/types.ts';\nimport type { CaptureSummary } from '../server/prebuilt-builder.ts';\nimport type { PrebuiltCaptureResult } from './prebuilt-capture.ts';\nimport type { PrebuiltManifest } from '../server/prebuilt/payload-source.ts';\nimport { collectLeafRoutes } from '../routing/walkers.ts';\nimport { formatSize } from '../utils/format.ts';\n\n// ─── Public types ─────────────────────────────────────────────────────────\n\nexport type RouteType = 'static' | 'dynamic' | 'function';\n\nexport interface RouteEntry {\n path: string;\n type: RouteType;\n /** Route-specific client JS size in bytes (raw). */\n size: number;\n /** Total first-load JS in bytes (gzip): route-specific + shared. */\n firstLoadSize: number;\n}\n\n// ─── Route classification ─────────────────────────────────────────────────\n\nconst ROUTE_TYPE_ICONS: Record<RouteType, string> = {\n static: '○',\n dynamic: 'λ',\n function: 'ƒ',\n};\n\n/**\n * Classify a route by its segment chain and output mode.\n *\n * In server mode (default), all pages are dynamic (rendered per-request)\n * and API routes (route.ts) are classified as function.\n * In static mode, everything is pre-rendered at build time — all routes\n * are static regardless of dynamic segments or route.ts presence.\n */\nexport function classifyRoute(\n segments: SegmentNode[],\n outputMode: 'server' | 'static' = 'server'\n): RouteType {\n if (outputMode === 'static') return 'static';\n const leaf = segments[segments.length - 1];\n if (leaf?.route) return 'function';\n return 'dynamic';\n}\n\n// ─── Size helpers ─────────────────────────────────────────────────────────\n\nexport { formatSize };\n\nfunction green(text: string): string {\n return `\\x1b[92m${text}\\x1b[39m`; // bright/light green (ANSI 92)\n}\n\n// ─── Route tree collection ────────────────────────────────────────────────\n\ninterface RouteInfo {\n path: string;\n segments: SegmentNode[];\n entryFilePath: string | null;\n}\n\n/**\n * Walk the route tree and collect all leaf routes (pages + API endpoints).\n *\n * Wraps the shared `collectLeafRoutes` walker (TIM-848). Parallel slots\n * (`@artists`, `@shows`, etc.) are intentionally skipped — they render\n * alongside the parent page at the same URL and are not separately\n * URL-addressable. Their JS is captured in shared/layout chunks.\n *\n * After collection, entries are deduplicated by URL path so that overlapping\n * route groups (e.g. `(browse)` and `(marketing)` both producing `/`) only\n * appear once. The entry with the longest segment chain (most specific\n * match) wins.\n */\nexport function collectRoutes(tree: RouteTree): RouteInfo[] {\n const leaves = collectLeafRoutes(tree.root);\n const routes: RouteInfo[] = leaves.map((leaf) => ({\n path: leaf.urlPath,\n segments: leaf.segments,\n entryFilePath: leaf.page?.filePath ?? leaf.route?.filePath ?? null,\n }));\n\n // Deduplicate entries with the same URL path (e.g. from overlapping route groups).\n // Keep the entry with the longest segment chain (most specific match).\n const seen = new Map<string, RouteInfo>();\n for (const route of routes) {\n const existing = seen.get(route.path);\n if (!existing || route.segments.length > existing.segments.length) {\n seen.set(route.path, route);\n }\n }\n return Array.from(seen.values());\n}\n\n// ─── Report formatting ────────────────────────────────────────────────────\n\n/** Produce formatted report lines for the Vite logger. */\nexport function buildRouteReport(entries: RouteEntry[], sharedSize: number): string[] {\n const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));\n\n const header = 'Route (app)';\n const sizeHeader = 'Size';\n const firstLoadHeader = 'First Load JS';\n\n const pathW = Math.max(header.length + 2, ...sorted.map((e) => e.path.length + 6));\n const sizeW = Math.max(sizeHeader.length, 14);\n const flW = Math.max(firstLoadHeader.length, 10);\n const totalW = pathW + sizeW + flW + 4;\n const sep = '─'.repeat(totalW);\n\n const lines: string[] = [];\n\n // Header\n lines.push(\n `${pad(header, pathW)} ${pad(sizeHeader, sizeW, 'left')} ${pad(firstLoadHeader, flW, 'left')}`\n );\n lines.push(sep);\n\n // Routes\n for (const entry of sorted) {\n const icon = ROUTE_TYPE_ICONS[entry.type];\n const pathStr = ` ${icon} ${entry.path}`;\n const sizeStr = entry.size === 0 ? green('zero unique JS') : formatSize(entry.size);\n const flStr = formatSize(entry.firstLoadSize);\n lines.push(\n `${pad(pathStr, pathW)} ${pad(sizeStr, sizeW, 'left')} ${pad(flStr, flW, 'left')}`\n );\n }\n\n // Footer\n lines.push(sep);\n lines.push(\n `${pad(' Shared by all', pathW)} ${pad('', sizeW, 'left')} ${pad(formatSize(sharedSize), flW, 'left')}`\n );\n lines.push('');\n lines.push('○ (Static) λ (Dynamic) ƒ (Function)');\n\n return lines;\n}\n\n/** Check route entries against a First-Load-JS budget and return warning lines. */\nexport function buildWarnings(entries: RouteEntry[], budget?: { firstLoadJs?: number }): string[] {\n if (!budget?.firstLoadJs) return [];\n const limit = budget.firstLoadJs;\n const warnings: string[] = [];\n for (const entry of entries) {\n if (entry.firstLoadSize > limit) {\n warnings.push(\n `⚠ ${entry.path} first-load JS (${formatSize(entry.firstLoadSize)}) exceeds budget (${formatSize(limit)})`\n );\n }\n }\n return warnings;\n}\n\nfunction pad(str: string, width: number, align: 'left' | 'right' = 'right'): string {\n const gap = Math.max(0, width - stripAnsi(str).length);\n return align === 'left' ? ' '.repeat(gap) + str : str + ' '.repeat(gap);\n}\n\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\u001b\\[\\d+m/g, '');\n}\n\n// ─── Prebuilt component stats ────────────────────────────────────────────\n\nexport interface PrebuiltComponentStats {\n componentId: string;\n entryCount: number;\n totalBytes: number;\n}\n\nexport interface PrebuiltReportData {\n components: PrebuiltComponentStats[];\n totalEntries: number;\n totalBytes: number;\n skippedCount: number;\n skippedReasons: Array<{ componentId: string; route: string; message: string }>;\n}\n\n/** Read the manifest of the prebuilt artifact this build recorded, if any. */\nexport function loadPrebuiltManifest(prebuiltDir: string | undefined): PrebuiltManifest | null {\n if (!prebuiltDir) return null;\n return JSON.parse(readFileSync(join(prebuiltDir, 'manifest.json'), 'utf-8')) as PrebuiltManifest;\n}\n\nexport function buildPrebuiltReportData(\n manifest: PrebuiltManifest | null,\n summary: CaptureSummary | undefined\n): PrebuiltReportData | null {\n const hasCaptures = summary && (summary.captured > 0 || summary.skipped.length > 0);\n if (!manifest && !hasCaptures) return null;\n\n const components: PrebuiltComponentStats[] = [];\n let totalEntries = 0;\n let totalBytes = 0;\n\n if (manifest) {\n for (const [componentId, component] of Object.entries(manifest)) {\n let entryCount = 0;\n let componentBytes = 0;\n for (const entry of Object.values(component.entries)) {\n entryCount++;\n componentBytes += entry.bytes ?? 0;\n }\n components.push({ componentId, entryCount, totalBytes: componentBytes });\n totalEntries += entryCount;\n totalBytes += componentBytes;\n }\n components.sort((a, b) => a.componentId.localeCompare(b.componentId));\n }\n\n const skippedCount = summary?.skipped.length ?? 0;\n const skippedReasons = (summary?.skipped ?? []).map((s) => ({\n componentId: s.componentId,\n route: s.routeUrlPath,\n message: s.message,\n }));\n\n return { components, totalEntries, totalBytes, skippedCount, skippedReasons };\n}\n\nexport function buildPrebuiltReport(data: PrebuiltReportData): string[] {\n const lines: string[] = [];\n\n const total = data.totalEntries + data.skippedCount;\n lines.push(\n `Prebuilt ${data.totalEntries}/${total} entries across ` +\n `${data.components.length} component${data.components.length !== 1 ? 's' : ''}` +\n (data.totalBytes > 0 ? ` (${formatSize(data.totalBytes)} total)` : '') +\n '.' +\n (data.skippedCount > 0 ? ` ${data.skippedCount} skipped due to errors.` : '')\n );\n\n if (data.components.length > 0) {\n lines.push('');\n const nameHeader = 'Component';\n const entriesHeader = 'Entries';\n const sizeHeader = 'Size';\n\n const nameW = Math.max(\n nameHeader.length + 2,\n ...data.components.map((c) => c.componentId.length + 4)\n );\n const entriesW = Math.max(entriesHeader.length, 8);\n const sizeW = Math.max(sizeHeader.length, 10);\n const totalW = nameW + entriesW + sizeW + 4;\n const sep = '─'.repeat(totalW);\n\n lines.push(\n `${pad(nameHeader, nameW)} ${pad(entriesHeader, entriesW, 'left')} ${pad(sizeHeader, sizeW, 'left')}`\n );\n lines.push(sep);\n\n for (const comp of data.components) {\n const nameStr = ` ◆ ${comp.componentId}`;\n const entriesStr = String(comp.entryCount);\n const sizeStr = formatSize(comp.totalBytes);\n lines.push(\n `${pad(nameStr, nameW)} ${pad(entriesStr, entriesW, 'left')} ${pad(sizeStr, sizeW, 'left')}`\n );\n }\n }\n\n if (data.skippedReasons.length > 0) {\n lines.push('');\n lines.push('Skipped entries:');\n for (const s of data.skippedReasons) {\n lines.push(` ⚠ ${s.componentId} (${s.route}) — ${s.message}`);\n }\n }\n\n return lines;\n}\n\n// ─── Bundle analysis ──────────────────────────────────────────────────────\n\ninterface ChunkSize {\n raw: number;\n gzip: number;\n}\n\ninterface OutputChunkLike {\n type: 'chunk' | 'asset';\n fileName: string;\n name?: string;\n code?: string;\n source?: string | Uint8Array;\n modules?: Record<string, unknown>;\n facadeModuleId?: string | null;\n}\n\n/** Measure raw + gzip sizes for all JS chunks and CSS assets in a bundle. */\nexport function collectChunkSizes(bundle: Record<string, OutputChunkLike>): Map<string, ChunkSize> {\n const sizes = new Map<string, ChunkSize>();\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type === 'chunk' && item.code) {\n sizes.set(fileName, measure(item.code));\n } else if (item.type === 'asset' && fileName.endsWith('.css') && item.source != null) {\n const src =\n typeof item.source === 'string' ? item.source : new TextDecoder().decode(item.source);\n sizes.set(fileName, measure(src));\n }\n }\n return sizes;\n}\n\nfunction measure(content: string): ChunkSize {\n const buf = new TextEncoder().encode(content);\n return { raw: buf.length, gzip: gzipSync(buf).length };\n}\n\n/** Find the output chunk that contains a given input file. */\nexport function findChunkForFile(\n filePath: string,\n bundle: Record<string, OutputChunkLike>\n): string | null {\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type !== 'chunk') continue;\n if (item.facadeModuleId === filePath) return fileName;\n if (item.modules && filePath in item.modules) return fileName;\n }\n return null;\n}\n\n// ─── Route → chunk group matching ────────────────────────────────────────\n\n/**\n * Derive the expected client chunk group prefix for a route.\n *\n * Mirrors the `clientChunkGroup` logic: extract the first non-group segment\n * from the route's file path under appDir. Routes at the root level or\n * without a matching segment return null (their JS is in client-shared).\n */\nfunction routeChunkGroupPrefix(entryFilePath: string, appDir: string, root: string): string | null {\n const appPrefix = relative(root, appDir).replace(/\\\\/g, '/') + '/';\n const relPath = relative(root, entryFilePath).replace(/\\\\/g, '/');\n if (!relPath.startsWith(appPrefix)) return null;\n\n const withinApp = relPath.slice(appPrefix.length);\n const segments = withinApp.split('/');\n for (const seg of segments) {\n if (seg.includes('.')) break;\n if (seg.startsWith('(') && seg.endsWith(')')) continue;\n return `client-${seg}`;\n }\n return null;\n}\n\n/**\n * Find all client bundle chunks belonging to a chunk group.\n *\n * Uses the chunk's `name` property (set by Rolldown from the `clientChunks`\n * callback's return value) for exact matching. The `name` is the group name\n * itself (e.g. `client-docs`), not the hashed filename.\n */\nexport function findChunksForGroup(\n groupName: string,\n chunkSizes: Map<string, ChunkSize>,\n bundle?: Record<string, OutputChunkLike>\n): string[] {\n if (!bundle) return [];\n const matched: string[] = [];\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type !== 'chunk') continue;\n if (item.name === groupName && chunkSizes.has(fileName)) {\n matched.push(fileName);\n }\n }\n return matched;\n}\n\n// ─── Build route entries from collected data ──────────────────────────────\n\nfunction buildEntries(\n routeTree: RouteTree,\n chunkSizes: Map<string, ChunkSize>,\n bundle: Record<string, OutputChunkLike>,\n outputMode: 'server' | 'static',\n appDir?: string,\n root?: string\n): { entries: RouteEntry[]; sharedGzip: number } {\n const routeInfos = collectRoutes(routeTree);\n\n // Total gzip across all client chunks\n let totalGzip = 0;\n for (const s of chunkSizes.values()) totalGzip += s.gzip;\n\n // Per-route sizes. Track route-specific chunks to compute shared size.\n const routeChunkFiles = new Set<string>();\n const entries: RouteEntry[] = [];\n\n for (const info of routeInfos) {\n let raw = 0;\n let gzip = 0;\n\n if (info.entryFilePath) {\n // Try chunk group matching first (works for server component routes\n // whose client JS is in client-<segment> chunks, not in the route's\n // own page.tsx chunk). Falls back to direct chunk lookup.\n let matched = false;\n if (appDir && root) {\n const groupPrefix = routeChunkGroupPrefix(info.entryFilePath, appDir, root);\n if (groupPrefix) {\n const chunks = findChunksForGroup(groupPrefix, chunkSizes, bundle);\n for (const chunk of chunks) {\n const s = chunkSizes.get(chunk);\n if (s) {\n raw += s.raw;\n gzip += s.gzip;\n }\n routeChunkFiles.add(chunk);\n }\n if (chunks.length > 0) matched = true;\n }\n }\n\n if (!matched) {\n const chunk = findChunkForFile(info.entryFilePath, bundle);\n if (chunk) {\n const s = chunkSizes.get(chunk);\n if (s) {\n raw = s.raw;\n gzip = s.gzip;\n }\n routeChunkFiles.add(chunk);\n }\n }\n }\n\n entries.push({\n path: info.path,\n type: classifyRoute(info.segments, outputMode),\n size: raw,\n firstLoadSize: gzip, // route-specific gzip — shared added below\n });\n }\n\n // Shared = total gzip minus route-specific gzip\n let routeGzip = 0;\n for (const f of routeChunkFiles) routeGzip += chunkSizes.get(f)?.gzip ?? 0;\n const sharedGzip = totalGzip - routeGzip;\n\n for (const e of entries) e.firstLoadSize += sharedGzip;\n\n return { entries, sharedGzip };\n}\n\n// ─── Vite plugin ──────────────────────────────────────────────────────────\n\n/**\n * Suppress RSC/SSR per-chunk build log lines.\n *\n * Vite logs each output chunk via config.logger.info(). We wrap that method\n * to filter lines matching dist/rsc/ or dist/ssr/ paths. The regex is\n * non-anchored because Vite prepends ANSI color codes.\n */\nfunction suppressNonClientLogs(config: { command: string; logger: Logger }): void {\n if (config.command !== 'build') return;\n const orig = config.logger.info.bind(config.logger);\n config.logger.info = (msg: string, opts?: { timestamp?: boolean }) => {\n if (typeof msg === 'string' && /dist\\/(rsc|ssr)\\//.test(msg)) return;\n orig(msg, opts);\n };\n}\n\n/**\n * What the post-build phase asks of the build report (plugins/post-build.ts).\n * Printed from there, once, after every environment is built and after the\n * prebuilt capture pass — so nothing here depends on the order in which\n * Vite closes each environment's bundle.\n */\nexport interface BuildReportStep {\n print(prebuilt: PrebuiltCaptureResult | null): void;\n}\n\nexport function timberBuildReport(ctx: PluginContext): Plugin & { api: BuildReportStep } {\n let logger: Logger | null = null;\n let chunkSizes: Map<string, ChunkSize> | null = null;\n let clientBundle: Record<string, OutputChunkLike> | null = null;\n const buildStart = performance.now();\n\n function printRouteTable(): void {\n if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;\n\n const outputMode = ctx.config.output ?? 'server';\n const clientJsDisabled = ctx.clientJavascript.disabled;\n const { entries, sharedGzip } = clientJsDisabled\n ? {\n entries: collectRoutes(ctx.routeTree).map((info) => ({\n path: info.path,\n type: classifyRoute(info.segments, outputMode),\n size: 0,\n firstLoadSize: 0,\n })),\n sharedGzip: 0,\n }\n : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);\n const elapsed = ((performance.now() - buildStart) / 1000).toFixed(2);\n const lines = buildRouteReport(entries, sharedGzip);\n\n logger.info('');\n for (const line of lines) logger.info(line);\n\n const warnings = buildWarnings(entries, ctx.config.budget);\n if (warnings.length > 0) {\n logger.info('');\n for (const w of warnings) logger.warn(w);\n }\n\n logger.info('');\n logger.info(\n `✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`\n );\n logger.info('');\n }\n\n function printPrebuiltReport(prebuilt: PrebuiltCaptureResult | null): void {\n if (!logger || !prebuilt) return;\n const manifest = loadPrebuiltManifest(prebuilt.artifact?.path);\n const prebuiltData = buildPrebuiltReportData(manifest, prebuilt.summary);\n if (!prebuiltData) return;\n\n logger.info('');\n for (const line of buildPrebuiltReport(prebuiltData)) logger.info(line);\n logger.info('');\n }\n\n return {\n name: 'timber-build-report',\n\n api: {\n print(prebuilt) {\n if (ctx.dev) return;\n printRouteTable();\n printPrebuiltReport(prebuilt);\n },\n },\n\n config(_cfg, { command }) {\n if (command !== 'build') return;\n return {\n environments: {\n rsc: { build: { reportCompressedSize: false } },\n ssr: { build: { reportCompressedSize: false } },\n },\n };\n },\n\n configResolved(config) {\n logger = config.logger;\n suppressNonClientLogs(config);\n },\n\n generateBundle(_options, bundle) {\n if (ctx.dev) return;\n if (this.environment?.name && this.environment.name !== 'client') return;\n\n chunkSizes = collectChunkSizes(bundle as Record<string, OutputChunkLike>);\n clientBundle = { ...bundle } as Record<string, OutputChunkLike>;\n },\n };\n}\n","/**\n * Server action bound args encryption utilities.\n *\n * Provides key management for the RSC plugin's built-in bound args encryption.\n * The RSC plugin (@vitejs/plugin-rsc) handles the actual encrypt/decrypt via\n * AES-256-GCM — this module handles:\n *\n * 1. Key sourcing: auto-generated at build time (embedded in bundle), overridable\n * via env var for cross-build key sharing (rolling/blue-green deployments)\n * 2. Build-time key expression generation for the RSC plugin's `defineEncryptionKey`\n *\n * Encryption is always on in production. In dev mode, it's on by default\n * (matching the RSC plugin's behavior) but can be disabled for debugging.\n *\n * ## Known Security Considerations\n *\n * 1. **defineEncryptionKey is a raw JS expression.** The RSC plugin inlines it\n * verbatim into generated code. We only emit the hardcoded string\n * `process.env.TIMBER_ACTIONS_ENCRYPTION_KEY` — never user-controlled input.\n * If this function is ever extended to accept configurable env var names,\n * the expression MUST be validated against a safe pattern.\n *\n * 2. **Key material lives in GC-visible JS strings.** `atob()` decodes the key\n * into a regular JavaScript string on the V8 heap. JavaScript has no\n * `SecureString` or memory-zeroing primitive — this is an inherent platform\n * limitation. Acceptable for web server use; would need review for FIPS.\n *\n * 3. **TIMBER_ACTIONS_ENCRYPTION_KEY must be set at both build time and runtime.**\n * At build time, we validate the key format and emit a runtime expression.\n * If the env var is present at build time but missing at runtime, the server\n * will crash on first action invocation with an opaque `atob(undefined)` error.\n * If the env var is present at runtime but was absent at build time, the RSC\n * plugin will have generated its own key and the env var is silently ignored.\n *\n * See design/08-forms-and-actions.md §\"Security\"\n * See design/13-security.md\n */\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/** User-facing configuration for action bound args encryption. */\nexport interface ActionEncryptionConfig {\n /**\n * Disable encryption in dev mode for easier debugging.\n * Has no effect in production — encryption is always enabled.\n * Default: false (encryption is on in dev too).\n */\n disableInDev?: boolean;\n}\n\n// ─── Key Resolution ───────────────────────────────────────────────────────\n\n/**\n * Regex for safe `defineEncryptionKey` expressions.\n *\n * The RSC plugin inlines this expression verbatim into generated JavaScript.\n * We restrict it to `process.env.<UPPER_SNAKE_CASE>` to prevent code injection.\n * See \"Known Security Considerations\" at the top of this file.\n */\nconst SAFE_KEY_EXPR = /^process\\.env\\.[A-Z_][A-Z0-9_]*$/;\n\n/**\n * Build the `defineEncryptionKey` expression for the RSC plugin.\n *\n * The RSC plugin accepts a JavaScript expression string that will be\n * inlined into the encryption runtime module. At runtime, this expression\n * must evaluate to the base64-encoded encryption key.\n *\n * Priority:\n * 1. `TIMBER_ACTIONS_ENCRYPTION_KEY` env var (for cross-build key sharing\n * in rolling/blue-green deployments)\n * 2. Auto-generated at build time (RSC plugin default — embedded in bundle,\n * consistent across all instances of the same build)\n *\n * For env var keys, we generate a runtime expression that reads the env var.\n * For auto-generated keys, we return undefined and let the RSC plugin handle it.\n */\nexport function resolveEncryptionKeyExpression(): string | undefined {\n // Check for env var override — used for cross-build key sharing where\n // multiple builds must agree on the same encryption key.\n const envKey = process.env.TIMBER_ACTIONS_ENCRYPTION_KEY;\n if (envKey) {\n // Validate the key format (must be base64-encoded 32-byte key)\n validateKeyFormat(envKey);\n\n // Return a runtime expression that reads the env var at startup.\n // This ensures the key is read at runtime, not embedded in the build.\n const expr = 'process.env.TIMBER_ACTIONS_ENCRYPTION_KEY';\n\n // Defense-in-depth: validate the expression matches our safe pattern.\n // This is redundant today (hardcoded string), but protects against\n // future refactors that might make the expression configurable.\n if (!SAFE_KEY_EXPR.test(expr)) {\n throw new Error(`Unsafe encryption key expression: ${expr}`);\n }\n\n return expr;\n }\n\n // No override — let the RSC plugin auto-generate a per-build key\n return undefined;\n}\n\n/**\n * Determine whether action encryption should be enabled.\n *\n * Encryption is always enabled in production. In dev mode, it's enabled\n * by default but can be disabled via config for debugging.\n */\nexport function shouldEnableEncryption(isDev: boolean, config?: ActionEncryptionConfig): boolean {\n if (!isDev) return true; // Always on in production\n if (config?.disableInDev) return false; // Opt-out in dev\n return true; // On by default in dev too\n}\n\n// ─── Key Validation ───────────────────────────────────────────────────────\n\n/**\n * Validate that a key string is a valid base64-encoded 256-bit key.\n * Throws a descriptive error if the key is malformed.\n */\nexport function validateKeyFormat(key: string): void {\n // Decode base64 and check length (32 bytes = 256 bits)\n try {\n const decoded = atob(key);\n const bytes = decoded.length;\n if (bytes !== 32) {\n throw new Error(\n `TIMBER_ACTIONS_ENCRYPTION_KEY must be a base64-encoded 256-bit (32-byte) key. ` +\n `Got ${bytes} bytes. Generate one with: ` +\n `node -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"`\n );\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes('TIMBER_ACTIONS_ENCRYPTION_KEY')) {\n throw error;\n }\n throw new Error(\n `TIMBER_ACTIONS_ENCRYPTION_KEY is not valid base64. ` +\n `Generate a key with: ` +\n `node -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"`\n );\n }\n}\n","/**\n * Dev holding server — serves a loading page while Vite initializes.\n *\n * When `timber dev` (or `vite dev`) starts, Vite takes several seconds\n * to initialize all plugins, scan routes, and boot the RSC environment.\n * During this window, the port is unbound and browsers get\n * ERR_CONNECTION_REFUSED.\n *\n * This module creates a lightweight HTTP server that binds the port\n * immediately and serves a branded holding page with auto-refresh.\n * Once Vite is ready, the holding server is closed and Vite's server\n * takes over the port.\n *\n * The holding server is started in rootSync's config() hook (the\n * earliest Vite plugin lifecycle point where we know the port) and\n * closed directly in timber-dev-server's configureServer() hook\n * (the last plugin, awaited). configureServer runs during\n * createServer(), well before Vite's port probe and bind, so the\n * port is free by the time httpServerStart() runs. (TIM-1419)\n *\n * Browser requests (Accept: text/html) get the HTML holding page.\n * API requests (Accept: application/json) get a 503 JSON response.\n * All responses include Retry-After: 1.\n *\n * See design/21-dev-server.md, TIM-665.\n */\n\nimport http from 'node:http';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface HoldingServer {\n /**\n * Start listening on the given port and host.\n * The host must match Vite's resolved `server.host` so the probe\n * faithfully detects conflicts on the same address Vite will bind.\n * Returns the actual bound port (useful when port is 0 for OS assignment).\n */\n listen(port: number, host?: string): Promise<number>;\n\n /** Gracefully close the server and stop accepting connections. */\n close(): Promise<void>;\n}\n\n// ─── Holding Page HTML ────────────────────────────────────────────────────\n\n/**\n * Minimal self-contained HTML holding page.\n *\n * Matches the timber.js docs site theme:\n * - Light mode: warm stone/grain background, timber/bark text\n * - Dark mode: stone-900 background, stone-200 text\n * - 🪵 timber.js branding\n *\n * Uses meta-refresh (1s) for auto-reload — works without JavaScript.\n * Inline CSS only, no external dependencies.\n */\nconst HOLDING_PAGE_HTML = [\n '<!DOCTYPE html>',\n '<html lang=\"en\">',\n '<head>',\n ' <meta charset=\"utf-8\">',\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">',\n ' <meta http-equiv=\"refresh\" content=\"2\">',\n ' <title>timber — starting...</title>',\n ' <style>',\n ' *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }',\n ' body {',\n ' font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;',\n ' background: #fafaf9;',\n ' color: #44403c;',\n ' display: flex;',\n ' align-items: center;',\n ' justify-content: center;',\n ' min-height: 100vh;',\n ' -webkit-font-smoothing: antialiased;',\n ' }',\n ' @media (prefers-color-scheme: dark) {',\n ' body { background: #1c1917; color: #e7e5e4; }',\n ' .message { color: #a8a29e; }',\n ' .spinner { border-color: #57534e; border-top-color: #a1887f; }',\n ' .logo { color: #e7e5e4; }',\n ' }',\n ' .container { text-align: center; padding: 2rem; }',\n ' .logo {',\n ' font-size: 1.5rem;',\n ' font-weight: 700;',\n ' letter-spacing: -0.02em;',\n ' color: #5c3d2e;',\n ' margin-bottom: 1.5rem;',\n ' }',\n ' .message {',\n ' font-size: 0.95rem;',\n ' color: #78716c;',\n ' margin-bottom: 2rem;',\n ' }',\n ' .spinner {',\n ' width: 24px;',\n ' height: 24px;',\n ' border: 2.5px solid #d7ccc8;',\n ' border-top-color: #6d4c41;',\n ' border-radius: 50%;',\n ' animation: spin 0.8s linear infinite;',\n ' margin: 0 auto;',\n ' }',\n ' @keyframes spin { to { transform: rotate(360deg); } }',\n ' </style>',\n '</head>',\n '<body>',\n ' <div class=\"container\">',\n ' <div class=\"logo\">\\u{1FAB5} timber.js</div>',\n ' <p class=\"message\">Dev server starting&hellip;</p>',\n ' <div class=\"spinner\"></div>',\n ' </div>',\n '</body>',\n '</html>',\n].join('\\n');\n\n// ─── Factory ──────────────────────────────────────────────────────────────\n\n/**\n * Create a holding HTTP server that serves a loading page during startup.\n *\n * The config hook attempts one bind on the requested port. If it fails,\n * startup continues without the holding page; Vite owns port selection.\n * The last configureServer hook awaits close() before Vite probes/binds.\n */\nexport function createHoldingServer(): HoldingServer {\n const server = http.createServer((req, res) => {\n const accept = req.headers.accept ?? '';\n\n // API requests: JSON 503\n if (accept.includes('application/json') && !accept.includes('text/html')) {\n res.writeHead(503, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Retry-After': '1',\n 'Cache-Control': 'no-store',\n });\n res.end(\n JSON.stringify({\n error: 'Service Unavailable',\n message: 'timber dev server is starting — please retry shortly',\n })\n );\n return;\n }\n\n // Browser and other requests: HTML holding page\n res.writeHead(503, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Retry-After': '1',\n 'Cache-Control': 'no-store',\n });\n res.end(HOLDING_PAGE_HTML);\n });\n\n return {\n listen(port: number, host?: string): Promise<number> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => {\n server.removeListener('error', reject);\n const addr = server.address();\n const boundPort = typeof addr === 'object' && addr ? addr.port : port;\n resolve(boundPort);\n });\n });\n },\n\n close(): Promise<void> {\n // Kill lingering keep-alive sockets immediately — the holding\n // page's meta-refresh keeps browser connections alive, and\n // server.close() waits for all sockets to drain before the\n // 'close' event fires. Without this, the close can stall for\n // the full keepAliveTimeout (~5s), blocking the port handoff.\n server.closeAllConnections();\n return new Promise((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n };\n}\n","/** Port input precedence for dev and preview. Vite owns binding and restart reuse. */\n\n/** Default port used by `timber dev` and `timber preview`. */\nexport const DEFAULT_PORT = 3000;\n\n// ── Pure resolution ────────────────────────────────────────────────────\n\nexport interface ResolvePortInput {\n /**\n * Port read from `vite.config.ts` `server.port` or the `--port` CLI\n * flag (Vite merges `--port` into `userConfig.server.port` before\n * plugins see it).\n */\n configPort?: number | undefined;\n /** Raw value of `process.env.PORT`. */\n envPort?: string | undefined;\n /** Default port to use when neither `configPort` nor `envPort` is set. */\n defaultPort?: number;\n}\n\nexport interface ResolvedPortInput {\n /** Port to start binding from. */\n port: number;\n /**\n * `true` if the port came from an explicit user override (config or\n * env). Preview uses this to default to strict port binding.\n */\n explicit: boolean;\n}\n\n/**\n * Pure: compute the starting port from config / env / defaults.\n *\n * Performs no I/O.\n */\nexport function resolveStartPort(input: ResolvePortInput): ResolvedPortInput {\n const defaultPort = input.defaultPort ?? DEFAULT_PORT;\n\n // `configPort` wins over `envPort`. This matches Vite's behavior:\n // `vite --port 4000` overrides `PORT=5000` in the environment.\n if (typeof input.configPort === 'number' && Number.isFinite(input.configPort)) {\n return { port: input.configPort, explicit: true };\n }\n\n if (input.envPort != null && input.envPort !== '') {\n const parsed = Number(input.envPort);\n if (Number.isFinite(parsed) && parsed > 0) {\n return { port: parsed, explicit: true };\n }\n }\n\n return { port: defaultPort, explicit: false };\n}\n","/**\n * @timber-js/app — Root entry point (public API).\n *\n * User-facing exports: timber(), defineConfig(), TimberUserConfig, Routes.\n *\n * Internal helpers (PluginContext, resolveAppDir, loadTimberConfigFile,\n * warnConfigConflicts, resolveClientJavascript) live in plugin-context.ts\n * and are NOT re-exported here. Sub-plugins import them via relative paths.\n *\n * Design doc: 18-build-system.md §\"Plugin Architecture\"\n */\n\nimport type { Plugin, PluginOption } from 'vite';\nimport type { ReactCompilerOptions } from '@vitejs/plugin-react';\nimport { createLogger } from 'vite';\nimport { join, relative, resolve } from 'node:path';\nimport { createRequire } from 'node:module';\nimport react from '@vitejs/plugin-react';\nimport { timberContent } from './plugins/content.ts';\nimport { timberDevServer } from './plugins/dev-server.ts';\nimport { timberEntries, BROWSER_ENTRY_FILE } from './plugins/entries.ts';\nimport { timberMdx } from './plugins/mdx.ts';\nimport { timberRouting } from './plugins/routing.ts';\nimport { timberShims } from './plugins/shims.ts';\nimport { timberFonts } from './plugins/fonts.ts';\nimport { timberStaticBuild } from './plugins/static-build.ts';\nimport { timberBuildManifest } from './plugins/build-manifest.ts';\nimport { timberDevLogs, originalConsole, wrapLoggerWithOriginalConsole } from './dev-tools/logs.ts';\nimport { resolveForwardConsole } from './dev-tools/browser-logs.ts';\nimport { timberReactProd } from './plugins/react-prod.ts';\nimport { timberReactResolve } from './plugins/react-resolve.ts';\nimport { timberChunks } from './plugins/chunks.ts';\nimport { clientChunkGroup } from './plugins/client-chunks.ts';\nimport { timberServerBundle } from './plugins/server-bundle.ts';\nimport { timberCacheTransform } from './plugins/cache.ts';\nimport { timberRequestDep } from './plugins/request-dep/index.ts';\nimport { timberPrebuilt } from './plugins/prebuilt.ts';\nimport { timberPrerenderSugar } from './plugins/prerender-sugar.ts';\nimport { timberCloudflareWasm } from './plugins/cloudflare-wasm.ts';\nimport { timberPostBuild } from './plugins/post-build.ts';\nimport { timberBuildReport } from './plugins/build-report.ts';\nimport { createNoopTimer } from './utils/startup-timer.ts';\nimport {\n validateConfig,\n reportConfigErrors,\n checkPeerDependencies,\n formatMissingPeers,\n} from './config-validation.ts';\nimport {\n resolveEncryptionKeyExpression,\n shouldEnableEncryption,\n} from './server/action-encryption.ts';\nimport { createHoldingServer } from './dev-tools/holding-server.ts';\nimport { resolveStartPort } from './server/port-resolution.ts';\nimport type { TimberUserConfig } from './config-types.ts';\nimport type { PluginContext, TimberPluginApi } from './plugin-context.ts';\nimport {\n createPluginContext,\n loadTimberConfigFile,\n mergeFileConfig,\n resolveAppDir,\n resolveClientJavascript,\n resolveBuildDir,\n} from './plugin-context.ts';\n\n// ── Public API ────────────────────────────────────────────────────────────\n\nexport type { TimberUserConfig } from './config-types.ts';\n\n// Metadata route handler types — re-exported so user-authored metadata\n// route files (sitemap.ts, robots.ts, manifest.ts, icon.tsx, etc.) can\n// import them from the package root without reaching into ./server.\n// The canonical location for these types is '@timber-js/app/server'; this\n// root re-export is a convenience for typed metadata route handlers.\n// See design/16-metadata.md §\"Metadata Routes\".\nexport type { Metadata, MetadataRoute, MetadataHandler, MetadataResult } from './server/types.ts';\n\n/**\n * Route map interface — augmented by the generated timber-routes.d.ts.\n *\n * Each key is a route path pattern. Values have:\n * segmentParams: shape of URL segment params (e.g. { id: string })\n *\n * There is no `searchParams` member: since TIM-1343 the framework does not\n * scan for search-param definitions, so it has nothing to type them with. A\n * definition carries its own type to call sites through an ordinary import.\n *\n * This interface is empty by default and populated via codegen.\n * See design/09-typescript.md §\"Typed Routes\".\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, typescript/no-empty-interface\nexport interface Routes {}\n\n/**\n * Type-safe helper for timber.config.ts files.\n *\n * A pass-through identity function that provides autocomplete and\n * type checking for timber configuration. No runtime validation —\n * purely a DX convenience (same pattern as Vite's defineConfig).\n *\n * @example\n * ```ts\n * // timber.config.ts\n * import { defineConfig } from '@timber-js/app';\n *\n * export default defineConfig({\n * output: 'server',\n * pageExtensions: ['tsx', 'ts', 'mdx'],\n * });\n * ```\n */\nexport function defineConfig(config: TimberUserConfig): TimberUserConfig {\n return config;\n}\n\n// ── Private helpers ───────────────────────────────────────────────────────\n\n/**\n * Build the options object for @vitejs/plugin-rsc.\n *\n * Uses a getter for `enableActionEncryption` so the RSC plugin reads\n * the value lazily — after ctx.dev is set in configResolved. This lets\n * `actionEncryption.disableInDev` work correctly even though the RSC\n * plugin is created before Vite resolves the command.\n */\nfunction createRscOptions(\n ctx: PluginContext,\n encryptionKeyExpr: string | undefined\n): Record<string, unknown> {\n const options: Record<string, unknown> = {\n serverHandler: false,\n customClientEntry: true,\n entries: {\n rsc: 'virtual:timber-rsc-entry',\n ssr: 'virtual:timber-ssr-entry',\n client: 'virtual:timber-browser-entry',\n },\n // Group client references by layout boundary to balance route-scoped code\n // splitting with HTTP request count. A constant group name ('client-refs')\n // would collapse all routes into one chunk — any page downloads every\n // client component. Per-serverChunk grouping creates many sub-500B files.\n // Layout-boundary grouping is the middle ground: components under the same\n // layout segment share a chunk. See design/27-chunking-strategy.md, TIM-440, TIM-499.\n clientChunks: (meta: { id: string; normalizedId: string; serverChunk: string }) =>\n clientChunkGroup(meta, ctx.appDir, ctx.root, ctx.sharedModuleFacades),\n };\n\n // Bound args encryption — AES-256-GCM authenticated encryption for\n // closure variables in 'use server' functions. Always on in production,\n // configurable in dev. See design/08-forms-and-actions.md §\"Bound Args Encryption\".\n //\n // Uses a getter so the RSC plugin reads the value lazily in its transform\n // hooks, after ctx.dev is set in configResolved. This lets disableInDev\n // work correctly — ctx.dev is false at construction time but true during\n // dev server transforms.\n Object.defineProperty(options, 'enableActionEncryption', {\n get() {\n return shouldEnableEncryption(ctx.dev, ctx.config.actionEncryption);\n },\n enumerable: true,\n });\n\n // When TIMBER_ACTIONS_ENCRYPTION_KEY is set, pass it as a runtime expression\n // so the RSC plugin uses it instead of auto-generating a per-build key.\n if (encryptionKeyExpr) {\n options.defineEncryptionKey = encryptionKeyExpr;\n }\n\n return options;\n}\n\n// NOTE: 'use cache' directive transform removed — future feature pending design doc.\n// The timber.cache() API (createCache) remains available for explicit caching.\n// See design/06-caching.md.\n\n// ── Main plugin factory ──────────────────────────────────────────────────\n\n/**\n * Create the timber Vite plugin array.\n *\n * Loads timber.config.ts and all dependencies synchronously before\n * constructing the plugin array. This ensures ALL plugins — including\n * the RSC plugin and React Compiler — see the fully merged config\n * (inline + file-based). No async, no deferred config, no stale reads.\n *\n * Requires Node >= 22.12 for synchronous require() of ESM modules\n * (@vitejs/plugin-rsc is ESM-only).\n *\n * Previous versions used async loading and deferred config merging,\n * causing file-based config for reactCompiler, actionEncryption, and\n * output mode to be silently ignored. See TIM-451.\n */\n/**\n * Wrap plugin-react's `vite:react-compiler` configResolved so it always\n * sees `isProduction: true` during builds. The compiler plugin uses\n * `!config.isProduction` to decide whether to emit jsxDEV calls, but\n * Vite derives isProduction from process.env.NODE_ENV — which may be\n * \"development\" in the shell. Rather than mutating the env, we pass a\n * prototype-based view with the single property overridden.\n */\nfunction patchReactCompilerForProdJsx(plugins: PluginOption[]): PluginOption[] {\n for (const p of plugins) {\n if (p && typeof p === 'object' && 'name' in p && p.name === 'vite:react-compiler') {\n const orig = (p as Plugin).configResolved;\n if (typeof orig === 'function') {\n (p as Plugin).configResolved = function (config) {\n const view =\n config.command === 'build' && !config.isProduction\n ? Object.create(config, { isProduction: { value: true } })\n : config;\n return orig.call(this, view);\n };\n }\n }\n }\n return plugins;\n}\n\nexport function timber(config?: TimberUserConfig): PluginOption[] {\n const ctx = createPluginContext(config);\n\n // Resolve dependencies from the consumer's project (process.cwd()),\n // not from timber's own node_modules. This is critical for pnpm link:\n // when linked, timber's node_modules has a separate vite instance, and\n // the RSC plugin must use the same vite instance as the dev server.\n const consumerRequire = createRequire(join(process.cwd(), 'package.json'));\n\n // ── Step 1: Load @vitejs/plugin-rsc ─────────────────────────────────\n // Synchronous require() works for ESM modules on Node 22.12+.\n ctx.timer.start('rsc-plugin-import');\n const rscMod = consumerRequire('@vitejs/plugin-rsc');\n const vitePluginRsc = rscMod.default ?? rscMod;\n ctx.timer.end('rsc-plugin-import');\n\n // ── Step 2: Compute config-dependent options ────────────────────────\n // encryptionKeyExpr is env-based and doesn't depend on file config.\n const encryptionKeyExpr = resolveEncryptionKeyExpression();\n\n // ── Step 3: Pre-load file config for plugin resolution ──────────────\n // Load timber.config.ts eagerly from process.cwd() so we can resolve\n // plugins (like React Compiler) and add them to the top-level array.\n // Vite's config() hook return type is Omit<UserConfig, 'plugins'> —\n // plugins returned from config() are silently ignored. See TIM-632.\n //\n // The config() hook still loads from the correct Vite root (which may\n // differ from cwd in monorepo setups — see TIM-498), but only for\n // non-plugin config merging.\n const earlyFileConfig = loadTimberConfigFile(process.cwd());\n\n // ── Step 4: Build rootSync plugin ───────────────────────────────────\n\n // rootSync loads timber.config.ts from Vite's resolved root and merges\n // it into ctx.config. Plugin resolution is handled eagerly above — the\n // config() hook must NOT return a `plugins` field (Vite ignores it).\n const rootSync: Plugin = {\n name: 'timber-root-sync',\n\n // The plugin context, published for out-of-band callers that need the\n // *resolved* configuration rather than a second reading of the files it\n // came from. `timber check` is the one today: it runs Vite's\n // `resolveConfig()` and reads root, appDir, and pageExtensions from here,\n // so it scans exactly the tree `timber build` builds — including config\n // passed inline as `timber({ ... })`, which lives only in this closure and\n // is invisible to anything that re-reads `timber.config.ts`. See\n // `cli-check.ts` and design/11-platform.md §`timber check`.\n //\n // Valid from `configResolved` onward; `appDir` and `root` are unset before\n // that, which is why the reader runs a full `resolveConfig()` rather than\n // just loading the config file.\n api: { getContext: () => ctx } satisfies TimberPluginApi,\n\n async config(userConfig, { command, isPreview }) {\n // ── Load timber.config.ts from the correct root ───────────────\n // Vite's `config` hook fires before `configResolved`. The user's\n // `root` option (if set) tells us where the project lives.\n // `resolve()` mirrors Vite's own root resolution logic.\n const viteRoot = resolve(userConfig.root ?? process.cwd());\n ctx.timer.start('config-load');\n const fileConfig = loadTimberConfigFile(viteRoot);\n if (fileConfig) {\n ctx.config = mergeFileConfig(ctx.config, fileConfig);\n ctx.clientJavascript = resolveClientJavascript(ctx.config);\n }\n // Apply defaults AFTER merge so file-based config isn't overridden\n // by defaults that were baked into the inline config object.\n ctx.config.output ??= 'server';\n ctx.timer.end('config-load');\n\n // ── Resolve build output directory ─────────────────────────\n // Priority: timber.config.ts `buildDir` > Vite `build.outDir` > .timber/dist\n // Set Vite's build.outDir so the RSC plugin and all environment\n // builds write to the correct location. ctx.buildDir is read back\n // from Vite in configResolved, so there is one answer to where the\n // build went.\n const resolvedRoot = resolve(userConfig.root ?? process.cwd());\n const buildDir = resolveBuildDir(resolvedRoot, ctx.config.buildDir, userConfig.build?.outDir);\n\n // Warn if the Vite root differs from cwd and the re-loaded config\n // has reactCompiler but the early cwd-based load missed it. In this\n // edge case the user must move reactCompiler to inline config.\n if (viteRoot !== process.cwd()) {\n const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;\n const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;\n if (hasCompilerInReloaded && !hadCompilerInEarly) {\n console.warn(\n '[timber] reactCompiler is set in timber.config.ts but could not be ' +\n 'registered because the config file is in a non-cwd root directory. ' +\n 'Move reactCompiler to the inline timber() config in vite.config.ts, or ' +\n 'run vite from the project root directory.'\n );\n }\n }\n\n // Force production JSX for builds.\n //\n // Vite derives `config.isProduction` from `process.env.NODE_ENV`.\n // If the shell has NODE_ENV=development, isProduction stays false\n // and Vite's built-in OXC transform emits jsxDEV calls (the\n // production jsx-runtime doesn't export jsxDEV). The oxc.jsx\n // override below fixes Vite's native path; plugin-react's compiler\n // plugin is handled by patchReactCompilerForProdJsx above.\n // ── Resolve dev/preview port (TIM-842) ───────────────────────\n // Default port is 3000. Vite handles conflicts and honors server.strictPort.\n //\n // For dev (`command === 'serve' && !isPreview`) we start the\n // holding server on the requested port when available.\n //\n // For `vite preview` (`command === 'serve' && isPreview`) we\n // resolve the config/env port but delegate the actual bind +\n // auto-bump to Vite's own preview server. Starting the holding\n // server in preview mode would self-conflict because the dev\n // plugin's `configureServer` handoff does not run for preview;\n // the holding server would keep the port occupied while Vite's\n // preview tried to bind the same port.\n //\n // See design/21-dev-server.md §\"Default Port and Auto-Bump\".\n let resolvedDevPort: number | null = null;\n let resolvedDevPortExplicit = false;\n // Middleware-mode embeddings (the analyze crawl, custom servers)\n // never bind a port, and the dev-server plugin's listen() handoff\n // that closes the holding server never runs — starting it would\n // occupy the default port for the embedding's lifetime.\n const isMiddlewareMode = Boolean(userConfig.server?.middlewareMode);\n // Resolve the host Vite will bind so the holding server probes the\n // same address. Vite defaults to 'localhost' when server.host is\n // unset; binding wildcard (no host) would mask conflicts on\n // localhost due to SO_REUSEADDR address-family differences. TIM-1419.\n const resolvedHost =\n typeof userConfig.server?.host === 'string'\n ? userConfig.server.host\n : userConfig.server?.host === true\n ? undefined\n : 'localhost';\n if (command === 'serve' && !isPreview && !isMiddlewareMode) {\n const start = resolveStartPort({\n configPort: userConfig.server?.port,\n envPort: process.env.PORT,\n });\n // Vite owns port selection and remembers its bound port on restart.\n // Never forward a probed/bumped port: replacement config runs while\n // the old listener still owns the port. The holding page is optional.\n resolvedDevPort = start.port;\n resolvedDevPortExplicit = userConfig.server?.strictPort ?? false;\n if (start.port !== 0) {\n ctx.holdingServer = createHoldingServer();\n await ctx.holdingServer.listen(start.port, resolvedHost).catch(() => {\n ctx.holdingServer = null;\n });\n }\n } else if (command === 'serve' && isPreview) {\n // Preview mode: resolve the starting port from config/env/\n // default but do NOT probe. Vite's preview server handles the\n // bind itself, with `preview.strictPort` controlling whether\n // an in-use port auto-bumps (implicit) or errors (explicit).\n const previewConfigPort =\n typeof userConfig.preview?.port === 'number'\n ? userConfig.preview.port\n : typeof userConfig.server?.port === 'number'\n ? userConfig.server.port\n : undefined;\n const start = resolveStartPort({\n configPort: previewConfigPort,\n envPort: process.env.PORT,\n });\n resolvedDevPort = start.port;\n resolvedDevPortExplicit = start.explicit;\n }\n\n // Derive relative buildOutDir from the absolute buildDir (set above)\n // so Vite's config receives a root-relative path.\n const buildOutDir = relative(resolvedRoot, buildDir);\n\n // Set per-environment build.outDir so Vite's RSC plugin writes\n // each environment to the correct subdirectory under our buildDir.\n // Without this, the RSC plugin defaults to dist/<envName> instead\n // of <buildOutDir>/<envName>.\n const envOutDirs: Record<string, { build: { outDir: string } }> = {};\n for (const envName of ['rsc', 'ssr', 'client']) {\n envOutDirs[envName] = { build: { outDir: join(buildOutDir, envName) } };\n }\n\n // Exclude @timber-js/app packages from the dep optimizer.\n // The shims plugin intercepts @timber-js/app/* imports per-environment\n // (e.g. replacing @timber-js/app/server with a stub in the client env).\n // The dep optimizer runs before per-environment resolution, so it would\n // pre-bundle @timber-js/app/cookies with the real server code inlined,\n // pulling AsyncLocalStorage into the browser bundle.\n const timberOptimizeDepsExclude = [\n '@timber-js/app',\n '@timber-js/app/server',\n '@timber-js/app/client',\n '@timber-js/app/cookies',\n '@timber-js/app/cache',\n '@timber-js/app/search-params',\n '@timber-js/app/params',\n '@timber-js/app/codec',\n ];\n\n if (command === 'build') {\n return {\n build: { outDir: buildOutDir },\n environments: envOutDirs,\n optimizeDeps: { exclude: timberOptimizeDepsExclude },\n oxc: {\n jsx: {\n development: false,\n },\n },\n };\n }\n\n // Dev/preview mode: set outDir so dev-time references are\n // consistent, and surface the resolved port to Vite.\n //\n // Dev auto-bumps unless the user sets server.strictPort.\n // Always forward the requested port so Vite can recognize unchanged\n // config and reuse its actual bound port across restarts (TIM-1456).\n //\n // For `vite preview`, we set `preview.strictPort` based on\n // whether the user explicitly set the port. Implicit (default)\n // preview uses strictPort: false so Vite's preview server can\n // auto-bump from 3000. Explicit preview uses strictPort: true\n // so conflicts fail loudly, matching the dev behavior and the\n // TIM-842 spec.\n const serverConfig: {\n port?: number;\n strictPort?: boolean;\n forwardConsole?: boolean | { unhandledErrors?: boolean; logLevels?: string[] };\n } = {};\n const previewConfig: { port?: number; strictPort?: boolean } = {};\n if (resolvedDevPort != null) {\n if (!isPreview) {\n serverConfig.port = resolvedDevPort;\n serverConfig.strictPort = resolvedDevPortExplicit;\n }\n previewConfig.port = resolvedDevPort;\n previewConfig.strictPort = resolvedDevPortExplicit;\n }\n\n // Enable Vite 8's built-in browser→terminal console forwarding.\n // Vite defaults this OFF for non-agent dev; timber enables it based\n // on the devBrowserLogs config (default: 'warn'). See TIM-1152.\n serverConfig.forwardConsole = resolveForwardConsole(ctx.config.devBrowserLogs);\n\n // Provide a customLogger whose output routes through the pre-patched\n // console methods so Vite's forwardConsole output never re-enters our\n // server→browser patch. If the user supplied their own customLogger,\n // wrap it so its console calls also bypass patching.\n const customLogger = userConfig.customLogger\n ? wrapLoggerWithOriginalConsole(userConfig.customLogger)\n : createLogger(userConfig.logLevel ?? 'info', {\n allowClearScreen: userConfig.clearScreen ?? true,\n console: originalConsole as Console,\n });\n\n // Seed the client optimizer's startup crawl with every 'use client'\n // file so client-only packages are pre-bundled before the first\n // request, not discovered mid-load (which full-reloads the page).\n // Vite concatenates these with any entries the user sets.\n // See design/21-dev-server.md §\"Client Dependency Pre-Bundling\".\n let environments: Record<string, object> = envOutDirs;\n if (!isPreview) {\n ctx.timer.start('client-deps-scan');\n // Loaded lazily: directive detection pulls in @vitejs/plugin-rsc's\n // transforms, which builds and preview never need.\n const { clientOptimizeDepsEntries } = await import('./plugins/client-dep-entries.ts');\n const entries = await clientOptimizeDepsEntries(resolvedRoot, BROWSER_ENTRY_FILE, buildDir);\n ctx.timer.end('client-deps-scan');\n environments = {\n ...envOutDirs,\n client: { ...envOutDirs.client, optimizeDeps: { entries } },\n };\n }\n\n return {\n build: { outDir: buildOutDir },\n environments,\n optimizeDeps: { exclude: timberOptimizeDepsExclude },\n customLogger,\n server: serverConfig,\n preview: previewConfig,\n };\n },\n configResolved(resolved) {\n ctx.root = resolved.root;\n ctx.appDir = resolveAppDir(resolved.root, ctx.config.appDir);\n ctx.dev = resolved.command === 'serve';\n // Vite's resolved base — the deployment path prefix. Captured once\n // here so every sub-plugin that emits a URL (assets, fonts, RSC\n // payloads) reads the same value. See TIM-1261.\n ctx.base = resolved.base;\n\n // timber.config.* files are NOT registered as configFileDependencies.\n // Vite's in-process restart cannot bust Node's require cache for ESM\n // modules loaded via require(), so the restarted server would serve\n // stale config. Instead, timber-dev-server watches these files and\n // calls process.exit(RESTART_EXIT_CODE) so the CLI supervisor\n // respawns a fresh process. See TIM-1444.\n // The watcher.add() call in dev-server.ts ensures the files are\n // watched even if created after server start.\n\n // The build directory is what Vite resolved build.outDir to — the\n // config hook's value after every other plugin and the user config had\n // their say. Vite keeps outDir as-is (may be relative), so resolve\n // against root.\n ctx.buildDir = resolve(resolved.root, resolved.build.outDir);\n // In production builds, swap to a no-op timer to avoid overhead\n if (!ctx.dev) {\n ctx.timer = createNoopTimer();\n } else {\n // Start the overall dev server setup timer — ends in timber-dev-server\n ctx.timer.start('dev-server-setup');\n }\n\n // Validate config and check peer dependencies at startup. Most errors\n // are logged and don't block startup; fatal ones (a security setting\n // that would not mean what it says) stop it. See reportConfigErrors.\n reportConfigErrors(validateConfig(ctx.config));\n\n const peerResults = checkPeerDependencies(ctx.root);\n const peerWarning = formatMissingPeers(peerResults);\n if (peerWarning) {\n process.stderr.write(`${peerWarning}\\n\\n`);\n }\n },\n };\n\n // ── Step 5: Resolve React Compiler config ───────────────────────────\n // Inline config takes precedence. File config (from the early cwd-based\n // load) is used when inline config doesn't set reactCompiler.\n // Default: true — oxc-transform-react is a direct dependency.\n const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler ?? true;\n\n // ── Step 6: Assemble plugin array ─────────────────────────────────────\n // @vitejs/plugin-rsc handles:\n // - RSC/SSR/client environment setup\n // - \"use client\" directive → client reference proxy transformation\n // - \"use server\" directive → server reference transformation\n // - Client reference tracking and module map generation\n //\n // serverHandler: false — timber has its own dev server (timber-dev-server)\n // entries — tells the RSC plugin about timber's virtual entry modules so\n // it correctly wires up the browser entry (needed for React Fast Refresh\n // preamble coordination with @vitejs/plugin-react)\n // customClientEntry: true — timber manages its own browser entry and\n // preloading; skips RSC plugin's default \"index\" client entry convention\n //\n // The RSC plugin's built-in buildApp handles the 5-step multi-environment\n // build sequence (analyze references → build RSC → build client → build SSR).\n // We do NOT set customBuildApp — the RSC plugin's orchestration is correct\n // and handles bundle ordering, asset manifest generation, and environment\n // imports manifest. See @vitejs/plugin-rsc's buildApp implementation.\n //\n // Everything after it runs in timber-post-build, in the order that plugin\n // states. The plugins that own a post-build step expose it as their `api`\n // and are handed to it here, so no step's order depends on where a plugin\n // sits in this array. See design/18-build-system.md §\"Post-Build Phase\".\n const fonts = timberFonts(ctx);\n const prebuilt = timberPrebuilt(ctx);\n const buildReport = timberBuildReport(ctx);\n return [\n rootSync,\n timberReactResolve(),\n timberReactProd(),\n // @vitejs/plugin-react provides React Fast Refresh (state-preserving HMR)\n // for client components via Babel transform. Placed before @vitejs/plugin-rsc\n // following Vinext's convention — the RSC plugin's virtual browser entry\n // coordinates with plugin-react via __vite_plugin_react_preamble_installed__.\n ...patchReactCompilerForProdJsx(\n react({\n compiler: (effectiveReactCompiler || false) as boolean | ReactCompilerOptions,\n })\n ),\n vitePluginRsc(createRscOptions(ctx, encryptionKeyExpr)),\n timberShims(ctx),\n timberRouting(ctx),\n timberEntries(ctx),\n timberBuildManifest(ctx),\n fonts,\n timberMdx(ctx),\n timberRequestDep(ctx),\n timberCacheTransform(ctx),\n timberPrerenderSugar(ctx), // export const prerender → cache.component() desugaring\n prebuilt, // cache.component() → __prebuilt() callsite rewrite\n timberStaticBuild(ctx), // Static mode: validate dynamic API usage\n timberContent(ctx),\n timberServerBundle(), // Bundle all deps in server environments for prod\n timberCloudflareWasm(ctx), // Externalize WASM for Cloudflare Workers\n timberChunks(ctx),\n buildReport, // Route table with bundle sizes, printed by timber-post-build\n timberPostBuild(ctx, { fonts: fonts.api, prebuilt: prebuilt.api, report: buildReport.api }),\n timberDevLogs(ctx), // Dev-only: forward server console.* to browser console\n timberDevServer(ctx), // Must be last — configureServer post-hook runs after all watchers\n ];\n}\n\nexport default timber;\n"],"x_google_ignoreList":[15,16],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["intToChar"],"sources":["../src/plugins/content.ts","../src/plugins/entries.ts","../src/plugins/mdx.ts","../src/routing/manifest-codegen.ts","../src/plugins/routing.ts","../src/plugins/shims.ts","../src/fonts/paths.ts","../src/fonts/google.ts","../src/fonts/css.ts","../src/fonts/fallbacks.ts","../src/fonts/ast-walk.ts","../src/fonts/ast.ts","../src/fonts/local.ts","../src/fonts/virtual-modules.ts","../src/fonts/pipeline.ts","../../../node_modules/.pnpm/@jridgewell+sourcemap-codec@1.6.0/node_modules/@jridgewell/sourcemap-codec/dist/sourcemap-codec.mjs","../../../node_modules/.pnpm/magic-string@1.4.1/node_modules/magic-string/dist/index.mjs","../src/fonts/transform.ts","../src/fonts/dev-middleware.ts","../src/fonts/bundle.ts","../src/plugins/fonts.ts","../src/server/flight-scripts.ts","../src/plugins/static-build.ts","../src/plugins/build-manifest.ts","../src/dev-tools/logs.ts","../src/dev-tools/browser-logs.ts","../src/plugins/react-prod.ts","../src/plugins/react-resolve.ts","../src/plugins/chunks.ts","../src/plugins/client-chunks.ts","../src/plugins/server-bundle.ts","../src/plugins/callsite-ast.ts","../src/plugins/cache.ts","../src/plugins/request-dep/analysis.ts","../src/plugins/request-dep/origin.ts","../src/plugins/request-dep/index.ts","../src/plugins/callsite-jsx.ts","../src/plugins/prebuilt-options-analysis.ts","../src/plugins/prebuilt-capture.ts","../src/plugins/prebuilt.ts","../src/plugins/prerender-sugar.ts","../src/plugins/cloudflare-wasm.ts","../src/plugins/rsc-assets-manifest.ts","../src/plugins/post-build.ts","../src/plugins/build-report.ts","../src/server/action-encryption.ts","../src/dev-tools/holding-server.ts","../src/server/port-resolution.ts","../src/index.ts"],"sourcesContent":["/**\n * timber-content — Vite sub-plugin for content collections.\n *\n * Wraps @content-collections/vite to provide content collection support.\n * Activates only when a content-collections.ts config file exists at the\n * project root.\n *\n * Design doc: 20-content-collections.md §\"Content Collections\"\n */\n\nimport type { Plugin, PluginOption } from 'vite';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PluginContext } from '../plugin-context.ts';\n\nconst CONFIG_FILE_NAMES = [\n 'content-collections.ts',\n 'content-collections.js',\n 'content-collections.mts',\n 'content-collections.mjs',\n];\n\n/**\n * Find the content-collections config file at the project root.\n * Returns the filename (not full path) if found, otherwise undefined.\n */\nfunction findConfigFile(root: string): string | undefined {\n for (const name of CONFIG_FILE_NAMES) {\n if (existsSync(join(root, name))) return name;\n }\n return undefined;\n}\n\n/** The name @content-collections/vite gives its plugin. */\nconst CONTENT_COLLECTIONS_PLUGIN_NAME = 'content-collections';\n\n/**\n * Whether the user's own config already registers @content-collections/vite.\n * Walks nested arrays and awaits promised plugins, the same PluginOption\n * shapes Vite flattens (and has already resolved by the time config hooks\n * run, so awaiting here costs nothing).\n */\nasync function registersContentCollections(plugins: PluginOption[] | undefined): Promise<boolean> {\n for (const option of plugins ?? []) {\n const plugin = await option;\n if (Array.isArray(plugin)) {\n if (await registersContentCollections(plugin)) return true;\n } else if (plugin && 'name' in plugin && plugin.name === CONTENT_COLLECTIONS_PLUGIN_NAME) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Create the timber-content Vite plugin.\n *\n * Delegates all content scanning, validation, code generation, and file watching\n * to @content-collections/vite. This plugin only handles detection and activation.\n */\nexport function timberContent(ctx: PluginContext): Plugin {\n let innerPlugin: Plugin | null = null;\n\n async function activate(root: string): Promise<void> {\n if (innerPlugin !== null) return;\n\n const configFile = findConfigFile(root);\n if (!configFile) return;\n\n let createPlugin: ((options?: { configPath?: string }) => Plugin) | undefined;\n try {\n const mod = await import('@content-collections/vite');\n createPlugin = (mod.default ?? mod) as typeof createPlugin;\n } catch {\n throw new Error(\n [\n '[timber] Content collections are enabled but @content-collections/vite is not installed.',\n '',\n 'Install content-collections:',\n ' pnpm add -D @content-collections/core @content-collections/vite',\n '',\n 'For MDX content, also install:',\n ' pnpm add -D @content-collections/mdx',\n '',\n 'Content collections are activated because a content-collections.ts file exists.',\n ].join('\\n')\n );\n }\n\n if (createPlugin) {\n innerPlugin = createPlugin({ configPath: configFile });\n }\n }\n\n return {\n name: 'timber-content',\n\n async config(config, env) {\n // Two registrations start two builders and two watchers that race on\n // the same cache (\"Failed to parse the cache mapping\"). The user's\n // own registration, with its options, wins.\n if (await registersContentCollections(config.plugins)) return;\n const root = config.root ?? ctx.root;\n ctx.timer.start('content-activate');\n await activate(root);\n ctx.timer.end('content-activate');\n if (!innerPlugin) return;\n if (typeof innerPlugin.config === 'function') {\n return innerPlugin.config.call(this, config, env);\n }\n },\n\n async configResolved(config) {\n if (!innerPlugin) return;\n if (typeof innerPlugin.configResolved === 'function') {\n await (innerPlugin.configResolved as (...args: unknown[]) => unknown).call(this, config);\n }\n },\n\n async buildStart(options) {\n if (!innerPlugin) return;\n if (typeof innerPlugin.buildStart === 'function') {\n await (innerPlugin.buildStart as (...args: unknown[]) => unknown).call(this, options);\n }\n },\n\n async resolveId(source: string, importer: string | undefined, options: unknown) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.resolveId === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.resolveId as any).call(this, source, importer, options);\n }\n return null;\n },\n\n async load(id: string) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.load === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.load as any).call(this, id);\n }\n return null;\n },\n\n async transform(code: string, id: string) {\n if (!innerPlugin) return null;\n if (typeof innerPlugin.transform === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.transform as any).call(this, code, id);\n }\n return null;\n },\n\n async configureServer(server) {\n // The analyze crawl child must not start content-collections'\n // file watcher — it outlives server.close() and holds the\n // process open (the child relies on process.exit to clean up).\n if (process.env.TIMBER_ANALYZE === '1') return;\n if (!innerPlugin) return;\n if (typeof innerPlugin.configureServer === 'function') {\n await (innerPlugin.configureServer as (...args: unknown[]) => unknown).call(this, server);\n }\n },\n };\n}\n","/**\n * timber-entries — Vite sub-plugin for entry virtual module resolution.\n *\n * Resolves virtual:timber-rsc-entry, virtual:timber-ssr-entry,\n * virtual:timber-browser-entry to real TypeScript files, and generates\n * virtual:timber-config as serialized runtime config.\n *\n * Entry modules are real .ts files — NOT codegen strings. The only\n * generated code is virtual:timber-config (serialized runtime config).\n *\n * Design docs: 18-build-system.md §\"Entry Generation\", §\"Virtual Modules\"\n */\n\nimport type { Plugin } from 'vite';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { existsSync } from 'node:fs';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { resolveRenderTimeoutMs } from '../server/render-timeout.ts';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n// In workspace dev, __dirname is src/plugins/ and src/ is the parent.\n// In published package, entries.ts is bundled into dist/index.js so\n// __dirname is dist/ and src/ is a sibling directory.\nconst SRC_DIR = existsSync(resolve(__dirname, '..', 'server', 'rsc-entry', 'index.ts'))\n ? resolve(__dirname, '..')\n : resolve(__dirname, '..', 'src');\n\n// ─── Virtual Module IDs ──────────────────────────────────────────────────\n\nconst VIRTUAL_IDS = {\n rscEntry: 'virtual:timber-rsc-entry',\n ssrEntry: 'virtual:timber-ssr-entry',\n browserEntry: 'virtual:timber-browser-entry',\n config: 'virtual:timber-config',\n instrumentation: 'virtual:timber-instrumentation',\n cacheHandler: 'virtual:timber-cache-handler',\n} as const;\n\n/**\n * Map from virtual module IDs to their resolved file paths.\n *\n * These point to .ts source files that Vite transpiles at runtime.\n * They import virtual modules (virtual:timber-config, etc.) so they\n * cannot be pre-compiled — they must be processed by Vite's pipeline\n * with timber's plugin active. The .ts files are included in the\n * published package via the `files` field.\n */\nconst ENTRY_FILE_MAP: Record<string, string> = {\n [VIRTUAL_IDS.rscEntry]: resolve(SRC_DIR, 'server', 'rsc-entry', 'index.ts'),\n [VIRTUAL_IDS.ssrEntry]: resolve(SRC_DIR, 'server', 'ssr-entry.ts'),\n [VIRTUAL_IDS.browserEntry]: resolve(SRC_DIR, 'client', 'browser-entry', 'index.ts'),\n};\n\n/**\n * The real file behind virtual:timber-browser-entry. The client dep\n * optimizer scans it explicitly once timber sets optimizeDeps.entries\n * (see plugins/client-dep-entries.ts).\n */\nexport const BROWSER_ENTRY_FILE = ENTRY_FILE_MAP[VIRTUAL_IDS.browserEntry];\n\n/** The \\0-prefixed resolved ID for virtual:timber-config */\nconst RESOLVED_CONFIG_ID = `\\0${VIRTUAL_IDS.config}`;\n\n/** The \\0-prefixed resolved ID for virtual:timber-instrumentation */\nconst RESOLVED_INSTRUMENTATION_ID = `\\0${VIRTUAL_IDS.instrumentation}`;\n\n/** The \\0-prefixed resolved ID for virtual:timber-cache-handler */\nconst RESOLVED_CACHE_HANDLER_ID = `\\0${VIRTUAL_IDS.cacheHandler}`;\n\n/**\n * Strip the \\0 prefix from a module ID.\n *\n * The RSC plugin generates browser entry imports using already-resolved\n * \\0-prefixed IDs. Vite's import-analysis cannot resolve these.\n * See 18-build-system.md §\"Resolution Quirks\".\n */\nfunction stripNullPrefix(id: string): string {\n return id.startsWith('\\0') ? id.slice(1) : id;\n}\n\n/**\n * Strip a root directory prefix from a module ID.\n *\n * Vite prefixes virtual module IDs with the project root when resolving\n * SSR build entries. We need to handle both `virtual:timber-rsc-entry`\n * and `<root>/virtual:timber-rsc-entry`.\n * See 18-build-system.md §\"Resolution Quirks\".\n */\nfunction stripRootPrefix(id: string, root: string): string {\n if (id.startsWith(root)) {\n // Remove root + path separator\n const stripped = id.slice(root.length);\n // Handle both /virtual:... and \\virtual:... (Windows)\n if (stripped.startsWith('/') || stripped.startsWith('\\\\')) {\n return stripped.slice(1);\n }\n return stripped;\n }\n return id;\n}\n\n/**\n * Generate the virtual:timber-config module source.\n *\n * Serializes output mode and feature flags for runtime consumption.\n */\n/**\n * Extract the JSON-serializable subset of `forms` config.\n *\n * Drops function-valued `stripSensitiveFields` with a build-time warning —\n * functions cannot cross the JSON boundary to the runtime, so users must\n * configure function predicates per-action via `createActionClient` instead.\n */\nfunction serializeFormsConfig(\n forms: { stripSensitiveFields?: unknown } | undefined\n): { stripSensitiveFields?: boolean | readonly string[] } | undefined {\n if (!forms) return undefined;\n const opt = forms.stripSensitiveFields;\n if (opt === undefined) return {};\n if (typeof opt === 'boolean') return { stripSensitiveFields: opt };\n if (Array.isArray(opt)) {\n // Coerce to a string array and drop any non-string entries.\n const names = opt.filter((v): v is string => typeof v === 'string');\n return { stripSensitiveFields: names };\n }\n if (typeof opt === 'function') {\n console.warn(\n '[timber] forms.stripSensitiveFields was set to a function in timber.config.ts — ' +\n 'this is not supported at the global level (functions cannot be serialized ' +\n 'into the runtime config). Use a per-action override via ' +\n '`createActionClient({ stripSensitiveFields: (name) => ... })` instead. ' +\n 'The built-in deny-list will be used globally.'\n );\n return {};\n }\n return {};\n}\n\nfunction generateConfigModule(ctx: PluginContext): string {\n const runtimeConfig = {\n output: ctx.config.output ?? 'server',\n csrf: ctx.config.csrf ?? true,\n allowedOrigins: ctx.config.allowedOrigins,\n clientJavascript: ctx.clientJavascript,\n // Vite's resolved `base` — the deployment path prefix. The client needs\n // it to address pre-generated RSC payloads in static mode, which live\n // below the base like every other emitted file (TIM-1261).\n base: ctx.base,\n dev: ctx.dev ?? false,\n slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,\n slowRequestMs: ctx.config.slowRequestMs ?? 3000,\n topLoader: ctx.config.topLoader,\n debug: ctx.config.debug ?? false,\n serverTiming: ctx.config.serverTiming,\n renderTimeoutMs: resolveRenderTimeoutMs(ctx.config.renderTimeoutMs),\n // Auto-generated sitemap config — opt-in via timber.config.ts.\n // See design/16-metadata.md §\"Auto-generated Sitemap\"\n sitemap: ctx.config.sitemap,\n // Forms config — only the serializable subset. `stripSensitiveFields`\n // accepts boolean | string[] at the global level. Functions must be\n // configured per-action via `createActionClient({ stripSensitiveFields })`\n // because JSON.stringify would silently drop them here. See TIM-816.\n forms: serializeFormsConfig(ctx.config.forms),\n // Per-build deployment ID for version skew detection (TIM-446).\n // Null in dev mode — HMR handles code updates without full reloads.\n deploymentId: ctx.deploymentId ?? null,\n clientSegmentCache: ctx.config.clientSegmentCache ?? false,\n cache: {\n strictKeyDiscipline: ctx.config.cache?.strictKeyDiscipline ?? false,\n },\n // Browser log forwarding threshold — used by buildClientScripts to\n // decide whether /@vite/client is needed when clientJavascript is\n // disabled. See TIM-1152.\n devBrowserLogs: ctx.config.devBrowserLogs,\n // Note: project root is NOT included here — it was leaking server\n // filesystem paths to client bundles (TIM-787). Dev error pages get\n // the root through the dev server, not the runtime config.\n };\n\n return [\n '// Auto-generated runtime config — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `const config = ${JSON.stringify(runtimeConfig, null, 2)};`,\n '',\n 'export default config;',\n ].join('\\n');\n}\n\n/**\n * Detect a user convention file at both root and src/.\n *\n * Root takes precedence over src/, extension priority: .ts > .js > .mjs.\n * Used for instrumentation.ts, timber.cache.ts, and similar file conventions.\n */\nexport function detectConventionFile(root: string, basename: string): string | null {\n const extensions = ['.ts', '.js', '.mjs'];\n const dirs = [root, resolve(root, 'src')];\n for (const dir of dirs) {\n for (const ext of extensions) {\n const candidate = resolve(dir, `${basename}${ext}`);\n if (existsSync(candidate)) return candidate;\n }\n }\n return null;\n}\n\nexport function detectInstrumentationFile(root: string): string | null {\n return detectConventionFile(root, 'instrumentation');\n}\n\n/**\n * Detect the user's timber.cache file.\n *\n * This file holds runtime cache instances (cacheHandler, cdnPurge)\n * that cannot be JSON-serialized. Separating them from timber.config.ts\n * prevents the RSC build from pulling build-time deps (adapters, MDX,\n * rollup) into the runtime bundle. See TIM-1211.\n */\nexport function detectCacheFile(root: string): string | null {\n return detectConventionFile(root, 'timber.cache');\n}\n\n/**\n * Generate the virtual:timber-instrumentation module source.\n *\n * When the user's instrumentation.ts exists, generates a module that\n * dynamically imports it. When it doesn't exist, generates a module\n * that returns null. The RSC entry calls this loader at startup time.\n *\n * See design/17-logging.md §\"instrumentation.ts — The Entry Point\"\n */\nexport function generateInstrumentationModule(instrumentationPath: string | null): string {\n if (instrumentationPath) {\n return [\n '// Auto-generated instrumentation loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `export default async function loadUserInstrumentation() {`,\n ` return import(${JSON.stringify(instrumentationPath)});`,\n `}`,\n ].join('\\n');\n }\n\n return [\n '// Auto-generated instrumentation loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '// No instrumentation.ts found at project root.',\n '',\n `export default async function loadUserInstrumentation() {`,\n ` return null;`,\n `}`,\n ].join('\\n');\n}\n\n/**\n * Generate the virtual:timber-cache-handler module source.\n *\n * When the user's timber.cache.ts exists, generates a module that\n * dynamically imports it and extracts cacheHandler and cdnPurge.\n * These are class instances (e.g. RedisCacheHandler) that cannot be\n * JSON-serialized into virtual:timber-config, so they must be loaded\n * at runtime via dynamic import.\n *\n * timber.cache.ts exports: default cacheHandler, named cdnPurge.\n *\n * See TIM-1211, TIM-599.\n */\nexport function generateCacheHandlerModule(cachePath: string | null): string {\n if (cachePath) {\n return [\n '// Auto-generated cache handler loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '',\n `export default async function loadCacheHandler() {`,\n ` const mod = await import(${JSON.stringify(cachePath)});`,\n ` return mod.default ?? null;`,\n `}`,\n '',\n `export async function loadCdnPurgeHandler() {`,\n ` const mod = await import(${JSON.stringify(cachePath)});`,\n ` return mod.cdnPurge ?? null;`,\n `}`,\n ].join('\\n');\n }\n\n return [\n '// Auto-generated cache handler loader — do not edit.',\n '// Generated by timber-entries plugin.',\n '// No timber.cache.ts found.',\n '',\n `export default async function loadCacheHandler() {`,\n ` return null;`,\n `}`,\n '',\n `export async function loadCdnPurgeHandler() {`,\n ` return null;`,\n `}`,\n ].join('\\n');\n}\n\n/**\n * Create the timber-entries Vite plugin.\n *\n * Hooks: resolveId, load\n */\nexport function timberEntries(ctx: PluginContext): Plugin {\n return {\n name: 'timber-entries',\n\n /**\n * Resolve virtual entry and config module IDs.\n *\n * Handles:\n * - virtual:timber-rsc-entry → real file path\n * - virtual:timber-ssr-entry → real file path\n * - virtual:timber-browser-entry → real file path\n * - virtual:timber-config → \\0-prefixed virtual ID\n * - \\0 prefix stripping (RSC plugin re-imports)\n * - Root prefix stripping (SSR build entries)\n */\n resolveId(id: string) {\n // Step 1: Strip \\0 prefix if present\n let cleanId = stripNullPrefix(id);\n\n // Step 2: Strip root prefix if present\n cleanId = stripRootPrefix(cleanId, ctx.root);\n\n // Check entry file map (real files)\n if (cleanId in ENTRY_FILE_MAP) {\n return ENTRY_FILE_MAP[cleanId];\n }\n\n // Check config virtual module\n if (cleanId === VIRTUAL_IDS.config) {\n return RESOLVED_CONFIG_ID;\n }\n\n // Check instrumentation virtual module\n if (cleanId === VIRTUAL_IDS.instrumentation) {\n return RESOLVED_INSTRUMENTATION_ID;\n }\n\n // Check cache handler virtual module\n if (cleanId === VIRTUAL_IDS.cacheHandler) {\n return RESOLVED_CACHE_HANDLER_ID;\n }\n\n return null;\n },\n\n /**\n * Load virtual modules: virtual:timber-config and virtual:timber-instrumentation.\n *\n * Entry files (rsc/ssr/browser) are real TypeScript files that Vite\n * processes normally. Only config and instrumentation need generated code.\n */\n load(id: string) {\n if (id === RESOLVED_CONFIG_ID) {\n return generateConfigModule(ctx);\n }\n if (id === RESOLVED_INSTRUMENTATION_ID) {\n const instrumentationPath = detectInstrumentationFile(ctx.root);\n return generateInstrumentationModule(instrumentationPath);\n }\n if (id === RESOLVED_CACHE_HANDLER_ID) {\n const cachePath = detectCacheFile(ctx.root);\n return generateCacheHandlerModule(cachePath);\n }\n return null;\n },\n\n /**\n * Rename \"rsc-entry\" chunks in the client build to \"rsc-client-entry\".\n *\n * The RSC plugin creates client reference facades named after the RSC\n * entry (virtual:timber-rsc-entry), producing chunks like \"rsc-entry-XYZ.js\"\n * in the client output. This is confusing since those chunks contain client\n * components, not server code. Renaming clarifies their purpose.\n */\n // Note: chunk renaming (rsc-entry → rsc-client-entry) was previously done\n // in generateBundle by mutating the bundle object. Rolldown does not support\n // bundle mutation in generateBundle — assignments are silently ignored, which\n // causes the renamed file to never be emitted while code references are\n // updated, breaking client hydration. The rename is purely cosmetic and has\n // been removed. The chunks keep their original \"rsc-entry\" names.\n };\n}\n","/**\n * timber-mdx — Vite sub-plugin for MDX and Markdown rendering.\n *\n * Wires vite-plugin-satteri into the Vite pipeline when MDX is activated.\n * MDX is activated when pageExtensions includes 'mdx' or 'md', or\n * when a content/ directory exists at the project root.\n *\n * Satteri is a Rust-based Markdown/MDX compiler with a native Vite plugin:\n * - `.mdx` files compile to React components (ES modules with real import\n * statements, so @vitejs/plugin-rsc client-boundary detection works).\n * - `.md` files compile to modules exporting a rendered HTML string.\n * - Frontmatter (YAML/TOML) parses natively and is emitted as a\n * `frontmatter` named export — no remark plugins needed.\n * - GFM (tables, footnotes, strikethrough, task lists) is on by default.\n *\n * Extensibility is satteri's visitor-based plugin API (defineMdastPlugin /\n * defineHastPlugin), not unified — the AST lives on the Rust side, so\n * remark/rehype plugins cannot run. See design/20-content-collections.md.\n *\n * Design doc: 20-content-collections.md §\"The timber-mdx Plugin\"\n */\n\nimport type { Plugin } from 'vite';\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport type { PluginContext } from '../plugin-context.ts';\n/** MDX/markdown extensions (dotted) — the canonical list for the compiler plugin. */\nconst MDX_EXTENSIONS = new Set(['.mdx', '.md']);\n\nconst MDX_EXTENSIONS_UNDOTTED = [...MDX_EXTENSIONS].map((ext) => ext.slice(1));\n\n/**\n * Check if mdx-components.tsx (or .ts, .jsx, .js) exists at the project root\n * or in src/. Root takes precedence, matching Next.js behavior.\n * Returns the absolute path if found, otherwise undefined.\n */\nexport function findMdxComponents(root: string): string | undefined {\n const candidates = [\n 'mdx-components.tsx',\n 'mdx-components.ts',\n 'mdx-components.jsx',\n 'mdx-components.js',\n ];\n const dirs = [root, join(root, 'src')];\n for (const dir of dirs) {\n for (const name of candidates) {\n const p = join(dir, name);\n if (existsSync(p)) return p;\n }\n }\n return undefined;\n}\n\n/**\n * Determine if MDX should be activated based on config and project structure.\n */\nfunction shouldActivate(ctx: PluginContext): boolean {\n // Explicit opt-out — the escape hatch for apps that register their own\n // MDX compiler (e.g. @mdx-js/rollup for the unified pipeline) in\n // vite.config.ts. Without this, a content/ directory would force\n // activation no matter what pageExtensions says.\n if (ctx.config.mdx === false) return false;\n\n const exts = ctx.config.pageExtensions;\n if (exts && exts.some((ext) => MDX_EXTENSIONS_UNDOTTED.includes(ext))) {\n return true;\n }\n\n if (existsSync(join(ctx.root, 'content'))) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Try to dynamically import a module by name, resolving from the user's\n * project root rather than from `@timber-js/app`'s own location.\n *\n * Why this matters: pnpm only hoists declared (peer) dependencies into a\n * package's resolution scope. The MDX integration's optional companions\n * — `vite-plugin-satteri` and `satteri` — are installed as direct deps of\n * the consumer (e.g. `packages/website`), not `@timber-js/app`. A bare\n * `import('vite-plugin-satteri')` from inside this file resolves against\n * `packages/timber-app/node_modules` and silently fails with\n * `ERR_MODULE_NOT_FOUND` (TIM-840).\n *\n * Resolving relative to `projectRoot` (via `createRequire`) makes the\n * lookup walk the consumer's `node_modules` tree first, which is where\n * pnpm puts the user's deps.\n *\n * Returns the default export, the module itself, or undefined if the\n * module is not installed.\n */\nasync function tryImport(name: string, projectRoot: string): Promise<unknown | undefined> {\n try {\n // Anchor resolution at the consumer's package.json so we walk their\n // node_modules tree, not @timber-js/app's. createRequire().resolve()\n // returns an absolute file path that ESM dynamic import accepts when\n // wrapped as a file:// URL.\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(name);\n const mod = await import(pathToFileURL(resolved).href);\n return mod.default ?? mod;\n } catch {\n // Fall back to a bare import — covers the rare case where the package\n // lives next to @timber-js/app (e.g. monorepo with hoisted deps).\n try {\n const mod = await import(name);\n return mod.default ?? mod;\n } catch (e) {\n console.debug(\n `[timber] optional MDX dependency '${name}' not available:`,\n e instanceof Error ? e.message : e\n );\n return undefined;\n }\n }\n}\n\n/**\n * Create the timber-mdx Vite plugin.\n *\n * Uses the transform and resolveId hooks to delegate MDX compilation\n * to vite-plugin-satteri. The inner plugin is loaded lazily on first\n * activation.\n *\n * Hooks: buildStart (loads vite-plugin-satteri), resolveId, load, transform\n */\nexport function timberMdx(ctx: PluginContext): Plugin {\n let innerPlugin: Plugin | null = null;\n\n async function activate(): Promise<void> {\n if (innerPlugin !== null || !shouldActivate(ctx)) return;\n\n // Satteri compiles .md to an HTML string, not a component — a page.md\n // route would make the renderer invoke a string as a component and\n // TypeError at request time. Fail at startup instead. Imported .md\n // files work without listing 'md' in pageExtensions.\n if (ctx.config.pageExtensions?.includes('md')) {\n throw new Error(\n [\n \"[timber] pageExtensions includes 'md', but .md route pages are not supported:\",\n 'Markdown files compile to HTML strings, not components.',\n '',\n \"Use .mdx for pages (pageExtensions: ['tsx', 'ts', 'mdx']).\",\n '.md files can still be imported as HTML strings — no pageExtensions entry needed.',\n ].join('\\n')\n );\n }\n\n const createSatteriPlugin = (await tryImport('vite-plugin-satteri', ctx.root)) as\n | ((options?: Record<string, unknown>) => Plugin)\n | undefined;\n\n if (!createSatteriPlugin) {\n throw new Error(\n [\n '[timber] MDX is enabled but vite-plugin-satteri is not installed.',\n '',\n 'Install it:',\n ' pnpm add -D vite-plugin-satteri satteri',\n '',\n 'MDX is activated because pageExtensions includes \"mdx\"/\"md\" or a content/ directory exists.',\n ].join('\\n')\n );\n }\n\n // `|| {}` (not `??`): mdx can be `false`, though shouldActivate() has\n // already bailed in that case.\n const mdxConfig = ctx.config.mdx || {};\n\n // We pass `development` explicitly (satteri otherwise infers it from\n // Vite's command via its own configResolved hook, which we don't\n // delegate) and control providerImportSource — the mdx-components.tsx\n // convention belongs to the framework, not the user config.\n const mdxOptions: Record<string, unknown> = { development: ctx.dev };\n\n const mdxComponentsPath = findMdxComponents(ctx.root);\n if (mdxComponentsPath) {\n mdxOptions.providerImportSource = mdxComponentsPath;\n }\n\n innerPlugin = createSatteriPlugin({\n mdx: mdxOptions,\n ...(mdxConfig.mdastPlugins ? { mdastPlugins: mdxConfig.mdastPlugins } : {}),\n ...(mdxConfig.hastPlugins ? { hastPlugins: mdxConfig.hastPlugins } : {}),\n ...(mdxConfig.features ? { features: mdxConfig.features } : {}),\n });\n }\n\n return {\n name: 'timber-mdx',\n // Must run before @vitejs/plugin-rsc (rsc:use-client) which tries to parse\n // all files as JS. MDX files must be compiled to JS first.\n enforce: 'pre',\n\n async buildStart(options) {\n ctx.timer.start('mdx-activate');\n await activate();\n ctx.timer.end('mdx-activate');\n if (!innerPlugin) return;\n if (typeof innerPlugin.buildStart === 'function') {\n await (innerPlugin.buildStart as (options: unknown) => void | Promise<void>).call(\n this,\n options\n );\n }\n },\n\n async resolveId(source, importer, options) {\n if (!innerPlugin) return null;\n // MDX pages are server components — only compile in the RSC environment.\n // This prevents server-only deps (e.g. bright via mdx-components) from\n // being pulled into SSR or client bundles.\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.resolveId === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.resolveId as any).call(this, source, importer, options);\n }\n return null;\n },\n\n async load(id) {\n if (!innerPlugin) return null;\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.load === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.load as any).call(this, id);\n }\n return null;\n },\n\n async transform(code, id) {\n if (!innerPlugin) return null;\n // Ids with a Vite query (?raw, ?url, ?import) are asset requests, not\n // modules to compile. vite-plugin-satteri's id regexes match them, but\n // by the time this transform runs the code is already the asset module\n // (e.g. `export default \"<file text>\"` for ?raw) — compiling that as\n // markdown corrupts it. @mdx-js/rollup matched by extname and skipped\n // queried ids; preserve that behavior.\n if (id.includes('?')) return null;\n const envName = (this as unknown as { environment?: { name?: string } }).environment?.name;\n if (envName && envName !== 'rsc') return null;\n if (typeof innerPlugin.transform === 'function') {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (innerPlugin.transform as any).call(this, code, id);\n }\n return null;\n },\n };\n}\n","/**\n * Route manifest codegen — generates virtual module source for the route\n * manifest and the global schema loader.\n *\n * Extracted from plugins/routing.ts to keep it under the 500-line budget.\n * See design/18-build-system.md §\"Virtual Modules\".\n *\n * Task: TIM-1071 item 8\n */\n\nimport { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { collectInterceptionRewrites } from './interception.ts';\nimport type { RouteTree, SegmentNode, RouteFile } from './types.ts';\n\n// ── Single-file conventions ─────────────────────────────────────────────\n// Each entry maps to a node property that holds a single RouteFile.\n// Order matches the original serializeNode output for byte-identical diffs.\nconst SINGLE_FILE_KEYS = [\n 'page',\n 'layout',\n 'middleware',\n 'access',\n 'route',\n 'error',\n 'default',\n 'denied',\n] as const;\n\n// ── Record-shaped conventions ───────────────────────────────────────────\n// Each entry maps to a node property that holds Record<string, RouteFile>.\nconst RECORD_FILE_KEYS = ['statusFiles', 'jsonStatusFiles', 'metadataRoutes'] as const;\n\nconst SCHEMA_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'];\n\n// ── Manifest generation ─────────────────────────────────────────────────\n\n/**\n * Generate the virtual module source for the route manifest.\n *\n * The output is a default-exported object containing the serialized route tree.\n * All file references use absolute paths (required for virtual modules).\n */\nexport function generateManifestModule(tree: RouteTree, viteRoot: string): string {\n const imports: string[] = [];\n let importIndex = 0;\n\n function addImport(file: RouteFile): string {\n const varName = `_route${importIndex++}`;\n imports.push(`const ${varName} = () => import(\"${file.filePath}\");`);\n return varName;\n }\n\n function serializeRouteFile(key: string, file: RouteFile, indent: string): string {\n const v = addImport(file);\n return `${indent}${key}: { load: ${v}, filePath: ${JSON.stringify(file.filePath)} },`;\n }\n\n function serializeRouteFileRecord(\n key: string,\n record: Record<string, RouteFile>,\n indent: string\n ): string | null {\n const entries = Object.entries(record);\n if (entries.length === 0) return null;\n const inner = entries.map(([name, file]) => {\n const v = addImport(file);\n return `${indent} ${JSON.stringify(name)}: { load: ${v}, filePath: ${JSON.stringify(file.filePath)} }`;\n });\n return `${indent}${key}: {\\n${inner.join(',\\n')}\\n${indent}},`;\n }\n\n function serializeNode(node: SegmentNode, indent: string): string {\n const nextIndent = indent + ' ';\n const parts: string[] = [];\n\n parts.push(`${nextIndent}segmentName: ${JSON.stringify(node.segmentName)},`);\n parts.push(`${nextIndent}segmentType: ${JSON.stringify(node.segmentType)},`);\n parts.push(`${nextIndent}urlPath: ${JSON.stringify(node.urlPath)},`);\n\n if (node.paramName) {\n parts.push(`${nextIndent}paramName: ${JSON.stringify(node.paramName)},`);\n }\n if (node.paramPrefix) {\n parts.push(`${nextIndent}paramPrefix: ${JSON.stringify(node.paramPrefix)},`);\n }\n if (node.paramSuffix) {\n parts.push(`${nextIndent}paramSuffix: ${JSON.stringify(node.paramSuffix)},`);\n }\n\n if (node.interceptionMarker) {\n parts.push(`${nextIndent}interceptionMarker: ${JSON.stringify(node.interceptionMarker)},`);\n }\n if (node.interceptedSegmentName) {\n parts.push(\n `${nextIndent}interceptedSegmentName: ${JSON.stringify(node.interceptedSegmentName)},`\n );\n }\n\n // Single-file conventions — table-driven to avoid copy-paste drift\n for (const key of SINGLE_FILE_KEYS) {\n const file = node[key];\n if (file) {\n parts.push(serializeRouteFile(key, file, nextIndent));\n }\n }\n\n // Read from route.ts source at scan time; the CSRF gate consults it\n // before any user module loads (design/08 §\"Per-route exemption\").\n if (node.csrfExempt) {\n parts.push(`${nextIndent}csrfExempt: true,`);\n }\n\n // Record-shaped conventions — table-driven\n for (const key of RECORD_FILE_KEYS) {\n const record = node[key];\n if (record) {\n const line = serializeRouteFileRecord(key, record, nextIndent);\n if (line) parts.push(line);\n }\n }\n\n // Children\n if (node.children.length > 0) {\n const childNodes = node.children.map((c) => serializeNode(c, nextIndent));\n parts.push(`${nextIndent}children: [\\n${childNodes.join(',\\n')}\\n${nextIndent}],`);\n } else {\n parts.push(`${nextIndent}children: [],`);\n }\n\n // Parallel slots\n const slotKeys = Object.keys(node.slots);\n if (slotKeys.length > 0) {\n const slotEntries: string[] = [];\n for (const slotName of slotKeys) {\n const slotNode = node.slots[slotName]!;\n slotEntries.push(\n `${nextIndent} ${JSON.stringify(slotName)}: ${serializeNode(slotNode, nextIndent + ' ')}`\n );\n }\n parts.push(`${nextIndent}slots: {\\n${slotEntries.join(',\\n')}\\n${nextIndent}},`);\n } else {\n parts.push(`${nextIndent}slots: {},`);\n }\n\n return `${indent}{\\n${parts.join('\\n')}\\n${indent}}`;\n }\n\n const rootSerialized = serializeNode(tree.root, ' ');\n\n let proxyLine = '';\n if (tree.proxy) {\n const v = addImport(tree.proxy);\n proxyLine = ` proxy: { load: ${v}, filePath: ${JSON.stringify(tree.proxy.filePath)} },`;\n }\n\n let globalErrorLine = '';\n if (tree.globalError) {\n const v = addImport(tree.globalError);\n globalErrorLine = ` globalError: { load: ${v}, filePath: ${JSON.stringify(tree.globalError.filePath)} },`;\n }\n\n // Serialize the rewrite objects wholesale — an explicit field list here\n // silently drops any field added to InterceptionRewrite, and the guard that\n // reads it would then fall back to matching too broadly. InterceptionRewrite\n // is plain JSON data by construction (no file references, no functions).\n const rewrites = collectInterceptionRewrites(tree.root);\n const rewritesLine =\n rewrites.length > 0 ? ` interceptionRewrites: ${JSON.stringify(rewrites)},` : '';\n\n const code = [\n '// Auto-generated route manifest — do not edit.',\n '// Generated by timber-routing plugin.',\n '',\n ...imports,\n '',\n 'const manifest = {',\n ` viteRoot: ${JSON.stringify(viteRoot)},`,\n proxyLine,\n globalErrorLine,\n rewritesLine,\n ` root: ${rootSerialized},`,\n '};',\n '',\n 'export default manifest;',\n ]\n .filter((line) => line !== undefined && line !== '')\n .join('\\n');\n\n return code;\n}\n\n// ── Schema module ───────────────────────────────────────────────────────\n\n/**\n * Generate the virtual:timber-schema module.\n *\n * When app/schema.{ts,tsx,js,jsx} exists, generates a module that\n * imports the schema and resolves its segmentParams codecs into a\n * bare-name codec map for runtime coercion.\n */\nexport function generateSchemaModule(appDir: string): string {\n let schemaPath: string | null = null;\n for (const ext of SCHEMA_EXTENSIONS) {\n const candidate = join(appDir, `schema${ext}`);\n if (existsSync(candidate)) {\n schemaPath = candidate;\n break;\n }\n }\n\n if (!schemaPath) {\n return [\n '// Auto-generated schema loader — no app/schema.ts found.',\n 'export default null;',\n ].join('\\n');\n }\n\n return [\n '// Auto-generated schema loader — do not edit.',\n '// Generated by timber-routing plugin (TIM-931).',\n '',\n `import schema from ${JSON.stringify(schemaPath)};`,\n `import { resolveSchemaCodecs } from '@timber-js/app/params';`,\n '',\n 'const globalCodecs = schema?.segmentParams',\n ' ? resolveSchemaCodecs(schema.segmentParams)',\n ' : null;',\n '',\n 'export default globalCodecs;',\n ].join('\\n');\n}\n","/**\n * timber-routing — Vite sub-plugin for route manifest generation.\n *\n * Bridges the route scanner with Vite's module graph. Scans app/ at startup,\n * watches for file changes in dev, and serves the virtual:timber-route-manifest\n * module that entry files consume.\n *\n * Design docs: 18-build-system.md §\"Virtual Modules\", 07-routing.md\n */\n\nimport type { Plugin, ViteDevServer } from 'vite';\nimport { join } from 'node:path';\nimport { scanRoutes } from '../routing/scanner.ts';\nimport { buildDirToRouteMap, type SegmentInfo } from '../routing/segment-codegen.ts';\nimport { writeRouteCodegen, flushCodegenWrites } from '../routing/codegen-write.ts';\nimport { validateSchemaAgainstRoutes } from '../routing/schema-validation.ts';\nimport { generateManifestModule, generateSchemaModule } from '../routing/manifest-codegen.ts';\nimport {\n lintConventions,\n checkAppDirExists,\n formatConventionWarnings,\n} from '../routing/convention-lint.ts';\nimport type { PluginContext } from '../plugin-context.ts';\n\nconst VIRTUAL_MODULE_ID = 'virtual:timber-route-manifest';\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n// TIM-931: Schema virtual module.\n//\n// When app/schema.ts exists, this module imports it and resolves the\n// bracket-keyed segmentParams codecs into a bare-name codec map for\n// runtime coercion. When no schema exists, exports null.\nconst SCHEMA_ID = 'virtual:timber-schema';\nconst RESOLVED_SCHEMA_ID = `\\0${SCHEMA_ID}`;\n\n// TIM-935: $segment virtual module prefix.\n// Resolved ID encodes segment info as JSON after the prefix.\n//\n// Each route directory gets a virtual module that exports the route\n// and segmentPath. `import { route, segmentPath } from './$segment'`\n// resolves to `\\0$segment:<json>`.\nconst SEGMENT_PREFIX = '\\0$segment:';\n\n/**\n * File convention names we track for changes that require manifest regeneration.\n */\nconst ROUTE_FILE_PATTERNS =\n /\\/(page|layout|middleware|access|route|error|global-error|default|denied|schema|proxy|\\d{3}|[45]xx|sitemap|robots|manifest|favicon|icon|opengraph-image|apple-icon)\\./;\n\n/**\n * Create the timber-routing Vite plugin.\n *\n * Hooks: resolveId, load, buildStart, configureServer\n */\n/**\n * Write the generated route map and the timber-env.d.ts reference file.\n *\n * Not awaited, to avoid blocking the hot path — use `flushCodegenWrites()` to\n * wait for the writes to land. Failures are logged, not thrown: a missing .d.ts\n * is a developer UX issue in dev/build, not a runtime failure. (`timber check`\n * calls `writeRouteCodegen` directly and does treat a failure as fatal.)\n */\nfunction writeCodegen(ctx: PluginContext): void {\n if (!ctx.routeTree) return;\n // The analyze crawl child only needs the route tree for\n // classification — codegen writes are fire-and-forget and can be\n // truncated by the child's process.exit, leaving partial .d.ts\n // files on disk.\n if (process.env.TIMBER_ANALYZE === '1') return;\n void writeRouteCodegen(ctx.routeTree, ctx.appDir, ctx.root).catch((err) => {\n console.warn('[timber] Failed to write codegen output:', err);\n });\n}\n\nexport function timberRouting(ctx: PluginContext): Plugin {\n /** Track warned files to avoid repeating warnings on rescan. */\n const warnedFiles = new Set<string>();\n\n /** Maps absolute filesystem directory → segment info for $segment resolution. */\n let dirToRoute: Map<string, SegmentInfo> = new Map();\n\n function rescan(): void {\n // Check app/ directory exists before scanning\n const appDirWarning = checkAppDirExists(ctx.appDir);\n if (appDirWarning) {\n const formatted = formatConventionWarnings([appDirWarning]);\n if (formatted) process.stderr.write(`${formatted}\\n`);\n // Still create an empty tree so the rest of the pipeline doesn't crash\n ctx.routeTree = {\n root: {\n segmentName: '',\n segmentType: 'static',\n urlPath: '/',\n children: [],\n slots: {},\n },\n };\n return;\n }\n\n ctx.timer.start('route-scan');\n const tree = scanRoutes(ctx.appDir, {\n pageExtensions: ctx.config.pageExtensions,\n });\n ctx.timer.end('route-scan');\n\n // Lint conventions (empty app, missing methods, missing root layout).\n // Runs on the scanned tree *before* it is published: error-level findings\n // are proven-fatal misconfigurations — the app cannot render at all — so\n // the tree must not reach codegen, the manifest, or a live dev server's\n // module graph. Fail loudly rather than let the developer discover it as\n // an unattributed React error on an unrelated page (TIM-1329). Never\n // deduplicated against `warnedFiles`: an error must not be downgraded to\n // silence by an earlier scan in the same process.\n const conventionWarnings = lintConventions(tree, ctx.appDir);\n const fatal = conventionWarnings.filter((w) => w.level === 'error');\n if (fatal.length > 0) {\n throw new Error(formatConventionWarnings(fatal, { color: false }));\n }\n\n ctx.routeTree = tree;\n dirToRoute = buildDirToRouteMap(ctx.routeTree, ctx.appDir);\n writeCodegen(ctx);\n\n // Validate schema keys against filesystem segments.\n // Warns on stale keys, bracket form mismatches, and missing keys.\n // See design/41-global-params.md §Auto-Scaffolding\n warnSchemaValidation(ctx);\n\n const newConventionWarnings = conventionWarnings.filter((w) => !warnedFiles.has(w.id));\n if (newConventionWarnings.length > 0) {\n for (const w of newConventionWarnings) warnedFiles.add(w.id);\n const formatted = formatConventionWarnings(newConventionWarnings);\n if (formatted) process.stderr.write(`${formatted}\\n`);\n }\n }\n\n return {\n name: 'timber-routing',\n\n /**\n * Resolve the virtual module ID.\n *\n * Handles:\n * - virtual:timber-route-manifest\n * - <root>/virtual:timber-route-manifest (Vite SSR build root prefix)\n * - \\0virtual:timber-route-manifest (RSC plugin re-imports)\n */\n resolveId(id: string, importer?: string) {\n // Strip \\0 prefix if present (RSC plugin generates these)\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (cleanId === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n // Handle root-prefixed resolution in SSR build\n if (cleanId.endsWith(`/${VIRTUAL_MODULE_ID}`)) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n // TIM-931: Schema virtual module\n if (cleanId === SCHEMA_ID || cleanId.endsWith(`/${SCHEMA_ID}`)) {\n return RESOLVED_SCHEMA_ID;\n }\n\n // TIM-935: $segment virtual module.\n // Resolves `import { route } from './$segment'` based on the\n // importing file's directory in the app/ tree.\n if (\n importer &&\n (cleanId === './$segment' || cleanId === './$segment.js' || cleanId === './$segment.ts')\n ) {\n // Strip \\0 prefix from importer if present\n const cleanImporter = importer.startsWith('\\0') ? importer.slice(1) : importer;\n const importerDir = cleanImporter.substring(0, cleanImporter.lastIndexOf('/'));\n const segmentInfo = dirToRoute.get(importerDir);\n if (segmentInfo !== undefined) {\n return `${SEGMENT_PREFIX}${JSON.stringify(segmentInfo)}`;\n }\n }\n\n return null;\n },\n\n /**\n * Generate the route manifest module.\n *\n * The manifest exports the route tree as a serialized data structure\n * with absolute import paths for all file references.\n */\n load(id: string) {\n if (id === RESOLVED_VIRTUAL_ID) {\n // If routeTree hasn't been built yet (shouldn't happen), scan now\n if (!ctx.routeTree) {\n rescan();\n }\n return generateManifestModule(ctx.routeTree!, ctx.root);\n }\n\n if (id === RESOLVED_SCHEMA_ID) {\n return generateSchemaModule(ctx.appDir);\n }\n\n // TIM-935: $segment virtual module — exports route and segmentPath.\n if (id.startsWith(SEGMENT_PREFIX)) {\n const info: SegmentInfo = JSON.parse(id.slice(SEGMENT_PREFIX.length));\n return [\n `export const ROUTE = ${JSON.stringify(info.route)};`,\n `export const SEGMENT_PATH = ${JSON.stringify(info.segmentPath)};`,\n '',\n ].join('\\n');\n }\n\n return null;\n },\n\n /**\n * Scan routes at build start.\n *\n * In dev mode, skip — configureServer runs after buildStart and will\n * do its own scan. Avoids a redundant FS traversal on cold start.\n */\n buildStart() {\n if (ctx.dev) return;\n rescan();\n },\n\n /**\n * Wait for the codegen writes started by `buildStart` before the build\n * reports done.\n *\n * `writeCodegen` runs unawaited so route scanning never blocks on disk.\n * Without this the build can finish — and the CLI can exit — while the\n * generated `.d.ts` files are still being written, leaving a project root\n * with no route types after an apparently successful build.\n */\n closeBundle() {\n return flushCodegenWrites();\n },\n\n /**\n * Set up file watcher in dev mode.\n *\n * Watches app/ for file additions/deletions/renames that affect\n * the route tree, regenerates the manifest, and invalidates\n * dependent modules via HMR.\n */\n configureServer(devServer: ViteDevServer) {\n // Initial scan (only scan point in dev — buildStart is skipped)\n rescan();\n\n // Watch the app directory\n devServer.watcher.add(ctx.appDir);\n\n /** Snapshot of the last generated manifest, used to detect structural changes. */\n let lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n\n /**\n * Rescan without letting a rejected route tree kill the dev server.\n *\n * `rescan()` throws on hard misconfigurations — duplicate conventions,\n * route collisions, a status file that is not a client component. Those\n * throws are correct at startup and in `vite build`, but here they run\n * inside a chokidar listener, where an exception is an unhandled\n * rejection that takes the process down mid-edit. Report and keep the\n * last good tree so the server stays up and the fix is one save away.\n *\n * Returns false when the scan failed, so callers skip the manifest\n * regeneration that would otherwise publish a stale tree as fresh.\n */\n /**\n * True while the last rescan is still failing.\n *\n * Recovery has to force a reload even when the manifest is byte-identical.\n * Adding a missing `'use client'` back to a status file changes no route\n * metadata, so the content-change path would send nothing and leave the\n * error overlay on screen over a page that is now fine.\n */\n let scanFailed = false;\n\n const rescanSafely = (): boolean => {\n try {\n rescan();\n if (scanFailed) {\n scanFailed = false;\n // Force the reload: see `scanFailed`.\n lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n invalidateManifest(devServer);\n }\n return true;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(\n `[timber] Route scan failed — keeping previous routes.\\n${message}\\n`\n );\n scanFailed = true;\n\n // The terminal is not the only surface that needs this. Keeping the\n // previous tree keeps the *server* alive, but it does not un-edit the\n // file: Vite still re-transforms it, so the very next render hits the\n // failure this scan just diagnosed — and the browser's version of it\n // names nothing. Put the diagnosis where the developer is looking.\n devServer.hot.send({\n type: 'error',\n err: { message, stack: '', plugin: 'timber-routing' },\n });\n return false;\n }\n };\n\n /**\n * Handle a route-significant file being added or removed.\n * Always triggers a full-reload since the route tree structure changed.\n */\n const handleStructuralChange = (filePath: string) => {\n if (!filePath.startsWith(ctx.appDir)) return;\n if (!ROUTE_FILE_PATTERNS.test(filePath)) return;\n\n if (!rescanSafely()) return;\n lastManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n invalidateManifest(devServer);\n };\n\n /**\n * Handle a route file's content changing.\n *\n * Most content edits (JSX changes, fixing typos) don't affect route\n * metadata — Vite's React Fast Refresh handles those via normal HMR.\n * Only rescan and full-reload when route metadata actually changed\n * (e.g., searchParams export added/removed, metadata export changed).\n */\n const handleContentChange = (filePath: string) => {\n if (!filePath.startsWith(ctx.appDir)) return;\n if (!ROUTE_FILE_PATTERNS.test(filePath)) return;\n\n if (!rescanSafely()) return;\n const newManifest = ctx.routeTree ? generateManifestModule(ctx.routeTree, ctx.root) : '';\n if (newManifest !== lastManifest) {\n lastManifest = newManifest;\n invalidateManifest(devServer);\n }\n // Otherwise: content edit didn't change route metadata — let Vite HMR handle it\n };\n\n devServer.watcher.on('add', handleStructuralChange);\n devServer.watcher.on('unlink', handleStructuralChange);\n // Watch content changes to page files — searchParams detection depends\n // on file contents (export const searchParams), not just file presence.\n // But only full-reload when route metadata actually changes.\n devServer.watcher.on('change', handleContentChange);\n // Also watch renames (which are add+unlink) — handled by the above\n },\n };\n}\n\n/**\n * Invalidate the virtual route manifest module across all Vite environments.\n *\n * When the route tree changes, any environment that has imported the manifest\n * needs to be invalidated so the next request/transform picks up the new tree.\n */\n/** Set of warning keys we've already emitted — avoid repeating on every rescan. */\nconst _warnedKeys = new Set<string>();\n\n/**\n * Validate schema keys against the filesystem route tree.\n * Warns on stale keys, bracket form mismatches, and missing keys.\n * Uses the already-scanned route tree instead of re-scanning.\n */\nfunction warnSchemaValidation(ctx: PluginContext): void {\n if (!ctx.routeTree) return;\n const warnings = validateSchemaAgainstRoutes(ctx.routeTree, ctx.appDir);\n\n for (const w of warnings) {\n const warnKey = `${w.type}:${w.key}`;\n if (_warnedKeys.has(warnKey)) continue;\n _warnedKeys.add(warnKey);\n\n switch (w.type) {\n case 'stale-key':\n console.warn(`[timber] ${w.message}`);\n break;\n case 'bracket-mismatch':\n console.warn(`[timber] ${w.message}`);\n break;\n case 'missing-key':\n console.warn(`[timber] ${w.message}`);\n break;\n }\n }\n}\n\nfunction invalidateManifest(server: ViteDevServer): void {\n for (const envName of Object.keys(server.environments)) {\n const env = server.environments[envName];\n if (!env?.moduleGraph) continue;\n\n for (const virtualId of [RESOLVED_VIRTUAL_ID, RESOLVED_SCHEMA_ID]) {\n const mod = env.moduleGraph.getModuleById(virtualId);\n if (mod) {\n env.moduleGraph.invalidateModule(mod);\n }\n }\n\n // TIM-935: Invalidate all $segment virtual modules (prefixed \\0$segment:)\n for (const mod of env.moduleGraph.idToModuleMap.values()) {\n if (mod.id?.startsWith(SEGMENT_PREFIX)) {\n env.moduleGraph.invalidateModule(mod);\n }\n }\n }\n\n // Trigger HMR full reload — route changes are structural\n server.hot.send({ type: 'full-reload' });\n}\n","/**\n * timber-shims — Vite sub-plugin for next/* → timber shim resolution.\n *\n * Intercepts imports of next/* modules and redirects them to timber.js\n * shim implementations. This enables Next.js-compatible libraries\n * (nuqs, next-intl, etc.) to work unmodified.\n *\n * This plugin also remaps ALL @timber-js/app/* subpath imports to src/ in\n * server environments (RSC + SSR). This is required because dist/ chunks\n * are pre-built and miss Vite's RSC transforms (e.g. createContext from\n * 'react' doesn't exist in RSC's React build). It also ensures a single\n * module instance for shared mutable state. See SUBPATH_SRC_MAP and TIM-568.\n *\n * Design doc: 18-build-system.md §\"Shim Map\"\n */\n\nimport type { Plugin } from 'vite';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { EXPLICIT_MARKERS, markerFor, poisonPillSource } from '../analyze/poison-rules.ts';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n// Detect whether we're running from source (src/plugins/) or dist (dist/).\n// From src/plugins/: go up 2 levels to package root.\n// From dist/: go up 1 level to package root.\n// When Rollup bundles into dist/index.js, __dirname is dist/, not src/plugins/.\nconst PKG_ROOT = __dirname.endsWith('plugins')\n ? resolve(__dirname, '..', '..')\n : resolve(__dirname, '..');\nconst SHIMS_DIR = resolve(PKG_ROOT, 'src', 'shims');\n\n/**\n * The server-only marker's virtual ID, needed directly by the\n * `#server-only-guard` resolution branch below. All poison-pill rules\n * (specifiers, virtual IDs, error messages, environment policy) live in\n * analyze/poison-rules.ts — the single source of truth shared with the\n * `timber graph` reporter (design/47 §3).\n */\nconst SERVER_ONLY_VIRTUAL = markerFor('server-only').virtualId;\n\n/**\n * Map from @timber-js/app/<subpath> to relative src/ file paths.\n *\n * Used by the catch-all resolveId rule to remap subpath imports to src/\n * in server environments. When adding a new subpath export to package.json,\n * add it here too — tests/shims-drift.test.ts enumerates package.json\n * exports and fails if an entry is missing. See TIM-568.\n *\n * Exported for the drift test.\n */\nexport const SUBPATH_SRC_MAP: Record<string, string> = {\n 'cache': 'cache/index.ts',\n 'codec': 'codec.ts',\n 'cookies': 'cookies/index.ts',\n 'params': 'params/index.ts',\n 'search-params': 'search-params/index.ts',\n\n 'cache/stores/memory': 'cache/stores/memory.ts',\n 'cache/stores/redis': 'cache/stores/redis.ts',\n 'cache/stores/cloudflare-kv': 'cache/stores/cloudflare-kv.ts',\n 'cache/stores/vercel': 'cache/stores/vercel.ts',\n\n 'cdn': 'cdn/index.ts',\n 'cdn/cloudflare': 'cdn/cloudflare-purge.ts',\n 'cdn/cloudflare-workers': 'cdn/workers-cache-purge.ts',\n 'cdn/fastly': 'cdn/fastly-purge.ts',\n\n 'adapters/cloudflare': 'adapters/cloudflare.ts',\n 'adapters/cloudflare/cache': 'adapters/cloudflare-kv-cache.ts',\n 'adapters/cloudflare/dev': 'adapters/cloudflare-dev.ts',\n 'adapters/nitro': 'adapters/nitro.ts',\n 'adapters/types': 'adapters/types.ts',\n};\n\n/**\n * Runtime value exports of @timber-js/app/server, stubbed in the client\n * (browser) environment so a stray client-side import fails with a clear\n * call-time error instead of a confusing bundler error.\n *\n * Must stay in sync with the actual runtime exports of server/index.ts —\n * tests/shims-drift.test.ts compares this list against\n * Object.keys(import('../server/index.ts')) and fails on drift.\n * Type-only exports (DenyOptions, AccessContext, …) are erased at runtime\n * and must NOT appear here.\n */\nexport const SERVER_STUB_EXPORTS: readonly string[] = [\n // request-context\n 'getHeaders',\n 'getSegmentParams',\n // cookie-context\n 'getCookieJar',\n // primitives\n 'deny',\n 'redirect',\n 'redirectExternal',\n 'RedirectType',\n 'waitUntil',\n // action-client\n 'createActionClient',\n 'ActionError',\n 'validated',\n // form-data\n 'coerce',\n 'parseFormData',\n // revalidation\n 'revalidatePath',\n 'revalidateTag',\n // tracing\n 'getTraceId',\n 'getSpanId',\n 'withSpan',\n 'addSpanEvent',\n];\n\n/**\n * Map from next/* import specifiers to shim file paths.\n *\n * The shim map is a separate data structure (not embedded in the plugin)\n * per the task's approach constraints.\n */\nconst SHIM_MAP: Record<string, string> = {\n 'next/link': resolve(SHIMS_DIR, 'link.ts'),\n 'next/image': resolve(SHIMS_DIR, 'image.ts'),\n 'next/navigation': resolve(SHIMS_DIR, 'navigation.ts'),\n 'next/headers': resolve(SHIMS_DIR, 'headers.ts'),\n // next/font/* and @timber-js/app/fonts/* redirect to the timber-fonts\n // virtual modules. The fonts plugin's load hook serves the actual module\n // code. The package.json exports point to shim stubs for non-Vite contexts\n // (tsc, tests), but in Vite the virtual module takes priority via this map.\n 'next/font/google': '\\0@timber/fonts/google',\n 'next/font/local': '\\0@timber/fonts/local',\n '@timber-js/app/fonts/google': '\\0@timber/fonts/google',\n '@timber-js/app/fonts/local': '\\0@timber/fonts/local',\n};\n\n/**\n * Strip .js extension from an import specifier.\n *\n * Libraries like nuqs import `next/navigation.js` with an explicit\n * extension. We strip it before matching against the shim map.\n */\nfunction stripJsExtension(id: string): string {\n return id.endsWith('.js') ? id.slice(0, -3) : id;\n}\n\n/**\n * Read the Vite environment name from a plugin hook's `this` context.\n *\n * Duck-typed because the hook context type doesn't expose `environment`\n * in a way that survives our Plugin typing — see Vite's Environment API.\n */\nfunction envName(hookCtx: unknown): string | undefined {\n return (hookCtx as { environment?: { name?: string } }).environment?.name;\n}\n\n/**\n * Create the timber-shims Vite plugin.\n *\n * Hooks: resolveId, load\n */\nexport function timberShims(_ctx: PluginContext): Plugin {\n return {\n name: 'timber-shims',\n // Must run before Vite's built-in resolution so that server-only/client-only\n // poison pills are intercepted even when imported from node_modules deps\n // (e.g. bright, next-intl). Without this, the dep optimizer resolves to the\n // real CJS package which throws at runtime in the SSR environment.\n enforce: 'pre',\n\n /**\n * Resolve next/* imports to shim files.\n *\n * Resolution order:\n * 1. Check server-only / client-only poison pill packages\n * 2. Strip .js extension from the import specifier\n * 3. Check next/* shim map\n * 4. Return null (pass through) for everything else\n *\n * In server environments (RSC + SSR), @timber-js/app/* subpath imports\n * are remapped to src/ via SUBPATH_SRC_MAP and the explicit branches\n * below — dist/ chunks miss Vite's RSC transforms and would duplicate\n * mutable module state (see TIM-568 and the rationale comments below).\n *\n * In the client (browser) environment, imports resolve to dist/ via\n * package.json exports — except @timber-js/app/client (remapped to src/\n * to share module instances with browser-entry) and @timber-js/app/server,\n * which returns a virtual stub: server code must never be bundled into\n * the browser.\n */\n resolveId(id: string) {\n // Poison pill packages — resolve to virtual modules handled by load()\n for (const marker of EXPLICIT_MARKERS) {\n if (id === marker.specifier) return marker.virtualId;\n }\n\n const cleanId = stripJsExtension(id);\n\n // Check next/* shim map.\n // next/navigation resolves per environment (TIM-1420):\n // RSC → navigation-rsc.ts (throwing stubs — no useContext)\n // SSR → navigation.ts (real hooks + server functions)\n // client → navigation-client.ts (real hooks, no server imports)\n if (cleanId in SHIM_MAP) {\n if (cleanId === 'next/navigation') {\n const env = envName(this);\n if (env === 'client') return resolve(SHIMS_DIR, 'navigation-client.ts');\n if (env === 'rsc') return resolve(SHIMS_DIR, 'navigation-rsc.ts');\n }\n return SHIM_MAP[cleanId];\n }\n\n // ── @timber-js/app/* → src/ resolution in server environments ──\n //\n // All @timber-js/app/* subpath imports are remapped to src/ in server\n // environments (RSC + SSR). This is required for two reasons:\n //\n // 1. RSC correctness: dist/ chunks eagerly import from 'react' (e.g.\n // createContext in segment-context) which doesn't exist in RSC's\n // React build. Vite's RSC plugin only transforms src/ files —\n // dist/ chunks are pre-built and served as-is.\n //\n // 2. Module singleton correctness: framework internals use relative\n // imports that resolve within src/. If user code resolved to dist/\n // while framework code resolved to src/, mutable module-level state\n // (ALS refs, registered callbacks) would be duplicated. By remapping\n // all @timber-js/app/* to src/, everything shares one module graph.\n //\n // Exception: @timber-js/app/client in RSC resolves to dist/ where\n // 'use client' is preserved for client boundary detection.\n //\n // In the client (browser) environment, all imports resolve to dist/\n // via package.json exports (no remapping needed).\n\n // ── #imports resolution for package-internal modules ─────────────\n //\n // #server-internal and #client-internal are Node package imports\n // (package.json \"imports\" field). They are only resolvable from\n // within this package — external consumers get module-not-found.\n //\n // In Vite, we intercept them here to resolve to src/ for dev/build\n // correctness (same rationale as the @timber-js/app/* remap above).\n if (cleanId === '#server-only-guard') {\n const env = envName(this);\n if (env === 'client') {\n return SERVER_ONLY_VIRTUAL;\n }\n return resolve(PKG_ROOT, 'src', 'server', 'server-only-guard-noop.js');\n }\n\n if (cleanId === '#server-internal') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n return resolve(PKG_ROOT, 'src', 'server', 'internal.ts');\n }\n\n if (cleanId === '#client-internal') {\n // Always resolve to src/ — all environments (RSC, SSR, client)\n // use src/ for framework internals. In the client env, this\n // ensures browser-entry and @timber-js/app/client share the\n // same module graph (both resolve to src/).\n return resolve(PKG_ROOT, 'src', 'client', 'internal.ts');\n }\n\n if (cleanId === '#routing') {\n return resolve(PKG_ROOT, 'src', 'routing', 'index.ts');\n }\n\n // Legacy aliases — vitest and monorepo configs may still reference\n // the old @timber-js/app/server/internal and @timber-js/app/client/internal\n // specifiers via resolve.alias. When those aliases resolve to the\n // absolute src/ path, they bypass this plugin entirely. But if the\n // specifier reaches us unresolved (e.g., in a Vite build without\n // aliases), handle it the same way as the #imports above.\n if (cleanId === '@timber-js/app/server/internal') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n return resolve(PKG_ROOT, 'src', 'server', 'internal.ts');\n }\n\n if (cleanId === '@timber-js/app/client/internal') {\n // Same as #client-internal above — always resolve to src/.\n return resolve(PKG_ROOT, 'src', 'client', 'internal.ts');\n }\n\n if (cleanId === '@timber-js/app/server') {\n const env = envName(this);\n if (env === 'client') {\n return '\\0timber:server-empty';\n }\n // RSC + SSR: remap to src/\n return resolve(PKG_ROOT, 'src', 'server', 'index.ts');\n }\n\n // Alias hardening: monorepo dev configs (tests/shared-vite-config.ts,\n // packages/website) alias @timber-js/app/server to the absolute\n // src/server path for vitest compatibility. Vite's resolve.alias runs\n // before every plugin, so the bare-specifier branch above never sees\n // the import in those apps — the real server barrel (and its\n // AsyncLocalStorage) would be bundled into the browser. Catch the\n // already-aliased absolute path here and return the same stub.\n if (\n cleanId === resolve(PKG_ROOT, 'src', 'server', 'index.ts') ||\n cleanId === resolve(PKG_ROOT, 'src', 'server', 'internal.ts')\n ) {\n if (envName(this) === 'client') {\n return '\\0timber:server-empty';\n }\n }\n\n if (cleanId === '@timber-js/app/client') {\n const env = envName(this);\n // RSC: return null — needs dist/ for 'use client' boundary detection.\n // SSR + Client: resolve to src/ so that browser-entry (which uses\n // relative imports from src/) and user code (which uses the bare\n // specifier @timber-js/app/client) share the same module instances.\n // Without this, state.ts is loaded twice (src/ and dist/) and\n // setGlobalRouter() writes to one copy while getRouterOrNull()\n // reads from the other (always null).\n if (env === 'ssr' || env === 'client') {\n return resolve(PKG_ROOT, 'src', 'client', 'index.ts');\n }\n return null;\n }\n\n // Catch-all: remap any other @timber-js/app/<subpath> to src/\n // in non-client environments (RSC + SSR).\n if (cleanId.startsWith('@timber-js/app/') && cleanId !== '@timber-js/app/package.json') {\n const env = envName(this);\n if (env !== 'client') {\n const subpath = cleanId.slice('@timber-js/app/'.length);\n const srcPath = SUBPATH_SRC_MAP[subpath];\n if (srcPath) {\n return resolve(PKG_ROOT, 'src', srcPath);\n }\n }\n }\n\n return null;\n },\n\n /**\n * Serve virtual modules for server-only / client-only poison pills.\n *\n * In the correct environment, the module is a no-op (empty export).\n * In the wrong environment, it throws a build-time error message that\n * clearly identifies the boundary violation.\n */\n load(id: string) {\n const env = envName(this);\n\n // Poison pill bodies — a top-level throw in the wrong environment,\n // a no-op in the right one. Behavior (which environments throw, and\n // the exact message) is defined entirely by poison-rules.ts.\n for (const marker of EXPLICIT_MARKERS) {\n if (id === marker.virtualId) return poisonPillSource(marker, env);\n }\n\n // Error module for @timber-js/app/server in client environment.\n // Server modules must never be bundled into the browser — if this\n // module is reached, there is a broken import chain that needs fixing.\n if (id === '\\0timber:server-empty') {\n // Export named stubs instead of throwing at evaluation time.\n // Throwing at eval breaks the module system — the browser can't\n // resolve named imports like `import { deny } from '...'`.\n // Instead, each stub throws at call time with a clear message.\n // The export names are generated from SERVER_STUB_EXPORTS so the\n // list cannot drift from server/index.ts (drift test enforced).\n // RedirectType is a plain const object on the server, so it is\n // mirrored as one here — libraries read RedirectType.push as a value.\n const stubExports = SERVER_STUB_EXPORTS.map((name) =>\n name === 'RedirectType'\n ? `export const RedirectType = { push: 'push', replace: 'replace' };`\n : `export const ${name} = stub;`\n ).join('\\n');\n return `\nconst msg = \"[timber] @timber-js/app/server was imported from client code. \" +\n \"Server modules (headers, cookies, redirect, deny, etc.) cannot be used in client components. \" +\n \"If you need these APIs, move the import to a server component or middleware.\";\nfunction stub() { throw new Error(msg); }\n${stubExports}\n`;\n }\n },\n };\n}\n","/**\n * Shared path/URL helpers for the timber-fonts pipeline.\n *\n * Two concerns live here:\n *\n * - `fontUrlPrefix` — the public URL prefix for font binaries, derived\n * from Vite's resolved `base`. Every URL the pipeline emits (@font-face\n * src, manifest hrefs, dev middleware matching) must go through this so\n * apps deployed under a non-root base (`base: '/my-app/'`) resolve\n * fonts correctly. Emitted *file* locations are not base-prefixed —\n * only URLs are.\n *\n * - `fontOutputBasename` / `hashedFontBasename` — basename derivation for\n * local font sources. Paths are absolutized with `resolve()`, which\n * produces backslash separators on Windows, so `split('/').pop()` is\n * not safe. `path.win32.basename` handles both separators.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { win32 } from 'node:path';\n\n/** Directory (relative to the build output / URL root) holding font binaries. */\nexport const FONT_OUTPUT_DIR = '_timber/fonts';\n\n/**\n * Build the URL prefix for font binaries from Vite's resolved `base`.\n *\n * `fontUrlPrefix('/')` → `/_timber/fonts`\n * `fontUrlPrefix('/my-app/')` → `/my-app/_timber/fonts`\n */\nexport function fontUrlPrefix(base = '/'): string {\n const normalized = base.endsWith('/') ? base : `${base}/`;\n return `${normalized}${FONT_OUTPUT_DIR}`;\n}\n\n/**\n * Derive the output basename for a local font source path.\n *\n * Uses `path.win32.basename` because it splits on both `/` and `\\`,\n * handling absolute paths produced by `resolve()` on any platform.\n */\nexport function fontOutputBasename(srcPath: string): string {\n return win32.basename(srcPath);\n}\n\n/**\n * Derive the content-hashed output basename for a local font source.\n *\n * `hashedFontBasename('C:\\\\fonts\\\\MyFont-Bold.woff2', 'a1b2c3d4')`\n * → `MyFont-Bold-a1b2c3d4.woff2`\n */\nexport function hashedFontBasename(srcPath: string, hash: string): string {\n const basename = fontOutputBasename(srcPath);\n const ext = win32.extname(basename);\n const stem = ext ? basename.slice(0, -ext.length) : basename;\n return `${stem}-${hash}${ext}`;\n}\n","/**\n * Google Fonts download, caching, and dev CDN fallback.\n *\n * At build time (production only):\n * 1. Queries Google Fonts CSS API v2 for font metadata and file URLs\n * 2. Downloads woff2 font files\n * 3. Caches them in node_modules/.cache/timber-fonts/\n * 4. Content-hashes filenames for cache busting\n * 5. Emits font files into the build output via generateBundle\n *\n * In dev mode:\n * - Generates @font-face rules pointing to Google Fonts CDN\n * - No downloads, no caching\n *\n * Design doc: 24-fonts.md §\"Step 2: Font Download & Subsetting\"\n */\n\nimport { createHash } from 'node:crypto';\nimport { readFile, writeFile, mkdir, stat } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { ExtractedFont, FontFaceDescriptor } from './types.ts';\nimport { fontUrlPrefix } from './paths.ts';\n\n/**\n * Extract a recognizable error code (ETIMEDOUT, ENOTFOUND, etc.) from a\n * network error's cause chain. Node's undici-based `fetch` wraps the\n * system error inside `cause` (sometimes as an AggregateError).\n */\nfunction extractNetworkErrorCode(err: unknown): string | undefined {\n if (!(err instanceof Error)) return undefined;\n const code = (err as NodeJS.ErrnoException).code;\n if (code) return code;\n const cause = (err as { cause?: unknown }).cause;\n if (cause instanceof AggregateError) {\n for (const inner of cause.errors) {\n const innerCode = (inner as NodeJS.ErrnoException).code;\n if (innerCode) return innerCode;\n }\n }\n if (cause instanceof Error) {\n return (cause as NodeJS.ErrnoException).code;\n }\n return undefined;\n}\n\nconst MAX_RETRIES = 3;\nconst MIN_TIMEOUT_MS = 100;\n\nasync function retry<T>(fn: () => Promise<T>): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (attempt < MAX_RETRIES) {\n const delay = MIN_TIMEOUT_MS * 2 ** attempt;\n console.error(\n `${err instanceof Error ? err.message : String(err)}\\n\\nRetrying ${attempt + 1}/${MAX_RETRIES}...`\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n throw lastError;\n}\n\n/** Google Fonts CSS API v2 base URL. */\nconst GOOGLE_FONTS_API = 'https://fonts.googleapis.com/css2';\n\n/**\n * User-Agent string that requests woff2 format from Google Fonts API.\n * Google serves different formats based on user-agent.\n */\nconst WOFF2_USER_AGENT =\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';\n\n/** Default cache directory for downloaded font files. */\nconst DEFAULT_CACHE_DIR = 'node_modules/.cache/timber-fonts';\n\n/** A parsed @font-face block from the Google Fonts CSS response. */\nexport interface GoogleFontFace {\n family: string;\n weight: string;\n style: string;\n /** The remote URL to the font file. */\n url: string;\n /** The unicode-range from the CSS (e.g. `U+0000-00FF, U+0131`). */\n unicodeRange: string;\n /** Subset label extracted from the CSS comment (e.g. `latin`, `cyrillic`). */\n subset: string;\n}\n\n/** A downloaded and cached font file, ready for build output. */\nexport interface CachedFont {\n /** The original parsed face data. */\n face: GoogleFontFace;\n /** Content-hashed filename (e.g. `inter-latin-400-normal-abc123.woff2`). */\n hashedFilename: string;\n /** Absolute path to the cached file. */\n cachePath: string;\n /** Raw font file bytes. */\n data: Buffer;\n}\n\n/**\n * Build the Google Fonts CSS API v2 URL for a given font config.\n *\n * Example output:\n * https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap&subset=latin\n */\nexport function buildGoogleFontsUrl(font: ExtractedFont): string {\n const family = font.family.replace(/\\s+/g, '+');\n\n // Build axis spec: wght for weights, ital for italic styles\n const hasItalic = font.styles.includes('italic');\n const weights = font.weights.map(Number).sort((a, b) => a - b);\n\n let axisSpec: string;\n if (hasItalic && weights.length > 0) {\n // ital,wght@0,400;0,700;1,400;1,700\n const pairs: string[] = [];\n for (const ital of [0, 1]) {\n if (ital === 1 && !hasItalic) continue;\n if (ital === 0 && font.styles.length === 1 && font.styles[0] === 'italic') continue;\n for (const w of weights) {\n pairs.push(`${ital},${w}`);\n }\n }\n axisSpec = `ital,wght@${pairs.join(';')}`;\n } else if (weights.length > 0) {\n axisSpec = `wght@${weights.join(';')}`;\n } else {\n axisSpec = '';\n }\n\n const familyParam = axisSpec ? `${family}:${axisSpec}` : family;\n\n // Build URL manually — URLSearchParams encodes +, :, @, ; which\n // the Google Fonts CSS API v2 requires as literal characters.\n const parts = [`family=${familyParam}`];\n if (font.display) parts.push(`display=${font.display}`);\n\n return `${GOOGLE_FONTS_API}?${parts.join('&')}`;\n}\n\n/**\n * Fetch the CSS from Google Fonts API and parse out @font-face blocks.\n *\n * The API returns CSS with subset comments like:\n * ```\n * /* latin * /\n * @font-face { ... }\n * ```\n *\n * We parse each block to extract the font URL, unicode-range, and subset label.\n */\nexport async function fetchGoogleFontsCss(url: string): Promise<GoogleFontFace[]> {\n const css = await retry(async () => {\n let response: Response;\n try {\n response = await fetch(url, {\n headers: { 'User-Agent': WOFF2_USER_AGENT },\n });\n } catch (err) {\n const code = extractNetworkErrorCode(err);\n throw new Error(\n `[timber] Failed to fetch Google Fonts CSS from ${url}` +\n (code ? ` (${code})` : '') +\n `. Build requires internet access for font optimization.` +\n ` If building offline, set TIMBER_SKIP_FONTS=1 to skip font downloading.`\n );\n }\n\n if (!response.ok) {\n throw new Error(\n `Google Fonts API returned ${response.status}: ${response.statusText} for ${url}`\n );\n }\n\n return response.text();\n });\n\n return parseGoogleFontsCss(css);\n}\n\n/**\n * Parse the CSS response from Google Fonts API into structured font face data.\n *\n * Handles the Google Fonts CSS format with subset comments and @font-face blocks.\n */\nexport function parseGoogleFontsCss(css: string): GoogleFontFace[] {\n const faces: GoogleFontFace[] = [];\n\n // Match subset comments followed by @font-face blocks\n const blockPattern = /\\/\\*\\s*([a-z0-9-]+)\\s*\\*\\/\\s*@font-face\\s*\\{([^}]+)\\}/g;\n\n let match;\n while ((match = blockPattern.exec(css)) !== null) {\n const subset = match[1];\n const block = match[2];\n\n const familyMatch = block.match(/font-family:\\s*'([^']+)'/);\n const weightMatch = block.match(/font-weight:\\s*(\\d+)/);\n const styleMatch = block.match(/font-style:\\s*(\\w+)/);\n const urlMatch = block.match(/url\\(([^)]+)\\)\\s*format\\('woff2'\\)/);\n const rangeMatch = block.match(/unicode-range:\\s*([^;]+)/);\n\n if (familyMatch && urlMatch) {\n faces.push({\n family: familyMatch[1],\n weight: weightMatch?.[1] ?? '400',\n style: styleMatch?.[1] ?? 'normal',\n url: urlMatch[1],\n unicodeRange: rangeMatch?.[1]?.trim() ?? '',\n subset,\n });\n }\n }\n\n return faces;\n}\n\n/**\n * Filter parsed font faces to only the requested subsets.\n */\nexport function filterBySubsets(faces: GoogleFontFace[], subsets: string[]): GoogleFontFace[] {\n if (subsets.length === 0) return faces;\n const subsetSet = new Set(subsets);\n return faces.filter((f) => subsetSet.has(f.subset));\n}\n\n/**\n * Generate a content hash for font data.\n * Returns the first 8 hex chars of the SHA-256 hash.\n */\nexport function contentHash(data: Buffer): string {\n return createHash('sha256').update(data).digest('hex').slice(0, 8);\n}\n\n/**\n * Generate a content-hashed filename for a font face.\n *\n * Format: `<family>-<subset>-<weight>-<style>-<hash>.woff2`\n * Example: `inter-latin-400-normal-abc12345.woff2`\n */\nexport function hashedFontFilename(face: GoogleFontFace, data: Buffer): string {\n const slug = face.family.toLowerCase().replace(/\\s+/g, '-');\n const hash = contentHash(data);\n return `${slug}-${face.subset}-${face.weight}-${face.style}-${hash}.woff2`;\n}\n\n/**\n * Build the cache key for a font face.\n * Used to check if a font has already been downloaded.\n */\nexport function cacheKey(face: GoogleFontFace): string {\n const slug = face.family.toLowerCase().replace(/\\s+/g, '-');\n return `${slug}-${face.subset}-${face.weight}-${face.style}`;\n}\n\n/**\n * Download a single font file from its URL.\n */\nexport async function downloadFontFile(url: string): Promise<Buffer> {\n return retry(async () => {\n let response: Response;\n try {\n response = await fetch(url);\n } catch (err) {\n const code = extractNetworkErrorCode(err);\n throw new Error(\n `[timber] Failed to download font file from ${url}` +\n (code ? ` (${code})` : '') +\n `. Build requires internet access for font optimization.` +\n ` If building offline, set TIMBER_SKIP_FONTS=1 to skip font downloading.`\n );\n }\n if (!response.ok) {\n throw new Error(`Failed to download font from ${url}: ${response.status}`);\n }\n return Buffer.from(await response.arrayBuffer());\n });\n}\n\n/**\n * Download and cache all font files for a set of extracted Google fonts.\n *\n * - Checks the local cache first (node_modules/.cache/timber-fonts/)\n * - Downloads missing fonts from Google Fonts CDN\n * - Writes downloaded fonts to cache\n * - Returns CachedFont entries with content-hashed filenames\n */\nexport async function downloadAndCacheFonts(\n fonts: ExtractedFont[],\n projectRoot: string\n): Promise<CachedFont[]> {\n const cacheDir = join(projectRoot, DEFAULT_CACHE_DIR);\n await mkdir(cacheDir, { recursive: true });\n\n const googleFonts = fonts.filter((f) => f.provider === 'google');\n const cached: CachedFont[] = [];\n\n for (const font of googleFonts) {\n const apiUrl = buildGoogleFontsUrl(font);\n let faces: GoogleFontFace[];\n try {\n faces = await fetchGoogleFontsCss(apiUrl);\n } catch (err) {\n throw new Error(\n `[timber] Failed to download font '${font.family}': ${err instanceof Error ? err.message : String(err)}`\n );\n }\n const filtered = filterBySubsets(faces, font.subsets);\n\n for (const face of filtered) {\n const key = cacheKey(face);\n const metaPath = join(cacheDir, `${key}.meta.json`);\n const dataPath = join(cacheDir, `${key}.woff2`);\n\n let data: Buffer;\n let filename: string;\n\n // Check cache\n const cacheHit = await isCacheHit(metaPath, dataPath);\n if (cacheHit) {\n data = await readFile(dataPath);\n const meta = JSON.parse(await readFile(metaPath, 'utf-8'));\n filename = meta.hashedFilename;\n } else {\n // Download and cache\n data = await downloadFontFile(face.url);\n filename = hashedFontFilename(face, data);\n\n await writeFile(dataPath, data);\n await writeFile(metaPath, JSON.stringify({ hashedFilename: filename, url: face.url }));\n }\n\n cached.push({ face, hashedFilename: filename, cachePath: dataPath, data });\n }\n }\n\n return cached;\n}\n\n/**\n * Check if both the meta and data files exist in the cache.\n */\nasync function isCacheHit(metaPath: string, dataPath: string): Promise<boolean> {\n try {\n await stat(metaPath);\n await stat(dataPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Generate @font-face descriptors for cached (production) Google Fonts.\n *\n * Each CachedFont gets a FontFaceDescriptor pointing to the\n * content-hashed URL under `<base>_timber/fonts/`. The `urlPrefix` comes\n * from `fontUrlPrefix(viteBase)` so apps deployed under a non-root base\n * resolve fonts correctly.\n */\nexport function generateProductionFontFaces(\n cachedFonts: CachedFont[],\n display: string,\n urlPrefix = fontUrlPrefix()\n): FontFaceDescriptor[] {\n return cachedFonts.map((cf) => ({\n family: cf.face.family,\n src: `url('${urlPrefix}/${cf.hashedFilename}') format('woff2')`,\n weight: cf.face.weight,\n style: cf.face.style,\n display,\n unicodeRange: cf.face.unicodeRange,\n }));\n}\n\n/**\n * Generate @font-face descriptors for dev mode (CDN-pointing).\n *\n * In dev mode, we query the Google Fonts API but use the CDN URLs\n * directly instead of downloading. This avoids the download/cache\n * step during `vite dev`.\n */\nexport function generateDevFontFaces(\n faces: GoogleFontFace[],\n display: string\n): FontFaceDescriptor[] {\n return faces.map((face) => ({\n family: face.family,\n src: `url('${face.url}') format('woff2')`,\n weight: face.weight,\n style: face.style,\n display,\n unicodeRange: face.unicodeRange,\n }));\n}\n\n/**\n * Resolve dev-mode font faces for an extracted font.\n *\n * Fetches the CSS from Google Fonts API and returns FontFaceDescriptors\n * pointing to CDN URLs. No files are downloaded.\n */\nexport async function resolveDevFontFaces(font: ExtractedFont): Promise<FontFaceDescriptor[]> {\n const apiUrl = buildGoogleFontsUrl(font);\n const faces = await fetchGoogleFontsCss(apiUrl);\n const filtered = filterBySubsets(faces, font.subsets);\n return generateDevFontFaces(filtered, font.display);\n}\n","/**\n * @font-face CSS generation.\n *\n * Generates CSS strings from font face descriptors. Used by both\n * Google and local font providers.\n *\n * Design doc: 24-fonts.md §\"Step 3: @font-face Generation\"\n */\n\nimport type { FontFaceDescriptor } from './types.ts';\n\n/**\n * Generate a single `@font-face` CSS rule from a descriptor.\n */\nexport function generateFontFace(desc: FontFaceDescriptor): string {\n const lines: string[] = [];\n lines.push('@font-face {');\n lines.push(` font-family: '${desc.family}';`);\n lines.push(` src: ${desc.src};`);\n if (desc.weight) lines.push(` font-weight: ${desc.weight};`);\n if (desc.style) lines.push(` font-style: ${desc.style};`);\n if (desc.display) lines.push(` font-display: ${desc.display};`);\n if (desc.unicodeRange) lines.push(` unicode-range: ${desc.unicodeRange};`);\n lines.push('}');\n return lines.join('\\n');\n}\n\n/**\n * Generate multiple `@font-face` rules from an array of descriptors.\n */\nexport function generateFontFaces(descriptors: FontFaceDescriptor[]): string {\n return descriptors.map(generateFontFace).join('\\n\\n');\n}\n\n/**\n * Generate a scoped CSS class that sets a CSS custom property for the font.\n *\n * Example output:\n * ```css\n * .timber-font-inter {\n * --font-sans: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * }\n * ```\n */\nexport function generateVariableClass(\n className: string,\n variable: string,\n fontFamily: string\n): string {\n return `.${className} {\\n ${variable}: ${fontFamily};\\n font-family: ${fontFamily};\\n}`;\n}\n\n/**\n * Generate a scoped CSS class that applies font-family directly.\n *\n * Used when no `variable` is specified — the className applies\n * the font-family inline instead of through a CSS custom property.\n *\n * Example output:\n * ```css\n * .timber-font-inter {\n * font-family: 'Inter', 'Inter Fallback', system-ui, sans-serif;\n * }\n * ```\n */\nexport function generateFontFamilyClass(className: string, fontFamily: string): string {\n return `.${className} {\\n font-family: ${fontFamily};\\n}`;\n}\n","/**\n * Size-adjusted fallback font generation.\n *\n * Generates `@font-face` declarations for fallback fonts with\n * `size-adjust`, `ascent-override`, `descent-override`, and\n * `line-gap-override` to match custom font metrics and eliminate CLS.\n *\n * Design doc: 24-fonts.md §\"Step 4: Size-Adjusted Fallbacks\"\n */\n\n/**\n * Font metrics for size-adjusted fallback calculation.\n *\n * Values are percentages used in CSS override descriptors.\n */\ninterface FallbackMetrics {\n /** The local() system font to use as base. */\n fallbackFont: string;\n /** size-adjust percentage (e.g. 107.64). */\n sizeAdjust: number;\n /** ascent-override percentage (e.g. 90.49). */\n ascentOverride: number;\n /** descent-override percentage (e.g. 22.48). */\n descentOverride: number;\n /** line-gap-override percentage (e.g. 0). */\n lineGapOverride: number;\n}\n\n/**\n * Lookup table for commonly used Google Fonts.\n *\n * Metrics sourced from fontaine / @capsizecss/metrics.\n * Keyed by lowercase font family name.\n */\nconst FALLBACK_METRICS: Record<string, FallbackMetrics> = {\n 'inter': {\n fallbackFont: 'Arial',\n sizeAdjust: 107.64,\n ascentOverride: 90.49,\n descentOverride: 22.48,\n lineGapOverride: 0,\n },\n 'roboto': {\n fallbackFont: 'Arial',\n sizeAdjust: 100.3,\n ascentOverride: 92.77,\n descentOverride: 24.41,\n lineGapOverride: 0,\n },\n 'open sans': {\n fallbackFont: 'Arial',\n sizeAdjust: 105.48,\n ascentOverride: 101.03,\n descentOverride: 27.47,\n lineGapOverride: 0,\n },\n 'lato': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.5,\n ascentOverride: 100.22,\n descentOverride: 21.16,\n lineGapOverride: 0,\n },\n 'montserrat': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.17,\n ascentOverride: 85.13,\n descentOverride: 22.07,\n lineGapOverride: 0,\n },\n 'poppins': {\n fallbackFont: 'Arial',\n sizeAdjust: 112.76,\n ascentOverride: 96.31,\n descentOverride: 32.1,\n lineGapOverride: 0,\n },\n 'roboto mono': {\n fallbackFont: 'Courier New',\n sizeAdjust: 109.29,\n ascentOverride: 87.79,\n descentOverride: 23.1,\n lineGapOverride: 0,\n },\n 'jetbrains mono': {\n fallbackFont: 'Courier New',\n sizeAdjust: 112.7,\n ascentOverride: 89.53,\n descentOverride: 24.21,\n lineGapOverride: 0,\n },\n 'source code pro': {\n fallbackFont: 'Courier New',\n sizeAdjust: 106.13,\n ascentOverride: 93.47,\n descentOverride: 26.01,\n lineGapOverride: 0,\n },\n 'fira code': {\n fallbackFont: 'Courier New',\n sizeAdjust: 112.96,\n ascentOverride: 86.87,\n descentOverride: 26.34,\n lineGapOverride: 0,\n },\n 'nunito': {\n fallbackFont: 'Arial',\n sizeAdjust: 103.62,\n ascentOverride: 99.45,\n descentOverride: 34.8,\n lineGapOverride: 0,\n },\n 'playfair display': {\n fallbackFont: 'Georgia',\n sizeAdjust: 110.72,\n ascentOverride: 84.44,\n descentOverride: 23.56,\n lineGapOverride: 0,\n },\n 'merriweather': {\n fallbackFont: 'Georgia',\n sizeAdjust: 107.66,\n ascentOverride: 91.93,\n descentOverride: 27.6,\n lineGapOverride: 0,\n },\n 'raleway': {\n fallbackFont: 'Arial',\n sizeAdjust: 107.74,\n ascentOverride: 94.19,\n descentOverride: 26.76,\n lineGapOverride: 0,\n },\n};\n\n/**\n * Known serif font families (lowercase).\n * Used for generic family detection when the name doesn't contain \"serif\".\n */\nconst SERIF_FAMILIES = new Set([\n 'playfair display',\n 'merriweather',\n 'lora',\n 'georgia',\n 'garamond',\n 'eb garamond',\n 'crimson text',\n 'libre baskerville',\n 'source serif pro',\n 'source serif 4',\n 'dm serif display',\n 'dm serif text',\n 'noto serif',\n 'pt serif',\n 'bitter',\n 'domine',\n 'cormorant',\n 'cormorant garamond',\n]);\n\nexport function getGenericFamily(family: string): string {\n const lc = family.toLowerCase();\n if (lc.includes('mono') || lc.includes('code')) return 'monospace';\n if ((lc.includes('serif') && !lc.includes('sans')) || SERIF_FAMILIES.has(lc)) {\n return 'serif';\n }\n return 'sans-serif';\n}\n\n/**\n * Generate the full CSS for a size-adjusted fallback font.\n *\n * This produces a complete @font-face block with override descriptors\n * that FontFaceDescriptor doesn't natively support.\n */\nexport function generateFallbackCss(family: string): string | null {\n const metrics = FALLBACK_METRICS[family.toLowerCase()];\n if (!metrics) return null;\n\n const fallbackFamily = `${family} Fallback`;\n\n const lines = [\n '@font-face {',\n ` font-family: '${fallbackFamily}';`,\n ` src: local('${metrics.fallbackFont}');`,\n ` size-adjust: ${metrics.sizeAdjust}%;`,\n ` ascent-override: ${metrics.ascentOverride}%;`,\n ` descent-override: ${metrics.descentOverride}%;`,\n ` line-gap-override: ${metrics.lineGapOverride}%;`,\n '}',\n ];\n\n return lines.join('\\n');\n}\n\n/**\n * Check whether fallback metrics are available for a font family.\n */\nexport function hasFallbackMetrics(family: string): boolean {\n return family.toLowerCase() in FALLBACK_METRICS;\n}\n\n/**\n * Build the full font stack string for a font, including its\n * size-adjusted fallback and a generic family.\n *\n * Example: `'Inter', 'Inter Fallback', system-ui, sans-serif`\n */\nexport function buildFontStack(family: string): string {\n const generic = getGenericFamily(family);\n const hasMetrics = hasFallbackMetrics(family);\n\n const parts = [`'${family}'`];\n if (hasMetrics) parts.push(`'${family} Fallback'`);\n\n // Add system-ui for sans-serif fonts, ui-monospace for mono\n if (generic === 'monospace') {\n parts.push('ui-monospace');\n } else if (generic === 'sans-serif') {\n parts.push('system-ui');\n }\n parts.push(generic);\n\n return parts.join(', ');\n}\n","/**\n * Generic AST node types and recursive walkers for font static analysis.\n *\n * `ast.ts` owns parsing, config extraction, and call-site discovery; this\n * module owns the recursive walks that police where font bindings may be\n * used (dynamic configs, nested scopes, unconsumed references). Split out\n * to keep `ast.ts` under the 500-code-line limit (design/18-build-system.md).\n *\n * Design doc: 24-fonts.md §\"Step 1: Static Analysis\"\n */\n\n// ── AST node types (minimal subset of estree) ────────────────────────────────\n\nexport interface AstNode {\n type: string;\n [key: string]: unknown;\n}\n\nexport interface IdentifierNode extends AstNode {\n type: 'Identifier';\n name: string;\n}\n\nexport interface PositionedNode extends AstNode {\n start: number;\n end: number;\n}\n\n/** A flagged reference/usage for build-error reporting. */\nexport interface FlaggedUsage {\n name: string;\n line: number;\n column: number;\n}\n\n// ── Offset → line/column helper ──────────────────────────────────────────────\n\n/** Convert a 0-based byte offset into a 1-based line and 0-based column. */\nexport function offsetToLineColumn(\n source: string,\n offset: number\n): { line: number; column: number } {\n let line = 1;\n let lastNewline = -1;\n for (let i = 0; i < offset; i++) {\n if (source[i] === '\\n') {\n line++;\n lastNewline = i;\n }\n }\n return { line, column: offset - lastNewline - 1 };\n}\n\n// ── Shared recursion plumbing ────────────────────────────────────────────────\n\n/**\n * Invoke `visit` on every direct child AST node of `node` (array elements\n * and object-valued properties with a `type` field).\n */\nexport function walkChildNodes(node: AstNode, visit: (child: AstNode) => void): void {\n for (const key of Object.keys(node)) {\n if (key === 'type') continue;\n const child = node[key];\n if (Array.isArray(child)) {\n for (const item of child) {\n if (item && typeof item === 'object' && (item as AstNode).type) {\n visit(item as AstNode);\n }\n }\n } else if (child && typeof child === 'object' && (child as AstNode).type) {\n visit(child as AstNode);\n }\n }\n}\n\n// ── Walkers ──────────────────────────────────────────────────────────────────\n\n/**\n * Recursively walk the AST looking for CallExpression nodes where\n * the callee is one of the imported font names and the first argument\n * is not an ObjectExpression (i.e. it's dynamic).\n */\nexport function walkForDynamicCalls(\n node: AstNode,\n names: ReadonlySet<string>,\n source: string\n): string | null {\n if (!node || typeof node !== 'object') return null;\n\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode;\n if (callee.type === 'Identifier' && names.has((callee as IdentifierNode).name)) {\n const args = node.arguments as AstNode[];\n if (args.length > 0 && args[0].type !== 'ObjectExpression') {\n // Extract the argument source text\n const argStart = (args[0] as PositionedNode).start;\n const argEnd = (args[0] as PositionedNode).end;\n const argText = source.slice(argStart, argEnd);\n const calleeName = (callee as IdentifierNode).name;\n return `${calleeName}(${argText})`;\n }\n }\n }\n\n let result: string | null = null;\n walkChildNodes(node, (child) => {\n if (!result) result = walkForDynamicCalls(child, names, source);\n });\n return result;\n}\n\n/**\n * Node types that introduce a nested scope — any font call inside is an\n * error (font calls must be module-level, same constraint as Next.js).\n * Module scope so it isn't rebuilt on every recursive walk call.\n */\nconst NESTED_SCOPE_TYPES = new Set([\n 'FunctionDeclaration',\n 'FunctionExpression',\n 'ArrowFunctionExpression',\n 'IfStatement',\n 'ForStatement',\n 'ForInStatement',\n 'ForOfStatement',\n 'WhileStatement',\n 'DoWhileStatement',\n 'SwitchStatement',\n 'TryStatement',\n 'BlockStatement',\n 'ClassDeclaration',\n 'ClassExpression',\n]);\n\n/**\n * Recursively walk an AST node looking for font CallExpressions in nested\n * scopes (function bodies, if-blocks, loops, etc.). Font calls must be\n * module-level; nested calls are collected as errors.\n *\n * `isNested` tracks whether we've descended past the top-level statement.\n * Top-level VariableDeclarations and ExpressionStatements are already\n * handled by the main loop in `findFontCallSites`, so we only flag calls\n * found deeper.\n */\nexport function walkForNestedFontCalls(\n node: AstNode,\n bindingNames: ReadonlyMap<string, unknown>,\n source: string,\n out: FlaggedUsage[],\n isNested: boolean\n): void {\n if (!node || typeof node !== 'object') return;\n\n if (node.type === 'CallExpression') {\n const callee = node.callee as AstNode;\n if (\n isNested &&\n callee.type === 'Identifier' &&\n bindingNames.has((callee as IdentifierNode).name)\n ) {\n const pos = offsetToLineColumn(source, (node as PositionedNode).start);\n out.push({ name: (callee as IdentifierNode).name, line: pos.line, column: pos.column });\n return; // Don't recurse into this call's children\n }\n }\n\n const enterNested = isNested || NESTED_SCOPE_TYPES.has(node.type);\n walkChildNodes(node, (child) =>\n walkForNestedFontCalls(child, bindingNames, source, out, enterNested)\n );\n}\n\n/**\n * Recursively walk an AST node looking for references to font bindings\n * that were not consumed by a recognized call site.\n *\n * Skips:\n * - recognized CallExpressions (the transform rewrites them wholesale)\n * - TS type-position nodes (erased at runtime)\n * - non-computed member properties (`obj.Inter` doesn't reference the binding)\n * - non-computed object keys (`{ Inter: 1 }` doesn't reference the binding)\n * - export aliases (`export { inter as Inter }` — only `local` is a reference)\n */\nexport function walkForUnconsumedReferences(\n node: AstNode,\n bindingNames: ReadonlyMap<string, unknown>,\n consumedCallStarts: ReadonlySet<number>,\n source: string,\n out: FlaggedUsage[]\n): void {\n if (!node || typeof node !== 'object') return;\n if (node.type === 'ImportDeclaration' || node.type.startsWith('TS')) return;\n\n if (node.type === 'Identifier') {\n const name = (node as IdentifierNode).name;\n if (bindingNames.has(name)) {\n const pos = offsetToLineColumn(source, (node as PositionedNode).start);\n out.push({ name, line: pos.line, column: pos.column });\n }\n return;\n }\n\n if (node.type === 'CallExpression' && consumedCallStarts.has((node as PositionedNode).start)) {\n return; // The whole call (callee + config object) is rewritten.\n }\n\n if (node.type === 'MemberExpression' && !(node as { computed?: boolean }).computed) {\n const object = (node as { object?: AstNode }).object;\n if (object) {\n walkForUnconsumedReferences(object, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n if (node.type === 'Property' && !(node as { computed?: boolean }).computed) {\n const value = (node as { value?: AstNode }).value;\n if (value) {\n walkForUnconsumedReferences(value, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n if (node.type === 'ExportSpecifier') {\n // Only `local` references a module binding. `exported` is just the\n // public name — `export { inter as Inter }` must not flag `Inter`.\n const local = (node as { local?: AstNode }).local;\n if (local) {\n walkForUnconsumedReferences(local, bindingNames, consumedCallStarts, source, out);\n }\n return;\n }\n\n walkChildNodes(node, (child) =>\n walkForUnconsumedReferences(child, bindingNames, consumedCallStarts, source, out)\n );\n}\n","/**\n * AST utilities for extracting static font configs from source code.\n * Uses OXC via Vite's `parseAst` — handles JS/JSX/TS/TSX natively.\n *\n * Provides two tiers of API:\n *\n * 1. **Source-text helpers** (`extractFontConfigAst`, `extractLocalFontConfigAst`,\n * `detectDynamicFontCallAst`) — parse a snippet and return extracted config.\n * Still used by tests and callers that have only a string.\n *\n * 2. **AST-node helpers** (`extractGoogleFontConfigFromNode`,\n * `extractLocalFontConfigFromNode`, `findFontCallSites`) — operate on\n * nodes from an already-parsed Program so the transform hook can share\n * one parse with all analysis steps.\n *\n * Design doc: 24-fonts.md §\"Step 1: Static Analysis\"\n */\n\nimport { parseAst as viteParseAst } from 'vite';\nimport type { GoogleFontConfig } from './types.ts';\nimport type { LocalFontConfig, LocalFontSrc } from './types.ts';\nimport type { AstNode, IdentifierNode, PositionedNode, FlaggedUsage } from './ast-walk.ts';\nimport {\n offsetToLineColumn,\n walkForDynamicCalls,\n walkForNestedFontCalls,\n walkForUnconsumedReferences,\n} from './ast-walk.ts';\n\nexport type { FlaggedUsage } from './ast-walk.ts';\n\n// ── AST node types (font-config-specific, on top of ast-walk.ts's base) ──────\n\ninterface LiteralNode extends AstNode {\n type: 'Literal';\n value: string | number | boolean | null;\n}\n\ninterface ArrayExpressionNode extends AstNode {\n type: 'ArrayExpression';\n elements: AstNode[];\n}\n\ninterface ObjectExpressionNode extends AstNode {\n type: 'ObjectExpression';\n properties: PropertyNode[];\n}\n\ninterface PropertyNode extends AstNode {\n type: 'Property';\n key: AstNode & { name?: string; value?: string | number };\n value: AstNode;\n}\n\n// ── Core AST extraction helpers ──────────────────────────────────────────────\n\n/**\n * Parse a JavaScript expression string into an AST node.\n *\n * Wraps the expression in parens so OXC (via vite.parseAst) treats it as an expression statement.\n * Returns null if parsing fails.\n */\nfunction parseExpression(source: string): AstNode | null {\n try {\n const ast = viteParseAst(`(${source})`, { lang: 'tsx' }) as unknown as {\n body: Array<{ expression: AstNode }>;\n };\n return ast.body[0]?.expression ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Extract a static string value from an AST node.\n * Returns undefined if the node is not a string literal.\n */\nfunction extractString(node: AstNode): string | undefined {\n if (node.type === 'Literal' && typeof (node as LiteralNode).value === 'string') {\n return (node as LiteralNode).value as string;\n }\n return undefined;\n}\n\n/**\n * Extract a static boolean value from an AST node.\n * Returns undefined if the node is not a boolean literal.\n */\nfunction extractBoolean(node: AstNode): boolean | undefined {\n if (node.type === 'Literal' && typeof (node as LiteralNode).value === 'boolean') {\n return (node as LiteralNode).value as boolean;\n }\n return undefined;\n}\n\n/**\n * Extract a string array from an AST ArrayExpression node.\n * Returns undefined if any element is not a string literal.\n */\nfunction extractStringArray(node: AstNode): string[] | undefined {\n if (node.type !== 'ArrayExpression') return undefined;\n const arr = node as ArrayExpressionNode;\n const result: string[] = [];\n for (const elem of arr.elements) {\n const s = extractString(elem);\n if (s === undefined) return undefined;\n result.push(s);\n }\n return result;\n}\n\n/**\n * Get the key name from a Property node.\n */\nfunction getPropertyKey(prop: PropertyNode): string | undefined {\n if (prop.key.type === 'Identifier') {\n return (prop.key as IdentifierNode).name;\n }\n if (prop.key.type === 'Literal' && typeof prop.key.value === 'string') {\n return prop.key.value;\n }\n return undefined;\n}\n\n/**\n * Build a map of property name → value node from an ObjectExpression.\n */\nfunction objectProperties(node: ObjectExpressionNode): Map<string, AstNode> {\n const map = new Map<string, AstNode>();\n for (const prop of node.properties) {\n // Skip spread elements or computed keys\n if (prop.type !== 'Property') continue;\n const key = getPropertyKey(prop);\n if (key) map.set(key, prop.value);\n }\n return map;\n}\n\n// ── Google font config extraction ────────────────────────────────────────────\n\n/**\n * Extract a GoogleFontConfig from the source text of a font function call's\n * object argument.\n *\n * The `callSource` should be the text of the call's argument list including\n * parens, e.g. `({ subsets: ['latin'], weight: '400' })`.\n *\n * Returns null if parsing or extraction fails.\n */\nexport function extractFontConfigAst(callSource: string): GoogleFontConfig | null {\n const node = parseExpression(callSource);\n if (!node || node.type !== 'ObjectExpression') return null;\n return extractGoogleConfig(node as ObjectExpressionNode);\n}\n\n// ── Local font config extraction ─────────────────────────────────────────────\n\n/**\n * Extract a single LocalFontSrc entry from an ObjectExpression AST node.\n */\nfunction extractLocalFontSrcEntry(node: AstNode): LocalFontSrc | null {\n if (node.type !== 'ObjectExpression') return null;\n const props = objectProperties(node as ObjectExpressionNode);\n\n const pathNode = props.get('path');\n if (!pathNode) return null;\n const path = extractString(pathNode);\n if (path === undefined) return null;\n\n const entry: LocalFontSrc = { path };\n\n const weightNode = props.get('weight');\n if (weightNode) {\n const w = extractString(weightNode);\n if (w !== undefined) entry.weight = w;\n }\n\n const styleNode = props.get('style');\n if (styleNode) {\n const s = extractString(styleNode);\n if (s !== undefined) entry.style = s;\n }\n\n return entry;\n}\n\n/**\n * Extract a LocalFontConfig from the source text of a localFont() call's\n * object argument.\n *\n * Returns null if parsing or extraction fails.\n */\nexport function extractLocalFontConfigAst(callSource: string): LocalFontConfig | null {\n const node = parseExpression(callSource);\n if (!node || node.type !== 'ObjectExpression') return null;\n return extractLocalConfig(node as ObjectExpressionNode);\n}\n\n// ── Dynamic call detection ───────────────────────────────────────────────────\n\n/**\n * Detect if source code contains dynamic/computed font function calls\n * that cannot be statically analyzed.\n *\n * Uses OXC (via vite.parseAst) to parse the full source and inspect CallExpression nodes.\n * Returns the offending expression string if found, null if all calls are static.\n */\nexport function detectDynamicFontCallAst(source: string, importedNames: string[]): string | null {\n if (importedNames.length === 0) return null;\n\n let ast;\n try {\n ast = viteParseAst(source, { lang: 'tsx' }) as unknown as { body: AstNode[] };\n } catch {\n // If we can't parse the source at all, fall back to no detection\n return null;\n }\n\n const nameSet = new Set(importedNames);\n return walkForDynamicCalls(ast as unknown as AstNode, nameSet, source);\n}\n\n// ── AST-node-level config extraction ─────────────────────────────────────────\n//\n// These work on an already-parsed ObjectExpression node so the transform\n// hook can share one OXC (via vite.parseAst) parse of the full source file with all analysis\n// steps (TIM-827).\n\n/**\n * Extract a GoogleFontConfig from an ObjectExpression AST node.\n *\n * This is the node-level equivalent of `extractFontConfigAst` — it skips\n * the parse step because the caller already has a parsed Program.\n */\nexport function extractGoogleFontConfigFromNode(node: AstNode): GoogleFontConfig | null {\n if (node.type !== 'ObjectExpression') return null;\n return extractGoogleConfig(node as ObjectExpressionNode);\n}\n\n/**\n * Extract a LocalFontConfig from an ObjectExpression AST node.\n */\nexport function extractLocalFontConfigFromNode(node: AstNode): LocalFontConfig | null {\n if (node.type !== 'ObjectExpression') return null;\n return extractLocalConfig(node as ObjectExpressionNode);\n}\n\n/** Shared implementation for GoogleFontConfig extraction from an object node. */\nfunction extractGoogleConfig(objNode: ObjectExpressionNode): GoogleFontConfig {\n const props = objectProperties(objNode);\n const config: GoogleFontConfig = {};\n\n const subsetsNode = props.get('subsets');\n if (subsetsNode) {\n const arr = extractStringArray(subsetsNode);\n if (arr) config.subsets = arr;\n }\n\n const weightNode = props.get('weight');\n if (weightNode) {\n const arr = extractStringArray(weightNode);\n if (arr) {\n config.weight = arr;\n } else {\n const s = extractString(weightNode);\n if (s !== undefined) config.weight = s;\n }\n }\n\n const displayNode = props.get('display');\n if (displayNode) {\n const s = extractString(displayNode);\n if (s !== undefined) config.display = s as GoogleFontConfig['display'];\n }\n\n const variableNode = props.get('variable');\n if (variableNode) {\n const s = extractString(variableNode);\n if (s !== undefined) config.variable = s;\n }\n\n const styleNode = props.get('style');\n if (styleNode) {\n const arr = extractStringArray(styleNode);\n if (arr) {\n config.style = arr;\n } else {\n const s = extractString(styleNode);\n if (s !== undefined) config.style = s;\n }\n }\n\n const preloadNode = props.get('preload');\n if (preloadNode) {\n const b = extractBoolean(preloadNode);\n if (b !== undefined) config.preload = b;\n }\n\n return config;\n}\n\n/** Shared implementation for LocalFontConfig extraction from an object node. */\nfunction extractLocalConfig(objNode: ObjectExpressionNode): LocalFontConfig | null {\n const props = objectProperties(objNode);\n\n const displayNode = props.get('display');\n const display = displayNode\n ? (extractString(displayNode) as LocalFontConfig['display'])\n : undefined;\n\n const variableNode = props.get('variable');\n const variable = variableNode ? extractString(variableNode) : undefined;\n\n const familyNode = props.get('family');\n const family = familyNode ? extractString(familyNode) : undefined;\n\n const srcNode = props.get('src');\n if (!srcNode) return null;\n\n const srcString = extractString(srcNode);\n if (srcString !== undefined) {\n return { src: srcString, display, variable, family };\n }\n\n if (srcNode.type === 'ArrayExpression') {\n const arr = srcNode as ArrayExpressionNode;\n const entries: LocalFontSrc[] = [];\n for (const elem of arr.elements) {\n const entry = extractLocalFontSrcEntry(elem);\n if (!entry) return null;\n entries.push(entry);\n }\n if (entries.length === 0) return null;\n return { src: entries, display, variable, family };\n }\n\n return null;\n}\n\n// ── Font module specifiers ───────────────────────────────────────────────────\n\nconst GOOGLE_FONT_SOURCES = new Set([\n '@timber/fonts/google',\n '@timber-js/app/fonts/google',\n 'next/font/google',\n]);\n\nconst LOCAL_FONT_SOURCES = new Set([\n '@timber/fonts/local',\n '@timber-js/app/fonts/local',\n 'next/font/local',\n]);\n\n// ── Parsed source types ──────────────────────────────────────────────────────\n\n/** A font import binding discovered from an ImportDeclaration. */\nexport interface FontBinding {\n /** The local name used in the module (after `as`, if present). */\n localName: string;\n /**\n * The original exported name (before `as`). For Google fonts this is\n * the PascalCase_With_Underscores name that maps to the family. For\n * local fonts (`default` import), this is `'default'`.\n */\n importedName: string;\n /** `'google'` or `'local'`. */\n provider: 'google' | 'local';\n /** The AST node of the ImportDeclaration (for removal via magic-string). */\n importNode: AstNode & { start: number; end: number };\n}\n\n/** A font function call site discovered from a CallExpression. */\nexport interface FontCallSite {\n /** The binding that this call references. */\n binding: FontBinding;\n /**\n * The variable name this call is assigned to, if the call appears in a\n * VariableDeclarator. `null` for bare expression statements.\n */\n assignedName: string | null;\n /** The first argument AST node (expected to be an ObjectExpression). */\n configNode: AstNode;\n /**\n * The outermost AST node to replace. For a VariableDeclaration with a\n * single declarator this is the full declaration; for a bare expression\n * statement it is the ExpressionStatement. The transform replaces\n * `source[replaceStart..replaceEnd]`.\n */\n replaceStart: number;\n replaceEnd: number;\n /** Line number (1-based) of the call for error messages. */\n line: number;\n /** Column (0-based) of the call for error messages. */\n column: number;\n}\n\n/** Result of `findFontCallSites` — everything the transform needs. */\nexport interface FontAnalysis {\n bindings: FontBinding[];\n callSites: FontCallSite[];\n /**\n * Import nodes that should be removed (deduplicated). Only imports that\n * produced at least one font binding are listed — removing an import\n * whose bindings the transform doesn't rewrite (e.g. a namespace\n * import) would leave dangling references behind.\n */\n importNodesToRemove: Array<{ start: number; end: number }>;\n /** First dynamic call expression text, or `null`. */\n dynamicCall: string | null;\n /**\n * Font calls found in nested scopes (functions, if-blocks, etc.).\n * These are errors — font calls must be module-level.\n */\n nestedCalls: FlaggedUsage[];\n /**\n * Namespace imports of font modules (`import * as fonts from ...`).\n * These are errors — the transform cannot rewrite `fonts.Inter(...)`\n * member calls, so the fonts would silently never load.\n */\n namespaceImports: FlaggedUsage[];\n /**\n * References to font bindings that were not consumed by a recognized\n * call site (`export default Inter({...})`, object-literal nesting,\n * member access on the call result, aliasing, re-exports). These are\n * errors — the import is removed, so any leftover reference would be a\n * silent runtime ReferenceError.\n */\n unsupportedUsages: FlaggedUsage[];\n}\n\ninterface ImportDeclarationNode extends PositionedNode {\n type: 'ImportDeclaration';\n source: LiteralNode & { value: string };\n specifiers: Array<\n PositionedNode & {\n type: string;\n local: IdentifierNode;\n imported?: IdentifierNode;\n }\n >;\n}\n\ninterface CallExpressionNode extends PositionedNode {\n type: 'CallExpression';\n callee: AstNode;\n arguments: PositionedNode[];\n}\n\ninterface VariableDeclaratorNode extends PositionedNode {\n type: 'VariableDeclarator';\n id: PositionedNode;\n init: PositionedNode | null;\n}\n\ninterface VariableDeclarationNode extends PositionedNode {\n type: 'VariableDeclaration';\n declarations: VariableDeclaratorNode[];\n}\n\ninterface ExpressionStatementNode extends PositionedNode {\n type: 'ExpressionStatement';\n expression: PositionedNode;\n}\n\ninterface ExportNamedDeclarationNode extends PositionedNode {\n type: 'ExportNamedDeclaration';\n declaration: VariableDeclarationNode | ExpressionStatementNode | null;\n}\n\n// ── Type guards for AST narrowing ────────────────────────────────────────────\n//\n// OXC's parsed nodes all share the base `PositionedNode` shape with\n// `type: string`. TypeScript can't narrow a union that includes a\n// `string`-typed catch-all, so we use explicit type guards instead of\n// bare `.type ===` checks.\n\nfunction isImportDeclaration(node: PositionedNode): node is ImportDeclarationNode {\n return node.type === 'ImportDeclaration';\n}\n\nfunction isVariableDeclaration(node: PositionedNode): node is VariableDeclarationNode {\n return node.type === 'VariableDeclaration';\n}\n\nfunction isExpressionStatement(node: PositionedNode): node is ExpressionStatementNode {\n return node.type === 'ExpressionStatement';\n}\n\nfunction isExportNamedDeclaration(node: PositionedNode): node is ExportNamedDeclarationNode {\n return node.type === 'ExportNamedDeclaration';\n}\n\nfunction isCallExpression(node: PositionedNode): node is CallExpressionNode {\n return node.type === 'CallExpression';\n}\n\nfunction isIdentifier(node: AstNode): node is IdentifierNode {\n return node.type === 'Identifier';\n}\n\ninterface ProgramNode extends PositionedNode {\n type: 'Program';\n body: PositionedNode[];\n}\n\n/**\n * Parse a full source file and find all font imports and call sites.\n *\n * Returns `null` if the source has no font-related imports.\n */\nexport function findFontCallSites(source: string): FontAnalysis | null {\n let program: ProgramNode;\n try {\n program = viteParseAst(source, { lang: 'tsx' }) as unknown as ProgramNode;\n } catch {\n return null;\n }\n\n // Step 1: Find all font import declarations and build the bindings list.\n const bindings: FontBinding[] = [];\n const importNodesToRemove: Array<{ start: number; end: number }> = [];\n const namespaceImports: FlaggedUsage[] = [];\n\n for (const stmt of program.body) {\n if (!isImportDeclaration(stmt)) continue;\n const importDecl = stmt;\n const specSource = importDecl.source.value;\n\n let provider: 'google' | 'local' | null = null;\n if (GOOGLE_FONT_SOURCES.has(specSource)) provider = 'google';\n else if (LOCAL_FONT_SOURCES.has(specSource)) provider = 'local';\n if (!provider) continue;\n\n let producedBinding = false;\n for (const spec of importDecl.specifiers) {\n if (spec.type === 'ImportSpecifier' && provider === 'google') {\n producedBinding = true;\n bindings.push({\n localName: spec.local.name,\n importedName: spec.imported?.name ?? spec.local.name,\n provider,\n importNode: importDecl,\n });\n } else if (spec.type === 'ImportDefaultSpecifier' && provider === 'local') {\n producedBinding = true;\n bindings.push({\n localName: spec.local.name,\n importedName: 'default',\n provider,\n importNode: importDecl,\n });\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // `import * as fonts from ...` cannot be rewritten — the transform\n // only matches direct identifier calls, so `fonts.Inter(...)` would\n // silently fall through to the runtime fallback module and never\n // load a real font. Collected as a build error.\n const pos = offsetToLineColumn(source, spec.start);\n namespaceImports.push({ name: spec.local.name, line: pos.line, column: pos.column });\n }\n }\n\n // Only remove imports whose bindings the transform actually rewrites.\n // Removing an import that produced no binding (namespace imports,\n // default imports of the google module) would orphan its references.\n if (producedBinding) {\n importNodesToRemove.push({ start: stmt.start, end: stmt.end });\n }\n }\n\n if (bindings.length === 0 && namespaceImports.length === 0) return null;\n\n // Step 2: Walk the AST for CallExpression nodes whose callee is a font binding.\n const bindingsByName = new Map(bindings.map((b) => [b.localName, b]));\n const callSites: FontCallSite[] = [];\n // Start offsets of recognized (and dynamic-flagged) CallExpressions, so\n // the unsupported-reference walk in step 4 can skip them.\n const consumedCallStarts = new Set<number>();\n let dynamicCall: string | null = null;\n\n for (const stmt of program.body) {\n // Unwrap `export const roboto = Roboto(...)` — the AST wraps the\n // VariableDeclaration inside an ExportNamedDeclaration node.\n const effectiveStmt =\n isExportNamedDeclaration(stmt) && stmt.declaration ? stmt.declaration : stmt;\n\n // VariableDeclaration: `const inter = Inter({ ... })`\n if (isVariableDeclaration(effectiveStmt)) {\n for (const declarator of effectiveStmt.declarations) {\n if (!declarator.init) continue;\n if (!isCallExpression(declarator.init)) continue;\n const call = declarator.init;\n const site = matchCallExpression(call, bindingsByName, source);\n if (!site) continue;\n\n if (site === 'dynamic') {\n consumedCallStarts.add(call.start);\n if (!dynamicCall && isIdentifier(call.callee)) {\n const argStart = call.arguments[0].start;\n const argEnd = call.arguments[0].end;\n dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;\n }\n continue;\n }\n\n const assignedName = isIdentifier(declarator.id) ? declarator.id.name : null;\n\n const { line, column } = offsetToLineColumn(source, call.start);\n consumedCallStarts.add(call.start);\n callSites.push({\n binding: site.binding,\n assignedName,\n configNode: site.configNode,\n replaceStart: call.start,\n replaceEnd: call.end,\n line,\n column,\n });\n }\n }\n\n // ExpressionStatement: `Inter({ ... })` as a bare call\n if (isExpressionStatement(effectiveStmt)) {\n if (isCallExpression(effectiveStmt.expression)) {\n const call = effectiveStmt.expression;\n const site = matchCallExpression(call, bindingsByName, source);\n if (site && site !== 'dynamic') {\n const { line, column } = offsetToLineColumn(source, call.start);\n consumedCallStarts.add(call.start);\n callSites.push({\n binding: site.binding,\n assignedName: null,\n configNode: site.configNode,\n replaceStart: effectiveStmt.start,\n replaceEnd: effectiveStmt.end,\n line,\n column,\n });\n } else if (site === 'dynamic') {\n consumedCallStarts.add(call.start);\n if (!dynamicCall && isIdentifier(call.callee)) {\n const argStart = call.arguments[0].start;\n const argEnd = call.arguments[0].end;\n dynamicCall = `${call.callee.name}(${source.slice(argStart, argEnd)})`;\n }\n }\n }\n }\n }\n\n // Step 3: Walk nested scopes to find font calls that aren't module-level.\n // Font calls must be at module scope (same constraint as Next.js).\n // If the import is removed but a nested call remains, it's a ReferenceError.\n const nestedCalls: FlaggedUsage[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration') continue;\n walkForNestedFontCalls(stmt as AstNode, bindingsByName, source, nestedCalls, false);\n }\n\n // Step 4: Walk for references to font bindings that were not consumed by\n // a recognized call site. The transform removes the import declarations,\n // so any leftover reference (`export default Inter({...})`, object-literal\n // nesting, `Inter({...}).className`, `const f = Inter`, `export { Inter }`)\n // would become a silent runtime ReferenceError. Collected as build errors.\n const unsupportedUsages: FlaggedUsage[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration') continue;\n walkForUnconsumedReferences(\n stmt as AstNode,\n bindingsByName,\n consumedCallStarts,\n source,\n unsupportedUsages\n );\n }\n\n return {\n bindings,\n callSites,\n importNodesToRemove,\n dynamicCall,\n nestedCalls,\n namespaceImports,\n unsupportedUsages,\n };\n}\n\n/**\n * Match a CallExpression against the font bindings map.\n *\n * Returns the binding + config node if the call is a static font call,\n * `'dynamic'` if it's a font call with a non-object argument, or `null`\n * if the callee doesn't match any font binding.\n */\nfunction matchCallExpression(\n call: CallExpressionNode,\n bindings: Map<string, FontBinding>,\n _source: string\n): { binding: FontBinding; configNode: AstNode } | 'dynamic' | null {\n if (!isIdentifier(call.callee)) return null;\n const calleeName = call.callee.name;\n const binding = bindings.get(calleeName);\n if (!binding) return null;\n\n const args = call.arguments;\n if (args.length === 0 || args[0].type !== 'ObjectExpression') {\n return 'dynamic';\n }\n\n return { binding, configNode: args[0] };\n}\n","/**\n * Local font processing for the timber-fonts pipeline.\n *\n * Handles:\n * - Resolving font file paths relative to the importing module\n * - Normalizing single-string `src` to array form\n * - Generating @font-face descriptors for each weight/style variant\n *\n * Does NOT handle:\n * - Font format conversion (serve whatever the user provides)\n * - Font subsetting (user's responsibility for local fonts)\n *\n * Design doc: 24-fonts.md §\"Local Fonts\"\n */\n\nimport { resolve, dirname, extname } from 'node:path';\nimport type { LocalFontConfig, LocalFontSrc, FontFaceDescriptor, ExtractedFont } from './types.ts';\nimport { buildFontStack } from './fallbacks.ts';\nimport { extractLocalFontConfigAst } from './ast.ts';\nimport { fontOutputBasename, fontUrlPrefix } from './paths.ts';\n\n/**\n * Infer the font format from a file extension.\n *\n * Returns the CSS `format()` value for `@font-face` src descriptors.\n */\nexport function inferFontFormat(filePath: string): string {\n const ext = extname(filePath).toLowerCase();\n switch (ext) {\n case '.woff2':\n return 'woff2';\n case '.woff':\n return 'woff';\n case '.ttf':\n return 'truetype';\n case '.otf':\n return 'opentype';\n case '.eot':\n return 'embedded-opentype';\n default:\n return 'woff2';\n }\n}\n\n/**\n * Normalize `src` config to an array of LocalFontSrc entries.\n *\n * When `src` is a single string, it becomes a single entry with\n * default weight '400' and style 'normal'.\n */\nexport function normalizeSrc(src: string | LocalFontSrc[]): LocalFontSrc[] {\n if (typeof src === 'string') {\n return [{ path: src, weight: '400', style: 'normal' }];\n }\n return src.map((entry) => ({\n path: entry.path,\n weight: entry.weight ?? '400',\n style: entry.style ?? 'normal',\n }));\n}\n\n/**\n * Resolve font file paths relative to the importing module's directory.\n *\n * Takes the importer's file path and the normalized src entries,\n * returns new entries with absolute resolved paths.\n */\nexport function resolveLocalFontPaths(\n importerPath: string,\n sources: LocalFontSrc[]\n): LocalFontSrc[] {\n const importerDir = dirname(importerPath);\n return sources.map((entry) => ({\n ...entry,\n path: resolve(importerDir, entry.path),\n }));\n}\n\n/**\n * Generate a deterministic font family name from the file path\n * when no explicit `family` is provided.\n *\n * Uses the filename without extension, e.g. \"MyFont-Regular.woff2\" → \"MyFont-Regular\".\n * For multi-weight sources, uses the first file's name stem.\n */\nexport function generateFamilyName(sources: LocalFontSrc[]): string {\n if (sources.length === 0) return 'Local Font';\n const firstPath = sources[0].path;\n const basename = fontOutputBasename(firstPath);\n // Remove extension and weight/style suffixes for a cleaner family name\n const stem = basename.replace(/\\.[^.]+$/, '');\n // Strip common weight/style suffixes to get the family root\n const family = stem.replace(\n /[-_]?(Regular|Bold|Italic|Light|Medium|SemiBold|ExtraBold|Thin|Black|Heavy)$/i,\n ''\n );\n return family || stem;\n}\n\n/**\n * Generate @font-face descriptors for local font sources.\n *\n * Each source entry produces one @font-face rule. The `src` descriptor\n * uses a `url()` pointing to the served path under `<base>_timber/fonts/`.\n * The `urlPrefix` defaults to `fontUrlPrefix()` (root base) — pass\n * `fontUrlPrefix(viteBase)` so non-root deployments resolve correctly.\n */\nexport function generateLocalFontFaces(\n family: string,\n sources: LocalFontSrc[],\n display: string,\n urlPrefix = fontUrlPrefix()\n): FontFaceDescriptor[] {\n return sources.map((entry) => {\n const format = inferFontFormat(entry.path);\n const filename = entry.hashedBasename ?? fontOutputBasename(entry.path);\n return {\n family,\n src: `url('${urlPrefix}/${filename}') format('${format}')`,\n weight: entry.weight,\n style: entry.style,\n display,\n };\n });\n}\n\n/**\n * Build the className for a local font, following the same convention\n * as Google fonts: `timber-font-<lowercase-hyphenated-family>`.\n */\nexport function localFontClassName(family: string): string {\n return `timber-font-${family.toLowerCase().replace(/\\s+/g, '-')}`;\n}\n\n/**\n * Process a local font config into an ExtractedFont.\n *\n * This is the main entry point called by the fonts plugin's transform hook\n * when it encounters a `localFont()` call.\n */\nexport function processLocalFont(config: LocalFontConfig, importerPath: string): ExtractedFont {\n const sources = normalizeSrc(config.src);\n const resolvedSources = resolveLocalFontPaths(importerPath, sources);\n const family = config.family ?? generateFamilyName(sources);\n const display = config.display ?? 'swap';\n const className = localFontClassName(family);\n const fontStack = buildFontStack(family);\n\n const weights = [...new Set(resolvedSources.map((s) => s.weight ?? '400'))];\n const styles = [...new Set(resolvedSources.map((s) => s.style ?? 'normal'))];\n\n return {\n id: `local-${family.toLowerCase().replace(/\\s+/g, '-')}-${weights.join(',')}-${styles.join(',')}`,\n family,\n provider: 'local',\n weights,\n styles,\n subsets: [],\n display,\n variable: config.variable,\n localSources: resolvedSources,\n importer: importerPath,\n className,\n fontFamily: fontStack,\n };\n}\n\n/**\n * Extract a LocalFontConfig from a static `localFont()` call source.\n *\n * Parses patterns like:\n * localFont({ src: './fonts/MyFont.woff2', display: 'swap', variable: '--font-custom' })\n * localFont({ src: [{ path: './a.woff2', weight: '400' }, { path: './b.woff2', weight: '700' }] })\n *\n * Returns null if the call cannot be statically analyzed.\n *\n * Uses OXC (via vite.parseAst) AST parsing for robust handling of comments, trailing commas,\n * and multi-line configs.\n */\nexport function extractLocalFontConfig(callSource: string): LocalFontConfig | null {\n return extractLocalFontConfigAst(callSource);\n}\n","/**\n * Virtual module source generators for the timber-fonts plugin.\n *\n * The plugin exposes three virtual modules:\n *\n * - `@timber/fonts/google` — exports Google font loader functions. The\n * transform hook replaces actual call sites with static `FontResult`\n * objects, so this module is only loaded as a fallback (e.g. when the\n * transform hook hasn't run yet, or when an unknown font is referenced\n * via the default export proxy).\n * - `@timber/fonts/local` — exports `localFont()` as a fallback default.\n * - `virtual:timber-font-css/<hash>.css` — per-importer CSS module that\n * holds the combined `@font-face` + fallback + class CSS for every\n * font registered under that importer. The transform hook injects a\n * side-effect `import 'virtual:timber-font-css/<hash>.css'` into each\n * file that calls a font function, so Vite's CSS pipeline picks it up\n * like any other CSS asset. @vitejs/plugin-rsc's `collectCss` walks\n * the RSC module graph, finds the virtual module, and injects a\n * `<link rel=\"stylesheet\" data-rsc-css-href=...>` via React Float —\n * the same machinery component CSS rides on (TIM-828).\n *\n * The `.css` suffix is load-bearing: Vite's `isCSSRequest` regex matches\n * on file extension, so keeping it in the virtual id is how we tell\n * Vite's CSS pipeline (dev HMR + build asset emission) that this\n * module is CSS. The old `virtual:timber-font-css-register` side-effect\n * module, `globalThis.__timber_font_css` channel, and inline `<style>`\n * tag in the RSC entry were all removed in TIM-828.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { createHash } from 'node:crypto';\nimport type { ExtractedFont } from './types.ts';\n\nexport const VIRTUAL_GOOGLE = '@timber/fonts/google';\nexport const VIRTUAL_LOCAL = '@timber/fonts/local';\nexport const RESOLVED_GOOGLE = '\\0@timber/fonts/google';\nexport const RESOLVED_LOCAL = '\\0@timber/fonts/local';\n\n/**\n * Prefix used for the per-importer virtual CSS modules. The full id is\n * `virtual:timber-font-css/<hash>.css` where `<hash>` is a short SHA-256\n * digest of the importer path. We encode the hash (not the path itself)\n * so the id stays filesystem-safe and opaque to downstream consumers.\n */\nexport const VIRTUAL_FONT_CSS_PREFIX = 'virtual:timber-font-css/';\nexport const VIRTUAL_FONT_CSS_SUFFIX = '.css';\nexport const RESOLVED_FONT_CSS_PREFIX = '\\0' + VIRTUAL_FONT_CSS_PREFIX;\n\n/**\n * In-memory map from the short hash used in virtual module ids back to\n * the absolute importer path. Populated by `virtualFontCssIdFor()` when\n * the transform hook registers an importer and read by the plugin's\n * `load` hook when Vite asks for the CSS content.\n *\n * Scoped to a single `FontPipeline` instance to avoid cross-plugin-\n * instance collisions during multi-build pipelines.\n */\nfunction stripIdDecorations(id: string): string {\n const bare = id.startsWith('\\0') ? id.slice(1) : id;\n const qIdx = bare.indexOf('?');\n return qIdx === -1 ? bare : bare.slice(0, qIdx);\n}\n\nexport class VirtualFontCssIdMap {\n private readonly map = new Map<string, string>();\n\n /**\n * Return a stable virtual module id for `importer`. Calling this twice\n * with the same importer returns the same id. Registering under an\n * existing hash is idempotent.\n */\n idFor(importer: string): string {\n const hash = createHash('sha256').update(importer).digest('hex').slice(0, 16);\n this.map.set(hash, importer);\n return `${VIRTUAL_FONT_CSS_PREFIX}${hash}${VIRTUAL_FONT_CSS_SUFFIX}`;\n }\n\n /** Decode the importer from a resolved (or unresolved) virtual css id. */\n importerFor(id: string): string | undefined {\n const body = stripIdDecorations(id);\n if (!body.startsWith(VIRTUAL_FONT_CSS_PREFIX)) return undefined;\n if (!body.endsWith(VIRTUAL_FONT_CSS_SUFFIX)) return undefined;\n const hash = body.slice(\n VIRTUAL_FONT_CSS_PREFIX.length,\n body.length - VIRTUAL_FONT_CSS_SUFFIX.length\n );\n return this.map.get(hash);\n }\n\n /** True if `id` is any form of the virtual font css module. */\n matches(id: string): boolean {\n const body = stripIdDecorations(id);\n return body.startsWith(VIRTUAL_FONT_CSS_PREFIX) && body.endsWith(VIRTUAL_FONT_CSS_SUFFIX);\n }\n\n /** Drop every registered mapping. Used by tests. */\n clear(): void {\n this.map.clear();\n }\n}\n\n/**\n * Convert a font family name to a PascalCase export name.\n * e.g. \"JetBrains Mono\" → \"JetBrains_Mono\"\n */\nfunction familyToExportName(family: string): string {\n return family.replace(/\\s+/g, '_');\n}\n\n/**\n * Generate the virtual module source for `@timber/fonts/google`.\n *\n * The transform hook replaces real call sites at build time, so this\n * module only matters as a runtime fallback. We export a Proxy default\n * that handles any font name plus named exports for known families\n * (for tree-shaking).\n */\nexport function generateGoogleVirtualModule(fonts: Iterable<ExtractedFont>): string {\n const families = new Set<string>();\n for (const font of fonts) {\n if (font.provider === 'google') families.add(font.family);\n }\n\n const lines = [\n '// Auto-generated virtual module: @timber/fonts/google',\n '// Each export is a font loader function that returns a FontResult.',\n '',\n 'function createFontResult(family, config) {',\n ' return {',\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n ' className: `timber-font-${family.toLowerCase().replace(/\\\\s+/g, \"-\")}`,',\n ' style: { fontFamily: family },',\n ' variable: config?.variable,',\n ' };',\n '}',\n '',\n 'export default new Proxy({}, {',\n ' get(_, prop) {',\n ' if (typeof prop === \"string\") {',\n ' return (config) => createFontResult(prop.replace(/_/g, \" \"), config);',\n ' }',\n ' }',\n '});',\n ];\n\n for (const family of families) {\n const exportName = familyToExportName(family);\n lines.push('');\n lines.push(`export function ${exportName}(config) {`);\n lines.push(` return createFontResult('${family}', config);`);\n lines.push('}');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Generate the virtual module source for `@timber/fonts/local`.\n *\n * Like the google virtual module, this is a runtime fallback. The\n * transform hook normally replaces `localFont(...)` calls with static\n * `FontResult` objects at build time.\n */\nexport function generateLocalVirtualModule(): string {\n return [\n '// Auto-generated virtual module: @timber/fonts/local',\n '',\n 'export default function localFont(config) {',\n ' const family = config?.family || \"Local Font\";',\n ' return {',\n // eslint-disable-next-line no-template-curly-in-string -- codegen output\n ' className: `timber-font-${family.toLowerCase().replace(/\\\\s+/g, \"-\")}`,',\n ' style: { fontFamily: family },',\n ' variable: config?.variable,',\n ' };',\n '}',\n ].join('\\n');\n}\n","/**\n * FontPipeline — owns all per-font state for the timber-fonts plugin.\n *\n * Before TIM-829, font state was spread across three parallel mutable maps:\n *\n * - `registry: Map<string, ExtractedFont>`\n * - `googleFontFacesMap: Map<string, FontFaceDescriptor[]>`\n * - `cachedFonts: CachedFont[]`\n *\n * Every plugin hook had to remember which map(s) it owned and which it\n * read. The TIM-824 bug existed because `transform` could write to\n * `registry` multiple times for the same `(importer, family)` pair without\n * a corresponding cleanup of the entries that `buildStart` / `load` would\n * later use. The fix in TIM-824 added prune calls in `transform` for the\n * registry, but the parallel maps still had the same hazard latent in\n * them: any future code path that ran `buildStart`-equivalent logic on\n * HMR could re-introduce a stale-entry leak in a different map.\n *\n * TIM-829 collapses the three maps into a single `Map<string, FontEntry>`\n * keyed by font ID. Mutation goes through a small set of methods that\n * maintain the core invariant: **every piece of state belonging to a font\n * lives on its `FontEntry`, and `pruneFor` removes the entry along with\n * everything attached to it in one call.** No code path inside the plugin\n * touches the underlying map directly.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { ExtractedFont, FontEntry, FontFaceDescriptor } from './types.ts';\nimport type { CachedFont } from './google.ts';\nimport { contentHash } from './google.ts';\nimport { generateVariableClass, generateFontFamilyClass, generateFontFaces } from './css.ts';\nimport { generateFallbackCss } from './fallbacks.ts';\nimport { generateLocalFontFaces } from './local.ts';\nimport { hashedFontBasename, fontUrlPrefix } from './paths.ts';\nimport { VirtualFontCssIdMap } from './virtual-modules.ts';\n\nexport class FontPipeline {\n /**\n * The single per-font store. Keyed by `FontEntry.id` (which is itself\n * derived from `family + weights + styles + subsets + display`, so any\n * config change produces a new key).\n *\n * Marked `readonly` so the field reference can never be reassigned, but\n * the map contents are mutable through the methods below.\n */\n private readonly _entries = new Map<string, FontEntry>();\n\n /** When true, local font sources are content-hashed at registration time. */\n private readonly _hashOnRegister: boolean;\n\n /**\n * Vite's resolved `base`. Set from the plugin's `configResolved` hook so\n * every @font-face URL the pipeline renders carries the prefix.\n */\n private _base = '/';\n\n constructor(opts?: { hashOnRegister?: boolean }) {\n this._hashOnRegister = opts?.hashOnRegister ?? false;\n }\n\n /** Set Vite's resolved `base` (from `configResolved`). */\n setBase(base: string): void {\n this._base = base;\n }\n\n /**\n * Per-importer virtual CSS module id registry. Populated by the\n * transform hook when it inlines a font function call, read by the\n * plugin's `load` hook when Vite asks for the module's CSS source.\n *\n * Lives on the pipeline (rather than a module-level singleton) so\n * multiple parallel plugin instances — e.g. in the test suite — cannot\n * collide on the hash-to-importer map. Also makes `clear()` reset the\n * id map alongside the font entries so test fixtures start clean.\n */\n readonly cssIdMap = new VirtualFontCssIdMap();\n\n // ── Read-only accessors ─────────────────────────────────────────────────\n\n /** Number of registered fonts. */\n size(): number {\n return this._entries.size;\n }\n\n /** Iterate every entry as a `FontEntry` (with `faces` / `cachedFiles`). */\n entries(): IterableIterator<FontEntry> {\n return this._entries.values();\n }\n\n /** Iterate every entry typed as the narrower `ExtractedFont` shape. */\n fonts(): IterableIterator<ExtractedFont> {\n return this._entries.values();\n }\n\n /** Iterate every Google-provider entry. */\n *googleFonts(): IterableIterator<FontEntry> {\n for (const entry of this._entries.values()) {\n if (entry.provider === 'google') yield entry;\n }\n }\n\n /** Lookup an entry by font ID. */\n getEntry(id: string): FontEntry | undefined {\n return this._entries.get(id);\n }\n\n /**\n * True if `attachFaces()` has been called for `fontId` — even with an\n * empty array. This intentionally treats an empty resolution as\n * \"already processed\" so the dev `load()` path doesn't keep retrying\n * `resolveDevFontFaces()` on every request when Google returns no\n * matching faces for the requested subset(s). Mirrors the previous\n * `Map.has()` semantics this method replaced. (Codex review on PR #596.)\n *\n * Failures inside `resolveDevFontFaces` do not call `attachFaces` at\n * all, so they correctly stay retryable on the next request — see the\n * TIM-636 comment in `plugins/fonts.ts`.\n */\n hasFaces(fontId: string): boolean {\n const entry = this._entries.get(fontId);\n return entry?.faces !== undefined;\n }\n\n /**\n * True if `attachCachedFiles()` has been called for `fontId` — even\n * with an empty array. Same presence-vs-content rationale as\n * `hasFaces`: an empty resolution is a deterministic outcome, not a\n * \"not yet processed\" signal.\n */\n hasCachedFiles(fontId: string): boolean {\n const entry = this._entries.get(fontId);\n return entry?.cachedFiles !== undefined;\n }\n\n // ── Mutators ────────────────────────────────────────────────────────────\n\n /**\n * Register an extracted font under its content-derived ID.\n *\n * If an entry with the same ID already exists it is replaced wholesale,\n * dropping any previously-attached `faces` and `cachedFiles`. Callers\n * must call `pruneFor(importer, family)` first to ensure that any\n * previous registration from the same `(importer, family)` pair has been\n * dropped (TIM-824).\n */\n register(extracted: ExtractedFont): void {\n // Wholesale replace — never merge faces/cachedFiles from a previous\n // registration. Re-registration with the same ID always represents the\n // newest authoritative config and must start from a clean slate.\n const entry: FontEntry = { ...extracted };\n if (this._hashOnRegister && entry.provider === 'local' && entry.localSources) {\n for (const src of entry.localSources) {\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) continue;\n const data = readFileSync(absolutePath);\n src.hashedBasename = hashedFontBasename(src.path, contentHash(data));\n }\n }\n this._entries.set(entry.id, entry);\n }\n\n /** Attach pre-resolved `@font-face` descriptors to a font entry. */\n attachFaces(fontId: string, faces: FontFaceDescriptor[]): void {\n const entry = this._entries.get(fontId);\n if (!entry) {\n throw new Error(\n `[timber-fonts] attachFaces: no font entry registered for id \"${fontId}\". ` +\n `Call register() first.`\n );\n }\n entry.faces = faces;\n }\n\n /** Attach downloaded Google Font binaries to a font entry. */\n attachCachedFiles(fontId: string, files: CachedFont[]): void {\n const entry = this._entries.get(fontId);\n if (!entry) {\n throw new Error(\n `[timber-fonts] attachCachedFiles: no font entry registered for id \"${fontId}\". ` +\n `Call register() first.`\n );\n }\n entry.cachedFiles = files;\n }\n\n /**\n * Drop every registry entry that originated from `importer` and shares\n * `family` (case-insensitive), **along with all of its attached state**.\n *\n * This is the single chokepoint that guarantees stale `@font-face`\n * descriptors and orphaned cached binaries cannot leak across HMR edits.\n * Because every piece of per-font state lives on the `FontEntry`,\n * deleting the entry from the underlying map drops everything in one\n * operation — no parallel maps to keep in sync.\n *\n * See TIM-824 (the original prune fix) and TIM-829 (single-store\n * refactor that made this guarantee structural).\n */\n pruneFor(importer: string, family: string): void {\n const familyKey = family.toLowerCase();\n for (const [id, entry] of this._entries) {\n if (entry.importer === importer && entry.family.toLowerCase() === familyKey) {\n this._entries.delete(id);\n }\n }\n }\n\n /** True if at least one entry is registered under `importer`. */\n hasImporter(importer: string): boolean {\n for (const entry of this._entries.values()) {\n if (entry.importer === importer) return true;\n }\n return false;\n }\n\n /**\n * Drop **every** registry entry that originated from `importer`,\n * regardless of family.\n *\n * Called at the start of the transform hook before re-registering the\n * current extraction set. This handles the cases `pruneFor` misses:\n *\n * - **Family rename** (Inter → Roboto): the old family's entries are\n * cleared because we prune by importer, not by (importer, family).\n * - **Font call deleted**: the old entries are cleared even though no\n * new call provides a family to prune against.\n *\n * Other importers' fonts are untouched.\n *\n * See TIM-1087.\n */\n pruneImporter(importer: string): void {\n for (const [id, entry] of this._entries) {\n if (entry.importer === importer) {\n this._entries.delete(id);\n }\n }\n }\n\n /** Drop every registered font. Used by tests and rebuild flows. */\n clear(): void {\n this._entries.clear();\n this.cssIdMap.clear();\n }\n\n // ── Derived views ───────────────────────────────────────────────────────\n\n /**\n * Iterate every cached Google Font binary across all registered entries,\n * deduplicated by `hashedFilename`. Multiple entries that share the same\n * family hold references to the same `CachedFont` objects, so this\n * iterator yields each unique binary exactly once.\n */\n *uniqueCachedFiles(): IterableIterator<CachedFont> {\n const seen = new Set<string>();\n for (const entry of this._entries.values()) {\n if (!entry.cachedFiles) continue;\n for (const cf of entry.cachedFiles) {\n if (seen.has(cf.hashedFilename)) continue;\n seen.add(cf.hashedFilename);\n yield cf;\n }\n }\n }\n\n /**\n * Generate the combined CSS output for every registered font.\n *\n * Includes `@font-face` rules for local and Google fonts, fallback\n * `@font-face` rules, and scoped class rules. Google fonts use the\n * `faces` attached via `attachFaces()` (in `buildStart` for production\n * or lazily in `load` for dev).\n */\n getCss(): string {\n const urlPrefix = fontUrlPrefix(this._base);\n const cssParts: string[] = [];\n for (const entry of this._entries.values()) {\n cssParts.push(renderEntryCss(entry, urlPrefix));\n }\n return cssParts.join('\\n\\n');\n }\n\n /**\n * Render the combined CSS for every font registered from a specific\n * importer file. This is the anchor point for the per-importer virtual\n * CSS module (`virtual:timber-font-css/<hash>.css`) that the transform\n * hook injects as a side-effect import.\n *\n * Scoping by importer means two concurrent requests rendering different\n * routes cannot see each other's font CSS: each importer's virtual\n * module only contains CSS for fonts that module registered. It also\n * means Vite's CSS HMR can surgically reload just the affected importer\n * when a single file changes, rather than rebuilding one giant blob.\n *\n * Returns an empty string when no fonts are registered under `importer`.\n * The empty string is semantically equivalent to \"no CSS\" — Vite's CSS\n * pipeline handles it as a valid empty CSS module.\n */\n getCssForSegment(importer: string): string {\n const urlPrefix = fontUrlPrefix(this._base);\n const cssParts: string[] = [];\n for (const entry of this._entries.values()) {\n if (entry.importer !== importer) continue;\n cssParts.push(renderEntryCss(entry, urlPrefix));\n }\n return cssParts.join('\\n\\n');\n }\n}\n\n/**\n * Render the combined CSS for a single font entry.\n *\n * Reads `faces` straight off the entry. Private to this module — the only\n * public way to render a `FontEntry`'s CSS is through `FontPipeline.getCss()`.\n */\nfunction renderEntryCss(entry: FontEntry, urlPrefix: string): string {\n const cssParts: string[] = [];\n\n if (entry.provider === 'local' && entry.localSources) {\n const faces = generateLocalFontFaces(\n entry.family,\n entry.localSources,\n entry.display,\n urlPrefix\n );\n const faceCss = generateFontFaces(faces);\n if (faceCss) cssParts.push(faceCss);\n }\n\n if (entry.provider === 'google' && entry.faces && entry.faces.length > 0) {\n const faceCss = generateFontFaces(entry.faces);\n if (faceCss) cssParts.push(faceCss);\n }\n\n const fallbackCss = generateFallbackCss(entry.family);\n if (fallbackCss) cssParts.push(fallbackCss);\n\n if (entry.variable) {\n cssParts.push(generateVariableClass(entry.className, entry.variable, entry.fontFamily));\n } else {\n cssParts.push(generateFontFamilyClass(entry.className, entry.fontFamily));\n }\n\n return cssParts.join('\\n\\n');\n}\n","// src/vlq.ts\nvar comma = \",\".charCodeAt(0);\nvar semicolon = \";\".charCodeAt(0);\nvar chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nvar intToChar = new Uint8Array(64);\nvar charToInt = new Uint8Array(128);\nfor (let i = 0; i < chars.length; i++) {\n const c = chars.charCodeAt(i);\n intToChar[i] = c;\n charToInt[c] = i;\n}\nfunction decodeInteger(reader) {\n let value = 0;\n let shift = 0;\n let integer = 0;\n do {\n const c = reader.next();\n integer = charToInt[c];\n value |= (integer & 31) << shift;\n shift += 5;\n } while (integer & 32);\n return value;\n}\nfunction decodeSign(num) {\n return num & 1 ? -2147483648 | -(num >>> 1) : num >>> 1;\n}\nfunction encodeInteger(builder, num) {\n do {\n let clamped = num & 31;\n num >>>= 5;\n if (num > 0) clamped |= 32;\n builder.write(intToChar[clamped]);\n } while (num > 0);\n}\nfunction encodeSign(num) {\n return num < 0 ? -num << 1 | 1 : num << 1;\n}\nfunction hasMoreVlq(reader, max) {\n if (reader.pos >= max) return false;\n return reader.peek() !== comma;\n}\n\n// src/strings.ts\nvar bufLength = 1024 * 16;\nvar td = typeof TextDecoder !== \"undefined\" ? /* @__PURE__ */ new TextDecoder() : typeof Buffer !== \"undefined\" ? {\n decode(buf) {\n const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);\n return out.toString();\n }\n} : {\n decode(buf) {\n let out = \"\";\n for (let i = 0; i < buf.length; i++) {\n out += String.fromCharCode(buf[i]);\n }\n return out;\n }\n};\nvar StringWriter = class {\n constructor() {\n this.pos = 0;\n this.out = \"\";\n this.buffer = new Uint8Array(bufLength);\n }\n write(v) {\n const { buffer } = this;\n buffer[this.pos++] = v;\n if (this.pos === bufLength) {\n this.out += td.decode(buffer);\n this.pos = 0;\n }\n }\n flush() {\n const { buffer, out, pos } = this;\n return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;\n }\n};\nvar StringReader = class {\n constructor(buffer) {\n this.pos = 0;\n this.buffer = buffer;\n }\n next() {\n return this.buffer.charCodeAt(this.pos++);\n }\n peek() {\n return this.buffer.charCodeAt(this.pos);\n }\n indexOf(char) {\n const { buffer, pos } = this;\n const idx = buffer.indexOf(char, pos);\n return idx === -1 ? buffer.length : idx;\n }\n};\n\n// src/scopes.ts\nvar EMPTY = [];\nfunction decodeOriginalScopes(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const scopes = [];\n const stack = [];\n let line = 0;\n for (; reader.pos < length; reader.pos++) {\n line += decodeSign(decodeInteger(reader));\n const column = decodeSign(decodeInteger(reader));\n if (!hasMoreVlq(reader, length)) {\n const last = stack.pop();\n last[2] = line;\n last[3] = column;\n continue;\n }\n const kind = decodeSign(decodeInteger(reader));\n const fields = decodeSign(decodeInteger(reader));\n const hasName = fields & 1;\n const scope = hasName ? [line, column, 0, 0, kind, decodeSign(decodeInteger(reader))] : [line, column, 0, 0, kind];\n let vars = EMPTY;\n if (hasMoreVlq(reader, length)) {\n vars = [];\n do {\n const varsIndex = decodeSign(decodeInteger(reader));\n vars.push(varsIndex);\n } while (hasMoreVlq(reader, length));\n }\n scope.vars = vars;\n scopes.push(scope);\n stack.push(scope);\n }\n return scopes;\n}\nfunction encodeOriginalScopes(scopes) {\n const writer = new StringWriter();\n for (let i = 0; i < scopes.length; ) {\n i = _encodeOriginalScopes(scopes, i, writer, [0]);\n }\n return writer.flush();\n}\nfunction _encodeOriginalScopes(scopes, index, writer, state) {\n const scope = scopes[index];\n const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;\n if (index > 0) writer.write(comma);\n encodeInteger(writer, encodeSign(startLine - state[0]));\n state[0] = startLine;\n encodeInteger(writer, encodeSign(startColumn));\n encodeInteger(writer, encodeSign(kind));\n const fields = scope.length === 6 ? 1 : 0;\n encodeInteger(writer, encodeSign(fields));\n if (scope.length === 6) encodeInteger(writer, encodeSign(scope[5]));\n for (const v of vars) {\n encodeInteger(writer, encodeSign(v));\n }\n for (index++; index < scopes.length; ) {\n const next = scopes[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeOriginalScopes(scopes, index, writer, state);\n }\n writer.write(comma);\n encodeInteger(writer, encodeSign(endLine - state[0]));\n state[0] = endLine;\n encodeInteger(writer, encodeSign(endColumn));\n return index;\n}\nfunction decodeGeneratedRanges(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const ranges = [];\n const stack = [];\n let genLine = 0;\n let definitionSourcesIndex = 0;\n let definitionScopeIndex = 0;\n let callsiteSourcesIndex = 0;\n let callsiteLine = 0;\n let callsiteColumn = 0;\n let bindingLine = 0;\n let bindingColumn = 0;\n do {\n const semi = reader.indexOf(\";\");\n let genColumn = 0;\n for (; reader.pos < semi; reader.pos++) {\n genColumn += decodeSign(decodeInteger(reader));\n if (!hasMoreVlq(reader, semi)) {\n const last = stack.pop();\n last[2] = genLine;\n last[3] = genColumn;\n continue;\n }\n const fields = decodeSign(decodeInteger(reader));\n const hasDefinition = fields & 1;\n const hasCallsite = fields & 2;\n const hasScope = fields & 4;\n let callsite = null;\n let bindings = EMPTY;\n let range;\n if (hasDefinition) {\n const defSourcesIndex = definitionSourcesIndex + decodeSign(decodeInteger(reader));\n definitionScopeIndex = decodeSign(decodeInteger(reader)) + (definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0);\n definitionSourcesIndex = defSourcesIndex;\n range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];\n } else {\n range = [genLine, genColumn, 0, 0];\n }\n range.isScope = !!hasScope;\n if (hasCallsite) {\n const prevCsi = callsiteSourcesIndex;\n const prevLine = callsiteLine;\n callsiteSourcesIndex += decodeSign(decodeInteger(reader));\n const sameSource = prevCsi === callsiteSourcesIndex;\n callsiteLine = (sameSource ? callsiteLine : 0) + decodeSign(decodeInteger(reader));\n callsiteColumn = (sameSource && prevLine === callsiteLine ? callsiteColumn : 0) + decodeSign(decodeInteger(reader));\n callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];\n }\n range.callsite = callsite;\n if (hasMoreVlq(reader, semi)) {\n bindings = [];\n do {\n bindingLine = genLine;\n bindingColumn = genColumn;\n const expressionsCount = decodeSign(decodeInteger(reader));\n let expressionRanges;\n if (expressionsCount < -1) {\n expressionRanges = [[decodeSign(decodeInteger(reader))]];\n for (let i = -1; i > expressionsCount; i--) {\n const prevBl = bindingLine;\n bindingLine += decodeSign(decodeInteger(reader));\n bindingColumn = (bindingLine === prevBl ? bindingColumn : 0) + decodeSign(decodeInteger(reader));\n const expression = decodeSign(decodeInteger(reader));\n expressionRanges.push([expression, bindingLine, bindingColumn]);\n }\n } else {\n expressionRanges = [[expressionsCount]];\n }\n bindings.push(expressionRanges);\n } while (hasMoreVlq(reader, semi));\n }\n range.bindings = bindings;\n ranges.push(range);\n stack.push(range);\n }\n genLine++;\n reader.pos = semi + 1;\n } while (reader.pos < length);\n return ranges;\n}\nfunction encodeGeneratedRanges(ranges) {\n if (ranges.length === 0) return \"\";\n const writer = new StringWriter();\n for (let i = 0; i < ranges.length; ) {\n i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);\n }\n return writer.flush();\n}\nfunction _encodeGeneratedRanges(ranges, index, writer, state) {\n const range = ranges[index];\n const {\n 0: startLine,\n 1: startColumn,\n 2: endLine,\n 3: endColumn,\n isScope,\n callsite,\n bindings\n } = range;\n if (state[0] < startLine) {\n catchupLine(writer, state[0], startLine);\n state[0] = startLine;\n state[1] = 0;\n } else if (index > 0) {\n writer.write(comma);\n }\n encodeInteger(writer, encodeSign(range[1] - state[1]));\n state[1] = range[1];\n const fields = (range.length === 6 ? 1 : 0) | (callsite ? 2 : 0) | (isScope ? 4 : 0);\n encodeInteger(writer, encodeSign(fields));\n if (range.length === 6) {\n const { 4: sourcesIndex, 5: scopesIndex } = range;\n if (sourcesIndex !== state[2]) {\n state[3] = 0;\n }\n encodeInteger(writer, encodeSign(sourcesIndex - state[2]));\n state[2] = sourcesIndex;\n encodeInteger(writer, encodeSign(scopesIndex - state[3]));\n state[3] = scopesIndex;\n }\n if (callsite) {\n const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;\n if (sourcesIndex !== state[4]) {\n state[5] = 0;\n state[6] = 0;\n } else if (callLine !== state[5]) {\n state[6] = 0;\n }\n encodeInteger(writer, encodeSign(sourcesIndex - state[4]));\n state[4] = sourcesIndex;\n encodeInteger(writer, encodeSign(callLine - state[5]));\n state[5] = callLine;\n encodeInteger(writer, encodeSign(callColumn - state[6]));\n state[6] = callColumn;\n }\n if (bindings) {\n for (const binding of bindings) {\n if (binding.length > 1) encodeInteger(writer, encodeSign(-binding.length));\n const expression = binding[0][0];\n encodeInteger(writer, encodeSign(expression));\n let bindingStartLine = startLine;\n let bindingStartColumn = startColumn;\n for (let i = 1; i < binding.length; i++) {\n const expRange = binding[i];\n encodeInteger(writer, encodeSign(expRange[1] - bindingStartLine));\n bindingStartLine = expRange[1];\n encodeInteger(writer, encodeSign(expRange[2] - bindingStartColumn));\n bindingStartColumn = expRange[2];\n encodeInteger(writer, encodeSign(expRange[0]));\n }\n }\n }\n for (index++; index < ranges.length; ) {\n const next = ranges[index];\n const { 0: l, 1: c } = next;\n if (l > endLine || l === endLine && c >= endColumn) {\n break;\n }\n index = _encodeGeneratedRanges(ranges, index, writer, state);\n }\n if (state[0] < endLine) {\n catchupLine(writer, state[0], endLine);\n state[0] = endLine;\n state[1] = 0;\n } else {\n writer.write(comma);\n }\n encodeInteger(writer, encodeSign(endColumn - state[1]));\n state[1] = endColumn;\n return index;\n}\nfunction catchupLine(writer, lastLine, line) {\n do {\n writer.write(semicolon);\n } while (++lastLine < line);\n}\n\n// src/range-mappings.ts\nfunction decodeRangeMappings(input) {\n const { length } = input;\n const reader = new StringReader(input);\n const rangeMappings = [];\n do {\n const semi = reader.indexOf(\";\");\n const indices = [];\n let index = 0;\n while (reader.pos < semi) {\n index += decodeInteger(reader);\n indices.push(index);\n }\n rangeMappings.push(indices);\n reader.pos = semi + 1;\n } while (reader.pos <= length);\n return rangeMappings;\n}\nfunction encodeRangeMappings(decoded) {\n if (decoded.length === 0) return \"\";\n const writer = new StringWriter();\n for (let i = 0; i < decoded.length; i++) {\n const indices = decoded[i];\n if (i > 0) writer.write(semicolon);\n let index = 0;\n for (let j = 0; j < indices.length; j++) {\n const offset = indices[j];\n encodeInteger(writer, offset - index);\n index = offset;\n }\n }\n return writer.flush();\n}\n\n// src/sourcemap-codec.ts\nfunction decode(mappings) {\n const { length } = mappings;\n const reader = new StringReader(mappings);\n const decoded = [];\n let genColumn = 0;\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n do {\n const semi = reader.indexOf(\";\");\n const line = [];\n let sorted = true;\n let lastCol = 0;\n genColumn = 0;\n while (reader.pos < semi) {\n let seg;\n genColumn += decodeSign(decodeInteger(reader));\n if (genColumn < lastCol) sorted = false;\n lastCol = genColumn;\n if (hasMoreVlq(reader, semi)) {\n sourcesIndex += decodeSign(decodeInteger(reader));\n sourceLine += decodeSign(decodeInteger(reader));\n sourceColumn += decodeSign(decodeInteger(reader));\n if (hasMoreVlq(reader, semi)) {\n namesIndex += decodeSign(decodeInteger(reader));\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];\n } else {\n seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];\n }\n } else {\n seg = [genColumn];\n }\n line.push(seg);\n reader.pos++;\n }\n if (!sorted) sort(line);\n decoded.push(line);\n reader.pos = semi + 1;\n } while (reader.pos <= length);\n return decoded;\n}\nfunction sort(line) {\n line.sort(sortComparator);\n}\nfunction sortComparator(a, b) {\n return a[0] - b[0];\n}\nfunction encode(decoded) {\n const writer = new StringWriter();\n let sourcesIndex = 0;\n let sourceLine = 0;\n let sourceColumn = 0;\n let namesIndex = 0;\n for (let i = 0; i < decoded.length; i++) {\n const line = decoded[i];\n if (i > 0) writer.write(semicolon);\n if (line.length === 0) continue;\n let genColumn = 0;\n for (let j = 0; j < line.length; j++) {\n const segment = line[j];\n if (j > 0) writer.write(comma);\n encodeInteger(writer, encodeSign(segment[0] - genColumn));\n genColumn = segment[0];\n if (segment.length === 1) continue;\n encodeInteger(writer, encodeSign(segment[1] - sourcesIndex));\n encodeInteger(writer, encodeSign(segment[2] - sourceLine));\n encodeInteger(writer, encodeSign(segment[3] - sourceColumn));\n sourcesIndex = segment[1];\n sourceLine = segment[2];\n sourceColumn = segment[3];\n if (segment.length === 4) continue;\n encodeInteger(writer, encodeSign(segment[4] - namesIndex));\n namesIndex = segment[4];\n }\n }\n return writer.flush();\n}\nexport {\n decode,\n decodeGeneratedRanges,\n decodeOriginalScopes,\n decodeRangeMappings,\n encode,\n encodeGeneratedRanges,\n encodeOriginalScopes,\n encodeRangeMappings\n};\n//# sourceMappingURL=sourcemap-codec.mjs.map\n","import { encode, encodeRangeMappings } from \"@jridgewell/sourcemap-codec\";\n//#region src/BitSet.ts\nvar BitSet = class BitSet {\n\tconstructor(arg) {\n\t\tthis.bits = arg instanceof BitSet ? arg.bits.slice() : [];\n\t}\n\tadd(n) {\n\t\tthis.bits[n >> 5] |= 1 << (n & 31);\n\t}\n\thas(n) {\n\t\treturn !!(this.bits[n >> 5] & 1 << (n & 31));\n\t}\n};\n//#endregion\n//#region src/Chunk.ts\nvar Chunk = class Chunk {\n\tconstructor(start, end, content) {\n\t\tthis.start = start;\n\t\tthis.end = end;\n\t\tthis.original = content;\n\t\tthis.intro = \"\";\n\t\tthis.outro = \"\";\n\t\tthis.content = content;\n\t\tthis.storeName = false;\n\t\tthis.edited = false;\n\t\tthis.previous = null;\n\t\tthis.next = null;\n\t}\n\tappendLeft(content) {\n\t\tthis.outro += content;\n\t}\n\tappendRight(content) {\n\t\tthis.intro = this.intro + content;\n\t}\n\tclone() {\n\t\tconst chunk = new Chunk(this.start, this.end, this.original);\n\t\tchunk.intro = this.intro;\n\t\tchunk.outro = this.outro;\n\t\tchunk.content = this.content;\n\t\tchunk.storeName = this.storeName;\n\t\tchunk.edited = this.edited;\n\t\treturn chunk;\n\t}\n\tcontains(index) {\n\t\treturn this.start < index && index < this.end;\n\t}\n\teachNext(fn) {\n\t\tfn(this);\n\t\tlet chunk = this.next;\n\t\twhile (chunk) {\n\t\t\tfn(chunk);\n\t\t\tchunk = chunk.next;\n\t\t}\n\t}\n\teachPrevious(fn) {\n\t\tfn(this);\n\t\tlet chunk = this.previous;\n\t\twhile (chunk) {\n\t\t\tfn(chunk);\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t}\n\tedit(content, storeName, contentOnly) {\n\t\tthis.content = content;\n\t\tif (!contentOnly) {\n\t\t\tthis.intro = \"\";\n\t\t\tthis.outro = \"\";\n\t\t}\n\t\tthis.storeName = storeName;\n\t\tthis.edited = true;\n\t\treturn this;\n\t}\n\tprependLeft(content) {\n\t\tthis.outro = content + this.outro;\n\t}\n\tprependRight(content) {\n\t\tthis.intro = content + this.intro;\n\t}\n\treset() {\n\t\tthis.intro = \"\";\n\t\tthis.outro = \"\";\n\t\tif (this.edited) {\n\t\t\tthis.content = this.original;\n\t\t\tthis.storeName = false;\n\t\t\tthis.edited = false;\n\t\t}\n\t}\n\tsplit(index) {\n\t\tconst sliceIndex = index - this.start;\n\t\tconst originalBefore = this.original.slice(0, sliceIndex);\n\t\tconst originalAfter = this.original.slice(sliceIndex);\n\t\tthis.original = originalBefore;\n\t\tconst newChunk = new Chunk(index, this.end, originalAfter);\n\t\tnewChunk.outro = this.outro;\n\t\tthis.outro = \"\";\n\t\tthis.end = index;\n\t\tif (this.edited) {\n\t\t\tnewChunk.edit(\"\", false);\n\t\t\tthis.content = \"\";\n\t\t} else this.content = originalBefore;\n\t\tnewChunk.next = this.next;\n\t\tif (newChunk.next) newChunk.next.previous = newChunk;\n\t\tnewChunk.previous = this;\n\t\tthis.next = newChunk;\n\t\treturn newChunk;\n\t}\n\ttoString() {\n\t\treturn this.intro + this.content + this.outro;\n\t}\n\ttrimEnd(rx) {\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\tif (this.outro.length) return true;\n\t\tconst trimmed = this.content.replace(rx, \"\");\n\t\tif (trimmed.length) {\n\t\t\tif (trimmed !== this.content) {\n\t\t\t\tif (this.edited) this.edit(trimmed, this.storeName, true);\n\t\t\t\telse this.split(this.start + trimmed.length).edit(\"\", void 0, true);\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tthis.edit(\"\", void 0, true);\n\t\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\t\tif (this.intro.length) return true;\n\t\t}\n\t}\n\ttrimStart(rx) {\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (this.intro.length) return true;\n\t\tconst trimmed = this.content.replace(rx, \"\");\n\t\tif (trimmed.length) {\n\t\t\tif (trimmed !== this.content) {\n\t\t\t\tif (this.edited) this.edit(trimmed, this.storeName, true);\n\t\t\t\telse {\n\t\t\t\t\tthis.split(this.end - trimmed.length);\n\t\t\t\t\tthis.edit(\"\", void 0, true);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} else {\n\t\t\tthis.edit(\"\", void 0, true);\n\t\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\t\tif (this.outro.length) return true;\n\t\t}\n\t}\n};\n//#endregion\n//#region src/MagicStringError.ts\n/**\n* The single error type thrown by MagicString.\n*\n* Every message is prefixed with `[MagicString]` so its source is obvious at a\n* glance, and is kept short and consistent in tone.\n*/\nvar MagicStringError = class extends Error {\n\tname = \"MagicStringError\";\n\tconstructor(message, options) {\n\t\tsuper(`[MagicString] ${message}`, options);\n\t}\n};\n//#endregion\n//#region src/SourceMap.ts\nfunction getBtoa() {\n\t/* v8 ignore next -- environment fallback, unreachable when `btoa` is present */\n\tif (typeof globalThis !== \"undefined\" && typeof globalThis.btoa === \"function\") return (str) => globalThis.btoa(unescape(encodeURIComponent(str)));\n\tconst buffer = globalThis[\"Buffer\"];\n\tif (buffer) return (str) => buffer.from(str, \"utf-8\").toString(\"base64\");\n\treturn () => {\n\t\tthrow new MagicStringError(\"unsupported environment: `btoa` or `Buffer` is required\");\n\t};\n\t/* v8 ignore stop */\n}\nconst btoa = /* #__PURE__ */ getBtoa();\nvar SourceMap = class {\n\tconstructor(properties) {\n\t\tthis.version = 3;\n\t\tthis.file = properties.file;\n\t\tthis.sources = properties.sources;\n\t\tthis.sourcesContent = properties.sourcesContent;\n\t\tthis.names = properties.names;\n\t\tthis.mappings = typeof properties.mappings === \"string\" ? properties.mappings : encode(properties.mappings);\n\t\tif (typeof properties.x_google_ignoreList !== \"undefined\") this.x_google_ignoreList = properties.x_google_ignoreList;\n\t\tif (typeof properties.debugId !== \"undefined\") this.debugId = properties.debugId;\n\t\tif (typeof properties.rangeMappings !== \"undefined\") {\n\t\t\tlet shouldOutputRangeMapping = false;\n\t\t\tfor (const line of properties.rangeMappings) if (line.length !== 0) {\n\t\t\t\tshouldOutputRangeMapping = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (shouldOutputRangeMapping) this.rangeMappings = encodeRangeMappings(properties.rangeMappings);\n\t\t}\n\t}\n\t/**\n\t* Returns the equivalent of `JSON.stringify(map)`\n\t*/\n\ttoString() {\n\t\treturn JSON.stringify(this);\n\t}\n\t/**\n\t* Returns a DataURI containing the sourcemap. Useful for doing this sort of thing:\n\t* `generateMap(options?: SourceMapOptions): SourceMap;`\n\t*/\n\ttoUrl() {\n\t\treturn `data:application/json;charset=utf-8;base64,${btoa(this.toString())}`;\n\t}\n};\n//#endregion\n//#region src/utils/getLocator.ts\nfunction getLocator(source) {\n\tconst lineOffsets = [0];\n\tfor (let i = source.indexOf(\"\\n\"); i !== -1; i = source.indexOf(\"\\n\", i + 1)) lineOffsets.push(i + 1);\n\treturn function locate(index) {\n\t\tlet i = 0;\n\t\tlet j = lineOffsets.length;\n\t\twhile (i < j) {\n\t\t\tconst m = i + j >> 1;\n\t\t\tif (index < lineOffsets[m]) j = m;\n\t\t\telse i = m + 1;\n\t\t}\n\t\tconst line = i - 1;\n\t\treturn {\n\t\t\tline,\n\t\t\tcolumn: index - lineOffsets[line]\n\t\t};\n\t};\n}\n//#endregion\n//#region src/utils/getRelativePath.ts\nfunction getRelativePath(from, to) {\n\tconst fromParts = from.split(/[/\\\\]/);\n\tconst toParts = to.split(/[/\\\\]/);\n\tfromParts.pop();\n\twhile (fromParts[0] === toParts[0]) {\n\t\tfromParts.shift();\n\t\ttoParts.shift();\n\t}\n\tif (fromParts.length) {\n\t\tlet i = fromParts.length;\n\t\twhile (i--) fromParts[i] = \"..\";\n\t}\n\treturn fromParts.concat(toParts).join(\"/\");\n}\n//#endregion\n//#region src/utils/guessIndent.ts\nfunction guessIndent(code) {\n\tconst lines = code.split(\"\\n\");\n\tconst tabbed = lines.filter((line) => /^\\t+/.test(line));\n\tconst spaced = lines.filter((line) => /^ {2,}/.test(line));\n\tif (tabbed.length === 0 && spaced.length === 0) return null;\n\tif (tabbed.length >= spaced.length) return \"\t\";\n\tconst min = spaced.reduce((previous, current) => {\n\t\tconst numSpaces = /^ +/.exec(current)[0].length;\n\t\treturn Math.min(numSpaces, previous);\n\t}, Infinity);\n\treturn \" \".repeat(min);\n}\n//#endregion\n//#region src/utils/isObject.ts\nconst toString = Object.prototype.toString;\nfunction isObject(thing) {\n\treturn toString.call(thing) === \"[object Object]\";\n}\nconst BASE64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\nconst intToChar = /* #__PURE__ */ (() => {\n\tconst chars = /* @__PURE__ */ new Uint8Array(64);\n\tfor (let i = 0; i < 64; i++) chars[i] = BASE64_CHARS.charCodeAt(i);\n\treturn chars;\n})();\nconst COMMA = 44;\nconst SEMICOLON = 59;\nconst BUFFER_SIZE = 16384;\nconst FLUSH_THRESHOLD = 16348;\nconst scratch = /* #__PURE__ */ new Uint8Array(BUFFER_SIZE);\nfunction writeVlq(pos, num) {\n\tnum = num < 0 ? -num << 1 | 1 : num << 1;\n\tdo {\n\t\tlet clamped = num & 31;\n\t\tnum >>>= 5;\n\t\tif (num > 0) clamped |= 32;\n\t\tscratch[pos++] = intToChar[clamped];\n\t} while (num > 0);\n\treturn pos;\n}\nconst decoder = /* #__PURE__ */ new TextDecoder();\nvar MappingsEncoder = class {\n\tconstructor() {\n\t\tthis.out = \"\";\n\t\tthis.pos = 0;\n\t\tthis.lines = [];\n\t\tthis.buffered = 0;\n\t\tthis.needsComma = false;\n\t\tthis.prevGenColumn = 0;\n\t\tthis.prevSourceIndex = 0;\n\t\tthis.prevSourceLine = 0;\n\t\tthis.prevSourceColumn = 0;\n\t\tthis.prevNameIndex = 0;\n\t}\n\tendLine(segments) {\n\t\tthis.lines.push(segments);\n\t\tthis.buffered += segments.length + 1;\n\t\tif (this.buffered >= 4096) this.drain(null);\n\t}\n\tsegments(segments) {\n\t\tthis.drain(segments);\n\t}\n\tfinish(segments) {\n\t\tthis.drain(segments);\n\t\tthis.flush();\n\t\treturn this.out;\n\t}\n\tdrain(trailing) {\n\t\tconst lines = this.lines;\n\t\tconst lineCount = lines.length;\n\t\tfor (let l = 0; l <= lineCount; l++) {\n\t\t\tconst line = l < lineCount ? lines[l] : trailing;\n\t\t\tif (line === null) break;\n\t\t\tfor (let i = 0; i < line.length; i++) {\n\t\t\t\tif (this.pos > FLUSH_THRESHOLD) this.flush();\n\t\t\t\tconst segment = line[i];\n\t\t\t\tif (this.needsComma) scratch[this.pos++] = COMMA;\n\t\t\t\tthis.needsComma = true;\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[0] - this.prevGenColumn);\n\t\t\t\tthis.prevGenColumn = segment[0];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[1] - this.prevSourceIndex);\n\t\t\t\tthis.prevSourceIndex = segment[1];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[2] - this.prevSourceLine);\n\t\t\t\tthis.prevSourceLine = segment[2];\n\t\t\t\tthis.pos = writeVlq(this.pos, segment[3] - this.prevSourceColumn);\n\t\t\t\tthis.prevSourceColumn = segment[3];\n\t\t\t\tif (segment.length === 5) {\n\t\t\t\t\tthis.pos = writeVlq(this.pos, segment[4] - this.prevNameIndex);\n\t\t\t\t\tthis.prevNameIndex = segment[4];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (l < lineCount) {\n\t\t\t\tif (this.pos > FLUSH_THRESHOLD) this.flush();\n\t\t\t\tscratch[this.pos++] = SEMICOLON;\n\t\t\t\tthis.needsComma = false;\n\t\t\t\tthis.prevGenColumn = 0;\n\t\t\t}\n\t\t}\n\t\tlines.length = 0;\n\t\tthis.buffered = 0;\n\t\tthis.flush();\n\t}\n\tflush() {\n\t\tthis.out += decoder.decode(scratch.subarray(0, this.pos));\n\t\tthis.pos = 0;\n\t}\n};\n//#endregion\n//#region src/utils/Mappings.ts\nconst NEWLINE_CHAR$1 = 10;\nfunction isWordCode(code) {\n\treturn code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 48 && code <= 57 || code === 95;\n}\nvar Mappings = class {\n\tconstructor(hires, encoder = null) {\n\t\tthis.hires = hires;\n\t\tthis.generatedCodeLine = 0;\n\t\tthis.generatedCodeColumn = 0;\n\t\tthis.raw = [];\n\t\tthis.rawSegments = this.raw[this.generatedCodeLine] = [];\n\t\tthis.rawRangeMappings = [];\n\t\tthis.rawRangeMappingsIndices = this.rawRangeMappings[this.generatedCodeLine] = [];\n\t\tthis.encoder = encoder;\n\t}\n\tnextLine() {\n\t\tif (this.encoder === null) {\n\t\t\tthis.generatedCodeLine += 1;\n\t\t\tthis.raw[this.generatedCodeLine] = this.rawSegments = [];\n\t\t} else {\n\t\t\tthis.encoder.endLine(this.rawSegments);\n\t\t\tthis.rawSegments = [];\n\t\t\tthis.generatedCodeLine += 1;\n\t\t}\n\t\tthis.generatedCodeColumn = 0;\n\t\tthis.rawRangeMappings[this.generatedCodeLine] = this.rawRangeMappingsIndices = [];\n\t}\n\taddEdit(sourceIndex, content, loc, nameIndex) {\n\t\tif (content.length) {\n\t\t\tconst contentLengthMinusOne = content.length - 1;\n\t\t\tlet contentLineEnd = content.indexOf(\"\\n\", 0);\n\t\t\tlet previousContentLineEnd = -1;\n\t\t\twhile (contentLineEnd >= 0 && contentLengthMinusOne > contentLineEnd) {\n\t\t\t\tconst segment = [\n\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\tsourceIndex,\n\t\t\t\t\tloc.line,\n\t\t\t\t\tloc.column\n\t\t\t\t];\n\t\t\t\tif (nameIndex >= 0) segment.push(nameIndex);\n\t\t\t\tthis.rawSegments.push(segment);\n\t\t\t\tthis.nextLine();\n\t\t\t\tpreviousContentLineEnd = contentLineEnd;\n\t\t\t\tcontentLineEnd = content.indexOf(\"\\n\", contentLineEnd + 1);\n\t\t\t}\n\t\t\tconst segment = [\n\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\tsourceIndex,\n\t\t\t\tloc.line,\n\t\t\t\tloc.column\n\t\t\t];\n\t\t\tif (nameIndex >= 0) segment.push(nameIndex);\n\t\t\tthis.rawSegments.push(segment);\n\t\t\tthis.advance(content.slice(previousContentLineEnd + 1));\n\t\t}\n\t}\n\taddUneditedChunk(sourceIndex, chunk, original, loc, sourcemapLocations) {\n\t\tconst end = chunk.end;\n\t\tlet i = chunk.start;\n\t\tif (this.hires) {\n\t\t\tconst boundary = this.hires === \"boundary\";\n\t\t\tconst experimentalRange = this.hires === \"experimental-range\";\n\t\t\tconst encoder = experimentalRange ? null : this.encoder;\n\t\t\tlet charInHiresBoundary = false;\n\t\t\twhile (i < end) {\n\t\t\t\tif (encoder !== null && this.rawSegments.length >= 4096) {\n\t\t\t\t\tencoder.segments(this.rawSegments);\n\t\t\t\t\tthis.rawSegments.length = 0;\n\t\t\t\t}\n\t\t\t\tif (experimentalRange && i + 1 >= end) this.rawSegments.push([\n\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\tsourceIndex,\n\t\t\t\t\tloc.line,\n\t\t\t\t\tloc.column\n\t\t\t\t]);\n\t\t\t\tconst code = original.charCodeAt(i);\n\t\t\t\tif (code === NEWLINE_CHAR$1) {\n\t\t\t\t\tloc.line += 1;\n\t\t\t\t\tloc.column = 0;\n\t\t\t\t\tthis.nextLine();\n\t\t\t\t\tcharInHiresBoundary = false;\n\t\t\t\t} else {\n\t\t\t\t\tif (boundary) {\n\t\t\t\t\t\tif (isWordCode(code)) {\n\t\t\t\t\t\t\tif (!charInHiresBoundary) {\n\t\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t\tcharInHiresBoundary = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\tcharInHiresBoundary = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (experimentalRange) {\n\t\t\t\t\t\tif (i === chunk.start) {\n\t\t\t\t\t\t\tthis.rawRangeMappingsIndices.push(this.rawSegments.length);\n\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\tloc.column\n\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else this.rawSegments.push([\n\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\tloc.column\n\t\t\t\t\t]);\n\t\t\t\t\tloc.column += 1;\n\t\t\t\t\tthis.generatedCodeColumn += 1;\n\t\t\t\t}\n\t\t\t\ti += 1;\n\t\t\t}\n\t\t} else {\n\t\t\tconst bits = sourcemapLocations.bits;\n\t\t\twhile (i < end) {\n\t\t\t\tlet newline = original.indexOf(\"\\n\", i);\n\t\t\t\tif (newline === -1 || newline > end) newline = end;\n\t\t\t\tif (newline > i) {\n\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\tthis.generatedCodeColumn,\n\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\tloc.column\n\t\t\t\t\t]);\n\t\t\t\t\tfor (let w = i + 1 >> 5, last = newline - 1 >> 5; w <= last; w++) {\n\t\t\t\t\t\tlet word = bits[w];\n\t\t\t\t\t\tif (!word) continue;\n\t\t\t\t\t\tconst base = w << 5;\n\t\t\t\t\t\twhile (word) {\n\t\t\t\t\t\t\tconst lowest = word & -word;\n\t\t\t\t\t\t\tconst index = base + 31 - Math.clz32(lowest);\n\t\t\t\t\t\t\tif (index > i && index < newline) {\n\t\t\t\t\t\t\t\tconst offset = index - i;\n\t\t\t\t\t\t\t\tthis.rawSegments.push([\n\t\t\t\t\t\t\t\t\tthis.generatedCodeColumn + offset,\n\t\t\t\t\t\t\t\t\tsourceIndex,\n\t\t\t\t\t\t\t\t\tloc.line,\n\t\t\t\t\t\t\t\t\tloc.column + offset\n\t\t\t\t\t\t\t\t]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tword ^= lowest;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tloc.column += newline - i;\n\t\t\t\t\tthis.generatedCodeColumn += newline - i;\n\t\t\t\t}\n\t\t\t\tif (newline === end) break;\n\t\t\t\tloc.line += 1;\n\t\t\t\tloc.column = 0;\n\t\t\t\tthis.nextLine();\n\t\t\t\ti = newline + 1;\n\t\t\t}\n\t\t}\n\t}\n\tadvance(str) {\n\t\tif (!str) return;\n\t\tconst lastNewline = str.lastIndexOf(\"\\n\");\n\t\tfor (let i = str.indexOf(\"\\n\"); i !== -1; i = str.indexOf(\"\\n\", i + 1)) this.nextLine();\n\t\tthis.generatedCodeColumn += str.length - lastNewline - 1;\n\t}\n};\n//#endregion\n//#region src/MagicString.ts\nconst n = \"\\n\";\nconst NEWLINE_CHAR = \"\\n\".charCodeAt(0);\nconst CR_CHAR = \"\\r\".charCodeAt(0);\nconst warned = {\n\tinsertLeft: false,\n\tinsertRight: false,\n\tstoreName: false\n};\n/**\n* Expands the `$` substitution patterns that `String.prototype.replace` accepts\n* in a string replacement.\n* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter\n*\n* `captures` holds the capture groups in order, so `captures[0]` is `$1`.\n* `namedCaptures` is `undefined` when the pattern has no named groups, and\n* `$<name>` is then literal text - which is also the case for a string search\n* value, where there are no groups of either kind.\n*/\nfunction expandReplacement(replacement, matched, position, str, captures, namedCaptures) {\n\tif (!replacement.includes(\"$\")) return replacement;\n\tlet result = \"\";\n\tlet index = 0;\n\twhile (index < replacement.length) {\n\t\tconst dollar = replacement.indexOf(\"$\", index);\n\t\tif (dollar === -1) {\n\t\t\tresult += replacement.slice(index);\n\t\t\tbreak;\n\t\t}\n\t\tresult += replacement.slice(index, dollar);\n\t\tconst char = replacement[dollar + 1];\n\t\tlet expansion = \"$\";\n\t\tlet consumed = 1;\n\t\tif (char === \"$\") consumed = 2;\n\t\telse if (char === \"&\") {\n\t\t\texpansion = matched;\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"`\") {\n\t\t\texpansion = str.slice(0, position);\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"'\") {\n\t\t\texpansion = str.slice(position + matched.length);\n\t\t\tconsumed = 2;\n\t\t} else if (char === \"<\" && namedCaptures !== void 0) {\n\t\t\tconst close = replacement.indexOf(\">\", dollar + 2);\n\t\t\tif (close !== -1) {\n\t\t\t\texpansion = namedCaptures[replacement.slice(dollar + 2, close)] ?? \"\";\n\t\t\t\tconsumed = close + 1 - dollar;\n\t\t\t}\n\t\t} else if (char >= \"0\" && char <= \"9\") {\n\t\t\tconst second = replacement[dollar + 2];\n\t\t\tconst double = second >= \"0\" && second <= \"9\" ? Number(char + second) : NaN;\n\t\t\tconst single = Number(char);\n\t\t\tif (double >= 1 && double <= captures.length) {\n\t\t\t\texpansion = captures[double - 1] ?? \"\";\n\t\t\t\tconsumed = 3;\n\t\t\t} else if (single >= 1 && single <= captures.length) {\n\t\t\t\texpansion = captures[single - 1] ?? \"\";\n\t\t\t\tconsumed = 2;\n\t\t\t}\n\t\t}\n\t\tresult += expansion;\n\t\tindex = dollar + consumed;\n\t}\n\treturn result;\n}\nvar MagicString = class MagicString {\n\tconstructor(string, options = {}) {\n\t\tconst chunk = new Chunk(0, string.length, string);\n\t\tObject.defineProperties(this, {\n\t\t\toriginal: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: string\n\t\t\t},\n\t\t\toutro: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: \"\"\n\t\t\t},\n\t\t\tintro: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: \"\"\n\t\t\t},\n\t\t\tfirstChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tlastChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tlastSearchedChunk: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: chunk\n\t\t\t},\n\t\t\tbyStart: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: /* @__PURE__ */ new Map([[0, chunk]])\n\t\t\t},\n\t\t\tbyEnd: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: /* @__PURE__ */ new Map([[string.length, chunk]])\n\t\t\t},\n\t\t\tfilename: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.filename\n\t\t\t},\n\t\t\tindentExclusionRanges: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.indentExclusionRanges\n\t\t\t},\n\t\t\tsourcemapLocations: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: new BitSet()\n\t\t\t},\n\t\t\tstoredNames: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: {}\n\t\t\t},\n\t\t\tindentStr: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: void 0\n\t\t\t},\n\t\t\tignoreList: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.ignoreList\n\t\t\t},\n\t\t\toffset: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: options.offset || 0\n\t\t\t},\n\t\t\thasMovedChunks: {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: false\n\t\t\t}\n\t\t});\n\t}\n\t/**\n\t* Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is false.\n\t*/\n\taddSourcemapLocation(char) {\n\t\tthis.sourcemapLocations.add(char);\n\t}\n\t/**\n\t* Appends the specified content to the end of the string.\n\t*/\n\tappend(content) {\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis.outro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Appends the specified content at the index in the original string.\n\t* If a range *ending* with index is subsequently moved, the insert will be moved with it.\n\t* See also `s.prependLeft(...)`.\n\t*/\n\tappendLeft(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byEnd.get(index);\n\t\tif (chunk) chunk.appendLeft(content);\n\t\telse this.intro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Appends the specified content at the index in the original string.\n\t* If a range *starting* with index is subsequently moved, the insert will be moved with it.\n\t* See also `s.prependRight(...)`.\n\t*/\n\tappendRight(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byStart.get(index);\n\t\tif (chunk) chunk.appendRight(content);\n\t\telse this.outro += content;\n\t\treturn this;\n\t}\n\t/**\n\t* Does what you'd expect.\n\t*/\n\tclone() {\n\t\tconst cloned = new MagicString(this.original, {\n\t\t\tfilename: this.filename,\n\t\t\tignoreList: this.ignoreList,\n\t\t\toffset: this.offset\n\t\t});\n\t\tlet originalChunk = this.firstChunk;\n\t\tlet clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();\n\t\twhile (originalChunk) {\n\t\t\tcloned.byStart.set(clonedChunk.start, clonedChunk);\n\t\t\tcloned.byEnd.set(clonedChunk.end, clonedChunk);\n\t\t\tconst nextOriginalChunk = originalChunk.next;\n\t\t\tconst nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();\n\t\t\tif (nextClonedChunk) {\n\t\t\t\tclonedChunk.next = nextClonedChunk;\n\t\t\t\tnextClonedChunk.previous = clonedChunk;\n\t\t\t\tclonedChunk = nextClonedChunk;\n\t\t\t}\n\t\t\toriginalChunk = nextOriginalChunk;\n\t\t}\n\t\tcloned.lastChunk = clonedChunk;\n\t\tif (this.indentExclusionRanges) cloned.indentExclusionRanges = this.indentExclusionRanges.slice();\n\t\tcloned.sourcemapLocations = new BitSet(this.sourcemapLocations);\n\t\tcloned.storedNames = { ...this.storedNames };\n\t\tcloned.intro = this.intro;\n\t\tcloned.outro = this.outro;\n\t\tcloned.hasMovedChunks = this.hasMovedChunks;\n\t\treturn cloned;\n\t}\n\t/**\n\t* Generates a sourcemap object with raw mappings in array form, rather than encoded as a string.\n\t* Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.\n\t*/\n\tgenerateDecodedMap(options) {\n\t\toptions = options || {};\n\t\tconst mappings = new Mappings(options.hires);\n\t\tconst names = this._generateMappings(mappings);\n\t\treturn {\n\t\t\t...this._mapProperties(options, names),\n\t\t\tmappings: mappings.raw,\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t};\n\t}\n\t/**\n\t* Generates a version 3 sourcemap.\n\t*/\n\tgenerateMap(options) {\n\t\toptions = options || {};\n\t\tconst encoder = new MappingsEncoder();\n\t\tconst mappings = new Mappings(options.hires, encoder);\n\t\tconst names = this._generateMappings(mappings);\n\t\treturn new SourceMap({\n\t\t\t...this._mapProperties(options, names),\n\t\t\tmappings: encoder.finish(mappings.rawSegments),\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t});\n\t}\n\t/** @internal */\n\t_generateMappings(mappings) {\n\t\tconst sourceIndex = 0;\n\t\tconst names = Object.keys(this.storedNames);\n\t\tconst locate = getLocator(this.original);\n\t\tif (this.intro) mappings.advance(this.intro);\n\t\tthis.firstChunk.eachNext((chunk) => {\n\t\t\tconst loc = locate(chunk.start);\n\t\t\tif (chunk.intro.length) mappings.advance(chunk.intro);\n\t\t\tif (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);\n\t\t\telse mappings.addUneditedChunk(sourceIndex, chunk, this.original, loc, this.sourcemapLocations);\n\t\t\tif (chunk.outro.length) mappings.advance(chunk.outro);\n\t\t});\n\t\tif (this.outro) mappings.advance(this.outro);\n\t\treturn names;\n\t}\n\t/** @internal */\n\t_mapProperties(options, names) {\n\t\treturn {\n\t\t\tfile: options.file ? options.file.split(/[/\\\\]/).pop() : void 0,\n\t\t\tsources: [options.source ? getRelativePath(options.file || \"\", options.source) : options.file || \"\"],\n\t\t\tsourcesContent: options.includeContent ? [this.original] : void 0,\n\t\t\tnames,\n\t\t\tx_google_ignoreList: this.ignoreList ? [0] : void 0\n\t\t};\n\t}\n\t/** @internal */\n\t_ensureindentStr() {\n\t\tif (this.indentStr === void 0) this.indentStr = guessIndent(this.original);\n\t}\n\t/** @internal */\n\t_getRawIndentString() {\n\t\tthis._ensureindentStr();\n\t\treturn this.indentStr;\n\t}\n\tgetIndentString() {\n\t\tthis._ensureindentStr();\n\t\treturn this.indentStr === null ? \"\t\" : this.indentStr;\n\t}\n\tindent(indentStr, options) {\n\t\tconst pattern = /^[^\\r\\n]/gm;\n\t\tif (isObject(indentStr)) {\n\t\t\toptions = indentStr;\n\t\t\tindentStr = void 0;\n\t\t}\n\t\tif (indentStr === void 0) {\n\t\t\tthis._ensureindentStr();\n\t\t\tindentStr = this.indentStr || \"\t\";\n\t\t}\n\t\tif (indentStr === \"\") return this;\n\t\tconst resolvedIndentStr = indentStr;\n\t\toptions = options || {};\n\t\tconst isExcluded = {};\n\t\tif (options.exclude) (typeof options.exclude[0] === \"number\" ? [options.exclude] : options.exclude).forEach((exclusion) => {\n\t\t\tfor (let i = exclusion[0]; i < exclusion[1]; i += 1) isExcluded[i] = true;\n\t\t});\n\t\tlet shouldIndentNextCharacter = options.indentStart !== false;\n\t\tconst indentPiece = (str) => {\n\t\t\tif (str === \"\") return str;\n\t\t\tconst indented = str.replace(pattern, (match, offset) => offset > 0 || shouldIndentNextCharacter ? `${resolvedIndentStr}${match}` : match);\n\t\t\tshouldIndentNextCharacter = str[str.length - 1] === \"\\n\";\n\t\t\treturn indented;\n\t\t};\n\t\tthis.intro = indentPiece(this.intro);\n\t\tlet charIndex = 0;\n\t\tlet chunk = this.firstChunk;\n\t\tconst indentAt = (index) => {\n\t\t\tshouldIndentNextCharacter = false;\n\t\t\tif (index === chunk.start) chunk.appendRight(resolvedIndentStr);\n\t\t\telse {\n\t\t\t\tthis._splitChunk(chunk, index);\n\t\t\t\tchunk = chunk.next;\n\t\t\t\tchunk.prependRight(resolvedIndentStr);\n\t\t\t}\n\t\t};\n\t\twhile (chunk) {\n\t\t\tconst end = chunk.end;\n\t\t\tif (!isExcluded[chunk.start]) chunk.intro = indentPiece(chunk.intro);\n\t\t\tif (chunk.edited) {\n\t\t\t\tif (!isExcluded[charIndex]) chunk.content = indentPiece(chunk.content);\n\t\t\t} else if (options.exclude) {\n\t\t\t\tcharIndex = chunk.start;\n\t\t\t\twhile (charIndex < end) {\n\t\t\t\t\tif (!isExcluded[charIndex]) {\n\t\t\t\t\t\tconst char = this.original.charCodeAt(charIndex);\n\t\t\t\t\t\tif (char === NEWLINE_CHAR) shouldIndentNextCharacter = true;\n\t\t\t\t\t\telse if (char !== CR_CHAR && shouldIndentNextCharacter) indentAt(charIndex);\n\t\t\t\t\t}\n\t\t\t\t\tcharIndex += 1;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcharIndex = chunk.start;\n\t\t\t\twhile (charIndex < end) {\n\t\t\t\t\tif (!shouldIndentNextCharacter) {\n\t\t\t\t\t\tconst nextLine = this.original.indexOf(n, charIndex);\n\t\t\t\t\t\tif (nextLine === -1 || nextLine >= end) break;\n\t\t\t\t\t\tshouldIndentNextCharacter = true;\n\t\t\t\t\t\tcharIndex = nextLine + 1;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst char = this.original.charCodeAt(charIndex);\n\t\t\t\t\tif (char === NEWLINE_CHAR || char === CR_CHAR) {\n\t\t\t\t\t\tcharIndex += 1;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tindentAt(charIndex);\n\t\t\t\t\tcharIndex += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!isExcluded[chunk.end - 1]) chunk.outro = indentPiece(chunk.outro);\n\t\t\tcharIndex = chunk.end;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tthis.outro = indentPiece(this.outro);\n\t\treturn this;\n\t}\n\t/** @internal */\n\tinsert() {\n\t\tthrow new MagicStringError(\"insert() is deprecated, use appendLeft() or prependRight()\");\n\t}\n\t/** @internal */\n\tinsertLeft(index, content) {\n\t\tif (!warned.insertLeft) {\n\t\t\tconsole.warn(\"magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead\");\n\t\t\twarned.insertLeft = true;\n\t\t}\n\t\treturn this.appendLeft(index, content);\n\t}\n\t/** @internal */\n\tinsertRight(index, content) {\n\t\tif (!warned.insertRight) {\n\t\t\tconsole.warn(\"magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead\");\n\t\t\twarned.insertRight = true;\n\t\t}\n\t\treturn this.prependRight(index, content);\n\t}\n\t/**\n\t* Moves the characters from `start` and `end` to `index`.\n\t*\n\t* `affinity` controls where the range is anchored at `index`. With the\n\t* default `'right'`, it is inserted before the content that starts at `index`;\n\t* with `'left'`, it is inserted after the content that ends at `index`. The\n\t* two differ only when other content has already been moved to that boundary,\n\t* mirroring the `appendLeft`/`appendRight` distinction.\n\t*/\n\tmove(start, end, index, affinity = \"right\") {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tindex = index + this.offset;\n\t\tif (start === end) return this;\n\t\tif (index >= start && index <= end) throw new MagicStringError(\"cannot move a selection inside itself\");\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tthis._split(index);\n\t\tconst first = this.byStart.get(start);\n\t\tconst last = this.byEnd.get(end);\n\t\tif (this.hasMovedChunks) {\n\t\t\tlet cursor = first;\n\t\t\twhile (cursor !== last) {\n\t\t\t\tcursor = cursor.next;\n\t\t\t\tif (!cursor || cursor.start < start || cursor.end > end) throw new MagicStringError(`cannot move ${start} to ${end} because an earlier move split that range`);\n\t\t\t}\n\t\t}\n\t\tconst oldLeft = first.previous;\n\t\tconst oldRight = last.next;\n\t\tlet newLeft;\n\t\tlet newRight;\n\t\tif (affinity === \"left\") {\n\t\t\tnewLeft = this.byEnd.get(index) ?? null;\n\t\t\tif (!newLeft) {\n\t\t\t\tif (first === this.firstChunk) return this;\n\t\t\t\tnewRight = this.firstChunk;\n\t\t\t} else {\n\t\t\t\tif (newLeft.next === first) return this;\n\t\t\t\tnewRight = newLeft.next;\n\t\t\t}\n\t\t} else {\n\t\t\tnewRight = this.byStart.get(index) ?? null;\n\t\t\tif (!newRight) {\n\t\t\t\tif (last === this.lastChunk) return this;\n\t\t\t\tnewLeft = this.lastChunk;\n\t\t\t} else {\n\t\t\t\tif (newRight.previous === last) return this;\n\t\t\t\tnewLeft = newRight.previous;\n\t\t\t}\n\t\t}\n\t\tif (oldLeft) oldLeft.next = oldRight;\n\t\tif (oldRight) oldRight.previous = oldLeft;\n\t\tif (newLeft) newLeft.next = first;\n\t\tif (newRight) newRight.previous = last;\n\t\tif (!first.previous) this.firstChunk = last.next;\n\t\tif (!last.next) {\n\t\t\tthis.lastChunk = first.previous;\n\t\t\tthis.lastChunk.next = null;\n\t\t}\n\t\tfirst.previous = newLeft;\n\t\tlast.next = newRight || null;\n\t\tif (!newLeft) this.firstChunk = first;\n\t\tif (!newRight) this.lastChunk = last;\n\t\tthis.hasMovedChunks = true;\n\t\treturn this;\n\t}\n\t/**\n\t* Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in\n\t* that range. The same restrictions as `s.remove()` apply.\n\t*\n\t* The fourth argument is optional. It can have a storeName property - if true, the original name will be stored\n\t* for later inclusion in a sourcemap's names array - and a contentOnly property which determines whether only\n\t* the content is overwritten, or anything that was appended/prepended to the range as well.\n\t*\n\t* It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.\n\t*/\n\toverwrite(start, end, content, options) {\n\t\tconst optionObject = typeof options === \"object\" && options ? options : {};\n\t\treturn this.update(start, end, content, {\n\t\t\t...optionObject,\n\t\t\toverwrite: !optionObject.contentOnly\n\t\t});\n\t}\n\t/**\n\t* Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply.\n\t*\n\t* The fourth argument is optional. It can have a storeName property - if true, the original name will be stored\n\t* for later inclusion in a sourcemap's names array - and an overwrite property which determines whether only\n\t* the content is overwritten, or anything that was appended/prepended to the range as well.\n\t*/\n\tupdate(start, end, content, options) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start < 0) throw new MagicStringError(`start ${start} is out of bounds`);\n\t\tif (end > this.original.length) throw new MagicStringError(`end ${end} is out of bounds`);\n\t\tif (start === end) throw new MagicStringError(`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tif (options === true) {\n\t\t\tif (!warned.storeName) {\n\t\t\t\tconsole.warn(\"The final argument to magicString.overwrite(...) should be an options object. See https://github.com/rich-harris/magic-string\");\n\t\t\t\twarned.storeName = true;\n\t\t\t}\n\t\t\toptions = { storeName: true };\n\t\t}\n\t\tconst optionObject = typeof options === \"object\" && options ? options : {};\n\t\tconst storeName = optionObject.storeName || false;\n\t\tconst overwrite = optionObject.overwrite || false;\n\t\tif (storeName) {\n\t\t\tconst original = this.original.slice(start, end);\n\t\t\tObject.defineProperty(this.storedNames, original, {\n\t\t\t\twritable: true,\n\t\t\t\tvalue: true,\n\t\t\t\tenumerable: true\n\t\t\t});\n\t\t}\n\t\tconst first = this.byStart.get(start);\n\t\tconst last = this.byEnd.get(end);\n\t\t/* v8 ignore else -- unreachable: a valid start/end always yields a `first` chunk */\n\t\tif (first) {\n\t\t\tlet chunk = first;\n\t\t\twhile (chunk !== last) {\n\t\t\t\tif (chunk.next !== this.byStart.get(chunk.end)) throw new MagicStringError(\"cannot overwrite across a split point\");\n\t\t\t\tchunk = chunk.next;\n\t\t\t\tchunk.edit(\"\", false);\n\t\t\t}\n\t\t\tfirst.edit(content, storeName, !overwrite);\n\t\t} else {\n\t\t\tconst newChunk = new Chunk(start, end, \"\").edit(content, storeName);\n\t\t\tlast.next = newChunk;\n\t\t\tnewChunk.previous = last;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Prepends the string with the specified content.\n\t*/\n\tprepend(content) {\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis.intro = content + this.intro;\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.appendLeft(...)`, except that the inserted content will go *before* any previous appends or prepends at index\n\t*/\n\tprependLeft(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byEnd.get(index);\n\t\tif (chunk) chunk.prependLeft(content);\n\t\telse this.intro = content + this.intro;\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.appendRight(...)`, except that the inserted content will go *before* any previous appends or prepends at `index`\n\t*/\n\tprependRight(index, content) {\n\t\tindex = index + this.offset;\n\t\tif (typeof content !== \"string\") throw new MagicStringError(`content must be a string, got ${typeof content}`);\n\t\tthis._split(index);\n\t\tconst chunk = this.byStart.get(index);\n\t\tif (chunk) chunk.prependRight(content);\n\t\telse this.outro = content + this.outro;\n\t\treturn this;\n\t}\n\t/**\n\t* Removes the characters from `start` to `end` (of the original string, **not** the generated string).\n\t* Content appended or prepended at positions strictly inside the range is removed with it, while\n\t* content attached at `start` or `end` is preserved — use `s.overwrite(start, end, '')` to remove\n\t* the range including its edge inserts.\n\t* Removing the same content twice, or making removals that partially overlap, will cause an error.\n\t*/\n\tremove(start, end) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start === end) return this;\n\t\tif (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tlet chunk = this.byStart.get(start);\n\t\twhile (chunk) {\n\t\t\tif (chunk.start > start) chunk.intro = \"\";\n\t\t\tif (chunk.end < end) chunk.outro = \"\";\n\t\t\tchunk.edit(\"\", false, true);\n\t\t\tchunk = end > chunk.end ? this.byStart.get(chunk.end) : null;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Reset the modified characters from `start` to `end` (of the original string, **not** the generated string).\n\t*/\n\treset(start, end) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tif (start === end) return this;\n\t\tif (start < 0 || end > this.original.length) throw new MagicStringError(`range ${start}–${end} is out of bounds`);\n\t\tif (start > end) throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`);\n\t\tthis._split(start);\n\t\tthis._split(end);\n\t\tlet chunk = this.byStart.get(start);\n\t\twhile (chunk) {\n\t\t\tchunk.reset();\n\t\t\tchunk = end > chunk.end ? this.byStart.get(chunk.end) : null;\n\t\t}\n\t\treturn this;\n\t}\n\tlastChar() {\n\t\tif (this.outro.length) return this.outro[this.outro.length - 1];\n\t\tlet chunk = this.lastChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.outro.length) return chunk.outro[chunk.outro.length - 1];\n\t\t\tif (chunk.content.length) return chunk.content[chunk.content.length - 1];\n\t\t\tif (chunk.intro.length) return chunk.intro[chunk.intro.length - 1];\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t\tif (this.intro.length) return this.intro[this.intro.length - 1];\n\t\treturn \"\";\n\t}\n\tlastLine() {\n\t\tlet lineIndex = this.outro.lastIndexOf(n);\n\t\tif (lineIndex !== -1) return this.outro.substr(lineIndex + 1);\n\t\tlet lineStr = this.outro;\n\t\tlet chunk = this.lastChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.outro.length > 0) {\n\t\t\t\tlineIndex = chunk.outro.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.outro.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.outro + lineStr;\n\t\t\t}\n\t\t\tif (chunk.content.length > 0) {\n\t\t\t\tlineIndex = chunk.content.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.content.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.content + lineStr;\n\t\t\t}\n\t\t\tif (chunk.intro.length > 0) {\n\t\t\t\tlineIndex = chunk.intro.lastIndexOf(n);\n\t\t\t\tif (lineIndex !== -1) return chunk.intro.substr(lineIndex + 1) + lineStr;\n\t\t\t\tlineStr = chunk.intro + lineStr;\n\t\t\t}\n\t\t\tchunk = chunk.previous;\n\t\t}\n\t\tlineIndex = this.intro.lastIndexOf(n);\n\t\tif (lineIndex !== -1) return this.intro.substr(lineIndex + 1) + lineStr;\n\t\treturn this.intro + lineStr;\n\t}\n\t/**\n\t* Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string.\n\t* Throws error if the indices are for characters that were already removed.\n\t*/\n\tslice(start = 0, end = this.original.length - this.offset) {\n\t\tstart = start + this.offset;\n\t\tend = end + this.offset;\n\t\tif (this.original.length !== 0) {\n\t\t\tif (start < 0) start = Math.max(0, start + this.original.length);\n\t\t\tif (end < 0) end = Math.max(0, end + this.original.length);\n\t\t}\n\t\tlet result = \"\";\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk && (chunk.start > start || chunk.end <= start)) {\n\t\t\tif (chunk.start < end && chunk.end >= end || end === 0 && chunk.start === 0) return result;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tif (chunk && chunk.edited && chunk.start !== start) throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`);\n\t\tconst startChunk = chunk;\n\t\twhile (chunk) {\n\t\t\tif (end === 0 && chunk.start === 0) break;\n\t\t\tif (chunk.intro && (startChunk !== chunk || chunk.start === start)) result += chunk.intro;\n\t\t\tconst containsEnd = chunk.start < end && chunk.end >= end;\n\t\t\tif (containsEnd && chunk.edited && chunk.end !== end) throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`);\n\t\t\tconst sliceStart = startChunk === chunk ? start - chunk.start : 0;\n\t\t\tconst sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;\n\t\t\tresult += chunk.content.slice(sliceStart, sliceEnd);\n\t\t\tif (chunk.outro && (!containsEnd || chunk.end === end)) result += chunk.outro;\n\t\t\tif (containsEnd) break;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn result;\n\t}\n\t/**\n\t* Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.\n\t*/\n\tsnip(start, end) {\n\t\tconst clone = this.clone();\n\t\tclone.remove(0, start);\n\t\tclone.remove(end, clone.original.length);\n\t\treturn clone;\n\t}\n\t/** @internal */\n\t_split(index) {\n\t\tif (this.byStart.get(index) || this.byEnd.get(index)) return;\n\t\tlet chunk = this.lastSearchedChunk;\n\t\tlet previousChunk = chunk;\n\t\tconst searchForward = index > chunk.end;\n\t\twhile (chunk) {\n\t\t\tif (chunk.contains(index)) return this._splitChunk(chunk, index);\n\t\t\tchunk = searchForward ? this.byStart.get(chunk.end) : this.byEnd.get(chunk.start);\n\t\t\tif (chunk === previousChunk) return;\n\t\t\tpreviousChunk = chunk;\n\t\t}\n\t}\n\t/** @internal */\n\t_splitChunk(chunk, index) {\n\t\tif (chunk.edited && chunk.content.length) {\n\t\t\tconst loc = getLocator(this.original)(index);\n\t\t\tthrow new MagicStringError(`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – \"${chunk.original}\")`);\n\t\t}\n\t\tconst newChunk = chunk.split(index);\n\t\tthis.byEnd.set(index, chunk);\n\t\tthis.byStart.set(index, newChunk);\n\t\tthis.byEnd.set(newChunk.end, newChunk);\n\t\tif (chunk === this.lastChunk) this.lastChunk = newChunk;\n\t\tthis.lastSearchedChunk = chunk;\n\t\treturn true;\n\t}\n\t/**\n\t* Returns the generated string.\n\t*/\n\ttoString() {\n\t\tlet str = this.intro;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tstr += chunk.toString();\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn str + this.outro;\n\t}\n\t/**\n\t* Returns true if the resulting source is empty (disregarding white space).\n\t*/\n\tisEmpty() {\n\t\tif (this.intro.length && this.intro.trim()) return false;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.intro.length && chunk.intro.trim() || chunk.content.length && chunk.content.trim() || chunk.outro.length && chunk.outro.trim()) return false;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\tif (this.outro.length && this.outro.trim()) return false;\n\t\treturn true;\n\t}\n\tlength() {\n\t\tlet chunk = this.firstChunk;\n\t\tlet length = 0;\n\t\twhile (chunk) {\n\t\t\tlength += chunk.intro.length + chunk.content.length + chunk.outro.length;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn length;\n\t}\n\t/**\n\t* Removes empty lines from the start and end.\n\t*/\n\ttrimLines() {\n\t\treturn this.trim(\"[\\\\r\\\\n]\");\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the start and end.\n\t*/\n\ttrim(charType) {\n\t\treturn this.trimStart(charType).trimEnd(charType);\n\t}\n\t/** @internal */\n\ttrimEndAborted(charType) {\n\t\tconst rx = new RegExp(`${charType || \"\\\\s\"}+$`);\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\tif (this.outro.length) return true;\n\t\tlet chunk = this.lastChunk;\n\t\tdo {\n\t\t\tconst end = chunk.end;\n\t\t\tconst aborted = chunk.trimEnd(rx);\n\t\t\tif (chunk.end !== end) {\n\t\t\t\tif (this.lastChunk === chunk) this.lastChunk = chunk.next;\n\t\t\t\tthis.byEnd.set(chunk.end, chunk);\n\t\t\t\tthis.byStart.set(chunk.next.start, chunk.next);\n\t\t\t\tthis.byEnd.set(chunk.next.end, chunk.next);\n\t\t\t}\n\t\t\tif (aborted) return true;\n\t\t\tchunk = chunk.previous;\n\t\t} while (chunk);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\treturn this.intro.length > 0;\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the end.\n\t*/\n\ttrimEnd(charType) {\n\t\tthis.trimEndAborted(charType);\n\t\treturn this;\n\t}\n\t/** @internal */\n\ttrimStartAborted(charType) {\n\t\tconst rx = new RegExp(`^${charType || \"\\\\s\"}+`);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (this.intro.length) return true;\n\t\tlet chunk = this.firstChunk;\n\t\tdo {\n\t\t\tconst end = chunk.end;\n\t\t\tconst aborted = chunk.trimStart(rx);\n\t\t\tif (chunk.end !== end) {\n\t\t\t\tif (chunk === this.lastChunk) this.lastChunk = chunk.next;\n\t\t\t\tthis.byEnd.set(chunk.end, chunk);\n\t\t\t\tthis.byStart.set(chunk.next.start, chunk.next);\n\t\t\t\tthis.byEnd.set(chunk.next.end, chunk.next);\n\t\t\t}\n\t\t\tif (aborted) return true;\n\t\t\tchunk = chunk.next;\n\t\t} while (chunk);\n\t\tthis.outro = this.outro.replace(rx, \"\");\n\t\treturn this.outro.length > 0;\n\t}\n\t/**\n\t* Trims content matching `charType` (defaults to `\\s`, i.e. whitespace) from the start.\n\t*/\n\ttrimStart(charType) {\n\t\tthis.trimStartAborted(charType);\n\t\treturn this;\n\t}\n\t/**\n\t* Indicates if the string has been changed.\n\t*/\n\thasChanged() {\n\t\tif (this.intro || this.outro) return true;\n\t\tlet outputIndex = 0;\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.intro || chunk.outro) return true;\n\t\t\tif (!chunk.edited && chunk.start === outputIndex) outputIndex = chunk.end;\n\t\t\telse {\n\t\t\t\tif (!this.original.startsWith(chunk.content, outputIndex)) return true;\n\t\t\t\toutputIndex += chunk.content.length;\n\t\t\t}\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn outputIndex !== this.original.length;\n\t}\n\t/**\n\t* Whether the original range [start, end) has had any of its characters\n\t* removed. `replace`/`replaceAll` search `original`, so a match can land on\n\t* text that is no longer in the output - overwriting it would resurrect the\n\t* removed characters, so such matches are skipped instead.\n\t*\n\t* @internal\n\t*/\n\t_hasRemovedContent(start, end) {\n\t\tlet chunk = this.firstChunk;\n\t\twhile (chunk) {\n\t\t\tif (chunk.content === \"\" && chunk.start < end && chunk.end > start) return true;\n\t\t\tchunk = chunk.next;\n\t\t}\n\t\treturn false;\n\t}\n\t/** @internal */\n\t_replaceRegexp(searchValue, replacement) {\n\t\tfunction getReplacement(match, str) {\n\t\t\tif (typeof replacement === \"string\") return expandReplacement(replacement, match[0], match.index, str, match.slice(1), match.groups);\n\t\t\telse return match.groups === void 0 ? replacement(match[0], ...match.slice(1), match.index, str) : replacement(match[0], ...match.slice(1), match.index, str, match.groups);\n\t\t}\n\t\tconst replaceMatch = (match) => {\n\t\t\t/* v8 ignore next 2 -- `match.index` is always defined for matches from `matchAll` */\n\t\t\tif (match.index == null) return false;\n\t\t\tif (this._hasRemovedContent(match.index, match.index + match[0].length)) return false;\n\t\t\tconst replacement = getReplacement(match, this.original);\n\t\t\tif (replacement === match[0]) return true;\n\t\t\tif (match[0].length === 0) this.appendRight(match.index, replacement);\n\t\t\telse this.overwrite(match.index, match.index + match[0].length, replacement);\n\t\t\treturn true;\n\t\t};\n\t\tif (searchValue.global) {\n\t\t\tsearchValue.lastIndex = 0;\n\t\t\tfor (const match of this.original.matchAll(searchValue)) replaceMatch(match);\n\t\t} else {\n\t\t\tconst match = this.original.match(searchValue);\n\t\t\tif (match && !replaceMatch(match)) {\n\t\t\t\tconst global = new RegExp(searchValue.source, `${searchValue.flags}g`);\n\t\t\t\tfor (const next of this.original.matchAll(global)) if (replaceMatch(next)) break;\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\t/** @internal */\n\t_replaceString(string, replacement) {\n\t\tconst { original } = this;\n\t\tlet index = original.indexOf(string);\n\t\twhile (index !== -1) {\n\t\t\tif (this._hasRemovedContent(index, index + string.length)) {\n\t\t\t\tindex = original.indexOf(string, index + string.length);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof replacement === \"function\") replacement = replacement(string, index, original);\n\t\t\telse replacement = expandReplacement(replacement, string, index, original, [], void 0);\n\t\t\tif (string !== replacement) {\n\t\t\t\tif (string.length === 0) this.appendRight(index, replacement);\n\t\t\t\telse this.overwrite(index, index + string.length, replacement);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* String replacement with RegExp or string.\n\t*/\n\treplace(searchValue, replacement) {\n\t\tif (typeof searchValue === \"string\") return this._replaceString(searchValue, replacement);\n\t\treturn this._replaceRegexp(searchValue, replacement);\n\t}\n\t/** @internal */\n\t_replaceAllString(string, replacement) {\n\t\tconst { original } = this;\n\t\tconst stringLength = string.length;\n\t\tif (stringLength === 0) {\n\t\t\tfor (let index = 0; index <= original.length; index += 1) {\n\t\t\t\tconst _replacement = typeof replacement === \"function\" ? replacement(\"\", index, original) : expandReplacement(replacement, \"\", index, original, [], void 0);\n\t\t\t\tif (_replacement !== \"\") this.appendRight(index, _replacement);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tfor (let index = original.indexOf(string); index !== -1; index = original.indexOf(string, index + stringLength)) {\n\t\t\tif (this._hasRemovedContent(index, index + stringLength)) continue;\n\t\t\tconst previous = original.slice(index, index + stringLength);\n\t\t\tconst _replacement = typeof replacement === \"function\" ? replacement(previous, index, original) : expandReplacement(replacement, previous, index, original, [], void 0);\n\t\t\tif (previous !== _replacement) this.overwrite(index, index + stringLength, _replacement);\n\t\t}\n\t\treturn this;\n\t}\n\t/**\n\t* Same as `s.replace`, but replace all matched strings instead of just one.\n\t*/\n\treplaceAll(searchValue, replacement) {\n\t\tif (typeof searchValue === \"string\") return this._replaceAllString(searchValue, replacement);\n\t\tif (!searchValue.global) throw new MagicStringError(\"replaceAll() requires a global RegExp\");\n\t\treturn this._replaceRegexp(searchValue, replacement);\n\t}\n};\n//#endregion\n//#region src/Bundle.ts\nconst hasOwnProp = Object.prototype.hasOwnProperty;\nvar Bundle = class Bundle {\n\tconstructor(options = {}) {\n\t\tthis.intro = options.intro || \"\";\n\t\tthis.separator = options.separator !== void 0 ? options.separator : \"\\n\";\n\t\tthis.sources = [];\n\t\tthis.uniqueSources = [];\n\t\tthis.uniqueSourceIndexByFilename = {};\n\t}\n\t/**\n\t* Adds the specified source to the bundle, which can either be a `MagicString` object directly,\n\t* or an options object that holds a magic string `content` property and optionally provides\n\t* a `filename` for the source within the bundle, as well as an optional `ignoreList` hint\n\t* (which defaults to `false`). The `filename` is used when constructing the source map for the\n\t* bundle, to identify this `source` in the source map's `sources` field. The `ignoreList` hint\n\t* is used to populate the `x_google_ignoreList` extension field in the source map, which is a\n\t* mechanism for tools to signal to debuggers that certain sources should be ignored by default\n\t* (depending on user preferences).\n\t*/\n\taddSource(source) {\n\t\tif (source instanceof MagicString) return this.addSource({\n\t\t\tcontent: source,\n\t\t\tfilename: source.filename,\n\t\t\tseparator: this.separator\n\t\t});\n\t\tif (!isObject(source) || !source.content) throw new MagicStringError(\"addSource() requires a `content` property that is a MagicString\");\n\t\t[\n\t\t\t\"filename\",\n\t\t\t\"ignoreList\",\n\t\t\t\"indentExclusionRanges\",\n\t\t\t\"separator\"\n\t\t].forEach((option) => {\n\t\t\tif (!hasOwnProp.call(source, option)) source[option] = source.content[option];\n\t\t});\n\t\tif (source.separator === void 0) source.separator = this.separator;\n\t\tif (source.filename) {\n\t\t\tif (!hasOwnProp.call(this.uniqueSourceIndexByFilename, source.filename)) {\n\t\t\t\tthis.uniqueSourceIndexByFilename[source.filename] = this.uniqueSources.length;\n\t\t\t\tthis.uniqueSources.push({\n\t\t\t\t\tfilename: source.filename,\n\t\t\t\t\tcontent: source.content.original\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconst uniqueSource = this.uniqueSources[this.uniqueSourceIndexByFilename[source.filename]];\n\t\t\t\tif (source.content.original !== uniqueSource.content) throw new MagicStringError(`duplicate filename \"${source.filename}\" with different content, use unique filenames`);\n\t\t\t}\n\t\t}\n\t\tthis.sources.push(source);\n\t\treturn this;\n\t}\n\tappend(str, options) {\n\t\tthis.addSource({\n\t\t\tcontent: new MagicString(str),\n\t\t\tseparator: options && options.separator || \"\"\n\t\t});\n\t\treturn this;\n\t}\n\tclone() {\n\t\tconst bundle = new Bundle({\n\t\t\tintro: this.intro,\n\t\t\tseparator: this.separator\n\t\t});\n\t\tthis.sources.forEach((source) => {\n\t\t\tbundle.addSource({\n\t\t\t\tfilename: source.filename,\n\t\t\t\tcontent: source.content.clone(),\n\t\t\t\tignoreList: source.ignoreList,\n\t\t\t\tindentExclusionRanges: source.indentExclusionRanges,\n\t\t\t\tseparator: source.separator\n\t\t\t});\n\t\t});\n\t\treturn bundle;\n\t}\n\t/**\n\t* Flattens the bundle into a single `MagicString`, so the concatenated result can be\n\t* processed further with the full `MagicString` API. The returned string's `original`\n\t* is the concatenation of every source's `original`, and all existing edits, inserts,\n\t* intros, outros and separators are preserved as inserted content, so its `toString()`\n\t* equals the bundle's `toString()` and its sourcemap maps back to that combined original.\n\t*\n\t* Because a `MagicString` maps to a single source, per-source `filename`s are not carried\n\t* over; generate the bundle's map before flattening if you need the multi-source mapping.\n\t*/\n\ttoMagicString() {\n\t\tconst combined = new MagicString(this.sources.map((source) => source.content.original).join(\"\"));\n\t\tlet offset = 0;\n\t\tlet pending = this.intro;\n\t\tlet first = null;\n\t\tlet last = null;\n\t\tconst byStart = /* @__PURE__ */ new Map();\n\t\tconst byEnd = /* @__PURE__ */ new Map();\n\t\tlet hasMovedChunks = false;\n\t\tthis.sources.forEach((source, i) => {\n\t\t\tconst magicString = source.content;\n\t\t\tconst separator = i > 0 ? source.separator !== void 0 ? source.separator : this.separator : \"\";\n\t\t\tif (magicString.original.length === 0) {\n\t\t\t\tpending += separator + magicString.toString();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpending += separator + magicString.intro;\n\t\t\tlet sourceFirst = null;\n\t\t\tlet previous = null;\n\t\t\tlet originalChunk = magicString.firstChunk;\n\t\t\twhile (originalChunk) {\n\t\t\t\tconst chunk = originalChunk.clone();\n\t\t\t\tchunk.start += offset;\n\t\t\t\tchunk.end += offset;\n\t\t\t\tchunk.previous = previous;\n\t\t\t\tchunk.next = null;\n\t\t\t\tif (previous) previous.next = chunk;\n\t\t\t\tbyStart.set(chunk.start, chunk);\n\t\t\t\tbyEnd.set(chunk.end, chunk);\n\t\t\t\tsourceFirst ??= chunk;\n\t\t\t\tprevious = chunk;\n\t\t\t\toriginalChunk = originalChunk.next;\n\t\t\t}\n\t\t\tconst sourceLast = previous;\n\t\t\tsourceFirst.intro = pending + sourceFirst.intro;\n\t\t\tpending = \"\";\n\t\t\tsourceLast.outro += magicString.outro;\n\t\t\tif (last) {\n\t\t\t\tlast.next = sourceFirst;\n\t\t\t\tsourceFirst.previous = last;\n\t\t\t} else first = sourceFirst;\n\t\t\tlast = sourceLast;\n\t\t\tfor (let index = 0; index < magicString.original.length; index += 1) if (magicString.sourcemapLocations.has(index)) combined.sourcemapLocations.add(index + offset);\n\t\t\tObject.keys(magicString.storedNames).forEach((name) => {\n\t\t\t\tObject.defineProperty(combined.storedNames, name, {\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: true,\n\t\t\t\t\tenumerable: true\n\t\t\t\t});\n\t\t\t});\n\t\t\tif (magicString.hasMovedChunks) hasMovedChunks = true;\n\t\t\toffset += magicString.original.length;\n\t\t});\n\t\tif (!first) {\n\t\t\tcombined.intro = pending;\n\t\t\treturn combined;\n\t\t}\n\t\tif (pending) last.outro += pending;\n\t\tcombined.firstChunk = first;\n\t\tcombined.lastChunk = last;\n\t\tcombined.lastSearchedChunk = first;\n\t\tcombined.byStart = byStart;\n\t\tcombined.byEnd = byEnd;\n\t\tcombined.hasMovedChunks = hasMovedChunks;\n\t\treturn combined;\n\t}\n\tgenerateDecodedMap(options = {}) {\n\t\tconst mappings = new Mappings(options.hires);\n\t\tconst { names, x_google_ignoreList } = this._generateMappings(mappings);\n\t\treturn {\n\t\t\t...this._mapProperties(options, names, x_google_ignoreList),\n\t\t\tmappings: mappings.raw,\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t};\n\t}\n\tgenerateMap(options = {}) {\n\t\tconst encoder = new MappingsEncoder();\n\t\tconst mappings = new Mappings(options.hires, encoder);\n\t\tconst { names, x_google_ignoreList } = this._generateMappings(mappings);\n\t\treturn new SourceMap({\n\t\t\t...this._mapProperties(options, names, x_google_ignoreList),\n\t\t\tmappings: encoder.finish(mappings.rawSegments),\n\t\t\trangeMappings: mappings.rawRangeMappings\n\t\t});\n\t}\n\t/** @internal */\n\t_generateMappings(mappings) {\n\t\tconst names = [];\n\t\tlet x_google_ignoreList;\n\t\tthis.sources.forEach((source) => {\n\t\t\tObject.keys(source.content.storedNames).forEach((name) => {\n\t\t\t\tif (!names.includes(name)) names.push(name);\n\t\t\t});\n\t\t});\n\t\tif (this.intro) mappings.advance(this.intro);\n\t\tthis.sources.forEach((source, i) => {\n\t\t\tif (i > 0)\n /* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tmappings.advance(source.separator !== void 0 ? source.separator : this.separator);\n\t\t\tconst sourceIndex = source.filename ? this.uniqueSourceIndexByFilename[source.filename] : -1;\n\t\t\tconst magicString = source.content;\n\t\t\tconst locate = getLocator(magicString.original);\n\t\t\tif (magicString.intro) mappings.advance(magicString.intro);\n\t\t\tmagicString.firstChunk.eachNext((chunk) => {\n\t\t\t\tconst loc = locate(chunk.start);\n\t\t\t\tif (chunk.intro.length) mappings.advance(chunk.intro);\n\t\t\t\tif (source.filename) {\n\t\t\t\t\tif (chunk.edited) mappings.addEdit(sourceIndex, chunk.content, loc, chunk.storeName ? names.indexOf(chunk.original) : -1);\n\t\t\t\t\telse mappings.addUneditedChunk(sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations);\n\t\t\t\t} else mappings.advance(chunk.content);\n\t\t\t\tif (chunk.outro.length) mappings.advance(chunk.outro);\n\t\t\t});\n\t\t\tif (magicString.outro) mappings.advance(magicString.outro);\n\t\t\tif (source.ignoreList && sourceIndex !== -1) {\n\t\t\t\tif (x_google_ignoreList === void 0) x_google_ignoreList = [];\n\t\t\t\tx_google_ignoreList.push(sourceIndex);\n\t\t\t}\n\t\t});\n\t\treturn {\n\t\t\tnames,\n\t\t\tx_google_ignoreList\n\t\t};\n\t}\n\t/** @internal */\n\t_mapProperties(options, names, x_google_ignoreList) {\n\t\treturn {\n\t\t\tfile: options.file ? options.file.split(/[/\\\\]/).pop() : void 0,\n\t\t\tsources: this.uniqueSources.map((source) => {\n\t\t\t\treturn options.file ? getRelativePath(options.file, source.filename) : source.filename;\n\t\t\t}),\n\t\t\tsourcesContent: this.uniqueSources.map((source) => {\n\t\t\t\treturn (typeof options.includeContent === \"function\" ? options.includeContent(source) : options.includeContent) ? source.content : null;\n\t\t\t}),\n\t\t\tnames,\n\t\t\tx_google_ignoreList\n\t\t};\n\t}\n\tgetIndentString() {\n\t\tconst indentStringCounts = {};\n\t\tthis.sources.forEach((source) => {\n\t\t\tconst indentStr = source.content._getRawIndentString();\n\t\t\tif (indentStr === null) return;\n\t\t\tif (!indentStringCounts[indentStr]) indentStringCounts[indentStr] = 0;\n\t\t\tindentStringCounts[indentStr] += 1;\n\t\t});\n\t\treturn Object.keys(indentStringCounts).sort((a, b) => {\n\t\t\treturn indentStringCounts[b] - indentStringCounts[a];\n\t\t})[0] || \"\t\";\n\t}\n\tindent(indentStr) {\n\t\tif (!arguments.length) indentStr = this.getIndentString();\n\t\tif (indentStr === \"\") return this;\n\t\tlet trailingNewline = !this.intro || this.intro.slice(-1) === \"\\n\";\n\t\tthis.sources.forEach((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\tconst indentStart = trailingNewline || i > 0 && /\\r?\\n$/.test(separator);\n\t\t\tsource.content.indent(indentStr, {\n\t\t\t\texclude: source.indentExclusionRanges,\n\t\t\t\tindentStart\n\t\t\t});\n\t\t\ttrailingNewline = source.content.lastChar() === \"\\n\";\n\t\t});\n\t\tif (this.intro) this.intro = indentStr + this.intro.replace(/^[^\\n]/gm, (match, index) => {\n\t\t\treturn index > 0 ? indentStr + match : match;\n\t\t});\n\t\treturn this;\n\t}\n\tprepend(str) {\n\t\tthis.intro = str + this.intro;\n\t\treturn this;\n\t}\n\ttoString() {\n\t\tconst body = this.sources.map((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn (i > 0 ? separator : \"\") + source.content.toString();\n\t\t}).join(\"\");\n\t\treturn this.intro + body;\n\t}\n\tisEmpty() {\n\t\tif (this.intro.length && this.intro.trim()) return false;\n\t\tif (this.sources.some((source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn i > 0 && separator.trim() !== \"\" || !source.content.isEmpty();\n\t\t})) return false;\n\t\treturn true;\n\t}\n\tlength() {\n\t\treturn this.sources.reduce((length, source, i) => {\n\t\t\t/* v8 ignore next -- addSource always normalizes source.separator */\n\t\t\tconst separator = source.separator !== void 0 ? source.separator : this.separator;\n\t\t\treturn length + (i > 0 ? separator.length : 0) + source.content.toString().length;\n\t\t}, this.intro.length);\n\t}\n\ttrimLines() {\n\t\treturn this.trim(\"[\\\\r\\\\n]\");\n\t}\n\ttrim(charType) {\n\t\treturn this.trimStart(charType).trimEnd(charType);\n\t}\n\ttrimStart(charType) {\n\t\tconst rx = new RegExp(`^${charType || \"\\\\s\"}+`);\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\tif (!this.intro) for (let i = 0; i < this.sources.length; i += 1) {\n\t\t\tconst source = this.sources[i];\n\t\t\tif (i > 0) {\n\t\t\t\tsource.separator = (source.separator !== void 0 ? source.separator : this.separator).replace(rx, \"\");\n\t\t\t\tif (source.separator) break;\n\t\t\t}\n\t\t\tif (source.content.trimStartAborted(charType)) break;\n\t\t}\n\t\treturn this;\n\t}\n\ttrimEnd(charType) {\n\t\tconst rx = new RegExp(`${charType || \"\\\\s\"}+$`);\n\t\tfor (let i = this.sources.length - 1; i >= 0; i -= 1) {\n\t\t\tconst source = this.sources[i];\n\t\t\tif (source.content.trimEndAborted(charType)) return this;\n\t\t\tif (i > 0) {\n\t\t\t\tsource.separator = (source.separator !== void 0 ? source.separator : this.separator).replace(rx, \"\");\n\t\t\t\tif (source.separator) return this;\n\t\t\t}\n\t\t}\n\t\tthis.intro = this.intro.replace(rx, \"\");\n\t\treturn this;\n\t}\n};\n//#endregion\nexport { Bundle, MagicString, MagicString as default, MagicStringError, SourceMap };\n","/**\n * Transform-hook logic for the timber-fonts plugin.\n *\n * Scans source files for font function calls (`Inter({...})`,\n * `localFont({...})`), validates that they are statically analysable,\n * registers the extracted fonts in the `FontPipeline`, and rewrites the\n * call sites to static `FontResult` literals so the runtime never has to\n * evaluate the font function.\n *\n * Uses a single OXC (via vite.parseAst) parse of the source file (via `findFontCallSites`)\n * and magic-string for precise source rewrites with source maps.\n *\n * Design doc: 24-fonts.md\n */\n\nimport MagicString from 'magic-string';\nimport type { ExtractedFont, GoogleFontConfig } from './types.ts';\nimport { buildFontStack } from './fallbacks.ts';\nimport { processLocalFont } from './local.ts';\nimport {\n extractFontConfigAst,\n detectDynamicFontCallAst,\n findFontCallSites,\n extractGoogleFontConfigFromNode,\n extractLocalFontConfigFromNode,\n} from './ast.ts';\nimport type { FontPipeline } from './pipeline.ts';\n\n/**\n * Convert a font family name to a scoped class name.\n * e.g. \"JetBrains Mono\" → \"timber-font-jetbrains-mono\"\n */\nfunction familyToClassName(family: string): string {\n return `timber-font-${family.toLowerCase().replace(/\\s+/g, '-')}`;\n}\n\n/** Normalize a string or string array to an array (default `['400']`). */\nfunction normalizeWeightArray(value: string | string[] | undefined): string[] {\n if (!value) return ['400'];\n return Array.isArray(value) ? value : [value];\n}\n\n/** Normalize style to an array (default `['normal']`). */\nfunction normalizeStyleArray(value: string | string[] | undefined): string[] {\n if (!value) return ['normal'];\n return Array.isArray(value) ? value : [value];\n}\n\n/**\n * Generate a unique font ID from family + config hash.\n *\n * The ID intentionally includes every property that affects the rendered\n * `@font-face` output (`weight`, `style`, `subsets`, `display`) so that an\n * HMR edit changing any of those produces a new ID and the registry is\n * forced to re-emit fresh CSS.\n */\nexport function generateFontId(family: string, config: GoogleFontConfig): string {\n const weights = normalizeWeightArray(config.weight);\n const styles = normalizeStyleArray(config.style);\n const subsets = config.subsets ?? ['latin'];\n const display = config.display ?? 'swap';\n return `${family.toLowerCase()}-${weights.join(',')}-${styles.join(',')}-${subsets.join(',')}-${display}`;\n}\n\n/**\n * Extract static font config from a font function call source.\n *\n * Returns `null` if the call cannot be statically analysed.\n */\nexport function extractFontConfig(callSource: string): GoogleFontConfig | null {\n return extractFontConfigAst(callSource);\n}\n\n/**\n * Detect dynamic/computed font function calls that cannot be statically\n * analysed. Returns the offending expression text, or `null` if all calls\n * are static.\n */\nexport function detectDynamicFontCall(source: string, importedNames: string[]): string | null {\n return detectDynamicFontCallAst(source, importedNames);\n}\n\n// ── Regex-free import/family parsing (thin wrappers over AST) ────────────────\n//\n// These keep the public surface stable. They use `findFontCallSites`\n// internally so they agree with the transform on what counts as an import.\n\n/**\n * Parse the local names imported from `@timber/fonts/google` /\n * `next/font/google`. e.g. `import { Inter, JetBrains_Mono as Mono }` →\n * `['Inter', 'Mono']`.\n */\nexport function parseGoogleFontImports(source: string): string[] {\n const analysis = findFontCallSites(source);\n if (!analysis) return [];\n return analysis.bindings.filter((b) => b.provider === 'google').map((b) => b.localName);\n}\n\n/**\n * Parse Google font imports into a `localName → familyName` map.\n *\n * e.g. `import { JetBrains_Mono as Mono }` → `{ Mono: 'JetBrains Mono' }`.\n * The original (pre-`as`) name is converted from PascalCase-with-underscores\n * to the human-readable family name by replacing `_` with a space.\n */\nexport function parseGoogleFontFamilies(source: string): Map<string, string> {\n const analysis = findFontCallSites(source);\n const families = new Map<string, string>();\n if (!analysis) return families;\n for (const b of analysis.bindings) {\n if (b.provider !== 'google') continue;\n const family = b.importedName.replace(/_/g, ' ');\n families.set(b.localName, family);\n }\n return families;\n}\n\n/**\n * Parse the local name used for the default import of `@timber/fonts/local`.\n *\n * Handles either spelling and arbitrary local names:\n * import localFont from '@timber/fonts/local'\n * import myLoader from 'next/font/local'\n */\nexport function parseLocalFontImportName(source: string): string | null {\n const analysis = findFontCallSites(source);\n if (!analysis) return null;\n const localBinding = analysis.bindings.find((b) => b.provider === 'local');\n return localBinding?.localName ?? null;\n}\n\n/** Build the static `FontResult` literal we substitute for a font call. */\nfunction buildFontResultLiteral(extracted: ExtractedFont): string {\n return extracted.variable\n ? `{ className: \"${extracted.className}\", style: { fontFamily: \"${extracted.fontFamily}\" }, variable: \"${extracted.variable}\" }`\n : `{ className: \"${extracted.className}\", style: { fontFamily: \"${extracted.fontFamily}\" } }`;\n}\n\n/** Type for the Vite plugin's `this.error` callback. */\ntype EmitError = (msg: string) => never;\n\n/**\n * Run the timber-fonts transform pass on a single source file.\n *\n * Parses the source once with OXC (via vite.parseAst), walks the AST to find font imports\n * and call sites, then uses magic-string to rewrite call sites to static\n * `FontResult` literals and strip the import declarations. Returns a\n * source map alongside the transformed code.\n *\n * Returns `null` if the file does not import from any font virtual module.\n *\n * Pre-filtering (extension allow-list, node_modules exclusion, and code\n * substring checks) is handled by Vite 8's rolldown-native `transform.filter`\n * in the plugin hook definition (plugins/fonts.ts). See TIM-840, TIM-1147.\n */\nexport function runFontsTransform(\n code: string,\n id: string,\n pipeline: FontPipeline,\n emitError: EmitError\n): { code: string; map: ReturnType<MagicString['generateMap']> } | null {\n // Single parse + AST walk.\n const analysis = findFontCallSites(code);\n if (!analysis) return null;\n\n // Bail on dynamic calls.\n if (analysis.dynamicCall) {\n emitError(\n `Font function calls must be statically analyzable. ` +\n `Found dynamic call: ${analysis.dynamicCall}. ` +\n `Pass a literal object with string/array values instead.`\n );\n }\n\n // Bail on nested font calls (must be module-level).\n if (analysis.nestedCalls.length > 0) {\n const first = analysis.nestedCalls[0];\n emitError(\n `Font function \\`${first.name}()\\` must be called at module scope. ` +\n `Found nested call at line ${first.line}, column ${first.column}. ` +\n `Move the call to the top level of the module.`\n );\n }\n\n // Bail on namespace imports of font modules — the transform cannot\n // rewrite `fonts.Inter(...)` member calls, so the font would silently\n // never load.\n if (analysis.namespaceImports.length > 0) {\n const first = analysis.namespaceImports[0];\n emitError(\n `Namespace imports of font modules are not supported ` +\n `(\\`* as ${first.name}\\` at line ${first.line}, column ${first.column}). ` +\n `Use a named import instead: \\`import { Inter } from 'next/font/google'\\`.`\n );\n }\n\n // Bail on font binding references the transform cannot rewrite\n // (`export default Inter({...})`, object-literal nesting, member access\n // on the call result, aliasing, re-exports). The import declaration is\n // removed, so leaving these would be a silent runtime ReferenceError.\n if (analysis.unsupportedUsages.length > 0) {\n const first = analysis.unsupportedUsages[0];\n emitError(\n `Unsupported usage of font function \\`${first.name}\\` at ` +\n `line ${first.line}, column ${first.column}. ` +\n `A font call must be \\`const x = Font({...})\\` at module scope ` +\n `(export const is fine). The call result cannot be nested in other ` +\n `expressions, and the imported font function cannot be aliased or re-exported.`\n );\n }\n\n if (analysis.callSites.length === 0 && analysis.bindings.length === 0) return null;\n\n const s = new MagicString(code);\n\n // Extract and validate all call sites before mutating the pipeline.\n // If any extraction fails (emitError throws), the pipeline is untouched\n // so the previous valid CSS stays intact (TIM-1087).\n const pending: { extracted: ExtractedFont; site: (typeof analysis.callSites)[0] }[] = [];\n\n for (const site of analysis.callSites) {\n if (site.binding.provider === 'google') {\n const family = site.binding.importedName.replace(/_/g, ' ');\n\n const config = extractGoogleFontConfigFromNode(site.configNode);\n if (!config) {\n emitError(\n `Could not statically analyze font config for ${family} ` +\n `at line ${site.line}, column ${site.column}. ` +\n `Ensure all config values are string literals or arrays of string literals.`\n );\n }\n\n const fontId = generateFontId(family, config!);\n const className = familyToClassName(family);\n const fontStack = buildFontStack(family);\n const display = config!.display ?? 'swap';\n\n pending.push({\n site,\n extracted: {\n id: fontId,\n family,\n provider: 'google',\n weights: normalizeWeightArray(config!.weight),\n styles: normalizeStyleArray(config!.style),\n subsets: config!.subsets ?? ['latin'],\n display,\n variable: config!.variable,\n className,\n fontFamily: fontStack,\n importer: id,\n },\n });\n } else {\n // local font\n const config = extractLocalFontConfigFromNode(site.configNode);\n if (!config) {\n emitError(\n `Could not statically analyze local font config ` +\n `at line ${site.line}, column ${site.column}. ` +\n `Ensure src is a string or array of { path, weight?, style? } objects.`\n );\n }\n\n pending.push({ site, extracted: processLocalFont(config!, id) });\n }\n }\n\n // All extractions succeeded — now prune stale entries and register.\n // Handles family renames and deleted font calls (TIM-1087).\n pipeline.pruneImporter(id);\n for (const { extracted, site } of pending) {\n pipeline.register(extracted);\n s.overwrite(site.replaceStart, site.replaceEnd, buildFontResultLiteral(extracted));\n }\n\n // Remove font import declarations. Use a Set to avoid double-removing\n // when multiple bindings come from the same ImportDeclaration.\n const removedRanges = new Set<string>();\n for (const imp of analysis.importNodesToRemove) {\n const key = `${imp.start}:${imp.end}`;\n if (removedRanges.has(key)) continue;\n removedRanges.add(key);\n\n // Also remove the trailing newline if present.\n let end = imp.end;\n if (code[end] === '\\n') end++;\n else if (code[end] === '\\r' && code[end + 1] === '\\n') end += 2;\n // Also remove a trailing semicolon before the newline.\n if (code[imp.end] === ';') {\n end = imp.end + 1;\n if (code[end] === '\\n') end++;\n else if (code[end] === '\\r' && code[end + 1] === '\\n') end += 2;\n }\n s.remove(imp.start, end);\n }\n\n if (!s.hasChanged()) return null;\n\n // Inject a side-effect import for the per-importer virtual CSS module.\n if (pipeline.size() > 0) {\n const virtualCssId = pipeline.cssIdMap.idFor(id);\n s.prepend(`import '${virtualCssId}';\\n`);\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: true }),\n };\n}\n","/**\n * Dev-mode middleware that serves local font binaries under\n * `/_timber/fonts/<basename>`.\n *\n * Only files registered in the FontPipeline are served, and only by\n * basename — directory traversal and path separators in the requested\n * filename are rejected up front. Font CSS is no longer served here; it\n * goes through Vite's CSS pipeline via virtual modules.\n *\n * Design doc: 24-fonts.md\n */\n\nimport type { ViteDevServer } from 'vite';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { FontPipeline } from './pipeline.ts';\nimport { fontOutputBasename, fontUrlPrefix } from './paths.ts';\n\nconst FONT_MIME_TYPES: Record<string, string> = {\n woff2: 'font/woff2',\n woff: 'font/woff',\n ttf: 'font/ttf',\n otf: 'font/otf',\n eot: 'application/vnd.ms-fontopen',\n};\n\n/**\n * Wire the timber-fonts dev middleware onto a Vite dev server.\n *\n * Returns synchronously after registering the middleware. The pipeline is\n * captured by reference so that fonts registered after `configureServer`\n * runs (during transform) are still resolvable.\n */\nexport function installFontDevMiddleware(\n server: ViteDevServer,\n pipeline: FontPipeline,\n base = '/'\n): void {\n const urlPrefix = `${fontUrlPrefix(base)}/`;\n server.middlewares.use((req, res, next) => {\n const url = req.url;\n if (!url || !url.startsWith(urlPrefix)) return next();\n\n const requestedFilename = url.slice(urlPrefix.length);\n // Reject path traversal attempts and any subdirectory access. We only\n // serve flat basenames out of the registry.\n if (requestedFilename.includes('..') || requestedFilename.includes('/')) {\n res.statusCode = 400;\n res.end('Bad request');\n return;\n }\n\n // Find the matching font file in the registry. We iterate every local\n // font's source list and match by basename. The set is small (one per\n // localFont() call) so this is cheap.\n for (const font of pipeline.fonts()) {\n if (font.provider !== 'local' || !font.localSources) continue;\n for (const src of font.localSources) {\n const basename = fontOutputBasename(src.path);\n if (basename !== requestedFilename && src.hashedBasename !== requestedFilename) continue;\n\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) {\n res.statusCode = 404;\n res.end('Not found');\n return;\n }\n const data = readFileSync(absolutePath);\n const ext = absolutePath.split('.').pop()?.toLowerCase();\n res.setHeader('Content-Type', FONT_MIME_TYPES[ext ?? ''] ?? 'application/octet-stream');\n // Dev URLs are raw (unhashed) basenames — `immutable` is only\n // justified by content hashing (design/24-fonts.md). `no-cache`\n // keeps responses revalidatable so edited fonts update without a\n // hard refresh. Production binaries are content-hashed and served\n // immutable by the platform, not this middleware.\n res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.end(data);\n return;\n }\n }\n\n next();\n });\n}\n","/**\n * Build-output emission for the timber-fonts plugin.\n *\n * Splits the `generateBundle` hook into pure helpers so the plugin shell\n * can stay focused on Vite wiring. The functions here are deliberately\n * Rollup-agnostic — they take an `EmitFile` callback so the plugin can\n * pass `this.emitFile` from the `generateBundle` context.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, normalize } from 'node:path';\nimport type { ManifestFontEntry, BuildManifest } from '../server/build-manifest.ts';\nimport { fontOutputBasename, fontUrlPrefix, FONT_OUTPUT_DIR } from './paths.ts';\n\n/**\n * Minimal shape of the asset descriptor accepted by Rollup's `emitFile`.\n * Declared inline rather than importing from `rollup` to keep `bundle.ts`\n * Rollup-agnostic and avoid pulling the type into the build graph.\n */\ninterface EmittedAsset {\n type: 'asset';\n fileName: string;\n source: string | Uint8Array;\n}\nimport type { FontPipeline } from './pipeline.ts';\nimport type { CachedFont } from './google.ts';\nimport { inferFontFormat } from './local.ts';\n\ntype EmitFile = (asset: EmittedAsset) => string;\ntype EmitWarning = (msg: string) => void;\n\n/** Group cached Google Font binaries by lowercase family name. */\nexport function groupCachedFontsByFamily(\n cachedFonts: readonly CachedFont[]\n): Map<string, CachedFont[]> {\n const cachedByFamily = new Map<string, CachedFont[]>();\n for (const cf of cachedFonts) {\n const key = cf.face.family.toLowerCase();\n const arr = cachedByFamily.get(key) ?? [];\n arr.push(cf);\n cachedByFamily.set(key, arr);\n }\n return cachedByFamily;\n}\n\n/**\n * Emit cached Google Font binaries and local font files into the build\n * output under `_timber/fonts/`. Local files missing on disk produce a\n * warning rather than an error so the build still succeeds.\n *\n * Cached Google Font binaries are deduplicated by `hashedFilename` so\n * each unique file is written exactly once even when multiple font\n * entries share a family (and therefore share `CachedFont` references).\n */\nexport function emitFontAssets(\n pipeline: FontPipeline,\n emitFile: EmitFile,\n warn: EmitWarning\n): void {\n // Cached Google Font binaries (content-hashed, deduped by filename)\n for (const cf of pipeline.uniqueCachedFiles()) {\n emitFile({\n type: 'asset',\n fileName: `${FONT_OUTPUT_DIR}/${cf.hashedFilename}`,\n source: cf.data,\n });\n }\n\n // Local font files (content-hashed for immutable caching)\n for (const font of pipeline.fonts()) {\n if (font.provider !== 'local' || !font.localSources) continue;\n for (const src of font.localSources) {\n const absolutePath = normalize(resolve(src.path));\n if (!existsSync(absolutePath)) {\n warn(`Local font file not found: ${absolutePath}`);\n continue;\n }\n const filename = src.hashedBasename ?? fontOutputBasename(src.path);\n const data = readFileSync(absolutePath);\n emitFile({\n type: 'asset',\n fileName: `${FONT_OUTPUT_DIR}/${filename}`,\n source: data,\n });\n }\n }\n}\n\n/**\n * Populate `buildManifest.fonts` with `ManifestFontEntry[]` keyed by the\n * absolute importer path. This matches the runtime route manifest's\n * `filePath` values (which are absolute) and is consistent with how\n * `buildManifest.css` keys work after TIM-1014.\n *\n * All font binaries use content-hashed filenames for immutable caching.\n * Hrefs are prefixed with Vite's resolved `base` so they match the URLs\n * the platform serves the emitted binaries under.\n */\nexport function writeFontManifest(\n pipeline: FontPipeline,\n buildManifest: BuildManifest,\n base = '/'\n): void {\n const urlPrefix = fontUrlPrefix(base);\n const fontsByImporter = new Map<string, ManifestFontEntry[]>();\n\n for (const entry of pipeline.entries()) {\n const manifestEntries = fontsByImporter.get(entry.importer) ?? [];\n\n if (entry.provider === 'local' && entry.localSources) {\n for (const src of entry.localSources) {\n const filename = src.hashedBasename ?? fontOutputBasename(src.path);\n const format = inferFontFormat(src.path);\n manifestEntries.push({\n href: `${urlPrefix}/${filename}`,\n format,\n crossOrigin: 'anonymous',\n });\n }\n } else if (entry.cachedFiles) {\n for (const cf of entry.cachedFiles) {\n manifestEntries.push({\n href: `${urlPrefix}/${cf.hashedFilename}`,\n format: 'woff2',\n crossOrigin: 'anonymous',\n });\n }\n }\n\n fontsByImporter.set(entry.importer, manifestEntries);\n }\n\n for (const [importer, entries] of fontsByImporter) {\n buildManifest.fonts[importer] = entries;\n }\n}\n","/**\n * timber-fonts — Vite sub-plugin shell for build-time font processing.\n *\n * This file is intentionally thin: it wires the Vite plugin hooks to the\n * pipeline + per-concern modules under `../fonts/`. All real logic lives\n * in:\n *\n * - `../fonts/pipeline.ts` — `FontPipeline` (state, mutators)\n * - `../fonts/transform.ts` — transform-hook logic, parsing helpers\n * - `../fonts/dev-middleware.ts` — dev font binary server\n * - `../fonts/virtual-modules.ts` — virtual module ID constants + source\n *\n * The public exports below are the stable API that the test suite and\n * other parts of the framework import. Anything new should be added to\n * one of the per-concern modules and re-exported here only if external\n * consumers need it.\n *\n * Design doc: 24-fonts.md\n */\n\nimport { parseAst } from 'vite';\nimport type { Plugin, ResolvedConfig, ViteDevServer } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport {\n downloadAndCacheFonts,\n generateProductionFontFaces,\n resolveDevFontFaces,\n} from '../fonts/google.ts';\nimport { FONT_OUTPUT_DIR, fontUrlPrefix } from '../fonts/paths.ts';\nimport { FontPipeline } from '../fonts/pipeline.ts';\nimport { runFontsTransform } from '../fonts/transform.ts';\nimport { installFontDevMiddleware } from '../fonts/dev-middleware.ts';\nimport { emitFontAssets, writeFontManifest, groupCachedFontsByFamily } from '../fonts/bundle.ts';\nimport {\n RESOLVED_GOOGLE,\n RESOLVED_LOCAL,\n VIRTUAL_GOOGLE,\n VIRTUAL_LOCAL,\n generateGoogleVirtualModule,\n generateLocalVirtualModule,\n} from '../fonts/virtual-modules.ts';\n\n// ── Public re-exports ────────────────────────────────────────────────────\n//\n// These exports are part of the stable surface area imported by tests and\n// downstream consumers. Do NOT change their names or signatures without\n// updating every caller. New helpers should be added to the per-concern\n// module first and re-exported here only if external code needs them.\n\nexport { FontPipeline } from '../fonts/pipeline.ts';\nexport {\n generateFontId,\n extractFontConfig,\n detectDynamicFontCall,\n parseGoogleFontImports,\n parseGoogleFontFamilies,\n parseLocalFontImportName,\n} from '../fonts/transform.ts';\n\n/**\n * What the post-build phase asks of the font plugin (plugins/post-build.ts).\n * Called after every environment has been built, so the font entries are\n * complete — no environment's `generateBundle` has to run after the build\n * manifest exists.\n */\nexport interface FontsBuildStep {\n /** Write this build's font entries into the build manifest. */\n contributeManifest(manifest: BuildManifest): void;\n /**\n * Directories of the client bundle this build filled with content-hashed\n * font binaries — `[FONT_OUTPUT_DIR]` when any were emitted, else none.\n */\n immutableDirs(): string[];\n}\n\n/**\n * Create the timber-fonts Vite plugin.\n */\nexport function timberFonts(ctx: PluginContext): Plugin & { api: FontsBuildStep } {\n const pipeline = new FontPipeline({ hashOnRegister: !ctx.dev });\n /** Whether the client environment emitted a binary this build. */\n let emittedToClient = false;\n\n return {\n name: 'timber-fonts',\n\n api: {\n contributeManifest: (manifest) => writeFontManifest(pipeline, manifest, ctx.base),\n immutableDirs: () => (emittedToClient ? [FONT_OUTPUT_DIR] : []),\n },\n\n /**\n * Push Vite's resolved `base` into the pipeline so every font URL it\n * emits (@font-face src, manifest hrefs, dev middleware matching)\n * carries the prefix. Emitted file locations are unaffected — only URLs.\n *\n * `config.base` is read here rather than `ctx.base`: this plugin is\n * `enforce: 'pre'`, so its configResolved runs before timber-root-sync\n * populates `ctx.base`. Every *later* hook reads `ctx.base` — the single\n * copy (TIM-1261).\n */\n configResolved(config: ResolvedConfig) {\n pipeline.setBase(config.base);\n\n // Font binaries are emitted in generateBundle, after Vite's CSS\n // url() resolution runs. The warnings are benign — suppress them.\n const originalWarnOnce = config.logger.warnOnce.bind(config.logger);\n config.logger.warnOnce = (msg, options) => {\n if (msg.includes('_timber/fonts/') && msg.includes(\"didn't resolve at build time\")) return;\n originalWarnOnce(msg, options);\n };\n },\n\n /**\n * `enforce: 'pre'` is load-bearing for the font CSS pipeline (TIM-828).\n *\n * The transform hook injects a side-effect\n * `import 'virtual:timber-font-css/<hash>.css'` into every file that\n * registers a font. @vitejs/plugin-rsc's `rsc:rsc-css-export-transform`\n * later inspects each server component's source for CSS imports and\n * wraps the default export in `import.meta.viteRsc.loadCss(...)` so\n * the matched virtual CSS module ends up `preinit`'d as\n * `<link rel=\"stylesheet\" data-rsc-css-href=...>`.\n *\n * If timber-fonts ran in normal order it would inject the CSS import\n * *after* plugin-rsc had already scanned the source, and the font CSS\n * would be silently dropped from the rendered HTML. Running in the\n * `pre` slot guarantees our injected import is visible to plugin-rsc's\n * later CSS-export scan.\n */\n enforce: 'pre',\n\n /**\n * Resolve `@timber/fonts/google`, `@timber/fonts/local`, and the\n * per-importer `virtual:timber-font-css/<hash>.css` modules injected\n * by the transform hook.\n *\n * Strips the `\\0` prefix added by the RSC plugin's re-imports and the\n * absolute root prefix added by SSR build entries before comparing\n * against the public IDs. The `.css` suffix on font-css ids is\n * preserved so Vite's CSS pipeline (`isCSSRequest`) recognises the\n * resolved id as CSS.\n */\n resolveId(id: string) {\n let cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n const qIdx = cleanId.indexOf('?');\n const query = qIdx !== -1 ? cleanId.slice(qIdx) : '';\n if (qIdx !== -1) cleanId = cleanId.slice(0, qIdx);\n if (cleanId.startsWith(ctx.root)) {\n const stripped = cleanId.slice(ctx.root.length);\n if (stripped.startsWith('/') || stripped.startsWith('\\\\')) {\n cleanId = stripped.slice(1);\n } else {\n cleanId = stripped;\n }\n }\n\n if (cleanId === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;\n if (cleanId === VIRTUAL_LOCAL) return RESOLVED_LOCAL;\n // Preserve query suffix (notably `?direct`) on the resolved CSS id.\n // Vite's transform middleware appends `?direct` when the browser\n // fetches the URL as a `<link rel=\"stylesheet\">`, and the CSS plugin\n // only skips its JS-wrapping step when `isDirectCSSRequest(id)` sees\n // that query on the resolved id. Dropping it here caused virtual\n // font CSS to be served as Vite's HMR JS shim, leaving the\n // `<link>`-loaded stylesheet empty (TIM-937 follow-up).\n if (pipeline.cssIdMap.matches(cleanId)) return '\\0' + cleanId + query;\n return null;\n },\n\n /**\n * Return generated source for font virtual modules.\n *\n * The per-importer `virtual:timber-font-css/<hash>.css` modules\n * return the combined font CSS for the specific importer that\n * registered them. Vite's CSS pipeline handles injection from here:\n * in dev the module rides the CSS HMR channel; in production it is\n * emitted as a real CSS asset and @vitejs/plugin-rsc's `collectCss`\n * walks the RSC module graph to find it.\n *\n * Google `@font-face` descriptors are resolved lazily here (both\n * dev and production) because `load` runs after `transform` has\n * registered the font. `buildStart` runs before any transforms,\n * so fonts aren't in the pipeline yet when it fires for the first\n * environment.\n */\n async load(id: string) {\n if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(pipeline.fonts());\n if (id === RESOLVED_LOCAL) return generateLocalVirtualModule();\n\n if (pipeline.cssIdMap.matches(id)) {\n const importer = pipeline.cssIdMap.importerFor(id);\n if (!importer) {\n return '';\n }\n\n // The analyze crawl only needs import edges, not actual font\n // CSS. Return an empty stylesheet so transforms resolve\n // without triggering network fetches or cache writes.\n if (process.env.TIMBER_ANALYZE === '1') {\n return '';\n }\n\n const skipFonts = process.env.TIMBER_SKIP_FONTS === '1';\n\n for (const font of pipeline.googleFonts()) {\n if (font.importer !== importer) continue;\n if (pipeline.hasFaces(font.id)) continue;\n if (skipFonts && !ctx.dev) {\n console.warn(`[timber-fonts] Skipping font \"${font.family}\" (TIMBER_SKIP_FONTS=1)`);\n continue;\n }\n try {\n if (ctx.dev) {\n const faces = await resolveDevFontFaces(font);\n pipeline.attachFaces(font.id, faces);\n } else {\n const cached = await downloadAndCacheFonts([font], ctx.root);\n const byFamily = groupCachedFontsByFamily(cached);\n const familyCached = byFamily.get(font.family.toLowerCase()) ?? [];\n pipeline.attachCachedFiles(font.id, familyCached);\n pipeline.attachFaces(\n font.id,\n generateProductionFontFaces(familyCached, font.display, fontUrlPrefix(ctx.base))\n );\n }\n } catch (e) {\n if (!ctx.dev) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n console.warn(\n `[timber-fonts] Failed to resolve Google font \"${font.family}\": ${msg}. Will retry on next request.`\n );\n }\n }\n\n return pipeline.getCssForSegment(importer);\n }\n return null;\n },\n\n /**\n * Serve local font files in dev mode under `/_timber/fonts/<basename>`.\n * Font CSS goes through Vite's CSS pipeline (virtual modules), not\n * this middleware.\n */\n configureServer(server: ViteDevServer) {\n installFontDevMiddleware(server, pipeline, ctx.base);\n },\n\n /**\n * No-op. Font downloading and face attachment happen lazily in `load()`\n * because `buildStart` runs before `transform` — fonts aren't registered\n * in the pipeline yet when this fires for the first environment.\n *\n * Local font hashing is handled at registration time by the pipeline\n * (when `hashOnRegister` is set) so hashed filenames are available\n * before the virtual CSS `load()` hook runs.\n */\n buildStart() {},\n\n /**\n * Prune stale font entries when a module that previously imported fonts\n * no longer contains any font import. The transform hook's `filter.code`\n * skips such modules, so without this hook the old entries would persist\n * until dev restart. See TIM-1087.\n */\n async hotUpdate({ type, file, read }) {\n if (!pipeline.hasImporter(file)) return;\n if (type === 'delete') {\n pipeline.pruneImporter(file);\n return;\n }\n const code = await read();\n const hasFontImport =\n code.includes('@timber/fonts/') ||\n code.includes('@timber-js/app/fonts/') ||\n code.includes('next/font/');\n if (hasFontImport) return;\n // Only prune if the new source parses successfully. A syntax error\n // means the HMR update will fail and the old module stays active —\n // pruning would leave it without font CSS until the next valid save.\n try {\n parseAst(code, { lang: 'tsx' });\n } catch {\n return;\n }\n pipeline.pruneImporter(file);\n },\n\n /**\n * Scan source files for font function calls and extract static config.\n *\n * Delegates to `runFontsTransform`. Errors raised through the\n * `this.error` callback are surfaced as Vite plugin errors.\n *\n * The `filter` option uses Vite 8's rolldown-native hook filters to\n * skip non-JS/TS files and files that don't mention any font module\n * before crossing into JS — replacing the hand-rolled pre-filter that\n * was previously inside `runFontsTransform` (TIM-840, TIM-1147).\n */\n transform: {\n filter: {\n id: {\n include: /^[^?]*\\.(?:js|jsx|ts|tsx|mjs|cjs|mts|cts)(?:\\?|$)/,\n exclude: /(?:^\\0|(?:^|\\/)node_modules\\/)/,\n },\n code: ['@timber/fonts/', '@timber-js/app/fonts/', 'next/font/'],\n },\n handler(code: string, id: string) {\n return runFontsTransform(code, id, pipeline, (msg) => this.error(msg));\n },\n },\n\n /**\n * Emit font binaries.\n *\n * All font binaries (Google and local) use content-hashed filenames\n * for immutable caching. Font CSS is handled by Vite's CSS pipeline\n * via virtual modules — we only emit binaries here. Manifest entries are\n * written by the post-build phase through `api.contributeManifest`.\n */\n generateBundle() {\n let emitted = 0;\n emitFontAssets(\n pipeline,\n (asset) => {\n emitted++;\n return this.emitFile(asset);\n },\n (msg) => this.warn(msg)\n );\n if (this.environment?.name === 'client') emittedToClient = emitted > 0;\n },\n };\n}\n","/**\n * Shared Flight data script generation.\n *\n * Both html-injectors.ts (Web Streams / dev) and node-stream-transforms.ts\n * (Node streams / production) use this module to generate inline `<script>`\n * tags for RSC Flight data injection.\n *\n * The init script goes in `<head>` as part of the HTML shell (guaranteed\n * to execute before any streaming chunk scripts). Push scripts are emitted\n * as RSC chunks arrive during streaming.\n *\n * Every generator takes the request's CSP nonce (from `getCspNonce()`)\n * so the tags run under a nonce-based `script-src` (TIM-1414).\n *\n * See design/02-rendering-pipeline.md, LOCAL-415\n */\n\nimport { nonceAttr } from './render-utils.ts';\nimport { formStateToBase64 } from '../shared/form-state-flight.ts';\n\n// ─── JSON Escaping ────────────────────────────────────────────────────────\n\n/**\n * Escape a JSON string for safe embedding inside an HTML `<script>` tag.\n *\n * Prevents XSS via `</script>` injection and handles Unicode line/paragraph\n * separators that are valid JSON but invalid in JS string literals (pre-ES2019).\n */\nexport function htmlEscapeJsonString(str: string): string {\n return str\n .replace(/</g, '\\\\u003c')\n .replace(/>/g, '\\\\u003e')\n .replace(/\\u2028/g, '\\\\u2028')\n .replace(/\\u2029/g, '\\\\u2029');\n}\n\n// ─── Script Generation ────────────────────────────────────────────────────\n\n/** The global variable name used for Flight data on the client. */\nconst FLIGHT_VAR = 'self.__timber_f';\n\n/**\n * Generate the init script that creates the Flight data array.\n *\n * This MUST be included in `<head>` (via headHtml) so it executes before\n * any streaming chunk scripts arrive in `<body>`. The array is created\n * unconditionally — no `||[]` guard needed in push scripts.\n *\n * Also emits the bootstrap signal [0] which tells the client that\n * Flight data is active for this page.\n */\nexport function flightInitScript(nonce?: string): string {\n return `<script${nonceAttr(nonce)}>${FLIGHT_VAR}=[${htmlEscapeJsonString(JSON.stringify([0]))}]</script>`;\n}\n\n/**\n * Generate a push script for a Flight data chunk.\n *\n * Normally the init script runs first (it's in `<head>`), so\n * `self.__timber_f` already exists. However, shell-less status pages\n * (e.g. standalone error pages) may have no `<head>` tag, so the init script\n * never runs. The `||[]` guard ensures the array is created on first\n * push if needed, preventing a TypeError. See TIM-559.\n */\nexport function flightChunkScript(data: string, nonce?: string): string {\n const escaped = htmlEscapeJsonString(JSON.stringify([1, data]));\n return `<script${nonceAttr(nonce)}>(${FLIGHT_VAR}=${FLIGHT_VAR}||[]).push(${escaped})</script>`;\n}\n\n/**\n * Generate the script that embeds a no-JS action's form state for\n * hydration: its Flight bytes (server/form-state-flight.ts), as base64. Only\n * a page answering a no-JS action has one. Base64 carries Flight's binary\n * rows, which a text chunk would corrupt, and has no character that can end\n * the script element or the string. See design/08-forms-and-actions.md\n * §\"No-JS Result Round-Trip\".\n */\nexport function formStateScript(bytes: Uint8Array, nonce?: string): string {\n return `<script${nonceAttr(nonce)}>self.__timber_form_state=\"${formStateToBase64(bytes)}\"</script>`;\n}\n","/**\n * timber-static-build — Vite sub-plugin for static output mode.\n *\n * When `output: 'static'` is set in timber.config.ts:\n * 1. The plugin validates that no dynamic APIs (getCookies(), getHeaders())\n * are used\n * 2. `runStaticGeneration`, the static generation step of the post-build\n * phase (plugins/post-build.ts), renders all routes to static HTML + RSC\n * flight files\n *\n * Design doc: design/11-platform.md §\"static output mode\"\n */\n\nimport type { Plugin } from 'vite';\nimport { mkdir, readdir, readFile, writeFile, rename, rm, stat } from 'node:fs/promises';\nimport { createHash, randomUUID } from 'node:crypto';\nimport { dirname, extname, isAbsolute, join, resolve, relative } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { writeFileAtomic } from '../utils/write-file-atomic.ts';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { DirectoryArtifact } from '../adapters/types.ts';\nimport type {\n StaticGenerationOptions,\n StaticGenerationSummary,\n StaticPageEntry,\n StaticRedirectEntry,\n} from '../server/static-generator.ts';\nimport { isRelativeBase, normalizeBasePath, withBasePath } from '../shared/base-path.ts';\nimport type { RscManifest, RscManifestEntry } from '../shared/rsc-manifest.ts';\nimport { htmlEscapeJsonString } from '../server/flight-scripts.ts';\nimport { RSC_PAYLOAD_DIR, rscPayloadPath } from '../shared/rsc-payload-path.ts';\nimport { REDIRECTS_FILE, RESERVED_OUTPUT_PATHS } from '../shared/static-platform-files.ts';\nimport {\n detectFsIdentity,\n fsKey,\n EXACT_FS_IDENTITY,\n type FsIdentity,\n} from '../adapters/fs-identity.ts';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * A single entry in the RSC manifest injected into static HTML.\n * Maps an unhashed `/_rsc/*.rsc` path to its hashed URL, with\n * optional route params inlined to avoid a sidecar fetch.\n */\n// Declared in shared/rsc-manifest.ts so the client that reads this manifest and\n// the build that writes it cannot drift. Re-exported for existing importers.\nexport type { RscManifestEntry, RscManifest } from '../shared/rsc-manifest.ts';\n\nexport interface StaticValidationError {\n type: 'dynamic-api';\n file: string;\n message: string;\n line?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Detection: dynamic APIs (getCookies, getHeaders, and legacy cookies/headers)\n// ---------------------------------------------------------------------------\n\n/**\n * Patterns that indicate dynamic per-request API usage.\n * These are build errors in static mode because there is no request at build time.\n *\n * We detect both import-level and call-level usage.\n */\nconst DYNAMIC_API_PATTERNS: Array<{ pattern: RegExp; name: string }> = [\n { pattern: /\\bgetCookieJar\\s*\\(/, name: 'getCookieJar()' },\n { pattern: /\\bgetHeaders\\s*\\(/, name: 'getHeaders()' },\n { pattern: /\\bcookies\\s*\\(/, name: 'cookies()' },\n { pattern: /\\bheaders\\s*\\(/, name: 'headers()' },\n];\n\n/**\n * Detect usage of dynamic per-request APIs (getCookies(), getHeaders())\n * that cannot work at build time in static mode.\n *\n * Returns an array of validation errors.\n */\nexport function detectDynamicApis(code: string, fileId: string): StaticValidationError[] {\n const errors: StaticValidationError[] = [];\n\n for (const { pattern, name } of DYNAMIC_API_PATTERNS) {\n if (pattern.test(code)) {\n // Find the line number of the first match\n const lines = code.split('\\n');\n let line: number | undefined;\n for (let i = 0; i < lines.length; i++) {\n if (pattern.test(lines[i])) {\n line = i + 1;\n break;\n }\n }\n\n errors.push({\n type: 'dynamic-api',\n file: fileId,\n message:\n `${name} cannot be used in static mode — there is no request at build time. ` +\n `Remove the ${name} call or switch to output: 'server'.`,\n line,\n });\n }\n }\n\n return errors;\n}\n\n// ---------------------------------------------------------------------------\n// Redirect rules\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a `_redirects` file from collected redirect entries.\n * Uses the Cloudflare Pages / Netlify format: `/from /to statusCode`\n *\n * Both sides are base-prefixed (TIM-1274). `from` is matched by the host\n * against the request path and `to` is served to the browser as a `Location`,\n * so both are deployed-URL space while `StaticRedirectEntry` carries route\n * space — under `base: '/repo/'`, a rule `/old /new 301` would match nothing\n * and, if it did, would send the browser off the deployment.\n *\n * An off-origin `to` is left alone: `redirectExternal()` produces an absolute\n * URL, and a protocol-relative one addresses another host too. Neither is a\n * path on this deployment, so neither takes the prefix.\n *\n * @param base Normalized deployment base (see `shared/base-path.ts`).\n * @internal Exported for testing.\n */\nexport function generateRedirectsFile(redirects: StaticRedirectEntry[], base: string): string {\n const target = (to: string) =>\n to.startsWith('/') && !to.startsWith('//') ? withBasePath(base, to) : to;\n const lines = redirects.map((r) => `${withBasePath(base, r.from)} ${target(r.to)} ${r.status}`);\n return lines.join('\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// File output helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Determine the output file path for a static page entry.\n *\n * Pages: /about → about/index.html, / → index.html\n * RSC: /about → _rsc/about/index.rsc, / → _rsc/index.rsc\n * API: /feed.xml → feed.xml, /api/data → api/data\n *\n * The RSC shape mirrors the HTML shape for the reason the HTML shape has it:\n * a route gets a directory and the artifact is the `index` inside it, so the\n * mapping is injective. See `shared/rsc-payload-path.ts` (TIM-1266).\n */\nexport function staticOutputPath(entry: StaticPageEntry): string {\n const urlPath = entry.urlPath === '/' ? '' : entry.urlPath;\n\n if (entry.kind === 'rsc') {\n // Route space is `/…`; the static output path is relative to the output\n // directory, so drop the leading slash.\n return rscPayloadPath(entry.urlPath).slice(1);\n }\n\n if (entry.kind === 'api') {\n // API routes use their URL path directly. If no extension, fall\n // back to the path as-is (static host serves based on content type).\n return urlPath.startsWith('/') ? urlPath.slice(1) : urlPath || 'index';\n }\n\n // HTML pages\n if (!urlPath) return 'index.html';\n // Synthetic 404 entry from static generation — must be 404.html at the\n // root so static hosts (GitHub Pages, Cloudflare Pages, Netlify) serve\n // it automatically for unmatched URLs. Uses an internal urlPath to avoid\n // colliding with a real /404 page route.\n if (urlPath === '/_timber_not_found') return '404.html';\n return `${urlPath.startsWith('/') ? urlPath.slice(1) : urlPath}/index.html`;\n}\n\n// ---------------------------------------------------------------------------\n// Output path collisions (TIM-1266)\n// ---------------------------------------------------------------------------\n\n/**\n * Records which entry claimed each output path and reports second claims.\n *\n * Two entries landing on one path is not a rendering failure — both render\n * fine — so nothing downstream notices. The file is written twice, the second\n * write wins, and the deployment serves one route's bytes at another route's\n * URL with the same content type and the same shape (TIM-1266).\n *\n * The naming rules are injective by construction (a route path is a directory\n * and the artifact is the `index` inside it), so a collision here means either\n * two entries were enumerated for one URL or a route reached a path the\n * framework reserves for itself (`404.html`). Both are build errors: there is\n * no correct file to write.\n *\n * Two entries can also be unwritable together without claiming the same\n * string: one wants a file where the other wants a directory (`about` from an\n * API route, `about/index.html` from a page). The filesystem does refuse that\n * one — `EISDIR` on the rename, `ENOTDIR` on the mkdir, depending on which\n * lands second — but an errno names a path, and in the rename case the path\n * it names is the write's temp file. Reported here instead, so the message says which\n * two routes.\n *\n * Collisions are **collected, not thrown**. `onEntry` runs inside the\n * generator, whose RSC branch treats a throw as \"this payload is unavailable,\n * SPA navigation falls back to a full load\" and swallows it — which for a\n * collision is the wrong end state, since the two payloads are still\n * ambiguous. The caller raises them once generation is done.\n *\n * @internal Exported for testing.\n */\nexport class StaticOutputPaths {\n private readonly claimed = new Map<string, StaticPageEntry>();\n /** Every ancestor directory of a claimed path, mapped to its claimant. */\n private readonly directories = new Map<string, StaticPageEntry>();\n private readonly collisions: string[] = [];\n\n /**\n * @param identity How the output filesystem decides two paths name one\n * file, from `detectFsIdentity`. The guard predicts whether two writes\n * land on one file, which is a property of the filesystem — so it is\n * asked, not assumed. Folding unconditionally would reject `/Foo` beside\n * `/foo` on Linux, where both are perfectly servable files.\n */\n private readonly identity: FsIdentity;\n\n constructor(identity: FsIdentity = EXACT_FS_IDENTITY) {\n this.identity = identity;\n }\n\n /** The identity under which the filesystem will compare this path. */\n private key(relPath: string): string {\n return fsKey(relPath, this.identity);\n }\n\n /**\n * Claim `relPath` for `entry`. Returns false when the path cannot be\n * written alongside an earlier claim, in which case the caller must not\n * write the file — the losing entry is recorded and the build fails at\n * the end.\n */\n claim(relPath: string, entry: StaticPageEntry): boolean {\n // Folded like every other comparison here: on a case-insensitive\n // filesystem a route rendering to `_HEADERS` is the same file the\n // adapter is about to write, so a case-sensitive match would wave it\n // through into the overwrite this reservation exists to stop.\n if (RESERVED_OUTPUT_PATHS.some((name) => this.key(name) === this.key(relPath))) {\n this.collisions.push(\n ` - ${relPath}: reserved — the framework writes this file itself, ` +\n `and ${entry.kind} for ${entry.urlPath} would be overwritten by it`\n );\n return false;\n }\n\n const key = this.key(relPath);\n const conflict =\n this.claimed.get(key) ??\n // This entry wants a file where an earlier one wants a directory…\n this.directories.get(key) ??\n // …or a directory where an earlier one wants a file.\n ancestors(relPath).reduce<StaticPageEntry | undefined>(\n (found, dir) => found ?? this.claimed.get(this.key(dir)),\n undefined\n );\n\n if (conflict) {\n this.collisions.push(\n ` - ${relPath}: ${conflict.kind} for ${conflict.urlPath} and ${entry.kind} for ${entry.urlPath}`\n );\n return false;\n }\n\n this.claimed.set(key, entry);\n for (const dir of ancestors(relPath)) {\n const dirKey = this.key(dir);\n if (!this.directories.has(dirKey)) this.directories.set(dirKey, entry);\n }\n return true;\n }\n\n /** Throw if any two entries could not both be written. */\n assertNoCollisions(): void {\n if (this.collisions.length === 0) return;\n throw new Error(\n `[timber] Static generation: ${this.collisions.length} output path collision(s) — ` +\n `two entries write the same path and one would silently overwrite the other. ` +\n `Rename or remove one route in each pair:\\n${this.collisions.join('\\n')}`\n );\n }\n}\n\n/** Every directory an output path sits under, outermost first. */\nfunction ancestors(relPath: string): string[] {\n const parts = relPath.split('/');\n parts.pop();\n return parts.map((_, i) => parts.slice(0, i + 1).join('/'));\n}\n\n/**\n * Writes generated entries into the static output directory, one file per\n * entry, refusing any write that would land on a path another entry holds.\n *\n * @internal Exported for testing.\n */\nexport class StaticSiteWriter {\n /** Content-Type per URL path for extensionless API routes (TIM-1241). */\n readonly contentTypes: Record<string, string> = {};\n private readonly paths: StaticOutputPaths;\n\n private readonly staticDir: string;\n\n constructor(staticDir: string, identity: FsIdentity = EXACT_FS_IDENTITY) {\n this.staticDir = staticDir;\n this.paths = new StaticOutputPaths(identity);\n }\n\n async write(entry: StaticPageEntry): Promise<void> {\n const relPath = staticOutputPath(entry);\n const fullPath = resolve(this.staticDir, relPath);\n\n // Reject path traversal: generated params with \"../\" could escape\n // the output directory and overwrite build artifacts.\n //\n // Tested on the first *segment*, not on the prefix. A slug is arbitrary\n // application data, and `..draft` is an ordinary directory name whose\n // relative path merely begins with two dots — a prefix test failed the\n // build on it. `isAbsolute` covers the case `relative()` gives up on and\n // returns an absolute path for: a different Windows drive, where the\n // round-trip check below compares equal and would let it through.\n const rel = relative(this.staticDir, fullPath);\n const firstSegment = rel.split(/[\\\\/]/)[0];\n if (firstSegment === '..' || isAbsolute(rel) || resolve(this.staticDir, rel) !== fullPath) {\n throw new Error(\n `[timber] Static generation: output path \"${relPath}\" escapes the ` +\n `static output directory — check generateStaticSegmentParams for ` +\n `path traversal characters in ${entry.urlPath}`\n );\n }\n\n // Claim the *normalized* path, not the one `staticOutputPath` built. Two\n // distinct strings can name one file — a generated param carrying `..`\n // makes `_rsc/a/../b/index.rsc` and `_rsc/b/index.rsc` different keys for\n // the same write, which is the collision this check exists to stop. The\n // traversal guard above only rejects escapes; it lets an in-bounds detour\n // through.\n //\n // A losing claim is not written: the build is about to fail, and\n // clobbering the winner would make the failure state worse than the one\n // being reported.\n if (!this.paths.claim(rel.replace(/\\\\/g, '/'), entry)) return;\n\n await mkdir(dirname(fullPath), { recursive: true });\n await writeFileAtomic(fullPath, entry.body);\n\n // Track Content-Type for extensionless API routes so adapters\n // can write per-path Content-Type rules in _headers. TIM-1241.\n if (entry.kind === 'api' && !extname(relPath) && entry.contentType) {\n this.contentTypes[entry.urlPath] = entry.contentType;\n }\n }\n\n /** Throw if any two entries could not both be written. */\n assertNoCollisions(): void {\n this.paths.assertNoCollisions();\n }\n}\n\n/**\n * Remove artifacts a generation pass produces only *conditionally*, so none\n * of them can survive from an earlier build into this one.\n *\n * Pages are not in this set: every page is rewritten each pass, and a page\n * whose route was deleted is a different problem (a stale file nothing links\n * to) from the one here.\n *\n * - `_rsc/` because the files are content-hashed. Left in place, a previous\n * build's already-hashed payload gets hashed again and accumulates.\n * - `_redirects` because it is written only when this pass found redirects.\n * A build whose redirects were removed would otherwise ship the previous\n * build's rules — and would break the merge exemption in\n * `shared/static-platform-files.ts`, which lets the pre-rendered copy\n * overwrite `public/_redirects` on the grounds that it *contains* it. That\n * holds only for a file the current pass produced (TIM-1266).\n *\n * @internal Exported for testing.\n */\nexport async function cleanConditionalArtifacts(staticDir: string): Promise<void> {\n await rm(join(staticDir, RSC_PAYLOAD_DIR), { recursive: true, force: true }).catch(() => {});\n await rm(join(staticDir, REDIRECTS_FILE), { force: true }).catch(() => {});\n}\n\n// ---------------------------------------------------------------------------\n// Static generation orchestration (runs after Vite build)\n// ---------------------------------------------------------------------------\n\ninterface StaticGenerateModule {\n __timber_generateStaticSite?: (\n options: StaticGenerationOptions\n ) => Promise<StaticGenerationSummary>;\n}\n\n/**\n * A port as Node actually hands it over: `unref()` is a Node addition the DOM\n * lib type does not declare. Optional rather than asserted, so a runtime whose\n * `MessageChannel` has no such method is simply skipped instead of throwing.\n */\ntype ReleasablePort = MessagePort & { unref?: () => void };\n\n/**\n * Run `fn` with `MessageChannel` instrumented, then stop every channel opened\n * while it ran from holding the process open.\n *\n * Static generation is the only build pass that renders **HTML** in the build\n * process: it imports the built app bundle and drives the full SSR pipeline\n * through it. React's scheduler opens a `MessageChannel` at module scope in\n * that bundle (`scheduler`'s DOM build) and never closes it, and a ref'd\n * `MessagePort` keeps Node's event loop alive on its own — so `timber build`\n * finished the site, printed its summary, and then hung forever. Server-mode\n * builds are unaffected because nothing there renders through react-dom.\n *\n * `unref()` is the whole fix: it leaves the port working and only drops the\n * \"keep the process alive\" property. It is applied **after** `fn` resolves, so\n * a render in flight can never be cut short by the process exiting under it —\n * an unref'd port would let Node exit while the scheduler still had a\n * continuation queued, which is a silently truncated page rather than a hang.\n *\n * Nothing renders after this pass. If that ever changes, the release has to\n * move to the end of whatever renders last.\n *\n * @internal Exported for testing.\n */\nexport async function withSchedulerPortsReleased<T>(fn: () => Promise<T>): Promise<T> {\n const opened: ReleasablePort[] = [];\n const OriginalMessageChannel = globalThis.MessageChannel;\n\n globalThis.MessageChannel = class extends OriginalMessageChannel {\n constructor() {\n super();\n opened.push(this.port1, this.port2);\n }\n };\n\n try {\n return await fn();\n } finally {\n globalThis.MessageChannel = OriginalMessageChannel;\n for (const port of opened) port.unref?.();\n }\n}\n\n/** The pre-rendered site a static generation pass wrote. */\nexport interface StaticSite {\n pages: DirectoryArtifact;\n /** Content-Type per URL path for extensionless API outputs (TIM-1241). */\n contentTypes: Record<string, string>;\n /** `[RSC_PAYLOAD_DIR]` when payloads were written and content-hashed, else none. */\n immutableDirs: string[];\n}\n\n/**\n * Load the built RSC entry and run the static generation pass — the static\n * generation step of the post-build phase (plugins/post-build.ts).\n *\n * The build manifest it renders with is already final: the phase merged the\n * RSC assets manifest into it and published it before this step. Unlike\n * prebuilt capture, this needs the FULL pipeline handler, so\n * __TIMBER_CAPTURE_MODE__ must be false.\n *\n * Returns the site only once it is complete, so an adapter is never handed a\n * directory a failed pass left half-written — a failure throws instead.\n */\nexport async function runStaticGeneration(ctx: PluginContext, rscDir: string): Promise<StaticSite> {\n const entryPath = join(rscDir, 'index.js');\n warnUnusableBase(ctx);\n\n // Ensure capture mode is off — we need the full handler.\n (globalThis as Record<string, unknown>).__TIMBER_CAPTURE_MODE__ = false;\n\n console.log('[timber] Static generation: building site…');\n\n const staticDir = join(ctx.buildDir, 'static-pages');\n await cleanConditionalArtifacts(staticDir);\n await mkdir(staticDir, { recursive: true });\n\n const sitemapConfig = ctx.config.sitemap;\n const autoSitemapEnabled = Boolean(sitemapConfig?.enabled && sitemapConfig?.baseUrl);\n\n const writer = new StaticSiteWriter(staticDir, await detectFsIdentity(staticDir));\n // Route params are not collected here any more. They used to be lifted off\n // the generated entry's response headers and inlined into the manifest,\n // because a `.rsc` file carries no headers and the manifest was the only\n // channel a static SPA navigation had (TIM-1255, TIM-1285). The params are\n // now inside the payload itself — a field on its root row — so the `.rsc`\n // file carries them and there is nothing to lift (TIM-1294).\n\n // The app bundle is imported and rendered inside this wrapper, and only\n // inside it: everything it opens to schedule React work is released on the\n // way out so the build process can exit.\n const summary = await withSchedulerPortsReleased(async () => {\n let mod: StaticGenerateModule;\n try {\n const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;\n mod = (await import(/* @vite-ignore */ entryUrl)) as StaticGenerateModule;\n } catch (error) {\n // A missing entry lands here too: the import is the existence check.\n throw new Error(\n `[timber] Static generation: failed to load the built RSC entry (${entryPath}). ` +\n `The full request handler must initialize for static rendering.`,\n { cause: error }\n );\n }\n\n const generate = mod.__timber_generateStaticSite;\n if (typeof generate !== 'function') {\n throw new Error(\n `[timber] Static generation: built RSC entry does not export ` +\n `__timber_generateStaticSite — rebuild from a clean build directory`\n );\n }\n\n return generate({\n autoSitemapEnabled,\n renderTimeoutMs: ctx.config.renderTimeoutMs,\n onEntry: (entry: StaticPageEntry) => writer.write(entry),\n });\n });\n\n const totalUrls = summary.rendered + summary.errors.length;\n console.log(\n `[timber] Static generation: rendered ${summary.rendered}/${totalUrls} entries.` +\n (summary.errors.length > 0 ? ` ${summary.errors.length} failed.` : '') +\n (summary.redirects.length > 0 ? ` ${summary.redirects.length} redirect(s).` : '')\n );\n\n // Warnings are non-fatal but must not be buried in the per-entry log stream —\n // they name a degraded artifact the developer is about to deploy (TIM-1258).\n for (const warning of summary.warnings) {\n console.warn(`[timber] Static generation warning: ${warning}`);\n }\n\n if (summary.errors.length > 0) {\n const details = summary.errors.map((e) => ` - ${e.urlPath}: ${e.message}`).join('\\n');\n throw new Error(`[timber] Static generation failed:\\n${details}`);\n }\n\n // Raised after the render errors above: a collision means the site is\n // ambiguous, not that a page failed, and the message names both routes.\n writer.assertNoCollisions();\n\n // Hash RSC flight payloads for immutable caching (TIM-1254).\n // Renames _rsc/*.rsc → _rsc/*-<hash>.rsc and injects a manifest\n // into each HTML file so the client can resolve hashed URLs.\n // Skip when client JS is disabled — no SPA navigation, no RSC fetches,\n // and injecting a <script> tag would violate the no-JS contract.\n const immutableDirs: string[] = [];\n if (!ctx.clientJavascript.disabled) {\n const rscManifest = await hashRscPayloads(staticDir);\n if (Object.keys(rscManifest).length > 0) {\n immutableDirs.push(RSC_PAYLOAD_DIR);\n await injectRscManifestIntoHtml(staticDir, rscManifest);\n console.log(\n `[timber] Static generation: hashed ${Object.keys(rscManifest).length} RSC flight payloads`\n );\n }\n }\n\n // Write _redirects file for platform redirect rules (Cloudflare Pages,\n // Netlify, etc.). Format: /from /to status. See TIM-1245.\n if (summary.redirects.length > 0) {\n const generated = generateRedirectsFile(summary.redirects, normalizeBasePath(ctx.base));\n const redirectsPath = join(staticDir, REDIRECTS_FILE);\n\n // Merge with user-authored _redirects if present. TIM-1249.\n const userRedirects = await readUserRedirects(ctx.root);\n if (userRedirects !== null) {\n await writeFileAtomic(redirectsPath, generated + '\\n' + userRedirects);\n console.log(\n `[timber] Static generation: wrote _redirects with ${summary.redirects.length} ` +\n `generated rule(s), merged with user-authored _redirects`\n );\n } else {\n await writeFileAtomic(redirectsPath, generated);\n console.log(\n `[timber] Static generation: wrote _redirects with ${summary.redirects.length} rule(s)`\n );\n }\n }\n\n // Content types travel with the site because they describe it: a static\n // host cannot infer the type of an extensionless API output (TIM-1241).\n return { pages: { path: staticDir }, contentTypes: writer.contentTypes, immutableDirs };\n}\n\n// ---------------------------------------------------------------------------\n// Base path validation (TIM-1261)\n// ---------------------------------------------------------------------------\n\n/**\n * Warn when Vite's `base` is document-relative (`'./'`) in static mode.\n *\n * Payload URLs are addressed from the deployment root plus the base prefix.\n * A relative base gives no prefix to compute (see shared/base-path.ts), so\n * `/_rsc/about.rsc` is requested at the domain root — correct only when the\n * site is served from there. The build still succeeds: relative bases work\n * fine for assets, and for a root-served site nothing is wrong. The warning\n * exists so a sub-path deployment does not silently degrade to a hard\n * navigation on every link.\n *\n * Skipped when client JS is disabled — there is no SPA navigation and no\n * payload fetch to mis-address.\n *\n * @internal Exported for testing.\n */\nexport function warnUnusableBase(ctx: PluginContext): void {\n if (ctx.clientJavascript.disabled) return;\n if (!isRelativeBase(ctx.base)) return;\n console.warn(\n `[timber] Static mode: base is \"${ctx.base}\", which is document-relative. ` +\n `RSC payload URLs are addressed from the domain root, so client-side ` +\n `navigation will fall back to a full page load if the site is served ` +\n `from a sub-path. Use an absolute base (e.g. base: '/repo/') to deploy ` +\n `under a sub-path. See design/11-platform.md.`\n );\n}\n\n// ---------------------------------------------------------------------------\n// RSC flight payload hashing (TIM-1254)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute a short content hash for immutable caching.\n * Uses 8 chars of base64url-encoded SHA-256, matching Vite's asset hash style.\n */\nexport function contentHash(data: Buffer | Uint8Array): string {\n return createHash('sha256').update(data).digest('base64url').slice(0, 8);\n}\n\n/**\n * Walk a directory recursively and return all file paths.\n */\nasync function walkDir(dir: string): Promise<string[]> {\n const results: string[] = [];\n let entries;\n try {\n entries = await readdir(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n for (const entry of entries) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) {\n results.push(...(await walkDir(full)));\n } else {\n results.push(full);\n }\n }\n return results;\n}\n\n/**\n * Hash all RSC flight payloads in `_rsc/`, rename them with content\n * hashes, and build a manifest with optional inlined route params.\n *\n * Before: `_rsc/index.rsc`, `_rsc/about.rsc`\n * After: `_rsc/index-B7YxEKdN.rsc`, `_rsc/about-C8ZzFLfO.rsc`\n *\n * The manifest maps the original `_rsc/` URL to an entry object:\n * `{\"/_rsc/index.rsc\":{\"url\":\"/_rsc/index-B7YxEKdN.rsc\"}, ...}`\n *\n * Keys and URLs are **route-space**: root-relative, never carrying Vite's\n * `base`. The client applies the base once, at fetch time\n * (`client/rsc-fetch.ts` → `toStaticRscUrl`), so the generated site stays\n * relocatable and the base has exactly one expression at runtime rather\n * than two that must agree. See TIM-1261.\n *\n * Route params (from `routeParams`) are inlined into the manifest\n * entry, eliminating the need for .params.json sidecar files. TIM-1255.\n *\n * Injected into HTML as:\n * `<script>window.__TIMBER_RSC_MANIFEST__={...}</script>`\n *\n * @internal Exported for testing.\n */\nexport async function hashRscPayloads(staticDir: string): Promise<RscManifest> {\n const rscDir = join(staticDir, RSC_PAYLOAD_DIR);\n const files = await walkDir(rscDir);\n const manifest: RscManifest = {};\n\n for (const filePath of files) {\n if (!filePath.endsWith('.rsc')) continue;\n\n const content = await readFile(filePath);\n const hash = contentHash(content);\n const rel = relative(staticDir, filePath).replace(/\\\\/g, '/');\n\n const base = filePath.slice(0, -'.rsc'.length);\n const hashedPath = `${base}-${hash}.rsc`;\n\n await rename(filePath, hashedPath);\n\n const hashedRel = relative(staticDir, hashedPath).replace(/\\\\/g, '/');\n const key = `/${rel}`;\n manifest[key] = { url: `/${hashedRel}` };\n }\n\n return manifest;\n}\n\n/**\n * Inject the RSC manifest into all HTML files as a `<script>` tag\n * before `</head>`. This lets the client resolve hashed RSC URLs\n * without an extra network request.\n *\n * @internal Exported for testing.\n */\nexport async function injectRscManifestIntoHtml(\n staticDir: string,\n manifest: RscManifest\n): Promise<void> {\n const allFiles = await walkDir(staticDir);\n const htmlFiles = allFiles.filter((f) => f.endsWith('.html'));\n const escapedJson = htmlEscapeJsonString(JSON.stringify(manifest));\n const scriptTag = `<script>window.__TIMBER_RSC_MANIFEST__=${escapedJson}</script>`;\n\n for (const htmlFile of htmlFiles) {\n let html = await readFile(htmlFile, 'utf-8');\n // Insert before </head> so it's available before any client JS runs\n const headClose = html.indexOf('</head>');\n if (headClose !== -1) {\n html = html.slice(0, headClose) + scriptTag + html.slice(headClose);\n } else {\n // Fallback: prepend to body\n html = scriptTag + html;\n }\n await writeFile(htmlFile, html);\n }\n}\n\n// ---------------------------------------------------------------------------\n// User-authored _redirects merge (TIM-1249)\n// ---------------------------------------------------------------------------\n\n/**\n * Read a user-authored `_redirects` file from the project's `public/`\n * directory. Returns `null` if no file exists.\n *\n * @internal Exported for testing.\n */\nexport async function readUserRedirects(root: string): Promise<string | null> {\n const candidates = [join(root, 'public', REDIRECTS_FILE)];\n for (const path of candidates) {\n try {\n return await readFile(path, 'utf-8');\n } catch {\n // File doesn't exist — try next\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Vite Plugin\n// ---------------------------------------------------------------------------\n\n/**\n * Create the timber-static-build Vite plugin.\n *\n * Only active when output: 'static' is configured. Validates source files\n * for static mode violations; rendering the site is `runStaticGeneration`,\n * which the post-build phase calls.\n */\nexport function timberStaticBuild(ctx: PluginContext): Plugin {\n return {\n name: 'timber-static-build',\n\n /**\n * Validate source files during transform.\n *\n * In static mode, we check every app/ file for:\n * - Dynamic API usage (getCookies(), getHeaders()) → build error\n */\n transform(code: string, id: string) {\n // Read ctx.config lazily inside the hook — not at plugin construction\n // time — so file-based config from timber.config.ts is respected.\n // See TIM-451.\n const isStatic = ctx.config.output === 'static';\n\n // Only active in static mode\n if (!isStatic) return null;\n\n // Skip node_modules\n if (id.includes('node_modules')) return null;\n\n // Only check files in the app directory\n if (!id.includes('/app/') && !id.startsWith('app/')) return null;\n\n // Only check JS/TS files\n if (!/\\.[jt]sx?$/.test(id)) return null;\n\n const errors = detectDynamicApis(code, id);\n\n if (errors.length > 0) {\n // Format all errors into a single build error message\n const messages = errors.map(\n (e) =>\n `[timber] Static mode error in ${e.file}${e.line ? `:${e.line}` : ''}: ${e.message}`\n );\n\n this.error(messages.join('\\n\\n'));\n }\n\n return null;\n },\n };\n}\n","/**\n * timber-build-manifest — Vite sub-plugin for build asset manifest generation.\n *\n * Provides `virtual:timber-build-manifest` which exports a BuildManifest\n * mapping route segment file paths to their CSS, JS, and modulepreload\n * output chunks.\n *\n * - Dev mode: exports an empty manifest (Vite HMR handles CSS/JS).\n * - Build mode: virtual module reads from globalThis.__TIMBER_BUILD_MANIFEST__\n * at runtime. The actual manifest data is injected by the adapter via a\n * _timber-manifest-init.js module that runs before the RSC handler.\n *\n * The generateBundle hook (client env only) extracts CSS/JS/modulepreload\n * data from the Rollup bundle and populates ctx.buildManifest.\n *\n * Design docs: 18-build-system.md §\"Build Manifest\", 02-rendering-pipeline.md §\"Early Hints\"\n */\n\nimport { randomUUID, createHash } from 'node:crypto';\nimport { readFileSync } from 'node:fs';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport { EMPTY_BUILD_MANIFEST, type BuildManifest } from '../server/build-manifest.ts';\nimport type { SegmentNode, RouteFile } from '../routing/types.ts';\nimport { isDynamicMetadataExtension } from '../server/metadata-routes.ts';\n\n// Rollup types used by generateBundle hook — imported from vite which re-exports them.\n// We define minimal interfaces here to avoid a direct 'rollup' dependency.\ninterface OutputChunk {\n type: 'chunk';\n fileName: string;\n facadeModuleId: string | null;\n imports: string[];\n name: string;\n code: string;\n viteMetadata?: { importedCss?: Set<string> };\n modules?: Record<string, { code: string | null; renderedLength: number }>;\n}\n\ninterface OutputAsset {\n type: 'asset';\n fileName: string;\n}\n\ntype OutputBundle = Record<string, OutputChunk | OutputAsset>;\n\nconst VIRTUAL_MODULE_ID = 'virtual:timber-build-manifest';\nconst RESOLVED_VIRTUAL_ID = `\\0${VIRTUAL_MODULE_ID}`;\n\n/**\n * Vite's manifest.json entry shape (subset we need).\n * See https://vite.dev/guide/backend-integration.html\n */\ninterface ViteManifestEntry {\n file: string;\n css?: string[];\n imports?: string[];\n}\n\n/**\n * Parse Vite's .vite/manifest.json into a BuildManifest.\n *\n * Walks each entry and collects:\n * - `css`: CSS output URLs per input file (transitive CSS included by Vite)\n * - `js`: Hashed JS chunk URL per input file\n * - `modulepreload`: Transitive JS dependency URLs per input file\n *\n * Keys are input file paths (relative to project root).\n */\nexport function parseViteManifest(\n viteManifest: Record<string, ViteManifestEntry>,\n base: string\n): BuildManifest {\n const css: Record<string, string[]> = {};\n const js: Record<string, string> = {};\n const modulepreload: Record<string, string[]> = {};\n\n for (const [inputPath, entry] of Object.entries(viteManifest)) {\n // JS chunk mapping\n js[inputPath] = base + entry.file;\n\n // CSS mapping\n if (entry.css && entry.css.length > 0) {\n css[inputPath] = entry.css.map((cssPath) => base + cssPath);\n }\n\n // Collect transitive JS dependencies for modulepreload\n modulepreload[inputPath] = collectTransitiveDeps(inputPath, viteManifest, base);\n }\n\n return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };\n}\n\n/**\n * Recursively collect transitive JS dependency URLs for an entry.\n *\n * Walks the `imports` graph in Vite's manifest, resolving each import\n * key to its output `file` URL. Deduplicates to avoid cycles and\n * redundant preloads.\n */\nfunction collectTransitiveDeps(\n entryKey: string,\n manifest: Record<string, ViteManifestEntry>,\n base: string\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n\n function walk(key: string) {\n const entry = manifest[key];\n if (!entry?.imports) return;\n\n for (const importKey of entry.imports) {\n if (seen.has(importKey)) continue;\n seen.add(importKey);\n\n const dep = manifest[importKey];\n if (dep) {\n result.push(base + dep.file);\n walk(importKey);\n }\n }\n }\n\n walk(entryKey);\n return result;\n}\n\n/**\n * Build a BuildManifest from a Rollup output bundle.\n *\n * Unlike parseViteManifest (which reads Vite's manifest.json), this\n * works directly with the Rollup bundle output. This is necessary because\n * the RSC plugin doesn't produce a standard Vite manifest.json.\n *\n * Walks each chunk in the bundle and collects:\n * - `css`: CSS files imported by each chunk (via viteMetadata.importedCss)\n * - `js`: The output filename for each chunk with a facadeModuleId\n * - `modulepreload`: Transitive JS imports for each entry chunk\n *\n * Keys are input file paths relative to root.\n */\nexport function buildManifestFromBundle(\n bundle: OutputBundle,\n base: string,\n root: string\n): BuildManifest {\n const css: Record<string, string[]> = {};\n const js: Record<string, string> = {};\n const modulepreload: Record<string, string[]> = {};\n\n // Build a map of chunk fileName → chunk for transitive dep resolution\n const chunksByFileName = new Map<string, OutputChunk>();\n for (const item of Object.values(bundle) as (OutputChunk | OutputAsset)[]) {\n if (item.type === 'chunk') {\n chunksByFileName.set(item.fileName, item);\n }\n }\n\n for (const item of Object.values(bundle) as (OutputChunk | OutputAsset)[]) {\n if (item.type !== 'chunk') continue;\n\n const chunk = item;\n if (!chunk.facadeModuleId) continue;\n\n // Convert absolute facadeModuleId to root-relative path\n let inputPath = chunk.facadeModuleId;\n if (inputPath.startsWith(root)) {\n inputPath = inputPath.slice(root.length + 1);\n }\n\n // JS chunk mapping\n js[inputPath] = base + chunk.fileName;\n\n // CSS mapping via viteMetadata\n const viteMetadata = chunk.viteMetadata;\n if (viteMetadata?.importedCss && viteMetadata.importedCss.size > 0) {\n css[inputPath] = Array.from(viteMetadata.importedCss).map((cssFile) => base + cssFile);\n }\n\n // Collect transitive JS dependencies for modulepreload\n const deps = collectTransitiveBundleDeps(chunk, chunksByFileName, base);\n if (deps.length > 0) {\n modulepreload[inputPath] = deps;\n }\n }\n\n return { css, js, modulepreload, fonts: {}, metadataRouteHashes: {} };\n}\n\n/**\n * Recursively collect transitive JS dependency URLs from a bundle chunk.\n */\nfunction collectTransitiveBundleDeps(\n chunk: OutputChunk,\n chunksByFileName: Map<string, OutputChunk>,\n base: string\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n\n function walk(imports: string[]) {\n for (const importFileName of imports) {\n if (seen.has(importFileName)) continue;\n seen.add(importFileName);\n\n result.push(base + importFileName);\n const dep = chunksByFileName.get(importFileName);\n if (dep) {\n walk(dep.imports);\n }\n }\n }\n\n walk(chunk.imports);\n return result;\n}\n\n/**\n * Walk the route tree and compute short content hashes for metadata route files\n * (opengraph-image, icon, apple-icon) used for cache-busting\n * the auto-linked URLs in <head>.\n */\nfunction computeMetadataRouteHashes(node: SegmentNode<RouteFile>): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n if (node.metadataRoutes) {\n for (const [baseName, file] of Object.entries(node.metadataRoutes)) {\n if (!isDynamicMetadataExtension(baseName, file.extension)) {\n // For static files, hash the file content\n try {\n const content = readFileSync(file.filePath);\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n hashes[file.filePath] = hash;\n } catch {\n // File unreadable — skip hash, DEV_NONCE fallback applies\n }\n } else {\n // For dynamic files (.ts/.tsx), hash the source file as a reasonable\n // approximation — the output depends on runtime data too, but the\n // source change is the best build-time signal we have.\n try {\n const content = readFileSync(file.filePath);\n const hash = createHash('sha256').update(content).digest('hex').slice(0, 8);\n hashes[file.filePath] = hash;\n } catch {\n // File unreadable — skip\n }\n }\n }\n }\n\n for (const child of node.children) {\n Object.assign(hashes, computeMetadataRouteHashes(child));\n }\n for (const slot of Object.values(node.slots)) {\n Object.assign(hashes, computeMetadataRouteHashes(slot));\n }\n\n return hashes;\n}\n\n// Regex to extract client reference hash keys from registerClientReference calls.\n// Matches: registerClientReference(..., \"abc123def456\", \"ExportName\")\nconst CLIENT_REF_KEY_RE = /registerClientReference\\([^,]+,\\s*\"([0-9a-f]{12})\"/g;\n\n/**\n * Collect all route file paths (layout, page) from the route tree.\n */\nfunction collectRouteFilePaths(node: SegmentNode<RouteFile>): string[] {\n const paths: string[] = [];\n if (node.layout) paths.push(node.layout.filePath);\n if (node.page) paths.push(node.page.filePath);\n for (const child of node.children) paths.push(...collectRouteFilePaths(child));\n for (const slot of Object.values(node.slots)) paths.push(...collectRouteFilePaths(slot));\n return paths;\n}\n\n/**\n * Scan RSC bundle chunks to find which modules contain registerClientReference\n * calls, and extract the reference hash keys from each.\n */\nfunction buildClientRefIndex(bundle: OutputBundle): Map<string, string[]> {\n const index = new Map<string, string[]>();\n for (const item of Object.values(bundle)) {\n if (item.type !== 'chunk' || !item.modules) continue;\n for (const [moduleId, mod] of Object.entries(item.modules)) {\n if (!mod.code) continue;\n const keys: string[] = [];\n for (const match of mod.code.matchAll(CLIENT_REF_KEY_RE)) {\n keys.push(match[1]);\n }\n if (keys.length > 0) {\n index.set(moduleId, keys);\n }\n }\n }\n return index;\n}\n\n/** Rollup getModuleInfo shape (subset). */\ninterface ModuleInfo {\n importedIds: string[];\n}\n\n/**\n * Walk a module's transitive imports to collect all client reference\n * keys reachable from it.\n */\nfunction walkModuleImports(\n moduleId: string,\n clientRefIndex: Map<string, string[]>,\n visited: Set<string>,\n result: Set<string>,\n getModuleInfo: (id: string) => ModuleInfo | null\n): void {\n if (visited.has(moduleId)) return;\n visited.add(moduleId);\n\n const refKeys = clientRefIndex.get(moduleId);\n if (refKeys) {\n for (const key of refKeys) result.add(key);\n }\n\n const info = getModuleInfo(moduleId);\n if (!info) return;\n for (const importedId of info.importedIds) {\n walkModuleImports(importedId, clientRefIndex, visited, result, getModuleInfo);\n }\n}\n\n/**\n * Create the timber-build-manifest Vite plugin.\n *\n * Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)\n */\nexport function timberBuildManifest(ctx: PluginContext): Plugin {\n let isDev = false;\n\n return {\n name: 'timber-build-manifest',\n\n configResolved(config: ResolvedConfig) {\n isDev = config.command === 'serve';\n\n // Generate a per-build deployment ID early so virtual:timber-config\n // can serialize it during the load hook (which runs before generateBundle).\n // A random UUID is used instead of a content hash — determinism provides\n // no real benefit here since you almost never redeploy identical code,\n // and a random ID avoids the timing problem where the content hash was\n // only available after generateBundle (TIM-452).\n if (!isDev && !ctx.deploymentId) {\n ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);\n }\n },\n\n resolveId(id: string) {\n const cleanId = id.startsWith('\\0') ? id.slice(1) : id;\n\n if (cleanId === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n if (cleanId.endsWith(`/${VIRTUAL_MODULE_ID}`)) {\n return RESOLVED_VIRTUAL_ID;\n }\n\n return null;\n },\n\n load(id: string) {\n if (id !== RESOLVED_VIRTUAL_ID) return null;\n\n // Serialized, not restated: an empty manifest is described once, in\n // server/build-manifest.ts. Both branches below emitted their own object\n // literal and had already drifted apart — see EMPTY_BUILD_MANIFEST.\n const empty = JSON.stringify(EMPTY_BUILD_MANIFEST);\n\n // In dev mode, return empty manifest — Vite HMR handles CSS.\n if (isDev) {\n return [\n '// Auto-generated build manifest — do not edit.',\n '// Dev mode: empty manifest (Vite HMR handles CSS/JS).',\n '',\n `const manifest = ${empty};`,\n '',\n 'export default manifest;',\n ].join('\\n');\n }\n\n // In production, read from globalThis at runtime.\n // The adapter writes a _timber-manifest-init.js that sets this global\n // before the RSC handler imports this module. ESM evaluation order\n // guarantees the global is set by the time this code runs.\n //\n // The literal is only reached when the global is unset — an app built\n // with no adapter, which writes no init module. It is NOT the map the\n // build computed; that lives in _timber-manifest-init.js (TIM-1300).\n return [\n '// Auto-generated build manifest — do not edit.',\n '// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',\n '// The object below is only the fallback for when that global is unset —',\n '// the real manifest, including the requestDep map, is in that init module.',\n '',\n `const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? ${empty};`,\n '',\n 'export default manifest;',\n ].join('\\n');\n },\n\n // Extract manifest data from the client bundle only.\n // The RSC plugin runs builds in order: RSC → client → SSR.\n // We only want client env data (CSS assets, client JS chunks).\n generateBundle(_options, bundle) {\n if (isDev) return;\n\n const envName = (this as { environment?: { name: string } }).environment?.name;\n\n // RSC environment: walk the module graph to find which client\n // references each route file transitively imports. Store the\n // mapping in ctx so the post-build phase can cross-reference\n // with clientReferenceDeps to populate per-route modulepreloads.\n if (envName === 'rsc' && ctx.routeTree) {\n const clientRefIndex = buildClientRefIndex(bundle);\n if (clientRefIndex.size > 0) {\n const routeFiles = collectRouteFilePaths(ctx.routeTree.root);\n const routeClientRefKeys = new Map<string, Set<string>>();\n\n const getInfo = (id: string) =>\n (this as { getModuleInfo?: (id: string) => ModuleInfo | null }).getModuleInfo?.(id) ??\n null;\n\n for (const filePath of routeFiles) {\n const refKeys = new Set<string>();\n walkModuleImports(filePath, clientRefIndex, new Set(), refKeys, getInfo);\n if (refKeys.size > 0) {\n routeClientRefKeys.set(filePath, refKeys);\n }\n }\n\n if (routeClientRefKeys.size > 0) {\n ctx.routeClientRefKeys = routeClientRefKeys;\n }\n }\n }\n\n if (envName === 'client') {\n ctx.buildManifest = buildManifestFromBundle(bundle, ctx.base, ctx.root);\n\n // Compute cache-busting hashes for metadata route files\n if (ctx.routeTree) {\n ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);\n }\n\n // Attach the static request-dependency map from the request-dep\n // plugin, computed in the RSC `buildEnd` hook. The RSC environment is\n // built before the client one, so the field is populated by now.\n //\n // Absent means the RSC `buildEnd` never ran — a broken plugin pipeline,\n // not an app without segments, which produces `{}`. Serializing that as\n // an empty map is indistinguishable at runtime from an analysis that\n // found nothing (`server/request-dep.ts` answers `true` for any absent\n // key either way), so every segment and slot silently stops being a\n // skip candidate and slot caching is off with nothing to show for it.\n // Fail the build instead (TIM-1300).\n if (ctx.requestDepMap === undefined) {\n throw new Error(\n '[timber] Build manifest: the request-dependency map was never computed. ' +\n \"The RSC environment's buildEnd hook did not run before the client build, \" +\n 'so no segment or slot could be skipped on client navigation. This is a ' +\n 'plugin pipeline bug — timber-request-dep must run in the rsc environment.'\n );\n }\n ctx.buildManifest.requestDep = ctx.requestDepMap;\n\n // When client JavaScript is disabled, strip JS chunks from the bundle\n // so Rollup never writes them to disk. CSS assets are preserved —\n // they're still needed for server-rendered HTML. The JS references\n // in the manifest are stripped once, by the post-build phase, after\n // it has merged in everything else (plugins/post-build.ts).\n if (ctx.clientJavascript.disabled) {\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type === 'chunk') {\n delete bundle[fileName];\n }\n }\n }\n }\n },\n };\n}\n","/**\n * timber-dev-logs — Pipes server console output to the browser console in dev.\n *\n * Patches `console.log/warn/error/debug/info` on the server side and\n * forwards messages to connected browsers via Vite's HMR WebSocket.\n * The browser entry replays them in the browser console with the\n * correct log level and a \"[server]\" prefix.\n *\n * Dev-only: this plugin only runs during `vite dev` (apply: 'serve').\n * No runtime overhead in production.\n *\n * Design docs: 18-build-system.md §\"Dev Server\", 02-rendering-pipeline.md\n */\n\nimport type { Plugin, ViteDevServer, Logger } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\n// ─── Original Console Snapshot ──────────────────────────────────────────\n\n/**\n * Snapshot of the original console methods, captured at module load time\n * (before any patching). Used as Vite's `customLogger` console so that\n * forwardConsole output bypasses our patch entirely — eliminating the\n * server→browser→server forwarding loop without string matching.\n */\nexport const originalConsole: Pick<Console, 'log' | 'warn' | 'error' | 'debug' | 'info'> = {\n log: console.log.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n info: console.info.bind(console),\n};\n\n/**\n * Wrap a Vite Logger so its output methods route through `originalConsole`\n * instead of the global (potentially patched) console. This prevents the\n * server→browser→server forwarding loop even when the user supplies their\n * own `customLogger` that internally calls console methods.\n */\nexport function wrapLoggerWithOriginalConsole(logger: Logger): Logger {\n // Swap all patched console methods to originals during any logger call,\n // since user loggers may call any combination of console methods internally.\n function withOriginals<T>(fn: () => T): T {\n const saved = {\n log: console.log,\n warn: console.warn,\n error: console.error,\n debug: console.debug,\n info: console.info,\n };\n console.log = originalConsole.log;\n console.warn = originalConsole.warn;\n console.error = originalConsole.error;\n console.debug = originalConsole.debug;\n console.info = originalConsole.info;\n try {\n return fn();\n } finally {\n console.log = saved.log;\n console.warn = saved.warn;\n console.error = saved.error;\n console.debug = saved.debug;\n console.info = saved.info;\n }\n }\n\n return {\n get hasWarned() {\n return logger.hasWarned;\n },\n set hasWarned(v) {\n logger.hasWarned = v;\n },\n info(msg, opts) {\n withOriginals(() => logger.info(msg, opts));\n },\n warn(msg, opts) {\n withOriginals(() => logger.warn(msg, opts));\n },\n warnOnce(msg, opts) {\n withOriginals(() => logger.warnOnce(msg, opts));\n },\n error(msg, opts) {\n withOriginals(() => logger.error(msg, opts));\n },\n clearScreen(type) {\n logger.clearScreen(type);\n },\n hasErrorLogged(error) {\n return logger.hasErrorLogged(error);\n },\n };\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/** Log levels that are patched and forwarded. */\nexport type ServerLogLevel = 'log' | 'warn' | 'error' | 'debug' | 'info';\n\nconst LOG_LEVELS: ServerLogLevel[] = ['log', 'warn', 'error', 'debug', 'info'];\n\n/** Payload sent over Vite's HMR WebSocket. */\nexport interface ServerLogPayload {\n level: ServerLogLevel;\n args: unknown[];\n /** Server-side source location (file:line:col) if available. */\n location: string | null;\n /** Timestamp in ms (Date.now()) */\n timestamp: number;\n}\n\n// ─── Serialization ───────────────────────────────────────────────────────\n\n/** Patterns that look like env vars or secrets — these are redacted. */\nconst SENSITIVE_PATTERNS =\n /(?:^|[^a-z])(?:SECRET|TOKEN|PASSWORD|API_KEY|PRIVATE_KEY|AUTH|CREDENTIAL|SESSION_SECRET)(?:[^a-z]|$)/i;\n\n/**\n * Serialize a console argument for transmission over WebSocket.\n *\n * Handles: strings, numbers, booleans, null, undefined, arrays, plain\n * objects, Errors, Dates, RegExps, and falls back to String() for others.\n *\n * Redacts values that match sensitive patterns to avoid leaking secrets.\n */\nfunction serializeArg(arg: unknown, depth = 0): unknown {\n if (depth > 5) return '[...]';\n\n if (arg === null) return null;\n if (arg === undefined) return '[undefined]';\n\n switch (typeof arg) {\n case 'string':\n if (SENSITIVE_PATTERNS.test(arg)) return '[REDACTED]';\n return arg;\n case 'number':\n case 'boolean':\n return arg;\n case 'bigint':\n return `${arg}n`;\n case 'symbol':\n return arg.toString();\n case 'function':\n return `[Function: ${arg.name || 'anonymous'}]`;\n case 'object':\n break;\n default:\n return String(arg);\n }\n\n // Error\n if (arg instanceof Error) {\n return {\n __type: 'Error',\n name: arg.name,\n message: arg.message,\n stack: arg.stack ?? null,\n };\n }\n\n // Date\n if (arg instanceof Date) {\n return arg.toISOString();\n }\n\n // RegExp\n if (arg instanceof RegExp) {\n return arg.toString();\n }\n\n // Array\n if (Array.isArray(arg)) {\n return arg.map((item) => serializeArg(item, depth + 1));\n }\n\n // Map\n if (arg instanceof Map) {\n const entries: Record<string, unknown> = {};\n for (const [key, value] of arg) {\n entries[String(key)] = serializeArg(value, depth + 1);\n }\n return { __type: 'Map', entries };\n }\n\n // Set\n if (arg instanceof Set) {\n return { __type: 'Set', values: [...arg].map((v) => serializeArg(v, depth + 1)) };\n }\n\n // Plain object\n if (Object.getPrototypeOf(arg) === Object.prototype || Object.getPrototypeOf(arg) === null) {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(arg as Record<string, unknown>)) {\n if (SENSITIVE_PATTERNS.test(key)) {\n result[key] = '[REDACTED]';\n } else {\n result[key] = serializeArg(value, depth + 1);\n }\n }\n return result;\n }\n\n // Fallback — use toString or constructor name\n try {\n return `[${(arg as object).constructor?.name ?? 'Object'}]`;\n } catch {\n return '[Object]';\n }\n}\n\n// ─── Source Location ─────────────────────────────────────────────────────\n\n/**\n * Extract the caller's source location from an Error stack trace.\n *\n * Walks the stack to find the first frame that isn't inside this file\n * or Node internals. Returns \"file:line:col\" or null.\n */\nfunction extractCallerLocation(projectRoot: string): string | null {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return null;\n\n const lines = stack.split('\\n');\n // Skip first line (\"Error\") and frames inside this module\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n // Skip our own patching frames\n if (line.includes('dev-tools/logs')) continue;\n // Skip node internals\n if (line.includes('node:') || line.includes('node_modules')) continue;\n\n // Extract file path from \"at ... (file:line:col)\" or \"at file:line:col\"\n const match = line.match(/\\((.+?):(\\d+):(\\d+)\\)/) ?? line.match(/at (.+?):(\\d+):(\\d+)/);\n if (match) {\n let filePath = match[1];\n // Make path relative to project root for readability\n if (filePath.startsWith(projectRoot)) {\n filePath = filePath.slice(projectRoot.length + 1);\n }\n return `${filePath}:${match[2]}:${match[3]}`;\n }\n }\n return null;\n}\n\n// ─── Framework-Internal Detection ────────────────────────────────────────\n\n/**\n * Check if the calling code is from timber's internal plugin/adapter plumbing.\n *\n * Only filters logs from `plugins/` and `adapters/` directories — these are\n * framework operational noise (request summaries, codegen warnings, adapter\n * setup). Logs from `server/` are preserved because they surface user errors\n * (render errors, action errors, route handler errors, etc.).\n *\n * Handles both monorepo paths (timber-app/src/plugins/) and installed\n * package paths (@timber-js/app/dist/plugins/).\n */\nexport function isFrameworkInternalCaller(): boolean {\n const err = new Error();\n const stack = err.stack;\n if (!stack) return false;\n\n const lines = stack.split('\\n');\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n // Skip our own patching frames\n if (line.includes('dev-tools/logs')) continue;\n // Skip node internals (but NOT node_modules — we need to inspect those)\n if (line.includes('node:')) continue;\n\n // Check if this first real frame is inside timber's own source\n const isTimberPath = line.includes('timber-app/') || line.includes('@timber-js/app/');\n if (!isTimberPath) return false;\n\n // Only filter plugin and adapter internals, not server/ runtime code\n // which surfaces user errors (render errors, action errors, etc.)\n return line.includes('/plugins/') || line.includes('/adapters/');\n }\n return false;\n}\n\n// ─── Console Patching ────────────────────────────────────────────────────\n\n/**\n * Patch console methods to forward logs to the browser via HMR WebSocket.\n *\n * Each patched method:\n * 1. Calls the original console method (server terminal still works)\n * 2. Serializes arguments for JSON transport\n * 3. Sends via server.hot.send() — dropped if no clients connected\n */\nfunction patchConsole(server: ViteDevServer, projectRoot: string): () => void {\n const prevConsole = new Map<ServerLogLevel, (...args: unknown[]) => void>();\n // Per-level guard so a console.warn inside a console.error handler isn't\n // suppressed — only same-level synchronous re-entrancy is blocked.\n const patchingLevel = new Set<ServerLogLevel>();\n\n for (const level of LOG_LEVELS) {\n prevConsole.set(level, console[level].bind(console));\n\n console[level] = (...args: unknown[]) => {\n // Same-level re-entrancy guard: if prevConsole's wrapper calls back\n // into console[level], just pass through without forwarding.\n if (patchingLevel.has(level)) {\n prevConsole.get(level)!(...args);\n return;\n }\n\n patchingLevel.add(level);\n try {\n // Call the previous console method first — guarantees terminal output\n // even if serialization or forwarding fails downstream. If prevConsole\n // throws, the error propagates (not swallowed) but patchingLevel is\n // still cleaned up by the outer finally.\n prevConsole.get(level)!(...args);\n\n // Skip framework-internal logs (plugins/, adapters/) from browser forwarding.\n if (isFrameworkInternalCaller()) return;\n\n try {\n const payload: ServerLogPayload = {\n level,\n args: args.map((arg) => serializeArg(arg)),\n location: extractCallerLocation(projectRoot),\n timestamp: Date.now(),\n };\n\n server.hot.send('timber:server-log', payload);\n } catch (e) {\n originalConsole.debug(\n '[timber] server log forwarding failed:',\n e instanceof Error ? e.message : e\n );\n }\n } finally {\n patchingLevel.delete(level);\n }\n };\n }\n\n // Return a cleanup function to restore the previous console methods\n return () => {\n for (const [level, prev] of prevConsole) {\n console[level] = prev;\n }\n };\n}\n\n// ─── Plugin ──────────────────────────────────────────────────────────────\n\n/**\n * Create the timber-dev-logs Vite plugin.\n *\n * Patches console methods when the dev server starts and restores them\n * when the server closes. Only active during `vite dev`.\n */\nexport function timberDevLogs(_ctx: PluginContext): Plugin {\n let cleanup: (() => void) | null = null;\n\n return {\n name: 'timber-dev-logs',\n apply: 'serve',\n\n configureServer(server: ViteDevServer) {\n cleanup = patchConsole(server, _ctx.root);\n\n // Restore console on server close\n server.httpServer?.on('close', () => {\n cleanup?.();\n cleanup = null;\n });\n },\n };\n}\n","/**\n * Browser log forwarding — maps timber's devBrowserLogs config to Vite 8's\n * server.forwardConsole option.\n *\n * Vite 8 ships built-in browser→terminal console forwarding via\n * server.forwardConsole, which patches console methods in /@vite/client\n * and prints forwarded output server-side. This replaces timber's custom\n * client-side interception script and HMR WebSocket transport.\n *\n * Client error forwarding (overlay echo, digest filtering, componentStack)\n * remains in browser-dev.ts — Vite's forwardConsole only logs to terminal\n * and has no client-side filter hook. See TIM-1152.\n *\n * See design/21-dev-server.md §\"Browser Log Forwarding\"\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────\n\n/** Log levels forwarded from the browser. */\nexport type BrowserLogLevel = 'error' | 'warn' | 'info';\n\n/** Configuration value for devBrowserLogs in timber.config.ts. */\nexport type DevBrowserLogsConfig = BrowserLogLevel | 'none' | undefined;\n\n// ─── Vite Config Mapping ─────────────────────────────────────────────────\n\n/**\n * Map timber's devBrowserLogs threshold to Vite 8's server.forwardConsole.\n *\n * Vite defaults forwardConsole OFF for non-agent dev; timber enables it\n * based on the configured threshold (default: 'warn'). The threshold acts\n * as a minimum severity — 'warn' forwards errors + warnings, 'info'\n * forwards everything, 'error' forwards only errors, 'none' disables.\n *\n * Vite's unhandledErrors is explicitly disabled — timber's own\n * setupClientErrorForwarding (browser-dev.ts) already catches window\n * error/unhandledrejection, filters framework control-flow signals\n * (redirect/deny digests) and page-unload aborts (TIM-838), and\n * echoes errors to the Vite overlay. Enabling Vite's unhandledErrors\n * would duplicate terminal output for normal errors and reintroduce\n * unfiltered noise for framework signals.\n */\nexport function resolveForwardConsole(\n threshold: DevBrowserLogsConfig\n): boolean | { unhandledErrors: boolean; logLevels: string[] } {\n const resolved = threshold ?? 'warn';\n if (resolved === 'none') return false;\n\n const logLevels: string[] = [];\n if (resolved === 'info') logLevels.push('info', 'warn', 'error');\n else if (resolved === 'warn') logLevels.push('warn', 'error');\n else logLevels.push('error');\n\n return { unhandledErrors: false, logLevels };\n}\n","import type { Plugin } from 'vite';\n\n/**\n * Redirect React's CJS development bundles to production bundles.\n *\n * React packages use a runtime `process.env.NODE_ENV` check in their CJS\n * entry points to conditionally require either `*.development.js` or\n * `*.production.js`. Rollup's CJS plugin resolves both branches statically\n * before the `define` replacement can eliminate the dead branch, causing\n * development React code to be included in production builds.\n *\n * This plugin intercepts `resolveId` and rewrites any `*.development.js`\n * import under `react/cjs/`, `react-dom/cjs/`, or `scheduler/cjs/` to\n * its `*.production.js` counterpart.\n *\n * Only active in production builds. Has no effect in dev mode.\n */\nexport function timberReactProd(): Plugin {\n let isProd = false;\n\n return {\n name: 'timber-react-prod',\n enforce: 'pre',\n configResolved(config) {\n isProd = config.command === 'build' && config.mode === 'production';\n },\n resolveId: {\n order: 'pre',\n async handler(source, importer, options) {\n if (!isProd) return;\n\n // Match: react/cjs/*.development.js, react-dom/cjs/*.development.js, scheduler/cjs/*.development.js\n if (!source.includes('.development.')) return;\n\n const resolved = await this.resolve(source, importer, {\n ...options,\n skipSelf: true,\n });\n if (!resolved) return;\n\n // Only rewrite paths inside react/react-dom/scheduler/react-server-dom CJS directories\n if (\n !resolved.id.includes('/react/cjs/') &&\n !resolved.id.includes('/react-dom/cjs/') &&\n !resolved.id.includes('/scheduler/cjs/') &&\n !resolved.id.includes('/react-server-dom/cjs/')\n ) {\n return;\n }\n\n const prodId = resolved.id.replace('.development.', '.production.');\n return { ...resolved, id: prodId };\n },\n },\n };\n}\n","/**\n * timber-react-resolve — Deduplicate React across timber and user project.\n *\n * Without this plugin, pnpm's strict isolation can install two physical\n * copies of React when the user's pinned version differs from timber's\n * peer dep. Timber's 47 bare `from 'react'` imports resolve to one copy\n * while react-dom uses the other — causing \"Invalid hook call\" hydration\n * crashes with no indication of the real cause.\n *\n * The fix: inject `resolve.dedupe` entries so Vite always resolves React\n * packages from the project root. Unlike `resolve.alias`, `dedupe`\n * preserves Vite's per-environment export conditions — the RSC\n * environment still gets the `react-server` build, SSR gets the SSR\n * build, and the browser gets the browser build. The deduplication\n * happens at the package level, not the file level.\n *\n * A `configResolved` check detects version mismatches between timber's\n * resolved React and the project's React, and logs an actionable error.\n *\n * Design doc: 18-build-system.md §\"Module Resolution\"\n * Task: TIM-1520\n */\n\nimport { createRequire } from 'node:module';\nimport { dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Plugin } from 'vite';\n\n/**\n * React packages to deduplicate. Vite's `resolve.dedupe` extracts the\n * base package name (via `deepImportRE`) before checking, so subpath\n * specifiers like `react/jsx-runtime` are covered by the base `react`\n * entry — listing them separately has no effect.\n */\nexport const REACT_DEDUPE_PACKAGES = ['react', 'react-dom'] as const;\n\n// ANSI escape codes — match config-validation.ts style\nconst RED = '\\x1b[31m';\nconst BOLD = '\\x1b[1m';\nconst DIM = '\\x1b[2m';\nconst RESET = '\\x1b[0m';\n\n/**\n * Read the version from a package's package.json given a resolve root.\n */\nfunction readPackageVersion(packageName: string, resolveRoot: string): string | null {\n try {\n const req = createRequire(`${resolveRoot}/package.json`);\n const pkgJsonPath = req.resolve(`${packageName}/package.json`);\n const pkg = req(pkgJsonPath) as { version?: string };\n return pkg.version ?? null;\n } catch {\n return null;\n }\n}\n\nexport interface ReactVersionMismatch {\n specifier: string;\n timberVersion: string;\n projectVersion: string;\n}\n\n/**\n * Check whether timber's React and the user project's React resolve to\n * the same version. Returns mismatches if any.\n */\nexport function detectReactMismatch(projectRoot: string): ReactVersionMismatch[] {\n const mismatches: ReactVersionMismatch[] = [];\n const timberRoot = dirname(dirname(fileURLToPath(import.meta.url)));\n\n for (const pkg of ['react', 'react-dom'] as const) {\n const timberVersion = readPackageVersion(pkg, timberRoot);\n const projectVersion = readPackageVersion(pkg, projectRoot);\n\n if (timberVersion && projectVersion && timberVersion !== projectVersion) {\n mismatches.push({ specifier: pkg, timberVersion, projectVersion });\n }\n }\n\n return mismatches;\n}\n\n/**\n * Format React version mismatches as an actionable warning.\n */\nexport function formatReactMismatch(mismatches: ReactVersionMismatch[]): string {\n if (mismatches.length === 0) return '';\n\n const lines: string[] = [];\n lines.push(\n `${RED}${BOLD}[timber]${RESET} ${RED}React version mismatch detected — this causes silent hydration crashes${RESET}`\n );\n lines.push('');\n for (const m of mismatches) {\n lines.push(\n ` ${RED}✗${RESET} ${m.specifier}: timber has ${BOLD}${m.timberVersion}${RESET}, project has ${BOLD}${m.projectVersion}${RESET}`\n );\n }\n lines.push('');\n lines.push(\n ` ${DIM}This typically causes \"Invalid hook call\" errors because two copies of${RESET}`\n );\n lines.push(` ${DIM}React are loaded. timber's resolve.dedupe should handle this, but${RESET}`);\n lines.push(\n ` ${DIM}if you see hook errors, ensure your React version satisfies timber's peer dep.${RESET}`\n );\n lines.push('');\n lines.push(` ${DIM}Fix: update React in your project to match —${RESET}`);\n lines.push(\n ` ${BOLD}pnpm add react@${mismatches[0].timberVersion} react-dom@${mismatches[0].timberVersion}${RESET}`\n );\n\n return lines.join('\\n');\n}\n\n/**\n * Create the timber-react-resolve Vite plugin.\n */\nexport function timberReactResolve(): Plugin {\n return {\n name: 'timber-react-resolve',\n enforce: 'pre',\n\n config(userConfig) {\n // Merge with any existing dedupe entries the user may have set.\n const existing = userConfig.resolve?.dedupe ?? [];\n const merged = [...existing];\n\n for (const pkg of REACT_DEDUPE_PACKAGES) {\n if (!merged.includes(pkg)) {\n merged.push(pkg);\n }\n }\n\n return {\n resolve: {\n dedupe: merged,\n },\n };\n },\n\n configResolved(resolved) {\n const mismatches = detectReactMismatch(resolved.root);\n if (mismatches.length > 0) {\n process.stderr.write(`${formatReactMismatch(mismatches)}\\n\\n`);\n }\n },\n };\n}\n","/**\n * timber-chunks — Vite sub-plugin for client chunk configuration.\n *\n * Previously implemented a 5-tier cache strategy (vendor-react, vendor-timber,\n * vendor-app, shared-app, shared-client) via manualChunks. This was removed\n * in LOCAL-337 because the cache-tier separation added HTTP requests,\n * complicated the architecture, and caused module duplication across chunks\n * that required globalThis + Symbol.for workarounds.\n *\n * Current strategy: let Rolldown handle natural code splitting.\n * Output is typically:\n * - 1 main bundle (React + timber runtime + shared app code + user vendors)\n * - Per-route chunks (page/layout components, only when route-specific)\n * - rolldown-runtime (Rolldown's own output, unavoidable)\n *\n * Additionally, this plugin builds a facade ancestry map during the RSC\n * build so that `clientChunkGroup` can reclassify `shared:` client\n * references that are only consumed by a single route boundary.\n * See TIM-1107, design/27-chunking-strategy.md.\n *\n * Design docs: 27-chunking-strategy.md\n */\n\nimport type { Plugin, Rollup } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\n/**\n * Check if a module is part of the timber framework runtime.\n *\n * Matches both monorepo paths (packages/timber-app/...) and consumer\n * project paths (node_modules/@timber-js/app/...) so identification\n * is consistent regardless of how timber is installed.\n *\n * Exported for use in tests (singleton-audit, etc.).\n */\nexport function isTimberRuntime(id: string): boolean {\n return (\n id.includes('/timber-app/') ||\n id.includes('/@timber-js/app/') ||\n id.includes('react-server-dom') ||\n id.includes('@vitejs/plugin-rsc')\n );\n}\n\ntype OutputChunk = Rollup.OutputChunk;\n\n/**\n * Build a map from absolute module IDs in non-facade RSC chunks to the\n * absolute facade module paths that transitively import them.\n *\n * Used by `clientChunkGroup` to reclassify `shared:` client references\n * that are only consumed by a single route boundary (TIM-1107).\n */\nfunction buildFacadeAncestryMap(bundle: Rollup.OutputBundle): Map<string, string[]> {\n const chunks = new Map<string, OutputChunk>();\n for (const [file, asset] of Object.entries(bundle)) {\n if (asset.type === 'chunk') chunks.set(file, asset);\n }\n\n // Reverse import graph: which chunks import this chunk file?\n const importedBy = new Map<string, string[]>();\n for (const [file, chunk] of chunks) {\n for (const imp of chunk.imports) {\n let parents = importedBy.get(imp);\n if (!parents) {\n parents = [];\n importedBy.set(imp, parents);\n }\n parents.push(file);\n }\n }\n\n // Trace upward from a chunk to find all facade modules that consume it\n function facadeAncestors(file: string, visited: Set<string>): string[] {\n if (visited.has(file)) return [];\n visited.add(file);\n const chunk = chunks.get(file);\n if (!chunk) return [];\n if (chunk.facadeModuleId) return [chunk.facadeModuleId];\n const parents = importedBy.get(file) ?? [];\n const result: string[] = [];\n for (const p of parents) {\n for (const f of facadeAncestors(p, visited)) result.push(f);\n }\n return result;\n }\n\n const moduleToFacades = new Map<string, string[]>();\n for (const [file, chunk] of chunks) {\n if (chunk.facadeModuleId) continue;\n const facades = facadeAncestors(file, new Set());\n if (facades.length === 0) continue;\n // Deduplicate facades\n const unique = [...new Set(facades)];\n for (const modId of chunk.moduleIds) {\n moduleToFacades.set(modId, unique);\n }\n }\n\n return moduleToFacades;\n}\n\n/**\n * Create the timber-chunks Vite plugin.\n *\n * Rolldown's default splitting produces the desired output (one main\n * bundle + per-route chunks). This plugin's main job is building the\n * facade ancestry map during the RSC build so `clientChunkGroup` can\n * reclassify shared client references to their correct route boundary.\n *\n * NOTE: Ideally we'd use Rolldown's `format: 'app'` (module registry format)\n * which guarantees single-copy module semantics like webpack/Turbopack.\n * However, `format: 'app'` is not yet implemented in Rolldown rc.10.\n * Until it ships, singleton state in navigation-context.ts uses\n * globalThis + Symbol.for as a cross-chunk safety net.\n *\n * Design docs: 27-chunking-strategy.md\n */\nexport function timberChunks(ctx: PluginContext): Plugin {\n return {\n name: 'timber-chunks',\n generateBundle(_options, bundle) {\n if (this.environment?.name !== 'rsc') return;\n ctx.sharedModuleFacades = buildFacadeAncestryMap(bundle);\n },\n };\n}\n","/**\n * Client chunk grouping strategy for @vitejs/plugin-rsc.\n *\n * Groups client reference modules by the **consuming route's** layout boundary\n * (derived from `meta.serverChunk`), not by the module's own file location.\n * This ensures components in shared directories (e.g. `components/`) land in\n * the chunk of the route that uses them, not in a single catch-all chunk.\n *\n * For `shared:` modules (client references in non-facade RSC chunks), the\n * function consults a facade ancestry map built during the RSC build. If all\n * consuming facades belong to the same route boundary, the module is\n * reclassified to that boundary instead of falling through to `client-shared`.\n *\n * See design/27-chunking-strategy.md, TIM-440, TIM-499, TIM-1104, TIM-1107.\n */\n\nimport { relative } from 'node:path';\n\n/**\n * Check whether a root-relative path lives under the app directory,\n * and if so return the first non-group route segment.\n *\n * `appPrefix` is the root-relative app directory with a trailing slash\n * (e.g. \"app/\" or \"src/app/\"), computed once from the resolved appDir\n * and root. Matching uses `startsWith` — no ambiguity.\n *\n * Returns:\n * { inApp: false } — path is not under app/\n * { inApp: true, segment: null } — root of app/ (e.g. app/layout.tsx)\n * { inApp: true, segment: \"dashboard\" } — nested route boundary\n */\nfunction findAppBoundary(\n path: string,\n appPrefix: string\n): { inApp: false } | { inApp: true; segment: string | null } {\n const relPath = path.replace(/\\\\/g, '/');\n if (!relPath.startsWith(appPrefix)) return { inApp: false };\n\n const withinApp = relPath.slice(appPrefix.length);\n const segments = withinApp.split('/');\n\n for (const seg of segments) {\n if (seg.includes('.')) break;\n if (seg.startsWith('(') && seg.endsWith(')')) continue;\n return { inApp: true, segment: seg };\n }\n\n return { inApp: true, segment: null };\n}\n\n/**\n * Check if a string is a bare import specifier (package name, not a path).\n * Bare specifiers don't start with `.`, `/`, or contain `:/`.\n */\nfunction isBareSpecifier(id: string): boolean {\n return !id.startsWith('.') && !id.startsWith('/') && !id.includes(':/');\n}\n\n/**\n * Look up facade ancestors for a module ID, handling bare package specifiers.\n *\n * The facade ancestry map is keyed by absolute resolved paths (from Rollup's\n * moduleIds), but the RSC plugin passes bare package names (e.g. 'streamdown')\n * as meta.id for npm package client references (TIM-1108). When a direct\n * lookup misses and the id is a bare specifier, scan map keys for a matching\n * node_modules path.\n */\nfunction lookupFacades(\n id: string,\n sharedModuleFacades: Map<string, string[]>\n): string[] | undefined {\n const direct = sharedModuleFacades.get(id);\n if (direct) return direct;\n\n if (!isBareSpecifier(id)) return undefined;\n\n // Bare specifier: match against node_modules/<name>/ in map keys.\n // Scoped packages use @scope/name, unscoped use just name.\n // A package may have multiple module IDs in the RSC bundle (e.g. main\n // entry + re-exported submodules), so aggregate facades from all matches.\n const needle = `/node_modules/${id}/`;\n let merged: string[] | undefined;\n for (const [key, facades] of sharedModuleFacades) {\n if (key.includes(needle)) {\n if (!merged) merged = [...facades];\n else merged.push(...facades);\n }\n }\n return merged;\n}\n\n/**\n * For a `shared:` client reference, check the facade ancestry map to\n * see if all consuming facades belong to the same route boundary.\n * Returns the boundary segment name, or null if the module is\n * genuinely shared across multiple boundaries.\n */\nfunction reclassifySharedModule(\n meta: { id: string; normalizedId: string },\n appPrefix: string,\n root: string,\n sharedModuleFacades: Map<string, string[]>\n): string | null {\n const facades = lookupFacades(meta.id, sharedModuleFacades);\n if (!facades || facades.length === 0) return null;\n\n const boundaries = new Set<string>();\n for (const facade of facades) {\n const relFacade = relative(root, facade).replace(/\\\\/g, '/');\n const result = findAppBoundary(relFacade, appPrefix);\n if (result.inApp && result.segment) {\n boundaries.add(result.segment);\n } else if (result.inApp) {\n // Root-level facade — module is used at root, keep shared\n return null;\n } else {\n // Facade outside app/ (e.g. src/posts/foo.mdx) — can't derive a\n // safe common boundary, so keep shared to avoid pulling outside-app\n // deps into a route chunk they don't belong to.\n return null;\n }\n }\n\n if (boundaries.size === 1) return [...boundaries][0];\n return null;\n}\n\n/**\n * Derive a chunk group name for a client reference module.\n *\n * Always derives the group from the **consuming route** (`serverChunk`'s\n * facade path), not from the module's own file location. This prevents\n * components in shared directories (e.g. `app/components/`, `src/lib/`)\n * from collapsing into a single chunk when they're only used by one route.\n *\n * For `shared:` modules (non-facade RSC chunks), consults the facade\n * ancestry map to reclassify modules that are only consumed by a single\n * route boundary. This prevents large dependencies from polluting\n * `client-shared` when they're route-scoped (TIM-1107).\n *\n * Examples:\n * - `facade:app/dashboard/settings/page.tsx` → `\"client-dashboard\"`\n * - `facade:app/(group-a)/group-page-a/page.tsx` → `\"client-group-page-a\"`\n * - `facade:app/layout.tsx` (root layout) → `\"client-shared\"`\n * - `shared:...` (shared across chunks) → reclassified or `\"client-shared\"`\n */\nexport function clientChunkGroup(\n meta: { id: string; normalizedId: string; serverChunk: string },\n appDir: string,\n root: string,\n sharedModuleFacades?: Map<string, string[]>\n): string {\n const { serverChunk } = meta;\n\n // Compute the root-relative app directory prefix once. Both normalizedId\n // and serverChunk paths from the RSC plugin are root-relative (via\n // path.relative(root, absoluteId)), so this prefix matches exactly —\n // no ambiguity with content directories that happen to share a name.\n const appPrefix = relative(root, appDir).replace(/\\\\/g, '/') + '/';\n\n if (serverChunk.startsWith('shared:')) {\n if (sharedModuleFacades) {\n const boundary = reclassifySharedModule(meta, appPrefix, root, sharedModuleFacades);\n if (boundary) return `client-${boundary}`;\n }\n return 'client-shared';\n }\n\n // Derive the group from the serverChunk's facade path — the RSC entry\n // point that references this client module. This groups by the consuming\n // route's layout boundary, not the module's own file location (TIM-1104).\n if (serverChunk.startsWith('facade:')) {\n const facadePath = serverChunk.slice('facade:'.length).replace(/\\\\/g, '/');\n const facadeResult = findAppBoundary(facadePath, appPrefix);\n if (facadeResult.inApp && facadeResult.segment) return `client-${facadeResult.segment}`;\n if (facadeResult.inApp) return 'client-shared';\n\n // Facade is outside app/ (e.g. src/posts/foo.mdx via import.meta.glob).\n // Derive a chunk name from the full facade path to keep these isolated.\n const facadeName = facadePath.replace(/\\.[^.]+$/, '').replace(/\\//g, '-');\n if (facadeName) return `client-${facadeName}`;\n }\n\n return 'client-shared';\n}\n","/**\n * timber-server-bundle — Bundle all dependencies for server environments.\n *\n * In production builds, sets `resolve.noExternal: true` for the rsc and ssr\n * environments. This ensures all npm dependencies are bundled into the output,\n * which is required for platforms like Cloudflare Workers that don't have\n * access to node_modules at runtime.\n *\n * In dev mode, Vite's default externalization is preserved for fast HMR.\n *\n * Design docs: design/11-platform.md, design/25-production-deployments.md\n */\n\nimport { builtinModules } from 'node:module';\nimport type { Plugin } from 'vite';\nimport { EXPLICIT_MARKERS } from '../analyze/poison-rules.ts';\n\n// The poison-pill marker packages (server-only, client-only) must never be\n// externalized — they have to reach the timber-shims resolveId hook so it\n// can substitute the poison virtual modules. Derived from poison-rules.ts\n// so the list cannot drift from what shims.ts intercepts.\nconst POISON_MARKER_SPECIFIERS = EXPLICIT_MARKERS.map((m) => m.specifier);\n\n// Every Node built-in as both bare (`stream`) and prefixed (`node:stream`).\n// Available at runtime on all targets (Node natively, Workers via nodejs_compat).\n// Listing explicitly silences Vite's \"Automatically externalized\" warnings.\nconst NODE_BUILTINS: string[] = builtinModules.flatMap((m) => [m, `node:${m}`]);\n\n// Packages that must never be bundled into the runtime server environments.\n// With `noExternal: true`, rolldown follows all transitive imports. These\n// are build-time-only tools that have no runtime use in a server bundle.\n//\n// The primary leak path (TIM-988) — `virtual:timber-cache-handler` importing\n// `timber.config.ts` and pulling in adapter/MDX deps — was eliminated by\n// TIM-1211: the cache handler virtual module now imports `timber.cache.ts`\n// instead. These externals are retained as defense-in-depth.\n//\n// Cloudflare runtime modules (cloudflare:workers, cloudflare:sockets, etc.)\n// available at runtime on Workers but must not be bundled.\nconst CLOUDFLARE_BUILTINS = [\n 'cloudflare:workers',\n 'cloudflare:sockets',\n 'cloudflare:email',\n 'cloudflare:workflows',\n];\n\nconst BUILD_ONLY_EXTERNALS: string[] = [\n ...NODE_BUILTINS,\n ...CLOUDFLARE_BUILTINS,\n 'vite',\n 'nitro',\n 'rollup',\n 'vite-plugin-satteri',\n 'satteri',\n 'fsevents',\n 'chokidar',\n];\n\nexport function timberServerBundle(): Plugin[] {\n const bundlePlugin: Plugin = {\n name: 'timber-server-bundle',\n\n config(_cfg, { command }) {\n // In dev mode, Vite externalizes node_modules by default for fast HMR.\n // But server-only/client-only must NOT be externalized — they need to\n // go through the timber-shims plugin so it can replace them with no-op\n // virtual modules. Without this, deps like `bright` that import\n // `server-only` get the real CJS package loaded via Node's require(),\n // which throws in the SSR environment.\n if (command === 'serve') {\n // In dev, Vite externalizes node_modules and loads them via Node's\n // native require(). This causes two problems:\n //\n // 1. Poison-pill packages: deps that import `server-only` (like `bright`)\n // hit the real CJS package which throws in the SSR environment.\n //\n // 2. Dual React instances: deps with React hooks (nuqs, etc.) are\n // externalized and loaded via Node.js, getting their own copy of\n // React. Meanwhile, SSR's renderToReadableStream uses Vite's\n // dep-optimized React. Two React instances = dispatcher mismatch,\n // causing \"Invalid hook call\" / \"Cannot read properties of null\n // (reading 'useId')\" errors. See LOCAL-297.\n //\n // We force these packages to be non-external so they go through\n // Vite's module pipeline, which deduplicates React correctly.\n return {\n environments: {\n rsc: {\n resolve: {\n noExternal: [...POISON_MARKER_SPECIFIERS],\n },\n },\n ssr: {\n resolve: {\n noExternal: [...POISON_MARKER_SPECIFIERS, 'nuqs'],\n },\n },\n },\n };\n }\n\n // Bundle all dependencies in server environments for production.\n // Without this, bare imports like 'nuqs/adapters/custom' are left\n // as external imports in the output, which fails on platforms\n // without node_modules (Cloudflare Workers, edge runtimes).\n // Define process.env.NODE_ENV in server environments so that\n // dead-code branches (dev-only tracing, React dev checks) are\n // eliminated by Rollup's tree-shaking. Without this, the runtime\n // check falls through on platforms where process.env is empty\n // (e.g. Cloudflare Workers), causing dev code to run in production.\n // Define process.env.NODE_ENV so dev-only React code is tree-shaken.\n // TIMBER_DEBUG is intentionally NOT defined here — it must remain a\n // runtime check so `isDebug()` in server/debug.ts can read it at\n // request time. See TIM-365.\n const serverDefine = {\n 'process.env.NODE_ENV': JSON.stringify('production'),\n };\n\n return {\n // Target webworker so Rolldown doesn't emit createRequire(import.meta.url)\n // shims that fail in Cloudflare Workers where import.meta.url is undefined\n // for non-entry modules. See design/11-platform.md.\n ssr: { target: 'webworker' },\n environments: {\n rsc: {\n resolve: { noExternal: true, external: BUILD_ONLY_EXTERNALS },\n build: { rolldownOptions: { external: [/^cloudflare:/] } },\n define: serverDefine,\n },\n ssr: {\n resolve: { noExternal: true, external: BUILD_ONLY_EXTERNALS },\n build: { rolldownOptions: { external: [/^cloudflare:/] } },\n define: serverDefine,\n },\n },\n };\n },\n };\n\n // Fix Rolldown's broken `__esmMin` lazy initializers in server bundles.\n //\n // Rolldown wraps ESM module initialization in `__esmMin` lazy functions.\n // For packages with `sideEffects: false` (e.g. nuqs), Rolldown drops\n // the variable assignment of the init function — so the module's React\n // imports, context creation, etc. never execute.\n //\n // The fix: patch `__esmMin` to eagerly *attempt* each init, but fall\n // back to lazy retry on failure. This handles two failure modes:\n //\n // 1. Forward references (e.g. Zod v4): `init_iso` calls `init_schemas`\n // which hasn't been defined yet. Eager execution fails silently, but\n // when the function is called lazily later, all dependencies are\n // available and the retry succeeds (and caches).\n //\n // 2. Optional peer dep shims (e.g. @emotion/is-prop-valid for\n // framer-motion): Vite generates shims that throw for missing\n // optional deps. The eager attempt swallows the throw; the lazy call\n // PROPAGATES it so the consuming package's try/catch handles it.\n //\n // The key: only the eager attempt swallows errors. Once the helper is\n // returned, lazy calls use the original Rolldown semantics — a throwing\n // init propagates to the caller (and clears `fn`, matching upstream).\n // On success, `fn` is set to 0 so subsequent calls are no-ops.\n const esmInitFixPlugin: Plugin = {\n name: 'timber-esm-init-fix',\n applyToEnvironment(environment) {\n return environment.name === 'rsc' || environment.name === 'ssr';\n },\n renderChunk(code) {\n const lazy = 'var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);';\n if (!code.includes(lazy)) return null;\n\n // Eager-with-retry: attempt init immediately, swallowing failures\n // (forward refs aren't defined yet). After the eager attempt, flip\n // to lazy mode where errors propagate to the caller — consumers'\n // try/catch (framer-motion's optional @emotion dep) must see them.\n const eager = [\n 'var __esmMin = (fn, res) => {',\n ' var eager = 1;',\n ' var l = () => {',\n ' if (fn) { if (eager) { try { res = fn(); fn = 0; } catch(e) {} } else { res = fn(fn = 0); } }',\n ' return res;',\n ' };',\n ' l();',\n ' eager = 0;',\n ' return l;',\n '};',\n ].join(' ');\n\n return { code: code.replace(lazy, eager), map: null };\n },\n };\n\n // Fix Rolldown's `createRequire(import.meta.url)` CJS interop shim for\n // Cloudflare Workers. Rolldown emits this for CJS dependencies (e.g.\n // @opentelemetry/context-async-hooks) that use `require()`. On Workers,\n // `import.meta.url` is `undefined` for non-entry modules, causing:\n // TypeError: The argument 'path' must be a file URL object, a file URL\n // string, or an absolute path string. Received 'undefined'\n //\n // The fix: provide a fallback URL when `import.meta.url` is undefined.\n // The actual URL doesn't matter — `createRequire` only needs it for\n // resolving relative paths, but the only `__require()` calls are for\n // Node built-ins (events, async_hooks) which resolve from any base.\n //\n // The top-level `ssr: { target: 'webworker' }` was supposed to prevent\n // this, but it doesn't propagate to custom environments (rsc) in Vite's\n // Environment API. See LOCAL-405.\n const createRequireFixPlugin: Plugin = {\n name: 'timber-create-require-fix',\n applyToEnvironment(environment) {\n return environment.name === 'rsc' || environment.name === 'ssr';\n },\n renderChunk(code) {\n const pattern = 'createRequire(import.meta.url)';\n if (!code.includes(pattern)) return null;\n\n return {\n code: code.replace(pattern, 'createRequire(import.meta.url || \"file:///app\")'),\n map: null,\n };\n },\n };\n\n return [bundlePlugin, esmInitFixPlugin, createRequireFixPlugin];\n}\n","/**\n * Shared AST helpers for callsite-ID transforms.\n *\n * Both timber-cache-transform (plugins/cache.ts) and timber-prebuilt\n * (plugins/prebuilt.ts) detect calls on bindings imported from the cache\n * module and stamp them with content-derived stable IDs. The node shapes,\n * import-binding resolution, recursive call walk, and ID derivation are\n * identical — only the callee shape and rewrite differ per plugin.\n *\n * See TIM-997, TIM-1053, design/06-caching.md §\"Cache Key Security\".\n */\n\nimport { fnv1aHash } from '../cache/fast-hash.ts';\n\n/** Module specifiers whose bindings the transforms track. */\nexport const CACHE_MODULE_SOURCES = new Set(['@timber-js/app/cache', 'timber/cache']);\n\nexport interface PositionedNode {\n type: string;\n start: number;\n end: number;\n [key: string]: unknown;\n}\n\nexport interface IdentifierNode extends PositionedNode {\n type: 'Identifier';\n name: string;\n}\n\nexport interface ImportDeclarationNode extends PositionedNode {\n type: 'ImportDeclaration';\n source: { value: string };\n specifiers: Array<\n PositionedNode & {\n type: string;\n local: IdentifierNode;\n imported?: IdentifierNode;\n }\n >;\n}\n\nexport interface CallExpressionNode extends PositionedNode {\n type: 'CallExpression';\n callee: PositionedNode;\n arguments: PositionedNode[];\n}\n\nexport interface MemberExpressionNode extends PositionedNode {\n type: 'MemberExpression';\n object: PositionedNode;\n property: PositionedNode;\n computed: boolean;\n}\n\nexport interface ProgramNode extends PositionedNode {\n type: 'Program';\n body: PositionedNode[];\n}\n\nexport interface ImportBindings {\n /** Local names bound to the named import (`import { cache as c }`). */\n named: Set<string>;\n /** Local names of namespace imports (`import * as ns`) of a tracked module. */\n namespaces: Set<string>;\n}\n\n/**\n * Find the local binding name(s) for `importedName` imported from one of\n * `sources` — both named imports (including aliases) and namespace imports\n * (TIM-1054).\n */\nexport function findImportBindings(\n program: ProgramNode,\n sources: ReadonlySet<string>,\n importedName: string\n): ImportBindings {\n const named = new Set<string>();\n const namespaces = new Set<string>();\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const decl = stmt as unknown as ImportDeclarationNode;\n if (!sources.has(decl.source.value)) continue;\n for (const spec of decl.specifiers) {\n if (spec.type === 'ImportNamespaceSpecifier') {\n namespaces.add(spec.local.name);\n continue;\n }\n if (spec.type !== 'ImportSpecifier') continue;\n const specImportedName = spec.imported?.name ?? spec.local.name;\n if (specImportedName === importedName) {\n named.add(spec.local.name);\n }\n }\n }\n return { named, namespaces };\n}\n\n/** Extract all bound identifier names from a parameter/binding pattern. */\nfunction collectPatternNames(node: PositionedNode, out: Set<string>): void {\n switch (node.type) {\n case 'Identifier':\n out.add((node as IdentifierNode).name);\n break;\n case 'AssignmentPattern':\n collectPatternNames(node.left as PositionedNode, out);\n break;\n case 'RestElement':\n collectPatternNames(node.argument as PositionedNode, out);\n break;\n case 'ArrayPattern':\n for (const el of (node.elements as (PositionedNode | null)[] | undefined) ?? []) {\n if (el) collectPatternNames(el, out);\n }\n break;\n case 'ObjectPattern':\n for (const prop of (node.properties as PositionedNode[] | undefined) ?? []) {\n if (prop.type === 'RestElement') {\n collectPatternNames(prop, out);\n } else {\n collectPatternNames(prop.value as PositionedNode, out);\n }\n }\n break;\n case 'TSParameterProperty':\n // TS constructor parameter properties: `constructor(private cache)`\n if (node.parameter) collectPatternNames(node.parameter as PositionedNode, out);\n break;\n }\n}\n\n/** Return the intersection of param names with `tracked`, or null if none. */\nfunction shadowedParamNames(\n params: PositionedNode[] | undefined,\n tracked: ReadonlySet<string>\n): Set<string> | null {\n if (!params) return null;\n const names = new Set<string>();\n for (const p of params) collectPatternNames(p, names);\n const hit = new Set<string>();\n for (const n of names) {\n if (tracked.has(n)) hit.add(n);\n }\n return hit.size > 0 ? hit : null;\n}\n\n/**\n * Collect names declared by `VariableDeclaration`, `FunctionDeclaration`,\n * and `ClassDeclaration` in a statement list. Only scans direct children\n * (not nested blocks). For-loop bindings are NOT included — they are\n * scoped to the loop statement and handled separately in\n * `collectShadowRanges` (codex review round 4 on PR #876).\n */\nfunction collectLexicalDeclNames(stmts: PositionedNode[], out: Set<string>): void {\n for (const stmt of stmts) {\n if (stmt.type === 'VariableDeclaration') {\n for (const decl of (stmt.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n } else if (stmt.type === 'FunctionDeclaration' || stmt.type === 'ClassDeclaration') {\n if (stmt.id && (stmt.id as PositionedNode).type === 'Identifier') {\n out.add((stmt.id as IdentifierNode).name);\n }\n }\n }\n}\n\n/**\n * Extract binding names from a for-loop's init/left clause, but ONLY for\n * `const`/`let` (block-scoped). `var` bindings hoist to the enclosing\n * function and are handled by `collectVarDeclNames` instead (codex review\n * round 5 on PR #876).\n */\nfunction collectForLoopBlockBindingNames(loop: PositionedNode, out: Set<string>): void {\n const init = (loop.init ?? loop.left) as PositionedNode | undefined;\n if (init?.type === 'VariableDeclaration' && init.kind !== 'var') {\n for (const decl of (init.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n}\n\n/**\n * Recursively collect `var` declaration names from a statement tree.\n * `var` hoists to the enclosing function regardless of block nesting,\n * so we must scan nested blocks, loops, switch cases, etc.\n */\nfunction collectVarDeclNames(stmts: PositionedNode[], out: Set<string>): void {\n for (const stmt of stmts) {\n if (stmt.type === 'VariableDeclaration' && stmt.kind === 'var') {\n for (const decl of (stmt.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n // Recurse into blocks, loops, if/else, switch, etc.\n if (stmt.type === 'BlockStatement' || stmt.type === 'StaticBlock') {\n collectVarDeclNames((stmt.body as PositionedNode[] | undefined) ?? [], out);\n } else if (stmt.type === 'IfStatement') {\n if (stmt.consequent) collectVarDeclNames([stmt.consequent as PositionedNode], out);\n if (stmt.alternate) collectVarDeclNames([stmt.alternate as PositionedNode], out);\n } else if (stmt.type === 'SwitchStatement') {\n for (const c of (stmt.cases as PositionedNode[] | undefined) ?? []) {\n collectVarDeclNames((c.consequent as PositionedNode[] | undefined) ?? [], out);\n }\n } else if (\n stmt.type === 'ForStatement' ||\n stmt.type === 'ForInStatement' ||\n stmt.type === 'ForOfStatement' ||\n stmt.type === 'WhileStatement' ||\n stmt.type === 'DoWhileStatement'\n ) {\n const init = (stmt.init ?? stmt.left) as PositionedNode | undefined;\n if (init?.type === 'VariableDeclaration' && init.kind === 'var') {\n for (const decl of (init.declarations as PositionedNode[] | undefined) ?? []) {\n if (decl.id) collectPatternNames(decl.id as PositionedNode, out);\n }\n }\n if (stmt.body) collectVarDeclNames([stmt.body as PositionedNode], out);\n } else if (stmt.type === 'WithStatement' || stmt.type === 'LabeledStatement') {\n if (stmt.body) collectVarDeclNames([stmt.body as PositionedNode], out);\n } else if (stmt.type === 'TryStatement') {\n if (stmt.block) collectVarDeclNames([stmt.block as PositionedNode], out);\n const handler = stmt.handler as PositionedNode | undefined;\n if (handler?.body) collectVarDeclNames([handler.body as PositionedNode], out);\n if (stmt.finalizer) collectVarDeclNames([stmt.finalizer as PositionedNode], out);\n }\n }\n}\n\nexport interface ShadowRange {\n start: number;\n end: number;\n /** Which tracked binding names are shadowed in this range. */\n names: ReadonlySet<string>;\n}\n\n/**\n * Collect byte ranges where any name in `tracked` is shadowed by a\n * function/arrow parameter, catch clause binding, or lexical declaration\n * (`const`/`let`/`var`, `function`, `class`, for-loop binding). Calls\n * inside these ranges must NOT be rewritten — the name resolves to the\n * local binding, not the import (TIM-1141).\n *\n * Each range records WHICH names are shadowed so the consumer can skip\n * only calls to the shadowed name, not unrelated imports (codex review\n * on PR #876).\n *\n * When a scope shadows some-but-not-all tracked names, the walker\n * continues descending to find inner scopes that shadow remaining names\n * (codex review round 2 on PR #876).\n */\nexport function collectShadowRanges(\n node: PositionedNode,\n tracked: ReadonlySet<string>,\n ranges: ShadowRange[]\n): void {\n if (tracked.size === 0) return;\n\n const isFn =\n node.type === 'FunctionDeclaration' ||\n node.type === 'FunctionExpression' ||\n node.type === 'ArrowFunctionExpression';\n\n let remainingTracked = tracked;\n\n // ── Function/arrow parameters + named function expression id ───────\n if (isFn) {\n const paramNames = new Set<string>();\n for (const p of (node.params as PositionedNode[] | undefined) ?? []) {\n collectPatternNames(p, paramNames);\n }\n // Named function expressions: `const w = function cache() { ... }`\n // — the name is in scope inside the body (codex review round 5).\n if (node.type === 'FunctionExpression' && node.id) {\n const fnId = node.id as PositionedNode;\n if (fnId.type === 'Identifier') paramNames.add((fnId as IdentifierNode).name);\n }\n const shadowed = new Set<string>();\n for (const n of paramNames) {\n if (tracked.has(n)) shadowed.add(n);\n }\n if (shadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: shadowed });\n if (shadowed.size === tracked.size) return;\n remainingTracked = new Set([...tracked].filter((n) => !shadowed.has(n)));\n }\n }\n\n // ── Catch clause binding ───────────────────────────────────────────\n if (node.type === 'CatchClause') {\n const param = node.param as PositionedNode | undefined;\n if (param) {\n const shadowed = shadowedParamNames([param], tracked);\n if (shadowed) {\n ranges.push({ start: node.start, end: node.end, names: shadowed });\n if (shadowed.size === tracked.size) return;\n remainingTracked = new Set([...tracked].filter((n) => !shadowed.has(n)));\n }\n }\n }\n\n // ── Named class expressions ───────────────────────────────────────\n // `const C = class cache { ... }` — the class name is in scope inside\n // the class body (codex review round 6 on PR #876).\n if (node.type === 'ClassExpression' && node.id) {\n const clsId = node.id as PositionedNode;\n if (clsId.type === 'Identifier' && remainingTracked.has((clsId as IdentifierNode).name)) {\n const names = new Set([(clsId as IdentifierNode).name]);\n ranges.push({ start: node.start, end: node.end, names });\n if (names.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !names.has(n)));\n }\n }\n\n // ── For-loop bindings (scoped to the loop, not the enclosing body) ─\n // `for (const cache of items) { ... }` shadows `cache` only inside\n // the loop statement, not in the rest of the function. Codex review\n // round 4 on PR #876.\n if (\n node.type === 'ForStatement' ||\n node.type === 'ForInStatement' ||\n node.type === 'ForOfStatement'\n ) {\n const loopNames = new Set<string>();\n collectForLoopBlockBindingNames(node, loopNames);\n const loopShadowed = new Set<string>();\n for (const n of loopNames) {\n if (remainingTracked.has(n)) loopShadowed.add(n);\n }\n if (loopShadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: loopShadowed });\n if (loopShadowed.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !loopShadowed.has(n)));\n }\n }\n\n // ── Lexical declarations in function/block/switch bodies ────────────\n // `const cache = ...`, `function cache() {}`, `class cache {}` inside\n // a function body, block, or switch shadow the tracked name for the\n // enclosing scope. `var` hoists to the enclosing function — scanned\n // recursively. Codex review rounds 3 & 5 on PR #876.\n const isScope =\n isFn ||\n node.type === 'BlockStatement' ||\n node.type === 'SwitchStatement' ||\n node.type === 'StaticBlock';\n if (isScope) {\n let bodyStmts: PositionedNode[] | null = null;\n if (isFn) {\n const body = node.body as PositionedNode | undefined;\n if (body?.type === 'BlockStatement') {\n bodyStmts = (body.body as PositionedNode[] | undefined) ?? null;\n }\n } else if (node.type === 'SwitchStatement') {\n // Switch cases: declarations in unbraced cases are scoped to the switch block\n const caseStmts: PositionedNode[] = [];\n for (const c of (node.cases as PositionedNode[] | undefined) ?? []) {\n for (const s of (c.consequent as PositionedNode[] | undefined) ?? []) {\n caseStmts.push(s);\n }\n }\n bodyStmts = caseStmts;\n } else {\n bodyStmts = (node.body as PositionedNode[] | undefined) ?? null;\n }\n if (bodyStmts) {\n const declNames = new Set<string>();\n collectLexicalDeclNames(bodyStmts, declNames);\n // For function scopes, also collect hoisted `var` declarations\n // from the entire body tree (var hoists past blocks).\n if (isFn) {\n collectVarDeclNames(bodyStmts, declNames);\n }\n const lexShadowed = new Set<string>();\n for (const n of declNames) {\n if (remainingTracked.has(n)) lexShadowed.add(n);\n }\n if (lexShadowed.size > 0) {\n ranges.push({ start: node.start, end: node.end, names: lexShadowed });\n if (lexShadowed.size === remainingTracked.size) return;\n remainingTracked = new Set([...remainingTracked].filter((n) => !lexShadowed.has(n)));\n }\n }\n }\n\n // ── Recurse into children ──────────────────────────────────────────\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n collectShadowRanges(item as PositionedNode, remainingTracked, ranges);\n }\n }\n } else if (typeof (val as PositionedNode).type === 'string') {\n collectShadowRanges(val as PositionedNode, remainingTracked, ranges);\n }\n }\n }\n}\n\n/**\n * Recursively walk AST nodes collecting call expressions accepted by\n * `matches`. Calls are typically at module scope, but calls inside\n * functions/blocks are handled for completeness.\n *\n * Consumers that match by binding NAME should pair this with\n * `collectShadowRanges` to filter out calls in scopes where the tracked\n * name is shadowed (TIM-1141). The prebuilt transform avoids the class\n * entirely by allowlisting top-level declarator positions\n * (plugins/prebuilt.ts).\n */\nexport function findCallSites(\n node: PositionedNode,\n matches: (call: CallExpressionNode) => boolean,\n results: CallExpressionNode[]\n): void {\n if (node.type === 'CallExpression') {\n const call = node as unknown as CallExpressionNode;\n if (matches(call)) {\n results.push(call);\n }\n }\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n const val = node[key];\n if (val && typeof val === 'object') {\n if (Array.isArray(val)) {\n for (const item of val) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n findCallSites(item as PositionedNode, matches, results);\n }\n }\n } else if (typeof (val as PositionedNode).type === 'string') {\n findCallSites(val as PositionedNode, matches, results);\n }\n }\n }\n}\n\n/**\n * Generate a stable callsite ID from a module path, a kind discriminator\n * ('cache' | 'component'), the source text of the enclosing top-level\n * statement, the source text of the call expression, and an occurrence index\n * among fully byte-identical (statement, call) pairs in the same file.\n *\n * The ID is deterministic and:\n * - Stable across cold starts AND across builds/deploys for unchanged calls —\n * inserting, deleting, or reordering other calls does not affect it\n * - Unique across different modules (relPath component)\n * - Unique across distinct calls within a module (statement + span hashes),\n * with fully identical duplicates disambiguated by source-order occurrence\n * - Fresh when the wrapped fn, opts, or enclosing statement change, which\n * intentionally invalidates the old persisted entries\n *\n * The enclosing-statement text is included so that byte-identical calls in\n * different scopes — e.g. two factory helpers with identical call spans —\n * get distinct, insertion-stable IDs. See plugins/cache.ts header for the\n * full derivation rationale (TIM-1053).\n */\nexport function generateStableCallsiteId(\n relativeModulePath: string,\n kind: string,\n statementText: string,\n callSpanText: string,\n occurrence: number\n): string {\n return fnv1aHash(\n `${relativeModulePath}:${kind}:${fnv1aHash(statementText)}:${fnv1aHash(callSpanText)}:${occurrence}`\n );\n}\n","/**\n * timber-cache-transform — Vite plugin that injects stable callsite IDs\n * into `cache.data()` calls imported from `@timber-js/app/cache`.\n *\n * Detected callsite forms (TIM-1054):\n * - named imports, including aliases: `import { cache as c }` + `c.data(fn, opts)`\n * - namespace imports: `import * as ns` + `ns.cache.data(fn, opts)`\n * Forms a per-module transform cannot trace — local variable aliases\n * (`const c = cache`), user re-export wrapper modules, computed access\n * (`cache['data']`) — fall back to the runtime fnId derived from\n * fnv1a(fn.toString()) (see cache/timber-cache.ts), which is deterministic\n * across instances and cold starts of the same build. Without either\n * mechanism, an ordinal counter would collide across instances with a shared\n * CacheHandler (Redis/KV) — cache key poisoning, serving one route's cached\n * data to another.\n *\n * The plugin transforms:\n * cache.data(fn, opts) → cache.data(fn, opts, \"stable-id\")\n * ns.cache.data(fn, opts) → ns.cache.data(fn, opts, \"stable-id\")\n *\n * where stable-id =\n * fnv1a(relPath + \":cache:\" + fnv1a(stmtText) + \":\" + fnv1a(callSpanText) + \":\" + occurrence)\n *\n * stmtText is the source text of the enclosing *top-level statement* and\n * callSpanText is the source text of the cache(...) call expression itself.\n *\n * The ID is derived from the *content* of the call, not its ordinal position\n * in the file. A position-based index (the original TIM-997 scheme) was stable\n * within one build but shifted across builds: inserting, deleting, or\n * reordering a cache() call changed the index of every call below it, so with\n * a persistent shared CacheHandler (Redis/KV) a new function could inherit\n * another function's old ID and serve its persisted data — cross-deploy cache\n * poisoning (TIM-1053). Content hashing makes IDs immune to reordering and\n * unrelated edits, while a changed call gets a fresh ID — which is exactly\n * when invalidation is wanted.\n *\n * The enclosing-statement text is included so that byte-identical cache.data()\n * calls in different scopes — e.g. two factory helpers that each `return\n * cache.data(fn, { ttl: 60 })` — get distinct, insertion-stable IDs: their\n * enclosing declarations differ by name/body even when the call spans are\n * identical. Without it, a source-order occurrence counter alone would shift\n * when an identical span is inserted above, reassigning IDs across deploys.\n * Calls that are byte-identical INCLUDING their enclosing top-level statement\n * are disambiguated by a source-order occurrence index. That residue is safe:\n * identical top-level declarations are a redeclaration error, so fully\n * identical (statement, call) pairs can only be expression statements\n * referencing the same bindings — the same function, where an ID swap is\n * harmless.\n *\n * AST helpers and the ID derivation are shared with timber-prebuilt\n * (plugins/prebuilt.ts) via plugins/callsite-ast.ts.\n *\n * See TIM-997, TIM-1053, design/06-caching.md §\"Cache Key Security\".\n */\n\nimport { relative } from 'node:path';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport {\n CACHE_MODULE_SOURCES,\n collectShadowRanges,\n findCallSites,\n findImportBindings,\n generateStableCallsiteId,\n} from './callsite-ast.ts';\nimport type {\n CallExpressionNode,\n IdentifierNode,\n ImportBindings,\n MemberExpressionNode,\n PositionedNode,\n ProgramNode,\n ShadowRange,\n} from './callsite-ast.ts';\n\n/**\n * Is this callee a `cache.data(...)` call? Matches two forms:\n * - Named import: `cache.data(fn, opts)` where `cache` is the imported binding\n * - Namespace import: `ns.cache.data(fn, opts)` where `ns` is the namespace\n * Computed access (`cache['data']`) is deliberately not matched; it falls back\n * to the runtime fnId derivation.\n */\nfunction isCacheDataCallee(callee: PositionedNode, bindings: ImportBindings): boolean {\n if (callee.type !== 'MemberExpression') return false;\n const member = callee as unknown as MemberExpressionNode;\n if (member.computed) return false;\n if (member.property.type !== 'Identifier' || (member.property as IdentifierNode).name !== 'data')\n return false;\n\n const obj = member.object;\n // Named import: `cache.data(...)` — obj is the imported `cache` identifier\n if (obj.type === 'Identifier') {\n return bindings.named.has((obj as IdentifierNode).name);\n }\n // Namespace import: `ns.cache.data(...)` — obj is `ns.cache`\n if (obj.type === 'MemberExpression') {\n const outer = obj as unknown as MemberExpressionNode;\n return (\n !outer.computed &&\n outer.object.type === 'Identifier' &&\n bindings.namespaces.has((outer.object as IdentifierNode).name) &&\n outer.property.type === 'Identifier' &&\n (outer.property as IdentifierNode).name === 'cache'\n );\n }\n return false;\n}\n\n/**\n * Extract the local binding name that a cache.data callee resolves to — the\n * `cache` identifier for named imports, or the namespace object for `ns.cache.data()`.\n */\nfunction calleeBindingName(callee: PositionedNode, bindings: ImportBindings): string | null {\n if (callee.type !== 'MemberExpression') return null;\n const member = callee as unknown as MemberExpressionNode;\n const obj = member.object;\n // Named import: `cache.data(...)` — binding is `cache`\n if (obj.type === 'Identifier') {\n const name = (obj as IdentifierNode).name;\n return bindings.named.has(name) ? name : null;\n }\n // Namespace import: `ns.cache.data(...)` — binding is `ns`\n if (obj.type === 'MemberExpression') {\n const outer = obj as unknown as MemberExpressionNode;\n if (outer.object.type === 'Identifier') {\n const name = (outer.object as IdentifierNode).name;\n return bindings.namespaces.has(name) ? name : null;\n }\n }\n return null;\n}\n\n/**\n * Generate a stable callsite ID for a cache() call. See callsite-ast.ts for\n * the derivation properties.\n */\nfunction generateStableId(\n relativeModulePath: string,\n statementText: string,\n callSpanText: string,\n occurrence: number\n): string {\n return generateStableCallsiteId(\n relativeModulePath,\n 'cache',\n statementText,\n callSpanText,\n occurrence\n );\n}\n\nexport function timberCacheTransform(ctx: PluginContext): Plugin {\n return {\n name: 'timber-cache-transform',\n\n transform(code, id) {\n if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;\n // Skip node_modules (don't transform third-party code)\n if (id.includes('node_modules')) return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(code);\n } catch {\n return;\n }\n\n const cacheBindings = findImportBindings(program, CACHE_MODULE_SOURCES, 'cache');\n if (cacheBindings.named.size === 0 && cacheBindings.namespaces.size === 0) return;\n\n // Collect byte ranges where tracked binding names are shadowed by\n // function/arrow parameters or catch bindings (TIM-1141). Calls inside\n // these ranges are NOT rewritten — they fall back to the runtime fnId.\n const trackedNames = new Set([...cacheBindings.named, ...cacheBindings.namespaces]);\n const shadowRanges: ShadowRange[] = [];\n collectShadowRanges(program, trackedNames, shadowRanges);\n\n // Check whether the specific binding name a callee resolves to is\n // shadowed at the call position. Only that name is blocked — other\n // tracked imports from the same module remain valid (codex review\n // on PR #876).\n const isCalleeShadowed = (call: CallExpressionNode): boolean => {\n const name = calleeBindingName(call.callee, cacheBindings);\n if (!name) return false;\n return shadowRanges.some(\n (r) => call.start >= r.start && call.start < r.end && r.names.has(name)\n );\n };\n\n // Collect call sites per top-level statement so each call carries its\n // enclosing statement's source text into the ID hash.\n const callSites: Array<{ call: CallExpressionNode; stmt: PositionedNode }> = [];\n for (const stmt of program.body) {\n const calls: CallExpressionNode[] = [];\n findCallSites(\n stmt,\n (call) =>\n call.arguments.length === 2 &&\n isCacheDataCallee(call.callee, cacheBindings) &&\n !isCalleeShadowed(call),\n calls\n );\n for (const call of calls) callSites.push({ call, stmt });\n }\n if (callSites.length === 0) return;\n\n // Sort by position in file so occurrence indices among byte-identical\n // (statement, call) pairs are assigned in deterministic source order\n callSites.sort((a, b) => a.call.start - b.call.start);\n\n const root = ctx.root || process.cwd();\n const relPath = relative(root, id);\n const s = new MagicString(code);\n const occurrences = new Map<string, number>();\n\n for (const { call, stmt } of callSites) {\n const stmtText = code.slice(stmt.start, stmt.end);\n const spanText = code.slice(call.start, call.end);\n const dupKey = stmtText + String.fromCharCode(0) + spanText;\n const occurrence = occurrences.get(dupKey) ?? 0;\n occurrences.set(dupKey, occurrence + 1);\n const stableId = generateStableId(relPath, stmtText, spanText, occurrence);\n // Insert the stable ID as the 3rd argument directly after the last\n // argument — NOT before the closing ')'. The call may already have a\n // trailing comma after the options argument (Prettier v3 default for\n // multiline calls); inserting before ')' would emit `,, \"id\"`, a\n // parse error (TIM-1021). A trailing comma after the inserted\n // argument remains valid JS.\n const lastArg = call.arguments[call.arguments.length - 1];\n s.appendLeft(lastArg.end, `, \"${stableId}\"`);\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n };\n}\n\n// Exported for testing\nexport { generateStableId };\n","/**\n * Per-module syntactic facts for request-dependency analysis.\n *\n * This module is deliberately dumb: it records *what the source says*, with no\n * knowledge of which specifiers or names are interesting. Every judgement —\n * \"is this an accessor\", \"is this a definition object\" — lives in `origin.ts`,\n * which resolves a binding to the module it actually came from.\n *\n * That split is the point. The previous shape asked each module in isolation\n * \"do you import `getSearchParams` from `@timber-js/app/server` and call it\",\n * which any indirection defeats: a barrel re-export, a namespace import, a\n * factory reached through the app's own `_lib`. Each of those was a separate\n * hole and each was found separately (TIM-1291). Recording bindings and edges\n * here, and resolving them across the graph there, closes the family instead of\n * its members.\n *\n * See design/19-client-navigation.md §\"Why the slot comparison ignores the query\".\n */\n\nimport type {\n ProgramNode,\n PositionedNode,\n IdentifierNode,\n CallExpressionNode,\n MemberExpressionNode,\n} from '../callsite-ast.ts';\n\n/**\n * One module-graph edge introduced by an `import` or `export … from`.\n *\n * `imported` is the name as it exists in the *source* module: an export name,\n * `'default'`, or `'*'` for a namespace/star form.\n */\nexport interface ImportEdge {\n source: string;\n imported: string;\n}\n\n/** The callee of `const x = f()` / `const x = ns.f()`. */\nexport type CalleeRef =\n | { kind: 'local'; name: string }\n | { kind: 'member'; object: string; property: string };\n\nexport interface ModuleFacts {\n /** Local name → the edge that bound it (`import { a as b } from 'x'`). */\n importedBindings: Map<string, ImportEdge>;\n /** Exported name → edge, for `export { a as b } from 'x'`. */\n reExports: Map<string, ImportEdge>;\n /** Sources of anonymous `export * from 'x'`, in source order. */\n starReExports: string[];\n /** Exported name → local name, for `export { x }`, `export const x = …`. */\n localExports: Map<string, string>;\n /** Local variable name → the callee that produced its value. */\n factoryCalls: Map<string, CalleeRef>;\n /** Local names invoked directly: `f()`. */\n calledLocals: Set<string>;\n /** `ns.f()` → `ns` → `{ f }`. */\n calledMembers: Map<string, Set<string>>;\n /** Base identifier of a `.get()` chain: `x.get()`, `x().get()`, `x.p.get()`. */\n getterLocals: Set<string>;\n /** `ns.defs.get()` → `ns` → `{ defs }`. */\n getterMembers: Map<string, Set<string>>;\n /** Every name the module *body* mentions — import/export clauses excluded. */\n referencedLocals: Set<string>;\n /** Specifier → resolved module id, filled by the plugin via `this.resolve`. */\n resolvedSources: Map<string, string>;\n /** Specifiers that failed to resolve — treated as request-dependent. */\n unresolvedSources: Set<string>;\n}\n\n/** `export default` has no local name of its own; this stands in for one. */\nexport const DEFAULT_EXPORT = 'default';\n\nexport function createModuleFacts(): ModuleFacts {\n return {\n importedBindings: new Map(),\n reExports: new Map(),\n starReExports: [],\n localExports: new Map(),\n factoryCalls: new Map(),\n calledLocals: new Set(),\n calledMembers: new Map(),\n getterLocals: new Set(),\n getterMembers: new Map(),\n referencedLocals: new Set(),\n resolvedSources: new Map(),\n unresolvedSources: new Set(),\n };\n}\n\n/**\n * Specifiers the origin walk can actually reach, so the plugin resolves those\n * and not every import in the file.\n *\n * A re-export edge is always reachable — a downstream module can ask for any\n * name it forwards. An `import` edge is reachable through any local name the\n * module body mentions, or that it re-exports.\n *\n * The name set must be **the same one the taint rules consult**. Deriving it\n * from the call shapes instead (called, `.get()`d, member-called, minted from)\n * left `read(filters)` — a definition passed as an argument — with its\n * specifier unresolved, so the origin walk reported it inert and the page read\n * as request-independent. Two hand-maintained lists of \"names that matter\" is\n * one list too many; this is the one, and `referencedLocals` is a superset of\n * every call shape by construction, since each of them is an identifier the\n * walk visits. (Codex review round 1 on PR #991.)\n */\nexport function usedSources(facts: ModuleFacts): Set<string> {\n const sources = new Set<string>(facts.starReExports);\n for (const edge of facts.reExports.values()) sources.add(edge.source);\n\n for (const local of facts.referencedLocals) {\n const edge = facts.importedBindings.get(local);\n if (edge) sources.add(edge.source);\n }\n for (const local of facts.localExports.values()) {\n const edge = facts.importedBindings.get(local);\n if (edge) sources.add(edge.source);\n }\n return sources;\n}\n\n/**\n * True when the module cannot affect any answer, so its facts need not be kept.\n *\n * Every judgement bottoms out at a module edge: a call site resolves through\n * `importedBindings`, a chain link through `reExports` / `starReExports`. A\n * module with none of those can only ever resolve to `none` — its exports lead\n * to locals that lead nowhere — which is exactly what a *missing* entry\n * produces. Dropping it is behaviour-preserving and keeps the dev-time map from\n * holding an entry for every leaf module in the graph.\n */\nexport function contributesNothing(facts: ModuleFacts): boolean {\n return (\n facts.importedBindings.size === 0 &&\n facts.reExports.size === 0 &&\n facts.starReExports.length === 0\n );\n}\n\nfunction addToMapSet(map: Map<string, Set<string>>, key: string, value: string): void {\n const existing = map.get(key);\n if (existing) existing.add(value);\n else map.set(key, new Set([value]));\n}\n\n// ─── Declaration collection ──────────────────────────────────────────────\n\n/**\n * A module-export name slot: `Identifier`, or the string-literal form ESTree\n * allows (`export { x as \"a-b\" } from './m'`) — a valid export name that is not\n * a valid identifier.\n */\ntype NameNode = PositionedNode | undefined;\n\ninterface SpecifierNode extends PositionedNode {\n local?: NameNode;\n imported?: NameNode;\n exported?: NameNode;\n}\n\nfunction nameOf(node: NameNode): string | null {\n if (!node) return null;\n if (node.type === 'Identifier') return (node as IdentifierNode).name;\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value;\n return null;\n}\n\n/**\n * `import type { … }` needs no handling here. Vite's TypeScript transform is a\n * core plugin and runs before this one, so types are already erased by the time\n * the analysis parses — and the parser it runs on is JavaScript-only, so\n * unerased TypeScript would throw rather than be silently misread.\n * `tests/request-dep-plugin.test.ts` pins the resulting property through the\n * real pipeline: a type-only accessor import is not request-dependent.\n */\nfunction collectImportDeclaration(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n if (typeof source !== 'string') return;\n for (const spec of (stmt.specifiers as SpecifierNode[] | undefined) ?? []) {\n const local = nameOf(spec.local);\n if (!local) continue;\n if (spec.type === 'ImportNamespaceSpecifier') {\n facts.importedBindings.set(local, { source, imported: '*' });\n } else if (spec.type === 'ImportDefaultSpecifier') {\n facts.importedBindings.set(local, { source, imported: DEFAULT_EXPORT });\n } else if (spec.type === 'ImportSpecifier') {\n facts.importedBindings.set(local, { source, imported: nameOf(spec.imported) ?? local });\n }\n }\n}\n\nfunction collectDeclaredNames(decl: PositionedNode, out: Set<string>): void {\n if (decl.type === 'VariableDeclaration') {\n for (const d of (decl.declarations as PositionedNode[] | undefined) ?? []) {\n const id = d.id as PositionedNode | undefined;\n if (id?.type === 'Identifier') out.add((id as IdentifierNode).name);\n }\n } else if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {\n const id = decl.id as PositionedNode | undefined;\n if (id?.type === 'Identifier') out.add((id as IdentifierNode).name);\n }\n}\n\nfunction collectExportNamed(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n const specifiers = (stmt.specifiers as SpecifierNode[] | undefined) ?? [];\n\n if (typeof source === 'string') {\n // `export { a as b } from './m'` — `local` names the export in './m'.\n for (const spec of specifiers) {\n const imported = nameOf(spec.imported) ?? nameOf(spec.local);\n const exported = nameOf(spec.exported);\n if (imported && exported) facts.reExports.set(exported, { source, imported });\n }\n return;\n }\n\n // `export { x }` / `export { x as y }` — `local` is a binding in this module.\n for (const spec of specifiers) {\n const local = nameOf(spec.local);\n const exported = nameOf(spec.exported);\n if (local && exported) facts.localExports.set(exported, local);\n }\n\n // `export const x = …`, `export function f() {}`\n const declaration = stmt.declaration as PositionedNode | undefined;\n if (declaration) {\n const names = new Set<string>();\n collectDeclaredNames(declaration, names);\n for (const name of names) facts.localExports.set(name, name);\n }\n}\n\nfunction collectExportAll(stmt: PositionedNode, facts: ModuleFacts): void {\n const source = (stmt.source as { value: string } | undefined)?.value;\n if (typeof source !== 'string') return;\n const exported = nameOf(stmt.exported as NameNode);\n if (exported) {\n // `export * as ns from './m'` — a namespace object under one name.\n facts.reExports.set(exported, { source, imported: '*' });\n } else {\n facts.starReExports.push(source);\n }\n}\n\nfunction collectExportDefault(stmt: PositionedNode, facts: ModuleFacts): void {\n const declaration = stmt.declaration as PositionedNode | undefined;\n if (!declaration) return;\n facts.localExports.set(DEFAULT_EXPORT, DEFAULT_EXPORT);\n if (declaration.type === 'Identifier') {\n // `export default x` — alias the default onto the existing binding.\n facts.localExports.set(DEFAULT_EXPORT, (declaration as IdentifierNode).name);\n } else if (declaration.type === 'CallExpression') {\n const ref = calleeRef(declaration as unknown as CallExpressionNode);\n if (ref) facts.factoryCalls.set(DEFAULT_EXPORT, ref);\n }\n}\n\n// ─── Expression collection ───────────────────────────────────────────────\n\nfunction calleeRef(call: CallExpressionNode): CalleeRef | null {\n const callee = call.callee;\n if (callee.type === 'Identifier') {\n return { kind: 'local', name: (callee as IdentifierNode).name };\n }\n if (callee.type === 'MemberExpression') {\n const member = callee as MemberExpressionNode;\n if (\n !member.computed &&\n member.object.type === 'Identifier' &&\n member.property.type === 'Identifier'\n ) {\n return {\n kind: 'member',\n object: (member.object as IdentifierNode).name,\n property: (member.property as IdentifierNode).name,\n };\n }\n }\n return null;\n}\n\n/**\n * Walk down a `.get()` receiver to the identifier it is ultimately rooted in,\n * along with the first property accessed on that identifier.\n *\n * `x.get()` → `x`, no property. `x(a).get()` → `x`. `ns.defs.get()` → `ns`\n * plus `defs`, which is both the namespace-member shape and the\n * `cookies.theme.get()` shape — the resolver tries the base binding and the\n * member, so one walk covers both.\n */\nfunction chainRoot(node: PositionedNode): { base: string; property: string | null } | null {\n let current = node;\n let property: string | null = null;\n for (;;) {\n if (current.type === 'Identifier') {\n return { base: (current as IdentifierNode).name, property };\n }\n if (current.type === 'MemberExpression') {\n const member = current as MemberExpressionNode;\n if (!member.computed && member.property.type === 'Identifier') {\n property = (member.property as IdentifierNode).name;\n } else {\n property = null;\n }\n current = member.object;\n continue;\n }\n if (current.type === 'CallExpression') {\n property = null;\n current = (current as CallExpressionNode).callee;\n continue;\n }\n return null;\n }\n}\n\nfunction collectExpression(node: PositionedNode, facts: ModuleFacts): void {\n if (node.type === 'VariableDeclarator') {\n const id = node.id as PositionedNode | undefined;\n const init = node.init as PositionedNode | undefined;\n if (id?.type === 'Identifier' && init?.type === 'CallExpression') {\n const ref = calleeRef(init as unknown as CallExpressionNode);\n if (ref) facts.factoryCalls.set((id as IdentifierNode).name, ref);\n }\n return;\n }\n\n if (node.type !== 'CallExpression') return;\n const call = node as unknown as CallExpressionNode;\n const callee = call.callee;\n\n if (callee.type === 'Identifier') {\n facts.calledLocals.add((callee as IdentifierNode).name);\n return;\n }\n if (callee.type !== 'MemberExpression') return;\n const member = callee as MemberExpressionNode;\n if (member.computed || member.property.type !== 'Identifier') return;\n const propertyName = (member.property as IdentifierNode).name;\n\n if (propertyName === 'get') {\n const root = chainRoot(member.object);\n if (root) {\n facts.getterLocals.add(root.base);\n if (root.property) addToMapSet(facts.getterMembers, root.base, root.property);\n }\n return;\n }\n if (member.object.type === 'Identifier') {\n addToMapSet(facts.calledMembers, (member.object as IdentifierNode).name, propertyName);\n }\n}\n\n/**\n * Statements whose whole subtree is an import/export *clause* rather than code.\n *\n * The walk skips them so `referencedLocals` means \"the module body mentions\n * this name\". Without the skip every imported name would count as referenced,\n * and a pure barrel — which mentions its names only in the clauses — would be\n * indistinguishable from a module that uses them.\n */\nfunction isClauseOnly(node: PositionedNode): boolean {\n if (node.type === 'ImportDeclaration' || node.type === 'ExportAllDeclaration') return true;\n if (node.type === 'ExportNamedDeclaration') return !node.declaration;\n // `export default someBinding` forwards; `export default f()` is code.\n if (node.type === 'ExportDefaultDeclaration') {\n return (node.declaration as PositionedNode | undefined)?.type === 'Identifier';\n }\n return false;\n}\n\n/**\n * Keys holding *binding* positions rather than references: the name being\n * declared, not a mention of one.\n *\n * `referencedLocals` must exclude these or `export const filters =\n * defineSearchParams({})` would count as referencing `filters`, and possession\n * would then taint every definition module — and through it every page that\n * imports one, whether or not it reads the request. Skipping only these keys\n * keeps a shadowing parameter's *body* uses as references, which over-reports\n * in the safe direction.\n */\nconst BINDING_KEYS: Readonly<Record<string, readonly string[]>> = {\n VariableDeclarator: ['id'],\n FunctionDeclaration: ['id', 'params'],\n FunctionExpression: ['id', 'params'],\n ArrowFunctionExpression: ['params'],\n ClassDeclaration: ['id'],\n ClassExpression: ['id'],\n CatchClause: ['param'],\n};\n\nfunction walk(node: PositionedNode, facts: ModuleFacts): void {\n if (isClauseOnly(node)) return;\n if (node.type === 'Identifier') facts.referencedLocals.add((node as IdentifierNode).name);\n collectExpression(node, facts);\n const bindingKeys = BINDING_KEYS[node.type];\n for (const key of Object.keys(node)) {\n if (key === 'type' || key === 'start' || key === 'end') continue;\n if (bindingKeys?.includes(key)) continue;\n const value = node[key];\n if (!value || typeof value !== 'object') continue;\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && typeof item.type === 'string') {\n walk(item as PositionedNode, facts);\n }\n }\n } else if (typeof (value as PositionedNode).type === 'string') {\n walk(value as PositionedNode, facts);\n }\n }\n}\n\n/**\n * Record every binding, module edge, and call shape in one module.\n *\n * Names are recorded without scope analysis, so a parameter that shadows an\n * imported name is credited to the import. That direction is deliberate: a\n * needlessly request-dependent segment costs a re-render, a wrongly static one\n * serves stale content.\n */\nexport function analyzeModule(program: ProgramNode): ModuleFacts {\n const facts = createModuleFacts();\n\n for (const stmt of program.body) {\n switch (stmt.type) {\n case 'ImportDeclaration':\n collectImportDeclaration(stmt, facts);\n break;\n case 'ExportNamedDeclaration':\n collectExportNamed(stmt, facts);\n break;\n case 'ExportAllDeclaration':\n collectExportAll(stmt, facts);\n break;\n case 'ExportDefaultDeclaration':\n collectExportDefault(stmt, facts);\n break;\n }\n }\n\n walk(program, facts);\n return facts;\n}\n","/**\n * Binding-origin resolution across the module graph.\n *\n * Given a local name at a call site, walk import and re-export edges until the\n * binding lands somewhere that can be classified: a framework request accessor,\n * a definition factory, a definition object minted by one, or nothing of\n * interest. The walk is what makes the analysis indifferent to how the app\n * organises its own code — a barrel, an alias, a namespace import, and a\n * re-export chain five hops deep all reach the same origin (TIM-1291).\n *\n * The asymmetry that governs every judgement here: over-reporting costs a\n * re-render, under-reporting serves stale content to a client that cached a\n * slot whose render varies with the query. So an edge we cannot follow resolves\n * to `unknown`, and `unknown` counts as request-dependent.\n *\n * See design/19-client-navigation.md §\"Why the slot comparison ignores the query\".\n */\n\nimport type { CalleeRef, ImportEdge, ModuleFacts } from './analysis.ts';\n\n// ─── What counts as a request accessor ───────────────────────────────────\n\nconst ACCESSOR_SOURCES = new Set(['@timber-js/app/server', 'next/headers', 'next/headers.js']);\n\nconst ACCESSOR_NAMES = new Set([\n 'getHeaders',\n 'getHeader',\n 'getSearchParams',\n 'getCookieJar',\n 'getCookie',\n // next/headers shim names\n 'headers',\n 'cookies',\n]);\n\nconst DEFINITION_FACTORY_SOURCES = new Set([\n '@timber-js/app/search-params',\n '@timber-js/app/cookies',\n]);\n\nconst DEFINITION_FACTORY_NAMES = new Set(['defineSearchParams', 'defineCookie']);\n\n/** Every specifier the classifier recognises without resolving it. */\nexport const FRAMEWORK_SOURCES: ReadonlySet<string> = new Set([\n ...ACCESSOR_SOURCES,\n ...DEFINITION_FACTORY_SOURCES,\n]);\n\n// ─── Origins ─────────────────────────────────────────────────────────────\n\nexport type Origin =\n /** A request accessor: `getSearchParams`, `cookies`, … */\n | { kind: 'accessor' }\n /** A definition factory: `defineSearchParams`, `defineCookie`. */\n | { kind: 'factory' }\n /** A value minted by a definition factory — `.get()` on it reads the request. */\n | { kind: 'definition' }\n /** A namespace object for a framework module (`import * as h from 'next/headers'`). */\n | { kind: 'framework-namespace'; source: string }\n /** A namespace object for an app module. */\n | { kind: 'namespace'; moduleId: string }\n /** An edge that could not be followed. Treated as request-dependent. */\n | { kind: 'unknown' }\n /** Resolved, and not interesting. */\n | { kind: 'none' };\n\nconst NONE: Origin = { kind: 'none' };\nconst UNKNOWN: Origin = { kind: 'unknown' };\n\n/**\n * Classify an edge that points at a framework module, without resolving it.\n *\n * Returns `null` when the specifier is not a framework source, which is the\n * signal to keep walking. Both name sets are consulted for either source so a\n * specifier that grows a second role does not silently stop matching.\n */\nfunction classifySpecifier(source: string, imported: string): Origin | null {\n const isAccessorSource = ACCESSOR_SOURCES.has(source);\n const isFactorySource = DEFINITION_FACTORY_SOURCES.has(source);\n if (!isAccessorSource && !isFactorySource) return null;\n if (imported === '*') return { kind: 'framework-namespace', source };\n if (isAccessorSource && ACCESSOR_NAMES.has(imported)) return { kind: 'accessor' };\n if (isFactorySource && DEFINITION_FACTORY_NAMES.has(imported)) return { kind: 'factory' };\n return NONE;\n}\n\n/** An origin whose *call* reads the request. */\nfunction callReadsRequest(origin: Origin): boolean {\n return origin.kind === 'accessor' || origin.kind === 'unknown';\n}\n\n/** An origin whose `.get()` reads the request. */\nfunction getterReadsRequest(origin: Origin): boolean {\n return origin.kind === 'definition' || origin.kind === 'unknown';\n}\n\n// ─── Resolver ────────────────────────────────────────────────────────────\n\nexport interface OriginResolver {\n /** Does this module itself read the request? */\n isTainted(moduleId: string): boolean;\n /** Does this module hold a definition factory binding? */\n isDefinitionModule(moduleId: string): boolean;\n /** Does this module call `.get()` on a binding it imported? */\n callsGetterOnImport(moduleId: string): boolean;\n}\n\nexport function createOriginResolver(factsMap: ReadonlyMap<string, ModuleFacts>): OriginResolver {\n /**\n * Cycle guard. A `(module, export)` pair already being resolved contributes\n * `none`: anything it could reach is reachable on the path still unwinding.\n */\n const resolving = new Map<string, Set<string>>();\n\n function enter(moduleId: string, name: string): boolean {\n const names = resolving.get(moduleId);\n if (!names) {\n resolving.set(moduleId, new Set([name]));\n return true;\n }\n if (names.has(name)) return false;\n names.add(name);\n return true;\n }\n\n function leave(moduleId: string, name: string): void {\n resolving.get(moduleId)?.delete(name);\n }\n\n /** Follow one `import`/`export … from` edge out of `moduleId`. */\n function resolveEdge(moduleId: string, edge: ImportEdge): Origin {\n const classified = classifySpecifier(edge.source, edge.imported);\n if (classified) return classified;\n\n const facts = factsMap.get(moduleId);\n const targetId = facts?.resolvedSources.get(edge.source);\n if (!targetId) {\n // An unresolvable specifier is an edge we cannot follow, not an absence\n // of one. A specifier the plugin never tried to resolve (module not\n // analysed) lands here too, and both take the conservative branch.\n return facts?.unresolvedSources.has(edge.source) ? UNKNOWN : NONE;\n }\n if (edge.imported === '*') return { kind: 'namespace', moduleId: targetId };\n return resolveExport(targetId, edge.imported);\n }\n\n /** What does `moduleId` export under `name`? */\n function resolveExport(moduleId: string, name: string): Origin {\n const facts = factsMap.get(moduleId);\n if (!facts) return NONE;\n if (!enter(moduleId, `export:${name}`)) return NONE;\n try {\n const reExport = facts.reExports.get(name);\n if (reExport) return resolveEdge(moduleId, reExport);\n\n const local = facts.localExports.get(name);\n if (local !== undefined) return resolveLocal(moduleId, local);\n\n // `export * from './m'` does not name what it forwards, so every star\n // source is a candidate. Ambiguity is resolved conservatively: the first\n // source that classifies as anything wins.\n for (const source of facts.starReExports) {\n const viaStar = resolveEdge(moduleId, { source, imported: name });\n if (viaStar.kind !== 'none') return viaStar;\n }\n return NONE;\n } finally {\n leave(moduleId, `export:${name}`);\n }\n }\n\n /** What is the local binding `name` in `moduleId`? */\n function resolveLocal(moduleId: string, name: string): Origin {\n const facts = factsMap.get(moduleId);\n if (!facts) return NONE;\n if (!enter(moduleId, `local:${name}`)) return NONE;\n try {\n const imported = facts.importedBindings.get(name);\n if (imported) return resolveEdge(moduleId, imported);\n\n const factoryCall = facts.factoryCalls.get(name);\n if (factoryCall) {\n // `const filters = defineSearchParams(…)` — the *result* is a\n // definition, and `.get()` on it reads the request.\n const callee = resolveCallee(moduleId, factoryCall);\n if (callee.kind === 'factory') return { kind: 'definition' };\n if (callee.kind === 'unknown') return UNKNOWN;\n }\n return NONE;\n } finally {\n leave(moduleId, `local:${name}`);\n }\n }\n\n function resolveCallee(moduleId: string, ref: CalleeRef): Origin {\n if (ref.kind === 'local') return resolveLocal(moduleId, ref.name);\n return resolveMember(moduleId, ref.object, ref.property);\n }\n\n /** `ns.name` where `ns` is a local binding in `moduleId`. */\n function resolveMember(moduleId: string, object: string, name: string): Origin {\n const base = resolveLocal(moduleId, object);\n if (base.kind === 'framework-namespace') {\n return classifySpecifier(base.source, name) ?? NONE;\n }\n if (base.kind === 'namespace') return resolveExport(base.moduleId, name);\n if (base.kind === 'unknown') return UNKNOWN;\n return NONE;\n }\n\n const taintCache = new Map<string, boolean>();\n\n function computeTainted(moduleId: string, facts: ModuleFacts): boolean {\n for (const local of facts.calledLocals) {\n if (callReadsRequest(resolveLocal(moduleId, local))) return true;\n }\n for (const [object, members] of facts.calledMembers) {\n for (const member of members) {\n if (callReadsRequest(resolveMember(moduleId, object, member))) return true;\n }\n }\n for (const local of facts.getterLocals) {\n if (getterReadsRequest(resolveLocal(moduleId, local))) return true;\n }\n for (const [object, members] of facts.getterMembers) {\n for (const member of members) {\n if (getterReadsRequest(resolveMember(moduleId, object, member))) return true;\n }\n }\n return holdsRequestBinding(moduleId, facts);\n }\n\n /**\n * Possession, not use: a module that binds a request accessor or a definition\n * value under a local name is request-dependent whether or not the call is\n * one this analysis can see.\n *\n * The call-shape rules above only find a read that happens through the\n * binding itself. A value can leave the binding first — `const read = flag ?\n * getSearchParams : noop`, `const { get } = filters`, a prop handed to a\n * helper — and every one of those is a fresh way to be missed, which is the\n * shape of bug this ticket exists to stop enumerating. Nothing distinguishes\n * those from an honest unused import except intent, so importing the accessor\n * at all is treated as reading it.\n *\n * The rule is scoped by *reference*, not by export shape, and that scoping is\n * what keeps it from being useless: `import { getSearchParams } from\n * '@timber-js/app/server'; export { getSearchParams }` is a barrel whose body\n * never mentions the name, and tainting it would taint every page that\n * imports anything from that barrel. The forwarded name stays resolvable\n * through `resolveExport`, so the page that actually calls it is still caught\n * one hop later, in the module that uses it.\n *\n * Scoping on \"the module only forwards it\" would have been the natural\n * phrasing and is wrong: a barrel can forward a name *and* use it\n * (`export { getSearchParams }` beside `const read = flag ? getSearchParams\n * : noop`), and that module is exactly the one this rule exists to catch.\n * `referencedLocals` excludes import/export clauses and nothing else, so\n * forwarding is exempt only when it is all the module does with the name.\n *\n * `unknown` is deliberately not included: an unresolvable specifier taints\n * only when something is actually called or read on it, or every module with\n * one broken import would go request-dependent.\n */\n function holdsRequestBinding(moduleId: string, facts: ModuleFacts): boolean {\n for (const local of facts.referencedLocals) {\n const origin = resolveLocal(moduleId, local);\n if (origin.kind === 'accessor' || origin.kind === 'definition') return true;\n }\n return false;\n }\n\n return {\n isTainted(moduleId) {\n const cached = taintCache.get(moduleId);\n if (cached !== undefined) return cached;\n const facts = factsMap.get(moduleId);\n const result = facts ? computeTainted(moduleId, facts) : false;\n taintCache.set(moduleId, result);\n return result;\n },\n\n isDefinitionModule(moduleId) {\n const facts = factsMap.get(moduleId);\n if (!facts) return false;\n for (const edge of facts.importedBindings.values()) {\n const origin = resolveEdge(moduleId, edge);\n if (origin.kind === 'factory') return true;\n // `import * as sp from '@timber-js/app/search-params'` — the factory is\n // behind a member access, so the whole namespace counts.\n if (\n origin.kind === 'framework-namespace' &&\n DEFINITION_FACTORY_SOURCES.has(origin.source)\n ) {\n return true;\n }\n }\n return false;\n },\n\n callsGetterOnImport(moduleId) {\n const facts = factsMap.get(moduleId);\n if (!facts) return false;\n for (const local of facts.getterLocals) {\n if (facts.importedBindings.has(local)) return true;\n }\n return false;\n },\n };\n}\n","/**\n * timber-request-dep — Static module-graph analysis for request-dependency.\n *\n * Replaces runtime ALS-based taint tracking with a build/dev-time computed\n * map: segment entry file → statically request-dependent?\n *\n * A segment/slot is request-dependent iff any module reachable from its\n * layout/page/default in the RSC module graph (stopping at client-reference\n * boundaries) reads the request: it calls a request accessor (`getHeaders`,\n * `getSearchParams`, `cookies`, …) or calls `.get()` on a value minted by\n * `defineSearchParams` / `defineCookie`.\n *\n * \"Calls a request accessor\" is decided by resolving the call site's binding\n * back through import and re-export edges (`origin.ts`), not by matching the\n * calling module's own import declarations. That distinction is the whole\n * ticket: a barrel, an alias, or a namespace import used to make a page that\n * reads the query look static, and a static slot is cached and skipped on a\n * query-only navigation — serving stale content (TIM-1273, TIM-1291).\n *\n * This is deterministic, covers children/barrels/node_modules/Suspense-\n * deferred code, and is computed before any byte is flushed.\n *\n * See design/19-client-navigation.md §\"X-Timber-State-Tree Header\"\n */\n\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../../plugin-context.ts';\nimport type { ProgramNode } from '../callsite-ast.ts';\nimport { analyzeModule, usedSources, contributesNothing, type ModuleFacts } from './analysis.ts';\nimport { createOriginResolver, FRAMEWORK_SOURCES } from './origin.ts';\n\nexport type { ModuleFacts } from './analysis.ts';\nexport { analyzeModule, usedSources } from './analysis.ts';\nexport { createOriginResolver } from './origin.ts';\n\n// ─── Framework module detection ─────────────────────────────────────────\n\nexport function isFrameworkModule(id: string): boolean {\n return (\n /[\\\\/]node_modules[\\\\/]@timber-js[\\\\/]app[\\\\/]/.test(id) ||\n /[\\\\/]packages[\\\\/]timber-app[\\\\/]src[\\\\/]/.test(id)\n );\n}\n\n// ─── Pre-filter ──────────────────────────────────────────────────────────\n\n/**\n * Cheap gate before parsing.\n *\n * This used to be a substring match on the accessor and factory names, which\n * was sound only for the analysis it served: when a call site had to name the\n * framework binding in its own import declaration, a module with no such name\n * could not be a call site. Resolving bindings across the graph removes that\n * guarantee — with\n *\n * // _lib/index.ts\n * export { getSearchParams as query } from '@timber-js/app/server';\n * // page.tsx\n * import { query } from './_lib';\n * export default function Page() { return query(); }\n *\n * the page contains no accessor name, no `.get(`, and no re-export syntax, and\n * skipping it would have put the rename right back where the barrel was. So the\n * gate is now structural: a module matters if it has any module-level binding\n * to follow. What it skips is source with no `import` and no `export` at all —\n * data blobs, generated constants, side-effect scripts — none of which can name\n * a framework binding or forward one.\n */\nfunction hasModuleBindings(code: string): boolean {\n return code.includes('import') || code.includes('export');\n}\n\n// ─── Module graph reachability ───────────────────────────────────────────\n\nexport interface ReachabilityInput {\n factsMap: ReadonlyMap<string, ModuleFacts>;\n getImports: (id: string) => string[];\n /**\n * Does the graph this walk runs over contain this module at all?\n *\n * Only the entry needs asking. Every other id the walk visits comes out of\n * `getImports`, which enumerates edges the graph already resolved, so those\n * are known by construction. The entry comes from outside — the route\n * manifest's `filePath`, produced by the scanner from the filesystem — and\n * nothing guarantees it is spelled the way the graph spells it, or that the\n * module has been pulled through the pipeline yet.\n */\n isKnownModule: (id: string) => boolean;\n}\n\n/**\n * Walk the module graph from an entry, returning true if any module reachable\n * from it reads the request.\n *\n * Two passes, and the second is a deliberately blunt backstop:\n *\n * 1. **Binding origins.** For each reachable module, resolve every call site's\n * binding to its origin. This is precise and indifferent to indirection.\n * 2. **Definition reachability.** A module that calls `.get()` on *something*\n * it imported, with a module holding a definition factory reachable behind\n * that import, counts too. The origin walk cannot see through a value that\n * is computed rather than bound — `getFilterCookie(key).get()`, where the\n * helper returns a definition — and this pass can.\n *\n * The second pass over-reports by construction, which is the safe direction: a\n * needlessly request-dependent segment costs a re-render, a wrongly static one\n * serves stale content.\n *\n * An entry the graph does not contain is an edge we failed to walk, not the\n * absence of one — the same rule an unresolvable specifier gets. Without the\n * check it reads as an entry with no imports and no facts, and both passes fall\n * through to `false`: confidently request-INdependent, for a module nothing\n * ever looked at. In the build that answer is worse than no answer, because it\n * is written into `requestDep` as a definite `false` and the runtime's own\n * \"absent key → conservative\" fallback never fires.\n */\nexport function isReachableTaintSource(entryId: string, input: ReachabilityInput): boolean {\n const { factsMap, getImports, isKnownModule } = input;\n if (!isKnownModule(entryId)) return true;\n const resolver = createOriginResolver(factsMap);\n\n const visited = new Set<string>();\n const stack = [entryId];\n\n while (stack.length > 0) {\n const id = stack.pop()!;\n if (visited.has(id)) continue;\n visited.add(id);\n\n if (resolver.isTainted(id)) return true;\n\n for (const imp of getImports(id)) {\n // Stop at client boundaries — 'use client' modules in the RSC graph\n // resolve to generated proxy stubs with no further imports.\n // Also stop at virtual modules (they're framework internals).\n if (!imp.startsWith('\\0') && !visited.has(imp)) {\n stack.push(imp);\n }\n }\n }\n\n const reachesDefinition = makeDefinitionReachability(resolver.isDefinitionModule, getImports);\n for (const id of visited) {\n if (!resolver.callsGetterOnImport(id)) continue;\n if (reachesDefinition(id)) return true;\n }\n\n return false;\n}\n\n/**\n * \"Can a definition module be reached from this module's imports?\", memoized\n * across the queries one entry makes.\n *\n * Walks the graph rather than testing direct imports, because `export … from`\n * is an ordinary module edge and a barrel is the common way an app shares one\n * `defineSearchParams` across routes.\n *\n * Cycles terminate on the memo seeded with `false`; a module already being\n * resolved contributes nothing, which is correct — anything it could reach is\n * reachable on the path that is still unwinding.\n */\nfunction makeDefinitionReachability(\n isDefinitionModule: (id: string) => boolean,\n getImports: (id: string) => string[]\n): (id: string) => boolean {\n const cache = new Map<string, boolean>();\n\n return function reaches(id: string): boolean {\n const cached = cache.get(id);\n if (cached !== undefined) return cached;\n cache.set(id, false); // cycle guard: assume false while resolving\n\n let result = false;\n for (const imp of getImports(id)) {\n if (imp.startsWith('\\0')) continue;\n if (isDefinitionModule(imp) || reaches(imp)) {\n result = true;\n break;\n }\n }\n cache.set(id, result);\n return result;\n };\n}\n\n// ─── Plugin ──────────────────────────────────────────────────────────────\n\nconst BRIDGE_KEY = Symbol.for('timber:request-dep');\n\ninterface ResolvePluginContext {\n parse(code: string): ProgramNode;\n resolve(source: string, importer: string): Promise<{ id: string } | null>;\n}\n\n/**\n * Resolve every specifier the module has an edge to, so the origin walk can\n * follow them later without a module graph.\n *\n * Framework specifiers are classified by name and never resolved — that is what\n * keeps the terminal check independent of how `@timber-js/app` happens to be\n * installed. A specifier that fails to resolve is recorded as unresolved rather\n * than dropped, so the walk can take the conservative branch on it.\n */\nasync function resolveEdgeSources(\n pluginCtx: ResolvePluginContext,\n facts: ModuleFacts,\n importer: string\n): Promise<void> {\n for (const source of usedSources(facts)) {\n if (FRAMEWORK_SOURCES.has(source)) continue;\n try {\n const resolved = await pluginCtx.resolve(source, importer);\n if (resolved?.id) facts.resolvedSources.set(source, resolved.id);\n else facts.unresolvedSources.add(source);\n } catch {\n facts.unresolvedSources.add(source);\n }\n }\n}\n\nexport function timberRequestDep(ctx: PluginContext): Plugin {\n const factsMap = new Map<string, ModuleFacts>();\n const cache = new Map<string, boolean>();\n\n return {\n name: 'timber-request-dep',\n // Only run in RSC environment — that's where server components render.\n applyToEnvironment(env) {\n return env.name === 'rsc';\n },\n\n async transform(code, id) {\n // Skip non-JS (include .mdx/.md — compiled to JS by timber-mdx before this runs)\n if (!/\\.[mc]?[jt]sx?$/.test(id) && !/\\.mdx?$/.test(id)) return;\n // Skip virtual modules\n if (id.startsWith('\\0') || id.startsWith('virtual:')) return;\n // Skip framework modules — their internal accessor calls (e.g.,\n // getCookieJar in define-cookie.ts) are implementation details.\n // In dev they're externalized and never reach transform; in prod\n // they would cause false positives (any module importing defineCookie\n // would be tainted). Analysis relies on user-code call patterns.\n if (isFrameworkModule(id)) return;\n // Cheap structural gate\n if (!hasModuleBindings(code)) return;\n\n const pluginCtx = this as unknown as ResolvePluginContext;\n const facts = analyzeModule(pluginCtx.parse(code));\n if (contributesNothing(facts)) {\n factsMap.delete(id);\n return undefined;\n }\n await resolveEdgeSources(pluginCtx, facts, id);\n factsMap.set(id, facts);\n\n // No code transform needed — this is analysis only.\n return undefined;\n },\n\n configureServer(server) {\n // Register the bridge so runtime can query request-dep status.\n const resolver = (filePath: string): boolean => {\n if (cache.has(filePath)) return cache.get(filePath)!;\n\n const rscEnv = server.environments?.rsc;\n if (!rscEnv?.moduleGraph) {\n return true; // Unknown → conservative\n }\n\n const getImports = (moduleId: string): string[] => {\n const mod = rscEnv.moduleGraph.getModuleById(moduleId);\n if (!mod) return [];\n const result: string[] = [];\n for (const imp of mod.importedModules) {\n if (imp.id) result.push(imp.id);\n }\n return result;\n };\n\n const isKnownModule = (moduleId: string): boolean =>\n rscEnv.moduleGraph.getModuleById(moduleId) !== undefined;\n\n const result = isReachableTaintSource(filePath, { factsMap, getImports, isKnownModule });\n\n // Do not memoize the conservative answer for an entry the graph has\n // not seen. Dev loads modules on demand, so \"unknown\" is a statement\n // about *now*, and the cache is only invalidated by file events —\n // caching it would pin the segment request-dependent for the rest of\n // the session even after the module is pulled in.\n if (isKnownModule(filePath)) cache.set(filePath, result);\n return result;\n };\n\n (globalThis as Record<symbol, unknown>)[BRIDGE_KEY] = resolver;\n\n // Clear cache on file changes\n const clearCache = () => cache.clear();\n server.watcher.on('change', clearCache);\n server.watcher.on('add', clearCache);\n server.watcher.on('unlink', clearCache);\n },\n\n buildEnd() {\n // Prod: compute the full map and register on globalThis for the\n // build manifest plugin to pick up.\n if (ctx.dev) return;\n\n const getModuleInfo = (\n this as unknown as {\n getModuleInfo: (\n id: string\n ) => { importedIds?: string[]; dynamicallyImportedIds?: string[] } | null;\n }\n ).getModuleInfo;\n\n const getImports = (moduleId: string): string[] => {\n const info = getModuleInfo(moduleId);\n if (!info) return [];\n return [...(info.importedIds ?? []), ...(info.dynamicallyImportedIds ?? [])];\n };\n\n // `!= null` rather than `!== null`: the declared return type is\n // `… | null`, but a bundler that hands back `undefined` for an unknown\n // id would otherwise read as \"known\" and put us right back on the\n // confidently-wrong `false`.\n const isKnownModule = (moduleId: string): boolean => getModuleInfo(moduleId) != null;\n\n const requestDepMap: Record<string, boolean> = {};\n\n // Walk the route tree to find all segment entry files\n if (ctx.routeTree) {\n walkSegmentTree(ctx.routeTree.root as unknown as WalkableNode, (filePath: string) => {\n requestDepMap[filePath] = isReachableTaintSource(filePath, {\n factsMap,\n getImports,\n isKnownModule,\n });\n });\n }\n\n // Store on ctx for build-manifest plugin to serialize into the manifest.\n // Prod runtime reads from __TIMBER_BUILD_MANIFEST__.requestDep.\n //\n // Assigned unconditionally, including when there is no route tree to\n // walk: the field's presence is what tells the build-manifest plugin the\n // analysis ran at all, so leaving it undefined on the empty-tree path\n // would report \"the RSC environment never analysed anything\" for an app\n // that genuinely has no segments.\n ctx.requestDepMap = requestDepMap;\n },\n };\n}\n\ninterface WalkableNode {\n layout?: { filePath: string };\n page?: { filePath: string };\n default?: { filePath: string };\n children?: unknown[];\n slots?: Record<string, unknown>;\n}\n\nfunction walkSegmentTree(node: WalkableNode, fn: (filePath: string) => void): void {\n if (node.layout) fn(node.layout.filePath);\n if (node.page) fn(node.page.filePath);\n if (node.default) fn((node.default as { filePath: string }).filePath);\n if (node.children) {\n for (const child of node.children) {\n walkSegmentTree(child as typeof node, fn);\n }\n }\n if (node.slots) {\n for (const slot of Object.values(node.slots)) {\n walkSegmentTree(slot as typeof node, fn);\n }\n }\n}\n","/**\n * JSX call-site props extraction for prebuilt components (TIM-1142).\n *\n * At build time, the timber-prebuilt transform captures the exact props\n * from each JSX usage site of a cache.component binding so the post-build\n * capture pass can prerender entries for each distinct prop set. Only\n * statically analyzable props (JSON-safe literals, arrays, and plain\n * objects) are captured; dynamic/computed props bail — those call sites\n * fall back to live rendering per design/44 §Props Derivation.\n *\n * See design/44-render-at-build-time.md §Props Derivation at Build Time.\n */\n\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { IdentifierNode, PositionedNode, ProgramNode } from './callsite-ast.ts';\n\ninterface JSXElementNode extends PositionedNode {\n type: 'JSXElement';\n openingElement: {\n type: 'JSXOpeningElement';\n name: PositionedNode;\n attributes: PositionedNode[];\n };\n}\n\ninterface JSXAttributeNode extends PositionedNode {\n type: 'JSXAttribute';\n name: { type: string; name?: string };\n value: PositionedNode | null;\n}\n\ninterface JSXExpressionContainerNode extends PositionedNode {\n type: 'JSXExpressionContainer';\n expression: PositionedNode;\n}\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/**\n * Try to extract a static JSON-safe value from an AST expression node.\n * Returns `undefined` (not null — null is a valid JSON value) when the\n * expression is dynamic/computed and cannot be captured statically.\n */\nfunction tryExtractStaticValue(node: PositionedNode): JsonValue | undefined {\n if (node.type === 'Literal') {\n const val = (node as { value?: unknown }).value;\n if (\n val === null ||\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n return val as JsonValue;\n }\n return undefined; // regex or bigint literal\n }\n if (node.type === 'UnaryExpression') {\n const unary = node as unknown as { operator: string; argument: PositionedNode };\n if (unary.operator === '-' && unary.argument.type === 'Literal') {\n const val = (unary.argument as { value?: unknown }).value;\n if (typeof val === 'number') return -val;\n }\n return undefined;\n }\n if (node.type === 'TemplateLiteral') {\n const tpl = node as unknown as {\n quasis: { value: { cooked: string } }[];\n expressions: unknown[];\n };\n if (tpl.expressions.length === 0) return tpl.quasis[0]?.value.cooked ?? undefined;\n return undefined;\n }\n if (node.type === 'ArrayExpression') {\n const elements = (node as unknown as { elements: (PositionedNode | null)[] }).elements;\n const arr: JsonValue[] = [];\n for (const el of elements) {\n if (el === null) return undefined; // sparse\n const val = tryExtractStaticValue(el);\n if (val === undefined) return undefined;\n arr.push(val);\n }\n return arr;\n }\n if (node.type === 'ObjectExpression') {\n const properties = (node as unknown as { properties: PositionedNode[] }).properties;\n const obj: Record<string, JsonValue> = {};\n for (const prop of properties) {\n if (prop.type === 'SpreadElement') return undefined;\n if (prop.type !== 'Property') return undefined;\n const p = prop as unknown as {\n computed?: boolean;\n key: PositionedNode & { name?: string; value?: unknown };\n value: PositionedNode;\n };\n if (p.computed) return undefined;\n const keyName =\n p.key.type === 'Identifier'\n ? p.key.name\n : p.key.type === 'Literal'\n ? String(p.key.value)\n : undefined;\n if (keyName === undefined) return undefined;\n const val = tryExtractStaticValue(p.value);\n if (val === undefined) return undefined;\n obj[keyName] = val;\n }\n return obj;\n }\n return undefined;\n}\n\n/**\n * Extract static props from a JSX element's attributes. Returns null if\n * any attribute is dynamic (spread, computed expression, JSX element, etc.)\n * — the component must fall back to dynamic rendering for that call site.\n */\nexport function extractStaticJsxProps(\n attributes: PositionedNode[]\n): Record<string, JsonValue> | null {\n const props: Record<string, JsonValue> = {};\n for (const attr of attributes) {\n if (attr.type === 'JSXSpreadAttribute') return null;\n if (attr.type !== 'JSXAttribute') return null;\n const jsxAttr = attr as unknown as JSXAttributeNode;\n const name = jsxAttr.name?.name;\n if (!name) return null;\n // React strips key and ref before passing to component props — including\n // them would produce cache entries unaddressable at request time.\n if (name === 'key' || name === 'ref') continue;\n if (jsxAttr.value === null) {\n props[name] = true;\n continue;\n }\n if (jsxAttr.value.type === 'Literal') {\n const val = tryExtractStaticValue(jsxAttr.value);\n if (val === undefined) return null;\n props[name] = val;\n continue;\n }\n if (jsxAttr.value.type === 'JSXExpressionContainer') {\n const container = jsxAttr.value as unknown as JSXExpressionContainerNode;\n const val = tryExtractStaticValue(container.expression);\n if (val === undefined) return null;\n props[name] = val;\n continue;\n }\n return null;\n }\n return props;\n}\n\n/**\n * Walk an AST tree and collect JSX usages of the given binding names,\n * returning the static props for each usage. Returns a map of\n * bindingName → array of static prop objects (or null for dynamic props).\n */\nexport function collectJsxUsages(\n program: ProgramNode,\n bindingNames: Set<string>\n): Map<string, Array<Record<string, JsonValue> | null>> {\n const result = new Map<string, Array<Record<string, JsonValue> | null>>();\n const walk = (node: unknown) => {\n if (!node || typeof node !== 'object') return;\n const n = node as PositionedNode;\n if (n.type === 'JSXElement') {\n const jsx = n as unknown as JSXElementNode;\n const tagName = jsx.openingElement.name;\n if (tagName.type === 'JSXIdentifier') {\n const name = (tagName as IdentifierNode).name;\n if (bindingNames.has(name)) {\n // Children become props.children at runtime — if the element has\n // children we can't capture the full props shape statically, so\n // treat it as a dynamic call site (bail to null).\n const children = (jsx as unknown as { children?: unknown[] }).children ?? [];\n const hasChildren =\n children.length > 0 &&\n children.some((c: unknown) => {\n const child = c as PositionedNode;\n if (child.type === 'JSXText') {\n // Whitespace-only text nodes are not passed as children\n return (child as unknown as { value: string }).value.trim().length > 0;\n }\n return true;\n });\n const props = hasChildren ? null : extractStaticJsxProps(jsx.openingElement.attributes);\n const usages = result.get(name) ?? [];\n usages.push(props);\n result.set(name, usages);\n }\n }\n }\n for (const value of Object.values(n)) {\n if (Array.isArray(value)) {\n for (const item of value) walk(item);\n } else if (value && typeof value === 'object' && 'type' in value) {\n walk(value);\n }\n }\n };\n for (const stmt of program.body) walk(stmt);\n return result;\n}\n\n/**\n * Deep stable JSON stringification with recursively sorted keys.\n * `JSON.stringify` with an array replacer only includes listed keys at\n * ALL nesting levels, so `{config:{theme:'dark'}}` and\n * `{config:{theme:'light'}}` would both serialize as `{\"config\":{}}`.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n if (Array.isArray(value)) return '[' + value.map(stableStringify).join(',') + ']';\n const obj = value as Record<string, unknown>;\n const parts = Object.keys(obj)\n .sort()\n .map((k) => JSON.stringify(k) + ':' + stableStringify(obj[k]));\n return '{' + parts.join(',') + '}';\n}\n\n/**\n * Add a distinct props object to the call-site-props map for a component,\n * deduplicating by deep JSON value (recursively sorted keys).\n */\nexport function recordCallSiteProps(\n ctx: PluginContext,\n componentId: string,\n props: Record<string, JsonValue>\n): void {\n ctx.prebuiltCallSiteProps ??= new Map();\n const existing = ctx.prebuiltCallSiteProps.get(componentId) ?? [];\n const canonical = stableStringify(props);\n const isDuplicate = existing.some((p) => stableStringify(p) === canonical);\n if (!isDuplicate) {\n existing.push(props);\n ctx.prebuiltCallSiteProps.set(componentId, existing);\n }\n}\n","/**\n * Static analysis of `cache.component(fn, options)` option literals for\n * the timber-prebuilt transform: can this call site's options put the\n * component in the prerender tier?\n *\n * Runtime-tier call sites must do NO build work — recording them would\n * make the post-build hook import the built RSC entry (running production\n * startup) and load route modules for routes that have nothing to\n * prerender (codex P2 on PR #836). The analysis is conservative in one\n * direction only: over-inclusion costs a wasted entry load (the capture\n * pass re-checks the real options at runtime and skips), under-inclusion\n * would silently skip prerendering.\n */\n\nimport type { CallExpressionNode, PositionedNode } from './callsite-ast.ts';\n\nconst EXPRESSION_WRAPPER_TYPES = new Set([\n 'TSAsExpression',\n 'TSSatisfiesExpression',\n 'TSNonNullExpression',\n 'ParenthesizedExpression',\n]);\n\n/** Unwrap TS expression wrappers (`as`, `satisfies`, `!`, parens). */\nexport function unwrapExpression(node: PositionedNode): PositionedNode {\n let current = node;\n while (EXPRESSION_WRAPPER_TYPES.has(current.type) && current.expression) {\n current = current.expression as PositionedNode;\n }\n return current;\n}\n\ninterface ObjectPropertyNode extends PositionedNode {\n type: 'Property';\n computed?: boolean;\n key: PositionedNode & { name?: string; value?: unknown };\n value: PositionedNode & { value?: unknown };\n}\n\n/** Three-state static knowledge about a property's runtime effect. */\ntype Tri = 'yes' | 'no' | 'unknown';\n\n/**\n * Statically classify a `slots` value node against resolveSlotNames'\n * runtime rules (server/prebuilt/slots.ts):\n *\n * - `yes` — certainly an ACTIVE shape: dense, non-empty array literal of\n * non-empty string literals.\n * - `no` — certainly NOT active (absent/empty/malformed): registration\n * falls back to non-slot semantics with `prerender` preserved.\n * - `unknown` — identifiers, spreads, holes, non-literal elements.\n */\nfunction classifySlotsValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'ArrayExpression') {\n const elements = ((value as unknown as { elements: (PositionedNode | null)[] }).elements ??\n []) as (PositionedNode | null)[];\n if (elements.length === 0) return 'no'; // empty → kind 'none'\n let allValidStrings = true;\n for (const el of elements) {\n if (el === null) return 'no'; // hole → sparse → malformed at runtime\n if (el.type === 'SpreadElement') return 'unknown';\n const entry = unwrapExpression(el) as { type: string; value?: unknown };\n if (entry.type !== 'Literal') {\n allValidStrings = false; // could still be a valid string at runtime\n continue;\n }\n if (typeof entry.value !== 'string' || entry.value.length === 0) {\n return 'no'; // a non-string/empty literal is malformed regardless of the rest\n }\n }\n return allValidStrings ? 'yes' : 'unknown';\n }\n if (value.type === 'Literal') return 'no'; // null / primitive → malformed → disabled\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') {\n return 'no'; // absent\n }\n return 'unknown';\n}\n\n/** Statically classify whether a `ttl` value gives a runtime lifetime (`ttl !== undefined`). */\nfunction classifyTtlValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'Literal') return 'yes'; // any literal (number, null, …) !== undefined\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') return 'no';\n return 'unknown';\n}\n\n/** Statically classify whether a `tags` value gives a runtime lifetime (`tags != null`). */\nfunction classifyTagsValue(node: PositionedNode): Tri {\n const value = unwrapExpression(node);\n if (value.type === 'ArrayExpression') return 'yes';\n if (value.type === 'ArrowFunctionExpression' || value.type === 'FunctionExpression') return 'yes';\n if (value.type === 'Literal') {\n return (value as { value?: unknown }).value === null ? 'no' : 'yes';\n }\n if (value.type === 'Identifier' && (value as { name?: string }).name === 'undefined') return 'no';\n return 'unknown';\n}\n\n/**\n * Can this call site's options put the component in the prerender tier?\n * The answer is static only when the options argument is an object\n * literal:\n *\n * - literal with `prerender: true` → yes\n * - literal with `prerender: false`/absent → no (spread-free)\n * - literal with statically ACTIVE `slots` + certain runtime lifetime\n * → no — registration strips `prerender` for active slot components\n * (TIM-1173), so attributing the callsite would make the post-build\n * hook import the RSC entry and enumerate route params for entries\n * the capture pass then skips (codex P2 on PR #890)\n * - anything else (identifier, spread, non-literal values)\n * → conservatively yes — the capture pass re-checks at runtime\n *\n * Properties walk in source order with last-write-wins, mirroring\n * object-literal evaluation: `{ prerender: false, ...opts }` may end up\n * prerenderable (the spread can override), while `{ ...opts,\n * prerender: false }` is statically false (codex P2 on PR #836).\n * Computed keys are treated like spreads — they may evaluate to any of\n * the tracked names.\n */\nexport function mayPrerender(call: CallExpressionNode): boolean {\n if (call.arguments.length < 2) return false; // no options → no lifetime → never prerender\n const options = unwrapExpression(call.arguments[1] as PositionedNode);\n if (options.type !== 'ObjectExpression') return true;\n const properties = (options as unknown as { properties: PositionedNode[] }).properties ?? [];\n\n type Verdict = 'absent' | 'true' | 'false' | 'unknown';\n let verdict: Verdict = 'absent';\n let slotsActive: Tri = 'no'; // absent slots are certainly not active\n let ttl: Tri = 'no';\n let tags: Tri = 'no';\n\n for (const prop of properties) {\n if (prop.type === 'SpreadElement' || (prop as ObjectPropertyNode).computed) {\n // A spread/computed key may write ANY of the tracked options.\n verdict = 'unknown';\n slotsActive = 'unknown';\n ttl = 'unknown';\n tags = 'unknown';\n continue;\n }\n if (prop.type !== 'Property') continue;\n const property = prop as ObjectPropertyNode;\n const keyName =\n property.key.type === 'Identifier'\n ? property.key.name\n : property.key.type === 'Literal'\n ? String(property.key.value)\n : undefined;\n if (keyName === 'prerender') {\n const value = unwrapExpression(property.value);\n if (value.type === 'Literal') {\n verdict = (value as { value?: unknown }).value === true ? 'true' : 'false';\n } else {\n verdict = 'unknown'; // `prerender: flag` — not statically known\n }\n } else if (keyName === 'slots') {\n slotsActive = classifySlotsValue(property.value);\n } else if (keyName === 'ttl') {\n ttl = classifyTtlValue(property.value);\n } else if (keyName === 'tags') {\n tags = classifyTagsValue(property.value);\n }\n }\n\n if (verdict !== 'true' && verdict !== 'unknown') return false;\n // Active slots + certain runtime lifetime → registration strips\n // prerender, so the callsite is certainly runtime-tier. Any uncertainty\n // (slots or lifetime not statically known) keeps the conservative\n // attribution.\n if (slotsActive === 'yes' && (ttl === 'yes' || tags === 'yes')) return false;\n return true;\n}\n","/**\n * Post-build prebuilt capture — Node-side orchestration (TIM-1119).\n *\n * Runs as the capture step of the post-build phase (plugins/post-build.ts),\n * after Vite's 5-step build sequence and the manifest finalization step. Imports the BUILT `rsc/index.js` (the bundle carries\n * the react-server condition resolved at build time, so a plain dynamic\n * import works) and calls its `__timber_capturePrebuilt` export — the\n * capture itself must run inside the bundle's module graph, where the\n * component registry and flight renderer live. See\n * server/prebuilt-builder.ts and design/44-render-at-build-time.md\n * §Build Phase.\n *\n * This side owns PERSISTENCE: each captured payload is written to\n * `.timber/dist/prebuilt/<componentId>/<cacheKey>.flight` atomically\n * (temp file + rename — a crashed build never leaves a torn artifact\n * under its final name), and `manifest.json` is written last, only after\n * every payload it references is fully on disk. Keeping node:fs on the\n * plugin side keeps it out of the server bundle, which must also run on\n * Cloudflare Workers.\n *\n * NOTE: importing the built entry runs the app's production startup —\n * instrumentation.ts register() and the configured cache handler load\n * inside the build process. That is by design (prebuilt components may\n * call timber.cache), and it only happens when the app actually declares\n * prebuilt components.\n */\n\nimport { mkdir, rm } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { writeFileAtomic } from '../utils/write-file-atomic.ts';\n\nimport type { DirectoryArtifact } from '../adapters/types.ts';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { CaptureOptions, CaptureSummary, CapturedEntry } from '../server/prebuilt-builder.ts';\nimport type { PrebuiltManifest } from '../server/prebuilt/payload-source.ts';\n\n// ─── Artifact writer ──────────────────────────────────────────────────────\n\n/**\n * Both patterns are framework-generated (plugins/prebuilt.ts assigns IDs,\n * server/prebuilt/cache-key.ts hashes keys), so a mismatch is a framework\n * bug or a tampered registry — either way it must never reach a path join.\n */\nconst COMPONENT_ID_RE = /^[a-z0-9]+_[0-9a-f]{16}$/;\nconst CACHE_KEY_RE = /^[0-9a-f]{16}$/;\n\nexport interface PrebuiltArtifactWriter {\n write(entry: CapturedEntry): Promise<void>;\n /** Write manifest.json (if any entries exist). Returns the entry count. */\n finalize(): Promise<number>;\n}\n\n/**\n * Create the writer for `.timber/dist/prebuilt/`. Storage layout per\n * design/44 §Storage: one directory per component ID, one `.flight` file\n * per cache key, one manifest.json mapping componentId + key → file +\n * metadata.\n */\nexport function createPrebuiltArtifactWriter(prebuiltDir: string): PrebuiltArtifactWriter {\n const manifest: PrebuiltManifest = {};\n const buildTimestamp = Date.now();\n let count = 0;\n\n return {\n async write(entry: CapturedEntry): Promise<void> {\n if (!COMPONENT_ID_RE.test(entry.componentId) || !CACHE_KEY_RE.test(entry.cacheKey)) {\n throw new Error(\n `[timber] prebuilt artifact writer received a malformed identity ` +\n `(componentId: ${JSON.stringify(entry.componentId)}, cacheKey: ` +\n `${JSON.stringify(entry.cacheKey)}) — refusing to write`\n );\n }\n const relativeFile = `${entry.componentId}/${entry.cacheKey}.flight`;\n const path = join(prebuiltDir, relativeFile);\n await mkdir(dirname(path), { recursive: true });\n await writeFileAtomic(path, entry.bytes);\n\n manifest[entry.componentId] ??= { entries: {} };\n if (entry.paramIndependent) manifest[entry.componentId].paramIndependent = true;\n manifest[entry.componentId].entries[entry.cacheKey] = {\n params: entry.params,\n file: relativeFile,\n bytes: entry.bytes.byteLength,\n buildTimestamp,\n ...(entry.tags ? { tags: entry.tags } : {}),\n };\n count++;\n },\n\n async finalize(): Promise<number> {\n if (count === 0) return 0;\n await writeFileAtomic(\n join(prebuiltDir, 'manifest.json'),\n JSON.stringify(manifest, null, 2) + '\\n'\n );\n return count;\n },\n };\n}\n\n/** What a capture pass produced. */\nexport interface PrebuiltCaptureResult {\n summary: CaptureSummary;\n /** The payload directory — present only when the pass wrote a payload. */\n artifact?: DirectoryArtifact;\n}\n\n/**\n * Remove any `prebuilt/` output left by a previous build in this\n * directory (watch mode, `emptyOutDir: false`). A stale manifest would\n * make adapters ship payloads from an OLD build — reviving them serves\n * outdated content with that build's chunk references instead of the\n * intended miss → live render. Runs unconditionally at the start of the\n * capture step, BEFORE the capture decision: a build whose app no\n * longer declares any prebuilt components must also shed the artifacts\n * (codex P2 on PR #836).\n */\nexport async function cleanPrebuiltDir(buildDir: string): Promise<void> {\n await rm(join(buildDir, 'prebuilt'), { recursive: true, force: true });\n}\n\n// ─── Capture orchestration ────────────────────────────────────────────────\n\n/** Shape of the built RSC entry's capture export. */\ninterface CaptureModule {\n __timber_capturePrebuilt?: (options: CaptureOptions) => Promise<CaptureSummary>;\n}\n\n/**\n * Load the built RSC entry and run the capture pass. Throws (failing the\n * build) on infrastructure errors — missing/unloadable entry — and on\n * dynamic-context hard errors (cookies()/headers() in a prerendered\n * component). Per-entry data errors skip-and-report per design/44\n * §Build-Phase Error Handling.\n */\nexport async function runPrebuiltCapture(\n ctx: PluginContext,\n rscDir: string\n): Promise<PrebuiltCaptureResult> {\n const routeComponents = ctx.routePrebuiltComponents;\n if (!routeComponents || routeComponents.size === 0) {\n return { summary: { captured: 0, skipped: [], hardErrors: [], nestingWarnings: 0 } };\n }\n const entryPath = join(rscDir, 'index.js');\n\n // The build manifest global the bundle reads is published by the\n // post-build phase before this step runs (plugins/post-build.ts).\n const g = globalThis as Record<string, unknown>;\n\n console.log('[timber] cache.component: capturing prebuilt flight payloads…');\n\n // Tell the RSC entry to skip createRequestHandler — the capture pass\n // only needs __timber_capturePrebuilt + the route manifest. Running the\n // full production startup (instrumentation, cache handler, CDN purge,\n // OTEL tracing, route matchers) is wasted work that can take 100+ seconds\n // on large apps.\n g.__TIMBER_CAPTURE_MODE__ = true;\n\n let mod: CaptureModule;\n try {\n // Cache-busting query: in a long-lived build process (vite build\n // --watch), a bare file URL would return the FIRST build's module from\n // the ESM cache — stale code and a stale (already-walked) registry.\n const entryUrl = `${pathToFileURL(entryPath).href}?t=${Date.now()}`;\n mod = (await import(/* @vite-ignore */ entryUrl)) as CaptureModule;\n } catch (error) {\n // A missing entry lands here too: the import is the existence check.\n throw new Error(\n `[timber] prebuilt capture: failed to load the built RSC entry (${entryPath}). ` +\n `The capture pass runs the production server module inside the build process — ` +\n `its startup must succeed for prerendering to work.`,\n { cause: error }\n );\n }\n const capture = mod.__timber_capturePrebuilt;\n if (typeof capture !== 'function') {\n throw new Error(\n `[timber] prebuilt capture: built RSC entry does not export __timber_capturePrebuilt — ` +\n `the build output predates this framework version; rebuild from a clean .timber/dist`\n );\n }\n\n const prebuiltDir = join(ctx.buildDir, 'prebuilt');\n const writer = createPrebuiltArtifactWriter(prebuiltDir);\n const summary = await capture({\n fileComponentMap: Object.fromEntries(routeComponents),\n callSiteProps: ctx.prebuiltCallSiteProps\n ? Object.fromEntries(ctx.prebuiltCallSiteProps)\n : undefined,\n lazyChunks: ctx.prebuiltLazyChunks ? Object.fromEntries(ctx.prebuiltLazyChunks) : undefined,\n onEntry: (entry) => writer.write(entry),\n });\n\n if (summary.hardErrors.length > 0) {\n const details = summary.hardErrors.map((issue) => ` - ${issue.message}`).join('\\n');\n throw new Error(\n `[timber] prebuilt capture failed: ${summary.hardErrors.length} component(s) read ` +\n `per-request context at build time:\\n${details}`\n );\n }\n\n // The manifest is written only when a payload was, so this is the one\n // point that knows whether prebuilt/ is a product of this build.\n const written = await writer.finalize();\n\n const total = summary.captured + summary.skipped.length;\n console.log(\n `[timber] Prebuilt ${summary.captured}/${total} entries.` +\n (summary.skipped.length > 0 ? ` ${summary.skipped.length} skipped due to errors.` : '')\n );\n return written > 0 ? { summary, artifact: { path: prebuiltDir } } : { summary };\n}\n","/**\n * timber-prebuilt — Vite plugin that detects `cache.component(...)` call\n * sites and rewrites them to `__prebuilt(stableId, component, options)`.\n *\n * `timber.cache.component(Component, { prerender: true })` is a build-time\n * transform, not a runtime function (design/44-render-at-build-time.md\n * §Registration, surface API renamed by design/45-cache-lifetimes.md). The\n * rewrite registers the component in the server-side prebuilt registry under\n * a stable ID that keys its cached flight payloads.\n *\n * Detected callsite forms (mirrors timber-cache-transform, TIM-1054):\n * - named imports, including aliases:\n * `import { cache } from '@timber-js/app/cache'` + `cache.component(fn, opts)`\n * - namespace imports:\n * `import * as timber` + `timber.cache.component(fn, opts)`\n * Computed access (`cache['component']`) is deliberately not matched — the\n * untransformed call reaches the runtime `cache.component` fallback\n * (cache/cache-api.ts), which warns once and renders dynamically.\n *\n * Matching is an ALLOWLIST of module-scope positions: the direct initializer\n * of a top-level variable declarator (including exported ones) and a\n * top-level `export default cache.component(...)`, with TS expression\n * wrappers (`as`, `satisfies`, `!`) unwrapped. Nothing else is walked — no\n * function/class/loop bodies, no params, no call arguments. Two reasons:\n * (1) `__prebuilt` must register exactly once at module load time; the\n * post-build capture pass walks the registry after loading modules, so a\n * call inside a function registers too late to ever be prebuilt, and a call\n * in a loop would re-register per iteration. (2) Name-based callee matching\n * is only shadow-proof in these positions — nested scopes can rebind `cache`\n * (`function render(cache) {...}`, `for (const cache of caches) ...`), and\n * rewriting those would corrupt user code; a top-level declarator initializer\n * cannot see a shadow of an import binding (redeclaration error). Calls in\n * other positions fall back to the runtime path like other untraceable forms.\n *\n * The rewrite per mode:\n * production: cache.component(fn, opts) → __prebuilt(\"<id>\", fn, opts)\n * dev: cache.component(fn, opts) → __prebuiltDev(\"<name>\", fn, opts)\n *\n * with `import { __prebuilt } from '#server-internal'` prepended. In dev the\n * wrapper is a no-op that logs once per component and renders dynamically —\n * no caching, no markers (design/44 §Dev Mode).\n *\n * Component identity: `<name>_<hash16>`, e.g. `blogbody_a1b2c3d4e5f6a7b8`.\n * The name prefix is the declaring variable's name (lowercased, for legible\n * manifest keys and log lines); the hash is the same content-derived callsite\n * scheme as the data cache transform (callsite-ast.ts) — deterministic across\n * builds for unchanged calls, immune to inserting/reordering other calls, and\n * fresh when the component or its options change. Component cache entries are\n * per-deploy (design/45 §Per-deploy namespacing) so cross-deploy ID reuse is\n * not a poisoning vector, but content-derived IDs keep prebuilt artifacts\n * addressable across incremental edits for free.\n *\n * The transform is skipped in the client environment: server components never\n * execute there, and `#server-internal` resolves to an empty stub in the\n * client bundle (plugins/shims.ts).\n *\n * See TIM-1118, design/44-render-at-build-time.md, design/45-cache-lifetimes.md.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { relative } from 'node:path';\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode } from '../routing/types.ts';\nimport {\n CACHE_MODULE_SOURCES,\n findImportBindings,\n generateStableCallsiteId,\n} from './callsite-ast.ts';\nimport { collectJsxUsages, recordCallSiteProps } from './callsite-jsx.ts';\nimport { mayPrerender, unwrapExpression } from './prebuilt-options-analysis.ts';\nimport { cleanPrebuiltDir, runPrebuiltCapture } from './prebuilt-capture.ts';\nimport type { PrebuiltCaptureResult } from './prebuilt-capture.ts';\nimport type {\n CallExpressionNode,\n IdentifierNode,\n ImportBindings,\n MemberExpressionNode,\n PositionedNode,\n ProgramNode,\n} from './callsite-ast.ts';\n\n/**\n * Is this callee `cache.component` (named import, aliases included) or\n * `ns.cache.component` (namespace import)? Computed access is not matched.\n */\nfunction isCacheComponentCallee(callee: PositionedNode, bindings: ImportBindings): boolean {\n if (callee.type !== 'MemberExpression') return false;\n const member = callee as unknown as MemberExpressionNode;\n if (\n member.computed ||\n member.property.type !== 'Identifier' ||\n (member.property as IdentifierNode).name !== 'component'\n ) {\n return false;\n }\n // cache.component — object is a named-import binding of `cache`\n if (member.object.type === 'Identifier') {\n return bindings.named.has((member.object as IdentifierNode).name);\n }\n // ns.cache.component — object is `ns.cache` on a namespace import\n if (member.object.type === 'MemberExpression') {\n const inner = member.object as unknown as MemberExpressionNode;\n return (\n !inner.computed &&\n inner.object.type === 'Identifier' &&\n bindings.namespaces.has((inner.object as IdentifierNode).name) &&\n inner.property.type === 'Identifier' &&\n (inner.property as IdentifierNode).name === 'cache'\n );\n }\n return false;\n}\n\ninterface VariableDeclaratorNode extends PositionedNode {\n type: 'VariableDeclarator';\n id: PositionedNode;\n init?: PositionedNode | null;\n}\n\n/**\n * Offset where an injected import may be inserted: after the directive\n * prologue ('use server', 'use strict', ...). Prepending at offset 0 would\n * demote a leading directive to a plain expression statement — silently\n * disabling it.\n */\nfunction importInsertionOffset(program: ProgramNode): number {\n for (const stmt of program.body) {\n const isDirective =\n stmt.type === 'ExpressionStatement' &&\n typeof (stmt as { directive?: unknown }).directive === 'string';\n if (!isDirective) return stmt.start;\n }\n // All statements are directives — no call sites can exist, but be safe.\n return program.body.length > 0 ? program.body[program.body.length - 1].end : 0;\n}\n\ninterface CandidateSite {\n call: CallExpressionNode;\n stmt: PositionedNode;\n displayName: string;\n}\n\n/**\n * Collect matching call sites from the allowlisted module-scope positions:\n * top-level (possibly exported) variable declarator initializers and\n * `export default` expressions. Returned in source order. The display name\n * is the declaring variable's name, or 'Component' for default exports.\n */\nfunction collectModuleScopeSites(program: ProgramNode, bindings: ImportBindings): CandidateSite[] {\n const isMatch = (node: PositionedNode): node is CallExpressionNode =>\n node.type === 'CallExpression' &&\n (node as unknown as CallExpressionNode).arguments.length >= 1 &&\n (node as unknown as CallExpressionNode).arguments.length <= 2 &&\n isCacheComponentCallee((node as unknown as CallExpressionNode).callee, bindings);\n\n const sites: CandidateSite[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ExportDefaultDeclaration' && stmt.declaration) {\n const call = unwrapExpression(stmt.declaration as PositionedNode);\n if (isMatch(call)) sites.push({ call, stmt, displayName: 'Component' });\n continue;\n }\n let decl = stmt;\n if (stmt.type === 'ExportNamedDeclaration' && stmt.declaration) {\n decl = stmt.declaration as PositionedNode;\n }\n if (decl.type !== 'VariableDeclaration' || !Array.isArray(decl.declarations)) continue;\n for (const d of decl.declarations as VariableDeclaratorNode[]) {\n if (!d.init) continue;\n const call = unwrapExpression(d.init as PositionedNode);\n if (!isMatch(call)) continue;\n const displayName = d.id.type === 'Identifier' ? (d.id as IdentifierNode).name : 'Component';\n sites.push({ call, stmt, displayName });\n }\n }\n return sites;\n}\n\n/**\n * Generate the stable component ID for a cache.component() call site:\n * `<sanitized-name>_<content-hash16>`. Exported for testing.\n */\nexport function generatePrebuiltId(\n relativeModulePath: string,\n statementText: string,\n callSpanText: string,\n occurrence: number,\n displayName: string\n): string {\n const prefix = displayName.toLowerCase().replace(/[^a-z0-9]/g, '') || 'component';\n const hash = generateStableCallsiteId(\n relativeModulePath,\n 'component',\n statementText,\n callSpanText,\n occurrence\n );\n return `${prefix}_${hash}`;\n}\n\n// ─── Route → component attribution (module-graph walk) ────────────────────\n\n/** Rollup getModuleInfo shape (subset — static + dynamic imports). */\nexport interface PrebuiltModuleInfo {\n importedIds: string[];\n dynamicallyImportedIds?: string[];\n}\n\n/**\n * Collect the prebuilt component IDs transitively reachable from a route\n * file, following static AND dynamic imports. Same pattern as the\n * client-reference walk in build-manifest.ts; dynamic imports are included\n * because a dynamically-imported module still registers its components\n * when it eventually loads — attribution over-approximating registration\n * is handled at capture time (an attributed-but-unregistered component is\n * reported and skipped).\n */\nexport function collectReachablePrebuiltComponents(\n entryModuleId: string,\n moduleComponents: Map<string, string[]>,\n getModuleInfo: (id: string) => PrebuiltModuleInfo | null\n): string[] {\n const visited = new Set<string>();\n const result = new Set<string>();\n const stack = [entryModuleId];\n while (stack.length > 0) {\n const moduleId = stack.pop()!;\n if (visited.has(moduleId)) continue;\n visited.add(moduleId);\n const ids = moduleComponents.get(moduleId);\n if (ids) for (const id of ids) result.add(id);\n const info = getModuleInfo(moduleId);\n if (!info) continue;\n for (const imported of info.importedIds) stack.push(imported);\n for (const imported of info.dynamicallyImportedIds ?? []) stack.push(imported);\n }\n return Array.from(result);\n}\n\n/**\n * Collect page and layout file paths from the scanned route tree — the\n * walk roots for attribution. Slots and intercepting/private segments are\n * excluded, mirroring the capture pass's route walk\n * (server/prebuilt-builder.ts §collectCandidateRoutes).\n */\nfunction collectPageAndLayoutFiles(root: SegmentNode): string[] {\n const files: string[] = [];\n const walk = (node: SegmentNode) => {\n if (node.segmentType === 'intercepting' || node.segmentType === 'private') return;\n if (node.page) files.push(node.page.filePath);\n if (node.layout) files.push(node.layout.filePath);\n for (const child of node.children) walk(child);\n };\n walk(root);\n return files;\n}\n\n// Sentinel key for default-export component IDs in the binding map.\n// Uses \\0 prefix so it can never collide with a real JS export name\n// (TIM-1187: 'Component'/'default' leaked into the named-import namespace).\nconst DEFAULT_SENTINEL = '\\0default';\n\nasync function collectCrossModuleProps(\n ctx: PluginContext,\n bindingNames: ReadonlyMap<string, ReadonlyMap<string, string>>,\n moduleId: string,\n getInfo: (id: string) => PrebuiltModuleInfo | null,\n resolve: (source: string, importer: string) => Promise<string | null>\n): Promise<void> {\n const info = getInfo(moduleId);\n if (!info) return;\n\n const declaringImports = info.importedIds.filter((id) => bindingNames.has(id) && id !== moduleId);\n if (declaringImports.length === 0) return;\n\n // Collect exported binding names from reachable declaring modules.\n // Skip sentinel keys — they are per-module and handled in the default\n // import branch below. Only real export names go into the merged map.\n const exportNameToId = new Map<string, string>();\n const collisions = new Set<string>();\n for (const declId of declaringImports) {\n const map = bindingNames.get(declId)!;\n for (const [name, compId] of map) {\n if (name === DEFAULT_SENTINEL) continue;\n if (exportNameToId.has(name)) collisions.add(name);\n exportNameToId.set(name, compId);\n }\n }\n for (const name of collisions) exportNameToId.delete(name);\n\n let source: string | null = null;\n const extInfo = getInfo(moduleId) as unknown as { code?: string | null };\n if (extInfo && typeof extInfo.code === 'string') {\n source = extInfo.code;\n } else {\n try {\n source = readFileSync(moduleId, 'utf8');\n } catch {\n return;\n }\n }\n if (!source) return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(source);\n } catch {\n return;\n }\n\n const declaringSet = new Set(declaringImports);\n const localToComponentId = new Map<string, string>();\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const importDecl = stmt as unknown as {\n source: { value: string };\n specifiers: Array<{\n type: string;\n local: { name: string };\n imported?: { name: string };\n }>;\n };\n for (const spec of importDecl.specifiers) {\n if (spec.type === 'ImportSpecifier') {\n const exportedName = spec.imported?.name ?? spec.local.name;\n // `import { default as X }` is parsed as an ImportSpecifier\n // with imported.name === 'default' — route through the same\n // per-source sentinel lookup as ImportDefaultSpecifier.\n if (exportedName === 'default') {\n const resolvedId = await resolve(importDecl.source.value, moduleId);\n if (resolvedId && declaringSet.has(resolvedId)) {\n const map = bindingNames.get(resolvedId)!;\n const compId = map.get(DEFAULT_SENTINEL);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n } else {\n const compId = exportNameToId.get(exportedName);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n } else if (spec.type === 'ImportDefaultSpecifier') {\n const resolvedId = await resolve(importDecl.source.value, moduleId);\n if (resolvedId && declaringSet.has(resolvedId)) {\n const map = bindingNames.get(resolvedId)!;\n const compId = map.get(DEFAULT_SENTINEL);\n if (compId) localToComponentId.set(spec.local.name, compId);\n }\n }\n }\n }\n if (localToComponentId.size === 0) return;\n\n const usages = collectJsxUsages(program, new Set(localToComponentId.keys()));\n for (const [localName, propsList] of usages) {\n const componentId = localToComponentId.get(localName);\n if (!componentId) continue;\n for (const props of propsList) {\n if (props === null) continue;\n recordCallSiteProps(ctx, componentId, props);\n }\n }\n}\n\n/**\n * What the post-build phase asks of the prebuilt plugin (plugins/post-build.ts).\n */\nexport interface PrebuiltBuildStep {\n /**\n * Run the capture pass against the built RSC bundle in `rscDir`. Always\n * removes the previous build's `prebuilt/` first — even when this build\n * captures nothing, a stale manifest must never ship. Returns null when\n * there was nothing to capture: no prerender call site is reachable from a\n * route, or `output: 'static'` already renders everything at build time.\n */\n capture(rscDir: string): Promise<PrebuiltCaptureResult | null>;\n}\n\nexport function timberPrebuilt(ctx: PluginContext): Plugin & { api: PrebuiltBuildStep } {\n /**\n * Module ID → prerender-capable component IDs declared in it. Recorded by\n * the RSC transform, read by the RSC `generateBundle` module-graph walk\n * that computes `ctx.routePrebuiltComponents`. Build only.\n */\n const moduleComponents = new Map<string, string[]>();\n /**\n * Module ID → variable name → component ID, for the prebuilt components\n * that module declares. Read at `generateBundle` time to trace imports in\n * other modules back to component IDs (cross-module call-site props).\n */\n const bindingNames = new Map<string, Map<string, string>>();\n\n return {\n name: 'timber-prebuilt',\n\n api: {\n async capture(rscDir) {\n await cleanPrebuiltDir(ctx.buildDir);\n if (!ctx.routePrebuiltComponents || ctx.routePrebuiltComponents.size === 0) return null;\n if (ctx.config.output === 'static') {\n // design/44 §output: 'static' — everything already renders at\n // build time there; the wrapper is a no-op, not an error.\n console.log(\n `[timber] cache.component: skipped prerender capture (output: 'static' renders all components at build time)`\n );\n return null;\n }\n return runPrebuiltCapture(ctx, rscDir);\n },\n },\n\n transform(code, id) {\n // Drop this module's stale attribution first — in a long-lived\n // `vite build --watch` process the plugin context outlives builds,\n // and an edit that removes a module's prerender call sites must\n // remove its recorded IDs even when this transform exits early\n // below (codex P2 on PR #836). Re-recorded at the bottom if the\n // edited module still has prerender-capable call sites.\n if (!ctx.dev && this?.environment?.name === 'rsc') {\n moduleComponents.delete(id);\n bindingNames.delete(id);\n }\n if (!code.includes('@timber-js/app/cache') && !code.includes('timber/cache')) return;\n // Skip node_modules (don't transform third-party code)\n if (id.includes('node_modules')) return;\n // Skip the client environment — server components never execute there\n // and #server-internal resolves to an empty stub.\n if (this?.environment?.name === 'client') return;\n\n let program: ProgramNode;\n try {\n program = ctx.parseCached!.parse(code);\n } catch {\n return;\n }\n\n const bindings = findImportBindings(program, CACHE_MODULE_SOURCES, 'cache');\n if (bindings.named.size === 0 && bindings.namespaces.size === 0) return;\n\n // Allowlisted module-scope positions only — each site carries its\n // enclosing statement's source text (into the ID hash) and the\n // declaring variable's name (display name). Already in source order.\n const callSites = collectModuleScopeSites(program, bindings);\n if (callSites.length === 0) return;\n\n const root = ctx.root || process.cwd();\n const relPath = relative(root, id);\n const s = new MagicString(code);\n const occurrences = new Map<string, number>();\n const wrapperName = ctx.dev ? '__prebuiltDev' : '__prebuilt';\n const componentIds: string[] = [];\n\n for (const { call, stmt, displayName } of callSites) {\n const stmtText = code.slice(stmt.start, stmt.end);\n const spanText = code.slice(call.start, call.end);\n // Byte-identical (statement, call) pairs are only possible via `var`\n // redeclaration; the occurrence index keeps their IDs distinct.\n const dupKey = stmtText + String.fromCharCode(0) + spanText;\n const occurrence = occurrences.get(dupKey) ?? 0;\n occurrences.set(dupKey, occurrence + 1);\n\n // Production gets the stable ID (keys build artifacts and cache\n // entries); dev gets the display name (only used for the one-time\n // \"rendering dynamically\" log).\n const firstArg = ctx.dev\n ? displayName\n : generatePrebuiltId(relPath, stmtText, spanText, occurrence, displayName);\n // Only prerender-capable call sites feed the capture attribution —\n // runtime-tier components (ttl/tags only) must do no build work.\n if (!ctx.dev && mayPrerender(call)) componentIds.push(firstArg);\n\n s.overwrite(call.callee.start, call.callee.end, wrapperName);\n s.appendLeft(call.arguments[0].start, `${JSON.stringify(firstArg)}, `);\n }\n\n // Record this module's component IDs for the RSC generateBundle\n // module-graph walk (route → component attribution, TIM-1119).\n if (!ctx.dev && componentIds.length > 0 && this?.environment?.name === 'rsc') {\n moduleComponents.set(id, componentIds);\n\n // Record binding name → component ID mapping for cross-module\n // prop detection at generateBundle time (TIM-1142).\n const bindingMap = new Map<string, string>();\n let componentIdIdx = 0;\n for (const { call, stmt, displayName } of callSites) {\n if (!ctx.dev && mayPrerender(call)) {\n const compId = componentIds[componentIdIdx++];\n // Direct `export default cache.component(...)` produces\n // displayName 'Component' from an ExportDefaultDeclaration —\n // a synthetic name, not a real export. Store only the sentinel\n // key. A variable literally named `Component` (from a\n // VariableDeclarator) is a real binding and stored as-is.\n if (stmt.type === 'ExportDefaultDeclaration') {\n bindingMap.set(DEFAULT_SENTINEL, compId);\n } else {\n bindingMap.set(displayName, compId);\n }\n }\n }\n // Detect default re-exports that reference a declared binding\n // and add a sentinel alias so cross-module default imports can\n // resolve the component ID. Handles both `export default X` and\n // `export { X as default }` (TIM-1189).\n for (const stmt of program.body) {\n if (\n stmt.type === 'ExportDefaultDeclaration' &&\n stmt.declaration &&\n (stmt.declaration as PositionedNode).type === 'Identifier'\n ) {\n const name = (stmt.declaration as PositionedNode as unknown as IdentifierNode).name;\n if (bindingMap.has(name) && !bindingMap.has(DEFAULT_SENTINEL)) {\n bindingMap.set(DEFAULT_SENTINEL, bindingMap.get(name)!);\n }\n }\n if (stmt.type === 'ExportNamedDeclaration' && Array.isArray(stmt.specifiers)) {\n for (const spec of stmt.specifiers as Array<{\n local: IdentifierNode;\n exported: IdentifierNode;\n }>) {\n if (spec.exported.name === 'default') {\n const compId = bindingMap.get(spec.local.name);\n if (compId && !bindingMap.has(DEFAULT_SENTINEL)) {\n bindingMap.set(DEFAULT_SENTINEL, compId);\n }\n }\n }\n }\n }\n\n if (bindingMap.size > 0) {\n bindingNames.set(id, bindingMap);\n }\n\n // Same-module JSX usages: if a prebuilt component is declared AND\n // used (<BlogBody variant=\"full\" />) in the same module, capture\n // its static call-site props here (TIM-1142, design/44 §Props).\n // Exclude sentinel keys — they are not real JSX element names.\n const declaredBindings = new Set(\n [...bindingMap.keys()].filter((k) => k !== DEFAULT_SENTINEL)\n );\n if (declaredBindings.size > 0) {\n const usages = collectJsxUsages(program, declaredBindings);\n for (const [bindingName, propsList] of usages) {\n const compId = bindingMap.get(bindingName);\n if (!compId) continue;\n for (const props of propsList) {\n if (props === null) {\n // Dynamic props at this call site — warn at build time,\n // this usage will always render live (design/44 §Props\n // Derivation limitation).\n continue;\n }\n recordCallSiteProps(ctx, compId, props);\n }\n }\n }\n }\n\n s.appendLeft(\n importInsertionOffset(program),\n `import { ${wrapperName} } from '#server-internal';\\n`\n );\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n\n /**\n * RSC environment, production: walk each route file's module graph to\n * attribute prebuilt components to the routes that can render them.\n * The graph walk (rather than load-order registry deltas) is what makes\n * SHARED components work — a component imported by several routes is\n * captured under every importing route's param combos.\n */\n async generateBundle(\n _options?: unknown,\n bundle?: Record<\n string,\n { type: string; modules?: Record<string, unknown>; fileName?: string }\n >\n ) {\n if (ctx.dev) return;\n if (this?.environment?.name !== 'rsc') return;\n ctx.routePrebuiltComponents = undefined;\n ctx.prebuiltLazyChunks = undefined;\n if (moduleComponents.size === 0 || !ctx.routeTree) return;\n\n const self = this as unknown as {\n getModuleInfo?: (id: string) => PrebuiltModuleInfo | null;\n resolve?: (\n source: string,\n importer: string,\n opts?: unknown\n ) => Promise<{ id: string } | null>;\n };\n const getInfo = (id: string) => self.getModuleInfo?.(id) ?? null;\n const resolveFn = async (source: string, importer: string): Promise<string | null> => {\n const result = await self.resolve?.(source, importer);\n return result?.id ?? null;\n };\n\n const routeComponents = new Map<string, string[]>();\n for (const filePath of collectPageAndLayoutFiles(ctx.routeTree.root)) {\n const ids = collectReachablePrebuiltComponents(filePath, moduleComponents, getInfo);\n if (ids.length > 0) routeComponents.set(filePath, ids);\n }\n if (routeComponents.size > 0) {\n ctx.routePrebuiltComponents = routeComponents;\n\n // Build a map of componentId → chunk fileName for declaring\n // modules that aren't route files themselves (behind dynamic\n // imports like import.meta.glob). The capture pass imports these\n // chunks to trigger cache.component() registration.\n if (bundle) {\n const routeFileSet = new Set(routeComponents.keys());\n const lazyChunks = new Map<string, string>();\n for (const [moduleId, componentIds] of moduleComponents) {\n if (routeFileSet.has(moduleId)) continue;\n for (const [, chunk] of Object.entries(bundle)) {\n if (chunk.type !== 'chunk' || !chunk.modules) continue;\n if (moduleId in chunk.modules) {\n for (const id of componentIds) lazyChunks.set(id, chunk.fileName!);\n break;\n }\n }\n }\n if (lazyChunks.size > 0) ctx.prebuiltLazyChunks = lazyChunks;\n }\n\n // Cross-module call-site prop detection (TIM-1142): walk the\n // module graph from each route file and scan ALL reachable modules\n // for JSX usages of prebuilt components — not just the route files\n // themselves. A component used in a helper (page → Shell → <BlogBody>)\n // must have its props captured from wherever the JSX lives.\n if (bindingNames.size > 0) {\n const scannedModules = new Set<string>();\n for (const filePath of routeComponents.keys()) {\n const visited = new Set<string>();\n const stack = [filePath];\n while (stack.length > 0) {\n const modId = stack.pop()!;\n if (visited.has(modId)) continue;\n visited.add(modId);\n if (!scannedModules.has(modId)) {\n scannedModules.add(modId);\n await collectCrossModuleProps(ctx, bindingNames, modId, getInfo, resolveFn);\n }\n const modInfo = getInfo(modId);\n if (!modInfo) continue;\n for (const imp of modInfo.importedIds) stack.push(imp);\n for (const imp of modInfo.dynamicallyImportedIds ?? []) stack.push(imp);\n }\n }\n }\n } else {\n // Call sites were transformed but none are reachable from any route\n // file — either they live behind slots (not modeled) or the graph\n // walk's module IDs diverged from the route tree's file paths. Say\n // so loudly: the alternative is prerender silently doing nothing.\n console.warn(\n `[timber] cache.component: ${moduleComponents.size} module(s) declare prebuilt ` +\n `components, but none are reachable from any page or layout — no payloads ` +\n `will be prerendered`\n );\n }\n },\n };\n}\n","/**\n * timber-prerender-sugar — Vite plugin that desugars `export const prerender`\n * on page and layout files into `cache.component(...)` wrappers.\n *\n * Design doc: design/45-cache-lifetimes.md §\"Route-Level Static\" and\n * §\"Layout Propagation\".\n *\n * `export const prerender = true` on a page is pure sugar: it desugars to\n * wrapping the page's default export in `timber.cache.component(Component,\n * { prerender: true })`. Layout propagation cascades a layout's\n * `export const prerender` to descendant pages via most-specific-wins:\n * walk the segment tree from leaf to root, first explicit value wins.\n *\n * Layout declarations are propagation policy only. Layouts receive the real\n * descendant React element as `children` to preserve the server-layout\n * containment boundary, so their props are not cache-keyable and the layout\n * itself must not be registered for capture.\n *\n * This transform runs BEFORE timber-prebuilt so the generated\n * `cache.component(...)` call is picked up by the callsite rewrite.\n */\n\nimport MagicString from 'magic-string';\nimport type { Plugin } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode, RouteFile } from '../routing/types.ts';\nimport { getPrerenderExport, type PrerenderExportValue } from '../routing/export-detect.ts';\n\ninterface AstNode {\n type: string;\n start: number;\n end: number;\n name?: string;\n declaration?: AstNode;\n id?: AstNode & { name?: string };\n expression?: AstNode;\n}\n\n/**\n * Walk the segment tree and resolve the effective prerender value for\n * every page. Returns a map from page file path to resolved value.\n *\n * **Pages:** walk from leaf toward root; first explicit `export const prerender`\n * wins (page > nearest layout > ... > root layout). If none, dynamic.\n *\n * **Layouts:** declarations propagate to descendant pages but layouts are not\n * included in the result. Their real React-element `children` preserve secure\n * containment and deliberately make child-independent layout caching invalid.\n */\nexport function resolvePagePrerender(root: SegmentNode): Map<string, PrerenderExportValue> {\n const result = new Map<string, PrerenderExportValue>();\n\n function walk(node: SegmentNode, ancestorStack: PrerenderExportValue[]) {\n if (node.segmentType === 'intercepting' || node.segmentType === 'private') return;\n\n // Check this segment's layout for a prerender export\n const layoutValue = node.layout ? getPrerenderExport(node.layout.filePath) : undefined;\n const stack = layoutValue !== undefined ? [layoutValue, ...ancestorStack] : ancestorStack;\n\n if (node.page) {\n const pageValue = getPrerenderExport(node.page.filePath);\n // Page's own value takes priority; otherwise use nearest ancestor\n const resolved = pageValue !== undefined ? pageValue : stack[0];\n // Only record if the resolved value is truthy (prerender: true or options object)\n // prerender: false explicitly opts out\n if (resolved !== undefined && resolved !== false) {\n result.set(node.page.filePath, resolved);\n }\n }\n\n for (const child of node.children) walk(child, stack);\n for (const slot of Object.values(node.slots)) walk(slot, stack);\n }\n\n walk(root, []);\n return result;\n}\n\n/**\n * Build the `cache.component` options source text from a resolved value.\n */\nfunction buildOptionsSource(value: PrerenderExportValue): string {\n if (value === true) return '{ prerender: true }';\n if (typeof value === 'object') {\n const parts = ['prerender: true'];\n if (value.ttl !== undefined) parts.push(`ttl: ${value.ttl}`);\n if (value.tags !== undefined) parts.push(`tags: ${JSON.stringify(value.tags)}`);\n return `{ ${parts.join(', ')} }`;\n }\n return '{ prerender: true }';\n}\n\n/**\n * Find the default export in the AST and return info needed for the rewrite.\n */\ninterface DefaultExportInfo {\n kind: 'declaration' | 'expression' | 'identifier';\n node: AstNode;\n name?: string;\n /** For `export { X as default, Y }` — position of the default specifier. */\n specifierIndex?: number;\n specifierCount?: number;\n specifierStart?: number;\n specifierEnd?: number;\n}\n\nfunction findDefaultExport(program: { body: AstNode[] }, source: string): DefaultExportInfo | null {\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportDefaultDeclaration' || !stmt.declaration) continue;\n const decl = stmt.declaration;\n\n // export default function Name(...) { ... }\n // export default class Name { ... }\n if (decl.type === 'FunctionDeclaration' || decl.type === 'ClassDeclaration') {\n const name = decl.id?.name;\n if (name) return { kind: 'declaration', node: stmt, name };\n // Anonymous function/class — treat as expression\n return { kind: 'expression', node: stmt };\n }\n\n // export default SomeIdentifier\n if (decl.type === 'Identifier') {\n return { kind: 'identifier', node: stmt, name: decl.name };\n }\n\n // export default <expression>\n return { kind: 'expression', node: stmt };\n }\n\n // Check for `export { X as default }` (not re-exports from other modules)\n for (const stmt of program.body) {\n if (stmt.type !== 'ExportNamedDeclaration') continue;\n // Skip re-exports: `export { X as default } from './other'`\n if ((stmt as any).source) continue;\n const specifiers = (stmt as any).specifiers as\n | Array<{\n type: string;\n start: number;\n end: number;\n local?: { name: string };\n exported?: { name: string };\n }>\n | undefined;\n if (!specifiers) continue;\n for (let i = 0; i < specifiers.length; i++) {\n const spec = specifiers[i];\n if (spec.exported?.name === 'default' && spec.local?.name && spec.local.name !== 'default') {\n return {\n kind: 'identifier' as const,\n node: stmt,\n name: spec.local.name,\n specifierIndex: i,\n specifierCount: specifiers.length,\n specifierStart: spec.start,\n specifierEnd: spec.end,\n };\n }\n }\n }\n\n return null;\n}\n\nexport function timberPrerenderSugar(ctx: PluginContext): Plugin {\n let resolvedPages: Map<string, PrerenderExportValue> | null = null;\n\n function ensureResolved() {\n if (resolvedPages) return;\n if (!ctx.routeTree) {\n resolvedPages = new Map();\n return;\n }\n resolvedPages = resolvePagePrerender(ctx.routeTree.root);\n }\n\n return {\n name: 'timber-prerender-sugar',\n\n buildStart() {\n // Reset on each build (watch mode rebuilds)\n resolvedPages = null;\n },\n\n transform(code, id) {\n // Only process in RSC environment (same gate as prebuilt.ts)\n if (this?.environment?.name === 'client') return;\n // Skip node_modules\n if (id.includes('node_modules')) return;\n\n ensureResolved();\n if (!resolvedPages || resolvedPages.size === 0) return;\n\n const value = resolvedPages.get(id);\n if (!value) return;\n\n // This page has a resolved prerender value — wrap its default export\n let program: { body: AstNode[] };\n try {\n program = ctx.parseCached!.parse(code) as unknown as { body: AstNode[] };\n } catch {\n return;\n }\n\n const defaultExport = findDefaultExport(program, code);\n if (!defaultExport) {\n // Warn if the file has a prerender export but no wrappable default export\n // (e.g. `export { default } from './impl'` — a re-export we can't rewrite).\n if (value) {\n const relPath = id.replace(ctx.root + '/', '');\n console.warn(\n `[timber] ${relPath}: export const prerender is declared but the default ` +\n `export cannot be wrapped (re-export or missing). The prerender declaration ` +\n `will be ignored for this file.`\n );\n }\n return;\n }\n\n // Skip if the default export is already a cache.component(...) call —\n // avoid double-wrapping. Only check the default export itself, not the\n // whole file (a page may use cache.component for child components).\n if (defaultExport.kind === 'expression' && defaultExport.node.declaration) {\n const declText = code.slice(\n defaultExport.node.declaration.start,\n defaultExport.node.declaration.end\n );\n if (declText.includes('.component(')) return;\n }\n\n const s = new MagicString(code);\n const optionsSource = buildOptionsSource(value);\n\n // Add the cache import at the top (after directives)\n const importAlias = '__timber_prerender_cache__';\n let insertOffset = 0;\n for (const stmt of program.body) {\n const isDirective =\n stmt.type === 'ExpressionStatement' && typeof (stmt as any).directive === 'string';\n if (!isDirective) {\n insertOffset = stmt.start;\n break;\n }\n }\n s.appendLeft(\n insertOffset,\n `import { cache as ${importAlias} } from '@timber-js/app/cache';\\n`\n );\n\n switch (defaultExport.kind) {\n case 'declaration': {\n // `export default function Name() { ... }`\n // → `function Name() { ... }` + `export default cache.component(Name, opts)`\n const declStart = defaultExport.node.declaration!.start;\n // Remove `export default ` prefix\n s.overwrite(defaultExport.node.start, declStart, '');\n // Append the wrapped export at the end\n s.append(\n `\\nexport default ${importAlias}.component(${defaultExport.name}, ${optionsSource});\\n`\n );\n break;\n }\n case 'identifier': {\n if (defaultExport.specifierCount !== undefined && defaultExport.specifierCount > 1) {\n // Multi-specifier: `export { Page as default, generateStaticSegmentParams }`\n // Remove only the default specifier + surrounding comma, keep others.\n const specStart = defaultExport.specifierStart!;\n const specEnd = defaultExport.specifierEnd!;\n const idx = defaultExport.specifierIndex!;\n // Remove the specifier and a comma (trailing if first, leading otherwise)\n if (idx === 0) {\n // First specifier: remove text up to (but not including) the next specifier start\n const nextSpec = (defaultExport.node as any).specifiers?.[1];\n if (nextSpec) s.remove(specStart, nextSpec.start);\n } else {\n // Not first: remove from end of previous specifier to this specifier's end\n const prevSpec = (defaultExport.node as any).specifiers?.[idx - 1];\n if (prevSpec) s.remove(prevSpec.end, specEnd);\n }\n // Append the wrapped default export separately\n s.appendLeft(\n defaultExport.node.end,\n `\\nexport default ${importAlias}.component(${defaultExport.name}, ${optionsSource});`\n );\n } else {\n // `export default MyPage` or `export { MyPage as default }` (sole specifier)\n // → `export default cache.component(MyPage, opts)`\n s.overwrite(\n defaultExport.node.start,\n defaultExport.node.end,\n `export default ${importAlias}.component(${defaultExport.name}, ${optionsSource});`\n );\n }\n break;\n }\n case 'expression': {\n // `export default () => <div/>` or `export default async function() { ... }`\n // → `const __default = ...; export default cache.component(__default, opts)`\n const decl = defaultExport.node.declaration!;\n s.overwrite(defaultExport.node.start, decl.start, 'const __timber_default_page__ = ');\n // Ensure trailing semicolon\n const afterExpr = code.charAt(defaultExport.node.end - 1) === ';' ? '' : ';';\n s.appendLeft(\n defaultExport.node.end,\n `${afterExpr}\\nexport default ${importAlias}.component(__timber_default_page__, ${optionsSource});`\n );\n break;\n }\n }\n\n return {\n code: s.toString(),\n map: s.generateMap({ hires: 'boundary' }),\n };\n },\n };\n}\n","/**\n * timber-cloudflare-wasm — Handle WASM modules for Cloudflare Workers builds.\n *\n * Cloudflare Workers can natively import `.wasm` files as compiled\n * WebAssembly.Module. But Rolldown can't load `.wasm` files at build time.\n *\n * This plugin bridges the gap:\n * 1. Adds the `workerd` resolve condition so libraries like @takumi-rs/wasm\n * resolve to their Cloudflare-native entry (bare `.wasm` import)\n * 2. Externalizes `.wasm` imports so Rolldown skips them\n * 3. Copies the WASM files to the build output so wrangler can find them\n *\n * Only active for Cloudflare adapter production builds — every hook bails\n * unless `isCloudflareBuild` was set in configResolved. In dev and non-CF\n * builds, `.wasm` imports are left to Vite's own handling (?init / ?url or\n * a clear build error), never silently externalized.\n */\n\nimport { basename, resolve, dirname } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { copyFile, mkdir, readFile } from 'node:fs/promises';\nimport type { Plugin, ResolvedConfig } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\n\nfunction isCloudflareAdapter(ctx: PluginContext): boolean {\n const adapter = ctx.config.adapter as { name?: string } | undefined;\n return adapter?.name === 'cloudflare';\n}\n\nexport function timberCloudflareWasm(ctx: PluginContext): Plugin[] {\n // Resolved WASM files, keyed by absolute source path so two files that\n // share a basename (e.g. lib_bg.wasm from two packages) don't collide.\n // The value is the unique output basename used for the external import\n // specifier and the copy destination.\n const wasmFiles = new Map<string, string>();\n const usedBasenames = new Set<string>();\n let isCloudflareBuild = false;\n\n const plugin: Plugin = {\n name: 'timber-cloudflare-wasm',\n\n configResolved(resolved: ResolvedConfig) {\n if (resolved.command !== 'build') return;\n if (!isCloudflareAdapter(ctx)) return;\n isCloudflareBuild = true;\n\n // Prepend `workerd` to resolve conditions for server environments\n // so @takumi-rs/wasm/auto resolves to the Cloudflare-native entry\n // (bare WASM import) instead of the Vite entry (?url + fetch).\n // Must happen in configResolved because the RSC plugin sets its own\n // conditions during config — merging via config() would lose them.\n for (const envName of ['rsc', 'ssr']) {\n const env = resolved.environments[envName];\n if (!env) continue;\n const conditions = env.resolve.conditions;\n if (!conditions.includes('workerd')) {\n conditions.unshift('workerd');\n }\n }\n },\n\n // Strip /* @vite-ignore */ from @takumi-rs/wasm dynamic imports so\n // Rolldown bundles them instead of leaving bare specifiers that fail\n // at runtime on Cloudflare Workers (no node_modules).\n transform(code, id) {\n if (!isCloudflareBuild) return;\n if (!id.includes('takumi')) return;\n const stripped = code.replaceAll(\n /\\/\\*\\s*@vite-ignore\\s*\\*\\/\\s*\\n\\s*\"@takumi-rs\\/wasm\"/g,\n '\"@takumi-rs/wasm\"'\n );\n if (stripped !== code) return stripped;\n },\n\n resolveId: {\n order: 'pre',\n async handler(source, importer) {\n if (!isCloudflareBuild) return;\n if (!source.endsWith('.wasm')) return;\n\n let absolutePath: string;\n if (source.startsWith('.') && importer) {\n absolutePath = resolve(dirname(importer), source);\n } else {\n return;\n }\n\n let outputName = wasmFiles.get(absolutePath);\n if (!outputName) {\n outputName = basename(absolutePath);\n if (usedBasenames.has(outputName)) {\n // Another wasm file already claimed this basename — disambiguate\n // with a short content hash so both files land in the output.\n const hash = createHash('sha256')\n .update(await readFile(absolutePath))\n .digest('hex')\n .slice(0, 8);\n outputName = outputName.replace(/\\.wasm$/, `.${hash}.wasm`);\n }\n usedBasenames.add(outputName);\n wasmFiles.set(absolutePath, outputName);\n }\n\n return { id: './' + outputName, external: true };\n },\n },\n\n async writeBundle(options, bundle) {\n if (!isCloudflareBuild) return;\n if (wasmFiles.size === 0) return;\n\n const outDir = options.dir;\n if (!outDir) return;\n\n // Find which output chunks reference WASM files and copy the WASM\n // to the same directory so the relative imports resolve correctly.\n const targetDirs = new Set<string>();\n for (const chunk of Object.values(bundle)) {\n if (chunk.type !== 'chunk') continue;\n for (const outputName of wasmFiles.values()) {\n if (chunk.code.includes(outputName)) {\n targetDirs.add(dirname(resolve(outDir, chunk.fileName)));\n }\n }\n }\n\n if (targetDirs.size === 0) return;\n\n const copies: Promise<void>[] = [];\n for (const dir of targetDirs) {\n await mkdir(dir, { recursive: true });\n for (const [absolutePath, outputName] of wasmFiles) {\n copies.push(copyFile(absolutePath, resolve(dir, outputName)));\n }\n }\n await Promise.all(copies);\n },\n };\n\n return [plugin];\n}\n","/**\n * The RSC plugin's assets manifest (`__vite_rsc_assets_manifest.js`) — read\n * into the build manifest, and stripped of JavaScript when client JS is off.\n *\n * The RSC plugin writes the file to rsc/ and ssr/ as a standalone file, not\n * a Rollup chunk, so no `generateBundle` can intercept it; both operations\n * work on the written files. Both run once, from the post-build phase's\n * manifest finalization step (plugins/post-build.ts), before anything\n * imports the built bundle.\n *\n * Design doc: 18-build-system.md §\"Post-Build Phase\"\n */\n\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport { swallow } from '../server/logger.ts';\n\n/**\n * Parse the RSC assets manifest at `manifestPath`. Tries JSON.parse first\n * (fast path for plain-string manifests); falls back to a dynamic import()\n * for manifests that contain runtime expressions from renderBuiltUrl.\n * Returns null if both paths fail.\n */\nasync function parseRscManifest(\n manifestPath: string,\n content: string\n): Promise<Record<string, unknown> | null> {\n const jsonStr = content.replace(/^export default\\s*/, '').replace(/;?\\s*$/, '');\n try {\n return JSON.parse(jsonStr);\n } catch {\n // Not strict JSON — manifest likely contains renderBuiltUrl runtime\n // expressions. Fall back to evaluating the module directly.\n }\n\n // When renderBuiltUrl's runtime expressions reference external helpers\n // not defined in the manifest file, this import will fail. That's an\n // inherent limitation: runtime-computed URLs can't be resolved at build\n // time for <link> tag injection. The warning below provides observability.\n try {\n const url = pathToFileURL(manifestPath).href;\n const mod = await import(`${url}?t=${Date.now()}`);\n return mod.default ?? null;\n } catch (err) {\n swallow(err, `failed to evaluate RSC assets manifest: ${manifestPath}`, { level: 'warn' });\n return null;\n }\n}\n\n/**\n * Replace all `\"js\": [...]` array contents with `\"js\": []` using balanced\n * bracket matching. Handles nested brackets from runtime expressions like\n * `__rbu(\"path/to/[slug]/file.js\")`.\n */\nfunction clearJsArrays(src: string): string {\n const pattern = /\"js\"\\s*:\\s*\\[/g;\n let result = '';\n let lastEnd = 0;\n let match: RegExpExecArray | null;\n\n while ((match = pattern.exec(src)) !== null) {\n const arrayStart = match.index + match[0].length;\n let depth = 1;\n let i = arrayStart;\n while (i < src.length && depth > 0) {\n if (src[i] === '[') depth++;\n else if (src[i] === ']') depth--;\n i++;\n }\n result += src.slice(lastEnd, match.index) + '\"js\": []';\n lastEnd = i;\n }\n result += src.slice(lastEnd);\n return result;\n}\n\n/**\n * Replace `\"bootstrapScriptContent\": <value>` with an empty string. The\n * value may be a JS expression (e.g., concatenation with runtime helpers),\n * not a simple string literal. Scans forward from the colon, tracking\n * balanced parens and brackets, and stops at the next unbalanced `,` or `}`.\n */\nfunction clearBootstrapScriptContent(src: string): string {\n const key = '\"bootstrapScriptContent\"';\n const idx = src.indexOf(key);\n if (idx === -1) return src;\n\n // Find the colon after the key\n const colonIdx = src.indexOf(':', idx + key.length);\n if (colonIdx === -1) return src;\n\n // Skip whitespace after colon\n let valStart = colonIdx + 1;\n while (valStart < src.length && /\\s/.test(src[valStart])) valStart++;\n\n // Scan forward to find the end of the value expression\n let i = valStart;\n let depth = 0;\n let inString = false;\n let stringChar = '';\n\n while (i < src.length) {\n const ch = src[i];\n if (inString) {\n if (ch === '\\\\') {\n i += 2;\n continue;\n }\n if (ch === stringChar) inString = false;\n } else {\n if (ch === '\"' || ch === \"'\") {\n inString = true;\n stringChar = ch;\n } else if (ch === '(' || ch === '[') {\n depth++;\n } else if (ch === ')' || ch === ']') {\n depth--;\n } else if (depth === 0 && (ch === ',' || ch === '}' || ch === '\\n')) {\n break;\n }\n }\n i++;\n }\n\n return src.slice(0, idx) + '\"bootstrapScriptContent\": \"\"' + src.slice(i);\n}\n\n/**\n * Read the RSC plugin's assets manifest and merge per-route CSS and\n * per-route JS modulepreloads into the build manifest.\n *\n * CSS: `serverResources` maps server component paths to CSS URLs.\n * JS: `clientReferenceDeps` maps reference hashes to JS dep URLs.\n * Combined with `routeClientRefKeys` (from the RSC generateBundle\n * module graph walk) to produce per-route modulepreload entries.\n */\nexport async function mergeRscAssetsManifest(\n rscDir: string,\n root: string,\n buildManifest: BuildManifest,\n routeClientRefKeys?: Map<string, Set<string>>\n): Promise<void> {\n const manifestPath = join(rscDir, '__vite_rsc_assets_manifest.js');\n let content: string;\n try {\n content = await readFile(manifestPath, 'utf-8');\n } catch {\n return;\n }\n\n const manifest = await parseRscManifest(manifestPath, content);\n if (!manifest) return;\n\n // Merge serverResources CSS into buildManifest.css.\n // Keys in serverResources are root-relative (e.g., \"app/layout.tsx\" or\n // \"src/app/layout.tsx\"). Convert to absolute paths to match the runtime\n // route manifest's filePath values.\n const serverResources = manifest.serverResources as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (serverResources) {\n for (const [relativePath, deps] of Object.entries(serverResources)) {\n if (deps.css && deps.css.length > 0) {\n const absolutePath = join(root, relativePath);\n buildManifest.css[absolutePath] = deps.css;\n }\n }\n }\n\n // Build per-route modulepreload entries from routeClientRefKeys +\n // clientReferenceDeps. Each route file's transitive client reference\n // keys (captured during RSC generateBundle) are mapped to their JS\n // chunk URLs via clientReferenceDeps.\n if (routeClientRefKeys && routeClientRefKeys.size > 0) {\n const clientReferenceDeps = manifest.clientReferenceDeps as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (clientReferenceDeps) {\n for (const [filePath, refKeys] of routeClientRefKeys) {\n const jsUrls = new Set<string>();\n for (const key of refKeys) {\n const deps = clientReferenceDeps[key];\n if (deps?.js) {\n for (const url of deps.js) jsUrls.add(url);\n }\n }\n if (jsUrls.size > 0) {\n buildManifest.modulepreload[filePath] = Array.from(jsUrls);\n }\n }\n }\n }\n}\n\n/**\n * Strip JS references from the RSC plugin's assets manifest files.\n *\n * The RSC plugin writes `__vite_rsc_assets_manifest.js` to rsc/ and ssr/\n * as standalone files (not Rollup chunks), so generateBundle can't\n * intercept them. This rewrites the files on disk after all builds\n * complete but before the adapter copies them to the output directory.\n */\nexport async function stripJsFromRscAssetsManifests(serverDirs: string[]): Promise<void> {\n const paths = serverDirs.map((dir) => join(dir, '__vite_rsc_assets_manifest.js'));\n\n for (const path of paths) {\n let content: string;\n try {\n content = await readFile(path, 'utf-8');\n } catch {\n continue;\n }\n\n // Try JSON.parse to check if we can safely re-serialize\n const jsonStr = content.replace(/^export default\\s*/, '').replace(/;?\\s*$/, '');\n let isStrictJson = true;\n let manifest: Record<string, unknown> | null = null;\n try {\n manifest = JSON.parse(jsonStr);\n } catch {\n isStrictJson = false;\n }\n\n if (!isStrictJson) {\n // Manifest contains renderBuiltUrl runtime expressions — cannot\n // safely re-serialize with JSON.stringify. Use targeted text\n // transforms to clear JS arrays and bootstrapScriptContent.\n let rewritten = content;\n rewritten = clearJsArrays(rewritten);\n rewritten = clearBootstrapScriptContent(rewritten);\n await writeFile(path, rewritten);\n continue;\n }\n\n // Clear JS from clientReferenceDeps — preserves CSS\n const deps = manifest?.clientReferenceDeps as\n | Record<string, { js: string[]; css: string[] }>\n | undefined;\n if (deps) {\n for (const entry of Object.values(deps)) {\n entry.js = [];\n }\n }\n\n if (manifest) manifest.bootstrapScriptContent = '';\n\n await writeFile(path, `export default ${JSON.stringify(manifest, null, 2)};\\n`);\n }\n}\n","/**\n * timber-post-build — the post-build phase, as one ordered handler.\n *\n * Everything timber does after Vite has built the three environments runs\n * here, in this order, each step handed what the previous one returned:\n *\n * 1. finalize the build manifest — font entries, the RSC assets manifest\n * merged in once, JavaScript stripped once when client JS is disabled\n * 2. prebuilt capture (cache.component prerender payloads, design/44)\n * 3. static generation (output: 'static', design/11)\n * 4. the build report\n * 5. assemble `BuildArtifacts` and call the adapter's `buildOutput`\n *\n * One `buildApp` hook with `order: 'post'` — so Vite runs the RSC plugin's\n * buildApp, which orchestrates every environment build and writes the\n * assets manifests, first. The order above is this function's, not the\n * plugin array's, and no step reads another's result off the shared\n * context: sibling plugins contribute through the typed steps they expose\n * (`FontsBuildStep`, `PrebuiltBuildStep`, `BuildReportStep`), which\n * `timber()` hands to this plugin directly.\n *\n * Design docs: 18-build-system.md §\"Post-Build Phase\", 11-platform.md\n * §\"Build Artifacts\", 49-explicit-subsystem-boundaries.md §B\n */\n\nimport type { Plugin, Rollup } from 'vite';\nimport { readdir } from 'node:fs/promises';\nimport { join, relative, resolve } from 'node:path';\nimport { adapterConfig, contextAdapter, type PluginContext } from '../plugin-context.ts';\nimport type { BuildArtifacts, DirectoryArtifact } from '../adapters/types.ts';\nimport type { BuildManifest } from '../server/build-manifest.ts';\nimport type { FontsBuildStep } from './fonts.ts';\nimport type { PrebuiltBuildStep } from './prebuilt.ts';\nimport type { BuildReportStep } from './build-report.ts';\nimport { runStaticGeneration, type StaticSite } from './static-build.ts';\nimport { mergeRscAssetsManifest, stripJsFromRscAssetsManifests } from './rsc-assets-manifest.ts';\n\n/** The Vite environments whose output adapters consume. */\nconst ARTIFACT_ENVIRONMENTS = ['client', 'rsc', 'ssr'] as const;\ntype ArtifactEnvironment = (typeof ARTIFACT_ENVIRONMENTS)[number];\n\nfunction isArtifactEnvironment(name: string): name is ArtifactEnvironment {\n return (ARTIFACT_ENVIRONMENTS as readonly string[]).includes(name);\n}\n\n/** Each environment's output directory, as its own `writeBundle` recorded it. */\nexport type EnvironmentOutputs = Partial<Record<ArtifactEnvironment, DirectoryArtifact>>;\n\n/** The steps sibling plugins own. */\nexport interface PostBuildSteps {\n fonts: FontsBuildStep;\n prebuilt: PrebuiltBuildStep;\n report: BuildReportStep;\n}\n\nexport function timberPostBuild(ctx: PluginContext, steps: PostBuildSteps): Plugin {\n const environments: EnvironmentOutputs = {};\n /** What the client environment's bundle wrote, from its `writeBundle`. */\n let clientOutput: ClientOutput = { assetsDir: '', emitted: new Set() };\n\n return {\n name: 'timber-post-build',\n\n // Record each environment's output directory as it is written, so the\n // phase learns what exists from the build rather than by probing for\n // it. The RSC plugin's scan builds run with `write: false` and never\n // reach this hook; only the real bundles do.\n writeBundle(options, bundle) {\n if (ctx.dev) return;\n const env = this.environment;\n if (!isArtifactEnvironment(env.name)) return;\n environments[env.name] = { path: resolve(env.config.root, env.config.build.outDir) };\n if (env.name === 'client') {\n clientOutput = {\n assetsDir: hashedAssetsDir(env.config.build.assetsDir, options),\n emitted: new Set(Object.keys(bundle)),\n };\n }\n },\n\n buildApp: {\n order: 'post' as const,\n async handler() {\n if (ctx.dev) return;\n await runPostBuild(ctx, steps, environments, clientOutput);\n },\n },\n };\n}\n\n/**\n * The client bundle's assets directory, in the artifacts' form (no leading\n * or trailing slash) — or `''` when its files are not all content-hashed.\n *\n * `assetsDir` names where Vite writes; it is the naming patterns that decide\n * whether a file name carries a hash. Vite's defaults do\n * (`<assetsDir>/[name]-[hash].js`), but an app can set\n * `assetFileNames: 'static/[name][extname]'`, and marking that directory\n * immutable would pin a changed image under an unchanged URL for a year. A\n * pattern given as a function cannot be inspected, so it counts as unhashed:\n * those files fall back to the revalidating per-file rule.\n *\n * @internal Exported for testing.\n */\nexport function hashedAssetsDir(\n assetsDir: string,\n output: Pick<\n Rollup.NormalizedOutputOptions,\n 'entryFileNames' | 'chunkFileNames' | 'assetFileNames'\n >\n): string {\n const dir = assetsDir.replace(/^\\/+|\\/+$/g, '');\n const patterns = [output.entryFileNames, output.chunkFileNames, output.assetFileNames];\n const hashed = patterns.every((p) => typeof p === 'string' && p.includes('[hash'));\n return hashed ? dir : '';\n}\n\n/** The client bundle as its own `writeBundle` saw it. */\ninterface ClientOutput {\n /** From `hashedAssetsDir` — `''` when the naming patterns are not all hashed. */\n assetsDir: string;\n /** Every file name the bundle emitted, relative to the client output directory. */\n emitted: ReadonlySet<string>;\n}\n\n/**\n * Keep only the directories whose every file the client bundle emitted.\n *\n * A producer knows it hashes what *it* writes, not what else lands beside it:\n * Vite copies `public/` into the client output verbatim, so `public/assets/logo.png`\n * sits in `assets/` under a stable name, and `public/_rsc/…` would sit among\n * the hashed payloads. A directory holding any file the bundle did not emit\n * is not content-hashed as a whole, and marking it immutable would pin that\n * file for a year — so it is dropped, and its files take the per-file rule.\n *\n * @internal Exported for testing.\n */\nexport async function onlyEmittedDirs(\n clientDir: string,\n dirs: readonly string[],\n emitted: ReadonlySet<string>\n): Promise<string[]> {\n const kept: string[] = [];\n for (const dir of dirs) {\n const root = join(clientDir, dir);\n const entries = await readdir(root, { recursive: true, withFileTypes: true }).catch(() => []);\n const foreign = entries.some(\n (entry) =>\n entry.isFile() &&\n !emitted.has(relative(clientDir, join(entry.parentPath, entry.name)).replace(/\\\\/g, '/'))\n );\n if (!foreign) kept.push(dir);\n }\n return kept;\n}\n\nasync function runPostBuild(\n ctx: PluginContext,\n steps: PostBuildSteps,\n environments: EnvironmentOutputs,\n clientOutput: ClientOutput\n): Promise<void> {\n const output = ctx.config.output ?? 'server';\n const rsc = requireEnvironment(environments, 'rsc');\n const ssr = requireEnvironment(environments, 'ssr');\n\n // 1. The manifest is complete before anything renders with it. Published\n // for the steps that import the built bundle in this process — the same\n // value `manifestInit` carries to production. Assigned, never `??=`: a\n // second build in one process must not render with the first one's.\n const manifest = await finalizeBuildManifest(ctx, steps.fonts, rsc, ssr);\n if (manifest) Reflect.set(globalThis, '__TIMBER_BUILD_MANIFEST__', manifest);\n\n // 2–3. Each writes its own output and returns what it wrote.\n const prebuilt = await steps.prebuilt.capture(rsc.path);\n const site = output === 'static' ? await runStaticGeneration(ctx, rsc.path) : undefined;\n\n // 4.\n steps.report.print(prebuilt);\n\n // 5.\n const adapter = contextAdapter(ctx);\n if (!adapter || typeof adapter.buildOutput !== 'function') return;\n\n await adapter.buildOutput(\n adapterConfig(ctx),\n assembleBuildArtifacts({\n output,\n outputDir: ctx.buildDir,\n environments,\n immutableDirs: await onlyEmittedDirs(\n requireEnvironment(environments, 'client').path,\n [\n ...(clientOutput.assetsDir ? [clientOutput.assetsDir] : []),\n ...steps.fonts.immutableDirs(),\n ...(site?.immutableDirs ?? []),\n ],\n clientOutput.emitted\n ),\n prebuilt: prebuilt?.artifact,\n site,\n manifestInit: manifest ? serializeManifestInit(manifest) : undefined,\n })\n );\n}\n\nfunction requireEnvironment(\n environments: EnvironmentOutputs,\n name: ArtifactEnvironment\n): DirectoryArtifact {\n const artifact = environments[name];\n if (!artifact) {\n throw new Error(`[timber] Build output: the ${name} environment wrote no bundle`);\n }\n return artifact;\n}\n\n/**\n * Step 1: bring the build manifest to its final shape, once.\n *\n * `timber-build-manifest` creates it from the client bundle; this adds what\n * only exists once every environment is built — the font entries and the\n * per-route CSS and modulepreloads in the RSC plugin's assets manifest —\n * and then, when client JavaScript is disabled, removes every JavaScript\n * reference, from the manifest and from the assets manifests on disk. The\n * manifest's `js` / `modulepreload` are cleared after the merge has written\n * into them, so nothing the merge adds survives.\n *\n * Returns null only when no client bundle produced a manifest.\n *\n * @internal Exported for testing.\n */\nexport async function finalizeBuildManifest(\n ctx: PluginContext,\n fonts: FontsBuildStep,\n rsc: DirectoryArtifact,\n ssr: DirectoryArtifact\n): Promise<BuildManifest | null> {\n const manifest = ctx.buildManifest;\n if (manifest) {\n fonts.contributeManifest(manifest);\n // Per-route CSS and client reference JS, for <link rel=\"stylesheet\">\n // and <link rel=\"modulepreload\"> on server component routes (TIM-1014).\n await mergeRscAssetsManifest(rsc.path, ctx.root, manifest, ctx.routeClientRefKeys);\n }\n if (ctx.clientJavascript.disabled) {\n // Those files are not served, so hints for them are useless.\n if (manifest) {\n manifest.js = {};\n manifest.modulepreload = {};\n }\n await stripJsFromRscAssetsManifests([rsc.path, ssr.path]);\n }\n return manifest;\n}\n\n/**\n * The build manifest as a JS module that sets the global. Adapters write\n * it as `_timber-manifest-init.js` (or prepend it to the entry) and\n * evaluate it before the RSC handler, so `virtual:timber-build-manifest`\n * finds it.\n */\nfunction serializeManifestInit(manifest: BuildManifest): string {\n return `globalThis.__TIMBER_BUILD_MANIFEST__ = ${JSON.stringify(manifest)};\\n`;\n}\n\n/**\n * Dedupe the producers' directories and drop any that sits inside another.\n *\n * Two producers can name overlapping directories — a custom `assetsDir` of\n * `_timber` beside the fonts' `_timber/fonts`. Cloudflare and Netlify apply\n * every matching `_headers` rule, so emitting both would send two\n * `Cache-Control` values for one file; the outer directory already covers\n * the inner one.\n */\nfunction canonicalImmutableDirs(dirs: readonly string[]): string[] {\n const unique = [...new Set(dirs)];\n return unique.filter(\n (dir) => !unique.some((other) => other !== dir && dir.startsWith(`${other}/`))\n );\n}\n\n/**\n * Assemble the adapter's view of the build from what each step returned.\n *\n * Not a validator: every field is copied from the phase that produced it.\n * The throws are the states the union cannot represent — a Vite environment\n * that wrote no bundle, a static build with no site. Each means an earlier\n * phase failed without failing the build, and a deploy missing its SSR\n * bundle fails on the first request rather than here.\n *\n * @internal Exported for testing.\n */\nexport function assembleBuildArtifacts(input: {\n output: 'server' | 'static';\n outputDir: string;\n environments: EnvironmentOutputs;\n immutableDirs: readonly string[];\n prebuilt?: DirectoryArtifact;\n site?: StaticSite;\n manifestInit?: string;\n}): BuildArtifacts {\n const { output, outputDir, environments } = input;\n const client = requireEnvironment(environments, 'client');\n const immutableDirs = canonicalImmutableDirs(input.immutableDirs);\n\n if (output === 'static') {\n if (!input.site) {\n throw new Error(\n \"[timber] Build output: output is 'static' but static generation recorded no site\"\n );\n }\n const { pages, contentTypes } = input.site;\n return { output, outputDir, client, immutableDirs, pages, contentTypes };\n }\n\n return {\n output,\n outputDir,\n client,\n immutableDirs,\n rsc: requireEnvironment(environments, 'rsc'),\n ssr: requireEnvironment(environments, 'ssr'),\n prebuilt: input.prebuilt,\n manifestInit: input.manifestInit,\n };\n}\n","/**\n * timber-build-report — Post-build route summary table.\n *\n * After a production build, logs a per-route table showing:\n * - Route type (○ static, λ dynamic, ƒ function)\n * - Route-specific client JS size\n * - First-load JS size (gzip) — route-specific + shared chunks\n *\n * Only active during production builds. Sizes are computed from the\n * already-generated Vite client bundle — no extra analysis passes.\n *\n * Design docs: 18-build-system.md §\"Build Pipeline\", 07-routing.md\n * Task: TIM-287\n */\n\nimport { readFileSync } from 'node:fs';\nimport { join, relative } from 'node:path';\nimport { gzipSync } from 'node:zlib';\nimport type { Plugin, Logger } from 'vite';\nimport type { PluginContext } from '../plugin-context.ts';\nimport type { SegmentNode, RouteTree } from '../routing/types.ts';\nimport type { CaptureSummary } from '../server/prebuilt-builder.ts';\nimport type { PrebuiltCaptureResult } from './prebuilt-capture.ts';\nimport type { PrebuiltManifest } from '../server/prebuilt/payload-source.ts';\nimport { collectLeafRoutes } from '../routing/walkers.ts';\nimport { formatSize } from '../utils/format.ts';\n\n// ─── Public types ─────────────────────────────────────────────────────────\n\nexport type RouteType = 'static' | 'dynamic' | 'function';\n\nexport interface RouteEntry {\n path: string;\n type: RouteType;\n /** Route-specific client JS size in bytes (raw). */\n size: number;\n /** Total first-load JS in bytes (gzip): route-specific + shared. */\n firstLoadSize: number;\n}\n\n// ─── Route classification ─────────────────────────────────────────────────\n\nconst ROUTE_TYPE_ICONS: Record<RouteType, string> = {\n static: '○',\n dynamic: 'λ',\n function: 'ƒ',\n};\n\n/**\n * Classify a route by its segment chain and output mode.\n *\n * In server mode (default), all pages are dynamic (rendered per-request)\n * and API routes (route.ts) are classified as function.\n * In static mode, everything is pre-rendered at build time — all routes\n * are static regardless of dynamic segments or route.ts presence.\n */\nexport function classifyRoute(\n segments: SegmentNode[],\n outputMode: 'server' | 'static' = 'server'\n): RouteType {\n if (outputMode === 'static') return 'static';\n const leaf = segments[segments.length - 1];\n if (leaf?.route) return 'function';\n return 'dynamic';\n}\n\n// ─── Size helpers ─────────────────────────────────────────────────────────\n\nexport { formatSize };\n\nfunction green(text: string): string {\n return `\\x1b[92m${text}\\x1b[39m`; // bright/light green (ANSI 92)\n}\n\n// ─── Route tree collection ────────────────────────────────────────────────\n\ninterface RouteInfo {\n path: string;\n segments: SegmentNode[];\n entryFilePath: string | null;\n}\n\n/**\n * Walk the route tree and collect all leaf routes (pages + API endpoints).\n *\n * Wraps the shared `collectLeafRoutes` walker (TIM-848). Parallel slots\n * (`@artists`, `@shows`, etc.) are intentionally skipped — they render\n * alongside the parent page at the same URL and are not separately\n * URL-addressable. Their JS is captured in shared/layout chunks.\n *\n * After collection, entries are deduplicated by URL path so that overlapping\n * route groups (e.g. `(browse)` and `(marketing)` both producing `/`) only\n * appear once. The entry with the longest segment chain (most specific\n * match) wins.\n */\nexport function collectRoutes(tree: RouteTree): RouteInfo[] {\n const leaves = collectLeafRoutes(tree.root);\n const routes: RouteInfo[] = leaves.map((leaf) => ({\n path: leaf.urlPath,\n segments: leaf.segments,\n entryFilePath: leaf.page?.filePath ?? leaf.route?.filePath ?? null,\n }));\n\n // Deduplicate entries with the same URL path (e.g. from overlapping route groups).\n // Keep the entry with the longest segment chain (most specific match).\n const seen = new Map<string, RouteInfo>();\n for (const route of routes) {\n const existing = seen.get(route.path);\n if (!existing || route.segments.length > existing.segments.length) {\n seen.set(route.path, route);\n }\n }\n return Array.from(seen.values());\n}\n\n// ─── Report formatting ────────────────────────────────────────────────────\n\n/** Produce formatted report lines for the Vite logger. */\nexport function buildRouteReport(entries: RouteEntry[], sharedSize: number): string[] {\n const sorted = [...entries].sort((a, b) => a.path.localeCompare(b.path));\n\n const header = 'Route (app)';\n const sizeHeader = 'Size';\n const firstLoadHeader = 'First Load JS';\n\n const pathW = Math.max(header.length + 2, ...sorted.map((e) => e.path.length + 6));\n const sizeW = Math.max(sizeHeader.length, 14);\n const flW = Math.max(firstLoadHeader.length, 10);\n const totalW = pathW + sizeW + flW + 4;\n const sep = '─'.repeat(totalW);\n\n const lines: string[] = [];\n\n // Header\n lines.push(\n `${pad(header, pathW)} ${pad(sizeHeader, sizeW, 'left')} ${pad(firstLoadHeader, flW, 'left')}`\n );\n lines.push(sep);\n\n // Routes\n for (const entry of sorted) {\n const icon = ROUTE_TYPE_ICONS[entry.type];\n const pathStr = ` ${icon} ${entry.path}`;\n const sizeStr = entry.size === 0 ? green('zero unique JS') : formatSize(entry.size);\n const flStr = formatSize(entry.firstLoadSize);\n lines.push(\n `${pad(pathStr, pathW)} ${pad(sizeStr, sizeW, 'left')} ${pad(flStr, flW, 'left')}`\n );\n }\n\n // Footer\n lines.push(sep);\n lines.push(\n `${pad(' Shared by all', pathW)} ${pad('', sizeW, 'left')} ${pad(formatSize(sharedSize), flW, 'left')}`\n );\n lines.push('');\n lines.push('○ (Static) λ (Dynamic) ƒ (Function)');\n\n return lines;\n}\n\n/** Check route entries against a First-Load-JS budget and return warning lines. */\nexport function buildWarnings(entries: RouteEntry[], budget?: { firstLoadJs?: number }): string[] {\n if (!budget?.firstLoadJs) return [];\n const limit = budget.firstLoadJs;\n const warnings: string[] = [];\n for (const entry of entries) {\n if (entry.firstLoadSize > limit) {\n warnings.push(\n `⚠ ${entry.path} first-load JS (${formatSize(entry.firstLoadSize)}) exceeds budget (${formatSize(limit)})`\n );\n }\n }\n return warnings;\n}\n\nfunction pad(str: string, width: number, align: 'left' | 'right' = 'right'): string {\n const gap = Math.max(0, width - stripAnsi(str).length);\n return align === 'left' ? ' '.repeat(gap) + str : str + ' '.repeat(gap);\n}\n\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\u001b\\[\\d+m/g, '');\n}\n\n// ─── Prebuilt component stats ────────────────────────────────────────────\n\nexport interface PrebuiltComponentStats {\n componentId: string;\n entryCount: number;\n totalBytes: number;\n}\n\nexport interface PrebuiltReportData {\n components: PrebuiltComponentStats[];\n totalEntries: number;\n totalBytes: number;\n skippedCount: number;\n skippedReasons: Array<{ componentId: string; route: string; message: string }>;\n}\n\n/** Read the manifest of the prebuilt artifact this build recorded, if any. */\nexport function loadPrebuiltManifest(prebuiltDir: string | undefined): PrebuiltManifest | null {\n if (!prebuiltDir) return null;\n return JSON.parse(readFileSync(join(prebuiltDir, 'manifest.json'), 'utf-8')) as PrebuiltManifest;\n}\n\nexport function buildPrebuiltReportData(\n manifest: PrebuiltManifest | null,\n summary: CaptureSummary | undefined\n): PrebuiltReportData | null {\n const hasCaptures = summary && (summary.captured > 0 || summary.skipped.length > 0);\n if (!manifest && !hasCaptures) return null;\n\n const components: PrebuiltComponentStats[] = [];\n let totalEntries = 0;\n let totalBytes = 0;\n\n if (manifest) {\n for (const [componentId, component] of Object.entries(manifest)) {\n let entryCount = 0;\n let componentBytes = 0;\n for (const entry of Object.values(component.entries)) {\n entryCount++;\n componentBytes += entry.bytes ?? 0;\n }\n components.push({ componentId, entryCount, totalBytes: componentBytes });\n totalEntries += entryCount;\n totalBytes += componentBytes;\n }\n components.sort((a, b) => a.componentId.localeCompare(b.componentId));\n }\n\n const skippedCount = summary?.skipped.length ?? 0;\n const skippedReasons = (summary?.skipped ?? []).map((s) => ({\n componentId: s.componentId,\n route: s.routeUrlPath,\n message: s.message,\n }));\n\n return { components, totalEntries, totalBytes, skippedCount, skippedReasons };\n}\n\nexport function buildPrebuiltReport(data: PrebuiltReportData): string[] {\n const lines: string[] = [];\n\n const total = data.totalEntries + data.skippedCount;\n lines.push(\n `Prebuilt ${data.totalEntries}/${total} entries across ` +\n `${data.components.length} component${data.components.length !== 1 ? 's' : ''}` +\n (data.totalBytes > 0 ? ` (${formatSize(data.totalBytes)} total)` : '') +\n '.' +\n (data.skippedCount > 0 ? ` ${data.skippedCount} skipped due to errors.` : '')\n );\n\n if (data.components.length > 0) {\n lines.push('');\n const nameHeader = 'Component';\n const entriesHeader = 'Entries';\n const sizeHeader = 'Size';\n\n const nameW = Math.max(\n nameHeader.length + 2,\n ...data.components.map((c) => c.componentId.length + 4)\n );\n const entriesW = Math.max(entriesHeader.length, 8);\n const sizeW = Math.max(sizeHeader.length, 10);\n const totalW = nameW + entriesW + sizeW + 4;\n const sep = '─'.repeat(totalW);\n\n lines.push(\n `${pad(nameHeader, nameW)} ${pad(entriesHeader, entriesW, 'left')} ${pad(sizeHeader, sizeW, 'left')}`\n );\n lines.push(sep);\n\n for (const comp of data.components) {\n const nameStr = ` ◆ ${comp.componentId}`;\n const entriesStr = String(comp.entryCount);\n const sizeStr = formatSize(comp.totalBytes);\n lines.push(\n `${pad(nameStr, nameW)} ${pad(entriesStr, entriesW, 'left')} ${pad(sizeStr, sizeW, 'left')}`\n );\n }\n }\n\n if (data.skippedReasons.length > 0) {\n lines.push('');\n lines.push('Skipped entries:');\n for (const s of data.skippedReasons) {\n lines.push(` ⚠ ${s.componentId} (${s.route}) — ${s.message}`);\n }\n }\n\n return lines;\n}\n\n// ─── Bundle analysis ──────────────────────────────────────────────────────\n\ninterface ChunkSize {\n raw: number;\n gzip: number;\n}\n\ninterface OutputChunkLike {\n type: 'chunk' | 'asset';\n fileName: string;\n name?: string;\n code?: string;\n source?: string | Uint8Array;\n modules?: Record<string, unknown>;\n facadeModuleId?: string | null;\n}\n\n/** Measure raw + gzip sizes for all JS chunks and CSS assets in a bundle. */\nexport function collectChunkSizes(bundle: Record<string, OutputChunkLike>): Map<string, ChunkSize> {\n const sizes = new Map<string, ChunkSize>();\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type === 'chunk' && item.code) {\n sizes.set(fileName, measure(item.code));\n } else if (item.type === 'asset' && fileName.endsWith('.css') && item.source != null) {\n const src =\n typeof item.source === 'string' ? item.source : new TextDecoder().decode(item.source);\n sizes.set(fileName, measure(src));\n }\n }\n return sizes;\n}\n\nfunction measure(content: string): ChunkSize {\n const buf = new TextEncoder().encode(content);\n return { raw: buf.length, gzip: gzipSync(buf).length };\n}\n\n/** Find the output chunk that contains a given input file. */\nexport function findChunkForFile(\n filePath: string,\n bundle: Record<string, OutputChunkLike>\n): string | null {\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type !== 'chunk') continue;\n if (item.facadeModuleId === filePath) return fileName;\n if (item.modules && filePath in item.modules) return fileName;\n }\n return null;\n}\n\n// ─── Route → chunk group matching ────────────────────────────────────────\n\n/**\n * Derive the expected client chunk group prefix for a route.\n *\n * Mirrors the `clientChunkGroup` logic: extract the first non-group segment\n * from the route's file path under appDir. Routes at the root level or\n * without a matching segment return null (their JS is in client-shared).\n */\nfunction routeChunkGroupPrefix(entryFilePath: string, appDir: string, root: string): string | null {\n const appPrefix = relative(root, appDir).replace(/\\\\/g, '/') + '/';\n const relPath = relative(root, entryFilePath).replace(/\\\\/g, '/');\n if (!relPath.startsWith(appPrefix)) return null;\n\n const withinApp = relPath.slice(appPrefix.length);\n const segments = withinApp.split('/');\n for (const seg of segments) {\n if (seg.includes('.')) break;\n if (seg.startsWith('(') && seg.endsWith(')')) continue;\n return `client-${seg}`;\n }\n return null;\n}\n\n/**\n * Find all client bundle chunks belonging to a chunk group.\n *\n * Uses the chunk's `name` property (set by Rolldown from the `clientChunks`\n * callback's return value) for exact matching. The `name` is the group name\n * itself (e.g. `client-docs`), not the hashed filename.\n */\nexport function findChunksForGroup(\n groupName: string,\n chunkSizes: Map<string, ChunkSize>,\n bundle?: Record<string, OutputChunkLike>\n): string[] {\n if (!bundle) return [];\n const matched: string[] = [];\n for (const [fileName, item] of Object.entries(bundle)) {\n if (item.type !== 'chunk') continue;\n if (item.name === groupName && chunkSizes.has(fileName)) {\n matched.push(fileName);\n }\n }\n return matched;\n}\n\n// ─── Build route entries from collected data ──────────────────────────────\n\nfunction buildEntries(\n routeTree: RouteTree,\n chunkSizes: Map<string, ChunkSize>,\n bundle: Record<string, OutputChunkLike>,\n outputMode: 'server' | 'static',\n appDir?: string,\n root?: string\n): { entries: RouteEntry[]; sharedGzip: number } {\n const routeInfos = collectRoutes(routeTree);\n\n // Total gzip across all client chunks\n let totalGzip = 0;\n for (const s of chunkSizes.values()) totalGzip += s.gzip;\n\n // Per-route sizes. Track route-specific chunks to compute shared size.\n const routeChunkFiles = new Set<string>();\n const entries: RouteEntry[] = [];\n\n for (const info of routeInfos) {\n let raw = 0;\n let gzip = 0;\n\n if (info.entryFilePath) {\n // Try chunk group matching first (works for server component routes\n // whose client JS is in client-<segment> chunks, not in the route's\n // own page.tsx chunk). Falls back to direct chunk lookup.\n let matched = false;\n if (appDir && root) {\n const groupPrefix = routeChunkGroupPrefix(info.entryFilePath, appDir, root);\n if (groupPrefix) {\n const chunks = findChunksForGroup(groupPrefix, chunkSizes, bundle);\n for (const chunk of chunks) {\n const s = chunkSizes.get(chunk);\n if (s) {\n raw += s.raw;\n gzip += s.gzip;\n }\n routeChunkFiles.add(chunk);\n }\n if (chunks.length > 0) matched = true;\n }\n }\n\n if (!matched) {\n const chunk = findChunkForFile(info.entryFilePath, bundle);\n if (chunk) {\n const s = chunkSizes.get(chunk);\n if (s) {\n raw = s.raw;\n gzip = s.gzip;\n }\n routeChunkFiles.add(chunk);\n }\n }\n }\n\n entries.push({\n path: info.path,\n type: classifyRoute(info.segments, outputMode),\n size: raw,\n firstLoadSize: gzip, // route-specific gzip — shared added below\n });\n }\n\n // Shared = total gzip minus route-specific gzip\n let routeGzip = 0;\n for (const f of routeChunkFiles) routeGzip += chunkSizes.get(f)?.gzip ?? 0;\n const sharedGzip = totalGzip - routeGzip;\n\n for (const e of entries) e.firstLoadSize += sharedGzip;\n\n return { entries, sharedGzip };\n}\n\n// ─── Vite plugin ──────────────────────────────────────────────────────────\n\n/**\n * Suppress RSC/SSR per-chunk build log lines.\n *\n * Vite logs each output chunk via config.logger.info(). We wrap that method\n * to filter lines matching dist/rsc/ or dist/ssr/ paths. The regex is\n * non-anchored because Vite prepends ANSI color codes.\n */\nfunction suppressNonClientLogs(config: { command: string; logger: Logger }): void {\n if (config.command !== 'build') return;\n const orig = config.logger.info.bind(config.logger);\n config.logger.info = (msg: string, opts?: { timestamp?: boolean }) => {\n if (typeof msg === 'string' && /dist\\/(rsc|ssr)\\//.test(msg)) return;\n orig(msg, opts);\n };\n}\n\n/**\n * What the post-build phase asks of the build report (plugins/post-build.ts).\n * Printed from there, once, after every environment is built and after the\n * prebuilt capture pass — so nothing here depends on the order in which\n * Vite closes each environment's bundle.\n */\nexport interface BuildReportStep {\n print(prebuilt: PrebuiltCaptureResult | null): void;\n}\n\nexport function timberBuildReport(ctx: PluginContext): Plugin & { api: BuildReportStep } {\n let logger: Logger | null = null;\n let chunkSizes: Map<string, ChunkSize> | null = null;\n let clientBundle: Record<string, OutputChunkLike> | null = null;\n const buildStart = performance.now();\n\n function printRouteTable(): void {\n if (!ctx.routeTree || !chunkSizes || !clientBundle || !logger) return;\n\n const outputMode = ctx.config.output ?? 'server';\n const clientJsDisabled = ctx.clientJavascript.disabled;\n const { entries, sharedGzip } = clientJsDisabled\n ? {\n entries: collectRoutes(ctx.routeTree).map((info) => ({\n path: info.path,\n type: classifyRoute(info.segments, outputMode),\n size: 0,\n firstLoadSize: 0,\n })),\n sharedGzip: 0,\n }\n : buildEntries(ctx.routeTree, chunkSizes, clientBundle, outputMode, ctx.appDir, ctx.root);\n const elapsed = ((performance.now() - buildStart) / 1000).toFixed(2);\n const lines = buildRouteReport(entries, sharedGzip);\n\n logger.info('');\n for (const line of lines) logger.info(line);\n\n const warnings = buildWarnings(entries, ctx.config.budget);\n if (warnings.length > 0) {\n logger.info('');\n for (const w of warnings) logger.warn(w);\n }\n\n logger.info('');\n logger.info(\n `✓ built ${entries.length} routes for all three environments (rsc, ssr, client) in ${elapsed}s`\n );\n logger.info('');\n }\n\n function printPrebuiltReport(prebuilt: PrebuiltCaptureResult | null): void {\n if (!logger || !prebuilt) return;\n const manifest = loadPrebuiltManifest(prebuilt.artifact?.path);\n const prebuiltData = buildPrebuiltReportData(manifest, prebuilt.summary);\n if (!prebuiltData) return;\n\n logger.info('');\n for (const line of buildPrebuiltReport(prebuiltData)) logger.info(line);\n logger.info('');\n }\n\n return {\n name: 'timber-build-report',\n\n api: {\n print(prebuilt) {\n if (ctx.dev) return;\n printRouteTable();\n printPrebuiltReport(prebuilt);\n },\n },\n\n config(_cfg, { command }) {\n if (command !== 'build') return;\n return {\n environments: {\n rsc: { build: { reportCompressedSize: false } },\n ssr: { build: { reportCompressedSize: false } },\n },\n };\n },\n\n configResolved(config) {\n logger = config.logger;\n suppressNonClientLogs(config);\n },\n\n generateBundle(_options, bundle) {\n if (ctx.dev) return;\n if (this.environment?.name && this.environment.name !== 'client') return;\n\n chunkSizes = collectChunkSizes(bundle as Record<string, OutputChunkLike>);\n clientBundle = { ...bundle } as Record<string, OutputChunkLike>;\n },\n };\n}\n","/**\n * Server action bound args encryption utilities.\n *\n * Provides key management for the RSC plugin's built-in bound args encryption.\n * The RSC plugin (@vitejs/plugin-rsc) handles the actual encrypt/decrypt via\n * AES-256-GCM — this module handles:\n *\n * 1. Key sourcing: auto-generated at build time (embedded in bundle), overridable\n * via env var for cross-build key sharing (rolling/blue-green deployments)\n * 2. Build-time key expression generation for the RSC plugin's `defineEncryptionKey`\n *\n * Encryption is always on in production. In dev mode, it's on by default\n * (matching the RSC plugin's behavior) but can be disabled for debugging.\n *\n * ## Known Security Considerations\n *\n * 1. **defineEncryptionKey is a raw JS expression.** The RSC plugin inlines it\n * verbatim into generated code. We only emit the hardcoded string\n * `process.env.TIMBER_ACTIONS_ENCRYPTION_KEY` — never user-controlled input.\n * If this function is ever extended to accept configurable env var names,\n * the expression MUST be validated against a safe pattern.\n *\n * 2. **Key material lives in GC-visible JS strings.** `atob()` decodes the key\n * into a regular JavaScript string on the V8 heap. JavaScript has no\n * `SecureString` or memory-zeroing primitive — this is an inherent platform\n * limitation. Acceptable for web server use; would need review for FIPS.\n *\n * 3. **TIMBER_ACTIONS_ENCRYPTION_KEY must be set at both build time and runtime.**\n * At build time, we validate the key format and emit a runtime expression.\n * If the env var is present at build time but missing at runtime, the server\n * will crash on first action invocation with an opaque `atob(undefined)` error.\n * If the env var is present at runtime but was absent at build time, the RSC\n * plugin will have generated its own key and the env var is silently ignored.\n *\n * See design/08-forms-and-actions.md §\"Security\"\n * See design/13-security.md\n */\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/** User-facing configuration for action bound args encryption. */\nexport interface ActionEncryptionConfig {\n /**\n * Disable encryption in dev mode for easier debugging.\n * Has no effect in production — encryption is always enabled.\n * Default: false (encryption is on in dev too).\n */\n disableInDev?: boolean;\n}\n\n// ─── Key Resolution ───────────────────────────────────────────────────────\n\n/**\n * Regex for safe `defineEncryptionKey` expressions.\n *\n * The RSC plugin inlines this expression verbatim into generated JavaScript.\n * We restrict it to `process.env.<UPPER_SNAKE_CASE>` to prevent code injection.\n * See \"Known Security Considerations\" at the top of this file.\n */\nconst SAFE_KEY_EXPR = /^process\\.env\\.[A-Z_][A-Z0-9_]*$/;\n\n/**\n * Build the `defineEncryptionKey` expression for the RSC plugin.\n *\n * The RSC plugin accepts a JavaScript expression string that will be\n * inlined into the encryption runtime module. At runtime, this expression\n * must evaluate to the base64-encoded encryption key.\n *\n * Priority:\n * 1. `TIMBER_ACTIONS_ENCRYPTION_KEY` env var (for cross-build key sharing\n * in rolling/blue-green deployments)\n * 2. Auto-generated at build time (RSC plugin default — embedded in bundle,\n * consistent across all instances of the same build)\n *\n * For env var keys, we generate a runtime expression that reads the env var.\n * For auto-generated keys, we return undefined and let the RSC plugin handle it.\n */\nexport function resolveEncryptionKeyExpression(): string | undefined {\n // Check for env var override — used for cross-build key sharing where\n // multiple builds must agree on the same encryption key.\n const envKey = process.env.TIMBER_ACTIONS_ENCRYPTION_KEY;\n if (envKey) {\n // Validate the key format (must be base64-encoded 32-byte key)\n validateKeyFormat(envKey);\n\n // Return a runtime expression that reads the env var at startup.\n // This ensures the key is read at runtime, not embedded in the build.\n const expr = 'process.env.TIMBER_ACTIONS_ENCRYPTION_KEY';\n\n // Defense-in-depth: validate the expression matches our safe pattern.\n // This is redundant today (hardcoded string), but protects against\n // future refactors that might make the expression configurable.\n if (!SAFE_KEY_EXPR.test(expr)) {\n throw new Error(`Unsafe encryption key expression: ${expr}`);\n }\n\n return expr;\n }\n\n // No override — let the RSC plugin auto-generate a per-build key\n return undefined;\n}\n\n/**\n * Determine whether action encryption should be enabled.\n *\n * Encryption is always enabled in production. In dev mode, it's enabled\n * by default but can be disabled via config for debugging.\n */\nexport function shouldEnableEncryption(isDev: boolean, config?: ActionEncryptionConfig): boolean {\n if (!isDev) return true; // Always on in production\n if (config?.disableInDev) return false; // Opt-out in dev\n return true; // On by default in dev too\n}\n\n// ─── Key Validation ───────────────────────────────────────────────────────\n\n/**\n * Validate that a key string is a valid base64-encoded 256-bit key.\n * Throws a descriptive error if the key is malformed.\n */\nexport function validateKeyFormat(key: string): void {\n // Decode base64 and check length (32 bytes = 256 bits)\n try {\n const decoded = atob(key);\n const bytes = decoded.length;\n if (bytes !== 32) {\n throw new Error(\n `TIMBER_ACTIONS_ENCRYPTION_KEY must be a base64-encoded 256-bit (32-byte) key. ` +\n `Got ${bytes} bytes. Generate one with: ` +\n `node -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"`\n );\n }\n } catch (error) {\n if (error instanceof Error && error.message.includes('TIMBER_ACTIONS_ENCRYPTION_KEY')) {\n throw error;\n }\n throw new Error(\n `TIMBER_ACTIONS_ENCRYPTION_KEY is not valid base64. ` +\n `Generate a key with: ` +\n `node -e \"console.log(require('crypto').randomBytes(32).toString('base64'))\"`\n );\n }\n}\n","/**\n * Dev holding server — serves a loading page while Vite initializes.\n *\n * When `timber dev` (or `vite dev`) starts, Vite takes several seconds\n * to initialize all plugins, scan routes, and boot the RSC environment.\n * During this window, the port is unbound and browsers get\n * ERR_CONNECTION_REFUSED.\n *\n * This module creates a lightweight HTTP server that binds the port\n * immediately and serves a branded holding page with auto-refresh.\n * Once Vite is ready, the holding server is closed and Vite's server\n * takes over the port.\n *\n * The holding server is started in rootSync's config() hook (the\n * earliest Vite plugin lifecycle point where we know the port) and\n * closed directly in timber-dev-server's configureServer() hook\n * (the last plugin, awaited). configureServer runs during\n * createServer(), well before Vite's port probe and bind, so the\n * port is free by the time httpServerStart() runs. (TIM-1419)\n *\n * Browser requests (Accept: text/html) get the HTML holding page.\n * API requests (Accept: application/json) get a 503 JSON response.\n * All responses include Retry-After: 1.\n *\n * See design/21-dev-server.md, TIM-665.\n */\n\nimport http from 'node:http';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface HoldingServer {\n /**\n * Start listening on the given port and host.\n * The host must match Vite's resolved `server.host` so the probe\n * faithfully detects conflicts on the same address Vite will bind.\n * Returns the actual bound port (useful when port is 0 for OS assignment).\n */\n listen(port: number, host?: string): Promise<number>;\n\n /** Gracefully close the server and stop accepting connections. */\n close(): Promise<void>;\n}\n\n// ─── Holding Page HTML ────────────────────────────────────────────────────\n\n/**\n * Minimal self-contained HTML holding page.\n *\n * Matches the timber.js docs site theme:\n * - Light mode: warm stone/grain background, timber/bark text\n * - Dark mode: stone-900 background, stone-200 text\n * - 🪵 timber.js branding\n *\n * Uses meta-refresh (1s) for auto-reload — works without JavaScript.\n * Inline CSS only, no external dependencies.\n */\nconst HOLDING_PAGE_HTML = [\n '<!DOCTYPE html>',\n '<html lang=\"en\">',\n '<head>',\n ' <meta charset=\"utf-8\">',\n ' <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">',\n ' <meta http-equiv=\"refresh\" content=\"2\">',\n ' <title>timber — starting...</title>',\n ' <style>',\n ' *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }',\n ' body {',\n ' font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;',\n ' background: #fafaf9;',\n ' color: #44403c;',\n ' display: flex;',\n ' align-items: center;',\n ' justify-content: center;',\n ' min-height: 100vh;',\n ' -webkit-font-smoothing: antialiased;',\n ' }',\n ' @media (prefers-color-scheme: dark) {',\n ' body { background: #1c1917; color: #e7e5e4; }',\n ' .message { color: #a8a29e; }',\n ' .spinner { border-color: #57534e; border-top-color: #a1887f; }',\n ' .logo { color: #e7e5e4; }',\n ' }',\n ' .container { text-align: center; padding: 2rem; }',\n ' .logo {',\n ' font-size: 1.5rem;',\n ' font-weight: 700;',\n ' letter-spacing: -0.02em;',\n ' color: #5c3d2e;',\n ' margin-bottom: 1.5rem;',\n ' }',\n ' .message {',\n ' font-size: 0.95rem;',\n ' color: #78716c;',\n ' margin-bottom: 2rem;',\n ' }',\n ' .spinner {',\n ' width: 24px;',\n ' height: 24px;',\n ' border: 2.5px solid #d7ccc8;',\n ' border-top-color: #6d4c41;',\n ' border-radius: 50%;',\n ' animation: spin 0.8s linear infinite;',\n ' margin: 0 auto;',\n ' }',\n ' @keyframes spin { to { transform: rotate(360deg); } }',\n ' </style>',\n '</head>',\n '<body>',\n ' <div class=\"container\">',\n ' <div class=\"logo\">\\u{1FAB5} timber.js</div>',\n ' <p class=\"message\">Dev server starting&hellip;</p>',\n ' <div class=\"spinner\"></div>',\n ' </div>',\n '</body>',\n '</html>',\n].join('\\n');\n\n// ─── Factory ──────────────────────────────────────────────────────────────\n\n/**\n * Create a holding HTTP server that serves a loading page during startup.\n *\n * The config hook attempts one bind on the requested port. If it fails,\n * startup continues without the holding page; Vite owns port selection.\n * The last configureServer hook awaits close() before Vite probes/binds.\n */\nexport function createHoldingServer(): HoldingServer {\n const server = http.createServer((req, res) => {\n const accept = req.headers.accept ?? '';\n\n // API requests: JSON 503\n if (accept.includes('application/json') && !accept.includes('text/html')) {\n res.writeHead(503, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Retry-After': '1',\n 'Cache-Control': 'no-store',\n });\n res.end(\n JSON.stringify({\n error: 'Service Unavailable',\n message: 'timber dev server is starting — please retry shortly',\n })\n );\n return;\n }\n\n // Browser and other requests: HTML holding page\n res.writeHead(503, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Retry-After': '1',\n 'Cache-Control': 'no-store',\n });\n res.end(HOLDING_PAGE_HTML);\n });\n\n return {\n listen(port: number, host?: string): Promise<number> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => {\n server.removeListener('error', reject);\n const addr = server.address();\n const boundPort = typeof addr === 'object' && addr ? addr.port : port;\n resolve(boundPort);\n });\n });\n },\n\n close(): Promise<void> {\n // Kill lingering keep-alive sockets immediately — the holding\n // page's meta-refresh keeps browser connections alive, and\n // server.close() waits for all sockets to drain before the\n // 'close' event fires. Without this, the close can stall for\n // the full keepAliveTimeout (~5s), blocking the port handoff.\n server.closeAllConnections();\n return new Promise((resolve, reject) => {\n server.close((err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n },\n };\n}\n","/** Port input precedence for dev and preview. Vite owns binding and restart reuse. */\n\n/** Default port used by `timber dev` and `timber preview`. */\nexport const DEFAULT_PORT = 3000;\n\n// ── Pure resolution ────────────────────────────────────────────────────\n\nexport interface ResolvePortInput {\n /**\n * Port read from `vite.config.ts` `server.port` or the `--port` CLI\n * flag (Vite merges `--port` into `userConfig.server.port` before\n * plugins see it).\n */\n configPort?: number | undefined;\n /** Raw value of `process.env.PORT`. */\n envPort?: string | undefined;\n /** Default port to use when neither `configPort` nor `envPort` is set. */\n defaultPort?: number;\n}\n\nexport interface ResolvedPortInput {\n /** Port to start binding from. */\n port: number;\n /**\n * `true` if the port came from an explicit user override (config or\n * env). Preview uses this to default to strict port binding.\n */\n explicit: boolean;\n}\n\n/**\n * Pure: compute the starting port from config / env / defaults.\n *\n * Performs no I/O.\n */\nexport function resolveStartPort(input: ResolvePortInput): ResolvedPortInput {\n const defaultPort = input.defaultPort ?? DEFAULT_PORT;\n\n // `configPort` wins over `envPort`. This matches Vite's behavior:\n // `vite --port 4000` overrides `PORT=5000` in the environment.\n if (typeof input.configPort === 'number' && Number.isFinite(input.configPort)) {\n return { port: input.configPort, explicit: true };\n }\n\n if (input.envPort != null && input.envPort !== '') {\n const parsed = Number(input.envPort);\n if (Number.isFinite(parsed) && parsed > 0) {\n return { port: parsed, explicit: true };\n }\n }\n\n return { port: defaultPort, explicit: false };\n}\n","/**\n * @timber-js/app — Root entry point (public API).\n *\n * User-facing exports: timber(), defineConfig(), TimberUserConfig, Routes.\n *\n * Internal helpers (PluginContext, resolveAppDir, loadTimberConfigFile,\n * warnConfigConflicts, resolveClientJavascript) live in plugin-context.ts\n * and are NOT re-exported here. Sub-plugins import them via relative paths.\n *\n * Design doc: 18-build-system.md §\"Plugin Architecture\"\n */\n\nimport type { Plugin, PluginOption } from 'vite';\nimport type { ReactCompilerOptions } from '@vitejs/plugin-react';\nimport { createLogger } from 'vite';\nimport { join, relative, resolve } from 'node:path';\nimport { createRequire } from 'node:module';\nimport react from '@vitejs/plugin-react';\nimport { timberContent } from './plugins/content.ts';\nimport { timberDevServer } from './plugins/dev-server.ts';\nimport { timberEntries, BROWSER_ENTRY_FILE } from './plugins/entries.ts';\nimport { timberMdx } from './plugins/mdx.ts';\nimport { timberRouting } from './plugins/routing.ts';\nimport { timberShims } from './plugins/shims.ts';\nimport { timberFonts } from './plugins/fonts.ts';\nimport { timberStaticBuild } from './plugins/static-build.ts';\nimport { timberBuildManifest } from './plugins/build-manifest.ts';\nimport { timberDevLogs, originalConsole, wrapLoggerWithOriginalConsole } from './dev-tools/logs.ts';\nimport { resolveForwardConsole } from './dev-tools/browser-logs.ts';\nimport { timberReactProd } from './plugins/react-prod.ts';\nimport { timberReactResolve } from './plugins/react-resolve.ts';\nimport { timberChunks } from './plugins/chunks.ts';\nimport { clientChunkGroup } from './plugins/client-chunks.ts';\nimport { timberServerBundle } from './plugins/server-bundle.ts';\nimport { timberCacheTransform } from './plugins/cache.ts';\nimport { timberRequestDep } from './plugins/request-dep/index.ts';\nimport { timberPrebuilt } from './plugins/prebuilt.ts';\nimport { timberPrerenderSugar } from './plugins/prerender-sugar.ts';\nimport { timberCloudflareWasm } from './plugins/cloudflare-wasm.ts';\nimport { timberPostBuild } from './plugins/post-build.ts';\nimport { timberBuildReport } from './plugins/build-report.ts';\nimport { createNoopTimer } from './utils/startup-timer.ts';\nimport {\n validateConfig,\n reportConfigErrors,\n checkPeerDependencies,\n formatMissingPeers,\n} from './config-validation.ts';\nimport {\n resolveEncryptionKeyExpression,\n shouldEnableEncryption,\n} from './server/action-encryption.ts';\nimport { createHoldingServer } from './dev-tools/holding-server.ts';\nimport { resolveStartPort } from './server/port-resolution.ts';\nimport type { TimberUserConfig } from './config-types.ts';\nimport type { PluginContext, TimberPluginApi } from './plugin-context.ts';\nimport {\n createPluginContext,\n loadTimberConfigFile,\n mergeFileConfig,\n resolveAppDir,\n resolveClientJavascript,\n resolveBuildDir,\n} from './plugin-context.ts';\n\n// ── Public API ────────────────────────────────────────────────────────────\n\nexport type { TimberUserConfig } from './config-types.ts';\n\n// Metadata route handler types — re-exported so user-authored metadata\n// route files (sitemap.ts, robots.ts, manifest.ts, icon.tsx, etc.) can\n// import them from the package root without reaching into ./server.\n// The canonical location for these types is '@timber-js/app/server'; this\n// root re-export is a convenience for typed metadata route handlers.\n// See design/16-metadata.md §\"Metadata Routes\".\nexport type { Metadata, MetadataRoute, MetadataHandler, MetadataResult } from './server/types.ts';\n\n/**\n * Route map interface — augmented by the generated timber-routes.d.ts.\n *\n * Each key is a route path pattern. Values have:\n * segmentParams: shape of URL segment params (e.g. { id: string })\n *\n * There is no `searchParams` member: since TIM-1343 the framework does not\n * scan for search-param definitions, so it has nothing to type them with. A\n * definition carries its own type to call sites through an ordinary import.\n *\n * This interface is empty by default and populated via codegen.\n * See design/09-typescript.md §\"Typed Routes\".\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type, typescript/no-empty-interface\nexport interface Routes {}\n\n/**\n * Type-safe helper for timber.config.ts files.\n *\n * A pass-through identity function that provides autocomplete and\n * type checking for timber configuration. No runtime validation —\n * purely a DX convenience (same pattern as Vite's defineConfig).\n *\n * @example\n * ```ts\n * // timber.config.ts\n * import { defineConfig } from '@timber-js/app';\n *\n * export default defineConfig({\n * output: 'server',\n * pageExtensions: ['tsx', 'ts', 'mdx'],\n * });\n * ```\n */\nexport function defineConfig(config: TimberUserConfig): TimberUserConfig {\n return config;\n}\n\n// ── Private helpers ───────────────────────────────────────────────────────\n\n/**\n * Build the options object for @vitejs/plugin-rsc.\n *\n * Uses a getter for `enableActionEncryption` so the RSC plugin reads\n * the value lazily — after ctx.dev is set in configResolved. This lets\n * `actionEncryption.disableInDev` work correctly even though the RSC\n * plugin is created before Vite resolves the command.\n */\nfunction createRscOptions(\n ctx: PluginContext,\n encryptionKeyExpr: string | undefined\n): Record<string, unknown> {\n const options: Record<string, unknown> = {\n serverHandler: false,\n customClientEntry: true,\n entries: {\n rsc: 'virtual:timber-rsc-entry',\n ssr: 'virtual:timber-ssr-entry',\n client: 'virtual:timber-browser-entry',\n },\n // Group client references by layout boundary to balance route-scoped code\n // splitting with HTTP request count. A constant group name ('client-refs')\n // would collapse all routes into one chunk — any page downloads every\n // client component. Per-serverChunk grouping creates many sub-500B files.\n // Layout-boundary grouping is the middle ground: components under the same\n // layout segment share a chunk. See design/27-chunking-strategy.md, TIM-440, TIM-499.\n clientChunks: (meta: { id: string; normalizedId: string; serverChunk: string }) =>\n clientChunkGroup(meta, ctx.appDir, ctx.root, ctx.sharedModuleFacades),\n };\n\n // Bound args encryption — AES-256-GCM authenticated encryption for\n // closure variables in 'use server' functions. Always on in production,\n // configurable in dev. See design/08-forms-and-actions.md §\"Bound Args Encryption\".\n //\n // Uses a getter so the RSC plugin reads the value lazily in its transform\n // hooks, after ctx.dev is set in configResolved. This lets disableInDev\n // work correctly — ctx.dev is false at construction time but true during\n // dev server transforms.\n Object.defineProperty(options, 'enableActionEncryption', {\n get() {\n return shouldEnableEncryption(ctx.dev, ctx.config.actionEncryption);\n },\n enumerable: true,\n });\n\n // When TIMBER_ACTIONS_ENCRYPTION_KEY is set, pass it as a runtime expression\n // so the RSC plugin uses it instead of auto-generating a per-build key.\n if (encryptionKeyExpr) {\n options.defineEncryptionKey = encryptionKeyExpr;\n }\n\n return options;\n}\n\n// NOTE: 'use cache' directive transform removed — future feature pending design doc.\n// The timber.cache() API (createCache) remains available for explicit caching.\n// See design/06-caching.md.\n\n// ── Main plugin factory ──────────────────────────────────────────────────\n\n/**\n * Create the timber Vite plugin array.\n *\n * Loads timber.config.ts and all dependencies synchronously before\n * constructing the plugin array. This ensures ALL plugins — including\n * the RSC plugin and React Compiler — see the fully merged config\n * (inline + file-based). No async, no deferred config, no stale reads.\n *\n * Requires Node >= 22.12 for synchronous require() of ESM modules\n * (@vitejs/plugin-rsc is ESM-only).\n *\n * Previous versions used async loading and deferred config merging,\n * causing file-based config for reactCompiler, actionEncryption, and\n * output mode to be silently ignored. See TIM-451.\n */\n/**\n * Wrap plugin-react's `vite:react-compiler` configResolved so it always\n * sees `isProduction: true` during builds. The compiler plugin uses\n * `!config.isProduction` to decide whether to emit jsxDEV calls, but\n * Vite derives isProduction from process.env.NODE_ENV — which may be\n * \"development\" in the shell. Rather than mutating the env, we pass a\n * prototype-based view with the single property overridden.\n */\nfunction patchReactCompilerForProdJsx(plugins: PluginOption[]): PluginOption[] {\n for (const p of plugins) {\n if (p && typeof p === 'object' && 'name' in p && p.name === 'vite:react-compiler') {\n const orig = (p as Plugin).configResolved;\n if (typeof orig === 'function') {\n (p as Plugin).configResolved = function (config) {\n const view =\n config.command === 'build' && !config.isProduction\n ? Object.create(config, { isProduction: { value: true } })\n : config;\n return orig.call(this, view);\n };\n }\n }\n }\n return plugins;\n}\n\nexport function timber(config?: TimberUserConfig): PluginOption[] {\n const ctx = createPluginContext(config);\n\n // Resolve dependencies from the consumer's project (process.cwd()),\n // not from timber's own node_modules. This is critical for pnpm link:\n // when linked, timber's node_modules has a separate vite instance, and\n // the RSC plugin must use the same vite instance as the dev server.\n const consumerRequire = createRequire(join(process.cwd(), 'package.json'));\n\n // ── Step 1: Load @vitejs/plugin-rsc ─────────────────────────────────\n // Synchronous require() works for ESM modules on Node 22.12+.\n ctx.timer.start('rsc-plugin-import');\n const rscMod = consumerRequire('@vitejs/plugin-rsc');\n const vitePluginRsc = rscMod.default ?? rscMod;\n ctx.timer.end('rsc-plugin-import');\n\n // ── Step 2: Compute config-dependent options ────────────────────────\n // encryptionKeyExpr is env-based and doesn't depend on file config.\n const encryptionKeyExpr = resolveEncryptionKeyExpression();\n\n // ── Step 3: Pre-load file config for plugin resolution ──────────────\n // Load timber.config.ts eagerly from process.cwd() so we can resolve\n // plugins (like React Compiler) and add them to the top-level array.\n // Vite's config() hook return type is Omit<UserConfig, 'plugins'> —\n // plugins returned from config() are silently ignored. See TIM-632.\n //\n // The config() hook still loads from the correct Vite root (which may\n // differ from cwd in monorepo setups — see TIM-498), but only for\n // non-plugin config merging.\n const earlyFileConfig = loadTimberConfigFile(process.cwd());\n\n // ── Step 4: Build rootSync plugin ───────────────────────────────────\n\n // rootSync loads timber.config.ts from Vite's resolved root and merges\n // it into ctx.config. Plugin resolution is handled eagerly above — the\n // config() hook must NOT return a `plugins` field (Vite ignores it).\n const rootSync: Plugin = {\n name: 'timber-root-sync',\n\n // The plugin context, published for out-of-band callers that need the\n // *resolved* configuration rather than a second reading of the files it\n // came from. `timber check` is the one today: it runs Vite's\n // `resolveConfig()` and reads root, appDir, and pageExtensions from here,\n // so it scans exactly the tree `timber build` builds — including config\n // passed inline as `timber({ ... })`, which lives only in this closure and\n // is invisible to anything that re-reads `timber.config.ts`. See\n // `cli-check.ts` and design/11-platform.md §`timber check`.\n //\n // Valid from `configResolved` onward; `appDir` and `root` are unset before\n // that, which is why the reader runs a full `resolveConfig()` rather than\n // just loading the config file.\n api: { getContext: () => ctx } satisfies TimberPluginApi,\n\n async config(userConfig, { command, isPreview }) {\n // ── Load timber.config.ts from the correct root ───────────────\n // Vite's `config` hook fires before `configResolved`. The user's\n // `root` option (if set) tells us where the project lives.\n // `resolve()` mirrors Vite's own root resolution logic.\n const viteRoot = resolve(userConfig.root ?? process.cwd());\n ctx.timer.start('config-load');\n const fileConfig = loadTimberConfigFile(viteRoot);\n if (fileConfig) {\n ctx.config = mergeFileConfig(ctx.config, fileConfig);\n ctx.clientJavascript = resolveClientJavascript(ctx.config);\n }\n // Apply defaults AFTER merge so file-based config isn't overridden\n // by defaults that were baked into the inline config object.\n ctx.config.output ??= 'server';\n ctx.timer.end('config-load');\n\n // ── Resolve build output directory ─────────────────────────\n // Priority: timber.config.ts `buildDir` > Vite `build.outDir` > .timber/dist\n // Set Vite's build.outDir so the RSC plugin and all environment\n // builds write to the correct location. ctx.buildDir is read back\n // from Vite in configResolved, so there is one answer to where the\n // build went.\n const resolvedRoot = resolve(userConfig.root ?? process.cwd());\n const buildDir = resolveBuildDir(resolvedRoot, ctx.config.buildDir, userConfig.build?.outDir);\n\n // Warn if the Vite root differs from cwd and the re-loaded config\n // has reactCompiler but the early cwd-based load missed it. In this\n // edge case the user must move reactCompiler to inline config.\n if (viteRoot !== process.cwd()) {\n const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;\n const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;\n if (hasCompilerInReloaded && !hadCompilerInEarly) {\n console.warn(\n '[timber] reactCompiler is set in timber.config.ts but could not be ' +\n 'registered because the config file is in a non-cwd root directory. ' +\n 'Move reactCompiler to the inline timber() config in vite.config.ts, or ' +\n 'run vite from the project root directory.'\n );\n }\n }\n\n // Force production JSX for builds.\n //\n // Vite derives `config.isProduction` from `process.env.NODE_ENV`.\n // If the shell has NODE_ENV=development, isProduction stays false\n // and Vite's built-in OXC transform emits jsxDEV calls (the\n // production jsx-runtime doesn't export jsxDEV). The oxc.jsx\n // override below fixes Vite's native path; plugin-react's compiler\n // plugin is handled by patchReactCompilerForProdJsx above.\n // ── Resolve dev/preview port (TIM-842) ───────────────────────\n // Default port is 3000. Vite handles conflicts and honors server.strictPort.\n //\n // For dev (`command === 'serve' && !isPreview`) we start the\n // holding server on the requested port when available.\n //\n // For `vite preview` (`command === 'serve' && isPreview`) we\n // resolve the config/env port but delegate the actual bind +\n // auto-bump to Vite's own preview server. Starting the holding\n // server in preview mode would self-conflict because the dev\n // plugin's `configureServer` handoff does not run for preview;\n // the holding server would keep the port occupied while Vite's\n // preview tried to bind the same port.\n //\n // See design/21-dev-server.md §\"Default Port and Auto-Bump\".\n let resolvedDevPort: number | null = null;\n let resolvedDevPortExplicit = false;\n // Middleware-mode embeddings (the analyze crawl, custom servers)\n // never bind a port, and the dev-server plugin's listen() handoff\n // that closes the holding server never runs — starting it would\n // occupy the default port for the embedding's lifetime.\n const isMiddlewareMode = Boolean(userConfig.server?.middlewareMode);\n // Resolve the host Vite will bind so the holding server probes the\n // same address. Vite defaults to 'localhost' when server.host is\n // unset; binding wildcard (no host) would mask conflicts on\n // localhost due to SO_REUSEADDR address-family differences. TIM-1419.\n const resolvedHost =\n typeof userConfig.server?.host === 'string'\n ? userConfig.server.host\n : userConfig.server?.host === true\n ? undefined\n : 'localhost';\n if (command === 'serve' && !isPreview && !isMiddlewareMode) {\n const start = resolveStartPort({\n configPort: userConfig.server?.port,\n envPort: process.env.PORT,\n });\n // Vite owns port selection and remembers its bound port on restart.\n // Never forward a probed/bumped port: replacement config runs while\n // the old listener still owns the port. The holding page is optional.\n resolvedDevPort = start.port;\n resolvedDevPortExplicit = userConfig.server?.strictPort ?? false;\n if (start.port !== 0) {\n ctx.holdingServer = createHoldingServer();\n await ctx.holdingServer.listen(start.port, resolvedHost).catch(() => {\n ctx.holdingServer = null;\n });\n }\n } else if (command === 'serve' && isPreview) {\n // Preview mode: resolve the starting port from config/env/\n // default but do NOT probe. Vite's preview server handles the\n // bind itself, with `preview.strictPort` controlling whether\n // an in-use port auto-bumps (implicit) or errors (explicit).\n const previewConfigPort =\n typeof userConfig.preview?.port === 'number'\n ? userConfig.preview.port\n : typeof userConfig.server?.port === 'number'\n ? userConfig.server.port\n : undefined;\n const start = resolveStartPort({\n configPort: previewConfigPort,\n envPort: process.env.PORT,\n });\n resolvedDevPort = start.port;\n resolvedDevPortExplicit = start.explicit;\n }\n\n // Derive relative buildOutDir from the absolute buildDir (set above)\n // so Vite's config receives a root-relative path.\n const buildOutDir = relative(resolvedRoot, buildDir);\n\n // Set per-environment build.outDir so Vite's RSC plugin writes\n // each environment to the correct subdirectory under our buildDir.\n // Without this, the RSC plugin defaults to dist/<envName> instead\n // of <buildOutDir>/<envName>.\n const envOutDirs: Record<string, { build: { outDir: string } }> = {};\n for (const envName of ['rsc', 'ssr', 'client']) {\n envOutDirs[envName] = { build: { outDir: join(buildOutDir, envName) } };\n }\n\n // Exclude @timber-js/app packages from the dep optimizer.\n // The shims plugin intercepts @timber-js/app/* imports per-environment\n // (e.g. replacing @timber-js/app/server with a stub in the client env).\n // The dep optimizer runs before per-environment resolution, so it would\n // pre-bundle @timber-js/app/cookies with the real server code inlined,\n // pulling AsyncLocalStorage into the browser bundle.\n const timberOptimizeDepsExclude = [\n '@timber-js/app',\n '@timber-js/app/server',\n '@timber-js/app/client',\n '@timber-js/app/cookies',\n '@timber-js/app/cache',\n '@timber-js/app/search-params',\n '@timber-js/app/params',\n '@timber-js/app/codec',\n ];\n\n if (command === 'build') {\n return {\n build: { outDir: buildOutDir },\n environments: envOutDirs,\n optimizeDeps: { exclude: timberOptimizeDepsExclude },\n oxc: {\n jsx: {\n development: false,\n },\n },\n };\n }\n\n // Dev/preview mode: set outDir so dev-time references are\n // consistent, and surface the resolved port to Vite.\n //\n // Dev auto-bumps unless the user sets server.strictPort.\n // Always forward the requested port so Vite can recognize unchanged\n // config and reuse its actual bound port across restarts (TIM-1456).\n //\n // For `vite preview`, we set `preview.strictPort` based on\n // whether the user explicitly set the port. Implicit (default)\n // preview uses strictPort: false so Vite's preview server can\n // auto-bump from 3000. Explicit preview uses strictPort: true\n // so conflicts fail loudly, matching the dev behavior and the\n // TIM-842 spec.\n const serverConfig: {\n port?: number;\n strictPort?: boolean;\n forwardConsole?: boolean | { unhandledErrors?: boolean; logLevels?: string[] };\n } = {};\n const previewConfig: { port?: number; strictPort?: boolean } = {};\n if (resolvedDevPort != null) {\n if (!isPreview) {\n serverConfig.port = resolvedDevPort;\n serverConfig.strictPort = resolvedDevPortExplicit;\n }\n previewConfig.port = resolvedDevPort;\n previewConfig.strictPort = resolvedDevPortExplicit;\n }\n\n // Enable Vite 8's built-in browser→terminal console forwarding.\n // Vite defaults this OFF for non-agent dev; timber enables it based\n // on the devBrowserLogs config (default: 'warn'). See TIM-1152.\n serverConfig.forwardConsole = resolveForwardConsole(ctx.config.devBrowserLogs);\n\n // Provide a customLogger whose output routes through the pre-patched\n // console methods so Vite's forwardConsole output never re-enters our\n // server→browser patch. If the user supplied their own customLogger,\n // wrap it so its console calls also bypass patching.\n const customLogger = userConfig.customLogger\n ? wrapLoggerWithOriginalConsole(userConfig.customLogger)\n : createLogger(userConfig.logLevel ?? 'info', {\n allowClearScreen: userConfig.clearScreen ?? true,\n console: originalConsole as Console,\n });\n\n // Seed the client optimizer's startup crawl with every 'use client'\n // file so client-only packages are pre-bundled before the first\n // request, not discovered mid-load (which full-reloads the page).\n // Vite concatenates these with any entries the user sets.\n // See design/21-dev-server.md §\"Client Dependency Pre-Bundling\".\n let environments: Record<string, object> = envOutDirs;\n if (!isPreview) {\n ctx.timer.start('client-deps-scan');\n // Loaded lazily: directive detection pulls in @vitejs/plugin-rsc's\n // transforms, which builds and preview never need.\n const { clientOptimizeDepsEntries } = await import('./plugins/client-dep-entries.ts');\n const entries = await clientOptimizeDepsEntries(resolvedRoot, BROWSER_ENTRY_FILE, buildDir);\n ctx.timer.end('client-deps-scan');\n environments = {\n ...envOutDirs,\n client: { ...envOutDirs.client, optimizeDeps: { entries } },\n };\n }\n\n return {\n build: { outDir: buildOutDir },\n environments,\n optimizeDeps: { exclude: timberOptimizeDepsExclude },\n customLogger,\n server: serverConfig,\n preview: previewConfig,\n };\n },\n configResolved(resolved) {\n ctx.root = resolved.root;\n ctx.appDir = resolveAppDir(resolved.root, ctx.config.appDir);\n ctx.dev = resolved.command === 'serve';\n // Vite's resolved base — the deployment path prefix. Captured once\n // here so every sub-plugin that emits a URL (assets, fonts, RSC\n // payloads) reads the same value. See TIM-1261.\n ctx.base = resolved.base;\n\n // timber.config.* files are NOT registered as configFileDependencies.\n // Vite's in-process restart cannot bust Node's require cache for ESM\n // modules loaded via require(), so the restarted server would serve\n // stale config. Instead, timber-dev-server watches these files and\n // calls process.exit(RESTART_EXIT_CODE) so the CLI supervisor\n // respawns a fresh process. See TIM-1444.\n // The watcher.add() call in dev-server.ts ensures the files are\n // watched even if created after server start.\n\n // The build directory is what Vite resolved build.outDir to — the\n // config hook's value after every other plugin and the user config had\n // their say. Vite keeps outDir as-is (may be relative), so resolve\n // against root.\n ctx.buildDir = resolve(resolved.root, resolved.build.outDir);\n // In production builds, swap to a no-op timer to avoid overhead\n if (!ctx.dev) {\n ctx.timer = createNoopTimer();\n } else {\n // Start the overall dev server setup timer — ends in timber-dev-server\n ctx.timer.start('dev-server-setup');\n }\n\n // Validate config and check peer dependencies at startup. Most errors\n // are logged and don't block startup; fatal ones (a security setting\n // that would not mean what it says) stop it. See reportConfigErrors.\n reportConfigErrors(validateConfig(ctx.config));\n\n const peerResults = checkPeerDependencies(ctx.root);\n const peerWarning = formatMissingPeers(peerResults);\n if (peerWarning) {\n process.stderr.write(`${peerWarning}\\n\\n`);\n }\n },\n };\n\n // ── Step 5: Resolve React Compiler config ───────────────────────────\n // Inline config takes precedence. File config (from the early cwd-based\n // load) is used when inline config doesn't set reactCompiler.\n // Default: true — oxc-transform-react is a direct dependency.\n const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler ?? true;\n\n // ── Step 6: Assemble plugin array ─────────────────────────────────────\n // @vitejs/plugin-rsc handles:\n // - RSC/SSR/client environment setup\n // - \"use client\" directive → client reference proxy transformation\n // - \"use server\" directive → server reference transformation\n // - Client reference tracking and module map generation\n //\n // serverHandler: false — timber has its own dev server (timber-dev-server)\n // entries — tells the RSC plugin about timber's virtual entry modules so\n // it correctly wires up the browser entry (needed for React Fast Refresh\n // preamble coordination with @vitejs/plugin-react)\n // customClientEntry: true — timber manages its own browser entry and\n // preloading; skips RSC plugin's default \"index\" client entry convention\n //\n // The RSC plugin's built-in buildApp handles the 5-step multi-environment\n // build sequence (analyze references → build RSC → build client → build SSR).\n // We do NOT set customBuildApp — the RSC plugin's orchestration is correct\n // and handles bundle ordering, asset manifest generation, and environment\n // imports manifest. See @vitejs/plugin-rsc's buildApp implementation.\n //\n // Everything after it runs in timber-post-build, in the order that plugin\n // states. The plugins that own a post-build step expose it as their `api`\n // and are handed to it here, so no step's order depends on where a plugin\n // sits in this array. See design/18-build-system.md §\"Post-Build Phase\".\n const fonts = timberFonts(ctx);\n const prebuilt = timberPrebuilt(ctx);\n const buildReport = timberBuildReport(ctx);\n return [\n rootSync,\n timberReactResolve(),\n timberReactProd(),\n // @vitejs/plugin-react provides React Fast Refresh (state-preserving HMR)\n // for client components via Babel transform. Placed before @vitejs/plugin-rsc\n // following Vinext's convention — the RSC plugin's virtual browser entry\n // coordinates with plugin-react via __vite_plugin_react_preamble_installed__.\n ...patchReactCompilerForProdJsx(\n react({\n compiler: (effectiveReactCompiler || false) as boolean | ReactCompilerOptions,\n })\n ),\n vitePluginRsc(createRscOptions(ctx, encryptionKeyExpr)),\n timberShims(ctx),\n timberRouting(ctx),\n timberEntries(ctx),\n timberBuildManifest(ctx),\n fonts,\n timberMdx(ctx),\n timberRequestDep(ctx),\n timberCacheTransform(ctx),\n timberPrerenderSugar(ctx), // export const prerender → cache.component() desugaring\n prebuilt, // cache.component() → __prebuilt() callsite rewrite\n timberStaticBuild(ctx), // Static mode: validate dynamic API usage\n timberContent(ctx),\n timberServerBundle(), // Bundle all deps in server environments for prod\n timberCloudflareWasm(ctx), // Externalize WASM for Cloudflare Workers\n timberChunks(ctx),\n buildReport, // Route table with bundle sizes, printed by timber-post-build\n timberPostBuild(ctx, { fonts: fonts.api, prebuilt: prebuilt.api, report: buildReport.api }),\n timberDevLogs(ctx), // Dev-only: forward server console.* to browser console\n timberDevServer(ctx), // Must be last — configureServer post-hook runs after all watchers\n ];\n}\n\nexport default timber;\n"],"x_google_ignoreList":[15,16],"mappings":"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"}