@timber-js/app 0.2.0-alpha.15 → 0.2.0-alpha.151

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 (854) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/actions-a0RczDnB.js +1106 -0
  3. package/dist/_chunks/actions-a0RczDnB.js.map +1 -0
  4. package/dist/_chunks/build-output-helper-B20ZuTSA.js +102 -0
  5. package/dist/_chunks/build-output-helper-B20ZuTSA.js.map +1 -0
  6. package/dist/_chunks/cache-api-Co-yI-gP.js +424 -0
  7. package/dist/_chunks/cache-api-Co-yI-gP.js.map +1 -0
  8. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → canonicalize-P41GR6tY.js} +94 -18
  9. package/dist/_chunks/canonicalize-P41GR6tY.js.map +1 -0
  10. package/dist/_chunks/cli-schema-sync-DJDdyEae.js +629 -0
  11. package/dist/_chunks/cli-schema-sync-DJDdyEae.js.map +1 -0
  12. package/dist/_chunks/cli-schema-sync-D_IhHEUW.js +2 -0
  13. package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
  14. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
  15. package/dist/_chunks/define-Bssfp6ot.js +82 -0
  16. package/dist/_chunks/define-Bssfp6ot.js.map +1 -0
  17. package/dist/_chunks/define-CFmvb4Bt.js +203 -0
  18. package/dist/_chunks/define-CFmvb4Bt.js.map +1 -0
  19. package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
  20. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
  21. package/dist/_chunks/format-CfwjgPz9.js +14 -0
  22. package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
  23. package/dist/_chunks/href-validation-FiA_rToW.js +141 -0
  24. package/dist/_chunks/href-validation-FiA_rToW.js.map +1 -0
  25. package/dist/_chunks/logger-CM0clugc.js +645 -0
  26. package/dist/_chunks/logger-CM0clugc.js.map +1 -0
  27. package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
  28. package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
  29. package/dist/_chunks/plugin-context-DurqFBuY.js +2 -0
  30. package/dist/_chunks/plugin-context-GfDWsdd2.js +268 -0
  31. package/dist/_chunks/plugin-context-GfDWsdd2.js.map +1 -0
  32. package/dist/_chunks/registry-DbJPKoBp.js +20 -0
  33. package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
  34. package/dist/_chunks/resolve-schema-3iUvBV5T.js +50 -0
  35. package/dist/_chunks/resolve-schema-3iUvBV5T.js.map +1 -0
  36. package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
  37. package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
  38. package/dist/_chunks/schema-bridge-BY3QLBL7.js +119 -0
  39. package/dist/_chunks/schema-bridge-BY3QLBL7.js.map +1 -0
  40. package/dist/_chunks/segment-classify-CDDRVKs7.js +137 -0
  41. package/dist/_chunks/segment-classify-CDDRVKs7.js.map +1 -0
  42. package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
  43. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
  44. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
  45. package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
  46. package/dist/_chunks/tree-match-D2l830j2.js +102 -0
  47. package/dist/_chunks/tree-match-D2l830j2.js.map +1 -0
  48. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-CbeQmext.js} +7 -20
  49. package/dist/_chunks/use-query-states-CbeQmext.js.map +1 -0
  50. package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
  51. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
  52. package/dist/_chunks/validation-taUkvA4Q.js +113 -0
  53. package/dist/_chunks/validation-taUkvA4Q.js.map +1 -0
  54. package/dist/_chunks/walkers-DvWDj453.js +790 -0
  55. package/dist/_chunks/walkers-DvWDj453.js.map +1 -0
  56. package/dist/adapters/build-output-helper.d.ts +28 -0
  57. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  58. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  59. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  60. package/dist/adapters/cloudflare-dev.js +73 -0
  61. package/dist/adapters/cloudflare-dev.js.map +1 -0
  62. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  63. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  64. package/dist/adapters/cloudflare-kv-cache.js +117 -0
  65. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  66. package/dist/adapters/cloudflare.d.ts +142 -20
  67. package/dist/adapters/cloudflare.d.ts.map +1 -1
  68. package/dist/adapters/cloudflare.js +150 -64
  69. package/dist/adapters/cloudflare.js.map +1 -1
  70. package/dist/adapters/compress-module.d.ts +5 -4
  71. package/dist/adapters/compress-module.d.ts.map +1 -1
  72. package/dist/adapters/nitro.d.ts +17 -3
  73. package/dist/adapters/nitro.d.ts.map +1 -1
  74. package/dist/adapters/nitro.js +146 -147
  75. package/dist/adapters/nitro.js.map +1 -1
  76. package/dist/adapters/shared.d.ts +16 -0
  77. package/dist/adapters/shared.d.ts.map +1 -0
  78. package/dist/cache/cache-api.d.ts +24 -0
  79. package/dist/cache/cache-api.d.ts.map +1 -0
  80. package/dist/cache/handler-store.d.ts +31 -0
  81. package/dist/cache/handler-store.d.ts.map +1 -0
  82. package/dist/cache/index.d.ts +25 -7
  83. package/dist/cache/index.d.ts.map +1 -1
  84. package/dist/cache/index.js +100 -240
  85. package/dist/cache/index.js.map +1 -1
  86. package/dist/cache/invalidation-epoch.d.ts +43 -0
  87. package/dist/cache/invalidation-epoch.d.ts.map +1 -0
  88. package/dist/cache/redis-handler.d.ts +85 -8
  89. package/dist/cache/redis-handler.d.ts.map +1 -1
  90. package/dist/cache/singleflight.d.ts +18 -1
  91. package/dist/cache/singleflight.d.ts.map +1 -1
  92. package/dist/cache/sizeof.d.ts +22 -0
  93. package/dist/cache/sizeof.d.ts.map +1 -0
  94. package/dist/cache/stable-stringify.d.ts +9 -0
  95. package/dist/cache/stable-stringify.d.ts.map +1 -1
  96. package/dist/cache/timber-cache.d.ts +20 -10
  97. package/dist/cache/timber-cache.d.ts.map +1 -1
  98. package/dist/cli-schema-sync.d.ts +59 -0
  99. package/dist/cli-schema-sync.d.ts.map +1 -0
  100. package/dist/cli.d.ts +26 -2
  101. package/dist/cli.d.ts.map +1 -1
  102. package/dist/cli.js +70 -33
  103. package/dist/cli.js.map +1 -1
  104. package/dist/client/browser-dev.d.ts +34 -1
  105. package/dist/client/browser-dev.d.ts.map +1 -1
  106. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  107. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  108. package/dist/client/browser-entry/hmr.d.ts +21 -0
  109. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  110. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  111. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  112. package/dist/client/browser-entry/index.d.ts +29 -0
  113. package/dist/client/browser-entry/index.d.ts.map +1 -0
  114. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  115. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  116. package/dist/client/browser-entry/router-init.d.ts +26 -0
  117. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  118. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  119. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  120. package/dist/client/browser-entry/scroll.d.ts +28 -0
  121. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  122. package/dist/client/error-boundary.d.ts +12 -5
  123. package/dist/client/error-boundary.d.ts.map +1 -1
  124. package/dist/client/error-boundary.js +47 -10
  125. package/dist/client/error-boundary.js.map +1 -1
  126. package/dist/client/error-reconstituter.d.ts +61 -0
  127. package/dist/client/error-reconstituter.d.ts.map +1 -0
  128. package/dist/client/form.d.ts +16 -27
  129. package/dist/client/form.d.ts.map +1 -1
  130. package/dist/client/history.d.ts +11 -3
  131. package/dist/client/history.d.ts.map +1 -1
  132. package/dist/client/index.d.ts +10 -24
  133. package/dist/client/index.d.ts.map +1 -1
  134. package/dist/client/index.js +183 -1134
  135. package/dist/client/index.js.map +1 -1
  136. package/dist/client/internal.d.ts +19 -0
  137. package/dist/client/internal.d.ts.map +1 -0
  138. package/dist/client/internal.js +900 -0
  139. package/dist/client/internal.js.map +1 -0
  140. package/dist/client/link.d.ts +69 -60
  141. package/dist/client/link.d.ts.map +1 -1
  142. package/dist/client/navigation-api-types.d.ts +90 -0
  143. package/dist/client/navigation-api-types.d.ts.map +1 -0
  144. package/dist/client/navigation-api.d.ts +122 -0
  145. package/dist/client/navigation-api.d.ts.map +1 -0
  146. package/dist/client/navigation-context.d.ts +3 -2
  147. package/dist/client/navigation-context.d.ts.map +1 -1
  148. package/dist/client/navigation-root.d.ts +119 -0
  149. package/dist/client/navigation-root.d.ts.map +1 -0
  150. package/dist/client/nuqs-adapter.d.ts +1 -1
  151. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  152. package/dist/client/router-ref.d.ts +1 -1
  153. package/dist/client/router.d.ts +86 -10
  154. package/dist/client/router.d.ts.map +1 -1
  155. package/dist/client/rsc-fetch.d.ts +46 -3
  156. package/dist/client/rsc-fetch.d.ts.map +1 -1
  157. package/dist/client/segment-cache.d.ts +3 -1
  158. package/dist/client/segment-cache.d.ts.map +1 -1
  159. package/dist/client/segment-outlet.d.ts +49 -0
  160. package/dist/client/segment-outlet.d.ts.map +1 -0
  161. package/dist/client/segment-update-context.d.ts +21 -0
  162. package/dist/client/segment-update-context.d.ts.map +1 -0
  163. package/dist/client/shallow-url.d.ts +10 -0
  164. package/dist/client/shallow-url.d.ts.map +1 -0
  165. package/dist/client/ssr-data.d.ts +13 -4
  166. package/dist/client/ssr-data.d.ts.map +1 -1
  167. package/dist/client/state.d.ts +1 -1
  168. package/dist/client/top-loader.d.ts +5 -5
  169. package/dist/client/top-loader.d.ts.map +1 -1
  170. package/dist/client/use-cookie.d.ts +12 -0
  171. package/dist/client/use-cookie.d.ts.map +1 -1
  172. package/dist/client/use-link-status.d.ts +5 -5
  173. package/dist/client/use-link-status.d.ts.map +1 -1
  174. package/dist/client/use-pathname.d.ts.map +1 -1
  175. package/dist/client/use-pending-navigation.d.ts +23 -0
  176. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  177. package/dist/client/use-query-states.d.ts +1 -1
  178. package/dist/client/use-query-states.d.ts.map +1 -1
  179. package/dist/client/use-router.d.ts +1 -1
  180. package/dist/client/use-router.d.ts.map +1 -1
  181. package/dist/client/use-search-params.d.ts +12 -5
  182. package/dist/client/use-search-params.d.ts.map +1 -1
  183. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
  184. package/dist/client/use-segment-params.d.ts.map +1 -0
  185. package/dist/codec.d.ts +69 -0
  186. package/dist/codec.d.ts.map +1 -0
  187. package/dist/codec.js +75 -0
  188. package/dist/codec.js.map +1 -0
  189. package/dist/config-types.d.ts +294 -0
  190. package/dist/config-types.d.ts.map +1 -0
  191. package/dist/config-validation.d.ts +51 -0
  192. package/dist/config-validation.d.ts.map +1 -0
  193. package/dist/content/index.d.ts +1 -10
  194. package/dist/content/index.d.ts.map +1 -1
  195. package/dist/content/index.js +0 -2
  196. package/dist/cookies/define-cookie.d.ts +58 -25
  197. package/dist/cookies/define-cookie.d.ts.map +1 -1
  198. package/dist/cookies/index.d.ts +2 -1
  199. package/dist/cookies/index.d.ts.map +1 -1
  200. package/dist/cookies/index.js +249 -36
  201. package/dist/cookies/index.js.map +1 -1
  202. package/dist/cookies/json-cookie.d.ts +64 -0
  203. package/dist/cookies/json-cookie.d.ts.map +1 -0
  204. package/dist/cookies/validation.d.ts +34 -0
  205. package/dist/cookies/validation.d.ts.map +1 -0
  206. package/dist/dev-tools/404-page.d.ts +50 -0
  207. package/dist/dev-tools/404-page.d.ts.map +1 -0
  208. package/dist/dev-tools/browser-logs.d.ts +84 -0
  209. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  210. package/dist/dev-tools/dev-page-shell.d.ts +78 -0
  211. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
  212. package/dist/dev-tools/error-page.d.ts +32 -0
  213. package/dist/dev-tools/error-page.d.ts.map +1 -0
  214. package/dist/dev-tools/holding-server.d.ts +54 -0
  215. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  216. package/dist/dev-tools/hydration-overlay.d.ts +11 -0
  217. package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
  218. package/dist/dev-tools/index.d.ts +31 -0
  219. package/dist/dev-tools/index.d.ts.map +1 -0
  220. package/dist/dev-tools/instrumentation.d.ts +59 -0
  221. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  222. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  223. package/dist/dev-tools/logger.d.ts.map +1 -0
  224. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
  225. package/dist/dev-tools/logs.d.ts.map +1 -0
  226. package/dist/dev-tools/overlay.d.ts +91 -0
  227. package/dist/dev-tools/overlay.d.ts.map +1 -0
  228. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  229. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  230. package/dist/dev-tools/terminal.d.ts +28 -0
  231. package/dist/dev-tools/terminal.d.ts.map +1 -0
  232. package/dist/fonts/ast-walk.d.ts +68 -0
  233. package/dist/fonts/ast-walk.d.ts.map +1 -0
  234. package/dist/fonts/ast.d.ts +110 -6
  235. package/dist/fonts/ast.d.ts.map +1 -1
  236. package/dist/fonts/bundle.d.ts +50 -0
  237. package/dist/fonts/bundle.d.ts.map +1 -0
  238. package/dist/fonts/dev-middleware.d.ts +22 -0
  239. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  240. package/dist/fonts/fallbacks.d.ts +0 -7
  241. package/dist/fonts/fallbacks.d.ts.map +1 -1
  242. package/dist/fonts/google.d.ts +4 -2
  243. package/dist/fonts/google.d.ts.map +1 -1
  244. package/dist/fonts/local.d.ts +4 -4
  245. package/dist/fonts/local.d.ts.map +1 -1
  246. package/dist/fonts/paths.d.ts +43 -0
  247. package/dist/fonts/paths.d.ts.map +1 -0
  248. package/dist/fonts/pipeline.d.ts +158 -0
  249. package/dist/fonts/pipeline.d.ts.map +1 -0
  250. package/dist/fonts/transform.d.ts +78 -0
  251. package/dist/fonts/transform.d.ts.map +1 -0
  252. package/dist/fonts/types.d.ts +47 -1
  253. package/dist/fonts/types.d.ts.map +1 -1
  254. package/dist/fonts/virtual-modules.d.ts +77 -0
  255. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  256. package/dist/index.d.ts +46 -180
  257. package/dist/index.d.ts.map +1 -1
  258. package/dist/index.js +6452 -13421
  259. package/dist/index.js.map +1 -1
  260. package/dist/params/codec-registry.d.ts +26 -0
  261. package/dist/params/codec-registry.d.ts.map +1 -0
  262. package/dist/params/define-schema.d.ts +81 -0
  263. package/dist/params/define-schema.d.ts.map +1 -0
  264. package/dist/params/index.d.ts +5 -0
  265. package/dist/params/index.d.ts.map +1 -0
  266. package/dist/params/index.js +34 -0
  267. package/dist/params/index.js.map +1 -0
  268. package/dist/params/resolve-schema.d.ts +34 -0
  269. package/dist/params/resolve-schema.d.ts.map +1 -0
  270. package/dist/plugin-context.d.ts +137 -0
  271. package/dist/plugin-context.d.ts.map +1 -0
  272. package/dist/plugins/adapter-build.d.ts +20 -1
  273. package/dist/plugins/adapter-build.d.ts.map +1 -1
  274. package/dist/plugins/build-manifest.d.ts +7 -3
  275. package/dist/plugins/build-manifest.d.ts.map +1 -1
  276. package/dist/plugins/build-report.d.ts +9 -7
  277. package/dist/plugins/build-report.d.ts.map +1 -1
  278. package/dist/plugins/cache.d.ts +73 -0
  279. package/dist/plugins/cache.d.ts.map +1 -0
  280. package/dist/plugins/client-chunks.d.ts +39 -0
  281. package/dist/plugins/client-chunks.d.ts.map +1 -0
  282. package/dist/plugins/cloudflare-wasm.d.ts +21 -0
  283. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  284. package/dist/plugins/content.d.ts +1 -1
  285. package/dist/plugins/content.d.ts.map +1 -1
  286. package/dist/plugins/dev-server.d.ts +17 -1
  287. package/dist/plugins/dev-server.d.ts.map +1 -1
  288. package/dist/plugins/entries.d.ts +1 -1
  289. package/dist/plugins/entries.d.ts.map +1 -1
  290. package/dist/plugins/fonts.d.ts +16 -73
  291. package/dist/plugins/fonts.d.ts.map +1 -1
  292. package/dist/plugins/mdx.d.ts +1 -1
  293. package/dist/plugins/mdx.d.ts.map +1 -1
  294. package/dist/plugins/routing.d.ts +1 -1
  295. package/dist/plugins/routing.d.ts.map +1 -1
  296. package/dist/plugins/server-bundle.d.ts.map +1 -1
  297. package/dist/plugins/shims.d.ts +29 -5
  298. package/dist/plugins/shims.d.ts.map +1 -1
  299. package/dist/plugins/static-build.d.ts +5 -26
  300. package/dist/plugins/static-build.d.ts.map +1 -1
  301. package/dist/routing/codegen-shared.d.ts +67 -0
  302. package/dist/routing/codegen-shared.d.ts.map +1 -0
  303. package/dist/routing/codegen-types.d.ts +64 -0
  304. package/dist/routing/codegen-types.d.ts.map +1 -0
  305. package/dist/routing/codegen.d.ts +7 -2
  306. package/dist/routing/codegen.d.ts.map +1 -1
  307. package/dist/routing/convention-lint.d.ts +41 -0
  308. package/dist/routing/convention-lint.d.ts.map +1 -0
  309. package/dist/routing/file-cache.d.ts +8 -0
  310. package/dist/routing/file-cache.d.ts.map +1 -0
  311. package/dist/routing/index.d.ts +7 -1
  312. package/dist/routing/index.d.ts.map +1 -1
  313. package/dist/routing/index.js +4 -2
  314. package/dist/routing/interception.d.ts +0 -5
  315. package/dist/routing/interception.d.ts.map +1 -1
  316. package/dist/routing/link-codegen.d.ts +90 -0
  317. package/dist/routing/link-codegen.d.ts.map +1 -0
  318. package/dist/routing/manifest-codegen.d.ts +32 -0
  319. package/dist/routing/manifest-codegen.d.ts.map +1 -0
  320. package/dist/routing/scanner.d.ts +1 -10
  321. package/dist/routing/scanner.d.ts.map +1 -1
  322. package/dist/routing/schema-validation.d.ts +35 -0
  323. package/dist/routing/schema-validation.d.ts.map +1 -0
  324. package/dist/routing/segment-classify.d.ts +75 -0
  325. package/dist/routing/segment-classify.d.ts.map +1 -0
  326. package/dist/routing/segment-codegen.d.ts +38 -0
  327. package/dist/routing/segment-codegen.d.ts.map +1 -0
  328. package/dist/routing/types.d.ts +77 -25
  329. package/dist/routing/types.d.ts.map +1 -1
  330. package/dist/routing/walkers.d.ts +51 -0
  331. package/dist/routing/walkers.d.ts.map +1 -0
  332. package/dist/rsc-runtime/rsc.d.ts +1 -1
  333. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  334. package/dist/rsc-runtime/ssr.d.ts +12 -0
  335. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  336. package/dist/schema-bridge.d.ts +91 -0
  337. package/dist/schema-bridge.d.ts.map +1 -0
  338. package/dist/search-params/define.d.ts +157 -0
  339. package/dist/search-params/define.d.ts.map +1 -0
  340. package/dist/search-params/index.d.ts +4 -7
  341. package/dist/search-params/index.d.ts.map +1 -1
  342. package/dist/search-params/index.js +37 -440
  343. package/dist/search-params/index.js.map +1 -1
  344. package/dist/search-params/registry.d.ts +2 -2
  345. package/dist/search-params/registry.d.ts.map +1 -1
  346. package/dist/search-params/wrappers.d.ts +53 -0
  347. package/dist/search-params/wrappers.d.ts.map +1 -0
  348. package/dist/segment-params/define.d.ts +89 -0
  349. package/dist/segment-params/define.d.ts.map +1 -0
  350. package/dist/segment-params/index.d.ts +3 -0
  351. package/dist/segment-params/index.d.ts.map +1 -0
  352. package/dist/segment-params/index.js +2 -0
  353. package/dist/server/access-gate.d.ts +8 -3
  354. package/dist/server/access-gate.d.ts.map +1 -1
  355. package/dist/server/action-client.d.ts +41 -6
  356. package/dist/server/action-client.d.ts.map +1 -1
  357. package/dist/server/action-encryption.d.ts +76 -0
  358. package/dist/server/action-encryption.d.ts.map +1 -0
  359. package/dist/server/action-handler.d.ts +35 -1
  360. package/dist/server/action-handler.d.ts.map +1 -1
  361. package/dist/server/actions.d.ts +9 -30
  362. package/dist/server/actions.d.ts.map +1 -1
  363. package/dist/server/als-registry.d.ts +70 -11
  364. package/dist/server/als-registry.d.ts.map +1 -1
  365. package/dist/server/asset-headers.d.ts +1 -15
  366. package/dist/server/asset-headers.d.ts.map +1 -1
  367. package/dist/server/body-limits.d.ts.map +1 -1
  368. package/dist/server/build-manifest.d.ts +6 -29
  369. package/dist/server/build-manifest.d.ts.map +1 -1
  370. package/dist/server/canonicalize.d.ts +10 -0
  371. package/dist/server/canonicalize.d.ts.map +1 -1
  372. package/dist/server/coalesce-tick.d.ts +40 -0
  373. package/dist/server/coalesce-tick.d.ts.map +1 -0
  374. package/dist/server/cookie-context.d.ts +170 -0
  375. package/dist/server/cookie-context.d.ts.map +1 -0
  376. package/dist/server/cookie-parsing.d.ts +51 -0
  377. package/dist/server/cookie-parsing.d.ts.map +1 -0
  378. package/dist/server/csrf.d.ts +3 -2
  379. package/dist/server/csrf.d.ts.map +1 -1
  380. package/dist/server/default-logger.d.ts +22 -0
  381. package/dist/server/default-logger.d.ts.map +1 -0
  382. package/dist/server/deny-boundary.d.ts +115 -0
  383. package/dist/server/deny-boundary.d.ts.map +1 -0
  384. package/dist/server/deny-renderer.d.ts +2 -2
  385. package/dist/server/deny-renderer.d.ts.map +1 -1
  386. package/dist/server/dev-source-map.d.ts +22 -0
  387. package/dist/server/dev-source-map.d.ts.map +1 -0
  388. package/dist/server/early-hints-sender.d.ts.map +1 -1
  389. package/dist/server/early-hints.d.ts +13 -11
  390. package/dist/server/early-hints.d.ts.map +1 -1
  391. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  392. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  393. package/dist/server/fallback-error.d.ts +12 -7
  394. package/dist/server/fallback-error.d.ts.map +1 -1
  395. package/dist/server/flight-injection-state.d.ts +66 -0
  396. package/dist/server/flight-injection-state.d.ts.map +1 -0
  397. package/dist/server/flight-scripts.d.ts +42 -0
  398. package/dist/server/flight-scripts.d.ts.map +1 -0
  399. package/dist/server/form-data.d.ts +29 -0
  400. package/dist/server/form-data.d.ts.map +1 -1
  401. package/dist/server/html-injector-core.d.ts +221 -0
  402. package/dist/server/html-injector-core.d.ts.map +1 -0
  403. package/dist/server/html-injectors.d.ts +81 -41
  404. package/dist/server/html-injectors.d.ts.map +1 -1
  405. package/dist/server/index.d.ts +10 -46
  406. package/dist/server/index.d.ts.map +1 -1
  407. package/dist/server/index.js +170 -2911
  408. package/dist/server/index.js.map +1 -1
  409. package/dist/server/internal.d.ts +44 -0
  410. package/dist/server/internal.d.ts.map +1 -0
  411. package/dist/server/internal.js +3015 -0
  412. package/dist/server/internal.js.map +1 -0
  413. package/dist/server/logger.d.ts +39 -7
  414. package/dist/server/logger.d.ts.map +1 -1
  415. package/dist/server/metadata-routes.d.ts +23 -7
  416. package/dist/server/metadata-routes.d.ts.map +1 -1
  417. package/dist/server/middleware-runner.d.ts +36 -4
  418. package/dist/server/middleware-runner.d.ts.map +1 -1
  419. package/dist/server/node-stream-transforms.d.ts +119 -0
  420. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  421. package/dist/server/param-coercion.d.ts +54 -0
  422. package/dist/server/param-coercion.d.ts.map +1 -0
  423. package/dist/server/pipeline-helpers.d.ts +95 -0
  424. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  425. package/dist/server/pipeline-interception.d.ts +1 -1
  426. package/dist/server/pipeline-interception.d.ts.map +1 -1
  427. package/dist/server/pipeline-metadata.d.ts +6 -0
  428. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  429. package/dist/server/pipeline-outcome.d.ts +49 -0
  430. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  431. package/dist/server/pipeline-phases.d.ts +56 -0
  432. package/dist/server/pipeline-phases.d.ts.map +1 -0
  433. package/dist/server/pipeline.d.ts +122 -19
  434. package/dist/server/pipeline.d.ts.map +1 -1
  435. package/dist/server/port-resolution.d.ts +117 -0
  436. package/dist/server/port-resolution.d.ts.map +1 -0
  437. package/dist/server/primitives.d.ts +75 -31
  438. package/dist/server/primitives.d.ts.map +1 -1
  439. package/dist/server/render-timeout.d.ts +51 -0
  440. package/dist/server/render-timeout.d.ts.map +1 -0
  441. package/dist/server/render-utils.d.ts +25 -0
  442. package/dist/server/render-utils.d.ts.map +1 -0
  443. package/dist/server/request-context.d.ts +62 -107
  444. package/dist/server/request-context.d.ts.map +1 -1
  445. package/dist/server/route-element-builder.d.ts +30 -18
  446. package/dist/server/route-element-builder.d.ts.map +1 -1
  447. package/dist/server/route-handler.d.ts.map +1 -1
  448. package/dist/server/route-matcher.d.ts +25 -36
  449. package/dist/server/route-matcher.d.ts.map +1 -1
  450. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  451. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  452. package/dist/server/rsc-entry/api-handler.d.ts +12 -3
  453. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  454. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  455. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  456. package/dist/server/rsc-entry/helpers.d.ts +51 -23
  457. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  458. package/dist/server/rsc-entry/index.d.ts +19 -8
  459. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  460. package/dist/server/rsc-entry/render-route.d.ts +50 -0
  461. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  462. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  463. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  464. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  465. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  466. package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
  467. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  468. package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
  469. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  470. package/dist/server/rsc-entry/ssr-renderer.d.ts +34 -4
  471. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  472. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
  473. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  474. package/dist/server/safe-load.d.ts +46 -0
  475. package/dist/server/safe-load.d.ts.map +1 -0
  476. package/dist/server/sensitive-fields.d.ts +74 -0
  477. package/dist/server/sensitive-fields.d.ts.map +1 -0
  478. package/dist/server/sitemap-generator.d.ts +129 -0
  479. package/dist/server/sitemap-generator.d.ts.map +1 -0
  480. package/dist/server/sitemap-handler.d.ts +22 -0
  481. package/dist/server/sitemap-handler.d.ts.map +1 -0
  482. package/dist/server/slot-resolver.d.ts +7 -5
  483. package/dist/server/slot-resolver.d.ts.map +1 -1
  484. package/dist/server/ssr-bridge-types.d.ts +121 -0
  485. package/dist/server/ssr-bridge-types.d.ts.map +1 -0
  486. package/dist/server/ssr-entry.d.ts +2 -43
  487. package/dist/server/ssr-entry.d.ts.map +1 -1
  488. package/dist/server/ssr-render.d.ts +64 -21
  489. package/dist/server/ssr-render.d.ts.map +1 -1
  490. package/dist/server/ssr-wrappers.d.ts +50 -0
  491. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  492. package/dist/server/state-tree-diff.d.ts +12 -5
  493. package/dist/server/state-tree-diff.d.ts.map +1 -1
  494. package/dist/server/status-code-resolver.d.ts +22 -11
  495. package/dist/server/status-code-resolver.d.ts.map +1 -1
  496. package/dist/server/stream-utils.d.ts +36 -0
  497. package/dist/server/stream-utils.d.ts.map +1 -0
  498. package/dist/server/tracing.d.ts +7 -6
  499. package/dist/server/tracing.d.ts.map +1 -1
  500. package/dist/server/tree-builder.d.ts +62 -30
  501. package/dist/server/tree-builder.d.ts.map +1 -1
  502. package/dist/server/tree-match.d.ts +49 -0
  503. package/dist/server/tree-match.d.ts.map +1 -0
  504. package/dist/server/types.d.ts +71 -6
  505. package/dist/server/types.d.ts.map +1 -1
  506. package/dist/server/utils/escape-html.d.ts +14 -0
  507. package/dist/server/utils/escape-html.d.ts.map +1 -0
  508. package/dist/server/utils/mdx-file.d.ts +15 -0
  509. package/dist/server/utils/mdx-file.d.ts.map +1 -0
  510. package/dist/server/version-skew.d.ts +61 -0
  511. package/dist/server/version-skew.d.ts.map +1 -0
  512. package/dist/shared/head-header.d.ts +54 -0
  513. package/dist/shared/head-header.d.ts.map +1 -0
  514. package/dist/shared/href-validation.d.ts +49 -0
  515. package/dist/shared/href-validation.d.ts.map +1 -0
  516. package/dist/shared/merge-search-params.d.ts +22 -0
  517. package/dist/shared/merge-search-params.d.ts.map +1 -0
  518. package/dist/shared/redirect-type.d.ts +17 -0
  519. package/dist/shared/redirect-type.d.ts.map +1 -0
  520. package/dist/shims/font-google.d.ts +1 -1
  521. package/dist/shims/font-google.d.ts.map +1 -1
  522. package/dist/shims/font-google.js +42 -0
  523. package/dist/shims/font-google.js.map +1 -0
  524. package/dist/shims/font-local.d.ts +26 -0
  525. package/dist/shims/font-local.d.ts.map +1 -0
  526. package/dist/shims/font-local.js +20 -0
  527. package/dist/shims/font-local.js.map +1 -0
  528. package/dist/shims/headers.d.ts +53 -1
  529. package/dist/shims/headers.d.ts.map +1 -1
  530. package/dist/shims/image.d.ts +16 -16
  531. package/dist/shims/navigation-client.d.ts +35 -11
  532. package/dist/shims/navigation-client.d.ts.map +1 -1
  533. package/dist/shims/navigation.d.ts +11 -5
  534. package/dist/shims/navigation.d.ts.map +1 -1
  535. package/dist/utils/state-machine.d.ts +80 -0
  536. package/dist/utils/state-machine.d.ts.map +1 -0
  537. package/package.json +63 -24
  538. package/src/adapters/build-output-helper.ts +139 -0
  539. package/src/adapters/cloudflare-dev.ts +177 -0
  540. package/src/adapters/cloudflare-kv-cache.ts +179 -0
  541. package/src/adapters/cloudflare.ts +356 -116
  542. package/src/adapters/compress-module.ts +27 -92
  543. package/src/adapters/nitro.ts +155 -99
  544. package/src/adapters/raw-imports.d.ts +5 -0
  545. package/src/adapters/shared.ts +40 -0
  546. package/src/adapters/wrangler.d.ts +7 -0
  547. package/src/cache/cache-api.ts +47 -0
  548. package/src/cache/handler-store.ts +68 -0
  549. package/src/cache/index.ts +84 -18
  550. package/src/cache/invalidation-epoch.ts +93 -0
  551. package/src/cache/redis-handler.ts +110 -15
  552. package/src/cache/singleflight.ts +62 -4
  553. package/src/cache/sizeof.ts +33 -0
  554. package/src/cache/stable-stringify.ts +65 -2
  555. package/src/cache/timber-cache.ts +132 -36
  556. package/src/cli-schema-sync.ts +388 -0
  557. package/src/cli.ts +98 -34
  558. package/src/client/browser-dev.ts +153 -1
  559. package/src/client/browser-entry/action-dispatch.ts +119 -0
  560. package/src/client/browser-entry/hmr.ts +70 -0
  561. package/src/client/browser-entry/hydrate.ts +187 -0
  562. package/src/client/browser-entry/index.ts +111 -0
  563. package/src/client/browser-entry/post-hydration.ts +104 -0
  564. package/src/client/browser-entry/router-init.ts +292 -0
  565. package/src/client/browser-entry/rsc-stream.ts +157 -0
  566. package/src/client/browser-entry/scroll.ts +50 -0
  567. package/src/client/error-boundary.tsx +127 -22
  568. package/src/client/error-reconstituter.tsx +79 -0
  569. package/src/client/form.tsx +31 -32
  570. package/src/client/history.ts +11 -3
  571. package/src/client/index.ts +67 -45
  572. package/src/client/internal.ts +58 -0
  573. package/src/client/link.tsx +346 -150
  574. package/src/client/navigation-api-types.ts +112 -0
  575. package/src/client/navigation-api.ts +347 -0
  576. package/src/client/navigation-context.ts +15 -7
  577. package/src/client/navigation-root.tsx +355 -0
  578. package/src/client/nuqs-adapter.tsx +16 -3
  579. package/src/client/router-ref.ts +1 -1
  580. package/src/client/router.ts +490 -140
  581. package/src/client/rsc-fetch.ts +220 -17
  582. package/src/client/segment-cache.ts +6 -3
  583. package/src/client/segment-outlet.tsx +77 -0
  584. package/src/client/segment-update-context.ts +42 -0
  585. package/src/client/shallow-url.ts +22 -0
  586. package/src/client/ssr-data.ts +13 -5
  587. package/src/client/state.ts +2 -2
  588. package/src/client/top-loader.tsx +11 -9
  589. package/src/client/use-cookie.ts +31 -2
  590. package/src/client/use-link-status.ts +7 -7
  591. package/src/client/use-pathname.ts +1 -0
  592. package/src/client/use-pending-navigation.ts +40 -0
  593. package/src/client/use-query-states.ts +9 -3
  594. package/src/client/use-router.ts +4 -1
  595. package/src/client/use-search-params.ts +31 -44
  596. package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
  597. package/src/codec.ts +147 -0
  598. package/src/config-types.ts +292 -0
  599. package/src/config-validation.ts +311 -0
  600. package/src/content/index.ts +5 -13
  601. package/src/cookies/define-cookie.ts +217 -53
  602. package/src/cookies/index.ts +12 -1
  603. package/src/cookies/json-cookie.ts +105 -0
  604. package/src/cookies/validation.ts +192 -0
  605. package/src/dev-tools/404-page.ts +286 -0
  606. package/src/dev-tools/browser-logs.ts +291 -0
  607. package/src/dev-tools/dev-page-shell.ts +260 -0
  608. package/src/dev-tools/error-page.ts +331 -0
  609. package/src/dev-tools/holding-server.ts +187 -0
  610. package/src/dev-tools/hydration-overlay.ts +158 -0
  611. package/src/dev-tools/index.ts +83 -0
  612. package/src/dev-tools/instrumentation.ts +213 -0
  613. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
  614. package/src/dev-tools/overlay.ts +469 -0
  615. package/src/dev-tools/stack-classifier.ts +75 -0
  616. package/src/dev-tools/terminal.ts +183 -0
  617. package/src/fonts/ast-walk.ts +235 -0
  618. package/src/fonts/ast.ts +477 -126
  619. package/src/fonts/bundle.ts +138 -0
  620. package/src/fonts/dev-middleware.ts +85 -0
  621. package/src/fonts/fallbacks.ts +0 -23
  622. package/src/fonts/google.ts +7 -3
  623. package/src/fonts/local.ts +9 -8
  624. package/src/fonts/paths.ts +58 -0
  625. package/src/fonts/pipeline.ts +316 -0
  626. package/src/fonts/transform.ts +344 -0
  627. package/src/fonts/types.ts +52 -1
  628. package/src/fonts/virtual-modules.ts +179 -0
  629. package/src/index.ts +417 -346
  630. package/src/params/codec-registry.ts +34 -0
  631. package/src/params/define-schema.ts +115 -0
  632. package/src/params/index.ts +17 -0
  633. package/src/params/resolve-schema.ts +84 -0
  634. package/src/plugin-context.ts +325 -0
  635. package/src/plugins/adapter-build.ts +98 -4
  636. package/src/plugins/build-manifest.ts +168 -23
  637. package/src/plugins/build-report.ts +16 -25
  638. package/src/plugins/cache.ts +285 -0
  639. package/src/plugins/client-chunks.ts +113 -0
  640. package/src/plugins/cloudflare-wasm.ts +141 -0
  641. package/src/plugins/content.ts +1 -1
  642. package/src/plugins/dev-server.ts +293 -46
  643. package/src/plugins/entries.ts +110 -8
  644. package/src/plugins/fonts.ts +170 -663
  645. package/src/plugins/mdx.ts +47 -10
  646. package/src/plugins/routing.ts +237 -241
  647. package/src/plugins/server-bundle.ts +85 -12
  648. package/src/plugins/shims.ts +207 -64
  649. package/src/plugins/static-build.ts +15 -89
  650. package/src/routing/codegen-shared.ts +115 -0
  651. package/src/routing/codegen-types.ts +65 -0
  652. package/src/routing/codegen.ts +380 -178
  653. package/src/routing/convention-lint.ts +358 -0
  654. package/src/routing/file-cache.ts +23 -0
  655. package/src/routing/index.ts +10 -1
  656. package/src/routing/interception.ts +3 -22
  657. package/src/routing/link-codegen.ts +310 -0
  658. package/src/routing/manifest-codegen.ts +290 -0
  659. package/src/routing/scanner.ts +248 -188
  660. package/src/routing/schema-validation.ts +149 -0
  661. package/src/routing/segment-classify.ts +188 -0
  662. package/src/routing/segment-codegen.ts +98 -0
  663. package/src/routing/types.ts +78 -25
  664. package/src/routing/walkers.ts +90 -0
  665. package/src/rsc-runtime/rsc.ts +2 -0
  666. package/src/rsc-runtime/ssr.ts +50 -0
  667. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  668. package/src/schema-bridge.ts +252 -0
  669. package/src/search-params/define.ts +570 -0
  670. package/src/search-params/index.ts +14 -20
  671. package/src/search-params/registry.ts +2 -2
  672. package/src/search-params/wrappers.ts +110 -0
  673. package/src/segment-params/define.ts +249 -0
  674. package/src/segment-params/index.ts +9 -0
  675. package/src/server/access-gate.tsx +84 -34
  676. package/src/server/action-client.ts +119 -28
  677. package/src/server/action-encryption.ts +144 -0
  678. package/src/server/action-handler.ts +122 -16
  679. package/src/server/actions.ts +39 -53
  680. package/src/server/als-registry.ts +108 -20
  681. package/src/server/asset-headers.ts +8 -34
  682. package/src/server/body-limits.ts +10 -2
  683. package/src/server/build-manifest.ts +13 -56
  684. package/src/server/canonicalize.ts +6 -3
  685. package/src/server/coalesce-tick.ts +75 -0
  686. package/src/server/compress.ts +34 -7
  687. package/src/server/cookie-context.ts +484 -0
  688. package/src/server/cookie-parsing.ts +147 -0
  689. package/src/server/csrf.ts +39 -6
  690. package/src/server/default-logger.ts +99 -0
  691. package/src/server/deny-boundary.ts +311 -0
  692. package/src/server/deny-renderer.ts +80 -64
  693. package/src/server/dev-source-map.ts +31 -0
  694. package/src/server/early-hints-sender.ts +3 -2
  695. package/src/server/early-hints.ts +37 -27
  696. package/src/server/error-boundary-wrapper.ts +61 -22
  697. package/src/server/fallback-error.ts +79 -102
  698. package/src/server/flight-injection-state.ts +113 -0
  699. package/src/server/flight-scripts.ts +62 -0
  700. package/src/server/form-data.ts +101 -5
  701. package/src/server/html-injector-core.ts +437 -0
  702. package/src/server/html-injectors.ts +256 -251
  703. package/src/server/index.ts +29 -183
  704. package/src/server/internal.ts +165 -0
  705. package/src/server/logger.ts +67 -36
  706. package/src/server/metadata-routes.ts +44 -19
  707. package/src/server/middleware-runner.ts +75 -4
  708. package/src/server/node-stream-transforms.ts +331 -0
  709. package/src/server/param-coercion.ts +206 -0
  710. package/src/server/pipeline-helpers.ts +204 -0
  711. package/src/server/pipeline-interception.ts +32 -18
  712. package/src/server/pipeline-metadata.ts +13 -0
  713. package/src/server/pipeline-outcome.ts +197 -0
  714. package/src/server/pipeline-phases.ts +527 -0
  715. package/src/server/pipeline.ts +213 -382
  716. package/src/server/port-resolution.ts +215 -0
  717. package/src/server/primitives.ts +126 -63
  718. package/src/server/render-timeout.ts +108 -0
  719. package/src/server/render-utils.ts +31 -0
  720. package/src/server/request-context.ts +168 -337
  721. package/src/server/route-element-builder.ts +481 -222
  722. package/src/server/route-handler.ts +31 -4
  723. package/src/server/route-matcher.ts +144 -277
  724. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  725. package/src/server/rsc-entry/api-handler.ts +69 -32
  726. package/src/server/rsc-entry/error-renderer.ts +306 -89
  727. package/src/server/rsc-entry/helpers.ts +160 -59
  728. package/src/server/rsc-entry/index.ts +299 -329
  729. package/src/server/rsc-entry/render-route.ts +311 -0
  730. package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
  731. package/src/server/rsc-entry/rsc-payload.ts +71 -26
  732. package/src/server/rsc-entry/rsc-stream.ts +85 -13
  733. package/src/server/rsc-entry/ssr-bridge.ts +18 -5
  734. package/src/server/rsc-entry/ssr-renderer.ts +273 -43
  735. package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
  736. package/src/server/safe-load.ts +60 -0
  737. package/src/server/sensitive-fields.ts +230 -0
  738. package/src/server/sitemap-generator.ts +338 -0
  739. package/src/server/sitemap-handler.ts +148 -0
  740. package/src/server/slot-resolver.ts +258 -257
  741. package/src/server/ssr-bridge-types.ts +124 -0
  742. package/src/server/ssr-entry.ts +206 -78
  743. package/src/server/ssr-render.ts +345 -82
  744. package/src/server/ssr-wrappers.tsx +141 -0
  745. package/src/server/state-tree-diff.ts +30 -23
  746. package/src/server/status-code-resolver.ts +115 -130
  747. package/src/server/stream-utils.ts +213 -0
  748. package/src/server/tracing.ts +38 -11
  749. package/src/server/tree-builder.ts +204 -90
  750. package/src/server/tree-match.ts +220 -0
  751. package/src/server/types.ts +78 -9
  752. package/src/server/utils/escape-html.ts +20 -0
  753. package/src/server/utils/mdx-file.ts +22 -0
  754. package/src/server/version-skew.ts +104 -0
  755. package/src/shared/head-header.ts +69 -0
  756. package/src/shared/href-validation.ts +159 -0
  757. package/src/shared/merge-search-params.ts +55 -0
  758. package/src/shared/redirect-type.ts +17 -0
  759. package/src/shims/font-google.ts +1 -1
  760. package/src/shims/font-local.ts +34 -0
  761. package/src/shims/headers.ts +122 -1
  762. package/src/shims/navigation-client.ts +51 -29
  763. package/src/shims/navigation.ts +14 -7
  764. package/src/utils/state-machine.ts +111 -0
  765. package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
  766. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  767. package/dist/_chunks/debug-B3Gypr3D.js +0 -108
  768. package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
  769. package/dist/_chunks/format-RyoGQL74.js +0 -164
  770. package/dist/_chunks/format-RyoGQL74.js.map +0 -1
  771. package/dist/_chunks/interception-BOoWmLUA.js +0 -676
  772. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  773. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  774. package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
  775. package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
  776. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  777. package/dist/_chunks/tracing-CemImE6h.js +0 -187
  778. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  779. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  780. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  781. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  782. package/dist/cache/register-cached-function.d.ts +0 -17
  783. package/dist/cache/register-cached-function.d.ts.map +0 -1
  784. package/dist/client/browser-entry.d.ts +0 -21
  785. package/dist/client/browser-entry.d.ts.map +0 -1
  786. package/dist/client/link-status-provider.d.ts +0 -11
  787. package/dist/client/link-status-provider.d.ts.map +0 -1
  788. package/dist/client/segment-merger.d.ts +0 -119
  789. package/dist/client/segment-merger.d.ts.map +0 -1
  790. package/dist/client/stale-reload.d.ts +0 -44
  791. package/dist/client/stale-reload.d.ts.map +0 -1
  792. package/dist/client/transition-root.d.ts +0 -74
  793. package/dist/client/transition-root.d.ts.map +0 -1
  794. package/dist/client/use-navigation-pending.d.ts +0 -26
  795. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  796. package/dist/client/use-params.d.ts.map +0 -1
  797. package/dist/plugins/cache-transform.d.ts +0 -36
  798. package/dist/plugins/cache-transform.d.ts.map +0 -1
  799. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  800. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  801. package/dist/plugins/dev-logs.d.ts.map +0 -1
  802. package/dist/plugins/dynamic-transform.d.ts +0 -72
  803. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  804. package/dist/plugins/server-action-exports.d.ts +0 -26
  805. package/dist/plugins/server-action-exports.d.ts.map +0 -1
  806. package/dist/routing/status-file-lint.d.ts +0 -33
  807. package/dist/routing/status-file-lint.d.ts.map +0 -1
  808. package/dist/search-params/analyze.d.ts +0 -54
  809. package/dist/search-params/analyze.d.ts.map +0 -1
  810. package/dist/search-params/builtin-codecs.d.ts +0 -105
  811. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  812. package/dist/search-params/codecs.d.ts +0 -53
  813. package/dist/search-params/codecs.d.ts.map +0 -1
  814. package/dist/search-params/create.d.ts +0 -106
  815. package/dist/search-params/create.d.ts.map +0 -1
  816. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  817. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  818. package/dist/server/dev-logger.d.ts.map +0 -1
  819. package/dist/server/dev-span-processor.d.ts +0 -29
  820. package/dist/server/dev-span-processor.d.ts.map +0 -1
  821. package/dist/server/dev-warnings.d.ts +0 -129
  822. package/dist/server/dev-warnings.d.ts.map +0 -1
  823. package/dist/server/flush.d.ts +0 -74
  824. package/dist/server/flush.d.ts.map +0 -1
  825. package/dist/server/manifest-status-resolver.d.ts +0 -58
  826. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  827. package/dist/server/prerender.d.ts +0 -77
  828. package/dist/server/prerender.d.ts.map +0 -1
  829. package/dist/utils/directive-parser.d.ts +0 -70
  830. package/dist/utils/directive-parser.d.ts.map +0 -1
  831. package/src/cache/register-cached-function.ts +0 -103
  832. package/src/client/browser-entry.ts +0 -678
  833. package/src/client/link-status-provider.tsx +0 -30
  834. package/src/client/segment-merger.ts +0 -339
  835. package/src/client/stale-reload.ts +0 -87
  836. package/src/client/transition-root.tsx +0 -166
  837. package/src/client/use-navigation-pending.ts +0 -38
  838. package/src/plugins/cache-transform.ts +0 -199
  839. package/src/plugins/dev-error-overlay.ts +0 -230
  840. package/src/plugins/dynamic-transform.ts +0 -161
  841. package/src/plugins/server-action-exports.ts +0 -220
  842. package/src/routing/status-file-lint.ts +0 -112
  843. package/src/search-params/analyze.ts +0 -192
  844. package/src/search-params/builtin-codecs.ts +0 -228
  845. package/src/search-params/codecs.ts +0 -153
  846. package/src/search-params/create.ts +0 -321
  847. package/src/server/dev-fetch-instrumentation.ts +0 -96
  848. package/src/server/dev-span-processor.ts +0 -78
  849. package/src/server/dev-warnings.ts +0 -283
  850. package/src/server/flush.ts +0 -182
  851. package/src/server/manifest-status-resolver.ts +0 -215
  852. package/src/server/prerender.ts +0 -139
  853. package/src/utils/directive-parser.ts +0 -529
  854. /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
@@ -6,9 +6,9 @@
6
6
  * rsc-entry.ts under the 500-line limit.
7
7
  *
8
8
  * This module handles:
9
- * 1. Loading page/layout components from the segment chain
10
- * 2. Running access.ts checks (DenySignal/RedirectSignal propagate to caller)
11
- * 3. Resolving metadata (static object or async function, both exported as `metadata`)
9
+ * 1. Running access.ts checks eagerly to gate metadata resolution (TIM-1027)
10
+ * 2. Loading page/layout components from the segment chain
11
+ * 3. Resolving metadata (skipped for denied segments to prevent side effects)
12
12
  * 4. Building the React element tree (page → error boundaries → access gates → layouts)
13
13
  * 5. Resolving parallel slots
14
14
  *
@@ -16,23 +16,106 @@
16
16
  */
17
17
 
18
18
  import { createElement } from 'react';
19
+ import { randomUUID } from 'node:crypto';
19
20
 
20
- import { withSpan, setSpanAttribute } from './tracing.js';
21
+ import { withSpan } from './tracing.js';
21
22
  import type { RouteMatch } from './pipeline.js';
22
23
  import type { ManifestSegmentNode } from './route-matcher.js';
23
24
  import { resolveMetadata, renderMetadataToElements } from './metadata.js';
24
- import type { HeadElement as MetadataHeadElement } from './metadata.js';
25
25
  import type { Metadata } from './types.js';
26
26
  import { METADATA_ROUTE_CONVENTIONS, getMetadataRouteAutoLink } from './metadata-routes.js';
27
+
28
+ // In dev mode, use a per-startup nonce for metadata route cache busting
29
+ // instead of per-file content hashes (avoids rehashing on every request).
30
+ let _devNonce: string | undefined;
31
+ function getDevNonce(): string {
32
+ _devNonce ??= randomUUID().slice(0, 8);
33
+ return _devNonce;
34
+ }
27
35
  import { DenySignal, RedirectSignal } from './primitives.js';
28
36
  import { AccessGate } from './access-gate.js';
37
+ import {
38
+ PageDenyBoundary,
39
+ buildDenyPageChain,
40
+ renderMatchingDenyPage,
41
+ setDenyStatus,
42
+ } from './deny-boundary.js';
43
+ import type { DenyPageEntry } from './deny-boundary.js';
29
44
  import { resolveSlotElement } from './slot-resolver.js';
30
- import { SegmentProvider } from '#/client/segment-context.js';
31
- import { setParsedSearchParams } from './request-context.js';
32
- import type { SearchParamsDefinition } from '#/search-params/create.js';
45
+ import { SegmentProvider } from '../client/segment-context.js';
46
+ import { SegmentOutlet } from '../client/segment-outlet.js';
47
+
33
48
  import { wrapSegmentWithErrorBoundaries } from './error-boundary-wrapper.js';
34
49
  import type { InterceptionContext } from './pipeline.js';
35
50
  import { shouldSkipSegment } from './state-tree-diff.js';
51
+ import { loadModule } from './safe-load.js';
52
+
53
+ /**
54
+ * Replace the outermost SegmentOutlet in a partial payload with its
55
+ * SegmentProvider child. Walks through AccessGate wrappers (which sit
56
+ * outside SegmentOutlet) to find the outlet.
57
+ */
58
+ function replaceOutermostSegmentOutlet(
59
+ element: React.ReactElement,
60
+ replacement: React.ReactElement
61
+ ): React.ReactElement {
62
+ if (element.type === SegmentOutlet) {
63
+ return replacement;
64
+ }
65
+ // AccessGate wraps outside SegmentOutlet — recurse through it.
66
+ const props = element.props as Record<string, unknown>;
67
+ if (element.type === AccessGate && props.children) {
68
+ const inner = replaceOutermostSegmentOutlet(props.children as React.ReactElement, replacement);
69
+ /* eslint-disable react/no-children-prop -- createElement API */
70
+ return createElement(element.type as React.FunctionComponent<Record<string, unknown>>, {
71
+ ...props,
72
+ children: inner,
73
+ });
74
+ /* eslint-enable react/no-children-prop */
75
+ }
76
+ return element;
77
+ }
78
+
79
+ // ─── Client Reference Detection ──────────────────────────────────────────
80
+
81
+ /**
82
+ * Symbol used by React Flight to mark client references.
83
+ * Client references are proxy objects created by @vitejs/plugin-rsc for
84
+ * 'use client' modules in the RSC environment. They must be passed to
85
+ * createElement() — calling them as functions throws:
86
+ * "Unexpectedly client reference export 'default' is called on server"
87
+ */
88
+ const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
89
+
90
+ /**
91
+ * Detect whether a component is a React client reference.
92
+ * Client references have $$typeof set to Symbol.for('react.client.reference')
93
+ * by registerClientReference() in the React Flight server runtime.
94
+ *
95
+ * Used to skip OTEL tracing wrappers that would call the component as a
96
+ * function. Client components must go through createElement only — they are
97
+ * serialized as references in the RSC Flight stream, not executed on the server.
98
+ */
99
+ export function isClientReference(component: unknown): boolean {
100
+ return (
101
+ component != null &&
102
+ typeof component === 'function' &&
103
+ (component as unknown as Record<string, unknown>).$$typeof === CLIENT_REFERENCE_TAG
104
+ );
105
+ }
106
+
107
+ // ─── Param Coercion Error ─────────────────────────────────────────────────
108
+
109
+ /**
110
+ * Thrown when a defineSegmentParams codec's parse() fails.
111
+ * The pipeline catches this and responds with 404.
112
+ */
113
+ export class ParamCoercionError extends Error {
114
+ constructor(message: string) {
115
+ super(message);
116
+ this.name = 'ParamCoercionError';
117
+ }
118
+ }
36
119
 
37
120
  // ─── Types ────────────────────────────────────────────────────────────────
38
121
 
@@ -70,18 +153,62 @@ export interface RouteElementResult {
70
153
  skippedSegments: string[];
71
154
  }
72
155
 
156
+ // ─── Module Processing Helpers ─────────────────────────────────────────────
157
+
158
+ /**
159
+ * Reject the legacy `generateMetadata` export with a helpful migration message.
160
+ * Throws if the module exports `generateMetadata` instead of `metadata`.
161
+ */
162
+ function rejectLegacyGenerateMetadata(mod: Record<string, unknown>, filePath: string): void {
163
+ if ('generateMetadata' in mod) {
164
+ throw new Error(
165
+ `${filePath}: "generateMetadata" is not a valid export. ` +
166
+ `Export an async function named "metadata" instead.\n\n` +
167
+ ` // Before\n` +
168
+ ` export async function generateMetadata({ params }) { ... }\n\n` +
169
+ ` // After\n` +
170
+ ` export async function metadata() { ... }`
171
+ );
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Extract and resolve metadata from a module (layout or page).
177
+ * Handles both static metadata objects and async metadata functions.
178
+ * Returns the resolved Metadata, or null if none exported.
179
+ *
180
+ * Metadata functions no longer receive { params } — they access params
181
+ * via getSegmentParams() from ALS, same as page/layout components.
182
+ */
183
+ async function extractMetadata(
184
+ mod: Record<string, unknown>,
185
+ segment: ManifestSegmentNode
186
+ ): Promise<Metadata | null> {
187
+ if (typeof mod.metadata === 'function') {
188
+ type MetadataFn = () => Promise<Metadata>;
189
+ return (
190
+ (await withSpan(
191
+ 'timber.metadata',
192
+ { 'timber.segment': segment.segmentName ?? segment.urlPath },
193
+ () => (mod.metadata as MetadataFn)()
194
+ )) ?? null
195
+ );
196
+ }
197
+ if (mod.metadata) {
198
+ return mod.metadata as Metadata;
199
+ }
200
+ return null;
201
+ }
202
+
73
203
  /**
74
- * Wraps a DenySignal or RedirectSignal with the layout components loaded
75
- * so far, enabling the caller to render deny pages inside the layout shell.
204
+ * Extract `deferSuspenseFor` from a module and return the maximum
205
+ * of the current value and the module's value.
76
206
  */
77
- export class RouteSignalWithContext extends Error {
78
- constructor(
79
- public readonly signal: DenySignal | RedirectSignal,
80
- public readonly layoutComponents: LayoutComponentEntry[],
81
- public readonly segments: ManifestSegmentNode[]
82
- ) {
83
- super(signal.message);
207
+ function extractDeferSuspenseFor(mod: Record<string, unknown>, current: number): number {
208
+ if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > current) {
209
+ return mod.deferSuspenseFor;
84
210
  }
211
+ return current;
85
212
  }
86
213
 
87
214
  // ─── Builder ──────────────────────────────────────────────────────────────
@@ -89,25 +216,68 @@ export class RouteSignalWithContext extends Error {
89
216
  /**
90
217
  * Build a React element tree from a matched route.
91
218
  *
92
- * Loads modules, runs access checks, resolves metadata, and constructs
93
- * the element tree. DenySignal and RedirectSignal propagate to the caller
94
- * for HTTP-level handling.
219
+ * Runs access checks eagerly to gate metadata resolution, then loads
220
+ * modules, resolves metadata (skipping denied segments), and constructs
221
+ * the element tree. DenySignal and RedirectSignal from access are stored
222
+ * as AccessGate verdicts for synchronous replay during render.
95
223
  *
96
224
  * Does NOT serialize to RSC Flight — the caller decides whether to render
97
225
  * to a stream or use the element directly (e.g., for action revalidation).
226
+ *
227
+ * For passing segments, AccessGate re-runs access during render so that
228
+ * React.cache is populated for layout dedup (TIM-662). For denied
229
+ * segments, the pre-computed verdict is replayed — no re-execution,
230
+ * no metadata side effects, no head leak (TIM-1027).
98
231
  */
99
232
  export async function buildRouteElement(
100
233
  req: Request,
101
234
  match: RouteMatch,
102
235
  interception?: InterceptionContext,
103
- clientStateTree?: Set<string> | null
236
+ clientStateTree?: Set<string> | null,
237
+ metadataRouteHashes?: Record<string, string>
104
238
  ): Promise<RouteElementResult> {
105
- const segments = match.segments as unknown as ManifestSegmentNode[];
239
+ const segments = match.segments;
240
+
241
+ // ── Access pre-pass ──────────────────────────────────────────────────
242
+ // Run access checks eagerly to determine which segments are denied.
243
+ // This gates metadata() resolution: denied segments' metadata functions
244
+ // are never called, preventing unauthorized side effects (DB queries)
245
+ // and metadata content leaking into the <head> of denied responses.
246
+ //
247
+ // Verdicts are passed to AccessGate for synchronous replay (DenySignal
248
+ // renders the deny page in-tree; RedirectSignal propagates). For PASSING
249
+ // segments, no verdict is passed — AccessGate re-runs access during
250
+ // renderToReadableStream to populate React.cache for layout dedup.
251
+ //
252
+ // See TIM-1027, design/04-authorization.md, design/13-security.md.
253
+ const accessVerdicts = new Map<number, DenySignal | RedirectSignal>();
254
+ let firstDeniedIndex = Infinity;
106
255
 
107
- // Params are passed as a Promise to match Next.js 15+ convention.
108
- const paramsPromise = Promise.resolve(match.params);
256
+ for (let i = 0; i < segments.length; i++) {
257
+ const segment = segments[i];
258
+ if (!segment.access || i >= firstDeniedIndex) continue;
259
+
260
+ try {
261
+ const accessMod = await loadModule(segment.access);
262
+ const accessFn = accessMod.default as (() => Promise<void>) | undefined;
263
+ if (accessFn) {
264
+ await withSpan(
265
+ 'timber.access.pre',
266
+ { 'timber.segment': segment.segmentName ?? 'unknown' },
267
+ () => accessFn()
268
+ );
269
+ }
270
+ } catch (error: unknown) {
271
+ if (error instanceof DenySignal || error instanceof RedirectSignal) {
272
+ accessVerdicts.set(i, error);
273
+ firstDeniedIndex = i;
274
+ } else {
275
+ throw error;
276
+ }
277
+ }
278
+ }
109
279
 
110
- // Load all modules along the segment chain
280
+ // ── Module loading + metadata resolution ─────────────────────────────
111
281
  const metadataEntries: Array<{ metadata: Metadata; isPage: boolean }> = [];
112
282
  const layoutComponents: LayoutComponentEntry[] = [];
113
283
  let PageComponent: ((...args: unknown[]) => unknown) | null = null;
@@ -116,152 +286,75 @@ export async function buildRouteElement(
116
286
  for (let i = 0; i < segments.length; i++) {
117
287
  const segment = segments[i];
118
288
  const isLeaf = i === segments.length - 1;
289
+ const isDenied = i >= firstDeniedIndex;
119
290
 
120
291
  // Load layout
121
292
  if (segment.layout) {
122
- const mod = (await segment.layout.load()) as Record<string, unknown>;
293
+ const mod = await loadModule(segment.layout);
123
294
  if (mod.default) {
124
295
  layoutComponents.push({
125
296
  component: mod.default as (...args: unknown[]) => unknown,
126
297
  segment,
127
298
  });
128
299
  }
129
- // Reject legacy generateMetadata export — use `export async function metadata()` instead
130
- if ('generateMetadata' in mod) {
131
- const filePath = segment.layout.filePath ?? segment.urlPath;
132
- throw new Error(
133
- `${filePath}: "generateMetadata" is not a valid export. ` +
134
- `Export an async function named "metadata" instead.\n\n` +
135
- ` // Before\n` +
136
- ` export async function generateMetadata({ params }) { ... }\n\n` +
137
- ` // After\n` +
138
- ` export async function metadata({ params }) { ... }`
139
- );
140
- }
141
- // Unified metadata export: static object or async function
142
- if (typeof mod.metadata === 'function') {
143
- type MetadataFn = (props: Record<string, unknown>) => Promise<Metadata>;
144
- const generated = await withSpan(
145
- 'timber.metadata',
146
- { 'timber.segment': segment.segmentName ?? segment.urlPath },
147
- () => (mod.metadata as MetadataFn)({ params: paramsPromise })
148
- );
149
- if (generated) {
150
- metadataEntries.push({ metadata: generated, isPage: false });
300
+
301
+ // Param coercion is handled in the pipeline (Stage 2c) before
302
+ // middleware and rendering. See coerceSegmentParams() in pipeline.ts.
303
+
304
+ rejectLegacyGenerateMetadata(mod, segment.layout.filePath ?? segment.urlPath);
305
+ if (!isDenied) {
306
+ const layoutMetadata = await extractMetadata(mod, segment);
307
+ if (layoutMetadata) {
308
+ metadataEntries.push({ metadata: layoutMetadata, isPage: false });
151
309
  }
152
- } else if (mod.metadata) {
153
- metadataEntries.push({ metadata: mod.metadata as Metadata, isPage: false });
154
- }
155
- // deferSuspenseFor hold window — max across all segments
156
- if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > deferSuspenseFor) {
157
- deferSuspenseFor = mod.deferSuspenseFor;
158
310
  }
311
+ deferSuspenseFor = extractDeferSuspenseFor(mod, deferSuspenseFor);
159
312
  }
160
313
 
161
314
  // Load page (leaf segment only)
162
315
  if (isLeaf && segment.page) {
163
- // Load and apply search-params.ts definition before rendering so
164
- // searchParams() from @timber-js/app/server returns parsed typed values.
165
- if (segment.searchParams) {
166
- const spMod = (await segment.searchParams.load()) as {
167
- default?: SearchParamsDefinition<Record<string, unknown>>;
168
- };
169
- if (spMod.default) {
170
- const rawSearchParams = new URL(req.url).searchParams;
171
- const parsed = spMod.default.parse(rawSearchParams);
172
- setParsedSearchParams(parsed);
173
- }
174
- }
316
+ const mod = await loadModule(segment.page);
317
+
318
+ // Param coercion is handled in the pipeline (Stage 2c) before
319
+ // middleware and rendering. See coerceSegmentParams() in pipeline.ts.
175
320
 
176
- const mod = (await segment.page.load()) as Record<string, unknown>;
177
321
  if (mod.default) {
178
322
  PageComponent = mod.default as (...args: unknown[]) => unknown;
179
323
  }
180
- // Reject legacy generateMetadata export — use `export async function metadata()` instead
181
- if ('generateMetadata' in mod) {
182
- const filePath = segment.page.filePath ?? segment.urlPath;
183
- throw new Error(
184
- `${filePath}: "generateMetadata" is not a valid export. ` +
185
- `Export an async function named "metadata" instead.\n\n` +
186
- ` // Before\n` +
187
- ` export async function generateMetadata({ params }) { ... }\n\n` +
188
- ` // After\n` +
189
- ` export async function metadata({ params }) { ... }`
190
- );
191
- }
192
- // Unified metadata export: static object or async function
193
- if (typeof mod.metadata === 'function') {
194
- type MetadataFn = (props: Record<string, unknown>) => Promise<Metadata>;
195
- const generated = await withSpan(
196
- 'timber.metadata',
197
- { 'timber.segment': segment.segmentName ?? segment.urlPath },
198
- () => (mod.metadata as MetadataFn)({ params: paramsPromise })
199
- );
200
- if (generated) {
201
- metadataEntries.push({ metadata: generated, isPage: true });
324
+ rejectLegacyGenerateMetadata(mod, segment.page.filePath ?? segment.urlPath);
325
+ if (!isDenied) {
326
+ const pageMetadata = await extractMetadata(mod, segment);
327
+ if (pageMetadata) {
328
+ metadataEntries.push({ metadata: pageMetadata, isPage: true });
202
329
  }
203
- } else if (mod.metadata) {
204
- metadataEntries.push({ metadata: mod.metadata as Metadata, isPage: true });
205
- }
206
- // deferSuspenseFor hold window — max across all segments
207
- if (typeof mod.deferSuspenseFor === 'number' && mod.deferSuspenseFor > deferSuspenseFor) {
208
- deferSuspenseFor = mod.deferSuspenseFor;
209
330
  }
331
+ deferSuspenseFor = extractDeferSuspenseFor(mod, deferSuspenseFor);
210
332
  }
211
333
  }
212
334
 
213
335
  if (!PageComponent) {
214
- throw new Error(`No page component found for route: ${new URL(req.url).pathname}`);
336
+ const segmentInfo = segments
337
+ .map(
338
+ (s, i) =>
339
+ ` [${i}] ${s.segmentName} (page: ${s.page ? 'yes' : 'no'}, layout: ${s.layout ? 'yes' : 'no'}, children: ${s.children?.length ?? 0})${i === segments.length - 1 ? ' ← leaf' : ''}`
340
+ )
341
+ .join('\n');
342
+ throw new Error(
343
+ `No page component found for route: ${new URL(req.url).pathname}\nMatched segments:\n${segmentInfo}`
344
+ );
215
345
  }
216
346
 
217
- // Run access.ts checks before rendering — top-down through the segment chain.
218
- // Verdicts are stored so AccessGate can replay them synchronously during
219
- // render, avoiding duplicate execution and Suspense timing issues.
220
- // DenySignal and RedirectSignal are wrapped with layout context so the caller
221
- // can render deny pages inside the layout shell.
222
- // See design/04-authorization.md §"access.ts Runs on Every Navigation".
223
- const accessVerdicts = new Map<number, 'pass' | DenySignal | RedirectSignal>();
224
-
225
- for (let si = 0; si < segments.length; si++) {
226
- const segment = segments[si];
227
- if (segment.access) {
228
- const accessMod = (await segment.access.load()) as Record<string, unknown>;
229
- const accessFn = accessMod.default as
230
- | ((ctx: { params: Record<string, string | string[]>; searchParams: unknown }) => unknown)
231
- | undefined;
232
- if (accessFn) {
233
- try {
234
- await withSpan(
235
- 'timber.access',
236
- { 'timber.segment': segment.segmentName ?? 'unknown' },
237
- async () => {
238
- try {
239
- await accessFn({ params: match.params, searchParams: {} });
240
- await setSpanAttribute('timber.result', 'pass');
241
- accessVerdicts.set(si, 'pass');
242
- } catch (error) {
243
- if (error instanceof DenySignal) {
244
- await setSpanAttribute('timber.result', 'deny');
245
- await setSpanAttribute('timber.deny_status', error.status);
246
- if (error.sourceFile) {
247
- await setSpanAttribute('timber.deny_file', error.sourceFile);
248
- }
249
- accessVerdicts.set(si, error);
250
- } else if (error instanceof RedirectSignal) {
251
- await setSpanAttribute('timber.result', 'redirect');
252
- accessVerdicts.set(si, error);
253
- }
254
- throw error;
255
- }
256
- }
257
- );
258
- } catch (error) {
259
- if (error instanceof DenySignal || error instanceof RedirectSignal) {
260
- throw new RouteSignalWithContext(error, layoutComponents, segments);
261
- }
262
- throw error;
263
- }
264
- }
347
+ // Build deny page fallback chains for each segment position.
348
+ // When AccessGate or PageDenyBoundary catches a DenySignal, they render
349
+ // the matching deny page in-tree instead of throwing into React Flight.
350
+ // The chain walks from the current segment outward to root, collecting
351
+ // status-code files (403.tsx → 4xx.tsx → error.tsx) in fallback order.
352
+ // See TIM-666.
353
+ const denyPageChains = new Map<number, DenyPageEntry[]>();
354
+ for (let i = 0; i < segments.length; i++) {
355
+ const chain = await buildDenyPageChain(segments, i);
356
+ if (chain.length > 0) {
357
+ denyPageChains.set(i, chain);
265
358
  }
266
359
  }
267
360
 
@@ -269,23 +362,63 @@ export async function buildRouteElement(
269
362
  const resolvedMetadata = resolveMetadata(metadataEntries);
270
363
  const headElements = renderMetadataToElements(resolvedMetadata);
271
364
 
272
- // Auto-link metadata route files (icon, apple-icon, manifest) from segments.
365
+ // Auto-link metadata route files (icon, apple-icon, manifest, opengraph-image).
366
+ // opengraph-image emits both og:image and twitter:image (no separate twitter-image convention).
367
+ // Skip OG auto-linking when the user already declared images in metadata.
273
368
  // See design/16-metadata.md §"Auto-Linking"
274
- for (const segment of segments) {
369
+ const hasUserOgImage = Boolean(resolvedMetadata.openGraph?.images);
370
+ const requestUrl = new URL(req.url);
371
+ const requestPathname = requestUrl.pathname;
372
+ // In dev mode, use the request origin so OG URLs resolve to localhost.
373
+ // In production, use metadataBase (the canonical domain).
374
+ const ogBase =
375
+ process.env.NODE_ENV !== 'production'
376
+ ? new URL(requestUrl.origin)
377
+ : resolvedMetadata.metadataBase;
378
+
379
+ for (let si = 0; si < segments.length; si++) {
380
+ const segment = segments[si];
275
381
  if (!segment.metadataRoutes) continue;
382
+ // Skip auto-linking for denied segments — same gate as metadata().
383
+ if (si >= firstDeniedIndex) continue;
276
384
  for (const baseName of Object.keys(segment.metadataRoutes)) {
277
385
  const convention = METADATA_ROUTE_CONVENTIONS[baseName];
278
386
  if (!convention) continue;
279
387
  // Non-nestable routes only auto-link from root
280
388
  if (!convention.nestable && segment.urlPath !== '/') continue;
281
- // Build the href: segment urlPath + serve path
282
- const prefix = segment.urlPath === '/' ? '' : segment.urlPath;
283
- const href = `${prefix}/${convention.servePath}`;
284
- const autoLink = getMetadataRouteAutoLink(convention.type, href);
285
- if (autoLink) {
286
- const attrs: Record<string, string> = { rel: autoLink.rel, href: autoLink.href };
287
- if (autoLink.type) attrs.type = autoLink.type;
288
- headElements.push({ tag: 'link', attrs } as MetadataHeadElement);
389
+ // Skip auto-linking if user already declared the image in metadata
390
+ if (convention.type === 'opengraph-image' && hasUserOgImage) continue;
391
+ // Build the href using the actual request path (not the pattern with [param]).
392
+ // For nestable routes, the metadata route sits under the same resolved path
393
+ // as the page. For root-only routes, use '/'.
394
+ const resolvedPrefix = convention.nestable
395
+ ? requestPathname === '/'
396
+ ? ''
397
+ : requestPathname
398
+ : '';
399
+ let href = `${resolvedPrefix}/${convention.servePath}`;
400
+ // Append cache-bust query param for image metadata routes
401
+ if (convention.type === 'opengraph-image') {
402
+ const metaFile = segment.metadataRoutes[baseName];
403
+ const fileHash = metaFile?.filePath ? metadataRouteHashes?.[metaFile.filePath] : undefined;
404
+ const cacheBust = fileHash ?? getDevNonce();
405
+ href = `${href}?${cacheBust}`;
406
+ }
407
+ // Resolve to absolute URL for og:image/twitter:image (social crawlers need full URLs)
408
+ if (ogBase && convention.type === 'opengraph-image') {
409
+ href = new URL(href, ogBase).toString();
410
+ }
411
+ for (const autoLink of getMetadataRouteAutoLink(convention.type, href)) {
412
+ if (autoLink.tag === 'link') {
413
+ const attrs: Record<string, string> = { rel: autoLink.rel, href: autoLink.href };
414
+ if (autoLink.type) attrs.type = autoLink.type;
415
+ headElements.push({ tag: 'link', attrs });
416
+ } else {
417
+ const attrs: Record<string, string> = { content: autoLink.content };
418
+ if (autoLink.property) attrs.property = autoLink.property;
419
+ if (autoLink.name) attrs.name = autoLink.name;
420
+ headElements.push({ tag: 'meta', attrs });
421
+ }
289
422
  }
290
423
  }
291
424
  }
@@ -293,19 +426,43 @@ export async function buildRouteElement(
293
426
  // Build element tree: page wrapped in layouts (innermost to outermost)
294
427
  const h = createElement as (...args: unknown[]) => React.ReactElement;
295
428
 
296
- // Wrap the page component in an OTEL span
297
- const TracedPage = async (props: Record<string, unknown>) => {
298
- return withSpan(
299
- 'timber.page',
300
- { 'timber.route': match.segments[match.segments.length - 1]?.urlPath ?? '/' },
301
- () => (PageComponent as (props: Record<string, unknown>) => unknown)(props)
302
- );
303
- };
304
-
305
- let element = h(TracedPage, {
306
- params: paramsPromise,
307
- searchParams: {},
308
- });
429
+ // Build the page element.
430
+ // Client references ('use client' pages) must NOT be called as functions —
431
+ // they are proxy objects that throw when invoked. They must go through
432
+ // createElement only, which serializes them as client references in the
433
+ // RSC Flight stream. OTEL tracing is skipped for client components.
434
+ // See TIM-627 for the original bug.
435
+ // Build the page element.
436
+ // Server component pages are wrapped in PageDenyBoundary which calls
437
+ // them as async functions and catches DenySignal — rendering the deny
438
+ // page in-tree instead of throwing into React Flight. This eliminates
439
+ // the second render pass for deny pages. See TIM-666.
440
+ //
441
+ // Client reference pages ('use client') can't call deny() (server-only),
442
+ // so they go through createElement normally — no wrapper needed.
443
+ const leafIndex = segments.length - 1;
444
+ const leafDenyPages = denyPageChains.get(leafIndex);
445
+ let element: React.ReactElement;
446
+ if (isClientReference(PageComponent)) {
447
+ element = h(PageComponent, {});
448
+ } else if (leafDenyPages && leafDenyPages.length > 0) {
449
+ // Server component page WITH deny page chain — wrap in PageDenyBoundary
450
+ element = h(PageDenyBoundary, {
451
+ Page: PageComponent,
452
+ route: match.segments[leafIndex]?.urlPath ?? '/',
453
+ denyPages: leafDenyPages,
454
+ });
455
+ } else {
456
+ // Server component page WITHOUT deny page chain — trace only
457
+ const TracedPage = async (props: Record<string, unknown>) => {
458
+ return withSpan(
459
+ 'timber.page',
460
+ { 'timber.route': match.segments[leafIndex]?.urlPath ?? '/' },
461
+ () => (PageComponent as (props: Record<string, unknown>) => unknown)(props)
462
+ );
463
+ };
464
+ element = h(TracedPage, {});
465
+ }
309
466
 
310
467
  // Build a lookup of layout components by segment for O(1) access.
311
468
  const layoutBySegment = new Map(
@@ -324,7 +481,7 @@ export async function buildRouteElement(
324
481
  //
325
482
  // When clientStateTree is provided (from X-Timber-State-Tree header on
326
483
  // client navigation), sync layouts the client already has are skipped.
327
- // Access.ts already ran for ALL segments in the pre-render loop above.
484
+ // Access.ts was pre-checked eagerly above for metadata gating (TIM-1027).
328
485
  // See design/19-client-navigation.md §"X-Timber-State-Tree Header"
329
486
  //
330
487
  // hasRenderedLayoutBelow tracks whether a non-skipped layout has been
@@ -335,6 +492,12 @@ export async function buildRouteElement(
335
492
  // Without this guard, skipping the innermost layout causes the merger
336
493
  // to drop the layout entirely and replace it with just the page.
337
494
  let hasRenderedLayoutBelow = false;
495
+ let outermostSegmentProvider: React.ReactElement | null = null;
496
+ // Track whether any rendered inner layout also exists in the client's
497
+ // state tree. This prevents cross-section skipping: e.g., navigating
498
+ // from /(group-a) to /dashboard shouldn't skip root "/" because the
499
+ // client has no mounted outlet at "/dashboard".
500
+ let innerRenderedInClientTree = false;
338
501
 
339
502
  for (let i = segments.length - 1; i >= 0; i--) {
340
503
  const segment = segments[i];
@@ -351,17 +514,43 @@ export async function buildRouteElement(
351
514
  // - Route groups are never skipped because sibling groups share the
352
515
  // same urlPath (e.g., /(marketing) and /(app) both have "/"),
353
516
  // which would cause the wrong cached layout to be reused
517
+ // - At least one inner rendered layout must exist in the client's
518
+ // state tree, ensuring the client has a mounted outlet to receive
519
+ // the partial payload
354
520
  const skip =
355
521
  shouldSkipSegment(segment.urlPath, layoutComponent, isLeaf, clientStateTree ?? null) &&
356
522
  hasRenderedLayoutBelow &&
357
- segment.segmentType !== 'group';
523
+ segment.segmentType !== 'group' &&
524
+ innerRenderedInClientTree;
358
525
 
359
526
  if (skip) {
360
- // Skip this segment entirely — the client uses its cached version.
361
- // Access.ts already ran in the pre-render loop (security guarantee).
527
+ // Skip this segment's layout/error boundaries — the client uses its cached version.
362
528
  // Metadata was already resolved above (head elements are correct).
363
529
  // Record for X-Timber-Skipped-Segments header (outermost first, so prepend).
364
530
  skippedSegments.unshift(segment.urlPath);
531
+
532
+ // SECURITY: Even though the layout is skipped, AccessGate MUST still
533
+ // wrap the element tree. access.ts runs on every navigation regardless
534
+ // of cached layouts or state tree content.
535
+ // See design/13-security.md §"Auth always runs" (test #11).
536
+ if (segment.access) {
537
+ const accessMod = await loadModule(segment.access);
538
+ const accessFn = accessMod.default as (() => unknown) | undefined;
539
+ if (accessFn) {
540
+ // Pass verdict for denied/redirected segments so AccessGate replays
541
+ // without re-execution. Passing segments omit verdict so AccessGate
542
+ // re-runs access during render for React.cache population.
543
+ const verdict = accessVerdicts.get(i);
544
+ element = h(AccessGate, {
545
+ accessFn,
546
+ segmentName: segment.segmentName,
547
+ denyPages: denyPageChains.get(i),
548
+ ...(verdict ? { verdict } : {}),
549
+ children: element,
550
+ });
551
+ }
552
+ }
553
+
365
554
  continue;
366
555
  }
367
556
 
@@ -369,86 +558,156 @@ export async function buildRouteElement(
369
558
  // a rendered layout below them and can safely be skipped.
370
559
  if (layoutComponent) {
371
560
  hasRenderedLayoutBelow = true;
561
+ // Use segmentId for the client state tree check. Route groups share
562
+ // their parent's urlPath (both "/"), but their segmentId includes
563
+ // the group name (e.g., "/(group-a)"), so the check correctly
564
+ // fails when the client has never visited that group.
565
+ const outletKey =
566
+ segment.segmentType === 'group'
567
+ ? `${segment.urlPath === '/' ? '' : segment.urlPath}/${segment.segmentName}`
568
+ : segment.urlPath;
569
+ if (clientStateTree?.has(outletKey)) {
570
+ innerRenderedInClientTree = true;
571
+ }
372
572
  }
373
573
 
374
574
  // Wrap with error boundaries from this segment (inside layout).
575
+ // Keep ALL error boundaries (including 4xx) — they're the safety net for
576
+ // DenySignal from nested server components that escape AccessGate/PageDenyBoundary
577
+ // try/catch. Status-code files must be 'use client' TSX or MDX to serialize
578
+ // as error boundary fallbacks. See TIM-666.
375
579
  element = await wrapSegmentWithErrorBoundaries(segment, element, h);
376
580
 
377
- // Wrap in AccessGate if segment has access.ts.
378
- // Pass the pre-computed verdict so AccessGate replays it synchronously
379
- // instead of re-calling accessFn (dedup + Suspense immunity).
380
- if (segment.access) {
381
- const accessMod = (await segment.access.load()) as Record<string, unknown>;
382
- const accessFn = accessMod.default as
383
- | ((ctx: { params: Record<string, string | string[]>; searchParams: unknown }) => unknown)
384
- | undefined;
385
- if (accessFn) {
386
- element = h(AccessGate, {
387
- accessFn,
388
- params: match.params,
389
- searchParams: {},
390
- segmentName: segment.segmentName,
391
- verdict: accessVerdicts.get(i),
392
- children: element,
393
- });
394
- }
395
- }
396
-
397
- // Wrap with layout if this segment has one — traced with OTEL span
581
+ // Wrap with layout BEFORE AccessGate — AccessGate is OUTSIDE the layout.
582
+ // When AccessGate denies, the layout never renders. The deny page appears
583
+ // at the AccessGate level, wrapped by PARENT layouts only.
584
+ // This prevents leaking layout UI (sidebars, nav) on denied pages.
585
+ // See design/04-authorization.md §"Access Failure".
398
586
  if (layoutComponent) {
399
- // Resolve parallel slots for this layout
587
+ // Resolve parallel slots for this layout.
588
+ // Compute the parent tree path so slots can build their full
589
+ // segment path for per-slot param storage in ALS.
590
+ const parentTreePath =
591
+ '/' +
592
+ segments
593
+ .slice(0, i + 1)
594
+ .map((s) => s.segmentName)
595
+ .filter(Boolean)
596
+ .join('/');
400
597
  const slotProps: Record<string, unknown> = {};
401
598
  const slotEntries = Object.entries(segment.slots ?? {});
402
599
  for (const [slotName, slotNode] of slotEntries) {
403
600
  slotProps[slotName] = await resolveSlotElement(
404
601
  slotNode as ManifestSegmentNode,
405
602
  match,
406
- paramsPromise,
407
603
  h,
408
- interception
604
+ interception,
605
+ parentTreePath
409
606
  );
410
607
  }
411
608
 
412
609
  const segmentPath = segment.urlPath.split('/');
413
610
  const parallelRouteKeys = Object.keys(segment.slots ?? {});
414
611
 
415
- // Wrap the layout component in an OTEL span.
416
- // For route groups, urlPath is "/" (groups don't add URL segments), so
417
- // include the directory name to distinguish e.g. "layout /(pre-release)"
418
- // from the root "layout /".
419
- const segmentForSpan = segment;
420
- const layoutComponentForSpan = layoutComponent;
421
- const segmentLabel =
422
- segmentForSpan.segmentType === 'group'
423
- ? `${segmentForSpan.urlPath === '/' ? '' : segmentForSpan.urlPath}/${segmentForSpan.segmentName}`
424
- : segmentForSpan.urlPath;
425
- const TracedLayout = async (props: Record<string, unknown>) => {
426
- return withSpan('timber.layout', { 'timber.segment': segmentLabel }, () =>
427
- (layoutComponentForSpan as (props: Record<string, unknown>) => unknown)(props)
428
- );
429
- };
430
-
431
- // segmentId uniquely identifies this segment for client-side element
432
- // caching. For route groups, urlPath is shared with the parent (both "/"),
433
- // so we include the group name to distinguish them. Without this, the
434
- // segment merger's element cache would conflate root and group elements.
612
+ // For route groups, urlPath is shared with the parent (both "/"),
613
+ // so include the group name to distinguish them. Used for both OTEL
614
+ // span labels and client-side element caching (segmentId).
435
615
  const segmentId =
436
616
  segment.segmentType === 'group'
437
617
  ? `${segment.urlPath === '/' ? '' : segment.urlPath}/${segment.segmentName}`
438
618
  : segment.urlPath;
439
619
 
440
- element = h(SegmentProvider, {
620
+ // Build the layout element.
621
+ // Same client reference guard as pages — client layouts must not be
622
+ // called as functions. OTEL tracing is skipped for client components.
623
+ let layoutElement: React.ReactElement;
624
+ if (isClientReference(layoutComponent)) {
625
+ layoutElement = h(layoutComponent, {
626
+ ...slotProps,
627
+ children: element,
628
+ });
629
+ } else {
630
+ // Server component layout — wrap with OTEL tracing AND DenySignal
631
+ // catching. If the layout calls deny(), the signal is caught here
632
+ // and the matching deny page renders in-tree (same pattern as
633
+ // AccessGate and PageDenyBoundary). Without this, DenySignal
634
+ // escapes to React Flight onError and triggers the re-render
635
+ // fallback path. See TIM-668, design/04-authorization.md.
636
+ const layoutComponentRef = layoutComponent;
637
+ const layoutDenyPages = denyPageChains.get(i);
638
+ const TracedLayout = async (props: Record<string, unknown>) => {
639
+ try {
640
+ return await withSpan('timber.layout', { 'timber.segment': segmentId }, () =>
641
+ (layoutComponentRef as (props: Record<string, unknown>) => unknown)(props)
642
+ );
643
+ } catch (error: unknown) {
644
+ if (error instanceof DenySignal && layoutDenyPages) {
645
+ const denyElement = renderMatchingDenyPage(layoutDenyPages, error.status, error.data);
646
+ if (denyElement) {
647
+ setDenyStatus(error.status);
648
+ return denyElement;
649
+ }
650
+ }
651
+ // Non-deny errors (RedirectSignal, runtime errors) propagate normally.
652
+ throw error;
653
+ }
654
+ };
655
+ layoutElement = h(TracedLayout, {
656
+ ...slotProps,
657
+ children: element,
658
+ });
659
+ }
660
+
661
+ const segmentProviderElement = h(SegmentProvider, {
441
662
  segments: segmentPath,
442
663
  segmentId,
443
664
  parallelRouteKeys,
444
- children: h(TracedLayout, {
445
- ...slotProps,
446
- params: paramsPromise,
447
- searchParams: {},
448
- children: element,
449
- }),
665
+ children: layoutElement,
450
666
  });
667
+
668
+ element = h(SegmentOutlet, {
669
+ segmentPath: segmentId,
670
+ children: segmentProviderElement,
671
+ });
672
+
673
+ // Track the SegmentProvider for the outermost rendered layout.
674
+ // On partial navigation (segments skipped above), the client already
675
+ // has a SegmentOutlet mounted at this position. Sending another one
676
+ // in the payload causes double-wrapping and infinite context recursion.
677
+ // We'll strip the outermost SegmentOutlet after the loop.
678
+ outermostSegmentProvider = segmentProviderElement;
451
679
  }
680
+
681
+ // Wrap in AccessGate OUTSIDE the layout.
682
+ // If access denies, the deny page renders here — the layout above
683
+ // never executes. Parent layouts (from outer iterations) form the shell.
684
+ // See TIM-662, TIM-666, design/04-authorization.md §"Access Failure".
685
+ if (segment.access) {
686
+ const accessMod = await loadModule(segment.access);
687
+ const accessFn = accessMod.default as (() => unknown) | undefined;
688
+ if (accessFn) {
689
+ // Pass verdict for denied/redirected segments so AccessGate replays
690
+ // without re-execution. Passing segments omit verdict so AccessGate
691
+ // re-runs access during render for React.cache population.
692
+ const verdict = accessVerdicts.get(i);
693
+ element = h(AccessGate, {
694
+ accessFn,
695
+ segmentName: segment.segmentName,
696
+ denyPages: denyPageChains.get(i),
697
+ ...(verdict ? { verdict } : {}),
698
+ children: element,
699
+ });
700
+ }
701
+ }
702
+ }
703
+
704
+ // On partial navigation (some segments skipped), the client already has a
705
+ // SegmentOutlet mounted at the outermost non-skipped segment's position.
706
+ // Sending another SegmentOutlet in the payload causes double-wrapping —
707
+ // the inner outlet reads the same context update and recurses infinitely.
708
+ // Replace the outermost SegmentOutlet with just its SegmentProvider child.
709
+ if (skippedSegments.length > 0 && outermostSegmentProvider) {
710
+ element = replaceOutermostSegmentOutlet(element, outermostSegmentProvider);
452
711
  }
453
712
 
454
713
  return {