@timber-js/app 0.2.0-alpha.9 → 0.2.0-alpha.90

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 (610) hide show
  1. package/dist/_chunks/actions-DLnUaR65.js +421 -0
  2. package/dist/_chunks/actions-DLnUaR65.js.map +1 -0
  3. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  4. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  5. package/dist/_chunks/chunk-BYIpzuS7.js +39 -0
  6. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  7. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  8. package/dist/_chunks/define-C77ScO0m.js +106 -0
  9. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  10. package/dist/_chunks/define-Itxvcd7F.js +199 -0
  11. package/dist/_chunks/define-Itxvcd7F.js.map +1 -0
  12. package/dist/_chunks/define-cookie-BowvzoP0.js +94 -0
  13. package/dist/_chunks/define-cookie-BowvzoP0.js.map +1 -0
  14. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  15. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  16. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  17. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  18. package/dist/_chunks/{interception-BOoWmLUA.js → interception-DRlhJWbu.js} +219 -97
  19. package/dist/_chunks/interception-DRlhJWbu.js.map +1 -0
  20. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  24. package/dist/_chunks/request-context-CK5tZqIP.js +478 -0
  25. package/dist/_chunks/request-context-CK5tZqIP.js.map +1 -0
  26. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  30. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  32. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  34. package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
  35. package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
  36. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  37. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  38. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  40. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-BiV5GJgm.js} +7 -4
  41. package/dist/_chunks/use-query-states-BiV5GJgm.js.map +1 -0
  42. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  43. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  44. package/dist/adapters/cloudflare-dev.js +73 -0
  45. package/dist/adapters/cloudflare-dev.js.map +1 -0
  46. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  47. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  48. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  49. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  50. package/dist/adapters/cloudflare.d.ts +148 -12
  51. package/dist/adapters/cloudflare.d.ts.map +1 -1
  52. package/dist/adapters/cloudflare.js +135 -11
  53. package/dist/adapters/cloudflare.js.map +1 -1
  54. package/dist/adapters/compress-module.d.ts.map +1 -1
  55. package/dist/adapters/nitro.d.ts +17 -1
  56. package/dist/adapters/nitro.d.ts.map +1 -1
  57. package/dist/adapters/nitro.js +56 -13
  58. package/dist/adapters/nitro.js.map +1 -1
  59. package/dist/cache/cache-api.d.ts +24 -0
  60. package/dist/cache/cache-api.d.ts.map +1 -0
  61. package/dist/cache/handler-store.d.ts +31 -0
  62. package/dist/cache/handler-store.d.ts.map +1 -0
  63. package/dist/cache/index.d.ts +23 -7
  64. package/dist/cache/index.d.ts.map +1 -1
  65. package/dist/cache/index.js +142 -80
  66. package/dist/cache/index.js.map +1 -1
  67. package/dist/cache/singleflight.d.ts +18 -1
  68. package/dist/cache/singleflight.d.ts.map +1 -1
  69. package/dist/cache/sizeof.d.ts +22 -0
  70. package/dist/cache/sizeof.d.ts.map +1 -0
  71. package/dist/cache/timber-cache.d.ts +1 -1
  72. package/dist/cache/timber-cache.d.ts.map +1 -1
  73. package/dist/cli.d.ts +6 -1
  74. package/dist/cli.d.ts.map +1 -1
  75. package/dist/cli.js +8 -3
  76. package/dist/cli.js.map +1 -1
  77. package/dist/client/browser-dev.d.ts +27 -1
  78. package/dist/client/browser-dev.d.ts.map +1 -1
  79. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  80. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  81. package/dist/client/browser-entry/hmr.d.ts +21 -0
  82. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  83. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  84. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  85. package/dist/client/browser-entry/index.d.ts +30 -0
  86. package/dist/client/browser-entry/index.d.ts.map +1 -0
  87. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  88. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  89. package/dist/client/browser-entry/router-init.d.ts +23 -0
  90. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  91. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  92. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  93. package/dist/client/browser-entry/scroll.d.ts +19 -0
  94. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  95. package/dist/client/error-boundary.d.ts +12 -5
  96. package/dist/client/error-boundary.d.ts.map +1 -1
  97. package/dist/client/error-boundary.js +10 -4
  98. package/dist/client/error-boundary.js.map +1 -1
  99. package/dist/client/error-reconstituter.d.ts +54 -0
  100. package/dist/client/error-reconstituter.d.ts.map +1 -0
  101. package/dist/client/form.d.ts +6 -3
  102. package/dist/client/form.d.ts.map +1 -1
  103. package/dist/client/history.d.ts +19 -4
  104. package/dist/client/history.d.ts.map +1 -1
  105. package/dist/client/index.d.ts +9 -21
  106. package/dist/client/index.d.ts.map +1 -1
  107. package/dist/client/index.js +229 -1018
  108. package/dist/client/index.js.map +1 -1
  109. package/dist/client/internal.d.ts +18 -0
  110. package/dist/client/internal.d.ts.map +1 -0
  111. package/dist/client/internal.js +890 -0
  112. package/dist/client/internal.js.map +1 -0
  113. package/dist/client/link-pending-store.d.ts +63 -0
  114. package/dist/client/link-pending-store.d.ts.map +1 -0
  115. package/dist/client/link.d.ts +62 -55
  116. package/dist/client/link.d.ts.map +1 -1
  117. package/dist/client/nav-link-store.d.ts +36 -0
  118. package/dist/client/nav-link-store.d.ts.map +1 -0
  119. package/dist/client/navigation-api-types.d.ts +90 -0
  120. package/dist/client/navigation-api-types.d.ts.map +1 -0
  121. package/dist/client/navigation-api.d.ts +115 -0
  122. package/dist/client/navigation-api.d.ts.map +1 -0
  123. package/dist/client/navigation-context.d.ts +13 -2
  124. package/dist/client/navigation-context.d.ts.map +1 -1
  125. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  126. package/dist/client/navigation-root.d.ts.map +1 -0
  127. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  128. package/dist/client/router-ref.d.ts +1 -1
  129. package/dist/client/router.d.ts +70 -4
  130. package/dist/client/router.d.ts.map +1 -1
  131. package/dist/client/rsc-fetch.d.ts +38 -3
  132. package/dist/client/rsc-fetch.d.ts.map +1 -1
  133. package/dist/client/segment-cache.d.ts +1 -1
  134. package/dist/client/segment-cache.d.ts.map +1 -1
  135. package/dist/client/segment-outlet.d.ts +63 -0
  136. package/dist/client/segment-outlet.d.ts.map +1 -0
  137. package/dist/client/ssr-data.d.ts +13 -4
  138. package/dist/client/ssr-data.d.ts.map +1 -1
  139. package/dist/client/stale-reload.d.ts +15 -0
  140. package/dist/client/stale-reload.d.ts.map +1 -1
  141. package/dist/client/top-loader.d.ts +5 -5
  142. package/dist/client/top-loader.d.ts.map +1 -1
  143. package/dist/client/use-link-status.d.ts +5 -5
  144. package/dist/client/use-link-status.d.ts.map +1 -1
  145. package/dist/client/use-params.d.ts +6 -4
  146. package/dist/client/use-params.d.ts.map +1 -1
  147. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  148. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  149. package/dist/client/use-query-states.d.ts +1 -1
  150. package/dist/client/use-query-states.d.ts.map +1 -1
  151. package/dist/client/use-router.d.ts +1 -1
  152. package/dist/codec.d.ts +33 -0
  153. package/dist/codec.d.ts.map +1 -0
  154. package/dist/codec.js +2 -0
  155. package/dist/config-types.d.ts +266 -0
  156. package/dist/config-types.d.ts.map +1 -0
  157. package/dist/config-validation.d.ts +51 -0
  158. package/dist/config-validation.d.ts.map +1 -0
  159. package/dist/content/index.d.ts +1 -10
  160. package/dist/content/index.d.ts.map +1 -1
  161. package/dist/content/index.js +0 -2
  162. package/dist/cookies/define-cookie.d.ts +35 -14
  163. package/dist/cookies/define-cookie.d.ts.map +1 -1
  164. package/dist/cookies/index.js +1 -83
  165. package/dist/fonts/bundle.d.ts +48 -0
  166. package/dist/fonts/bundle.d.ts.map +1 -0
  167. package/dist/fonts/css.d.ts +1 -0
  168. package/dist/fonts/css.d.ts.map +1 -1
  169. package/dist/fonts/dev-middleware.d.ts +22 -0
  170. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  171. package/dist/fonts/pipeline.d.ts +138 -0
  172. package/dist/fonts/pipeline.d.ts.map +1 -0
  173. package/dist/fonts/transform.d.ts +72 -0
  174. package/dist/fonts/transform.d.ts.map +1 -0
  175. package/dist/fonts/types.d.ts +45 -1
  176. package/dist/fonts/types.d.ts.map +1 -1
  177. package/dist/fonts/virtual-modules.d.ts +59 -0
  178. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  179. package/dist/index.d.ts +45 -190
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +4294 -2453
  182. package/dist/index.js.map +1 -1
  183. package/dist/plugin-context.d.ts +107 -0
  184. package/dist/plugin-context.d.ts.map +1 -0
  185. package/dist/plugins/adapter-build.d.ts +1 -1
  186. package/dist/plugins/adapter-build.d.ts.map +1 -1
  187. package/dist/plugins/build-manifest.d.ts +2 -2
  188. package/dist/plugins/build-manifest.d.ts.map +1 -1
  189. package/dist/plugins/build-report.d.ts +3 -3
  190. package/dist/plugins/build-report.d.ts.map +1 -1
  191. package/dist/plugins/client-chunks.d.ts +32 -0
  192. package/dist/plugins/client-chunks.d.ts.map +1 -0
  193. package/dist/plugins/content.d.ts +1 -1
  194. package/dist/plugins/content.d.ts.map +1 -1
  195. package/dist/plugins/dev-404-page.d.ts +56 -0
  196. package/dist/plugins/dev-404-page.d.ts.map +1 -0
  197. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  198. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  199. package/dist/plugins/dev-error-overlay.d.ts +49 -9
  200. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  201. package/dist/plugins/dev-error-page.d.ts +58 -0
  202. package/dist/plugins/dev-error-page.d.ts.map +1 -0
  203. package/dist/plugins/dev-logs.d.ts +1 -1
  204. package/dist/plugins/dev-logs.d.ts.map +1 -1
  205. package/dist/plugins/dev-server.d.ts +1 -1
  206. package/dist/plugins/dev-server.d.ts.map +1 -1
  207. package/dist/plugins/dev-terminal-error.d.ts +28 -0
  208. package/dist/plugins/dev-terminal-error.d.ts.map +1 -0
  209. package/dist/plugins/entries.d.ts +1 -1
  210. package/dist/plugins/entries.d.ts.map +1 -1
  211. package/dist/plugins/fonts.d.ts +17 -73
  212. package/dist/plugins/fonts.d.ts.map +1 -1
  213. package/dist/plugins/mdx.d.ts +1 -1
  214. package/dist/plugins/mdx.d.ts.map +1 -1
  215. package/dist/plugins/routing.d.ts +1 -1
  216. package/dist/plugins/routing.d.ts.map +1 -1
  217. package/dist/plugins/server-bundle.d.ts.map +1 -1
  218. package/dist/plugins/shims.d.ts +6 -5
  219. package/dist/plugins/shims.d.ts.map +1 -1
  220. package/dist/plugins/static-build.d.ts +4 -4
  221. package/dist/plugins/static-build.d.ts.map +1 -1
  222. package/dist/routing/codegen.d.ts +2 -2
  223. package/dist/routing/codegen.d.ts.map +1 -1
  224. package/dist/routing/convention-lint.d.ts +41 -0
  225. package/dist/routing/convention-lint.d.ts.map +1 -0
  226. package/dist/routing/index.d.ts +2 -0
  227. package/dist/routing/index.d.ts.map +1 -1
  228. package/dist/routing/index.js +3 -2
  229. package/dist/routing/scanner.d.ts.map +1 -1
  230. package/dist/routing/segment-classify.d.ts +46 -0
  231. package/dist/routing/segment-classify.d.ts.map +1 -0
  232. package/dist/routing/status-file-lint.d.ts +2 -1
  233. package/dist/routing/status-file-lint.d.ts.map +1 -1
  234. package/dist/routing/types.d.ts +16 -4
  235. package/dist/routing/types.d.ts.map +1 -1
  236. package/dist/rsc-runtime/rsc.d.ts +1 -1
  237. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  238. package/dist/rsc-runtime/ssr.d.ts +12 -0
  239. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  240. package/dist/schema-bridge.d.ts +76 -0
  241. package/dist/schema-bridge.d.ts.map +1 -0
  242. package/dist/search-params/define.d.ts +139 -0
  243. package/dist/search-params/define.d.ts.map +1 -0
  244. package/dist/search-params/index.d.ts +4 -7
  245. package/dist/search-params/index.d.ts.map +1 -1
  246. package/dist/search-params/index.js +32 -441
  247. package/dist/search-params/index.js.map +1 -1
  248. package/dist/search-params/registry.d.ts +2 -2
  249. package/dist/search-params/registry.d.ts.map +1 -1
  250. package/dist/search-params/wrappers.d.ts +53 -0
  251. package/dist/search-params/wrappers.d.ts.map +1 -0
  252. package/dist/segment-params/define.d.ts +78 -0
  253. package/dist/segment-params/define.d.ts.map +1 -0
  254. package/dist/segment-params/index.d.ts +3 -0
  255. package/dist/segment-params/index.d.ts.map +1 -0
  256. package/dist/segment-params/index.js +2 -0
  257. package/dist/server/access-gate.d.ts +4 -0
  258. package/dist/server/access-gate.d.ts.map +1 -1
  259. package/dist/server/action-client.d.ts +41 -6
  260. package/dist/server/action-client.d.ts.map +1 -1
  261. package/dist/server/action-encryption.d.ts +76 -0
  262. package/dist/server/action-encryption.d.ts.map +1 -0
  263. package/dist/server/action-handler.d.ts +7 -0
  264. package/dist/server/action-handler.d.ts.map +1 -1
  265. package/dist/server/actions.d.ts +3 -6
  266. package/dist/server/actions.d.ts.map +1 -1
  267. package/dist/server/als-registry.d.ts +32 -4
  268. package/dist/server/als-registry.d.ts.map +1 -1
  269. package/dist/server/build-manifest.d.ts +2 -2
  270. package/dist/server/build-manifest.d.ts.map +1 -1
  271. package/dist/server/debug.d.ts +1 -1
  272. package/dist/server/default-logger.d.ts +22 -0
  273. package/dist/server/default-logger.d.ts.map +1 -0
  274. package/dist/server/deny-page-resolver.d.ts +52 -0
  275. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  276. package/dist/server/deny-renderer.d.ts.map +1 -1
  277. package/dist/server/dev-holding-server.d.ts +52 -0
  278. package/dist/server/dev-holding-server.d.ts.map +1 -0
  279. package/dist/server/dev-source-map.d.ts +22 -0
  280. package/dist/server/dev-source-map.d.ts.map +1 -0
  281. package/dist/server/dev-warnings.d.ts +1 -21
  282. package/dist/server/dev-warnings.d.ts.map +1 -1
  283. package/dist/server/early-hints.d.ts +13 -5
  284. package/dist/server/early-hints.d.ts.map +1 -1
  285. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  286. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  287. package/dist/server/fallback-error.d.ts +12 -7
  288. package/dist/server/fallback-error.d.ts.map +1 -1
  289. package/dist/server/flight-injection-state.d.ts +66 -0
  290. package/dist/server/flight-injection-state.d.ts.map +1 -0
  291. package/dist/server/flight-scripts.d.ts +42 -0
  292. package/dist/server/flight-scripts.d.ts.map +1 -0
  293. package/dist/server/flush.d.ts.map +1 -1
  294. package/dist/server/form-data.d.ts +29 -0
  295. package/dist/server/form-data.d.ts.map +1 -1
  296. package/dist/server/html-injectors.d.ts +51 -11
  297. package/dist/server/html-injectors.d.ts.map +1 -1
  298. package/dist/server/index.d.ts +5 -43
  299. package/dist/server/index.d.ts.map +1 -1
  300. package/dist/server/index.js +195 -2800
  301. package/dist/server/index.js.map +1 -1
  302. package/dist/server/internal.d.ts +46 -0
  303. package/dist/server/internal.d.ts.map +1 -0
  304. package/dist/server/internal.js +2900 -0
  305. package/dist/server/internal.js.map +1 -0
  306. package/dist/server/logger.d.ts +25 -7
  307. package/dist/server/logger.d.ts.map +1 -1
  308. package/dist/server/middleware-runner.d.ts +19 -4
  309. package/dist/server/middleware-runner.d.ts.map +1 -1
  310. package/dist/server/node-stream-transforms.d.ts +113 -0
  311. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  312. package/dist/server/page-deny-boundary.d.ts +31 -0
  313. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  314. package/dist/server/pipeline-interception.d.ts +1 -1
  315. package/dist/server/pipeline-interception.d.ts.map +1 -1
  316. package/dist/server/pipeline-metadata.d.ts +6 -0
  317. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  318. package/dist/server/pipeline.d.ts +52 -10
  319. package/dist/server/pipeline.d.ts.map +1 -1
  320. package/dist/server/primitives.d.ts +69 -18
  321. package/dist/server/primitives.d.ts.map +1 -1
  322. package/dist/server/render-timeout.d.ts +51 -0
  323. package/dist/server/render-timeout.d.ts.map +1 -0
  324. package/dist/server/request-context.d.ts +112 -43
  325. package/dist/server/request-context.d.ts.map +1 -1
  326. package/dist/server/route-element-builder.d.ts +27 -1
  327. package/dist/server/route-element-builder.d.ts.map +1 -1
  328. package/dist/server/route-handler.d.ts.map +1 -1
  329. package/dist/server/route-matcher.d.ts +16 -2
  330. package/dist/server/route-matcher.d.ts.map +1 -1
  331. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  332. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  333. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  334. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  335. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  336. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  337. package/dist/server/rsc-entry/index.d.ts +20 -3
  338. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  339. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  340. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  341. package/dist/server/rsc-entry/rsc-stream.d.ts +14 -1
  342. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  343. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  344. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  345. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  346. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  347. package/dist/server/safe-load.d.ts +46 -0
  348. package/dist/server/safe-load.d.ts.map +1 -0
  349. package/dist/server/sensitive-fields.d.ts +74 -0
  350. package/dist/server/sensitive-fields.d.ts.map +1 -0
  351. package/dist/server/sitemap-generator.d.ts +129 -0
  352. package/dist/server/sitemap-generator.d.ts.map +1 -0
  353. package/dist/server/sitemap-handler.d.ts +22 -0
  354. package/dist/server/sitemap-handler.d.ts.map +1 -0
  355. package/dist/server/slot-resolver.d.ts +1 -1
  356. package/dist/server/slot-resolver.d.ts.map +1 -1
  357. package/dist/server/ssr-entry.d.ts +23 -0
  358. package/dist/server/ssr-entry.d.ts.map +1 -1
  359. package/dist/server/ssr-render.d.ts +39 -21
  360. package/dist/server/ssr-render.d.ts.map +1 -1
  361. package/dist/server/ssr-wrappers.d.ts +50 -0
  362. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  363. package/dist/server/status-code-resolver.d.ts +1 -1
  364. package/dist/server/status-code-resolver.d.ts.map +1 -1
  365. package/dist/server/stream-utils.d.ts +36 -0
  366. package/dist/server/stream-utils.d.ts.map +1 -0
  367. package/dist/server/tracing.d.ts +4 -4
  368. package/dist/server/tracing.d.ts.map +1 -1
  369. package/dist/server/tree-builder.d.ts +22 -19
  370. package/dist/server/tree-builder.d.ts.map +1 -1
  371. package/dist/server/types.d.ts +1 -4
  372. package/dist/server/types.d.ts.map +1 -1
  373. package/dist/server/version-skew.d.ts +61 -0
  374. package/dist/server/version-skew.d.ts.map +1 -0
  375. package/dist/shared/merge-search-params.d.ts +22 -0
  376. package/dist/shared/merge-search-params.d.ts.map +1 -0
  377. package/dist/shims/font-google.d.ts +1 -1
  378. package/dist/shims/font-google.d.ts.map +1 -1
  379. package/dist/shims/font-google.js +42 -0
  380. package/dist/shims/font-google.js.map +1 -0
  381. package/dist/shims/font-local.d.ts +26 -0
  382. package/dist/shims/font-local.d.ts.map +1 -0
  383. package/dist/shims/font-local.js +20 -0
  384. package/dist/shims/font-local.js.map +1 -0
  385. package/dist/shims/headers.d.ts +2 -1
  386. package/dist/shims/headers.d.ts.map +1 -1
  387. package/dist/shims/navigation-client.d.ts +1 -1
  388. package/dist/shims/navigation-client.d.ts.map +1 -1
  389. package/dist/shims/navigation.d.ts +3 -2
  390. package/dist/shims/navigation.d.ts.map +1 -1
  391. package/dist/utils/directive-parser.d.ts +5 -2
  392. package/dist/utils/directive-parser.d.ts.map +1 -1
  393. package/dist/utils/state-machine.d.ts +80 -0
  394. package/dist/utils/state-machine.d.ts.map +1 -0
  395. package/package.json +51 -16
  396. package/src/adapters/cloudflare-dev.ts +177 -0
  397. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  398. package/src/adapters/cloudflare.ts +342 -28
  399. package/src/adapters/compress-module.ts +24 -4
  400. package/src/adapters/nitro.ts +52 -8
  401. package/src/adapters/wrangler.d.ts +7 -0
  402. package/src/cache/cache-api.ts +38 -0
  403. package/src/cache/handler-store.ts +68 -0
  404. package/src/cache/index.ts +81 -18
  405. package/src/cache/singleflight.ts +62 -4
  406. package/src/cache/sizeof.ts +31 -0
  407. package/src/cache/timber-cache.ts +24 -20
  408. package/src/cli.ts +16 -6
  409. package/src/client/browser-dev.ts +128 -1
  410. package/src/client/browser-entry/action-dispatch.ts +116 -0
  411. package/src/client/browser-entry/hmr.ts +81 -0
  412. package/src/client/browser-entry/hydrate.ts +145 -0
  413. package/src/client/browser-entry/index.ts +143 -0
  414. package/src/client/browser-entry/post-hydration.ts +119 -0
  415. package/src/client/browser-entry/router-init.ts +193 -0
  416. package/src/client/browser-entry/rsc-stream.ts +157 -0
  417. package/src/client/browser-entry/scroll.ts +27 -0
  418. package/src/client/error-boundary.tsx +48 -16
  419. package/src/client/error-reconstituter.tsx +65 -0
  420. package/src/client/form.tsx +14 -7
  421. package/src/client/history.ts +26 -4
  422. package/src/client/index.ts +65 -38
  423. package/src/client/internal.ts +57 -0
  424. package/src/client/link-pending-store.ts +111 -0
  425. package/src/client/link.tsx +342 -113
  426. package/src/client/nav-link-store.ts +47 -0
  427. package/src/client/navigation-api-types.ts +112 -0
  428. package/src/client/navigation-api.ts +332 -0
  429. package/src/client/navigation-context.ts +31 -6
  430. package/src/client/navigation-root.tsx +342 -0
  431. package/src/client/nuqs-adapter.tsx +16 -3
  432. package/src/client/router-ref.ts +1 -1
  433. package/src/client/router.ts +299 -72
  434. package/src/client/rsc-fetch.ts +97 -8
  435. package/src/client/segment-cache.ts +1 -1
  436. package/src/client/segment-outlet.tsx +86 -0
  437. package/src/client/ssr-data.ts +13 -5
  438. package/src/client/stale-reload.ts +72 -3
  439. package/src/client/top-loader.tsx +18 -6
  440. package/src/client/use-link-status.ts +7 -7
  441. package/src/client/use-params.ts +7 -5
  442. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  443. package/src/client/use-query-states.ts +9 -3
  444. package/src/client/use-router.ts +1 -1
  445. package/src/codec.ts +49 -0
  446. package/src/config-types.ts +264 -0
  447. package/src/config-validation.ts +303 -0
  448. package/src/content/index.ts +5 -13
  449. package/src/cookies/define-cookie.ts +78 -25
  450. package/src/cookies/index.ts +8 -0
  451. package/src/fonts/bundle.ts +142 -0
  452. package/src/fonts/css.ts +2 -1
  453. package/src/fonts/dev-middleware.ts +74 -0
  454. package/src/fonts/pipeline.ts +275 -0
  455. package/src/fonts/transform.ts +353 -0
  456. package/src/fonts/types.ts +50 -1
  457. package/src/fonts/virtual-modules.ts +159 -0
  458. package/src/index.ts +314 -355
  459. package/src/plugin-context.ts +240 -0
  460. package/src/plugins/adapter-build.ts +9 -3
  461. package/src/plugins/build-manifest.ts +13 -2
  462. package/src/plugins/build-report.ts +3 -3
  463. package/src/plugins/client-chunks.ts +65 -0
  464. package/src/plugins/content.ts +1 -1
  465. package/src/plugins/dev-404-page.ts +418 -0
  466. package/src/plugins/dev-browser-logs.ts +288 -0
  467. package/src/plugins/dev-error-overlay.ts +286 -42
  468. package/src/plugins/dev-error-page.ts +536 -0
  469. package/src/plugins/dev-logs.ts +1 -1
  470. package/src/plugins/dev-server.ts +146 -19
  471. package/src/plugins/dev-terminal-error.ts +217 -0
  472. package/src/plugins/entries.ts +111 -10
  473. package/src/plugins/fonts.ts +133 -638
  474. package/src/plugins/mdx.ts +1 -1
  475. package/src/plugins/routing.ts +213 -31
  476. package/src/plugins/server-action-exports.ts +1 -1
  477. package/src/plugins/server-bundle.ts +32 -1
  478. package/src/plugins/shims.ts +136 -35
  479. package/src/plugins/static-build.ts +17 -11
  480. package/src/routing/codegen.ts +273 -105
  481. package/src/routing/convention-lint.ts +356 -0
  482. package/src/routing/index.ts +2 -0
  483. package/src/routing/scanner.ts +93 -23
  484. package/src/routing/segment-classify.ts +89 -0
  485. package/src/routing/status-file-lint.ts +3 -2
  486. package/src/routing/types.ts +17 -4
  487. package/src/rsc-runtime/rsc.ts +2 -0
  488. package/src/rsc-runtime/ssr.ts +50 -0
  489. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  490. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  491. package/src/search-params/define.ts +482 -0
  492. package/src/search-params/index.ts +14 -20
  493. package/src/search-params/registry.ts +2 -2
  494. package/src/search-params/wrappers.ts +85 -0
  495. package/src/segment-params/define.ts +279 -0
  496. package/src/segment-params/index.ts +9 -0
  497. package/src/server/access-gate.tsx +70 -29
  498. package/src/server/action-client.ts +88 -15
  499. package/src/server/action-encryption.ts +144 -0
  500. package/src/server/action-handler.ts +53 -6
  501. package/src/server/actions.ts +10 -9
  502. package/src/server/als-registry.ts +34 -6
  503. package/src/server/build-manifest.ts +10 -4
  504. package/src/server/compress.ts +25 -7
  505. package/src/server/debug.ts +1 -1
  506. package/src/server/default-logger.ts +99 -0
  507. package/src/server/deny-page-resolver.ts +154 -0
  508. package/src/server/deny-renderer.ts +24 -38
  509. package/src/server/dev-holding-server.ts +185 -0
  510. package/src/server/dev-source-map.ts +31 -0
  511. package/src/server/dev-warnings.ts +4 -49
  512. package/src/server/early-hints.ts +36 -15
  513. package/src/server/error-boundary-wrapper.ts +74 -22
  514. package/src/server/fallback-error.ts +74 -102
  515. package/src/server/flight-injection-state.ts +113 -0
  516. package/src/server/flight-scripts.ts +62 -0
  517. package/src/server/flush.ts +2 -1
  518. package/src/server/form-data.ts +76 -0
  519. package/src/server/html-injectors.ts +280 -120
  520. package/src/server/index.ts +25 -177
  521. package/src/server/internal.ts +169 -0
  522. package/src/server/logger.ts +44 -36
  523. package/src/server/middleware-runner.ts +31 -4
  524. package/src/server/node-stream-transforms.ts +509 -0
  525. package/src/server/page-deny-boundary.tsx +56 -0
  526. package/src/server/pipeline-interception.ts +17 -16
  527. package/src/server/pipeline-metadata.ts +13 -0
  528. package/src/server/pipeline.ts +261 -66
  529. package/src/server/primitives.ts +111 -28
  530. package/src/server/render-timeout.ts +108 -0
  531. package/src/server/request-context.ts +293 -132
  532. package/src/server/route-element-builder.ts +283 -191
  533. package/src/server/route-handler.ts +24 -4
  534. package/src/server/route-matcher.ts +31 -20
  535. package/src/server/rsc-entry/api-handler.ts +15 -16
  536. package/src/server/rsc-entry/error-renderer.ts +305 -89
  537. package/src/server/rsc-entry/helpers.ts +134 -5
  538. package/src/server/rsc-entry/index.ts +304 -111
  539. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  540. package/src/server/rsc-entry/rsc-stream.ts +81 -13
  541. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  542. package/src/server/rsc-entry/ssr-renderer.ts +171 -38
  543. package/src/server/safe-load.ts +60 -0
  544. package/src/server/sensitive-fields.ts +230 -0
  545. package/src/server/sitemap-generator.ts +338 -0
  546. package/src/server/sitemap-handler.ts +126 -0
  547. package/src/server/slot-resolver.ts +244 -229
  548. package/src/server/ssr-entry.ts +215 -32
  549. package/src/server/ssr-render.ts +289 -67
  550. package/src/server/ssr-wrappers.tsx +139 -0
  551. package/src/server/status-code-resolver.ts +1 -1
  552. package/src/server/stream-utils.ts +213 -0
  553. package/src/server/tracing.ts +20 -9
  554. package/src/server/tree-builder.ts +92 -58
  555. package/src/server/types.ts +3 -6
  556. package/src/server/version-skew.ts +104 -0
  557. package/src/shared/merge-search-params.ts +55 -0
  558. package/src/shims/font-google.ts +1 -1
  559. package/src/shims/font-local.ts +34 -0
  560. package/src/shims/headers.ts +5 -1
  561. package/src/shims/navigation-client.ts +1 -1
  562. package/src/shims/navigation.ts +7 -2
  563. package/src/utils/directive-parser.ts +5 -2
  564. package/src/utils/state-machine.ts +111 -0
  565. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  566. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  567. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  568. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  569. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  570. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  571. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  572. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  573. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  574. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  575. package/dist/cache/register-cached-function.d.ts +0 -17
  576. package/dist/cache/register-cached-function.d.ts.map +0 -1
  577. package/dist/client/browser-entry.d.ts +0 -21
  578. package/dist/client/browser-entry.d.ts.map +0 -1
  579. package/dist/client/link-status-provider.d.ts +0 -11
  580. package/dist/client/link-status-provider.d.ts.map +0 -1
  581. package/dist/client/transition-root.d.ts.map +0 -1
  582. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  583. package/dist/cookies/index.js.map +0 -1
  584. package/dist/plugins/cache-transform.d.ts +0 -36
  585. package/dist/plugins/cache-transform.d.ts.map +0 -1
  586. package/dist/plugins/dynamic-transform.d.ts +0 -72
  587. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  588. package/dist/search-params/analyze.d.ts +0 -54
  589. package/dist/search-params/analyze.d.ts.map +0 -1
  590. package/dist/search-params/builtin-codecs.d.ts +0 -105
  591. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  592. package/dist/search-params/codecs.d.ts +0 -53
  593. package/dist/search-params/codecs.d.ts.map +0 -1
  594. package/dist/search-params/create.d.ts +0 -106
  595. package/dist/search-params/create.d.ts.map +0 -1
  596. package/dist/server/prerender.d.ts +0 -77
  597. package/dist/server/prerender.d.ts.map +0 -1
  598. package/dist/server/response-cache.d.ts +0 -54
  599. package/dist/server/response-cache.d.ts.map +0 -1
  600. package/src/cache/register-cached-function.ts +0 -103
  601. package/src/client/browser-entry.ts +0 -678
  602. package/src/client/link-status-provider.tsx +0 -30
  603. package/src/client/transition-root.tsx +0 -166
  604. package/src/plugins/cache-transform.ts +0 -199
  605. package/src/plugins/dynamic-transform.ts +0 -161
  606. package/src/search-params/analyze.ts +0 -192
  607. package/src/search-params/builtin-codecs.ts +0 -228
  608. package/src/search-params/create.ts +0 -321
  609. package/src/server/prerender.ts +0 -139
  610. package/src/server/response-cache.ts +0 -410
@@ -13,7 +13,7 @@
13
13
 
14
14
  import { canonicalize } from './canonicalize.js';
15
15
  import { runProxy, type ProxyExport } from './proxy.js';
16
- import { runMiddleware, type MiddlewareFn } from './middleware-runner.js';
16
+ import { runMiddlewareChain, type MiddlewareFn } from './middleware-runner.js';
17
17
  import { runWithTimingCollector, withTiming, getServerTimingHeader } from './server-timing.js';
18
18
  import {
19
19
  runWithRequestContext,
@@ -21,6 +21,7 @@ import {
21
21
  setMutableCookieContext,
22
22
  getSetCookieHeaders,
23
23
  markResponseFlushed,
24
+ setSegmentParams,
24
25
  } from './request-context.js';
25
26
  import {
26
27
  generateTraceId,
@@ -29,7 +30,7 @@ import {
29
30
  replaceTraceId,
30
31
  withSpan,
31
32
  setSpanAttribute,
32
- traceId,
33
+ getTraceId,
33
34
  } from './tracing.js';
34
35
  import {
35
36
  logRequestReceived,
@@ -42,10 +43,35 @@ import {
42
43
  } from './logger.js';
43
44
  import { callOnRequestError } from './instrumentation.js';
44
45
  import { RedirectSignal, DenySignal } from './primitives.js';
46
+ import { ParamCoercionError } from './route-element-builder.js';
47
+ import { checkVersionSkew, applyReloadHeaders } from './version-skew.js';
45
48
  import { serveStaticMetadataFile, serializeSitemap } from './pipeline-metadata.js';
49
+ import { loadModule } from './safe-load.js';
46
50
  import { findInterceptionMatch } from './pipeline-interception.js';
47
51
  import type { MiddlewareContext } from './types.js';
48
- import type { SegmentNode } from '#/routing/types.js';
52
+ import type { SegmentNode } from '../routing/types.js';
53
+
54
+ // ─── Prototype-Pollution-Safe Merge ────────────────────────────────────────
55
+
56
+ /** Keys that must never be merged via Object.assign — they pollute Object.prototype. */
57
+ const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
58
+
59
+ /**
60
+ * Shallow merge that skips prototype-polluting keys.
61
+ *
62
+ * Used instead of Object.assign when the source object comes from
63
+ * user-authored codec output (segmentParams.parse), which could
64
+ * contain __proto__, constructor, or prototype keys.
65
+ *
66
+ * See TIM-655, design/13-security.md
67
+ */
68
+ export function safeMerge(target: Record<string, unknown>, source: Record<string, unknown>): void {
69
+ for (const key of Object.keys(source)) {
70
+ if (!DANGEROUS_KEYS.has(key)) {
71
+ target[key] = source[key];
72
+ }
73
+ }
74
+ }
49
75
 
50
76
  // ─── Route Match Result ────────────────────────────────────────────────────
51
77
 
@@ -53,10 +79,10 @@ import type { SegmentNode } from '#/routing/types.js';
53
79
  export interface RouteMatch {
54
80
  /** The matched segment chain from root to leaf. */
55
81
  segments: SegmentNode[];
56
- /** Extracted route params (catch-all segments produce string[]). */
57
- params: Record<string, string | string[]>;
58
- /** The leaf segment's middleware.ts export, if any. */
59
- middleware?: MiddlewareFn;
82
+ /** Extracted segment params (catch-all segments produce string[]). */
83
+ segmentParams: Record<string, string | string[]>;
84
+ /** Middleware chain from the segment tree, ordered root-to-leaf. */
85
+ middlewareChain: MiddlewareFn[];
60
86
  }
61
87
 
62
88
  /** Function that matches a canonical pathname to a route. */
@@ -115,14 +141,25 @@ export interface PipelineConfig {
115
141
  * Generated at build time from intercepting route directories.
116
142
  * See design/07-routing.md §"Intercepting Routes"
117
143
  */
118
- interceptionRewrites?: import('#/routing/interception.js').InterceptionRewrite[];
144
+ interceptionRewrites?: import('../routing/interception.js').InterceptionRewrite[];
119
145
  /**
120
- * Emit Server-Timing header on responses for Chrome DevTools visibility.
121
- * Only enable in dev mode — exposes internal timing data.
146
+ * Control Server-Timing header output.
122
147
  *
123
- * Default: false (production-safe).
148
+ * - `'detailed'` — per-phase breakdown (proxy, middleware, render).
149
+ * - `'total'` — single `total;dur=N` entry (production-safe).
150
+ * - `false` — no Server-Timing header at all.
151
+ *
152
+ * Default: `'total'`.
124
153
  */
125
- enableServerTiming?: boolean;
154
+ serverTiming?: 'detailed' | 'total' | false;
155
+ /**
156
+ * Auto-generated sitemap handler. When provided, the pipeline intercepts
157
+ * `/sitemap.xml` and `/sitemap/N.xml` requests and delegates to this
158
+ * function. Returns a Response or null (pass-through to regular routing).
159
+ *
160
+ * See design/16-metadata.md §"Auto-generated Sitemap"
161
+ */
162
+ autoSitemapHandler?: (pathname: string) => Promise<Response | null>;
126
163
  /**
127
164
  * Dev pipeline error callback — called when a pipeline phase (proxy,
128
165
  * middleware, render) catches an unhandled error. Used to wire the error
@@ -131,6 +168,7 @@ export interface PipelineConfig {
131
168
  * Undefined in production — zero overhead.
132
169
  */
133
170
  onPipelineError?: (error: Error, phase: string) => void;
171
+
134
172
  /**
135
173
  * Fallback error renderer — called when a catastrophic error escapes the
136
174
  * render phase. Produces an HTML Response instead of a bare empty 500.
@@ -147,6 +185,64 @@ export interface PipelineConfig {
147
185
  req: Request,
148
186
  responseHeaders: Headers
149
187
  ) => Response | Promise<Response>;
188
+ /**
189
+ * Fallback deny page renderer — called when a DenySignal escapes from
190
+ * middleware or the render phase. Renders the appropriate status-code
191
+ * page (403.tsx, 404.tsx, etc.) instead of returning a bare empty response.
192
+ *
193
+ * If this function throws, the pipeline falls back to a bare
194
+ * `new Response(null, { status: denyStatus })`.
195
+ */
196
+ renderDenyFallback?: (
197
+ deny: DenySignal,
198
+ req: Request,
199
+ responseHeaders: Headers
200
+ ) => Response | Promise<Response>;
201
+ }
202
+
203
+ // ─── Param Coercion ────────────────────────────────────────────────────────
204
+
205
+ /**
206
+ * Run segment param coercion on the matched route's segments.
207
+ *
208
+ * Loads params.ts modules from segments that have them, extracts the
209
+ * segmentParams definition, and coerces raw string params through codecs.
210
+ * Throws ParamCoercionError if any codec fails (→ 404).
211
+ *
212
+ * This runs BEFORE middleware, so ctx.segmentParams is already typed.
213
+ * See design/07-routing.md §"Where Coercion Runs"
214
+ */
215
+ export async function coerceSegmentParams(match: RouteMatch): Promise<void> {
216
+ const segments = match.segments as unknown as import('./route-matcher.js').ManifestSegmentNode[];
217
+
218
+ for (const segment of segments) {
219
+ // Only process segments that have a params.ts convention file
220
+ if (!segment.params) continue;
221
+
222
+ let mod: Record<string, unknown>;
223
+ try {
224
+ mod = await loadModule(segment.params);
225
+ } catch (err) {
226
+ throw new ParamCoercionError(
227
+ `Failed to load params module for segment "${segment.segmentName}": ${err instanceof Error ? err.message : String(err)}`
228
+ );
229
+ }
230
+
231
+ const segmentParamsDef = mod.segmentParams as
232
+ | { parse(raw: Record<string, string | string[]>): Record<string, unknown> }
233
+ | undefined;
234
+
235
+ if (!segmentParamsDef || typeof segmentParamsDef.parse !== 'function') continue;
236
+
237
+ try {
238
+ const coerced = segmentParamsDef.parse(match.segmentParams);
239
+ // Merge coerced values back — use safeMerge to prevent prototype pollution
240
+ // from malicious/buggy codec output. See TIM-655.
241
+ safeMerge(match.segmentParams, coerced as Record<string, unknown>);
242
+ } catch (err) {
243
+ throw new ParamCoercionError(err instanceof Error ? err.message : String(err));
244
+ }
245
+ }
150
246
  }
151
247
 
152
248
  // ─── Pipeline ──────────────────────────────────────────────────────────────
@@ -165,7 +261,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
165
261
  earlyHints,
166
262
  stripTrailingSlash = true,
167
263
  slowRequestMs = 3000,
168
- enableServerTiming = false,
264
+ serverTiming = 'total',
169
265
  onPipelineError,
170
266
  } = config;
171
267
 
@@ -186,7 +282,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
186
282
  const traceIdValue = generateTraceId();
187
283
 
188
284
  return runWithTraceId(traceIdValue, async () => {
189
- // Establish request context ALS scope so headers() and cookies() work
285
+ // Establish request context ALS scope so getHeaders() and getCookies() work
190
286
  // throughout the entire request lifecycle (proxy, middleware, render).
191
287
  return runWithRequestContext(req, async () => {
192
288
  // In dev mode, wrap with timing collector for Server-Timing header.
@@ -216,25 +312,25 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
216
312
  // DevSpanProcessor reads this for tree/summary output.
217
313
  await setSpanAttribute('http.response.status_code', result.status);
218
314
 
219
- // Append Server-Timing header.
220
- // In dev mode: detailed per-phase breakdown (proxy, middleware, render).
221
- // In production: single total duration — safe to expose, no phase names.
315
+ // Append Server-Timing header based on configured mode.
222
316
  // Response.redirect() creates immutable headers, so we must
223
317
  // ensure mutability before writing Server-Timing.
224
- if (enableServerTiming) {
225
- const serverTiming = getServerTimingHeader();
226
- if (serverTiming) {
318
+ if (serverTiming === 'detailed') {
319
+ // Detailed: per-phase breakdown (proxy, middleware, render).
320
+ const timingHeader = getServerTimingHeader();
321
+ if (timingHeader) {
227
322
  result = ensureMutableResponse(result);
228
- result.headers.set('Server-Timing', serverTiming);
323
+ result.headers.set('Server-Timing', timingHeader);
229
324
  }
230
- } else {
231
- // Production: emit total request duration only.
232
- // No phase breakdown prevents information disclosure
233
- // while giving browser DevTools useful timing data.
325
+ } else if (serverTiming === 'total') {
326
+ // Total only: single `total;dur=N` no phase names.
327
+ // Prevents information disclosure while giving browser
328
+ // DevTools useful timing data.
234
329
  const totalMs = Math.round(performance.now() - startTime);
235
330
  result = ensureMutableResponse(result);
236
331
  result.headers.set('Server-Timing', `total;dur=${totalMs}`);
237
332
  }
333
+ // serverTiming === false: no header at all
238
334
 
239
335
  return result;
240
336
  }
@@ -254,7 +350,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
254
350
  return response;
255
351
  };
256
352
 
257
- return enableServerTiming ? runWithTimingCollector(runRequest) : runRequest();
353
+ return serverTiming === 'detailed' ? runWithTimingCollector(runRequest) : runRequest();
258
354
  });
259
355
  });
260
356
  };
@@ -272,7 +368,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
272
368
  }
273
369
  const proxyFn = () => runProxy(proxyExport, req, () => handleRequest(req, method, path));
274
370
  return await withSpan('timber.proxy', {}, () =>
275
- enableServerTiming ? withTiming('proxy', 'proxy.ts', proxyFn) : proxyFn()
371
+ serverTiming === 'detailed' ? withTiming('proxy', 'proxy.ts', proxyFn) : proxyFn()
276
372
  );
277
373
  } catch (error) {
278
374
  // Uncaught proxy.ts error → bare HTTP 500
@@ -283,6 +379,24 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
283
379
  }
284
380
  }
285
381
 
382
+ /**
383
+ * Build a redirect Response from a RedirectSignal.
384
+ *
385
+ * For RSC payload requests (client navigation), returns 204 + X-Timber-Redirect
386
+ * so the client router can perform a soft SPA redirect. A raw 302 would be
387
+ * turned into an opaque redirect by fetch({redirect:'manual'}), crashing
388
+ * createFromFetch. See design/19-client-navigation.md.
389
+ */
390
+ function buildRedirectResponse(signal: RedirectSignal, req: Request, headers: Headers): Response {
391
+ const isRsc = (req.headers.get('Accept') ?? '').includes('text/x-component');
392
+ if (isRsc) {
393
+ headers.set('X-Timber-Redirect', signal.location);
394
+ return new Response(null, { status: 204, headers });
395
+ }
396
+ headers.set('Location', signal.location);
397
+ return new Response(null, { status: signal.status, headers });
398
+ }
399
+
286
400
  async function handleRequest(req: Request, method: string, path: string): Promise<Response> {
287
401
  // Stage 1: URL canonicalization
288
402
  const url = new URL(req.url);
@@ -306,7 +420,7 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
306
420
  return await serveStaticMetadataFile(metaMatch);
307
421
  }
308
422
 
309
- const mod = (await metaMatch.file.load()) as { default?: Function };
423
+ const mod = await loadModule<{ default?: Function }>(metaMatch.file);
310
424
  if (typeof mod.default !== 'function') {
311
425
  return new Response('Metadata route must export a default function', { status: 500 });
312
426
  }
@@ -339,6 +453,36 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
339
453
  }
340
454
  }
341
455
 
456
+ // Stage 1b.2: Auto-generated sitemap — serves /sitemap.xml and /sitemap/N.xml
457
+ // when sitemap generation is enabled and no user-authored sitemap exists.
458
+ // Runs after metadata route matching so user sitemaps always take precedence.
459
+ // See design/16-metadata.md §"Auto-generated Sitemap"
460
+ if (config.autoSitemapHandler) {
461
+ try {
462
+ const sitemapResponse = await config.autoSitemapHandler(canonicalPathname);
463
+ if (sitemapResponse) return sitemapResponse;
464
+ } catch (error) {
465
+ logRenderError({ method, path, error });
466
+ if (onPipelineError && error instanceof Error) onPipelineError(error, 'auto-sitemap');
467
+ return new Response(null, { status: 500 });
468
+ }
469
+ }
470
+
471
+ // Stage 1c: Version skew detection (TIM-446).
472
+ // For RSC payload requests (client navigation), check if the client's
473
+ // deployment ID matches the current build. On mismatch, signal the
474
+ // client to do a full page reload instead of returning an RSC payload
475
+ // that references mismatched module IDs.
476
+ const isRscRequest = (req.headers.get('Accept') ?? '').includes('text/x-component');
477
+ if (isRscRequest) {
478
+ const skewCheck = checkVersionSkew(req);
479
+ if (!skewCheck.ok) {
480
+ const reloadHeaders = new Headers();
481
+ applyReloadHeaders(reloadHeaders);
482
+ return new Response(null, { status: 204, headers: reloadHeaders });
483
+ }
484
+ }
485
+
342
486
  // Stage 2: Route matching
343
487
  let match = matchRoute(canonicalPathname);
344
488
  let interception: InterceptionContext | undefined;
@@ -397,18 +541,57 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
397
541
  }
398
542
  }
399
543
 
400
- // Stage 3: Leaf middleware.ts (only the leaf route's middleware runs)
401
- if (match.middleware) {
544
+ // Stage 2c: Param coercion (before middleware)
545
+ // Load params.ts modules from matched segments and coerce raw string
546
+ // params through defineSegmentParams codecs. Coercion failure → 404
547
+ // (middleware never runs). See design/07-routing.md §"Where Coercion Runs"
548
+ try {
549
+ await coerceSegmentParams(match);
550
+ } catch (error) {
551
+ if (error instanceof ParamCoercionError) {
552
+ // For API routes (route.ts), return a bare 404 — not an HTML page.
553
+ // API consumers expect JSON/empty responses, not rendered HTML.
554
+ const leafSegment = match.segments[match.segments.length - 1];
555
+ if (
556
+ (leafSegment as { route?: unknown }).route &&
557
+ !(leafSegment as { page?: unknown }).page
558
+ ) {
559
+ return new Response(null, { status: 404 });
560
+ }
561
+ // Route through the app's 404 page (404.tsx in root layout) instead of
562
+ // returning a bare empty 404 Response. Falls back to bare 404 only if
563
+ // no renderNoMatch renderer is configured.
564
+ if (config.renderNoMatch) {
565
+ return config.renderNoMatch(req, responseHeaders);
566
+ }
567
+ return new Response(null, { status: 404 });
568
+ }
569
+ throw error;
570
+ }
571
+
572
+ // Store coerced segment params in ALS so components can access them
573
+ // via getSegmentParams() instead of receiving them as a prop.
574
+ // See design/07-routing.md §"params.ts — Convention File for Typed Params"
575
+ setSegmentParams(match.segmentParams);
576
+
577
+ // Stage 3: Middleware chain (root-to-leaf, short-circuits on first Response)
578
+ if (match.middlewareChain.length > 0) {
402
579
  const ctx: MiddlewareContext = {
403
580
  req,
404
581
  requestHeaders: requestHeaderOverlay,
405
582
  headers: responseHeaders,
406
- params: match.params,
407
- searchParams: new URL(req.url).searchParams,
583
+ segmentParams: match.segmentParams,
408
584
  earlyHints: (hints) => {
409
585
  for (const hint of hints) {
410
- let value = `<${hint.href}>; rel=${hint.rel}`;
411
- if (hint.as !== undefined) value += `; as=${hint.as}`;
586
+ // Match Cloudflare's cached Early Hints attribute order: `as` before `rel`.
587
+ // Cloudflare caches Link headers and re-emits them on subsequent 200s.
588
+ // If our order differs, the browser sees duplicate preloads and warns.
589
+ let value: string;
590
+ if (hint.as !== undefined) {
591
+ value = `<${hint.href}>; as=${hint.as}; rel=${hint.rel}`;
592
+ } else {
593
+ value = `<${hint.href}>; rel=${hint.rel}`;
594
+ }
412
595
  if (hint.crossOrigin !== undefined) value += `; crossorigin=${hint.crossOrigin}`;
413
596
  if (hint.fetchPriority !== undefined) value += `; fetchpriority=${hint.fetchPriority}`;
414
597
  responseHeaders.append('Link', value);
@@ -419,9 +602,9 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
419
602
  try {
420
603
  // Enable cookie mutation during middleware (design/29-cookies.md §"Context Tracking")
421
604
  setMutableCookieContext(true);
422
- const middlewareFn = () => runMiddleware(match.middleware!, ctx);
605
+ const chainFn = () => runMiddlewareChain(match.middlewareChain, ctx);
423
606
  const middlewareResponse = await withSpan('timber.middleware', {}, () =>
424
- enableServerTiming ? withTiming('mw', 'middleware.ts', middlewareFn) : middlewareFn()
607
+ serverTiming === 'detailed' ? withTiming('mw', 'middleware.ts', chainFn) : chainFn()
425
608
  );
426
609
  setMutableCookieContext(false);
427
610
  if (middlewareResponse) {
@@ -430,32 +613,43 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
430
613
  // mutability before appending Set-Cookie entries.
431
614
  const finalResponse = ensureMutableResponse(middlewareResponse);
432
615
  applyCookieJar(finalResponse.headers);
616
+ // Merge parent-set responseHeaders onto the short-circuit response.
617
+ // Child-set headers take precedence — only add headers not already present.
618
+ // Snapshot existing keys first so multi-value headers (Set-Cookie, Link)
619
+ // from the parent are all appended when the child didn't set that key.
620
+ const existingKeys = new Set(
621
+ [...finalResponse.headers.keys()].map((k) => k.toLowerCase())
622
+ );
623
+ for (const [key, value] of responseHeaders.entries()) {
624
+ if (!existingKeys.has(key.toLowerCase())) {
625
+ finalResponse.headers.append(key, value);
626
+ }
627
+ }
433
628
  logMiddlewareShortCircuit({ method, path, status: finalResponse.status });
434
629
  return finalResponse;
435
630
  }
436
- // Middleware succeeded without short-circuiting — apply any
437
- // injected request headers so headers() returns them downstream.
631
+ // Middleware chain completed without short-circuiting — apply any
632
+ // injected request headers so getHeaders() returns them downstream.
438
633
  applyRequestHeaderOverlay(requestHeaderOverlay);
439
634
  } catch (error) {
440
635
  setMutableCookieContext(false);
441
- // RedirectSignal from middleware → HTTP redirect (not an error).
442
- // For RSC payload requests (client navigation), return 204 + X-Timber-Redirect
443
- // so the client router can perform a soft SPA redirect. A raw 302 would be
444
- // turned into an opaque redirect by fetch({redirect:'manual'}), crashing
445
- // createFromFetch. See design/19-client-navigation.md.
636
+ // RedirectSignal from middleware → HTTP redirect (not an error)
446
637
  if (error instanceof RedirectSignal) {
447
638
  applyCookieJar(responseHeaders);
448
- const isRsc = (req.headers.get('Accept') ?? '').includes('text/x-component');
449
- if (isRsc) {
450
- responseHeaders.set('X-Timber-Redirect', error.location);
451
- return new Response(null, { status: 204, headers: responseHeaders });
452
- }
453
- responseHeaders.set('Location', error.location);
454
- return new Response(null, { status: error.status, headers: responseHeaders });
639
+ return buildRedirectResponse(error, req, responseHeaders);
455
640
  }
456
- // DenySignal from middleware → HTTP deny status
641
+ // DenySignal from middleware → render deny page with correct status code.
642
+ // Previously returned bare Response(null) — now renders 403.tsx etc.
457
643
  if (error instanceof DenySignal) {
458
- return new Response(null, { status: error.status });
644
+ applyCookieJar(responseHeaders);
645
+ if (config.renderDenyFallback) {
646
+ try {
647
+ return await config.renderDenyFallback(error, req, responseHeaders);
648
+ } catch {
649
+ // Deny page rendering failed — fall through to bare response
650
+ }
651
+ }
652
+ return new Response(null, { status: error.status, headers: responseHeaders });
459
653
  }
460
654
  // Middleware throw → HTTP 500 (middleware runs before rendering,
461
655
  // no error boundary to catch it)
@@ -476,28 +670,29 @@ export function createPipeline(config: PipelineConfig): (req: Request) => Promis
476
670
  const renderFn = () =>
477
671
  render(req, match, responseHeaders, requestHeaderOverlay, interception);
478
672
  const response = await withSpan('timber.render', { 'http.route': canonicalPathname }, () =>
479
- enableServerTiming ? withTiming('render', 'RSC + SSR render', renderFn) : renderFn()
673
+ serverTiming === 'detailed'
674
+ ? withTiming('render', 'RSC + SSR render', renderFn)
675
+ : renderFn()
480
676
  );
481
677
  markResponseFlushed();
482
678
  return response;
483
679
  } catch (error) {
484
680
  // DenySignal leaked from render (e.g. notFound() in metadata()).
485
- // Return the deny status code instead of 500.
681
+ // Render the deny page with the correct status code.
486
682
  if (error instanceof DenySignal) {
487
- return new Response(null, { status: error.status });
488
- }
489
- // RedirectSignal leaked from render — honour the redirect.
490
- // For RSC payload requests, return 204 + X-Timber-Redirect so the
491
- // client router can perform a soft SPA redirect (same as middleware path).
492
- if (error instanceof RedirectSignal) {
493
- const isRsc = (req.headers.get('Accept') ?? '').includes('text/x-component');
494
- if (isRsc) {
495
- responseHeaders.set('X-Timber-Redirect', error.location);
496
- return new Response(null, { status: 204, headers: responseHeaders });
683
+ if (config.renderDenyFallback) {
684
+ try {
685
+ return await config.renderDenyFallback(error, req, responseHeaders);
686
+ } catch {
687
+ // Deny page rendering failed fall through to bare response
688
+ }
497
689
  }
498
- responseHeaders.set('Location', error.location);
499
690
  return new Response(null, { status: error.status, headers: responseHeaders });
500
691
  }
692
+ // RedirectSignal leaked from render — honour the redirect
693
+ if (error instanceof RedirectSignal) {
694
+ return buildRedirectResponse(error, req, responseHeaders);
695
+ }
501
696
  logRenderError({ method, path, error });
502
697
  await fireOnRequestError(error, req, 'render');
503
698
  if (onPipelineError && error instanceof Error) onPipelineError(error, 'render');
@@ -532,7 +727,7 @@ async function fireOnRequestError(
532
727
  await callOnRequestError(
533
728
  error,
534
729
  { method: req.method, path: url.pathname, headers: headersObj },
535
- { phase, routePath: url.pathname, routeType: 'page', traceId: traceId() }
730
+ { phase, routePath: url.pathname, routeType: 'page', traceId: getTraceId() }
536
731
  );
537
732
  }
538
733