@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.80

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 (573) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/actions-Dg-ANYHb.js +421 -0
  3. package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
  4. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  5. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  6. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  7. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  8. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  9. package/dist/_chunks/define-C77ScO0m.js +106 -0
  10. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  11. package/dist/_chunks/define-CZqDwhSu.js +199 -0
  12. package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
  13. package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
  14. package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  16. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  17. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  18. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
  20. package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  22. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  24. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  25. package/dist/_chunks/request-context-qMsWgy9C.js +478 -0
  26. package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  28. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  30. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  32. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  34. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  35. package/dist/_chunks/stale-reload-C2plcNtG.js +64 -0
  36. package/dist/_chunks/stale-reload-C2plcNtG.js.map +1 -0
  37. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  38. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  40. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  41. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
  42. package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
  43. package/dist/_chunks/wrappers-_DTmImGt.js +63 -0
  44. package/dist/_chunks/wrappers-_DTmImGt.js.map +1 -0
  45. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  46. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  47. package/dist/adapters/cloudflare-dev.js +73 -0
  48. package/dist/adapters/cloudflare-dev.js.map +1 -0
  49. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  50. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  51. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  52. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  53. package/dist/adapters/cloudflare.d.ts +148 -12
  54. package/dist/adapters/cloudflare.d.ts.map +1 -1
  55. package/dist/adapters/cloudflare.js +135 -11
  56. package/dist/adapters/cloudflare.js.map +1 -1
  57. package/dist/adapters/compress-module.d.ts.map +1 -1
  58. package/dist/adapters/nitro.d.ts +17 -1
  59. package/dist/adapters/nitro.d.ts.map +1 -1
  60. package/dist/adapters/nitro.js +56 -13
  61. package/dist/adapters/nitro.js.map +1 -1
  62. package/dist/cache/cache-api.d.ts +24 -0
  63. package/dist/cache/cache-api.d.ts.map +1 -0
  64. package/dist/cache/handler-store.d.ts +31 -0
  65. package/dist/cache/handler-store.d.ts.map +1 -0
  66. package/dist/cache/index.d.ts +23 -7
  67. package/dist/cache/index.d.ts.map +1 -1
  68. package/dist/cache/index.js +142 -80
  69. package/dist/cache/index.js.map +1 -1
  70. package/dist/cache/singleflight.d.ts +18 -1
  71. package/dist/cache/singleflight.d.ts.map +1 -1
  72. package/dist/cache/sizeof.d.ts +22 -0
  73. package/dist/cache/sizeof.d.ts.map +1 -0
  74. package/dist/cache/timber-cache.d.ts +1 -1
  75. package/dist/cache/timber-cache.d.ts.map +1 -1
  76. package/dist/cli.d.ts +6 -1
  77. package/dist/cli.d.ts.map +1 -1
  78. package/dist/cli.js +6 -1
  79. package/dist/cli.js.map +1 -1
  80. package/dist/client/browser-dev.d.ts +27 -1
  81. package/dist/client/browser-dev.d.ts.map +1 -1
  82. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  83. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  84. package/dist/client/browser-entry/hmr.d.ts +21 -0
  85. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  86. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  87. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  88. package/dist/client/browser-entry/index.d.ts +30 -0
  89. package/dist/client/browser-entry/index.d.ts.map +1 -0
  90. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  91. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  92. package/dist/client/browser-entry/router-init.d.ts +23 -0
  93. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  94. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  95. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  96. package/dist/client/browser-entry/scroll.d.ts +19 -0
  97. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  98. package/dist/client/error-boundary.d.ts +12 -5
  99. package/dist/client/error-boundary.d.ts.map +1 -1
  100. package/dist/client/error-boundary.js +10 -4
  101. package/dist/client/error-boundary.js.map +1 -1
  102. package/dist/client/error-reconstituter.d.ts +54 -0
  103. package/dist/client/error-reconstituter.d.ts.map +1 -0
  104. package/dist/client/form.d.ts +2 -2
  105. package/dist/client/form.d.ts.map +1 -1
  106. package/dist/client/history.d.ts +19 -4
  107. package/dist/client/history.d.ts.map +1 -1
  108. package/dist/client/index.d.ts +7 -21
  109. package/dist/client/index.d.ts.map +1 -1
  110. package/dist/client/index.js +210 -1017
  111. package/dist/client/index.js.map +1 -1
  112. package/dist/client/internal.d.ts +18 -0
  113. package/dist/client/internal.d.ts.map +1 -0
  114. package/dist/client/internal.js +890 -0
  115. package/dist/client/internal.js.map +1 -0
  116. package/dist/client/link-pending-store.d.ts +63 -0
  117. package/dist/client/link-pending-store.d.ts.map +1 -0
  118. package/dist/client/link.d.ts +90 -32
  119. package/dist/client/link.d.ts.map +1 -1
  120. package/dist/client/nav-link-store.d.ts +36 -0
  121. package/dist/client/nav-link-store.d.ts.map +1 -0
  122. package/dist/client/navigation-api-types.d.ts +90 -0
  123. package/dist/client/navigation-api-types.d.ts.map +1 -0
  124. package/dist/client/navigation-api.d.ts +115 -0
  125. package/dist/client/navigation-api.d.ts.map +1 -0
  126. package/dist/client/navigation-context.d.ts +13 -2
  127. package/dist/client/navigation-context.d.ts.map +1 -1
  128. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  129. package/dist/client/navigation-root.d.ts.map +1 -0
  130. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  131. package/dist/client/router-ref.d.ts +1 -1
  132. package/dist/client/router.d.ts +70 -4
  133. package/dist/client/router.d.ts.map +1 -1
  134. package/dist/client/rsc-fetch.d.ts +38 -3
  135. package/dist/client/rsc-fetch.d.ts.map +1 -1
  136. package/dist/client/segment-cache.d.ts +1 -1
  137. package/dist/client/segment-cache.d.ts.map +1 -1
  138. package/dist/client/segment-outlet.d.ts +63 -0
  139. package/dist/client/segment-outlet.d.ts.map +1 -0
  140. package/dist/client/ssr-data.d.ts +13 -4
  141. package/dist/client/ssr-data.d.ts.map +1 -1
  142. package/dist/client/stale-reload.d.ts +15 -0
  143. package/dist/client/stale-reload.d.ts.map +1 -1
  144. package/dist/client/top-loader.d.ts +5 -5
  145. package/dist/client/top-loader.d.ts.map +1 -1
  146. package/dist/client/use-link-status.d.ts +5 -5
  147. package/dist/client/use-link-status.d.ts.map +1 -1
  148. package/dist/client/use-params.d.ts +6 -4
  149. package/dist/client/use-params.d.ts.map +1 -1
  150. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  151. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  152. package/dist/client/use-query-states.d.ts +1 -1
  153. package/dist/client/use-query-states.d.ts.map +1 -1
  154. package/dist/client/use-router.d.ts +1 -1
  155. package/dist/codec.d.ts +33 -0
  156. package/dist/codec.d.ts.map +1 -0
  157. package/dist/codec.js +2 -0
  158. package/dist/config-types.d.ts +210 -0
  159. package/dist/config-types.d.ts.map +1 -0
  160. package/dist/content/index.d.ts +1 -10
  161. package/dist/content/index.d.ts.map +1 -1
  162. package/dist/content/index.js +0 -2
  163. package/dist/cookies/define-cookie.d.ts +35 -14
  164. package/dist/cookies/define-cookie.d.ts.map +1 -1
  165. package/dist/cookies/index.js +1 -83
  166. package/dist/fonts/css.d.ts +1 -0
  167. package/dist/fonts/css.d.ts.map +1 -1
  168. package/dist/index.d.ts +45 -192
  169. package/dist/index.d.ts.map +1 -1
  170. package/dist/index.js +12296 -11901
  171. package/dist/index.js.map +1 -1
  172. package/dist/plugin-context.d.ts +84 -0
  173. package/dist/plugin-context.d.ts.map +1 -0
  174. package/dist/plugins/adapter-build.d.ts +1 -1
  175. package/dist/plugins/adapter-build.d.ts.map +1 -1
  176. package/dist/plugins/build-manifest.d.ts +2 -2
  177. package/dist/plugins/build-manifest.d.ts.map +1 -1
  178. package/dist/plugins/build-report.d.ts +3 -3
  179. package/dist/plugins/build-report.d.ts.map +1 -1
  180. package/dist/plugins/client-chunks.d.ts +32 -0
  181. package/dist/plugins/client-chunks.d.ts.map +1 -0
  182. package/dist/plugins/content.d.ts +1 -1
  183. package/dist/plugins/content.d.ts.map +1 -1
  184. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  185. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  186. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  187. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  188. package/dist/plugins/dev-logs.d.ts +1 -1
  189. package/dist/plugins/dev-logs.d.ts.map +1 -1
  190. package/dist/plugins/dev-server.d.ts +1 -1
  191. package/dist/plugins/dev-server.d.ts.map +1 -1
  192. package/dist/plugins/entries.d.ts +1 -1
  193. package/dist/plugins/entries.d.ts.map +1 -1
  194. package/dist/plugins/fonts.d.ts +19 -5
  195. package/dist/plugins/fonts.d.ts.map +1 -1
  196. package/dist/plugins/mdx.d.ts +1 -1
  197. package/dist/plugins/mdx.d.ts.map +1 -1
  198. package/dist/plugins/routing.d.ts +1 -1
  199. package/dist/plugins/routing.d.ts.map +1 -1
  200. package/dist/plugins/server-bundle.d.ts.map +1 -1
  201. package/dist/plugins/shims.d.ts +6 -5
  202. package/dist/plugins/shims.d.ts.map +1 -1
  203. package/dist/plugins/static-build.d.ts +4 -4
  204. package/dist/plugins/static-build.d.ts.map +1 -1
  205. package/dist/routing/codegen.d.ts +2 -2
  206. package/dist/routing/codegen.d.ts.map +1 -1
  207. package/dist/routing/index.d.ts +2 -0
  208. package/dist/routing/index.d.ts.map +1 -1
  209. package/dist/routing/index.js +3 -2
  210. package/dist/routing/scanner.d.ts.map +1 -1
  211. package/dist/routing/segment-classify.d.ts +46 -0
  212. package/dist/routing/segment-classify.d.ts.map +1 -0
  213. package/dist/routing/status-file-lint.d.ts +2 -1
  214. package/dist/routing/status-file-lint.d.ts.map +1 -1
  215. package/dist/routing/types.d.ts +16 -4
  216. package/dist/routing/types.d.ts.map +1 -1
  217. package/dist/rsc-runtime/rsc.d.ts +1 -1
  218. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  219. package/dist/rsc-runtime/ssr.d.ts +12 -0
  220. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  221. package/dist/schema-bridge.d.ts +76 -0
  222. package/dist/schema-bridge.d.ts.map +1 -0
  223. package/dist/search-params/define.d.ts +139 -0
  224. package/dist/search-params/define.d.ts.map +1 -0
  225. package/dist/search-params/index.d.ts +4 -7
  226. package/dist/search-params/index.d.ts.map +1 -1
  227. package/dist/search-params/index.js +4 -474
  228. package/dist/search-params/registry.d.ts +2 -2
  229. package/dist/search-params/registry.d.ts.map +1 -1
  230. package/dist/search-params/wrappers.d.ts +53 -0
  231. package/dist/search-params/wrappers.d.ts.map +1 -0
  232. package/dist/segment-params/define.d.ts +78 -0
  233. package/dist/segment-params/define.d.ts.map +1 -0
  234. package/dist/segment-params/index.d.ts +6 -0
  235. package/dist/segment-params/index.d.ts.map +1 -0
  236. package/dist/segment-params/index.js +4 -0
  237. package/dist/server/access-gate.d.ts +4 -0
  238. package/dist/server/access-gate.d.ts.map +1 -1
  239. package/dist/server/action-client.d.ts +12 -1
  240. package/dist/server/action-client.d.ts.map +1 -1
  241. package/dist/server/action-encryption.d.ts +76 -0
  242. package/dist/server/action-encryption.d.ts.map +1 -0
  243. package/dist/server/action-handler.d.ts.map +1 -1
  244. package/dist/server/actions.d.ts +3 -6
  245. package/dist/server/actions.d.ts.map +1 -1
  246. package/dist/server/als-registry.d.ts +32 -4
  247. package/dist/server/als-registry.d.ts.map +1 -1
  248. package/dist/server/build-manifest.d.ts +2 -2
  249. package/dist/server/build-manifest.d.ts.map +1 -1
  250. package/dist/server/debug.d.ts +1 -1
  251. package/dist/server/default-logger.d.ts +22 -0
  252. package/dist/server/default-logger.d.ts.map +1 -0
  253. package/dist/server/deny-page-resolver.d.ts +52 -0
  254. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  255. package/dist/server/deny-renderer.d.ts.map +1 -1
  256. package/dist/server/dev-holding-server.d.ts +52 -0
  257. package/dist/server/dev-holding-server.d.ts.map +1 -0
  258. package/dist/server/dev-warnings.d.ts +1 -21
  259. package/dist/server/dev-warnings.d.ts.map +1 -1
  260. package/dist/server/early-hints.d.ts +13 -5
  261. package/dist/server/early-hints.d.ts.map +1 -1
  262. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  263. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  264. package/dist/server/fallback-error.d.ts +4 -3
  265. package/dist/server/fallback-error.d.ts.map +1 -1
  266. package/dist/server/flight-injection-state.d.ts +66 -0
  267. package/dist/server/flight-injection-state.d.ts.map +1 -0
  268. package/dist/server/flight-scripts.d.ts +42 -0
  269. package/dist/server/flight-scripts.d.ts.map +1 -0
  270. package/dist/server/flush.d.ts.map +1 -1
  271. package/dist/server/form-data.d.ts +29 -0
  272. package/dist/server/form-data.d.ts.map +1 -1
  273. package/dist/server/html-injectors.d.ts +51 -11
  274. package/dist/server/html-injectors.d.ts.map +1 -1
  275. package/dist/server/index.d.ts +6 -43
  276. package/dist/server/index.d.ts.map +1 -1
  277. package/dist/server/index.js +38 -2798
  278. package/dist/server/index.js.map +1 -1
  279. package/dist/server/internal.d.ts +46 -0
  280. package/dist/server/internal.d.ts.map +1 -0
  281. package/dist/server/internal.js +2883 -0
  282. package/dist/server/internal.js.map +1 -0
  283. package/dist/server/logger.d.ts +25 -7
  284. package/dist/server/logger.d.ts.map +1 -1
  285. package/dist/server/middleware-runner.d.ts +19 -4
  286. package/dist/server/middleware-runner.d.ts.map +1 -1
  287. package/dist/server/node-stream-transforms.d.ts +113 -0
  288. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  289. package/dist/server/page-deny-boundary.d.ts +31 -0
  290. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  291. package/dist/server/pipeline-interception.d.ts +1 -1
  292. package/dist/server/pipeline-interception.d.ts.map +1 -1
  293. package/dist/server/pipeline-metadata.d.ts +6 -0
  294. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  295. package/dist/server/pipeline.d.ts +42 -10
  296. package/dist/server/pipeline.d.ts.map +1 -1
  297. package/dist/server/primitives.d.ts +69 -18
  298. package/dist/server/primitives.d.ts.map +1 -1
  299. package/dist/server/render-timeout.d.ts +51 -0
  300. package/dist/server/render-timeout.d.ts.map +1 -0
  301. package/dist/server/request-context.d.ts +112 -43
  302. package/dist/server/request-context.d.ts.map +1 -1
  303. package/dist/server/route-element-builder.d.ts +27 -1
  304. package/dist/server/route-element-builder.d.ts.map +1 -1
  305. package/dist/server/route-handler.d.ts.map +1 -1
  306. package/dist/server/route-matcher.d.ts +9 -2
  307. package/dist/server/route-matcher.d.ts.map +1 -1
  308. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  309. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  310. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  311. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  312. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  313. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  314. package/dist/server/rsc-entry/index.d.ts +8 -3
  315. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  316. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  317. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  318. package/dist/server/rsc-entry/rsc-stream.d.ts +4 -1
  319. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  320. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  321. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  322. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  323. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  324. package/dist/server/safe-load.d.ts +46 -0
  325. package/dist/server/safe-load.d.ts.map +1 -0
  326. package/dist/server/sitemap-generator.d.ts +129 -0
  327. package/dist/server/sitemap-generator.d.ts.map +1 -0
  328. package/dist/server/sitemap-handler.d.ts +22 -0
  329. package/dist/server/sitemap-handler.d.ts.map +1 -0
  330. package/dist/server/slot-resolver.d.ts +1 -1
  331. package/dist/server/slot-resolver.d.ts.map +1 -1
  332. package/dist/server/ssr-entry.d.ts +22 -0
  333. package/dist/server/ssr-entry.d.ts.map +1 -1
  334. package/dist/server/ssr-render.d.ts +39 -21
  335. package/dist/server/ssr-render.d.ts.map +1 -1
  336. package/dist/server/ssr-wrappers.d.ts +50 -0
  337. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  338. package/dist/server/status-code-resolver.d.ts +1 -1
  339. package/dist/server/status-code-resolver.d.ts.map +1 -1
  340. package/dist/server/stream-utils.d.ts +36 -0
  341. package/dist/server/stream-utils.d.ts.map +1 -0
  342. package/dist/server/tracing.d.ts +4 -4
  343. package/dist/server/tracing.d.ts.map +1 -1
  344. package/dist/server/tree-builder.d.ts +22 -19
  345. package/dist/server/tree-builder.d.ts.map +1 -1
  346. package/dist/server/types.d.ts +1 -4
  347. package/dist/server/types.d.ts.map +1 -1
  348. package/dist/server/version-skew.d.ts +61 -0
  349. package/dist/server/version-skew.d.ts.map +1 -0
  350. package/dist/shared/merge-search-params.d.ts +22 -0
  351. package/dist/shared/merge-search-params.d.ts.map +1 -0
  352. package/dist/shims/font-google.d.ts +1 -1
  353. package/dist/shims/font-google.d.ts.map +1 -1
  354. package/dist/shims/font-google.js +42 -0
  355. package/dist/shims/font-google.js.map +1 -0
  356. package/dist/shims/font-local.d.ts +26 -0
  357. package/dist/shims/font-local.d.ts.map +1 -0
  358. package/dist/shims/font-local.js +20 -0
  359. package/dist/shims/font-local.js.map +1 -0
  360. package/dist/shims/headers.d.ts +2 -1
  361. package/dist/shims/headers.d.ts.map +1 -1
  362. package/dist/shims/navigation-client.d.ts +1 -1
  363. package/dist/shims/navigation-client.d.ts.map +1 -1
  364. package/dist/shims/navigation.d.ts +3 -2
  365. package/dist/shims/navigation.d.ts.map +1 -1
  366. package/dist/utils/directive-parser.d.ts +5 -2
  367. package/dist/utils/directive-parser.d.ts.map +1 -1
  368. package/dist/utils/state-machine.d.ts +80 -0
  369. package/dist/utils/state-machine.d.ts.map +1 -0
  370. package/package.json +53 -23
  371. package/src/adapters/cloudflare-dev.ts +177 -0
  372. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  373. package/src/adapters/cloudflare.ts +342 -28
  374. package/src/adapters/compress-module.ts +24 -4
  375. package/src/adapters/nitro.ts +52 -8
  376. package/src/adapters/wrangler.d.ts +7 -0
  377. package/src/cache/cache-api.ts +38 -0
  378. package/src/cache/handler-store.ts +68 -0
  379. package/src/cache/index.ts +81 -18
  380. package/src/cache/singleflight.ts +62 -4
  381. package/src/cache/sizeof.ts +31 -0
  382. package/src/cache/timber-cache.ts +24 -20
  383. package/src/cli.ts +6 -1
  384. package/src/client/browser-dev.ts +128 -1
  385. package/src/client/browser-entry/action-dispatch.ts +116 -0
  386. package/src/client/browser-entry/hmr.ts +81 -0
  387. package/src/client/browser-entry/hydrate.ts +145 -0
  388. package/src/client/browser-entry/index.ts +138 -0
  389. package/src/client/browser-entry/post-hydration.ts +119 -0
  390. package/src/client/browser-entry/router-init.ts +193 -0
  391. package/src/client/browser-entry/rsc-stream.ts +157 -0
  392. package/src/client/browser-entry/scroll.ts +27 -0
  393. package/src/client/error-boundary.tsx +48 -16
  394. package/src/client/error-reconstituter.tsx +65 -0
  395. package/src/client/form.tsx +2 -2
  396. package/src/client/history.ts +26 -4
  397. package/src/client/index.ts +19 -38
  398. package/src/client/internal.ts +57 -0
  399. package/src/client/link-pending-store.ts +111 -0
  400. package/src/client/link.tsx +329 -97
  401. package/src/client/nav-link-store.ts +47 -0
  402. package/src/client/navigation-api-types.ts +112 -0
  403. package/src/client/navigation-api.ts +332 -0
  404. package/src/client/navigation-context.ts +31 -6
  405. package/src/client/navigation-root.tsx +342 -0
  406. package/src/client/nuqs-adapter.tsx +16 -3
  407. package/src/client/router-ref.ts +1 -1
  408. package/src/client/router.ts +299 -72
  409. package/src/client/rsc-fetch.ts +97 -8
  410. package/src/client/segment-cache.ts +1 -1
  411. package/src/client/segment-outlet.tsx +86 -0
  412. package/src/client/ssr-data.ts +13 -5
  413. package/src/client/stale-reload.ts +72 -3
  414. package/src/client/top-loader.tsx +16 -8
  415. package/src/client/use-link-status.ts +7 -7
  416. package/src/client/use-params.ts +7 -5
  417. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  418. package/src/client/use-query-states.ts +3 -3
  419. package/src/client/use-router.ts +1 -1
  420. package/src/codec.ts +49 -0
  421. package/src/config-types.ts +208 -0
  422. package/src/content/index.ts +5 -13
  423. package/src/cookies/define-cookie.ts +78 -25
  424. package/src/cookies/index.ts +8 -0
  425. package/src/fonts/css.ts +2 -1
  426. package/src/index.ts +258 -354
  427. package/src/plugin-context.ts +200 -0
  428. package/src/plugins/adapter-build.ts +8 -2
  429. package/src/plugins/build-manifest.ts +13 -2
  430. package/src/plugins/build-report.ts +3 -3
  431. package/src/plugins/client-chunks.ts +65 -0
  432. package/src/plugins/content.ts +1 -1
  433. package/src/plugins/dev-browser-logs.ts +288 -0
  434. package/src/plugins/dev-error-overlay.ts +70 -1
  435. package/src/plugins/dev-logs.ts +1 -1
  436. package/src/plugins/dev-server.ts +70 -9
  437. package/src/plugins/entries.ts +71 -10
  438. package/src/plugins/fonts.ts +168 -61
  439. package/src/plugins/mdx.ts +1 -1
  440. package/src/plugins/routing.ts +57 -17
  441. package/src/plugins/server-action-exports.ts +1 -1
  442. package/src/plugins/server-bundle.ts +32 -1
  443. package/src/plugins/shims.ts +135 -35
  444. package/src/plugins/static-build.ts +17 -11
  445. package/src/routing/codegen.ts +165 -105
  446. package/src/routing/index.ts +2 -0
  447. package/src/routing/scanner.ts +93 -23
  448. package/src/routing/segment-classify.ts +89 -0
  449. package/src/routing/status-file-lint.ts +3 -2
  450. package/src/routing/types.ts +17 -4
  451. package/src/rsc-runtime/rsc.ts +2 -0
  452. package/src/rsc-runtime/ssr.ts +50 -0
  453. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  454. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  455. package/src/search-params/define.ts +482 -0
  456. package/src/search-params/index.ts +14 -20
  457. package/src/search-params/registry.ts +2 -2
  458. package/src/search-params/wrappers.ts +85 -0
  459. package/src/segment-params/define.ts +279 -0
  460. package/src/segment-params/index.ts +29 -0
  461. package/src/server/access-gate.tsx +70 -29
  462. package/src/server/action-client.ts +21 -2
  463. package/src/server/action-encryption.ts +144 -0
  464. package/src/server/action-handler.ts +21 -4
  465. package/src/server/actions.ts +10 -9
  466. package/src/server/als-registry.ts +34 -6
  467. package/src/server/build-manifest.ts +10 -4
  468. package/src/server/compress.ts +25 -7
  469. package/src/server/debug.ts +1 -1
  470. package/src/server/default-logger.ts +99 -0
  471. package/src/server/deny-page-resolver.ts +154 -0
  472. package/src/server/deny-renderer.ts +24 -38
  473. package/src/server/dev-holding-server.ts +185 -0
  474. package/src/server/dev-warnings.ts +4 -49
  475. package/src/server/early-hints.ts +36 -15
  476. package/src/server/error-boundary-wrapper.ts +74 -22
  477. package/src/server/fallback-error.ts +31 -15
  478. package/src/server/flight-injection-state.ts +113 -0
  479. package/src/server/flight-scripts.ts +62 -0
  480. package/src/server/flush.ts +2 -1
  481. package/src/server/form-data.ts +76 -0
  482. package/src/server/html-injectors.ts +280 -120
  483. package/src/server/index.ts +26 -177
  484. package/src/server/internal.ts +169 -0
  485. package/src/server/logger.ts +44 -36
  486. package/src/server/middleware-runner.ts +31 -4
  487. package/src/server/node-stream-transforms.ts +509 -0
  488. package/src/server/page-deny-boundary.tsx +56 -0
  489. package/src/server/pipeline-interception.ts +17 -16
  490. package/src/server/pipeline-metadata.ts +13 -0
  491. package/src/server/pipeline.ts +227 -62
  492. package/src/server/primitives.ts +111 -28
  493. package/src/server/render-timeout.ts +108 -0
  494. package/src/server/request-context.ts +293 -132
  495. package/src/server/route-element-builder.ts +283 -191
  496. package/src/server/route-handler.ts +24 -4
  497. package/src/server/route-matcher.ts +24 -20
  498. package/src/server/rsc-entry/api-handler.ts +15 -16
  499. package/src/server/rsc-entry/error-renderer.ts +300 -89
  500. package/src/server/rsc-entry/helpers.ts +134 -5
  501. package/src/server/rsc-entry/index.ts +200 -112
  502. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  503. package/src/server/rsc-entry/rsc-stream.ts +65 -13
  504. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  505. package/src/server/rsc-entry/ssr-renderer.ts +168 -38
  506. package/src/server/safe-load.ts +60 -0
  507. package/src/server/sitemap-generator.ts +338 -0
  508. package/src/server/sitemap-handler.ts +126 -0
  509. package/src/server/slot-resolver.ts +244 -229
  510. package/src/server/ssr-entry.ts +211 -32
  511. package/src/server/ssr-render.ts +289 -67
  512. package/src/server/ssr-wrappers.tsx +139 -0
  513. package/src/server/status-code-resolver.ts +1 -1
  514. package/src/server/stream-utils.ts +213 -0
  515. package/src/server/tracing.ts +20 -9
  516. package/src/server/tree-builder.ts +92 -58
  517. package/src/server/types.ts +3 -6
  518. package/src/server/version-skew.ts +104 -0
  519. package/src/shared/merge-search-params.ts +55 -0
  520. package/src/shims/font-google.ts +1 -1
  521. package/src/shims/font-local.ts +34 -0
  522. package/src/shims/headers.ts +5 -1
  523. package/src/shims/navigation-client.ts +1 -1
  524. package/src/shims/navigation.ts +7 -2
  525. package/src/utils/directive-parser.ts +5 -2
  526. package/src/utils/state-machine.ts +111 -0
  527. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  528. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  529. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  530. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  531. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  532. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  533. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  534. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  535. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  536. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  537. package/dist/cache/register-cached-function.d.ts +0 -17
  538. package/dist/cache/register-cached-function.d.ts.map +0 -1
  539. package/dist/client/browser-entry.d.ts +0 -21
  540. package/dist/client/browser-entry.d.ts.map +0 -1
  541. package/dist/client/link-status-provider.d.ts +0 -11
  542. package/dist/client/link-status-provider.d.ts.map +0 -1
  543. package/dist/client/transition-root.d.ts.map +0 -1
  544. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  545. package/dist/cookies/index.js.map +0 -1
  546. package/dist/plugins/cache-transform.d.ts +0 -36
  547. package/dist/plugins/cache-transform.d.ts.map +0 -1
  548. package/dist/plugins/dynamic-transform.d.ts +0 -72
  549. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  550. package/dist/search-params/analyze.d.ts +0 -54
  551. package/dist/search-params/analyze.d.ts.map +0 -1
  552. package/dist/search-params/builtin-codecs.d.ts +0 -105
  553. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  554. package/dist/search-params/codecs.d.ts +0 -53
  555. package/dist/search-params/codecs.d.ts.map +0 -1
  556. package/dist/search-params/create.d.ts +0 -106
  557. package/dist/search-params/create.d.ts.map +0 -1
  558. package/dist/search-params/index.js.map +0 -1
  559. package/dist/server/prerender.d.ts +0 -77
  560. package/dist/server/prerender.d.ts.map +0 -1
  561. package/dist/server/response-cache.d.ts +0 -54
  562. package/dist/server/response-cache.d.ts.map +0 -1
  563. package/src/cache/register-cached-function.ts +0 -103
  564. package/src/client/browser-entry.ts +0 -678
  565. package/src/client/link-status-provider.tsx +0 -30
  566. package/src/client/transition-root.tsx +0 -166
  567. package/src/plugins/cache-transform.ts +0 -199
  568. package/src/plugins/dynamic-transform.ts +0 -161
  569. package/src/search-params/analyze.ts +0 -192
  570. package/src/search-params/builtin-codecs.ts +0 -228
  571. package/src/search-params/create.ts +0 -321
  572. package/src/server/prerender.ts +0 -139
  573. package/src/server/response-cache.ts +0 -410
@@ -50,14 +50,14 @@ export interface ManifestSegmentNode {
50
50
  middleware?: ManifestFile;
51
51
  access?: ManifestFile;
52
52
  route?: ManifestFile;
53
+ /** params.ts — isomorphic convention file for segmentParams + searchParams definitions. */
54
+ params?: ManifestFile;
53
55
  error?: ManifestFile;
54
56
  default?: ManifestFile;
55
57
  denied?: ManifestFile;
56
- searchParams?: ManifestFile;
57
58
  statusFiles?: Record<string, ManifestFile>;
58
59
  jsonStatusFiles?: Record<string, ManifestFile>;
59
60
  legacyStatusFiles?: Record<string, ManifestFile>;
60
- prerender?: ManifestFile;
61
61
  /** Metadata route files (sitemap.ts, robots.ts, icon.tsx, etc.) keyed by base name */
62
62
  metadataRoutes?: Record<string, ManifestFile>;
63
63
 
@@ -69,6 +69,13 @@ export interface ManifestSegmentNode {
69
69
  export interface ManifestRoot {
70
70
  root: ManifestSegmentNode;
71
71
  proxy?: ManifestFile;
72
+ /**
73
+ * Global error page: app/global-error.{tsx,ts,jsx,js}
74
+ * Tier 2 — standalone full-page replacement (no layouts) when no
75
+ * segment-level error file is found. SSR-only render.
76
+ * See design/10-error-handling.md §"Tier 2"
77
+ */
78
+ globalError?: ManifestFile;
72
79
  }
73
80
 
74
81
  // ─── Matcher ──────────────────────────────────────────────────────────────
@@ -102,30 +109,27 @@ function matchPathname(root: ManifestSegmentNode, pathname: string): RouteMatch
102
109
  const matched = matchSegments(root, parts, 0, segments, params);
103
110
  if (!matched) return null;
104
111
 
105
- // Convert ManifestSegmentNodes to the SegmentNode shape expected by RouteMatch.
106
- // The pipeline and tree builder use SegmentNode which has RouteFile references,
107
- // but we pass the manifest nodes directly — they're structurally compatible
108
- // for the fields the pipeline cares about (segments array + params).
109
- // Resolve the leaf segment's middleware.ts if present.
110
- // Only the leaf route's middleware runs — no chain, no inheritance.
111
- const leafSegment = segments[segments.length - 1];
112
- let middleware: MiddlewareFn | undefined;
113
- if (leafSegment?.middleware) {
114
- const loader = leafSegment.middleware.load;
115
- middleware = async (ctx) => {
116
- const mod = (await loader()) as { default?: MiddlewareFn };
117
- if (mod.default) {
118
- return mod.default(ctx);
119
- }
120
- };
112
+ // Collect middleware from all segments in the chain, root to leaf.
113
+ // Each middleware is lazy-loaded via dynamic import on first invocation.
114
+ const middlewareChain: MiddlewareFn[] = [];
115
+ for (const segment of segments) {
116
+ if (segment.middleware) {
117
+ const loader = segment.middleware.load;
118
+ middlewareChain.push(async (ctx) => {
119
+ const mod = (await loader()) as { default?: MiddlewareFn };
120
+ if (mod.default) {
121
+ return mod.default(ctx);
122
+ }
123
+ });
124
+ }
121
125
  }
122
126
 
123
127
  return {
124
128
  // The pipeline uses segments as opaque objects passed to the renderer.
125
129
  // Cast is safe — the renderer receives what the manifest provides.
126
130
  segments: segments as unknown as RouteMatch['segments'],
127
- params,
128
- middleware,
131
+ segmentParams: params,
132
+ middlewareChain,
129
133
  };
130
134
  }
131
135
 
@@ -6,13 +6,14 @@
6
6
  * See design/04-authorization.md §"Auth in API Routes".
7
7
  */
8
8
 
9
- import { withSpan, setSpanAttribute } from '#/server/tracing.js';
10
- import type { ManifestSegmentNode } from '#/server/route-matcher.js';
11
- import type { RouteMatch } from '#/server/pipeline.js';
12
- import { DenySignal, RedirectSignal } from '#/server/primitives.js';
13
- import { handleRouteRequest } from '#/server/route-handler.js';
14
- import type { RouteModule } from '#/server/route-handler.js';
15
- import type { RouteContext } from '#/server/types.js';
9
+ import { withSpan, setSpanAttribute } from '../tracing.js';
10
+ import type { ManifestSegmentNode } from '../route-matcher.js';
11
+ import { loadModule } from '../safe-load.js';
12
+ import type { RouteMatch } from '../pipeline.js';
13
+ import { DenySignal, RedirectSignal } from '../primitives.js';
14
+ import { handleRouteRequest } from '../route-handler.js';
15
+ import type { RouteModule } from '../route-handler.js';
16
+ import type { RouteContext } from '../types.js';
16
17
 
17
18
  export async function handleApiRoute(
18
19
  req: Request,
@@ -26,10 +27,8 @@ export async function handleApiRoute(
26
27
  // Each access.ts is independent — deny()/redirect() throws a signal.
27
28
  for (const segment of segments) {
28
29
  if (segment.access) {
29
- const accessMod = (await segment.access.load()) as Record<string, unknown>;
30
- const accessFn = accessMod.default as
31
- | ((ctx: { params: Record<string, string | string[]>; searchParams: unknown }) => unknown)
32
- | undefined;
30
+ const accessMod = await loadModule(segment.access);
31
+ const accessFn = accessMod.default as (() => unknown) | undefined;
33
32
  if (accessFn) {
34
33
  try {
35
34
  await withSpan(
@@ -37,7 +36,7 @@ export async function handleApiRoute(
37
36
  { 'timber.segment': segment.segmentName ?? 'unknown' },
38
37
  async () => {
39
38
  try {
40
- await accessFn({ params: match.params, searchParams: {} });
39
+ await accessFn();
41
40
  await setSpanAttribute('timber.result', 'pass');
42
41
  } catch (error) {
43
42
  if (error instanceof DenySignal) {
@@ -68,10 +67,10 @@ export async function handleApiRoute(
68
67
  }
69
68
 
70
69
  // Load route.ts module and dispatch
71
- const routeMod = (await leaf.route!.load()) as RouteModule;
70
+ const routeMod = await loadModule<RouteModule>(leaf.route!);
72
71
  const ctx: RouteContext = {
73
72
  req,
74
- params: match.params,
73
+ params: match.segmentParams,
75
74
  searchParams: new URL(req.url).searchParams,
76
75
  headers: responseHeaders,
77
76
  };
@@ -90,11 +89,11 @@ async function renderApiDeny(
90
89
  segments: ManifestSegmentNode[],
91
90
  responseHeaders: Headers
92
91
  ): Promise<Response> {
93
- const { resolveManifestStatusFile } = await import('#/server/manifest-status-resolver.js');
92
+ const { resolveManifestStatusFile } = await import('../manifest-status-resolver.js');
94
93
 
95
94
  const resolution = resolveManifestStatusFile(deny.status, segments, 'json');
96
95
  if (resolution) {
97
- const mod = (await resolution.file.load()) as Record<string, unknown>;
96
+ const mod = await loadModule(resolution.file);
98
97
  const jsonContent = mod.default ?? mod;
99
98
  responseHeaders.set('content-type', 'application/json; charset=utf-8');
100
99
  return new Response(JSON.stringify(jsonContent), {
@@ -1,136 +1,347 @@
1
1
  /**
2
2
  * RSC Error & No-Match Renderers — handles error pages and 404s.
3
3
  *
4
- * Renders error.tsx / status files and 404 pages through the RSC → SSR pipeline.
4
+ * All error pages (TSX and MDX) render through the RSC → SSR pipeline:
5
+ * - TSX ('use client'): Error is converted to SerializableError, wrapped
6
+ * with ErrorReconstituter to reconstitute a real Error on the client.
7
+ * - MDX (server component): Receives plain props ({ status }), no wrapper needed.
8
+ *
9
+ * This unified approach replaces the former SSR-only bypass for TSX error
10
+ * pages. See design/spike-TIM-565-unify-error-pages.md for the full analysis.
11
+ *
12
+ * Design docs: 10-error-handling.md §"Three-Tier Error Page Rendering"
5
13
  */
6
14
 
7
15
  import { createElement } from 'react';
8
- import { renderToReadableStream } from '#/rsc-runtime/rsc.js';
9
-
10
- import type { RouteMatch } from '#/server/pipeline.js';
11
- import { logRenderError } from '#/server/logger.js';
12
- import type { ManifestSegmentNode } from '#/server/route-matcher.js';
13
- import { DenySignal, RenderError } from '#/server/primitives.js';
14
- import type { ClientBootstrapConfig } from '#/server/html-injectors.js';
15
- import { renderDenyPage } from '#/server/deny-renderer.js';
16
- import type { LayoutEntry } from '#/server/deny-renderer.js';
17
- import type { NavContext } from '#/server/ssr-entry.js';
18
- import { createDebugChannelSink, parseCookiesFromHeader } from './helpers.js';
16
+ import { renderToReadableStream } from '../../rsc-runtime/rsc.js';
17
+
18
+ import type { RouteMatch } from '../pipeline.js';
19
+ import { logRenderError } from '../logger.js';
20
+ import type { ManifestSegmentNode } from '../route-matcher.js';
21
+ import { DenySignal, RenderError } from '../primitives.js';
22
+ import type { ClientBootstrapConfig } from '../html-injectors.js';
23
+ import { flightInitScript } from '../flight-scripts.js';
24
+ import { renderDenyPage } from '../deny-renderer.js';
25
+ import type { LayoutEntry } from '../deny-renderer.js';
26
+ import type { NavContext } from '../ssr-entry.js';
27
+ import { createDebugChannelSink } from './helpers.js';
28
+ import { getCookiesForSsr } from '../request-context.js';
19
29
  import { callSsr } from './ssr-bridge.js';
30
+ import { teeWithErrorPropagation } from '../stream-utils.js';
31
+ import { isDevMode } from '../debug.js';
32
+ import { ErrorReconstituter } from '../../client/error-reconstituter.js';
33
+ import type { SerializableError } from '../../client/error-reconstituter.js';
34
+ import { loadModule } from '../safe-load.js';
20
35
 
21
36
  /**
22
- * Render an error page for unhandled throws or RenderError outside Suspense.
23
- *
24
- * Walks the segment chain from leaf to root looking for:
25
- * 1. Specific status file (e.g. 503.tsx) matching the error's status
26
- * 2. 5xx.tsx category catch-all
27
- * 3. error.tsx
28
- *
29
- * Renders the found component with { error, digest, reset } props
30
- * wrapped in layouts, with the correct HTTP status code.
37
+ * A manifest file reference with lazy import and path.
38
+ * Mirrors the shape from ManifestSegmentNode but kept local to avoid
39
+ * exporting internal types from route-matcher.
31
40
  */
32
- export async function renderErrorPage(
33
- error: unknown,
34
- status: number,
35
- segments: ManifestSegmentNode[],
36
- layoutComponents: LayoutEntry[],
37
- req: Request,
38
- match: RouteMatch,
39
- responseHeaders: Headers,
40
- clientBootstrap: ClientBootstrapConfig
41
- ): Promise<Response> {
42
- const h = createElement as (...args: unknown[]) => React.ReactElement;
41
+ export interface GlobalErrorFile {
42
+ load: () => Promise<unknown>;
43
+ filePath: string;
44
+ }
43
45
 
44
- // Walk segments from leaf to root to find the error component
45
- let errorComponent: ((...args: unknown[]) => unknown) | null = null;
46
- let foundSegmentIndex = -1;
46
+ /** MDX/markdown extensions server components that need RSC rendering. */
47
+ const MDX_EXTENSIONS = new Set(['.mdx', '.md']);
48
+
49
+ /**
50
+ * Check if a file path ends with an MDX/markdown extension.
51
+ */
52
+ function isMdxFile(filePath: string): boolean {
53
+ const dotIndex = filePath.lastIndexOf('.');
54
+ if (dotIndex === -1) return false;
55
+ return MDX_EXTENSIONS.has(filePath.slice(dotIndex));
56
+ }
47
57
 
58
+ /**
59
+ * Result of walking the segment chain for an error file.
60
+ */
61
+ interface ErrorFileResolution {
62
+ /** The loaded component */
63
+ component: (...args: unknown[]) => unknown;
64
+ /** Index of the segment where the file was found */
65
+ segmentIndex: number;
66
+ /** Whether the file is MDX (server component) */
67
+ isMdx: boolean;
68
+ }
69
+
70
+ /**
71
+ * Walk segments from leaf to root to find the nearest error file.
72
+ *
73
+ * Fallback chain at each segment:
74
+ * 1. Specific status file (e.g., 503.tsx) — exact match
75
+ * 2. 5xx.tsx — category catch-all
76
+ * 3. error.tsx — catches all unmatched errors
77
+ */
78
+ async function resolveErrorFile(
79
+ status: number,
80
+ segments: ManifestSegmentNode[]
81
+ ): Promise<ErrorFileResolution | null> {
48
82
  for (let i = segments.length - 1; i >= 0; i--) {
49
83
  const segment = segments[i];
50
84
 
51
- // Check specific status file (e.g. 503.tsx)
52
85
  if (segment.statusFiles) {
86
+ // Check specific status file (e.g. 503.tsx)
53
87
  const statusKey = String(status);
54
88
  const specificFile = segment.statusFiles[statusKey];
55
89
  if (specificFile) {
56
- const mod = (await specificFile.load()) as Record<string, unknown>;
57
- if (mod.default) {
58
- errorComponent = mod.default as (...args: unknown[]) => unknown;
59
- foundSegmentIndex = i;
60
- break;
90
+ // .catch: if the error page module itself fails to load (syntax error,
91
+ // missing file), fall through to next tier instead of recursive failure.
92
+ // See TIM-584, design/spike-TIM-551-dynamic-import-audit.md §H1.
93
+ const mod = await loadModule(specificFile).catch(() => null);
94
+ if (mod?.default) {
95
+ return {
96
+ component: mod.default as (...args: unknown[]) => unknown,
97
+ segmentIndex: i,
98
+ isMdx: isMdxFile(specificFile.filePath),
99
+ };
61
100
  }
62
101
  }
63
102
 
64
103
  // Check 5xx.tsx category catch-all
65
104
  const categoryFile = segment.statusFiles['5xx'];
66
105
  if (categoryFile && status >= 500 && status <= 599) {
67
- const mod = (await categoryFile.load()) as Record<string, unknown>;
68
- if (mod.default) {
69
- errorComponent = mod.default as (...args: unknown[]) => unknown;
70
- foundSegmentIndex = i;
71
- break;
106
+ const mod = await loadModule(categoryFile).catch(() => null);
107
+ if (mod?.default) {
108
+ return {
109
+ component: mod.default as (...args: unknown[]) => unknown,
110
+ segmentIndex: i,
111
+ isMdx: isMdxFile(categoryFile.filePath),
112
+ };
72
113
  }
73
114
  }
74
115
  }
75
116
 
76
117
  // Check error.tsx
77
118
  if (segment.error) {
78
- const mod = (await segment.error.load()) as Record<string, unknown>;
79
- if (mod.default) {
80
- errorComponent = mod.default as (...args: unknown[]) => unknown;
81
- foundSegmentIndex = i;
82
- break;
119
+ const mod = await loadModule(segment.error).catch(() => null);
120
+ if (mod?.default) {
121
+ return {
122
+ component: mod.default as (...args: unknown[]) => unknown,
123
+ segmentIndex: i,
124
+ isMdx: isMdxFile(segment.error.filePath),
125
+ };
83
126
  }
84
127
  }
85
128
  }
86
129
 
87
- // No error component found — fall back to bare response
88
- if (!errorComponent) {
130
+ return null;
131
+ }
132
+
133
+ /**
134
+ * Build the layouts-to-wrap list for an error file at a given segment index.
135
+ */
136
+ function getLayoutsForErrorFile(
137
+ segments: ManifestSegmentNode[],
138
+ layoutComponents: LayoutEntry[],
139
+ foundSegmentIndex: number
140
+ ): LayoutEntry[] {
141
+ const resolvedSegments = new Set(segments.slice(0, foundSegmentIndex + 1));
142
+ return layoutComponents.filter((lc) => resolvedSegments.has(lc.segment));
143
+ }
144
+
145
+ /**
146
+ * Convert an error to a SerializableError for RSC Flight serialization.
147
+ * Stack traces are stripped in production (gated by isDevMode).
148
+ *
149
+ * See design/13-security.md §"Debug Flag Security Boundary" — uses isDevMode(),
150
+ * not isDebug(), because this data crosses the RSC → client boundary.
151
+ */
152
+ function toSerializableError(error: unknown): SerializableError {
153
+ const err = error instanceof Error ? error : new Error(String(error));
154
+ return {
155
+ message: err.message,
156
+ name: err.name,
157
+ ...(isDevMode() && err.stack ? { stack: err.stack } : {}),
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Render an error page for unhandled throws or RenderError outside Suspense.
163
+ *
164
+ * All error pages (TSX and MDX) go through RSC → SSR:
165
+ * - TSX: ErrorReconstituter wrapper converts SerializableError → real Error
166
+ * - MDX: Plain props ({ status }), no wrapper needed
167
+ */
168
+ export async function renderErrorPage(
169
+ error: unknown,
170
+ status: number,
171
+ segments: ManifestSegmentNode[],
172
+ layoutComponents: LayoutEntry[],
173
+ req: Request,
174
+ match: RouteMatch,
175
+ responseHeaders: Headers,
176
+ clientBootstrap: ClientBootstrapConfig,
177
+ globalError?: GlobalErrorFile
178
+ ): Promise<Response> {
179
+ // Walk segments from leaf to root to find the error component
180
+ const resolution = await resolveErrorFile(status, segments);
181
+
182
+ // Tier 2: No segment-level error file — try global-error.tsx
183
+ if (!resolution && globalError) {
184
+ return renderGlobalErrorPage(
185
+ error,
186
+ status,
187
+ globalError,
188
+ req,
189
+ match,
190
+ responseHeaders,
191
+ clientBootstrap
192
+ );
193
+ }
194
+
195
+ // Tier 3: No error component found at any level — bare response
196
+ if (!resolution) {
89
197
  return new Response(null, { status, headers: responseHeaders });
90
198
  }
91
199
 
92
- // Build digest prop for RenderError, null for unhandled errors
93
- const digest =
94
- error instanceof RenderError ? { code: error.code, data: error.digest.data } : null;
200
+ const { component: errorComponent, segmentIndex, isMdx } = resolution;
201
+ const layoutsToWrap = getLayoutsForErrorFile(segments, layoutComponents, segmentIndex);
95
202
 
96
- // Error pages receive { error, digest, reset } per design/10-error-handling.md
97
- let element = h(errorComponent, {
98
- error: error instanceof Error ? error : new Error(String(error)),
99
- digest,
100
- reset: undefined, // reset is only meaningful on the client
101
- });
203
+ return renderErrorPageViaRsc(
204
+ error,
205
+ errorComponent,
206
+ isMdx,
207
+ status,
208
+ layoutsToWrap,
209
+ req,
210
+ match,
211
+ responseHeaders,
212
+ clientBootstrap
213
+ );
214
+ }
102
215
 
103
- // Wrap in layouts from root up to the segment where the error file was found
104
- const resolvedSegments = new Set(segments.slice(0, foundSegmentIndex + 1));
105
- const layoutsToWrap = layoutComponents.filter((lc) => resolvedSegments.has(lc.segment));
216
+ /**
217
+ * Render an error page through the RSC → SSR pipeline.
218
+ *
219
+ * Handles both TSX and MDX error pages:
220
+ * - TSX: Wrapped with ErrorReconstituter to reconstitute Error on client
221
+ * - MDX: Receives plain props ({ status }), rendered as server component
222
+ */
223
+ async function renderErrorPageViaRsc(
224
+ error: unknown,
225
+ errorComponent: (...args: unknown[]) => unknown,
226
+ isMdx: boolean,
227
+ status: number,
228
+ layoutsToWrap: LayoutEntry[],
229
+ req: Request,
230
+ match: RouteMatch,
231
+ responseHeaders: Headers,
232
+ clientBootstrap: ClientBootstrapConfig
233
+ ): Promise<Response> {
234
+ const h = createElement as (...args: unknown[]) => React.ReactElement;
235
+ const url = new URL(req.url);
236
+
237
+ let element: React.ReactElement;
238
+
239
+ if (isMdx) {
240
+ // MDX error pages receive plain props — no Error serialization issue
241
+ element = h(errorComponent, { status });
242
+ } else {
243
+ // TSX error pages: wrap with ErrorReconstituter for Error reconstitution.
244
+ // The ErrorReconstituter is a 'use client' component that receives
245
+ // SerializableError (plain object) and reconstitutes a real Error
246
+ // before passing to the user's error component.
247
+ const serializedError = toSerializableError(error);
248
+ const digest =
249
+ error instanceof RenderError ? { code: error.code, data: error.digest.data } : null;
250
+
251
+ element = h(ErrorReconstituter, {
252
+ error: serializedError,
253
+ digest,
254
+ reset: undefined,
255
+ component: errorComponent,
256
+ });
257
+ }
258
+
259
+ // Wrap in layouts
106
260
  for (let i = layoutsToWrap.length - 1; i >= 0; i--) {
107
261
  const { component } = layoutsToWrap[i];
108
262
  element = h(component, null, element);
109
263
  }
110
264
 
111
- // Render to fresh RSC Flight stream
112
- const rscStream = renderToReadableStream(element, {
113
- onError(err: unknown) {
114
- logRenderError({ method: req.method, path: new URL(req.url).pathname, error: err });
115
- },
116
- debugChannel: createDebugChannelSink(),
117
- });
118
-
119
- const [ssrStream, inlineStream] = rscStream.tee();
120
-
121
- const navContext: NavContext = {
122
- pathname: new URL(req.url).pathname,
123
- params: match.params,
124
- searchParams: Object.fromEntries(new URL(req.url).searchParams),
125
- statusCode: status,
126
- responseHeaders,
127
- headHtml: '',
128
- bootstrapScriptContent: clientBootstrap.bootstrapScriptContent,
129
- rscStream: inlineStream,
130
- cookies: parseCookiesFromHeader(req.headers.get('cookie') ?? ''),
131
- };
265
+ // Render through RSC SSR (same path as deny pages)
266
+ try {
267
+ const rscStream = renderToReadableStream(element, {
268
+ signal: req.signal,
269
+ onError(err: unknown) {
270
+ logRenderError({ method: req.method, path: url.pathname, error: err });
271
+ },
272
+ debugChannel: createDebugChannelSink(),
273
+ });
274
+
275
+ const [ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
276
+
277
+ // Build params bootstrap script so useSegmentParams() works on hydration.
278
+ // Without this, error pages on dynamic routes hydrate with empty params.
279
+ const paramsScript =
280
+ Object.keys(match.segmentParams).length === 0
281
+ ? ''
282
+ : `<script>self.__timber_params=${JSON.stringify(match.segmentParams)}</script>`;
283
+
284
+ const navContext: NavContext = {
285
+ pathname: url.pathname,
286
+ params: match.segmentParams,
287
+ searchParams: Object.fromEntries(url.searchParams),
288
+ statusCode: status,
289
+ responseHeaders,
290
+ headHtml: paramsScript + flightInitScript(),
291
+ bootstrapScriptContent: clientBootstrap.bootstrapScriptContent,
292
+ rscStream: inlineStream,
293
+ signal: req.signal,
294
+ cookies: getCookiesForSsr(),
295
+ };
296
+
297
+ return callSsr(ssrStream, navContext);
298
+ } catch (renderError) {
299
+ // Error page itself failed to render — fall through to bare response.
300
+ // This guards against recursive errors in user error page code.
301
+ logRenderError({ method: req.method, path: url.pathname, error: renderError });
302
+ return new Response(null, { status, headers: responseHeaders });
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Tier 2 — Render global-error.tsx as a standalone full-page replacement.
308
+ *
309
+ * No layout wrapping. The component must provide its own <html> and <body>.
310
+ * All formats (TSX and MDX) go through RSC → SSR.
311
+ *
312
+ * See design/10-error-handling.md §"Tier 2 — Global Error Page"
313
+ */
314
+ async function renderGlobalErrorPage(
315
+ error: unknown,
316
+ status: number,
317
+ globalError: GlobalErrorFile,
318
+ req: Request,
319
+ match: RouteMatch,
320
+ responseHeaders: Headers,
321
+ clientBootstrap: ClientBootstrapConfig
322
+ ): Promise<Response> {
323
+ // .catch: if global-error.tsx fails to load, fall through to bare response.
324
+ // This is the last tier — no further recovery. See TIM-584.
325
+ const mod = await loadModule(globalError).catch(() => null);
326
+ if (!mod?.default) {
327
+ return new Response(null, { status, headers: responseHeaders });
328
+ }
132
329
 
133
- return callSsr(ssrStream, navContext);
330
+ const component = mod.default as (...args: unknown[]) => unknown;
331
+ const isMdx = isMdxFile(globalError.filePath);
332
+
333
+ // Reuse the unified RSC path with no layouts
334
+ return renderErrorPageViaRsc(
335
+ error,
336
+ component,
337
+ isMdx,
338
+ status,
339
+ [], // No layouts — global-error is standalone
340
+ req,
341
+ match,
342
+ responseHeaders,
343
+ clientBootstrap
344
+ );
134
345
  }
135
346
 
136
347
  /**
@@ -151,7 +362,7 @@ export async function renderNoMatchPage(
151
362
  // Load root layout if present
152
363
  const layoutComponents: LayoutEntry[] = [];
153
364
  if (rootSegment.layout) {
154
- const mod = (await rootSegment.layout.load()) as Record<string, unknown>;
365
+ const mod = await loadModule(rootSegment.layout);
155
366
  if (mod.default) {
156
367
  layoutComponents.push({
157
368
  component: mod.default as (...args: unknown[]) => unknown,
@@ -161,7 +372,7 @@ export async function renderNoMatchPage(
161
372
  }
162
373
 
163
374
  const deny = new DenySignal(404);
164
- const match: RouteMatch = { segments: segments as never, params: {} };
375
+ const match: RouteMatch = { segments: segments as never, segmentParams: {}, middlewareChain: [] };
165
376
 
166
377
  return renderDenyPage(
167
378
  deny,