theokit 0.66.1 → 0.68.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/dist/{actions-virtual-module-RMEAW2NX.js → actions-virtual-module-3OPYLD76.js} +4 -4
  2. package/dist/{actions-virtual-module-LVWXLDCT.js → actions-virtual-module-SE44BKR4.js} +6 -6
  3. package/dist/adapters/security-headers.d.ts +2 -2
  4. package/dist/adapters/security-headers.js +1 -1
  5. package/dist/{agent-OCQA4WXF.js → agent-UBDDP2L5.js} +2 -2
  6. package/dist/{app-typed-client-J7NWKMS7.js → app-typed-client-BE3PV3JY.js} +4 -4
  7. package/dist/{app-typed-client-Z4MF5HCB.js → app-typed-client-RAFEBA7S.js} +6 -6
  8. package/dist/assets-map-BMQASQHW.js +70 -0
  9. package/dist/assets-map-BMQASQHW.js.map +1 -0
  10. package/dist/assets-map-CV2YZ3MY.js +69 -0
  11. package/dist/assets-map-CV2YZ3MY.js.map +1 -0
  12. package/dist/{aws-lambda-AN6CEBXO.js → aws-lambda-R76PWR27.js} +3 -3
  13. package/dist/boot/index.d.ts +4 -5
  14. package/dist/boot/index.js +1 -1
  15. package/dist/boot/index.js.map +1 -1
  16. package/dist/{build-JQSCQ3SQ.js → build-U4HVYY6F.js} +6 -6
  17. package/dist/{bun-3FFL7CS4.js → bun-NPBIAWSU.js} +3 -3
  18. package/dist/chunk-46FM5AFZ.js +44 -0
  19. package/dist/chunk-46FM5AFZ.js.map +1 -0
  20. package/dist/{chunk-PALZUV6E.js → chunk-6B3CMPE4.js} +2 -2
  21. package/dist/{chunk-D4VP2QPR.js → chunk-7L7LQ2GU.js} +1 -1
  22. package/dist/{chunk-D4VP2QPR.js.map → chunk-7L7LQ2GU.js.map} +1 -1
  23. package/dist/{chunk-MOTGIGWC.js → chunk-7THO4PRL.js} +23 -11
  24. package/dist/{chunk-MOTGIGWC.js.map → chunk-7THO4PRL.js.map} +1 -1
  25. package/dist/{chunk-3IIKKBOJ.js → chunk-AL5JHX7X.js} +24 -1
  26. package/dist/chunk-AL5JHX7X.js.map +1 -0
  27. package/dist/{chunk-EQCSUC65.js → chunk-AROOYXI5.js} +2 -2
  28. package/dist/{chunk-OPHA3577.js → chunk-CO7Q75IS.js} +28 -13
  29. package/dist/chunk-CO7Q75IS.js.map +1 -0
  30. package/dist/{chunk-5GZROLDV.js → chunk-ENSFCKP6.js} +5 -1
  31. package/dist/{chunk-5GZROLDV.js.map → chunk-ENSFCKP6.js.map} +1 -1
  32. package/dist/{chunk-N6XDYNWK.js → chunk-FYYKMPST.js} +2 -2
  33. package/dist/{chunk-O3EBLVMP.js → chunk-G2NWAVGG.js} +3 -3
  34. package/dist/chunk-G2NWAVGG.js.map +1 -0
  35. package/dist/{chunk-WAYUHS54.js → chunk-GDF2XQOO.js} +2 -2
  36. package/dist/{chunk-2ERTA4FM.js → chunk-LADTWXOB.js} +44 -17
  37. package/dist/chunk-LADTWXOB.js.map +1 -0
  38. package/dist/{chunk-5VLP3GQ2.js → chunk-MS4A7N77.js} +1 -1
  39. package/dist/chunk-MS4A7N77.js.map +1 -0
  40. package/dist/{chunk-5AGNZXHJ.js → chunk-Q7T3UQ4L.js} +89 -30
  41. package/dist/chunk-Q7T3UQ4L.js.map +1 -0
  42. package/dist/{chunk-5LRBIP4B.js → chunk-QGNSZ2ZK.js} +27 -2
  43. package/dist/chunk-QGNSZ2ZK.js.map +1 -0
  44. package/dist/{chunk-GAPBPRPP.js → chunk-TRCJHFAX.js} +1 -1
  45. package/dist/{chunk-GAPBPRPP.js.map → chunk-TRCJHFAX.js.map} +1 -1
  46. package/dist/{chunk-VV2VU3LJ.js → chunk-WSMLSIS5.js} +5 -1
  47. package/dist/chunk-WSMLSIS5.js.map +1 -0
  48. package/dist/{chunk-EYRWD2AB.js → chunk-WSOAN4KN.js} +2 -2
  49. package/dist/cli/index.js +6 -6
  50. package/dist/{cloudflare-VIQX4FVC.js → cloudflare-5HU56XIH.js} +38 -11
  51. package/dist/cloudflare-5HU56XIH.js.map +1 -0
  52. package/dist/{route-config-B7FaTSby.d.ts → define-middleware-D2n71Svm.d.ts} +39 -1
  53. package/dist/{deno-deploy-PTO7IE4G.js → deno-deploy-BXOQ45LD.js} +3 -3
  54. package/dist/{dev-DPOAVHUS.js → dev-E3USPAWQ.js} +7 -7
  55. package/dist/{health-route-C0hk64_U.d.ts → health-route-CYI7z5g3.d.ts} +2 -3
  56. package/dist/{index-BXGSBlxf.d.ts → index-B9iVBHJI.d.ts} +49 -7
  57. package/dist/index.js +6 -6
  58. package/dist/{internal-api-VHFQCXR2.js → internal-api-OOTVIOH2.js} +4 -4
  59. package/dist/{internal-api-C5NIIJJY.js → internal-api-VAKXXW6F.js} +6 -6
  60. package/dist/{mcp-LOMU5PGA.js → mcp-7UOQM4FW.js} +2 -2
  61. package/dist/{netlify-3VSNVURQ.js → netlify-LPJAPMQ2.js} +3 -3
  62. package/dist/{observability-bootstrap-H4NSILXD.js → observability-bootstrap-YQKMEYW7.js} +2 -2
  63. package/dist/{preview-24MJYNYN.js → preview-GPMF43QX.js} +3 -3
  64. package/dist/registry-UOWTDUFL.js +23 -0
  65. package/dist/{security-headers-C2cByfJn.d.ts → security-headers-vris2MQq.d.ts} +14 -0
  66. package/dist/server/auth/index.d.ts +17 -1
  67. package/dist/server/auth/index.js +3 -1
  68. package/dist/server/define/index.d.ts +3 -29
  69. package/dist/server/define/index.js +3 -3
  70. package/dist/server/http/index.d.ts +2 -2
  71. package/dist/server/http/index.js +5 -3
  72. package/dist/server/index.d.ts +7 -6
  73. package/dist/server/index.js +12 -8
  74. package/dist/server/index.js.map +1 -1
  75. package/dist/server/security/index.d.ts +2 -2
  76. package/dist/server/security/index.js +2 -2
  77. package/dist/{server-boundary-DJ4PYJR5.js → server-boundary-A3HW27C7.js} +4 -4
  78. package/dist/{server-boundary-FVMJ5WAU.js → server-boundary-V6PCM22J.js} +6 -6
  79. package/dist/{start-TXRUHKFJ.js → start-6WEPXA3X.js} +39 -15
  80. package/dist/start-6WEPXA3X.js.map +1 -0
  81. package/dist/{static-SVDWIOXJ.js → static-7OJNB7D2.js} +4 -4
  82. package/dist/{vercel-BZ35DF3B.js → vercel-YUZADKGV.js} +3 -3
  83. package/dist/vite-plugin/index.js +6 -6
  84. package/dist/{vite-plugin-AVFHID5Z.js → vite-plugin-WBF5NXGW.js} +7 -7
  85. package/package.json +2 -2
  86. package/dist/chunk-2ERTA4FM.js.map +0 -1
  87. package/dist/chunk-3IIKKBOJ.js.map +0 -1
  88. package/dist/chunk-5AGNZXHJ.js.map +0 -1
  89. package/dist/chunk-5LRBIP4B.js.map +0 -1
  90. package/dist/chunk-5VLP3GQ2.js.map +0 -1
  91. package/dist/chunk-O3EBLVMP.js.map +0 -1
  92. package/dist/chunk-OPHA3577.js.map +0 -1
  93. package/dist/chunk-VV2VU3LJ.js.map +0 -1
  94. package/dist/cloudflare-VIQX4FVC.js.map +0 -1
  95. package/dist/registry-RZHBBLIF.js +0 -23
  96. package/dist/start-TXRUHKFJ.js.map +0 -1
  97. /package/dist/{actions-virtual-module-RMEAW2NX.js.map → actions-virtual-module-3OPYLD76.js.map} +0 -0
  98. /package/dist/{actions-virtual-module-LVWXLDCT.js.map → actions-virtual-module-SE44BKR4.js.map} +0 -0
  99. /package/dist/{agent-OCQA4WXF.js.map → agent-UBDDP2L5.js.map} +0 -0
  100. /package/dist/{app-typed-client-J7NWKMS7.js.map → app-typed-client-BE3PV3JY.js.map} +0 -0
  101. /package/dist/{app-typed-client-Z4MF5HCB.js.map → app-typed-client-RAFEBA7S.js.map} +0 -0
  102. /package/dist/{aws-lambda-AN6CEBXO.js.map → aws-lambda-R76PWR27.js.map} +0 -0
  103. /package/dist/{build-JQSCQ3SQ.js.map → build-U4HVYY6F.js.map} +0 -0
  104. /package/dist/{bun-3FFL7CS4.js.map → bun-NPBIAWSU.js.map} +0 -0
  105. /package/dist/{chunk-PALZUV6E.js.map → chunk-6B3CMPE4.js.map} +0 -0
  106. /package/dist/{chunk-EQCSUC65.js.map → chunk-AROOYXI5.js.map} +0 -0
  107. /package/dist/{chunk-N6XDYNWK.js.map → chunk-FYYKMPST.js.map} +0 -0
  108. /package/dist/{chunk-WAYUHS54.js.map → chunk-GDF2XQOO.js.map} +0 -0
  109. /package/dist/{chunk-EYRWD2AB.js.map → chunk-WSOAN4KN.js.map} +0 -0
  110. /package/dist/{deno-deploy-PTO7IE4G.js.map → deno-deploy-BXOQ45LD.js.map} +0 -0
  111. /package/dist/{dev-DPOAVHUS.js.map → dev-E3USPAWQ.js.map} +0 -0
  112. /package/dist/{internal-api-VHFQCXR2.js.map → internal-api-OOTVIOH2.js.map} +0 -0
  113. /package/dist/{internal-api-C5NIIJJY.js.map → internal-api-VAKXXW6F.js.map} +0 -0
  114. /package/dist/{mcp-LOMU5PGA.js.map → mcp-7UOQM4FW.js.map} +0 -0
  115. /package/dist/{netlify-3VSNVURQ.js.map → netlify-LPJAPMQ2.js.map} +0 -0
  116. /package/dist/{observability-bootstrap-H4NSILXD.js.map → observability-bootstrap-YQKMEYW7.js.map} +0 -0
  117. /package/dist/{preview-24MJYNYN.js.map → preview-GPMF43QX.js.map} +0 -0
  118. /package/dist/{registry-RZHBBLIF.js.map → registry-UOWTDUFL.js.map} +0 -0
  119. /package/dist/{server-boundary-DJ4PYJR5.js.map → server-boundary-A3HW27C7.js.map} +0 -0
  120. /package/dist/{server-boundary-FVMJ5WAU.js.map → server-boundary-V6PCM22J.js.map} +0 -0
  121. /package/dist/{static-SVDWIOXJ.js.map → static-7OJNB7D2.js.map} +0 -0
  122. /package/dist/{vercel-BZ35DF3B.js.map → vercel-YUZADKGV.js.map} +0 -0
  123. /package/dist/{vite-plugin-AVFHID5Z.js.map → vite-plugin-WBF5NXGW.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/cloudflare.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Cloudflare deploy adapter. All write paths are under `cwd/.theokit/cloudflare/`\n * and `cwd/wrangler.toml`. Build-time tool — no HTTP input.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { TheoConfig } from '../config/schema.js'\nimport { findRootDiv } from '../core/contracts/find-root-div.js'\nimport { parseAssetsMap } from '../core/contracts/module-preloads.js'\nimport type { SecurityHeadersConfig } from '../core/contracts/security-headers.js'\nimport { assertServicesUnsupported, readManifest } from '../services/index.js'\n\nimport { deployedAgentsFragment, type DeployedAgent } from './deployed-agents.js'\nimport { deployedCorsFragment, type DeployedCorsOptions } from './deployed-cors.js'\nimport { deployedCsrfFragment, type DeployedCsrfOptions } from './deployed-csrf.js'\nimport { planDeployedPlugins } from './deployed-plugins-module.js'\nimport {\n deployedRuntimeConfigFragment,\n serverDirLiteral,\n type DeployedRuntimeConfigOptions,\n type DeployedServerDirOptions,\n} from './deployed-runtime-config.js'\nimport { deployedTraceFragment } from './deployed-trace.js'\nimport { nodeAdapter } from './node.js'\nimport {\n describeDeployedSecurityHeaders,\n renderSecurityHeadersConfigLiteral,\n} from './security-headers.js'\nimport type { AdapterBuildContext, DeployAdapter } from './types.js'\n\n/**\n * T2.1 — Cloudflare adapter rewritten to consume `theokit/adapters/web-shim`\n * instead of emitting an inline plain-object Request/Response shim. Reduces\n * template from ~50 lines to ~25 and centralizes maintenance.\n */\n\n/**\n * The built `index.html` split into the part before `<div id=\"root\">` and the\n * part after it.\n *\n * Refuses by name when streaming is on and the template is missing, rather than\n * emitting a worker that serves a headless document. A build that cannot produce\n * a correct artifact should say so at build time; the alternative is a deploy\n * that looks successful and serves pages with no stylesheet.\n */\nfunction readDocumentShell(\n cwd: string,\n streaming: boolean,\n): { htmlHead?: string; htmlTail?: string } {\n if (!streaming) return {}\n\n const indexPath = resolve(cwd, '.theokit/client/index.html')\n if (!existsSync(indexPath)) {\n throw new Error(\n `[adapter-cloudflare] ssrStreaming is on but ${indexPath} does not exist, so the worker ` +\n `would serve a document with no <head> and no client entry. Run the client build first, ` +\n `or set ssrStreaming: false in theo.config.ts.`,\n )\n }\n\n const indexHtml = readFileSync(indexPath, 'utf-8')\n const rootDiv = findRootDiv(indexHtml)\n if (rootDiv === undefined) {\n throw new Error(\n `[adapter-cloudflare] ${indexPath} has no <div id=\"root\">, so the streamed document has ` +\n `nowhere to put the app. Add one, or set ssrStreaming: false in theo.config.ts.`,\n )\n }\n\n return {\n htmlHead: indexHtml.slice(0, rootDiv.insertAt),\n htmlTail: indexHtml.slice(rootDiv.insertAt),\n }\n}\n\n/**\n * The routes, turned into source: static imports, a module map and a literal table (#369).\n *\n * Extracted so the worker renderer stays inside its length budget, and because this is the whole of\n * what changed about how a Worker finds a route — it reads as one idea rather than as three loops\n * inside a hundred lines of template.\n *\n * `../../` because the worker is written to `.theokit/cloudflare/worker.mjs` and `filePath` is\n * relative to the project root. The imports are static so Wrangler's bundler follows them:\n * `wrangler.toml` uploads `.theokit/client` and has never uploaded `server/`, so a module not\n * bundled INTO the worker is not on the platform at all.\n */\nfunction renderBakedRoutes(\n routes: readonly { filePath: string; routePath: string; methods?: readonly string[] }[],\n): { routeImports: string[]; routeModuleEntries: string[]; routeTableEntries: string[] } {\n const routeVar = (index: number): string => `__theoRoute${String(index)}`\n return {\n routeImports: routes.map(\n (route, index) => `import * as ${routeVar(index)} from '../../${route.filePath}'`,\n ),\n routeModuleEntries: routes.map(\n (route, index) => ` ${JSON.stringify(route.filePath)}: ${routeVar(index)},`,\n ),\n routeTableEntries: routes.map(\n (route) =>\n ` { filePath: ${JSON.stringify(route.filePath)}, routePath: ${JSON.stringify(route.routePath)}, ` +\n `methods: ${JSON.stringify([...(route.methods ?? [])])}, ` +\n `...compilePattern(${JSON.stringify(route.routePath)}) },`,\n ),\n }\n}\n\n/**\n * The route-resolution runtime the Worker gets instead of a directory scan (#369).\n *\n * A module map, the literal table, and a loader that refuses anything the build did not bake.\n * Emitted as its own block because it replaces one idea — \"find the routes\" — wholesale.\n */\nfunction routeRuntimeLines(moduleEntries: string[], tableEntries: string[]): string[] {\n return [\n `// #369 — the routes are baked at build time. The Worker used to reach for`,\n `// \\`scanServerRoutes\\` on the server directory — a readdirSync, in a runtime with no`,\n `// filesystem. The pattern is recompiled here from the same routePath the scanner`,\n `// used, so one function decides precedence on every target.`,\n `const ROUTE_MODULES = {`,\n ...moduleEntries,\n `}`,\n ``,\n `const routes = [`,\n ...tableEntries,\n `]`,\n ``,\n `// The executor asks for a module by the path the table names. Anything else was`,\n `// never bundled, and saying so beats returning undefined and failing later on a`,\n `// property access far from the cause.`,\n `async function loadModule(path) {`,\n ` const mod = ROUTE_MODULES[path]`,\n ` if (mod === undefined) {`,\n // No backticks in this message: it is emitted INTO a template literal, and a stray one closes\n // it. That is how #344 shipped a SyntaxError, and the emitted-entry parse gate caught this one\n // before it left the branch.\n \" throw new Error(`Route module '\" +\n '${path}' +\n \"' was not bundled into this Worker. \" +\n 'A Worker has no filesystem, so every route is imported at build time. ' +\n 'Re-run: theokit build --target cloudflare`)',\n ` }`,\n ` return mod`,\n `}`,\n ``,\n ]\n}\n\n/**\n * Read the map `theokit build` emitted, for baking into the worker (B-035).\n *\n * Returns `undefined` — never throws — for an absent or malformed file. A deploy that failed\n * because an optimisation was missing would turn a lost round trip into a broken build, and the\n * worker is correct without it.\n */\nexport function readAssetsMapForBake(path: string): Record<string, string[]> | undefined {\n try {\n return parseAssetsMap(readFileSync(path, 'utf8'))\n } catch {\n return undefined\n }\n}\n\n/**\n * The baked route-to-chunks map, as worker source (B-035).\n *\n * A literal and not a read, for the same reason the document shell is: a Worker has no filesystem\n * at request time. Emitted only when the build produced a map; otherwise the worker carries\n * nothing about preloads and behaves exactly as before.\n *\n * **It emits the DATA and no longer the code.** An earlier revision emitted a hand-written copy of\n * `injectModulePreloads`, justified by a claim that the worker could not import it. That claim was\n * false — `theokit/server` re-exports from `core/contracts/` and the generated worker already\n * imports that subpath — and the copy drifted within a day: a fix for proxy-form request targets\n * landed in the original and not in the duplicate. The worker now imports the real function, which\n * is the shape `adapters/security-headers.ts` established one directory over for exactly this\n * build-half/runtime-half pair.\n */\n/**\n * Whether this worker can preload at all (B-035).\n *\n * ONE predicate, read by the bake, the import and the call. Two conditions for one decision is\n * how the import came to be emitted for a worker that had no map to give it — found at review, in\n * the same change where a copy and its original had already drifted apart.\n *\n * Streaming is required because the other branch serves the document from `env.ASSETS` as a\n * static file and can inject nothing into it.\n */\nfunction preloadsApplyTo(opts: {\n ssrStreaming?: boolean\n assetsMap?: Record<string, string[]>\n}): boolean {\n return opts.ssrStreaming === true && opts.assetsMap !== undefined\n}\n\nfunction renderPreloadSupport(assetsMap: Record<string, string[]> | undefined): string {\n if (assetsMap === undefined) return ''\n return `const __THEO_ASSETS_MAP = ${JSON.stringify(assetsMap)}`\n}\n\n/**\n * The branch that answers a non-API request: streamed SSR, or the static asset the Worker\n * platform serves. Extracted at review — it is the one decision in this emitter with two whole\n * shapes behind it, and keeping it inline pushed the caller past its line budget.\n */\nfunction renderNonApiBranch(\n opts: NonNullable<Parameters<typeof renderCloudflareWorkerEntry>[0]>,\n preloadsApply: boolean,\n): string {\n return opts.ssrStreaming\n ? [\n ` // T2.3 — streaming SSR for non-API routes`,\n ` // The same primitive \\`theokit start\\` uses, not a second one:`,\n ` // 16 bytes of Web Crypto entropy, base64.`,\n ` const nonce = generateNonce()`,\n ` return withSecurityHeaders(`,\n ` await renderStreamingWeb(request, {`,\n !preloadsApply\n ? ` htmlHead: ${JSON.stringify(opts.htmlHead ?? '')},`\n : ` htmlHead: injectModulePreloads(${JSON.stringify(opts.htmlHead ?? '')}, __THEO_ASSETS_MAP, new URL(request.url).pathname),`,\n ` htmlTail: ${JSON.stringify(opts.htmlTail ?? '')},`,\n ` nonce,`,\n ` }),`,\n ` buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true }, { nonce }),`,\n ` )`,\n ].join('\\n')\n : [\n ` // #412 — the document, served by the worker so it carries the same baseline every`,\n ` // API response carries. It used to return 404 here while wrangler.toml declared a`,\n ` // \\`[site]\\` bucket nothing read, so the page was missing rather than unprotected.`,\n ` const assets = env?.ASSETS`,\n ` // A wrangler.toml that predates this binding has no ASSETS. Reading .fetch off`,\n ` // undefined would turn every page request into a 500; 404 is what this target`,\n ` // answered before, which is the honest fallback rather than a new failure.`,\n ` if (assets === undefined) return notFoundResponse()`,\n ` return withSecurityHeaders(await assets.fetch(request), SECURITY_HEADERS)`,\n ].join('\\n')\n}\n\nexport function renderCloudflareWorkerEntry(\n opts: {\n ssrStreaming?: boolean\n htmlHead?: string\n htmlTail?: string\n /**\n * B-035 — the route-to-chunks map, baked as a literal for the same reason the shell above\n * is: a Worker has no filesystem at request time. Absent when the build produced no map,\n * and then nothing about preloads is emitted at all.\n */\n assetsMap?: Record<string, string[]>\n securityHeaders?: SecurityHeadersConfig\n /**\n * The server routes, scanned on the BUILD machine (#369).\n *\n * A Worker has no filesystem, so the worker used to call `scanServerRoutes` — a `readdirSync` —\n * against a directory that does not exist there, and load each module through `import()` of a\n * file path. Both are baked here instead, which is the road this adapter already takes for the\n * document shell one function away.\n *\n * `filePath` is relative to the project root and is used for two things: the key the executor\n * looks a module up by, and the specifier the static import uses. Paths are emitted relative to\n * `.theokit/cloudflare/`, where the worker is written.\n */\n routes?: readonly { filePath: string; routePath: string; methods?: readonly string[] }[]\n /**\n * The two concerns #410 could not bake (#425), composed from one place so the six targets\n * cannot drift into six spellings. `serialization` is a literal like the security values above;\n * `plugins` is an import, because a closure has no literal.\n */\n runtimeConfigModule?: DeployedRuntimeConfigOptions['runtimeConfigModule']\n serialization?: DeployedRuntimeConfigOptions['serialization']\n /**\n * The app's agents, scanned on the build machine (#367).\n *\n * A different scan from `routes` and served by a different function — which is why a worker\n * that only consulted the route table answered every `/api/agents/<name>` with a 404.\n */\n agents?: readonly DeployedAgent[]\n /** WebSocket route files, scanned on the build machine. Only their presence is used (#369). */\n wsRoutes?: readonly string[]\n } & DeployedServerDirOptions &\n DeployedCsrfOptions &\n DeployedCorsOptions = {},\n): string {\n const streamingImport = opts.ssrStreaming\n ? `import { renderStreamingWeb } from '/@theo/entry-server'`\n : `// (ssrStreaming off: renderStreamingWeb not imported)`\n // #343 — the document shell is inlined as a build-time literal because a Worker\n // has no filesystem to read `index.html` from at request time. Without it,\n // `renderStreamingWeb` falls back to its empty-string defaults and the response\n // is React output with no `<html>`, no `<head>`, no stylesheet and no client\n // entry — hydration data for a page that cannot hydrate. The streaming\n // assembly was fixed in the generated entry and this, its only caller, was\n // left passing nothing.\n //\n // `JSON.stringify` and not a template literal: the shell contains quotes,\n // angle brackets and a `</script>`, and embedding it naively produces a worker\n // that fails to parse at deploy time rather than here.\n //\n // #410 — this is also the ONE deploy path that renders HTML at request time,\n // so the one that can mint a per-request CSP nonce: `renderStreamingWeb`\n // threads `options.nonce` into `renderToReadableStream` and into the hydration\n // script (`router/entry-server.ts`). Every other response below carries the\n // nonce-less baseline, which is what `buildSecurityHeaders` already does for a\n // prerendered route (EC-4).\n // Only the streaming branch renders HTML at request time; the other serves the document from\n // `env.ASSETS` as a static file and can inject nothing. Baking the map for it would ship the whole\n // route table as dead weight — found at review, where the emitter was measured declaring it with\n // zero call sites.\n const preloadsApply = preloadsApplyTo(opts)\n const preloadSupport = preloadsApply ? renderPreloadSupport(opts.assetsMap) : ''\n\n const nonApiBranch = renderNonApiBranch(opts, preloadsApply)\n\n // CR-006: Workers lack `process.cwd()` and the `node:*` import surface\n // is brittle even under `nodejs_compat`. We use the Web Crypto\n // `crypto.randomUUID()` instead of `node:crypto.randomUUID`, and embed\n // the server directory as a build-time literal instead of resolving via\n // `node:path` at runtime.\n const { routeImports, routeModuleEntries, routeTableEntries } = renderBakedRoutes(\n opts.routes ?? [],\n )\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n const agentsFragment = deployedAgentsFragment(\n opts.agents === undefined ? undefined : { kind: 'baked', agents: opts.agents },\n { wrapSecurityHeaders: true },\n )\n\n return [\n `// Generated by Theo — Cloudflare Workers Adapter`,\n `//`,\n `// REQUIREMENTS (EC-3):`,\n `// - wrangler.toml MUST include compatibility_flags = [\"nodejs_compat\"]`,\n `// (still required for transitive theokit/server deps, e.g. busboy)`,\n `// - package.json MUST list \"theokit\" in dependencies (not devDependencies)`,\n `// so Wrangler bundles theokit and its transitive deps`,\n `// - Deploy: wrangler deploy`,\n ``,\n !preloadsApply\n ? `import { matchRoute, executeRoute, compilePattern, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`\n : `import { matchRoute, executeRoute, compilePattern, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'\\nimport { injectModulePreloads } from 'theokit/server/http'`,\n `import { createWebShim } from 'theokit/adapters/web-shim'`,\n opts.ssrStreaming\n ? `import { buildSecurityHeaders, generateNonce, withSecurityHeaders } from 'theokit/adapters/security-headers'`\n : `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,\n `// T3.4 — WS bridge for Cloudflare Workers`,\n `import { createCloudflareWsBridge } from 'theokit/adapters/ws-shim'`,\n streamingImport,\n ``,\n ...runtimeConfig.imports,\n ...agentsFragment.imports,\n ...routeImports,\n ``,\n `// CR-006: server directory is a build-time literal — Workers cannot`,\n `// call process.cwd() and resolving paths at runtime returned '/server'.`,\n `const serverDir = ${serverDirLiteral(opts)}`,\n ``,\n ...routeRuntimeLines(routeModuleEntries, routeTableEntries),\n `// #410 — the security baseline \\`theokit start\\` puts on every response, carried`,\n `// here as a literal because a Worker has no theo.config.ts to read. Same`,\n `// function, same input, so the deployed page and the local one cannot`,\n `// disagree about what the configuration means.`,\n preloadSupport,\n `const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(opts.securityHeaders)}`,\n `const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,\n ``,\n ...deployedCsrfFragment(opts, 'a Worker'),\n ``,\n ...runtimeConfig.declarations,\n ...agentsFragment.declarations,\n ...deployedCorsFragment(opts.cors, 'cloudflare'),\n `// #369 — whether this project declares a WebSocket route, decided at build time. It used`,\n `// to answer it with \\`scanWebSocketRoutes\\`, which is the same readdirSync.`,\n `const HAS_WS_ROUTES = ${String((opts.wsRoutes ?? []).length > 0)}`,\n ``,\n `function notFoundResponse() {`,\n ` return withSecurityHeaders(`,\n ` new Response(`,\n ` JSON.stringify({ error: { code: 'NOT_FOUND', message: 'Route not found' } }),`,\n ` { status: 404, headers: { 'Content-Type': 'application/json' } },`,\n ` ),`,\n ` SECURITY_HEADERS,`,\n ` )`,\n `}`,\n ``,\n ...cloudflareHandleRequestFragment(\n nonApiBranch,\n runtimeConfig.executeRouteSpread,\n agentsFragment.branch,\n ),\n ].join('\\n')\n}\n\n/**\n * The Worker's request handler, as generated source.\n *\n * Extracted for the reason `vercel.ts` extracts its own fragments: the emitter is one array\n * literal, so every line the entry gains counts against `max-lines-per-function`, and #410 added\n * the CSRF literal to an emitter already sitting exactly at the ceiling.\n *\n * @param nonApiBranch - what a non-`/api/` request gets, which differs with `ssrStreaming`\n */\nfunction cloudflareHandleRequestFragment(\n nonApiBranch: string,\n runtimeSpread: string,\n agentBranch: readonly string[],\n): string[] {\n return [\n `async function handleRequest(request, url, env) {`,\n ` if (!url.pathname.startsWith('/api/')) {`,\n nonApiBranch,\n ` }`,\n ``,\n ...agentBranch,\n ``,\n ` const match = matchRoute(url.pathname, routes)`,\n ` if (!match) return notFoundResponse()`,\n ``,\n ` const { req, res, toResponse } = createWebShim(request, { trustedProxy: 'platform' })`,\n ...deployedTraceFragment('request', ' '),\n ` const method = request.method.toUpperCase()`,\n ` // #382 — the run is NOT awaited before the Response is taken. toResponse()`,\n ` // settles as soon as status + headers are known and carries a live body, so`,\n ` // the Worker starts flushing while the handler is still writing. Awaiting`,\n ` // executeRoute() first would re-buffer the whole response here even though`,\n ` // the shim streams; awaiting toResponse() does not — it settles at the head.`,\n ` return withSecurityHeaders(await toResponse(executeRoute({`,\n ` route: match.route, method, params: match.params,`,\n ` req, res, loadModule, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread}`,\n ` })), SECURITY_HEADERS)`,\n `}`,\n ``,\n `export default {`,\n ` async fetch(request, env, ctx) {`,\n ` const url = new URL(request.url)`,\n ``,\n ` // T3.4 — Detect WebSocket upgrade and delegate to the CF bridge.`,\n ` // A 101 carries no document and no script, so the security baseline does`,\n ` // not apply to it.`,\n ` if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {`,\n ` if (!HAS_WS_ROUTES) return notFoundResponse()`,\n ` const cfWs = createCloudflareWsBridge({`,\n ` onOpen: () => {},`,\n ` onMessage: (ws, data) => { ws.send(data) },`,\n ` onClose: () => {},`,\n ` })`,\n ` return cfWs.handle(request)`,\n ` }`,\n ``,\n ` // #409 — the preflight is answered BEFORE anything routes: an OPTIONS the router handles`,\n ` // is an OPTIONS the browser never gets a CORS answer to. The WebSocket upgrade above is`,\n ` // deliberately upstream of it — a 101 is not a CORS-governed response.`,\n ` const preflight = corsPreflight(request)`,\n ` if (preflight !== null) return withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ``,\n ` return withCors(request, await handleRequest(request, url, env))`,\n ` },`,\n `}`,\n ]\n}\n\nexport function renderWranglerToml(): string {\n return [\n `# Generated by Theo — Cloudflare Workers`,\n `name = \"theo-app\"`,\n `main = \".theokit/cloudflare/worker.mjs\"`,\n `compatibility_date = \"2025-09-01\"`,\n `compatibility_flags = [\"nodejs_compat\"]`,\n ``,\n `# #412 — \\`[assets]\\` with a BINDING, not the legacy \\`[site]\\` bucket.`,\n `#`,\n `# \\`[site]\\` uploads to KV and is read through \\`kv-asset-handler\\` and a`,\n `# \\`__STATIC_CONTENT\\` binding — neither of which this worker has ever had. So the`,\n `# bucket was declared, uploaded, and consumed by nothing: with ssrStreaming off, a`,\n `# deploy answered 404 for its own page. This binding is what the worker calls.`,\n `[assets]`,\n `directory = \".theokit/client\"`,\n `binding = \"ASSETS\"`,\n `# A client-routed app asks for /dashboard, which is no file. Without this the asset`,\n `# handler 404s a deep link and the SPA never boots.`,\n `not_found_handling = \"single-page-application\"`,\n ``,\n `# Environment variables are set via wrangler secret or dashboard`,\n `# Example: wrangler secret put DATABASE_URL`,\n ].join('\\n')\n}\n\nexport const cloudflareAdapter: DeployAdapter = {\n name: 'cloudflare',\n streamsResponses: true,\n // #409 / #410 — the generated entry calls `executeRoute` with routes, loader\n // and serverDir only. CSRF, route policy, file middleware and Zod validation\n // still run because they live inside `executeRoute`; none of the remaining\n // configurable concerns reach it. Declared explicitly rather than omitted so\n // the gap is a statement in the source and not an absence.\n //\n // `securityHeaders` IS applied: the worker carries `security.headers` as a\n // literal and puts the built baseline on every response it returns, including\n // the streamed SSR document — with a per-request nonce, the only deploy path\n // that can mint one (`adapters/security-headers.ts`).\n servesAgents: true,\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization', 'plugins'],\n\n async build(config: TheoConfig, cwd: string, ctx?: AdapterBuildContext): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('cloudflare', readManifest(cwd))\n\n // 1. Run the standard Node build first (ctx forwarded so nodeAdapter has makeVitePlugins)\n await nodeAdapter.build(config, cwd, ctx)\n\n const outputDir = resolve(cwd, '.theokit/cloudflare')\n mkdirSync(outputDir, { recursive: true })\n\n // 2. Emit Worker entry (now uses the shared web-shim)\n //\n // The document shell is read HERE, after the Node build produced\n // `.theokit/client/index.html`, and inlined into the worker: a Worker has no\n // filesystem at request time. Split on the root div with the same helper the\n // Node server uses (`ssr-setup.ts`), so the two paths cannot disagree about\n // where the shell ends (#343).\n const shell = readDocumentShell(cwd, config.ssrStreaming)\n // B-035 — the route-to-chunks map, read HERE on the build machine for the same reason the\n // shell above is: a Worker has no filesystem at request time. `nodeAdapter.build` ran\n // first, so the map the Node build emitted is on disk by now. Absent map -> nothing about\n // preloads is emitted, and the worker behaves exactly as it did before.\n const assetsMap = readAssetsMapForBake(resolve(cwd, '.theokit', 'client', 'assets-map.json'))\n\n // #369 — the routes are resolved HERE, on the build machine, for the same reason the document\n // shell above is read here: a Worker has no filesystem at request time, and the worker used to\n // run the scan itself against a directory that does not exist there.\n //\n // The scanner is INJECTED rather than imported: importing it would add an `adapters → server`\n // edge, which is the layering inversion ADR-0001 v3 removed for `vite-plugin` and which\n // `adapters-may-only-depend-on-core-router-services` refuses. An absent scanner emits a worker\n // with no routes rather than falling back to a runtime scan — the fallback IS the defect.\n const scanned = ctx?.scanRoutes?.(config.serverDir) ?? { routes: [], wsRoutes: [], agents: [] }\n\n const pluginsPlan = planDeployedPlugins(config.plugins, 'cloudflare')\n if (pluginsPlan !== undefined) {\n // Beside the worker, so the emitted import is a sibling. Wrangler bundles from here, which is\n // what lets the static import reach the app's own module at all (#425).\n writeFileSync(resolve(outputDir, 'theo.plugins.mjs'), pluginsPlan.source)\n }\n\n writeFileSync(\n resolve(outputDir, 'worker.mjs'),\n renderCloudflareWorkerEntry({\n ssrStreaming: config.ssrStreaming,\n ...shell,\n securityHeaders: config.security?.headers,\n csrf: config.security?.csrf,\n disallowed: config.security?.disallowed,\n cors: config.security?.cors,\n assetsMap,\n // #425 — a selector, not a transformer, so it rides as a literal like the values above.\n serialization: config.serialization,\n // #425 — the ONE concern that is not a literal. A closure cannot be baked, so a plugin\n // declared by module specifier is imported by the emitted module instead; a constructed one\n // is refused by name at build time rather than dropped in silence.\n runtimeConfigModule: pluginsPlan?.moduleSpecifier,\n routes: scanned.routes,\n // #367 — a Worker has no filesystem, so its agents are decided here like its routes.\n agents: scanned.agents,\n wsRoutes: scanned.wsRoutes,\n }),\n )\n\n // 3. Emit wrangler.toml (with nodejs_compat enforced)\n writeFileSync(resolve(cwd, 'wrangler.toml'), renderWranglerToml())\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ Cloudflare output → .theokit/cloudflare/ + wrangler.toml')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'cloudflare',\n securityHeaders: config.security?.headers,\n // Only the streaming worker renders HTML per request, so only it can put\n // the same nonce on the header and on the script tag it emits.\n mintsNonce: config.ssrStreaming,\n // #412 — either way the worker returns the document now: streamed by\n // `renderStreamingWeb`, or from the ASSETS binding it finally calls.\n documentHeaders: 'handler',\n })}\\n`,\n )\n },\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,eAAe;AAyCxB,SAAS,kBACP,KACA,WAC0C;AAC1C,MAAI,CAAC,UAAW,QAAO,CAAC;AAExB,QAAM,YAAY,QAAQ,KAAK,4BAA4B;AAC3D,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,UAAM,IAAI;AAAA,MACR,+CAA+C,SAAS;AAAA,IAG1D;AAAA,EACF;AAEA,QAAM,YAAY,aAAa,WAAW,OAAO;AACjD,QAAM,UAAU,YAAY,SAAS;AACrC,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI;AAAA,MACR,wBAAwB,SAAS;AAAA,IAEnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,UAAU,MAAM,GAAG,QAAQ,QAAQ;AAAA,IAC7C,UAAU,UAAU,MAAM,QAAQ,QAAQ;AAAA,EAC5C;AACF;AAcA,SAAS,kBACP,QACuF;AACvF,QAAM,WAAW,CAAC,UAA0B,cAAc,OAAO,KAAK,CAAC;AACvE,SAAO;AAAA,IACL,cAAc,OAAO;AAAA,MACnB,CAAC,OAAO,UAAU,eAAe,SAAS,KAAK,CAAC,gBAAgB,MAAM,QAAQ;AAAA,IAChF;AAAA,IACA,oBAAoB,OAAO;AAAA,MACzB,CAAC,OAAO,UAAU,KAAK,KAAK,UAAU,MAAM,QAAQ,CAAC,KAAK,SAAS,KAAK,CAAC;AAAA,IAC3E;AAAA,IACA,mBAAmB,OAAO;AAAA,MACxB,CAAC,UACC,iBAAiB,KAAK,UAAU,MAAM,QAAQ,CAAC,gBAAgB,KAAK,UAAU,MAAM,SAAS,CAAC,cAClF,KAAK,UAAU,CAAC,GAAI,MAAM,WAAW,CAAC,CAAE,CAAC,CAAC,uBACjC,KAAK,UAAU,MAAM,SAAS,CAAC;AAAA,IACxD;AAAA,EACF;AACF;AAQA,SAAS,kBAAkB,eAAyB,cAAkC;AACpF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,IAKA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AASO,SAAS,qBAAqB,MAAoD;AACvF,MAAI;AACF,WAAO,eAAe,aAAa,MAAM,MAAM,CAAC;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AA2BA,SAAS,gBAAgB,MAGb;AACV,SAAO,KAAK,iBAAiB,QAAQ,KAAK,cAAc;AAC1D;AAEA,SAAS,qBAAqB,WAAyD;AACrF,MAAI,cAAc,OAAW,QAAO;AACpC,SAAO,6BAA6B,KAAK,UAAU,SAAS,CAAC;AAC/D;AAOA,SAAS,mBACP,MACA,eACQ;AACR,SAAO,KAAK,eACR;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC,gBACG,uBAAuB,KAAK,UAAU,KAAK,YAAY,EAAE,CAAC,MAC1D,4CAA4C,KAAK,UAAU,KAAK,YAAY,EAAE,CAAC;AAAA,IACnF,uBAAuB,KAAK,UAAU,KAAK,YAAY,EAAE,CAAC;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI,IACX;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACjB;AAEO,SAAS,4BACd,OA0CwB,CAAC,GACjB;AACR,QAAM,kBAAkB,KAAK,eACzB,6DACA;AAuBJ,QAAM,gBAAgB,gBAAgB,IAAI;AAC1C,QAAM,iBAAiB,gBAAgB,qBAAqB,KAAK,SAAS,IAAI;AAE9E,QAAM,eAAe,mBAAmB,MAAM,aAAa;AAO3D,QAAM,EAAE,cAAc,oBAAoB,kBAAkB,IAAI;AAAA,IAC9D,KAAK,UAAU,CAAC;AAAA,EAClB;AACA,QAAM,gBAAgB,8BAA8B,IAAI;AACxD,QAAM,iBAAiB;AAAA,IACrB,KAAK,WAAW,SAAY,SAAY,EAAE,MAAM,SAAS,QAAQ,KAAK,OAAO;AAAA,IAC7E,EAAE,qBAAqB,KAAK;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,CAAC,gBACG,6IACA;AAAA;AAAA,IACJ;AAAA,IACA,KAAK,eACD,iHACA;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,cAAc;AAAA,IACjB,GAAG,eAAe;AAAA,IAClB,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,qBAAqB,iBAAiB,IAAI,CAAC;AAAA,IAC3C;AAAA,IACA,GAAG,kBAAkB,oBAAoB,iBAAiB;AAAA,IAC1D;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mCAAmC,mCAAmC,KAAK,eAAe,CAAC;AAAA,IAC3F;AAAA,IACA;AAAA,IACA,GAAG,qBAAqB,MAAM,UAAU;AAAA,IACxC;AAAA,IACA,GAAG,cAAc;AAAA,IACjB,GAAG,eAAe;AAAA,IAClB,GAAG,qBAAqB,KAAK,MAAM,YAAY;AAAA,IAC/C;AAAA,IACA;AAAA,IACA,yBAAyB,QAAQ,KAAK,YAAY,CAAC,GAAG,SAAS,CAAC,CAAC;AAAA,IACjE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,IACjB;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAWA,SAAS,gCACP,cACA,eACA,aACU;AACV,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,sBAAsB,WAAW,MAAM;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,qEAAqE,aAAa;AAAA,IAClF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,qBAA6B;AAC3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEO,IAAM,oBAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWlB,cAAc;AAAA,EACd,eAAe,CAAC,mBAAmB,QAAQ,cAAc,QAAQ,iBAAiB,SAAS;AAAA,EAE3F,MAAM,MAAM,QAAoB,KAAa,KAA0C;AAErF,8BAA0B,cAAc,aAAa,GAAG,CAAC;AAGzD,UAAM,YAAY,MAAM,QAAQ,KAAK,GAAG;AAExC,UAAM,YAAY,QAAQ,KAAK,qBAAqB;AACpD,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AASxC,UAAM,QAAQ,kBAAkB,KAAK,OAAO,YAAY;AAKxD,UAAM,YAAY,qBAAqB,QAAQ,KAAK,YAAY,UAAU,iBAAiB,CAAC;AAU5F,UAAM,UAAU,KAAK,aAAa,OAAO,SAAS,KAAK,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE;AAE9F,UAAM,cAAc,oBAAoB,OAAO,SAAS,YAAY;AACpE,QAAI,gBAAgB,QAAW;AAG7B,oBAAc,QAAQ,WAAW,kBAAkB,GAAG,YAAY,MAAM;AAAA,IAC1E;AAEA;AAAA,MACE,QAAQ,WAAW,YAAY;AAAA,MAC/B,4BAA4B;AAAA,QAC1B,cAAc,OAAO;AAAA,QACrB,GAAG;AAAA,QACH,iBAAiB,OAAO,UAAU;AAAA,QAClC,MAAM,OAAO,UAAU;AAAA,QACvB,YAAY,OAAO,UAAU;AAAA,QAC7B,MAAM,OAAO,UAAU;AAAA,QACvB;AAAA;AAAA,QAEA,eAAe,OAAO;AAAA;AAAA;AAAA;AAAA,QAItB,qBAAqB,aAAa;AAAA,QAClC,QAAQ,QAAQ;AAAA;AAAA,QAEhB,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,MACpB,CAAC;AAAA,IACH;AAGA,kBAAc,QAAQ,KAAK,eAAe,GAAG,mBAAmB,CAAC;AAGjE,YAAQ,IAAI,0EAAgE;AAE5E,YAAQ;AAAA,MACN,GAAG,gCAAgC;AAAA,QACjC,QAAQ;AAAA,QACR,iBAAiB,OAAO,UAAU;AAAA;AAAA;AAAA,QAGlC,YAAY,OAAO;AAAA;AAAA;AAAA,QAGnB,iBAAiB;AAAA,MACnB,CAAC,CAAC;AAAA;AAAA,IACJ;AAAA,EACF;AACF;","names":[]}
@@ -69,4 +69,42 @@ interface RouteConfig<TQuery extends z.ZodType = z.ZodUndefined, TBody extends z
69
69
  }) => TResponse | Promise<TResponse>;
70
70
  }
71
71
 
72
- export type { RouteConfig as R };
72
+ /**
73
+ * A middleware, as the framework's own builder produces it (usetheokit/theokit#345).
74
+ *
75
+ * `(request, context)`: read the request as a Web `Request`, decorate `context` for the route that
76
+ * follows, and RETURN a `Response` to answer the request yourself. Returning nothing continues to
77
+ * the next middleware, and then to the route.
78
+ *
79
+ * ## Why not `(request, next) => Response`
80
+ *
81
+ * That was this type's first shape, and it described a continuation pipeline nothing in this
82
+ * repository implements: the file-scan runner runs BEFORE routing, so it has no downstream
83
+ * `Response` to hand back from `next(request)`. The consequence was measured rather than
84
+ * theorised — `MiddlewareHandler` had **zero runtime consumers**, while `README.md` documented the
85
+ * builder that produces it as the way to write middleware. A published builder whose output nothing
86
+ * can call is worse than a missing one, because it reads as supported.
87
+ *
88
+ * This shape is the one that fits the model AND already runs: `executeWebRequest` has invoked
89
+ * `(request, context) => Response | void` since T3.2 (`http/web-middleware-runner.ts`). Adopting it
90
+ * here converges two of the three middleware contracts instead of adding a fourth.
91
+ *
92
+ * The Express-style `(req, res, next)` export keeps working in `server/middleware/*.ts`. It is
93
+ * Node-bound — which is why it cannot be the framework's contract — but evicting it would break
94
+ * every app that has one.
95
+ */
96
+ /**
97
+ * Run the rest of the chain and resolve to what it produced.
98
+ *
99
+ * Declared HERE rather than beside the runner because the dependency runs
100
+ * `http/ -> define/` and never the other way (`http/middleware-runner.ts:10`
101
+ * already imports from this module). A middleware's contract belongs with the
102
+ * definition of a middleware; the runner consumes it.
103
+ *
104
+ * `docs/adr/0006` clause 3 is what this parameter buys: code AFTER the
105
+ * downstream, which the short-circuit shape cannot express.
106
+ */
107
+ type MiddlewareNext = () => Promise<Response | undefined>;
108
+ type MiddlewareHandler = (request: Request, context: Record<string, unknown>, next?: MiddlewareNext) => Response | undefined | void | Promise<Response | undefined | void>;
109
+
110
+ export type { MiddlewareHandler as M, RouteConfig as R, MiddlewareNext as a };
@@ -11,11 +11,11 @@ import {
11
11
  deployedTraceFragment,
12
12
  describeDeployedSecurityHeaders,
13
13
  renderSecurityHeadersConfigLiteral
14
- } from "./chunk-PALZUV6E.js";
14
+ } from "./chunk-6B3CMPE4.js";
15
15
  import {
16
16
  nodeAdapter
17
17
  } from "./chunk-KI4DOTN4.js";
18
- import "./chunk-VV2VU3LJ.js";
18
+ import "./chunk-WSMLSIS5.js";
19
19
  import {
20
20
  assertServicesUnsupported,
21
21
  readManifest
@@ -193,4 +193,4 @@ export {
193
193
  denoDeployAdapter,
194
194
  renderDenoEntry
195
195
  };
196
- //# sourceMappingURL=deno-deploy-PTO7IE4G.js.map
196
+ //# sourceMappingURL=deno-deploy-BXOQ45LD.js.map
@@ -11,19 +11,19 @@ import {
11
11
  } from "./chunk-KTMQUYED.js";
12
12
  import {
13
13
  theoPluginAsync
14
- } from "./chunk-OPHA3577.js";
15
- import "./chunk-MOTGIGWC.js";
14
+ } from "./chunk-CO7Q75IS.js";
15
+ import "./chunk-7THO4PRL.js";
16
16
  import "./chunk-BDH5GKFZ.js";
17
17
  import "./chunk-3PWQQWT6.js";
18
18
  import "./chunk-FDOOBTXJ.js";
19
- import "./chunk-47MM2JUK.js";
20
- import "./chunk-O3EBLVMP.js";
19
+ import "./chunk-G2NWAVGG.js";
21
20
  import "./chunk-UETVDZBE.js";
22
21
  import "./chunk-QD5X56I3.js";
23
- import "./chunk-VV2VU3LJ.js";
24
- import "./chunk-5VLP3GQ2.js";
22
+ import "./chunk-WSMLSIS5.js";
23
+ import "./chunk-MS4A7N77.js";
25
24
  import "./chunk-C27VRUVN.js";
26
25
  import "./chunk-7UZZHCRN.js";
26
+ import "./chunk-47MM2JUK.js";
27
27
  import "./chunk-BCFA6LHL.js";
28
28
  import "./chunk-5NNFO7R7.js";
29
29
  import "./chunk-NO6HA4FG.js";
@@ -128,4 +128,4 @@ export {
128
128
  devCommand,
129
129
  startDevServer
130
130
  };
131
- //# sourceMappingURL=dev-DPOAVHUS.js.map
131
+ //# sourceMappingURL=dev-E3USPAWQ.js.map
@@ -2,9 +2,8 @@
2
2
  * M7-2 — health/ready reserved routes for the convention/filesystem-route
3
3
  * server. Liveness (`/__theo/health`, always 200) and readiness
4
4
  * (`/__theo/ready`, 200/503 from a probe) are registered on a reserved
5
- * namespace BEFORE the user-route catch-all + 404 branch — mirroring nitro's
6
- * `/_nitro/*` reserved-namespace pattern (knowledge-base/references/nitro/src/
7
- * runtime/internal/routes/dev-tasks.ts). Liveness and readiness are kept
5
+ * namespace BEFORE the user-route catch-all + 404 branch, which is why a user
6
+ * route can never shadow them. Liveness and readiness are kept
8
7
  * separate by design: liveness says "the process is up", readiness says
9
8
  * "dependencies are up".
10
9
  *
@@ -6,7 +6,7 @@ import { J as JobBackend } from './job-backend-CgC8Xf33.js';
6
6
  import { L as LoadModule, S as ServerRouteNode } from './match-Dw4CNXJH.js';
7
7
  import { C as CsrfMode, D as DisallowedConfig } from './csrf-Dgot9qSM.js';
8
8
  import { z } from 'zod';
9
- import { R as RouteConfig } from './route-config-B7FaTSby.js';
9
+ import { a as MiddlewareNext, R as RouteConfig } from './define-middleware-D2n71Svm.js';
10
10
  import './action-protocol-tGm3NKRg.js';
11
11
 
12
12
  interface ExecuteActionOptions {
@@ -461,6 +461,28 @@ declare function serverErrorToEnvelope(value: unknown): TheoErrorEnvelope;
461
461
  */
462
462
  declare function envelopeCodeToStatus(code: string): number;
463
463
 
464
+ /**
465
+ * Render `<link rel="modulepreload">` for the chunks a route needs beyond the entry (B-035).
466
+ *
467
+ * **The single source of truth, for the Node server AND the Cloudflare worker.**
468
+ *
469
+ * An earlier revision of this file asserted that the worker had to carry a COPY because
470
+ * `theokit`'s package exports declare no subpath reaching `core/`. **That was false, and it was
471
+ * stated three times** — here, in `adapters/cloudflare.ts`, and in a commit message. `server/
472
+ * index.ts` already re-exports from `core/contracts/` *"for consumer ergonomics"* in its own
473
+ * words, `adapters/security-headers.ts` imports `generateNonce` and `buildSecurityHeaders` from
474
+ * here, and the generated worker imports BOTH of those subpaths. Adding a named export to an
475
+ * existing barrel touches no `package.json`, so the constraint never existed.
476
+ *
477
+ * The copy is gone. `theokit/server` re-exports `injectModulePreloads` and the worker imports it,
478
+ * which is the shape `adapters/security-headers.ts` established one directory over — and whose
479
+ * docblock states the reason better than this one could: *"a shape stated in two files drifts"*.
480
+ * It drifted the same day: the proxy fix below landed in this file and not in the copy.
481
+ */
482
+ /** A route path mapped to the chunk file names it needs beyond the entry. */
483
+ type AssetsMap = Record<string, string[] | undefined>;
484
+ declare function injectModulePreloads(head: string, assetsMap: AssetsMap | undefined, url: string): string;
485
+
464
486
  /**
465
487
  * Canonical error handler for HTTP request pipelines (T3.4 of
466
488
  * architecture-review-remediation-plan, PV-9 DRY).
@@ -647,8 +669,30 @@ declare function serveStaticFile(req: IncomingMessage, res: ServerResponse, clie
647
669
  * Full semantic parity with the Node `defineMiddleware` contract is part of the
648
670
  * deferred Node→Web pipeline convergence, not this slice.
649
671
  */
650
- /** A Web-path middleware: mutate `context`, or return a `Response` to short-circuit. */
651
- type WebMiddleware = (request: Request, context: Record<string, unknown>) => Promise<Response | undefined> | Response | undefined | void;
672
+
673
+ /**
674
+ * Run the rest of the chain and resolve to what it produced.
675
+ *
676
+ * An ALIAS, not a second declaration. The two lived as separate structurally
677
+ * identical types before this change and were measured on 2026-09-19 to be
678
+ * incompatible the moment either moved — `MiddlewareHandler` admits
679
+ * `Promise<void>` and `WebMiddleware` did not, so the builder's output was not
680
+ * assignable to the runner's parameter and `tsc` said so in SEVERAL errors that no
681
+ * test could see. (This said "15" until review: control gives 0, an isolated revert 3, a full
682
+ * revert 14, and no reconstruction gives 15 — it was measured on an uncommitted tree and
683
+ * published as a measurement. The mechanism holds; the figure did not, and a figure in a code
684
+ * comment outlives the CHANGELOG entry that carried the same one.) Two names for one contract is how that happens.
685
+ */
686
+ type WebNext = MiddlewareNext;
687
+ /**
688
+ * A Web-path middleware: mutate `context`, return a `Response`, or call `next`.
689
+ *
690
+ * `next` is OPTIONAL in the parameter list so every middleware written against
691
+ * the two-parameter shape keeps compiling and keeps behaving identically — see
692
+ * `docs/adr/0006` clause 5, which rests that claim on a measured call site
693
+ * rather than on confidence.
694
+ */
695
+ type WebMiddleware = (request: Request, context: Record<string, unknown>, next?: WebNext) => Response | undefined | void | Promise<Response | undefined | void>;
652
696
 
653
697
  /**
654
698
  * The route module exported by a `server/routes/*.ts` file (after T2.6 G6
@@ -808,11 +852,9 @@ declare function validateRouteInput(config: RouteInputSchemas, raw: RawRouteInpu
808
852
  * (`validateRouteInput`) so there is no drift, and reuses the SAME `config.response` server-fault
809
853
  * check. Failures throw typed errors (there is no HTTP status off-web).
810
854
  *
811
- * Prior art: tRPC `callProcedure` / `createCallerFactory`
812
- *
813
855
  * Design (ADR-0044 / blueprint §5.4): the AUTHOR passes structured input `{query?, body?, params?}`
814
856
  * — never synthesizes a Request. A minimal in-process `Request` is provided to the handler ONLY so
815
- * handlers that read `request.headers`/`request.url` still work (opencode's proven pattern); the
857
+ * handlers that read `request.headers`/`request.url` still work; the
816
858
  * input itself is NOT parsed from it.
817
859
  */
818
860
 
@@ -909,4 +951,4 @@ interface OpenApiDocsOptions {
909
951
  */
910
952
  declare function createOpenApiHandler(opts?: OpenApiDocsOptions): (request: Request) => Response | null;
911
953
 
912
- export { extractTraceIdFromRequest as $, appendDeleteCookieToHeaders as A, BATCH_PATH as B, type CookieOptions as C, callProcedure as D, type ExecuteActionOptions as E, FileTooLargeError as F, createCorsHandler as G, type HandleBatchOptions as H, createCorsWebHandler as I, createOpenApiHandler as J, createServerContext as K, deleteCookie as L, MAX_ERROR_HTML_BYTES as M, NotFoundError as N, type OpenApiDocsOptions as O, type ParsedBody as P, envelopeCodeToStatus as Q, type RawRouteInput as R, STRIPPED_HEADERS as S, TRACE_HEADER as T, type UploadedFile as U, executeAction as V, type W3CTraceContext as W, executeRoute as X, executeWebRequest as Y, extractTraceId as Z, _resetMiddlewareCacheForTests as _, type BatchExecuteFn as a, extractW3CTraceContext as a0, fromUnknown as a1, getCookie as a2, getCookieFromRequest as a3, handleBatchRequest as a4, handleRequestError as a5, handleWebRequestError as a6, jsonTransformer as a7, loadCustomErrorPages as a8, matchesOrigin as a9, parseCookieHeader as aa, parseRequestBody as ab, parseTraceparent as ac, parseTraceparentContext as ad, resolveTransformer as ae, runMiddlewareAndContext as af, sendError as ag, sendJson as ah, serializeCookie as ai, serveStaticFile as aj, serverErrorToEnvelope as ak, setCookie as al, superjsonTransformer as am, validateRouteInput as an, BatchPathConflictError as b, type BatchPayload as c, type BatchRequestItem as d, type BatchResponse as e, type BatchResultItem as f, type BodyParserOptions as g, type CorsConfig as h, type CorsHandler as i, type CorsOrigin as j, type CorsWebHandler as k, type CustomErrorPages as l, type ExecuteRouteContext as m, type MiddlewareResult as n, type ProcedureInput as o, ProcedureInputError as p, ProcedureOutputError as q, type RouteInputChannel as r, type RouteInputSchemas as s, type RouteInputValidation as t, type SendErrorInput as u, type SendErrorOptions as v, TRACE_PARENT_HEADER as w, TheoError as x, type TheoTransformer as y, appendCookieToHeaders as z };
954
+ export { extractTraceIdFromRequest as $, appendDeleteCookieToHeaders as A, BATCH_PATH as B, type CookieOptions as C, callProcedure as D, type ExecuteActionOptions as E, FileTooLargeError as F, createCorsHandler as G, type HandleBatchOptions as H, createCorsWebHandler as I, createOpenApiHandler as J, createServerContext as K, deleteCookie as L, MAX_ERROR_HTML_BYTES as M, NotFoundError as N, type OpenApiDocsOptions as O, type ParsedBody as P, envelopeCodeToStatus as Q, type RawRouteInput as R, STRIPPED_HEADERS as S, TRACE_HEADER as T, type UploadedFile as U, executeAction as V, type W3CTraceContext as W, executeRoute as X, executeWebRequest as Y, extractTraceId as Z, _resetMiddlewareCacheForTests as _, type BatchExecuteFn as a, extractW3CTraceContext as a0, fromUnknown as a1, getCookie as a2, getCookieFromRequest as a3, handleBatchRequest as a4, handleRequestError as a5, handleWebRequestError as a6, injectModulePreloads as a7, jsonTransformer as a8, loadCustomErrorPages as a9, matchesOrigin as aa, parseCookieHeader as ab, parseRequestBody as ac, parseTraceparent as ad, parseTraceparentContext as ae, resolveTransformer as af, runMiddlewareAndContext as ag, sendError as ah, sendJson as ai, serializeCookie as aj, serveStaticFile as ak, serverErrorToEnvelope as al, setCookie as am, superjsonTransformer as an, validateRouteInput as ao, BatchPathConflictError as b, type BatchPayload as c, type BatchRequestItem as d, type BatchResponse as e, type BatchResultItem as f, type BodyParserOptions as g, type CorsConfig as h, type CorsHandler as i, type CorsOrigin as j, type CorsWebHandler as k, type CustomErrorPages as l, type ExecuteRouteContext as m, type MiddlewareResult as n, type ProcedureInput as o, ProcedureInputError as p, ProcedureOutputError as q, type RouteInputChannel as r, type RouteInputSchemas as s, type RouteInputValidation as t, type SendErrorInput as u, type SendErrorOptions as v, TRACE_PARENT_HEADER as w, TheoError as x, type TheoTransformer as y, appendCookieToHeaders as z };
package/dist/index.js CHANGED
@@ -8,20 +8,20 @@ import {
8
8
  scanRoutes,
9
9
  theoConfigSchema,
10
10
  theoPlugin
11
- } from "./chunk-2ERTA4FM.js";
11
+ } from "./chunk-LADTWXOB.js";
12
12
  import "./chunk-7NRFZBAL.js";
13
13
  import "./chunk-SSYDEKWF.js";
14
- import "./chunk-WAYUHS54.js";
14
+ import "./chunk-GDF2XQOO.js";
15
15
  import "./chunk-GAJOZJWD.js";
16
16
  import "./chunk-OIGJOYX6.js";
17
17
  import "./chunk-U3SPBLJF.js";
18
- import "./chunk-EYRWD2AB.js";
19
- import "./chunk-5GZROLDV.js";
18
+ import "./chunk-WSOAN4KN.js";
19
+ import "./chunk-ENSFCKP6.js";
20
20
  import "./chunk-OGLS76RN.js";
21
- import "./chunk-5AGNZXHJ.js";
21
+ import "./chunk-Q7T3UQ4L.js";
22
22
  import "./chunk-P6OS7652.js";
23
23
  import "./chunk-ZDUO4IYN.js";
24
- import "./chunk-D4VP2QPR.js";
24
+ import "./chunk-7L7LQ2GU.js";
25
25
  import "./chunk-ENRT6DAU.js";
26
26
  import "./chunk-47FFT43U.js";
27
27
  import "./chunk-NTDN54XO.js";
@@ -16,7 +16,7 @@ import {
16
16
  handleCspReport,
17
17
  handleCsrfReadiness,
18
18
  mountAgent
19
- } from "./chunk-O3EBLVMP.js";
19
+ } from "./chunk-G2NWAVGG.js";
20
20
  import {
21
21
  resolveProvider
22
22
  } from "./chunk-UETVDZBE.js";
@@ -27,11 +27,11 @@ import {
27
27
  } from "./chunk-QD5X56I3.js";
28
28
  import {
29
29
  generateNonce
30
- } from "./chunk-VV2VU3LJ.js";
30
+ } from "./chunk-WSMLSIS5.js";
31
31
  import {
32
32
  TRACE_HEADER,
33
33
  extractTraceId
34
- } from "./chunk-5VLP3GQ2.js";
34
+ } from "./chunk-MS4A7N77.js";
35
35
  import {
36
36
  logRequest
37
37
  } from "./chunk-C27VRUVN.js";
@@ -87,4 +87,4 @@ export {
87
87
  scanWebSocketRoutes,
88
88
  sendError
89
89
  };
90
- //# sourceMappingURL=internal-api-VHFQCXR2.js.map
90
+ //# sourceMappingURL=internal-api-OOTVIOH2.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dispatchControllerRequest
3
- } from "./chunk-WAYUHS54.js";
3
+ } from "./chunk-GDF2XQOO.js";
4
4
  import {
5
5
  mountAgent
6
6
  } from "./chunk-GAJOZJWD.js";
@@ -10,8 +10,8 @@ import {
10
10
  applySecurityHeaders,
11
11
  handleCspReport,
12
12
  handleCsrfReadiness
13
- } from "./chunk-EYRWD2AB.js";
14
- import "./chunk-5GZROLDV.js";
13
+ } from "./chunk-WSOAN4KN.js";
14
+ import "./chunk-ENSFCKP6.js";
15
15
  import {
16
16
  BATCH_PATH,
17
17
  createCorsHandler,
@@ -20,10 +20,10 @@ import {
20
20
  handleBatchRequest,
21
21
  incomingMessageToHandlerRequest,
22
22
  sendError
23
- } from "./chunk-5AGNZXHJ.js";
23
+ } from "./chunk-Q7T3UQ4L.js";
24
24
  import "./chunk-P6OS7652.js";
25
25
  import "./chunk-ZDUO4IYN.js";
26
- import "./chunk-D4VP2QPR.js";
26
+ import "./chunk-7L7LQ2GU.js";
27
27
  import "./chunk-ENRT6DAU.js";
28
28
  import "./chunk-47FFT43U.js";
29
29
  import {
@@ -107,4 +107,4 @@ export {
107
107
  scanWebSocketRoutes,
108
108
  sendError
109
109
  };
110
- //# sourceMappingURL=internal-api-C5NIIJJY.js.map
110
+ //# sourceMappingURL=internal-api-VAKXXW6F.js.map
@@ -2,7 +2,7 @@
2
2
  import "tsx/esm";
3
3
  import {
4
4
  createAgentSsrLoader
5
- } from "./chunk-N6XDYNWK.js";
5
+ } from "./chunk-FYYKMPST.js";
6
6
  import {
7
7
  extractAppResources,
8
8
  handleMcpJsonRpc
@@ -75,4 +75,4 @@ async function mcpCommand(name, deps = {}) {
75
75
  export {
76
76
  mcpCommand
77
77
  };
78
- //# sourceMappingURL=mcp-LOMU5PGA.js.map
78
+ //# sourceMappingURL=mcp-7UOQM4FW.js.map
@@ -7,13 +7,13 @@ import {
7
7
  deployedTraceFragment,
8
8
  describeDeployedSecurityHeaders,
9
9
  renderSecurityHeadersConfigLiteral
10
- } from "./chunk-PALZUV6E.js";
10
+ } from "./chunk-6B3CMPE4.js";
11
11
  import {
12
12
  nodeAdapter
13
13
  } from "./chunk-KI4DOTN4.js";
14
14
  import {
15
15
  buildSecurityHeaders
16
- } from "./chunk-VV2VU3LJ.js";
16
+ } from "./chunk-WSMLSIS5.js";
17
17
  import {
18
18
  assertServicesUnsupported,
19
19
  readManifest
@@ -242,4 +242,4 @@ export {
242
242
  netlifyAdapter,
243
243
  renderNetlifyFunction
244
244
  };
245
- //# sourceMappingURL=netlify-3VSNVURQ.js.map
245
+ //# sourceMappingURL=netlify-LPJAPMQ2.js.map
@@ -4,7 +4,7 @@ import {
4
4
  _resetObservabilityAdapter,
5
5
  createObservabilityPluginFromConfig,
6
6
  getObservabilityAdapter
7
- } from "./chunk-5VLP3GQ2.js";
7
+ } from "./chunk-MS4A7N77.js";
8
8
  import "./chunk-C27VRUVN.js";
9
9
  import "./chunk-7UZZHCRN.js";
10
10
  import "./chunk-OSBGZYXZ.js";
@@ -13,4 +13,4 @@ export {
13
13
  createObservabilityPluginFromConfig,
14
14
  getObservabilityAdapter
15
15
  };
16
- //# sourceMappingURL=observability-bootstrap-H4NSILXD.js.map
16
+ //# sourceMappingURL=observability-bootstrap-YQKMEYW7.js.map
@@ -4,8 +4,8 @@ import "tsx/esm";
4
4
  // src/cli/commands/preview.ts
5
5
  async function defaultSteps() {
6
6
  const [{ buildCommand }, { startCommand }] = await Promise.all([
7
- import("./build-JQSCQ3SQ.js"),
8
- import("./start-TXRUHKFJ.js")
7
+ import("./build-U4HVYY6F.js"),
8
+ import("./start-6WEPXA3X.js")
9
9
  ]);
10
10
  return {
11
11
  build: (opts) => buildCommand(opts),
@@ -20,4 +20,4 @@ async function previewCommand(options = {}, steps) {
20
20
  export {
21
21
  previewCommand
22
22
  };
23
- //# sourceMappingURL=preview-24MJYNYN.js.map
23
+ //# sourceMappingURL=preview-GPMF43QX.js.map
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+
4
+ // src/adapters/registry.ts
5
+ var adapterRegistry = {
6
+ node: async () => (await import("./node-OSVPYQ3D.js")).nodeAdapter,
7
+ vercel: async () => (await import("./vercel-YUZADKGV.js")).vercelAdapter,
8
+ cloudflare: async () => (await import("./cloudflare-5HU56XIH.js")).cloudflareAdapter,
9
+ static: async () => (await import("./static-7OJNB7D2.js")).staticAdapter,
10
+ bun: async () => (await import("./bun-NPBIAWSU.js")).bunAdapter,
11
+ "deno-deploy": async () => (await import("./deno-deploy-BXOQ45LD.js")).denoDeployAdapter,
12
+ netlify: async () => (await import("./netlify-LPJAPMQ2.js")).netlifyAdapter,
13
+ "aws-lambda": async () => (await import("./aws-lambda-R76PWR27.js")).awsLambdaAdapter,
14
+ "theo-cloud": async () => (await import("./theo-cloud-3ET4G5T6.js")).theoCloudAdapter
15
+ };
16
+ async function resolveAdapter(target) {
17
+ const factory = adapterRegistry[target];
18
+ return factory();
19
+ }
20
+ export {
21
+ resolveAdapter
22
+ };
23
+ //# sourceMappingURL=registry-UOWTDUFL.js.map
@@ -124,6 +124,20 @@ interface SecurityEnv {
124
124
  interface SecurityHeadersOptions {
125
125
  nonce?: string;
126
126
  prerender?: boolean;
127
+ /**
128
+ * B-034 — this response is being served against a valid preview credential.
129
+ *
130
+ * Two headers follow, and both are the Definition-of-done rather than decoration. `X-Robots-Tag`
131
+ * keeps an unpublished document out of an index. `Cache-Control: private, no-store` keeps it out
132
+ * of a CDN, without which *"served only against a valid credential"* is false however good the
133
+ * credential is: the first hit fills a shared cache and every later reader gets the draft for
134
+ * free.
135
+ *
136
+ * The nonce path below emits the same `Cache-Control` for a different reason (EC-3) and exempts
137
+ * prerendered routes, whose HTML is meant to be cached. **This condition takes no such exemption:
138
+ * a prerendered draft is still a draft.** That is why the two are separate `if`s rather than one.
139
+ */
140
+ preview?: boolean;
127
141
  }
128
142
  /**
129
143
  * Build the security headers map for a given config + env. Pure function —
@@ -134,6 +134,22 @@ declare function rotateIfNeeded<TSession>(sm: SessionManager<TSession>, req: Inc
134
134
  */
135
135
  declare function assertProductionSecret(secret: string | string[]): void;
136
136
 
137
+ interface PreviewMarkerConfig {
138
+ /** Same shape the session takes — a string, or an array whose index 0 is newest. */
139
+ readonly secret: string | string[];
140
+ /** Defaults to `theo_preview`; distinct from the session cookie so revoking one leaves the other. */
141
+ readonly cookieName?: string;
142
+ }
143
+ interface PreviewMarker {
144
+ /** Write a marker good for `ttlSeconds`. The cookie and the signed payload expire together. */
145
+ grant(target: Headers, ttlSeconds: number): Promise<void>;
146
+ /** Clear the marker. Safe to call when none is present. */
147
+ revoke(target: Headers): void;
148
+ /** Is this request carrying a marker that is intact, ours, and unexpired? */
149
+ isPreview(request: Request): Promise<boolean>;
150
+ }
151
+ declare function createPreviewMarker(config: PreviewMarkerConfig): PreviewMarker;
152
+
137
153
  /**
138
154
  * Is this string a secret, or is it the thing a developer types when an error message asks for
139
155
  * 32 characters? (usetheokit/theokit#610)
@@ -574,4 +590,4 @@ declare function clearOidcCache(): void;
574
590
  */
575
591
  declare function discoverOidcProvider(issuer: string | URL): Promise<OidcMetadata>;
576
592
 
577
- export { AuthRequiredError, Authenticated, type BackupCode, type BackupCodeOptions, MIN_SECRET_LENGTH, type OidcMetadata, type PkceChallenge, type SecretWeakness, type SecretWeaknessCode, type SessionConfig, type SessionManager, type SessionManagerWeb, type SessionMeta, type SessionReader, type ThrottleOptions, type ThrottleState, type TotpAlgorithm, type TotpOptions, type TotpUriOptions, type VerifyTotpOptions, _resetKeyCacheForTests, assertProductionSecret, checkThrottle, clearOidcCache, createSessionManager, createSessionManagerWeb, decrypt, discoverOidcProvider, encrypt, generateBackupCodes, generateOAuthState, generatePkceChallenge, generateTotp, generateTotpSecret, inspectSecret, pkceChallengeFromVerifier, recordAttempt, requireAuth, rotateIfNeeded, rotateIfNeededWeb, totpUri, verifyBackupCode, verifyOAuthState, verifyTotp };
593
+ export { AuthRequiredError, Authenticated, type BackupCode, type BackupCodeOptions, MIN_SECRET_LENGTH, type OidcMetadata, type PkceChallenge, type PreviewMarker, type PreviewMarkerConfig, type SecretWeakness, type SecretWeaknessCode, type SessionConfig, type SessionManager, type SessionManagerWeb, type SessionMeta, type SessionReader, type ThrottleOptions, type ThrottleState, type TotpAlgorithm, type TotpOptions, type TotpUriOptions, type VerifyTotpOptions, _resetKeyCacheForTests, assertProductionSecret, checkThrottle, clearOidcCache, createPreviewMarker, createSessionManager, createSessionManagerWeb, decrypt, discoverOidcProvider, encrypt, generateBackupCodes, generateOAuthState, generatePkceChallenge, generateTotp, generateTotpSecret, inspectSecret, pkceChallengeFromVerifier, recordAttempt, requireAuth, rotateIfNeeded, rotateIfNeededWeb, totpUri, verifyBackupCode, verifyOAuthState, verifyTotp };
@@ -6,6 +6,7 @@ import {
6
6
  assertProductionSecret,
7
7
  checkThrottle,
8
8
  clearOidcCache,
9
+ createPreviewMarker,
9
10
  createSessionManager,
10
11
  createSessionManagerWeb,
11
12
  decrypt,
@@ -26,7 +27,7 @@ import {
26
27
  verifyBackupCode,
27
28
  verifyOAuthState,
28
29
  verifyTotp
29
- } from "../../chunk-3IIKKBOJ.js";
30
+ } from "../../chunk-AL5JHX7X.js";
30
31
  import "../../chunk-4FWBKX6G.js";
31
32
  import "../../chunk-YSJOZEI6.js";
32
33
  import {
@@ -41,6 +42,7 @@ export {
41
42
  assertProductionSecret,
42
43
  checkThrottle,
43
44
  clearOidcCache,
45
+ createPreviewMarker,
44
46
  createSessionManager,
45
47
  createSessionManagerWeb,
46
48
  decrypt,
@@ -1,4 +1,4 @@
1
- import { R as RouteConfig } from '../../route-config-B7FaTSby.js';
1
+ import { R as RouteConfig, M as MiddlewareHandler } from '../../define-middleware-D2n71Svm.js';
2
2
  import { z } from 'zod';
3
3
  import { W as WebSocketHandler, b as WebSocketLike } from '../../define-websocket-DzPn1sR6.js';
4
4
  export { a as WebSocketHandlerWeb } from '../../define-websocket-DzPn1sR6.js';
@@ -10,7 +10,7 @@ import { c as OnRequestHook, f as PreHandlerHook, d as OnResponseHook, O as OnEr
10
10
  export { b as HookName, P as PluginContext, e as PluginErrorContext } from '../../plugin-types-BUVfUQ0V.js';
11
11
  import { WireChunk } from '@theokit/presenter/wire';
12
12
  import { IncomingMessage } from 'node:http';
13
- export { H as HEALTH_PATH, a as HealthRouteConfig, b as READY_PATH, c as ReadyRouteConfig, d as ReservedResponse, R as ReservedRoutes, e as defineHealthRoute, f as defineReadyRoute, s as serveReservedRoute } from '../../health-route-C0hk64_U.js';
13
+ export { H as HEALTH_PATH, a as HealthRouteConfig, b as READY_PATH, c as ReadyRouteConfig, d as ReservedResponse, R as ReservedRoutes, e as defineHealthRoute, f as defineReadyRoute, s as serveReservedRoute } from '../../health-route-CYI7z5g3.js';
14
14
 
15
15
  /**
16
16
  * Action wire-protocol accept mode per plan g3-server-actions-and-useaction
@@ -47,32 +47,6 @@ interface ActionConfig<TInput extends z.ZodType, TCtx = unknown> {
47
47
  }) => unknown;
48
48
  }
49
49
 
50
- /**
51
- * A middleware, as the framework's own builder produces it (usetheokit/theokit#345).
52
- *
53
- * `(request, context)`: read the request as a Web `Request`, decorate `context` for the route that
54
- * follows, and RETURN a `Response` to answer the request yourself. Returning nothing continues to
55
- * the next middleware, and then to the route.
56
- *
57
- * ## Why not `(request, next) => Response`
58
- *
59
- * That was this type's first shape, and it described a continuation pipeline nothing in this
60
- * repository implements: the file-scan runner runs BEFORE routing, so it has no downstream
61
- * `Response` to hand back from `next(request)`. The consequence was measured rather than
62
- * theorised — `MiddlewareHandler` had **zero runtime consumers**, while `README.md` documented the
63
- * builder that produces it as the way to write middleware. A published builder whose output nothing
64
- * can call is worse than a missing one, because it reads as supported.
65
- *
66
- * This shape is the one that fits the model AND already runs: `executeWebRequest` has invoked
67
- * `(request, context) => Response | void` since T3.2 (`http/web-middleware-runner.ts`). Adopting it
68
- * here converges two of the three middleware contracts instead of adding a fourth.
69
- *
70
- * The Express-style `(req, res, next)` export keeps working in `server/middleware/*.ts`. It is
71
- * Node-bound — which is why it cannot be the framework's contract — but evicting it would break
72
- * every app that has one.
73
- */
74
- type MiddlewareHandler = (request: Request, context: Record<string, unknown>) => Response | undefined | void | Promise<Response | undefined | void>;
75
-
76
50
  /**
77
51
  * M31 Phase 3 — `route()`, the fluent builder that replaces `defineRoute({...})`.
78
52
  *
@@ -403,4 +377,4 @@ interface WebChannelHandler<TMessage = unknown> {
403
377
  */
404
378
  declare function defineWebChannel<TMessage = unknown>(handler: WebChannelHandler<TMessage>): WebChannelHandler<TMessage>;
405
379
 
406
- export { type ActionAccept, type ActionBuilder, type ActionConfig, type ChannelHandler, CustomTool, type MiddlewareBuilder, type MiddlewareHandler, OnErrorHook, OnRequestHook, OnResponseHook, type PluginBuilder, PreHandlerHook, type RouteBuilder, RouteConfig, RoutePolicy, TheoPlugin, type ToolBuilder, ToolTransform, type WebChannelHandler, type WebSocketBuilder, WebSocketHandler, WebSocketLike, action, defineChannel, defineWebChannel, middleware, plugin, route, tool, uiMessageStreamResponse, websocket };
380
+ export { type ActionAccept, type ActionBuilder, type ActionConfig, type ChannelHandler, CustomTool, type MiddlewareBuilder, MiddlewareHandler, OnErrorHook, OnRequestHook, OnResponseHook, type PluginBuilder, PreHandlerHook, type RouteBuilder, RouteConfig, RoutePolicy, TheoPlugin, type ToolBuilder, ToolTransform, type WebChannelHandler, type WebSocketBuilder, WebSocketHandler, WebSocketLike, action, defineChannel, defineWebChannel, middleware, plugin, route, tool, uiMessageStreamResponse, websocket };
@@ -8,8 +8,8 @@ import {
8
8
  tool,
9
9
  uiMessageStreamResponse,
10
10
  websocket
11
- } from "../../chunk-EQCSUC65.js";
12
- import "../../chunk-D4VP2QPR.js";
11
+ } from "../../chunk-AROOYXI5.js";
12
+ import "../../chunk-7L7LQ2GU.js";
13
13
  import {
14
14
  evaluateRoutePolicy,
15
15
  requireOwner,
@@ -21,7 +21,7 @@ import {
21
21
  defineHealthRoute,
22
22
  defineReadyRoute,
23
23
  serveReservedRoute
24
- } from "../../chunk-GAPBPRPP.js";
24
+ } from "../../chunk-TRCJHFAX.js";
25
25
  import {
26
26
  applyTransform
27
27
  } from "../../chunk-DVUJLMTF.js";