@timber-js/app 0.2.0-alpha.14 → 0.2.0-alpha.141

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 (801) hide show
  1. package/dist/_chunks/actions-DzFMnUAR.js +1147 -0
  2. package/dist/_chunks/actions-DzFMnUAR.js.map +1 -0
  3. package/dist/_chunks/build-output-helper-B20ZuTSA.js +102 -0
  4. package/dist/_chunks/build-output-helper-B20ZuTSA.js.map +1 -0
  5. package/dist/_chunks/cli-schema-sync-D2IpXicg.js +785 -0
  6. package/dist/_chunks/cli-schema-sync-D2IpXicg.js.map +1 -0
  7. package/dist/_chunks/cli-schema-sync-DH-M8Poy.js +2 -0
  8. package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
  9. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
  10. package/dist/_chunks/define-C3RvHQPK.js +195 -0
  11. package/dist/_chunks/define-C3RvHQPK.js.map +1 -0
  12. package/dist/_chunks/define-DMVhsipD.js +112 -0
  13. package/dist/_chunks/define-DMVhsipD.js.map +1 -0
  14. package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
  15. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
  16. package/dist/_chunks/format-CfwjgPz9.js +14 -0
  17. package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
  18. package/dist/_chunks/handler-store-DjISKYEB.js +54 -0
  19. package/dist/_chunks/handler-store-DjISKYEB.js.map +1 -0
  20. package/dist/_chunks/href-validation-EZktELp8.js +124 -0
  21. package/dist/_chunks/href-validation-EZktELp8.js.map +1 -0
  22. package/dist/_chunks/logger-Dt-jQaBO.js +291 -0
  23. package/dist/_chunks/logger-Dt-jQaBO.js.map +1 -0
  24. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BjepjefT.js} +32 -19
  25. package/dist/_chunks/metadata-routes-BjepjefT.js.map +1 -0
  26. package/dist/_chunks/navigation-root-DLc4s4ZC.js +103 -0
  27. package/dist/_chunks/navigation-root-DLc4s4ZC.js.map +1 -0
  28. package/dist/_chunks/registry-DbJPKoBp.js +20 -0
  29. package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
  30. package/dist/_chunks/resolve-schema-Dj8tQloi.js +77 -0
  31. package/dist/_chunks/resolve-schema-Dj8tQloi.js.map +1 -0
  32. package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
  33. package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
  34. package/dist/_chunks/schema-bridge-DK_89h8O.js +86 -0
  35. package/dist/_chunks/schema-bridge-DK_89h8O.js.map +1 -0
  36. package/dist/_chunks/segment-classify-CDDRVKs7.js +137 -0
  37. package/dist/_chunks/segment-classify-CDDRVKs7.js.map +1 -0
  38. package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
  39. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
  40. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
  41. package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
  42. package/dist/_chunks/tracing-M_zKubhk.js +358 -0
  43. package/dist/_chunks/tracing-M_zKubhk.js.map +1 -0
  44. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-CbeQmext.js} +7 -20
  45. package/dist/_chunks/use-query-states-CbeQmext.js.map +1 -0
  46. package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
  47. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
  48. package/dist/_chunks/validation-taUkvA4Q.js +113 -0
  49. package/dist/_chunks/validation-taUkvA4Q.js.map +1 -0
  50. package/dist/_chunks/walkers-7FBPM-hX.js +724 -0
  51. package/dist/_chunks/walkers-7FBPM-hX.js.map +1 -0
  52. package/dist/_chunks/{format-RyoGQL74.js → warnings-CNPXaypM.js} +6 -45
  53. package/dist/_chunks/warnings-CNPXaypM.js.map +1 -0
  54. package/dist/adapters/build-output-helper.d.ts +28 -0
  55. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  56. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  57. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  58. package/dist/adapters/cloudflare-dev.js +73 -0
  59. package/dist/adapters/cloudflare-dev.js.map +1 -0
  60. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  61. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  62. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  63. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  64. package/dist/adapters/cloudflare.d.ts +148 -12
  65. package/dist/adapters/cloudflare.d.ts.map +1 -1
  66. package/dist/adapters/cloudflare.js +142 -38
  67. package/dist/adapters/cloudflare.js.map +1 -1
  68. package/dist/adapters/compress-module.d.ts.map +1 -1
  69. package/dist/adapters/nitro.d.ts +17 -1
  70. package/dist/adapters/nitro.d.ts.map +1 -1
  71. package/dist/adapters/nitro.js +154 -48
  72. package/dist/adapters/nitro.js.map +1 -1
  73. package/dist/adapters/shared.d.ts +16 -0
  74. package/dist/adapters/shared.d.ts.map +1 -0
  75. package/dist/cache/cache-api.d.ts +24 -0
  76. package/dist/cache/cache-api.d.ts.map +1 -0
  77. package/dist/cache/handler-store.d.ts +31 -0
  78. package/dist/cache/handler-store.d.ts.map +1 -0
  79. package/dist/cache/index.d.ts +23 -7
  80. package/dist/cache/index.d.ts.map +1 -1
  81. package/dist/cache/index.js +165 -117
  82. package/dist/cache/index.js.map +1 -1
  83. package/dist/cache/singleflight.d.ts +18 -1
  84. package/dist/cache/singleflight.d.ts.map +1 -1
  85. package/dist/cache/sizeof.d.ts +22 -0
  86. package/dist/cache/sizeof.d.ts.map +1 -0
  87. package/dist/cache/timber-cache.d.ts +1 -1
  88. package/dist/cache/timber-cache.d.ts.map +1 -1
  89. package/dist/cli-schema-sync.d.ts +39 -0
  90. package/dist/cli-schema-sync.d.ts.map +1 -0
  91. package/dist/cli.d.ts +14 -2
  92. package/dist/cli.d.ts.map +1 -1
  93. package/dist/cli.js +48 -6
  94. package/dist/cli.js.map +1 -1
  95. package/dist/client/browser-dev.d.ts +34 -1
  96. package/dist/client/browser-dev.d.ts.map +1 -1
  97. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  98. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  99. package/dist/client/browser-entry/hmr.d.ts +21 -0
  100. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  101. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  102. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  103. package/dist/client/browser-entry/index.d.ts +30 -0
  104. package/dist/client/browser-entry/index.d.ts.map +1 -0
  105. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  106. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  107. package/dist/client/browser-entry/router-init.d.ts +26 -0
  108. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  109. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  110. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  111. package/dist/client/browser-entry/scroll.d.ts +19 -0
  112. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  113. package/dist/client/error-boundary.d.ts +12 -5
  114. package/dist/client/error-boundary.d.ts.map +1 -1
  115. package/dist/client/error-boundary.js +29 -6
  116. package/dist/client/error-boundary.js.map +1 -1
  117. package/dist/client/error-reconstituter.d.ts +54 -0
  118. package/dist/client/error-reconstituter.d.ts.map +1 -0
  119. package/dist/client/form.d.ts +16 -27
  120. package/dist/client/form.d.ts.map +1 -1
  121. package/dist/client/history.d.ts +19 -4
  122. package/dist/client/history.d.ts.map +1 -1
  123. package/dist/client/index.d.ts +10 -24
  124. package/dist/client/index.d.ts.map +1 -1
  125. package/dist/client/index.js +183 -1134
  126. package/dist/client/index.js.map +1 -1
  127. package/dist/client/internal.d.ts +19 -0
  128. package/dist/client/internal.d.ts.map +1 -0
  129. package/dist/client/internal.js +925 -0
  130. package/dist/client/internal.js.map +1 -0
  131. package/dist/client/link-pending-store.d.ts +65 -0
  132. package/dist/client/link-pending-store.d.ts.map +1 -0
  133. package/dist/client/link.d.ts +69 -60
  134. package/dist/client/link.d.ts.map +1 -1
  135. package/dist/client/nav-link-store.d.ts +27 -0
  136. package/dist/client/nav-link-store.d.ts.map +1 -0
  137. package/dist/client/navigation-api-types.d.ts +90 -0
  138. package/dist/client/navigation-api-types.d.ts.map +1 -0
  139. package/dist/client/navigation-api.d.ts +115 -0
  140. package/dist/client/navigation-api.d.ts.map +1 -0
  141. package/dist/client/navigation-context.d.ts +14 -2
  142. package/dist/client/navigation-context.d.ts.map +1 -1
  143. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +46 -9
  144. package/dist/client/navigation-root.d.ts.map +1 -0
  145. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  146. package/dist/client/router-ref.d.ts +1 -1
  147. package/dist/client/router.d.ts +79 -10
  148. package/dist/client/router.d.ts.map +1 -1
  149. package/dist/client/rsc-fetch.d.ts +46 -3
  150. package/dist/client/rsc-fetch.d.ts.map +1 -1
  151. package/dist/client/segment-cache.d.ts +3 -1
  152. package/dist/client/segment-cache.d.ts.map +1 -1
  153. package/dist/client/segment-outlet.d.ts +49 -0
  154. package/dist/client/segment-outlet.d.ts.map +1 -0
  155. package/dist/client/segment-update-context.d.ts +21 -0
  156. package/dist/client/segment-update-context.d.ts.map +1 -0
  157. package/dist/client/shallow-url.d.ts +10 -0
  158. package/dist/client/shallow-url.d.ts.map +1 -0
  159. package/dist/client/ssr-data.d.ts +13 -4
  160. package/dist/client/ssr-data.d.ts.map +1 -1
  161. package/dist/client/stale-reload.d.ts +15 -0
  162. package/dist/client/stale-reload.d.ts.map +1 -1
  163. package/dist/client/state.d.ts +1 -1
  164. package/dist/client/top-loader.d.ts +5 -5
  165. package/dist/client/top-loader.d.ts.map +1 -1
  166. package/dist/client/use-cookie.d.ts +12 -0
  167. package/dist/client/use-cookie.d.ts.map +1 -1
  168. package/dist/client/use-link-status.d.ts +5 -5
  169. package/dist/client/use-link-status.d.ts.map +1 -1
  170. package/dist/client/use-pathname.d.ts.map +1 -1
  171. package/dist/client/use-pending-navigation.d.ts +23 -0
  172. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  173. package/dist/client/use-query-states.d.ts +1 -1
  174. package/dist/client/use-query-states.d.ts.map +1 -1
  175. package/dist/client/use-router.d.ts +1 -1
  176. package/dist/client/use-router.d.ts.map +1 -1
  177. package/dist/client/use-search-params.d.ts +7 -5
  178. package/dist/client/use-search-params.d.ts.map +1 -1
  179. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
  180. package/dist/client/use-segment-params.d.ts.map +1 -0
  181. package/dist/codec.d.ts +69 -0
  182. package/dist/codec.d.ts.map +1 -0
  183. package/dist/codec.js +75 -0
  184. package/dist/codec.js.map +1 -0
  185. package/dist/config-types.d.ts +294 -0
  186. package/dist/config-types.d.ts.map +1 -0
  187. package/dist/config-validation.d.ts +51 -0
  188. package/dist/config-validation.d.ts.map +1 -0
  189. package/dist/content/index.d.ts +1 -10
  190. package/dist/content/index.d.ts.map +1 -1
  191. package/dist/content/index.js +0 -2
  192. package/dist/cookies/define-cookie.d.ts +58 -25
  193. package/dist/cookies/define-cookie.d.ts.map +1 -1
  194. package/dist/cookies/index.d.ts +2 -1
  195. package/dist/cookies/index.d.ts.map +1 -1
  196. package/dist/cookies/index.js +251 -36
  197. package/dist/cookies/index.js.map +1 -1
  198. package/dist/cookies/json-cookie.d.ts +64 -0
  199. package/dist/cookies/json-cookie.d.ts.map +1 -0
  200. package/dist/cookies/validation.d.ts +34 -0
  201. package/dist/cookies/validation.d.ts.map +1 -0
  202. package/dist/dev-tools/404-page.d.ts +46 -0
  203. package/dist/dev-tools/404-page.d.ts.map +1 -0
  204. package/dist/dev-tools/browser-logs.d.ts +84 -0
  205. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  206. package/dist/dev-tools/error-page.d.ts +58 -0
  207. package/dist/dev-tools/error-page.d.ts.map +1 -0
  208. package/dist/dev-tools/holding-server.d.ts +54 -0
  209. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  210. package/dist/dev-tools/index.d.ts +31 -0
  211. package/dist/dev-tools/index.d.ts.map +1 -0
  212. package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
  213. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  214. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  215. package/dist/dev-tools/logger.d.ts.map +1 -0
  216. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
  217. package/dist/dev-tools/logs.d.ts.map +1 -0
  218. package/dist/dev-tools/overlay.d.ts +91 -0
  219. package/dist/dev-tools/overlay.d.ts.map +1 -0
  220. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  221. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  222. package/dist/dev-tools/terminal.d.ts +28 -0
  223. package/dist/dev-tools/terminal.d.ts.map +1 -0
  224. package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
  225. package/dist/dev-tools/warnings.d.ts.map +1 -0
  226. package/dist/fonts/ast.d.ts +98 -6
  227. package/dist/fonts/ast.d.ts.map +1 -1
  228. package/dist/fonts/bundle.d.ts +48 -0
  229. package/dist/fonts/bundle.d.ts.map +1 -0
  230. package/dist/fonts/dev-middleware.d.ts +22 -0
  231. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  232. package/dist/fonts/local.d.ts +1 -1
  233. package/dist/fonts/pipeline.d.ts +172 -0
  234. package/dist/fonts/pipeline.d.ts.map +1 -0
  235. package/dist/fonts/transform.d.ts +78 -0
  236. package/dist/fonts/transform.d.ts.map +1 -0
  237. package/dist/fonts/types.d.ts +47 -1
  238. package/dist/fonts/types.d.ts.map +1 -1
  239. package/dist/fonts/virtual-modules.d.ts +94 -0
  240. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  241. package/dist/index.d.ts +46 -180
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +5315 -12687
  244. package/dist/index.js.map +1 -1
  245. package/dist/params/codec-registry.d.ts +26 -0
  246. package/dist/params/codec-registry.d.ts.map +1 -0
  247. package/dist/params/define-schema.d.ts +81 -0
  248. package/dist/params/define-schema.d.ts.map +1 -0
  249. package/dist/params/index.d.ts +5 -0
  250. package/dist/params/index.d.ts.map +1 -0
  251. package/dist/params/index.js +34 -0
  252. package/dist/params/index.js.map +1 -0
  253. package/dist/params/resolve-schema.d.ts +34 -0
  254. package/dist/params/resolve-schema.d.ts.map +1 -0
  255. package/dist/plugin-context.d.ts +114 -0
  256. package/dist/plugin-context.d.ts.map +1 -0
  257. package/dist/plugins/adapter-build.d.ts +20 -1
  258. package/dist/plugins/adapter-build.d.ts.map +1 -1
  259. package/dist/plugins/build-manifest.d.ts +7 -3
  260. package/dist/plugins/build-manifest.d.ts.map +1 -1
  261. package/dist/plugins/build-report.d.ts +9 -7
  262. package/dist/plugins/build-report.d.ts.map +1 -1
  263. package/dist/plugins/cache.d.ts +31 -0
  264. package/dist/plugins/cache.d.ts.map +1 -0
  265. package/dist/plugins/client-chunks.d.ts +39 -0
  266. package/dist/plugins/client-chunks.d.ts.map +1 -0
  267. package/dist/plugins/cloudflare-wasm.d.ts +18 -0
  268. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  269. package/dist/plugins/content.d.ts +1 -1
  270. package/dist/plugins/content.d.ts.map +1 -1
  271. package/dist/plugins/dev-server.d.ts +1 -1
  272. package/dist/plugins/dev-server.d.ts.map +1 -1
  273. package/dist/plugins/entries.d.ts +1 -1
  274. package/dist/plugins/entries.d.ts.map +1 -1
  275. package/dist/plugins/fonts.d.ts +17 -73
  276. package/dist/plugins/fonts.d.ts.map +1 -1
  277. package/dist/plugins/mdx.d.ts +1 -1
  278. package/dist/plugins/mdx.d.ts.map +1 -1
  279. package/dist/plugins/routing.d.ts +1 -1
  280. package/dist/plugins/routing.d.ts.map +1 -1
  281. package/dist/plugins/server-bundle.d.ts.map +1 -1
  282. package/dist/plugins/shims.d.ts +6 -5
  283. package/dist/plugins/shims.d.ts.map +1 -1
  284. package/dist/plugins/static-build.d.ts +5 -26
  285. package/dist/plugins/static-build.d.ts.map +1 -1
  286. package/dist/routing/codegen-shared.d.ts +67 -0
  287. package/dist/routing/codegen-shared.d.ts.map +1 -0
  288. package/dist/routing/codegen-types.d.ts +60 -0
  289. package/dist/routing/codegen-types.d.ts.map +1 -0
  290. package/dist/routing/codegen.d.ts +7 -2
  291. package/dist/routing/codegen.d.ts.map +1 -1
  292. package/dist/routing/convention-lint.d.ts +41 -0
  293. package/dist/routing/convention-lint.d.ts.map +1 -0
  294. package/dist/routing/index.d.ts +7 -1
  295. package/dist/routing/index.d.ts.map +1 -1
  296. package/dist/routing/index.js +4 -2
  297. package/dist/routing/link-codegen.d.ts +90 -0
  298. package/dist/routing/link-codegen.d.ts.map +1 -0
  299. package/dist/routing/scanner.d.ts +1 -10
  300. package/dist/routing/scanner.d.ts.map +1 -1
  301. package/dist/routing/schema-validation.d.ts +35 -0
  302. package/dist/routing/schema-validation.d.ts.map +1 -0
  303. package/dist/routing/segment-classify.d.ts +75 -0
  304. package/dist/routing/segment-classify.d.ts.map +1 -0
  305. package/dist/routing/segment-codegen.d.ts +38 -0
  306. package/dist/routing/segment-codegen.d.ts.map +1 -0
  307. package/dist/routing/types.d.ts +77 -25
  308. package/dist/routing/types.d.ts.map +1 -1
  309. package/dist/routing/walkers.d.ts +51 -0
  310. package/dist/routing/walkers.d.ts.map +1 -0
  311. package/dist/rsc-runtime/rsc.d.ts +1 -1
  312. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  313. package/dist/rsc-runtime/ssr.d.ts +12 -0
  314. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  315. package/dist/schema-bridge.d.ts +76 -0
  316. package/dist/schema-bridge.d.ts.map +1 -0
  317. package/dist/search-params/define.d.ts +157 -0
  318. package/dist/search-params/define.d.ts.map +1 -0
  319. package/dist/search-params/index.d.ts +4 -7
  320. package/dist/search-params/index.d.ts.map +1 -1
  321. package/dist/search-params/index.js +34 -441
  322. package/dist/search-params/index.js.map +1 -1
  323. package/dist/search-params/registry.d.ts +2 -2
  324. package/dist/search-params/registry.d.ts.map +1 -1
  325. package/dist/search-params/wrappers.d.ts +53 -0
  326. package/dist/search-params/wrappers.d.ts.map +1 -0
  327. package/dist/segment-params/define.d.ts +89 -0
  328. package/dist/segment-params/define.d.ts.map +1 -0
  329. package/dist/segment-params/index.d.ts +3 -0
  330. package/dist/segment-params/index.d.ts.map +1 -0
  331. package/dist/segment-params/index.js +2 -0
  332. package/dist/server/access-gate.d.ts +8 -3
  333. package/dist/server/access-gate.d.ts.map +1 -1
  334. package/dist/server/action-client.d.ts +41 -6
  335. package/dist/server/action-client.d.ts.map +1 -1
  336. package/dist/server/action-encryption.d.ts +76 -0
  337. package/dist/server/action-encryption.d.ts.map +1 -0
  338. package/dist/server/action-handler.d.ts +35 -1
  339. package/dist/server/action-handler.d.ts.map +1 -1
  340. package/dist/server/actions.d.ts +6 -14
  341. package/dist/server/actions.d.ts.map +1 -1
  342. package/dist/server/als-registry.d.ts +70 -11
  343. package/dist/server/als-registry.d.ts.map +1 -1
  344. package/dist/server/asset-headers.d.ts +1 -15
  345. package/dist/server/asset-headers.d.ts.map +1 -1
  346. package/dist/server/body-limits.d.ts.map +1 -1
  347. package/dist/server/build-manifest.d.ts +8 -2
  348. package/dist/server/build-manifest.d.ts.map +1 -1
  349. package/dist/server/coalesce-tick.d.ts +40 -0
  350. package/dist/server/coalesce-tick.d.ts.map +1 -0
  351. package/dist/server/cookie-context.d.ts +170 -0
  352. package/dist/server/cookie-context.d.ts.map +1 -0
  353. package/dist/server/cookie-parsing.d.ts +51 -0
  354. package/dist/server/cookie-parsing.d.ts.map +1 -0
  355. package/dist/server/csrf.d.ts +3 -2
  356. package/dist/server/csrf.d.ts.map +1 -1
  357. package/dist/server/default-logger.d.ts +22 -0
  358. package/dist/server/default-logger.d.ts.map +1 -0
  359. package/dist/server/deny-boundary.d.ts +90 -0
  360. package/dist/server/deny-boundary.d.ts.map +1 -0
  361. package/dist/server/deny-renderer.d.ts +1 -1
  362. package/dist/server/deny-renderer.d.ts.map +1 -1
  363. package/dist/server/dev-source-map.d.ts +22 -0
  364. package/dist/server/dev-source-map.d.ts.map +1 -0
  365. package/dist/server/early-hints-sender.d.ts.map +1 -1
  366. package/dist/server/early-hints.d.ts +13 -11
  367. package/dist/server/early-hints.d.ts.map +1 -1
  368. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  369. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  370. package/dist/server/fallback-error.d.ts +12 -7
  371. package/dist/server/fallback-error.d.ts.map +1 -1
  372. package/dist/server/flight-injection-state.d.ts +66 -0
  373. package/dist/server/flight-injection-state.d.ts.map +1 -0
  374. package/dist/server/flight-scripts.d.ts +42 -0
  375. package/dist/server/flight-scripts.d.ts.map +1 -0
  376. package/dist/server/flush.d.ts.map +1 -1
  377. package/dist/server/form-data.d.ts +29 -0
  378. package/dist/server/form-data.d.ts.map +1 -1
  379. package/dist/server/html-injector-core.d.ts +213 -0
  380. package/dist/server/html-injector-core.d.ts.map +1 -0
  381. package/dist/server/html-injectors.d.ts +81 -41
  382. package/dist/server/html-injectors.d.ts.map +1 -1
  383. package/dist/server/index.d.ts +10 -46
  384. package/dist/server/index.d.ts.map +1 -1
  385. package/dist/server/index.js +170 -2911
  386. package/dist/server/index.js.map +1 -1
  387. package/dist/server/internal.d.ts +48 -0
  388. package/dist/server/internal.d.ts.map +1 -0
  389. package/dist/server/internal.js +3126 -0
  390. package/dist/server/internal.js.map +1 -0
  391. package/dist/server/logger.d.ts +39 -7
  392. package/dist/server/logger.d.ts.map +1 -1
  393. package/dist/server/metadata-routes.d.ts +23 -7
  394. package/dist/server/metadata-routes.d.ts.map +1 -1
  395. package/dist/server/middleware-runner.d.ts +36 -4
  396. package/dist/server/middleware-runner.d.ts.map +1 -1
  397. package/dist/server/node-stream-transforms.d.ts +112 -0
  398. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  399. package/dist/server/param-coercion.d.ts +54 -0
  400. package/dist/server/param-coercion.d.ts.map +1 -0
  401. package/dist/server/pipeline-helpers.d.ts +95 -0
  402. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  403. package/dist/server/pipeline-interception.d.ts +1 -1
  404. package/dist/server/pipeline-interception.d.ts.map +1 -1
  405. package/dist/server/pipeline-metadata.d.ts +6 -0
  406. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  407. package/dist/server/pipeline-outcome.d.ts +49 -0
  408. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  409. package/dist/server/pipeline-phases.d.ts +56 -0
  410. package/dist/server/pipeline-phases.d.ts.map +1 -0
  411. package/dist/server/pipeline.d.ts +111 -19
  412. package/dist/server/pipeline.d.ts.map +1 -1
  413. package/dist/server/port-resolution.d.ts +117 -0
  414. package/dist/server/port-resolution.d.ts.map +1 -0
  415. package/dist/server/primitives.d.ts +74 -20
  416. package/dist/server/primitives.d.ts.map +1 -1
  417. package/dist/server/render-timeout.d.ts +51 -0
  418. package/dist/server/render-timeout.d.ts.map +1 -0
  419. package/dist/server/request-context.d.ts +62 -107
  420. package/dist/server/request-context.d.ts.map +1 -1
  421. package/dist/server/route-element-builder.d.ts +28 -2
  422. package/dist/server/route-element-builder.d.ts.map +1 -1
  423. package/dist/server/route-handler.d.ts.map +1 -1
  424. package/dist/server/route-matcher.d.ts +25 -36
  425. package/dist/server/route-matcher.d.ts.map +1 -1
  426. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  427. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  428. package/dist/server/rsc-entry/api-handler.d.ts +12 -3
  429. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  430. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  431. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  432. package/dist/server/rsc-entry/helpers.d.ts +50 -6
  433. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  434. package/dist/server/rsc-entry/index.d.ts +19 -8
  435. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  436. package/dist/server/rsc-entry/render-route.d.ts +50 -0
  437. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  438. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  439. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  440. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  441. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  442. package/dist/server/rsc-entry/rsc-stream.d.ts +17 -1
  443. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  444. package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
  445. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  446. package/dist/server/rsc-entry/ssr-renderer.d.ts +34 -4
  447. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  448. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
  449. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  450. package/dist/server/safe-load.d.ts +46 -0
  451. package/dist/server/safe-load.d.ts.map +1 -0
  452. package/dist/server/sensitive-fields.d.ts +74 -0
  453. package/dist/server/sensitive-fields.d.ts.map +1 -0
  454. package/dist/server/sitemap-generator.d.ts +129 -0
  455. package/dist/server/sitemap-generator.d.ts.map +1 -0
  456. package/dist/server/sitemap-handler.d.ts +22 -0
  457. package/dist/server/sitemap-handler.d.ts.map +1 -0
  458. package/dist/server/slot-resolver.d.ts +1 -1
  459. package/dist/server/slot-resolver.d.ts.map +1 -1
  460. package/dist/server/ssr-bridge-types.d.ts +121 -0
  461. package/dist/server/ssr-bridge-types.d.ts.map +1 -0
  462. package/dist/server/ssr-entry.d.ts +2 -43
  463. package/dist/server/ssr-entry.d.ts.map +1 -1
  464. package/dist/server/ssr-render.d.ts +64 -21
  465. package/dist/server/ssr-render.d.ts.map +1 -1
  466. package/dist/server/ssr-wrappers.d.ts +50 -0
  467. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  468. package/dist/server/state-tree-diff.d.ts +12 -5
  469. package/dist/server/state-tree-diff.d.ts.map +1 -1
  470. package/dist/server/status-code-resolver.d.ts +16 -11
  471. package/dist/server/status-code-resolver.d.ts.map +1 -1
  472. package/dist/server/stream-utils.d.ts +36 -0
  473. package/dist/server/stream-utils.d.ts.map +1 -0
  474. package/dist/server/tracing.d.ts +5 -5
  475. package/dist/server/tracing.d.ts.map +1 -1
  476. package/dist/server/tree-builder.d.ts +62 -30
  477. package/dist/server/tree-builder.d.ts.map +1 -1
  478. package/dist/server/tree-match.d.ts +49 -0
  479. package/dist/server/tree-match.d.ts.map +1 -0
  480. package/dist/server/types.d.ts +71 -6
  481. package/dist/server/types.d.ts.map +1 -1
  482. package/dist/server/utils/escape-html.d.ts +14 -0
  483. package/dist/server/utils/escape-html.d.ts.map +1 -0
  484. package/dist/server/version-skew.d.ts +61 -0
  485. package/dist/server/version-skew.d.ts.map +1 -0
  486. package/dist/shared/href-validation.d.ts +38 -0
  487. package/dist/shared/href-validation.d.ts.map +1 -0
  488. package/dist/shared/merge-search-params.d.ts +22 -0
  489. package/dist/shared/merge-search-params.d.ts.map +1 -0
  490. package/dist/shims/font-google.d.ts +1 -1
  491. package/dist/shims/font-google.d.ts.map +1 -1
  492. package/dist/shims/font-google.js +42 -0
  493. package/dist/shims/font-google.js.map +1 -0
  494. package/dist/shims/font-local.d.ts +26 -0
  495. package/dist/shims/font-local.d.ts.map +1 -0
  496. package/dist/shims/font-local.js +20 -0
  497. package/dist/shims/font-local.js.map +1 -0
  498. package/dist/shims/headers.d.ts +2 -1
  499. package/dist/shims/headers.d.ts.map +1 -1
  500. package/dist/shims/image.d.ts +1 -1
  501. package/dist/shims/navigation-client.d.ts +3 -1
  502. package/dist/shims/navigation-client.d.ts.map +1 -1
  503. package/dist/shims/navigation.d.ts +11 -5
  504. package/dist/shims/navigation.d.ts.map +1 -1
  505. package/dist/utils/state-machine.d.ts +80 -0
  506. package/dist/utils/state-machine.d.ts.map +1 -0
  507. package/package.json +63 -22
  508. package/src/adapters/build-output-helper.ts +139 -0
  509. package/src/adapters/cloudflare-dev.ts +177 -0
  510. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  511. package/src/adapters/cloudflare.ts +350 -76
  512. package/src/adapters/compress-module.ts +24 -4
  513. package/src/adapters/nitro.ts +147 -60
  514. package/src/adapters/shared.ts +40 -0
  515. package/src/adapters/wrangler.d.ts +7 -0
  516. package/src/cache/cache-api.ts +39 -0
  517. package/src/cache/handler-store.ts +68 -0
  518. package/src/cache/index.ts +81 -18
  519. package/src/cache/singleflight.ts +62 -4
  520. package/src/cache/sizeof.ts +33 -0
  521. package/src/cache/timber-cache.ts +52 -24
  522. package/src/cli-schema-sync.ts +295 -0
  523. package/src/cli.ts +76 -8
  524. package/src/client/browser-dev.ts +153 -1
  525. package/src/client/browser-entry/action-dispatch.ts +125 -0
  526. package/src/client/browser-entry/hmr.ts +81 -0
  527. package/src/client/browser-entry/hydrate.ts +153 -0
  528. package/src/client/browser-entry/index.ts +151 -0
  529. package/src/client/browser-entry/post-hydration.ts +113 -0
  530. package/src/client/browser-entry/router-init.ts +219 -0
  531. package/src/client/browser-entry/rsc-stream.ts +157 -0
  532. package/src/client/browser-entry/scroll.ts +27 -0
  533. package/src/client/error-boundary.tsx +99 -22
  534. package/src/client/error-reconstituter.tsx +65 -0
  535. package/src/client/form.tsx +31 -32
  536. package/src/client/history.ts +26 -4
  537. package/src/client/index.ts +67 -45
  538. package/src/client/internal.ts +58 -0
  539. package/src/client/link-pending-store.ts +116 -0
  540. package/src/client/link.tsx +343 -150
  541. package/src/client/nav-link-store.ts +37 -0
  542. package/src/client/navigation-api-types.ts +112 -0
  543. package/src/client/navigation-api.ts +338 -0
  544. package/src/client/navigation-context.ts +35 -7
  545. package/src/client/navigation-root.tsx +347 -0
  546. package/src/client/nuqs-adapter.tsx +16 -3
  547. package/src/client/router-ref.ts +1 -1
  548. package/src/client/router.ts +418 -128
  549. package/src/client/rsc-fetch.ts +208 -10
  550. package/src/client/segment-cache.ts +6 -3
  551. package/src/client/segment-outlet.tsx +77 -0
  552. package/src/client/segment-update-context.ts +42 -0
  553. package/src/client/shallow-url.ts +22 -0
  554. package/src/client/ssr-data.ts +13 -5
  555. package/src/client/stale-reload.ts +72 -3
  556. package/src/client/state.ts +2 -2
  557. package/src/client/top-loader.tsx +11 -9
  558. package/src/client/use-cookie.ts +31 -2
  559. package/src/client/use-link-status.ts +7 -7
  560. package/src/client/use-pathname.ts +1 -0
  561. package/src/client/use-pending-navigation.ts +40 -0
  562. package/src/client/use-query-states.ts +9 -3
  563. package/src/client/use-router.ts +4 -1
  564. package/src/client/use-search-params.ts +26 -44
  565. package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
  566. package/src/codec.ts +147 -0
  567. package/src/config-types.ts +292 -0
  568. package/src/config-validation.ts +303 -0
  569. package/src/content/index.ts +5 -13
  570. package/src/cookies/define-cookie.ts +233 -53
  571. package/src/cookies/index.ts +12 -1
  572. package/src/cookies/json-cookie.ts +105 -0
  573. package/src/cookies/validation.ts +192 -0
  574. package/src/dev-tools/404-page.ts +387 -0
  575. package/src/dev-tools/browser-logs.ts +291 -0
  576. package/src/dev-tools/error-page.ts +507 -0
  577. package/src/dev-tools/holding-server.ts +187 -0
  578. package/src/dev-tools/index.ts +90 -0
  579. package/src/dev-tools/instrumentation.ts +176 -0
  580. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +9 -5
  581. package/src/dev-tools/overlay.ts +469 -0
  582. package/src/dev-tools/stack-classifier.ts +75 -0
  583. package/src/dev-tools/terminal.ts +183 -0
  584. package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +5 -50
  585. package/src/fonts/ast.ts +525 -16
  586. package/src/fonts/bundle.ts +131 -0
  587. package/src/fonts/dev-middleware.ts +74 -0
  588. package/src/fonts/local.ts +3 -3
  589. package/src/fonts/pipeline.ts +337 -0
  590. package/src/fonts/transform.ts +317 -0
  591. package/src/fonts/types.ts +52 -1
  592. package/src/fonts/virtual-modules.ts +235 -0
  593. package/src/index.ts +415 -345
  594. package/src/params/codec-registry.ts +34 -0
  595. package/src/params/define-schema.ts +115 -0
  596. package/src/params/index.ts +17 -0
  597. package/src/params/resolve-schema.ts +116 -0
  598. package/src/plugin-context.ts +247 -0
  599. package/src/plugins/adapter-build.ts +98 -4
  600. package/src/plugins/build-manifest.ts +168 -23
  601. package/src/plugins/build-report.ts +16 -25
  602. package/src/plugins/cache.ts +180 -0
  603. package/src/plugins/client-chunks.ts +113 -0
  604. package/src/plugins/cloudflare-wasm.ts +103 -0
  605. package/src/plugins/content.ts +1 -1
  606. package/src/plugins/dev-server.ts +179 -37
  607. package/src/plugins/entries.ts +110 -8
  608. package/src/plugins/fonts.ts +167 -655
  609. package/src/plugins/mdx.ts +47 -10
  610. package/src/plugins/routing.ts +386 -47
  611. package/src/plugins/server-bundle.ts +59 -3
  612. package/src/plugins/shims.ts +136 -35
  613. package/src/plugins/static-build.ts +15 -89
  614. package/src/routing/codegen-shared.ts +115 -0
  615. package/src/routing/codegen-types.ts +61 -0
  616. package/src/routing/codegen.ts +321 -177
  617. package/src/routing/convention-lint.ts +357 -0
  618. package/src/routing/index.ts +10 -1
  619. package/src/routing/interception.ts +1 -1
  620. package/src/routing/link-codegen.ts +310 -0
  621. package/src/routing/scanner.ts +165 -110
  622. package/src/routing/schema-validation.ts +149 -0
  623. package/src/routing/segment-classify.ts +188 -0
  624. package/src/routing/segment-codegen.ts +98 -0
  625. package/src/routing/types.ts +78 -25
  626. package/src/routing/walkers.ts +90 -0
  627. package/src/rsc-runtime/rsc.ts +2 -0
  628. package/src/rsc-runtime/ssr.ts +50 -0
  629. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  630. package/src/{search-params/codecs.ts → schema-bridge.ts} +60 -22
  631. package/src/search-params/define.ts +538 -0
  632. package/src/search-params/index.ts +14 -20
  633. package/src/search-params/registry.ts +2 -2
  634. package/src/search-params/wrappers.ts +92 -0
  635. package/src/segment-params/define.ts +309 -0
  636. package/src/segment-params/index.ts +9 -0
  637. package/src/server/access-gate.tsx +76 -34
  638. package/src/server/action-client.ts +119 -28
  639. package/src/server/action-encryption.ts +144 -0
  640. package/src/server/action-handler.ts +112 -14
  641. package/src/server/actions.ts +34 -26
  642. package/src/server/als-registry.ts +108 -20
  643. package/src/server/asset-headers.ts +8 -34
  644. package/src/server/body-limits.ts +10 -2
  645. package/src/server/build-manifest.ts +17 -4
  646. package/src/server/coalesce-tick.ts +75 -0
  647. package/src/server/compress.ts +25 -7
  648. package/src/server/cookie-context.ts +473 -0
  649. package/src/server/cookie-parsing.ts +135 -0
  650. package/src/server/csrf.ts +39 -6
  651. package/src/server/default-logger.ts +99 -0
  652. package/src/server/deny-boundary.ts +218 -0
  653. package/src/server/deny-renderer.ts +32 -52
  654. package/src/server/dev-source-map.ts +31 -0
  655. package/src/server/early-hints-sender.ts +3 -2
  656. package/src/server/early-hints.ts +35 -27
  657. package/src/server/error-boundary-wrapper.ts +74 -22
  658. package/src/server/fallback-error.ts +74 -102
  659. package/src/server/flight-injection-state.ts +113 -0
  660. package/src/server/flight-scripts.ts +62 -0
  661. package/src/server/flush.ts +2 -1
  662. package/src/server/form-data.ts +101 -5
  663. package/src/server/html-injector-core.ts +418 -0
  664. package/src/server/html-injectors.ts +238 -223
  665. package/src/server/index.ts +29 -183
  666. package/src/server/internal.ts +182 -0
  667. package/src/server/logger.ts +67 -36
  668. package/src/server/metadata-routes.ts +44 -19
  669. package/src/server/middleware-runner.ts +75 -4
  670. package/src/server/node-stream-transforms.ts +361 -0
  671. package/src/server/param-coercion.ts +206 -0
  672. package/src/server/pipeline-helpers.ts +204 -0
  673. package/src/server/pipeline-interception.ts +32 -18
  674. package/src/server/pipeline-metadata.ts +13 -0
  675. package/src/server/pipeline-outcome.ts +197 -0
  676. package/src/server/pipeline-phases.ts +527 -0
  677. package/src/server/pipeline.ts +201 -382
  678. package/src/server/port-resolution.ts +215 -0
  679. package/src/server/primitives.ts +130 -46
  680. package/src/server/render-timeout.ts +108 -0
  681. package/src/server/request-context.ts +168 -337
  682. package/src/server/route-element-builder.ts +437 -208
  683. package/src/server/route-handler.ts +31 -4
  684. package/src/server/route-matcher.ts +128 -277
  685. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  686. package/src/server/rsc-entry/api-handler.ts +69 -32
  687. package/src/server/rsc-entry/error-renderer.ts +316 -89
  688. package/src/server/rsc-entry/helpers.ts +155 -26
  689. package/src/server/rsc-entry/index.ts +283 -329
  690. package/src/server/rsc-entry/render-route.ts +313 -0
  691. package/src/server/rsc-entry/revalidate-renderer.ts +344 -0
  692. package/src/server/rsc-entry/rsc-payload.ts +65 -22
  693. package/src/server/rsc-entry/rsc-stream.ts +85 -13
  694. package/src/server/rsc-entry/ssr-bridge.ts +18 -5
  695. package/src/server/rsc-entry/ssr-renderer.ts +271 -41
  696. package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
  697. package/src/server/safe-load.ts +60 -0
  698. package/src/server/sensitive-fields.ts +230 -0
  699. package/src/server/sitemap-generator.ts +338 -0
  700. package/src/server/sitemap-handler.ts +148 -0
  701. package/src/server/slot-resolver.ts +234 -246
  702. package/src/server/ssr-bridge-types.ts +124 -0
  703. package/src/server/ssr-entry.ts +217 -78
  704. package/src/server/ssr-render.ts +344 -71
  705. package/src/server/ssr-wrappers.tsx +141 -0
  706. package/src/server/state-tree-diff.ts +30 -23
  707. package/src/server/status-code-resolver.ts +112 -128
  708. package/src/server/stream-utils.ts +213 -0
  709. package/src/server/tracing.ts +21 -10
  710. package/src/server/tree-builder.ts +204 -90
  711. package/src/server/tree-match.ts +210 -0
  712. package/src/server/types.ts +78 -9
  713. package/src/server/utils/escape-html.ts +20 -0
  714. package/src/server/version-skew.ts +104 -0
  715. package/src/shared/href-validation.ts +127 -0
  716. package/src/shared/merge-search-params.ts +55 -0
  717. package/src/shims/font-google.ts +1 -1
  718. package/src/shims/font-local.ts +34 -0
  719. package/src/shims/headers.ts +5 -1
  720. package/src/shims/navigation-client.ts +4 -3
  721. package/src/shims/navigation.ts +14 -7
  722. package/src/utils/state-machine.ts +111 -0
  723. package/LICENSE +0 -8
  724. package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
  725. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  726. package/dist/_chunks/debug-B3Gypr3D.js +0 -108
  727. package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
  728. package/dist/_chunks/format-RyoGQL74.js.map +0 -1
  729. package/dist/_chunks/interception-BOoWmLUA.js +0 -676
  730. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  731. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  732. package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
  733. package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
  734. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  735. package/dist/_chunks/tracing-CemImE6h.js +0 -187
  736. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  737. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  738. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  739. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  740. package/dist/cache/register-cached-function.d.ts +0 -17
  741. package/dist/cache/register-cached-function.d.ts.map +0 -1
  742. package/dist/client/browser-entry.d.ts +0 -21
  743. package/dist/client/browser-entry.d.ts.map +0 -1
  744. package/dist/client/link-status-provider.d.ts +0 -11
  745. package/dist/client/link-status-provider.d.ts.map +0 -1
  746. package/dist/client/segment-merger.d.ts +0 -119
  747. package/dist/client/segment-merger.d.ts.map +0 -1
  748. package/dist/client/transition-root.d.ts.map +0 -1
  749. package/dist/client/use-navigation-pending.d.ts +0 -26
  750. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  751. package/dist/client/use-params.d.ts.map +0 -1
  752. package/dist/plugins/cache-transform.d.ts +0 -36
  753. package/dist/plugins/cache-transform.d.ts.map +0 -1
  754. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  755. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  756. package/dist/plugins/dev-logs.d.ts.map +0 -1
  757. package/dist/plugins/dynamic-transform.d.ts +0 -72
  758. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  759. package/dist/plugins/server-action-exports.d.ts +0 -26
  760. package/dist/plugins/server-action-exports.d.ts.map +0 -1
  761. package/dist/routing/status-file-lint.d.ts +0 -33
  762. package/dist/routing/status-file-lint.d.ts.map +0 -1
  763. package/dist/search-params/analyze.d.ts +0 -54
  764. package/dist/search-params/analyze.d.ts.map +0 -1
  765. package/dist/search-params/builtin-codecs.d.ts +0 -105
  766. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  767. package/dist/search-params/codecs.d.ts +0 -53
  768. package/dist/search-params/codecs.d.ts.map +0 -1
  769. package/dist/search-params/create.d.ts +0 -106
  770. package/dist/search-params/create.d.ts.map +0 -1
  771. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  772. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  773. package/dist/server/dev-logger.d.ts.map +0 -1
  774. package/dist/server/dev-span-processor.d.ts.map +0 -1
  775. package/dist/server/dev-warnings.d.ts.map +0 -1
  776. package/dist/server/manifest-status-resolver.d.ts +0 -58
  777. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  778. package/dist/server/prerender.d.ts +0 -77
  779. package/dist/server/prerender.d.ts.map +0 -1
  780. package/dist/utils/directive-parser.d.ts +0 -70
  781. package/dist/utils/directive-parser.d.ts.map +0 -1
  782. package/src/cache/register-cached-function.ts +0 -103
  783. package/src/client/browser-entry.ts +0 -678
  784. package/src/client/link-status-provider.tsx +0 -30
  785. package/src/client/segment-merger.ts +0 -339
  786. package/src/client/transition-root.tsx +0 -166
  787. package/src/client/use-navigation-pending.ts +0 -38
  788. package/src/plugins/cache-transform.ts +0 -199
  789. package/src/plugins/dev-error-overlay.ts +0 -230
  790. package/src/plugins/dynamic-transform.ts +0 -161
  791. package/src/plugins/server-action-exports.ts +0 -220
  792. package/src/routing/status-file-lint.ts +0 -112
  793. package/src/search-params/analyze.ts +0 -192
  794. package/src/search-params/builtin-codecs.ts +0 -228
  795. package/src/search-params/create.ts +0 -321
  796. package/src/server/dev-fetch-instrumentation.ts +0 -96
  797. package/src/server/dev-span-processor.ts +0 -78
  798. package/src/server/manifest-status-resolver.ts +0 -215
  799. package/src/server/prerender.ts +0 -139
  800. package/src/utils/directive-parser.ts +0 -529
  801. /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-routes-BjepjefT.js","names":[],"sources":["../../src/server/metadata-routes.ts"],"sourcesContent":["/**\n * Metadata route classification for timber.js.\n *\n * Metadata routes are file-based endpoints that generate well-known URLs for\n * crawlers and browsers (sitemap.xml, robots.txt, OG images, etc.).\n *\n * These routes run through proxy.ts but NOT through middleware.ts or access.ts —\n * they are public endpoints by nature.\n *\n * See design/16-metadata.md §\"Metadata Routes\"\n */\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Classification of a metadata route file. */\nexport interface MetadataRouteInfo {\n /** The metadata route type. */\n type: MetadataRouteType;\n /** The content type to serve this route with. */\n contentType: string;\n /** Whether this route can appear in nested segments (not just app root). */\n nestable: boolean;\n}\n\nexport type MetadataRouteType =\n | 'sitemap'\n | 'robots'\n | 'manifest'\n | 'favicon'\n | 'icon'\n | 'opengraph-image'\n | 'apple-icon';\n\n// ─── Convention Table ────────────────────────────────────────────────────────\n\n/**\n * All recognized metadata route file conventions.\n *\n * Each entry maps a base file name (without extension) to its route info.\n * The extensions determine whether the file is static or dynamic.\n *\n * Static extensions: .xml, .txt, .json, .png, .jpg, .ico, .svg\n * Dynamic extensions: .ts, .tsx\n */\nexport const METADATA_ROUTE_CONVENTIONS: Record<\n string,\n {\n type: MetadataRouteType;\n contentType: string;\n nestable: boolean;\n staticExtensions: string[];\n dynamicExtensions: string[];\n /** The URL path this file serves at (relative to segment). */\n servePath: string;\n }\n> = {\n 'sitemap': {\n type: 'sitemap',\n contentType: 'application/xml',\n nestable: true,\n staticExtensions: ['xml'],\n dynamicExtensions: ['ts'],\n servePath: 'sitemap.xml',\n },\n 'robots': {\n type: 'robots',\n contentType: 'text/plain',\n nestable: false,\n staticExtensions: ['txt'],\n dynamicExtensions: ['ts'],\n servePath: 'robots.txt',\n },\n 'manifest': {\n type: 'manifest',\n contentType: 'application/manifest+json',\n nestable: false,\n staticExtensions: ['json'],\n dynamicExtensions: ['ts'],\n servePath: 'manifest.webmanifest',\n },\n 'favicon': {\n type: 'favicon',\n contentType: 'image/x-icon',\n nestable: false,\n staticExtensions: ['ico'],\n dynamicExtensions: ['ts', 'tsx'],\n servePath: 'favicon.ico',\n },\n 'icon': {\n type: 'icon',\n contentType: 'image/*',\n nestable: true,\n staticExtensions: ['png', 'jpg', 'svg'],\n dynamicExtensions: ['ts', 'tsx'],\n servePath: 'icon',\n },\n 'opengraph-image': {\n type: 'opengraph-image',\n contentType: 'image/*',\n nestable: true,\n staticExtensions: ['png', 'jpg'],\n dynamicExtensions: ['ts', 'tsx'],\n servePath: 'opengraph-image',\n },\n\n 'apple-icon': {\n type: 'apple-icon',\n contentType: 'image/*',\n nestable: true,\n staticExtensions: ['png'],\n dynamicExtensions: ['ts', 'tsx'],\n servePath: 'apple-icon',\n },\n};\n\n// ─── MIME Type Resolution ─────────────────────────────────────────────────────\n\n/**\n * Map of file extensions to MIME types for static metadata route files.\n * Used to resolve the generic `image/*` content type for static image files.\n */\nconst EXTENSION_MIME_TYPES: Record<string, string> = {\n xml: 'application/xml',\n txt: 'text/plain',\n json: 'application/json',\n ico: 'image/x-icon',\n png: 'image/png',\n jpg: 'image/jpeg',\n jpeg: 'image/jpeg',\n svg: 'image/svg+xml',\n webp: 'image/webp',\n};\n\n/**\n * Resolve the concrete MIME type for a static metadata route file.\n *\n * For generic content types like `image/*`, this resolves to the actual\n * MIME type based on the file extension (e.g. `image/png` for `.png`).\n *\n * @param conventionContentType - The content type from the convention table (may be generic like `image/*`)\n * @param extension - The file extension without leading dot (e.g. \"png\", \"xml\")\n * @returns The resolved MIME type\n */\nexport function resolveStaticContentType(conventionContentType: string, extension: string): string {\n if (conventionContentType.includes('*')) {\n return EXTENSION_MIME_TYPES[extension] ?? 'application/octet-stream';\n }\n return conventionContentType;\n}\n\n/**\n * Check if a file extension represents a static (non-code) metadata route file.\n *\n * @param baseName - The base file name without extension (e.g. \"sitemap\", \"icon\")\n * @param extension - The file extension without leading dot (e.g. \"xml\", \"png\", \"ts\")\n * @returns true if this is a static file, false if dynamic or unrecognized\n */\nexport function isStaticMetadataExtension(baseName: string, extension: string): boolean {\n const convention = METADATA_ROUTE_CONVENTIONS[baseName];\n if (!convention) return false;\n return convention.staticExtensions.includes(extension);\n}\n\n/**\n * Check if a file extension represents a dynamic (code) metadata route file.\n *\n * @param baseName - The base file name without extension (e.g. \"sitemap\", \"icon\")\n * @param extension - The file extension without leading dot (e.g. \"ts\", \"tsx\")\n * @returns true if this is a dynamic file, false if static or unrecognized\n */\nexport function isDynamicMetadataExtension(baseName: string, extension: string): boolean {\n const convention = METADATA_ROUTE_CONVENTIONS[baseName];\n if (!convention) return false;\n return convention.dynamicExtensions.includes(extension);\n}\n\n// ─── Classification ──────────────────────────────────────────────────────────\n\n/**\n * Classify a file name as a metadata route, or return null if it's not one.\n *\n * @param fileName - The full file name including extension (e.g. \"sitemap.xml\", \"icon.tsx\")\n * @returns Classification info, or null if not a metadata route\n */\nexport function classifyMetadataRoute(fileName: string): MetadataRouteInfo | null {\n const dotIndex = fileName.lastIndexOf('.');\n if (dotIndex === -1) return null;\n\n const baseName = fileName.slice(0, dotIndex);\n const ext = fileName.slice(dotIndex + 1);\n\n const convention = METADATA_ROUTE_CONVENTIONS[baseName];\n if (!convention) return null;\n\n const isStatic = convention.staticExtensions.includes(ext);\n const isDynamic = convention.dynamicExtensions.includes(ext);\n\n if (!isStatic && !isDynamic) return null;\n\n return {\n type: convention.type,\n contentType: convention.contentType,\n nestable: convention.nestable,\n };\n}\n\n/**\n * Get the serve path for a metadata route type.\n *\n * @param type - The metadata route type\n * @returns The URL path fragment this route serves at\n */\nexport function getMetadataRouteServePath(type: MetadataRouteType): string {\n for (const convention of Object.values(METADATA_ROUTE_CONVENTIONS)) {\n if (convention.type === type) return convention.servePath;\n }\n throw new Error(`[timber] Unknown metadata route type: ${type}`);\n}\n\nconst METADATA_SERVE_PATHS = new Set(\n Object.values(METADATA_ROUTE_CONVENTIONS).map((c) => c.servePath)\n);\n\nexport function isMetadataRouteServePath(pathname: string): boolean {\n const lastSegment = pathname.slice(pathname.lastIndexOf('/') + 1);\n return METADATA_SERVE_PATHS.has(lastSegment);\n}\n\n/** A <link> auto-link tag. */\nexport interface AutoLinkLink {\n tag: 'link';\n rel: string;\n href: string;\n type?: string;\n}\n\n/** A <meta> auto-link tag. */\nexport interface AutoLinkMeta {\n tag: 'meta';\n property?: string;\n name?: string;\n content: string;\n}\n\nexport type AutoLinkTag = AutoLinkLink | AutoLinkMeta;\n\n/**\n * Get the auto-link tags to inject into <head> for metadata route files\n * discovered in a segment.\n *\n * Returns link tags for icon/apple-icon/manifest, and meta tags for\n * opengraph-image (emits both og:image and twitter:image). Returns null\n * for types that don't auto-link (favicon, sitemap, robots).\n *\n * @param type - The metadata route type\n * @param href - The resolved URL path to the metadata route\n * @returns Tag descriptor(s) for the <head>, or null if no auto-link\n */\nexport function getMetadataRouteAutoLink(type: MetadataRouteType, href: string): AutoLinkTag[] {\n switch (type) {\n case 'icon':\n return [{ tag: 'link', rel: 'icon', href }];\n case 'apple-icon':\n return [{ tag: 'link', rel: 'apple-touch-icon', href }];\n case 'manifest':\n return [{ tag: 'link', rel: 'manifest', href }];\n case 'opengraph-image':\n return [\n { tag: 'meta', property: 'og:image', content: href },\n { tag: 'meta', name: 'twitter:image', content: href },\n ];\n default:\n return [];\n }\n}\n"],"mappings":";;;;;;;;;;AA4CA,IAAa,6BAWT;CACF,WAAW;EACT,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,KAAK;EACxB,mBAAmB,CAAC,IAAI;EACxB,WAAW;CACb;CACA,UAAU;EACR,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,KAAK;EACxB,mBAAmB,CAAC,IAAI;EACxB,WAAW;CACb;CACA,YAAY;EACV,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,MAAM;EACzB,mBAAmB,CAAC,IAAI;EACxB,WAAW;CACb;CACA,WAAW;EACT,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,KAAK;EACxB,mBAAmB,CAAC,MAAM,KAAK;EAC/B,WAAW;CACb;CACA,QAAQ;EACN,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB;GAAC;GAAO;GAAO;EAAK;EACtC,mBAAmB,CAAC,MAAM,KAAK;EAC/B,WAAW;CACb;CACA,mBAAmB;EACjB,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,OAAO,KAAK;EAC/B,mBAAmB,CAAC,MAAM,KAAK;EAC/B,WAAW;CACb;CAEA,cAAc;EACZ,MAAM;EACN,aAAa;EACb,UAAU;EACV,kBAAkB,CAAC,KAAK;EACxB,mBAAmB,CAAC,MAAM,KAAK;EAC/B,WAAW;CACb;AACF;;;;;;;;AAyDA,SAAgB,2BAA2B,UAAkB,WAA4B;CACvF,MAAM,aAAa,2BAA2B;CAC9C,IAAI,CAAC,YAAY,OAAO;CACxB,OAAO,WAAW,kBAAkB,SAAS,SAAS;AACxD;;;;;;;AAUA,SAAgB,sBAAsB,UAA4C;CAChF,MAAM,WAAW,SAAS,YAAY,GAAG;CACzC,IAAI,aAAa,IAAI,OAAO;CAE5B,MAAM,WAAW,SAAS,MAAM,GAAG,QAAQ;CAC3C,MAAM,MAAM,SAAS,MAAM,WAAW,CAAC;CAEvC,MAAM,aAAa,2BAA2B;CAC9C,IAAI,CAAC,YAAY,OAAO;CAExB,MAAM,WAAW,WAAW,iBAAiB,SAAS,GAAG;CACzD,MAAM,YAAY,WAAW,kBAAkB,SAAS,GAAG;CAE3D,IAAI,CAAC,YAAY,CAAC,WAAW,OAAO;CAEpC,OAAO;EACL,MAAM,WAAW;EACjB,aAAa,WAAW;EACxB,UAAU,WAAW;CACvB;AACF;;;;;;;AAQA,SAAgB,0BAA0B,MAAiC;CACzE,KAAK,MAAM,cAAc,OAAO,OAAO,0BAA0B,GAC/D,IAAI,WAAW,SAAS,MAAM,OAAO,WAAW;CAElD,MAAM,IAAI,MAAM,yCAAyC,MAAM;AACjE;AAEA,IAAM,uBAAuB,IAAI,IAC/B,OAAO,OAAO,0BAA0B,EAAE,KAAK,MAAM,EAAE,SAAS,CAClE;AAEA,SAAgB,yBAAyB,UAA2B;CAClE,MAAM,cAAc,SAAS,MAAM,SAAS,YAAY,GAAG,IAAI,CAAC;CAChE,OAAO,qBAAqB,IAAI,WAAW;AAC7C;;;;;;;;;;;;;AAgCA,SAAgB,yBAAyB,MAAyB,MAA6B;CAC7F,QAAQ,MAAR;EACE,KAAK,QACH,OAAO,CAAC;GAAE,KAAK;GAAQ,KAAK;GAAQ;EAAK,CAAC;EAC5C,KAAK,cACH,OAAO,CAAC;GAAE,KAAK;GAAQ,KAAK;GAAoB;EAAK,CAAC;EACxD,KAAK,YACH,OAAO,CAAC;GAAE,KAAK;GAAQ,KAAK;GAAY;EAAK,CAAC;EAChD,KAAK,mBACH,OAAO,CACL;GAAE,KAAK;GAAQ,UAAU;GAAY,SAAS;EAAK,GACnD;GAAE,KAAK;GAAQ,MAAM;GAAiB,SAAS;EAAK,CACtD;EACF,SACE,OAAO,CAAC;CACZ;AACF"}
@@ -0,0 +1,103 @@
1
+ import "./use-segment-params-D1CzlgBo.js";
2
+ import { n as getRouterOrNull } from "./router-ref-CtmF-aPv.js";
3
+ import { useSyncExternalStore } from "react";
4
+ //#region src/client/use-pending-navigation.ts
5
+ function subscribe(onStoreChange) {
6
+ const router = getRouterOrNull();
7
+ if (!router) return () => {};
8
+ return router.onPendingChange(onStoreChange);
9
+ }
10
+ function getSnapshot() {
11
+ const router = getRouterOrNull();
12
+ return router ? router.isPending() : false;
13
+ }
14
+ var getServerSnapshot = getSnapshot;
15
+ /**
16
+ * Returns true while an RSC navigation is in flight.
17
+ *
18
+ * Reads from the router's external pending store via useSyncExternalStore.
19
+ * Only components that call this hook re-render when pending state
20
+ * changes — no full-tree re-render.
21
+ *
22
+ * ```tsx
23
+ * 'use client'
24
+ * import { usePendingNavigation } from '@timber-js/app/client'
25
+ *
26
+ * export function NavBar() {
27
+ * const isPending = usePendingNavigation()
28
+ * return (
29
+ * <nav className={isPending ? 'opacity-50' : ''}>
30
+ * <Link href="/dashboard">Dashboard</Link>
31
+ * </nav>
32
+ * )
33
+ * }
34
+ * ```
35
+ */
36
+ function usePendingNavigation() {
37
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
38
+ }
39
+ //#endregion
40
+ //#region src/client/top-loader.tsx
41
+ /**
42
+ * TopLoader — Built-in progress bar for client navigations.
43
+ *
44
+ * Shows an animated progress bar at the top of the viewport while an RSC
45
+ * navigation is in flight. Injected automatically by the framework into
46
+ * NavigationRoot — users never render this component directly.
47
+ *
48
+ * Configuration is via timber.config.ts `topLoader` key. Enabled by default.
49
+ * Users who want a fully custom progress indicator disable the built-in one
50
+ * (`topLoader: { enabled: false }`) and use `usePendingNavigation()` directly.
51
+ *
52
+ * Animation approach: pure CSS @keyframes. The bar crawls from 0% to ~90%
53
+ * width over ~30s using ease-out timing. When navigation completes, the bar
54
+ * snaps to 100% and fades out over 200ms. No JS animation loops (RAF, setInterval).
55
+ *
56
+ * Phase transitions are derived synchronously during render (React's
57
+ * getDerivedStateFromProps pattern) — no useEffect needed for state tracking.
58
+ * The finishing → hidden cleanup uses onTransitionEnd from the CSS transition.
59
+ *
60
+ * When delay > 0, CSS animation-delay + a visibility keyframe ensure the bar
61
+ * stays invisible during the delay period. If navigation finishes before the
62
+ * delay, the bar was never visible so the finish transition is also invisible.
63
+ *
64
+ * See design/19-client-navigation.md §"usePendingNavigation()"
65
+ * See LOCAL-336 for design decisions.
66
+ */
67
+ //#endregion
68
+ //#region src/client/navigation-root.tsx
69
+ /**
70
+ * Module-level flag indicating a hard (MPA) navigation is in progress.
71
+ *
72
+ * When true:
73
+ * - NavigationRoot throws an unresolved thenable to suspend forever,
74
+ * preventing React from rendering children during page teardown
75
+ * (avoids "Rendered more hooks" crashes).
76
+ * - The Navigation API handler skips interception, letting the browser
77
+ * perform a full page load (prevents infinite loops where
78
+ * window.location.href → navigate event → router.navigate → 500 →
79
+ * window.location.href → ...).
80
+ *
81
+ * Uses globalThis for singleton guarantee across chunks (same pattern
82
+ * as NavigationContext). See design/19-client-navigation.md §"Singleton
83
+ * Guarantee via globalThis".
84
+ */
85
+ var HARD_NAV_KEY = Symbol.for("__timber_hard_navigating");
86
+ function getHardNavStore() {
87
+ const g = globalThis;
88
+ if (!g[HARD_NAV_KEY]) g[HARD_NAV_KEY] = { value: false };
89
+ return g[HARD_NAV_KEY];
90
+ }
91
+ /**
92
+ * Set the hard-navigating flag. Call this BEFORE setting
93
+ * window.location.href or window.location.reload() to prevent:
94
+ * 1. React from rendering children during page teardown
95
+ * 2. Navigation API from intercepting the hard navigation
96
+ */
97
+ function setHardNavigating(value) {
98
+ getHardNavStore().value = value;
99
+ }
100
+ //#endregion
101
+ export { usePendingNavigation as n, setHardNavigating as t };
102
+
103
+ //# sourceMappingURL=navigation-root-DLc4s4ZC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-root-DLc4s4ZC.js","names":[],"sources":["../../src/client/use-pending-navigation.ts","../../src/client/top-loader.tsx","../../src/client/navigation-root.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react';\nimport { getRouterOrNull } from './router-ref.js';\n\nfunction subscribe(onStoreChange: () => void): () => void {\n const router = getRouterOrNull();\n if (!router) return () => {};\n return router.onPendingChange(onStoreChange);\n}\n\nfunction getSnapshot(): boolean {\n const router = getRouterOrNull();\n return router ? router.isPending() : false;\n}\n\nconst getServerSnapshot = getSnapshot;\n\n/**\n * Returns true while an RSC navigation is in flight.\n *\n * Reads from the router's external pending store via useSyncExternalStore.\n * Only components that call this hook re-render when pending state\n * changes — no full-tree re-render.\n *\n * ```tsx\n * 'use client'\n * import { usePendingNavigation } from '@timber-js/app/client'\n *\n * export function NavBar() {\n * const isPending = usePendingNavigation()\n * return (\n * <nav className={isPending ? 'opacity-50' : ''}>\n * <Link href=\"/dashboard\">Dashboard</Link>\n * </nav>\n * )\n * }\n * ```\n */\nexport function usePendingNavigation(): boolean {\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","/**\n * TopLoader — Built-in progress bar for client navigations.\n *\n * Shows an animated progress bar at the top of the viewport while an RSC\n * navigation is in flight. Injected automatically by the framework into\n * NavigationRoot — users never render this component directly.\n *\n * Configuration is via timber.config.ts `topLoader` key. Enabled by default.\n * Users who want a fully custom progress indicator disable the built-in one\n * (`topLoader: { enabled: false }`) and use `usePendingNavigation()` directly.\n *\n * Animation approach: pure CSS @keyframes. The bar crawls from 0% to ~90%\n * width over ~30s using ease-out timing. When navigation completes, the bar\n * snaps to 100% and fades out over 200ms. No JS animation loops (RAF, setInterval).\n *\n * Phase transitions are derived synchronously during render (React's\n * getDerivedStateFromProps pattern) — no useEffect needed for state tracking.\n * The finishing → hidden cleanup uses onTransitionEnd from the CSS transition.\n *\n * When delay > 0, CSS animation-delay + a visibility keyframe ensure the bar\n * stays invisible during the delay period. If navigation finishes before the\n * delay, the bar was never visible so the finish transition is also invisible.\n *\n * See design/19-client-navigation.md §\"usePendingNavigation()\"\n * See LOCAL-336 for design decisions.\n */\n\n'use client';\n\nimport { useState, createElement } from 'react';\nimport { usePendingNavigation } from './use-pending-navigation.js';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface TopLoaderConfig {\n /** Whether the top-loader is enabled. Default: true. */\n enabled?: boolean;\n /** Bar color. Default: '#2299DD'. */\n color?: string;\n /** Bar height in pixels. Default: 3. */\n height?: number;\n /** Show subtle glow/shadow effect. Default: false. */\n shadow?: boolean;\n /** Delay in ms before showing the bar. Default: 0. */\n delay?: number;\n /** CSS z-index. Default: 1600. */\n zIndex?: number;\n}\n\n// ─── Defaults ────────────────────────────────────────────────────\n\nconst DEFAULT_COLOR = '#2299DD';\nconst DEFAULT_HEIGHT = 3;\nconst DEFAULT_SHADOW = false;\nconst DEFAULT_DELAY = 0;\nconst DEFAULT_Z_INDEX = 1600;\n\n// ─── Keyframes ───────────────────────────────────────────────────\n\n// Unique keyframes name to avoid collisions with user styles.\nconst CRAWL_KEYFRAMES = '__timber_top_loader_crawl';\nconst APPEAR_KEYFRAMES = '__timber_top_loader_appear';\nconst FINISH_KEYFRAMES = '__timber_top_loader_finish';\n\n// Track whether the @keyframes rules have been injected into the document.\nlet keyframesInjected = false;\n\n/**\n * Inject the @keyframes rules into the document head once.\n * Called during render (idempotent). Uses a <style> tag so the\n * animations are available for inline-styled elements.\n */\nfunction ensureKeyframes(): void {\n if (keyframesInjected) return;\n if (typeof document === 'undefined') return;\n\n const style = document.createElement('style');\n style.textContent = `\n@keyframes ${CRAWL_KEYFRAMES} {\n 0% { width: 0%; }\n 100% { width: 90%; }\n}\n@keyframes ${APPEAR_KEYFRAMES} {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n@keyframes ${FINISH_KEYFRAMES} {\n 0% { width: 90%; opacity: 1; }\n 50% { width: 100%; opacity: 1; }\n 100% { width: 100%; opacity: 0; }\n}\n`;\n document.head.appendChild(style);\n keyframesInjected = true;\n}\n\n// ─── Component ───────────────────────────────────────────────────\n\n/**\n * Internal top-loader component. Injected by NavigationRoot.\n *\n * Reads pending navigation state from PendingNavigationContext.\n * Phase transitions are derived synchronously during render:\n *\n * hidden → crawling: when isPending becomes true\n * crawling → finishing: when isPending becomes false\n * finishing → hidden: when CSS transition ends (onTransitionEnd)\n * finishing → crawling: when isPending becomes true again\n *\n * No useEffect — all state changes are either derived during render\n * (getDerivedStateFromProps pattern) or triggered by DOM events.\n */\nexport function TopLoader({ config }: { config?: TopLoaderConfig }): React.ReactElement | null {\n // Read pending state from the router's external store via\n // useSyncExternalStore (inside usePendingNavigation). Only this\n // component re-renders when pending changes — no full-tree re-render.\n const isPending = usePendingNavigation();\n\n const color = config?.color ?? DEFAULT_COLOR;\n const height = config?.height ?? DEFAULT_HEIGHT;\n const shadow = config?.shadow ?? DEFAULT_SHADOW;\n const delay = config?.delay ?? DEFAULT_DELAY;\n const zIndex = config?.zIndex ?? DEFAULT_Z_INDEX;\n\n const [phase, setPhase] = useState<'hidden' | 'crawling' | 'finishing'>('hidden');\n\n // ─── Synchronous phase derivation (getDerivedStateFromProps) ──\n // React allows setState during render if the value changes — it\n // immediately re-renders with the updated state before committing.\n\n if (isPending && (phase === 'hidden' || phase === 'finishing')) {\n setPhase('crawling');\n }\n if (!isPending && phase === 'crawling') {\n setPhase('finishing');\n }\n\n // Inject keyframes on first visible render (idempotent)\n if (phase !== 'hidden') {\n ensureKeyframes();\n }\n\n if (phase === 'hidden') return null;\n\n // ─── Styles ──────────────────────────────────────────────────\n\n const containerStyle: React.CSSProperties = {\n position: 'fixed',\n top: 0,\n left: 0,\n width: '100%',\n height: `${height}px`,\n zIndex,\n pointerEvents: 'none',\n };\n\n const barStyle: React.CSSProperties = {\n height: '100%',\n backgroundColor: color,\n ...(phase === 'crawling'\n ? {\n // Crawl from 0% to 90% over 30s. When delay > 0, both the crawl\n // and a visibility animation are delayed — the bar stays at width 0%\n // and opacity 0 during the delay, then appears and starts crawling.\n // With delay 0, the appear animation is instant (0s duration, no delay).\n animation: [\n `${CRAWL_KEYFRAMES} 30s ease-out ${delay}ms forwards`,\n `${APPEAR_KEYFRAMES} 0s ${delay}ms both`,\n ].join(', '),\n }\n : {\n // Finishing: fill to 100% then fade out via a keyframe animation.\n // We use a keyframe instead of a CSS transition because the\n // animation-to-transition handoff is unreliable — the browser\n // may not capture the animated width as the transition's \"from\"\n // value when both the animation removal and transition are\n // applied in the same render frame.\n animation: `${FINISH_KEYFRAMES} 400ms ease forwards`,\n }),\n ...(shadow\n ? {\n boxShadow: `0 0 10px ${color}, 0 0 5px ${color}`,\n }\n : {}),\n };\n\n // Clean up the finishing phase when the finish animation completes.\n const handleAnimationEnd =\n phase === 'finishing'\n ? (e: React.AnimationEvent) => {\n if (e.animationName === FINISH_KEYFRAMES) {\n setPhase('hidden');\n }\n }\n : undefined;\n\n return createElement(\n 'div',\n {\n 'style': containerStyle,\n 'aria-hidden': 'true',\n 'data-timber-top-loader': '',\n },\n createElement('div', { style: barStyle, onAnimationEnd: handleAnimationEnd })\n );\n}\n","/**\n * NavigationRoot — Wrapper component for transition-based rendering.\n *\n * Solves the \"new boundary has no old content\" problem for client-side\n * navigation. When React renders a completely new Suspense boundary via\n * root.render(), it shows the fallback immediately — root.render() is\n * always an urgent update regardless of startTransition.\n *\n * NavigationRoot holds the current element in React state. Navigation\n * updates call startTransition(() => setState(newElement)), which IS\n * a transition update. React keeps the old committed tree visible while\n * any new Suspense boundaries in the transition resolve.\n *\n * Also manages `pendingUrl` as React state with an urgent/transition split:\n * - Navigation START: `setPendingUrl(url)` is an urgent update — React\n * commits it before the next paint, showing the spinner immediately.\n * - Navigation END: `setPendingUrl(null)` is inside `startTransition`\n * alongside `setElement(newTree)` — both commit atomically, so the\n * spinner disappears in the same frame as the new content appears.\n *\n * Hard navigation guard: When a hard navigation is triggered (500 error,\n * version skew), the component throws an unresolved thenable AFTER all\n * hooks to suspend forever — preventing React from rendering children\n * during page teardown. The throw must come after hooks to satisfy\n * React's rules (same hook count every render) while still preventing\n * child renders that could hit hook count mismatches in components\n * whose positions shift during teardown. This pattern is borrowed from\n * Next.js (app-router.tsx pushRef.mpaNavigation — also after hooks).\n *\n * See design/05-streaming.md §\"deferSuspenseFor\"\n * See design/19-client-navigation.md §\"NavigationContext\"\n */\n\nimport { createElement, Fragment, startTransition, useState, type ReactNode } from 'react';\nimport { PendingNavigationProvider } from './navigation-context.js';\nimport { TopLoader, type TopLoaderConfig } from './top-loader.js';\n\n// ─── Navigation Transition Counter ──────────────────────────────\n// Monotonically increasing counter that increments each time\n// navigateTransition() is called. Used to detect stale transitions:\n// if a newer transition started while the current one's perform()\n// was in flight, the current transition is stale and should reject.\n//\n// Separate from the link-pending navId (which only increments on\n// link clicks). This counter covers all navigation types: link clicks,\n// programmatic navigate(), refresh(), and handlePopState().\n//\n// Uses globalThis for singleton guarantee across chunks — same pattern\n// as NavigationContext and the link pending store.\n\nconst NAV_TRANSITION_KEY = Symbol.for('__timber_nav_transition_counter');\n\nfunction getTransitionCounter(): { id: number } {\n const g = globalThis as Record<symbol, unknown>;\n if (!g[NAV_TRANSITION_KEY]) {\n g[NAV_TRANSITION_KEY] = { id: 0 };\n }\n return g[NAV_TRANSITION_KEY] as { id: number };\n}\n\n// ─── Hard Navigation Guard ──────────────────────────────────────\n\n/**\n * Module-level flag indicating a hard (MPA) navigation is in progress.\n *\n * When true:\n * - NavigationRoot throws an unresolved thenable to suspend forever,\n * preventing React from rendering children during page teardown\n * (avoids \"Rendered more hooks\" crashes).\n * - The Navigation API handler skips interception, letting the browser\n * perform a full page load (prevents infinite loops where\n * window.location.href → navigate event → router.navigate → 500 →\n * window.location.href → ...).\n *\n * Uses globalThis for singleton guarantee across chunks (same pattern\n * as NavigationContext). See design/19-client-navigation.md §\"Singleton\n * Guarantee via globalThis\".\n */\nconst HARD_NAV_KEY = Symbol.for('__timber_hard_navigating');\n\nfunction getHardNavStore(): { value: boolean } {\n const g = globalThis as Record<symbol, unknown>;\n if (!g[HARD_NAV_KEY]) {\n g[HARD_NAV_KEY] = { value: false };\n }\n return g[HARD_NAV_KEY] as { value: boolean };\n}\n\n/**\n * Set the hard-navigating flag. Call this BEFORE setting\n * window.location.href or window.location.reload() to prevent:\n * 1. React from rendering children during page teardown\n * 2. Navigation API from intercepting the hard navigation\n */\nexport function setHardNavigating(value: boolean): void {\n getHardNavStore().value = value;\n}\n\n/**\n * Check if a hard navigation is in progress.\n * Used by NavigationRoot (throw unresolvedThenable) and by the\n * Navigation API handler (skip interception).\n */\nexport function isHardNavigating(): boolean {\n return getHardNavStore().value;\n}\n\n/**\n * A thenable that never resolves. When thrown during React render,\n * it causes the component to suspend forever — React keeps the\n * old committed tree visible and never attempts to render children.\n *\n * This is the same pattern Next.js uses in app-router.tsx for MPA\n * navigations (pushRef.mpaNavigation → throw unresolvedThenable).\n */\n// for React's Suspense mechanism. Same pattern as Next.js's unresolvedThenable.\n// eslint-disable-next-line unicorn/no-thenable -- Intentionally a never-resolving thenable\nconst unresolvedThenable = { then() {} } as PromiseLike<never>;\n\n// ─── Module-level functions ──────────────────────────────────────\n\n/**\n * Module-level reference to the state setter wrapped in startTransition.\n * Used for non-navigation renders (applyRevalidation, popstate replay).\n */\nlet _transitionRender: ((element: ReactNode) => void) | null = null;\n\n/**\n * Module-level reference to the navigation transition function.\n * Wraps a full navigation (fetch + render) in a single startTransition\n * with the pending URL.\n */\nlet _navigateTransition:\n | ((\n pendingUrl: string,\n perform: () => Promise<{ element: ReactNode; decodePromise: Promise<void> | null }>\n ) => Promise<void>)\n | null = null;\n\n// ─── Component ───────────────────────────────────────────────────\n\n/**\n * Root wrapper component that enables transition-based rendering.\n *\n * Renders PendingNavigationProvider around children for the pending URL\n * context. The DOM tree matches the server-rendered HTML during hydration\n * (the provider renders no extra DOM elements).\n *\n * Usage in browser-entry.ts:\n * const rootEl = createElement(NavigationRoot, { initial: wrapped });\n * reactRoot = hydrateRoot(document, rootEl);\n *\n * Subsequent navigations:\n * navigateTransition(url, async () => { fetch; return wrappedElement; });\n *\n * Non-navigation renders:\n * transitionRender(newWrappedElement);\n */\nexport function NavigationRoot({\n initial,\n topLoaderConfig,\n}: {\n initial: ReactNode;\n topLoaderConfig?: TopLoaderConfig;\n}): ReactNode {\n const [element, setElement] = useState<ReactNode>(initial);\n const [pendingUrl, setPendingUrl] = useState<string | null>(null);\n\n // NOTE: We use standalone `startTransition` (imported from 'react'),\n // NOT `useTransition`. The `useTransition` hook's `startTransition`\n // is tied to a single fiber and tracks one async callback at a time.\n // When two navigations overlap (click slow-page, then click dashboard),\n // calling useTransition's startTransition twice with concurrent async\n // callbacks corrupts React's internal hook tracking — causing\n // \"Rendered more hooks than during the previous render.\"\n //\n // Standalone `startTransition` creates independent transition lanes\n // for each call, so concurrent navigations don't interfere. We don't\n // need useTransition's `isPending` — we track pending state via our\n // own `pendingUrl` useState.\n //\n // This matches the Next.js pattern (TIM-625): \"No useTransition in\n // the router at all — only standalone startTransition.\"\n\n // Non-navigation render (revalidation, popstate cached replay).\n _transitionRender = (newElement: ReactNode) => {\n startTransition(() => {\n setElement(newElement);\n });\n };\n\n // Full navigation transition.\n // setPendingUrl(url) is an URGENT update — React commits it before the next\n // paint, so the pending spinner appears immediately when navigation starts.\n // Inside startTransition: the async fetch + setElement + setPendingUrl(null)\n // are deferred. When the transition commits, the new tree and pendingUrl=null\n // both apply in the same React commit — making the pending→active transition\n // atomic (no frame where pending is false but the old tree is still visible).\n _navigateTransition = (\n url: string,\n perform: () => Promise<{ element: ReactNode; decodePromise: Promise<void> | null }>\n ) => {\n // Increment the transition counter SYNCHRONOUSLY (before startTransition\n // schedules the async work). Each call gets a unique transId; the counter\n // is the same globalThis singleton, so a newer call always has a higher id.\n const counter = getTransitionCounter();\n const transId = ++counter.id;\n\n // NO urgent setPendingUrl here. Per-link pending state is driven by\n // Link's own useTransition — only the clicked Link re-renders for\n // isPending. setPendingUrl is set INSIDE startTransition so the\n // TopLoader activates as a transition update (no full-tree re-render).\n\n return new Promise<void>((resolve, reject) => {\n startTransition(async () => {\n setPendingUrl(url);\n try {\n const { element, decodePromise } = await perform();\n if (counter.id !== transId) {\n decodePromise?.catch(() => {});\n reject(new DOMException('Navigation superseded', 'AbortError'));\n return;\n }\n setElement(element);\n if (decodePromise) await decodePromise;\n if (counter.id === transId) {\n setPendingUrl(null);\n resolve();\n } else {\n reject(new DOMException('Navigation superseded', 'AbortError'));\n }\n } catch (err) {\n if (counter.id === transId) {\n setPendingUrl(null);\n }\n reject(err);\n }\n });\n });\n };\n\n // ─── Hard navigation guard ─────────────────────────────────\n // When a hard navigation is in progress (500 error, version skew),\n // suspend forever to prevent React from rendering children during\n // page teardown. This avoids \"Rendered more hooks\" crashes in\n // CHILD components whose hook counts may shift during teardown.\n //\n // CRITICAL: This throw MUST come AFTER all hooks (the two\n // useState calls above). React requires the same hooks to run on\n // every render. If we threw before hooks, React would see 0 hooks\n // on the re-render vs 2 hooks on the initial render — triggering\n // the exact \"Rendered more hooks\" error we're trying to prevent.\n //\n // By placing it after hooks but before the return, all hooks\n // satisfy React's rules, but the thrown thenable prevents any\n // children from rendering. Same pattern as Next.js app-router.tsx\n // (pushRef.mpaNavigation — also placed after all hooks).\n if (isHardNavigating()) {\n throw unresolvedThenable;\n }\n\n // Inject TopLoader alongside the element tree inside PendingNavigationProvider.\n // The TopLoader reads pendingUrl from context to show/hide the progress bar.\n // It is rendered only when not explicitly disabled via config.\n const showTopLoader = topLoaderConfig?.enabled !== false;\n const children = showTopLoader\n ? createElement(Fragment, null, createElement(TopLoader, { config: topLoaderConfig }), element)\n : element;\n return createElement(PendingNavigationProvider, { value: pendingUrl }, children);\n}\n\n// ─── Public API ──────────────────────────────────────────────────\n\n/**\n * Trigger a transition render for non-navigation updates.\n * React keeps the old committed tree visible while any new Suspense\n * boundaries in the update resolve.\n *\n * Used for: applyRevalidation, popstate replay with cached payload.\n */\nexport function transitionRender(element: ReactNode): void {\n if (_transitionRender) {\n _transitionRender(element);\n }\n}\n\n/**\n * Run a full navigation inside a React transition with optimistic pending URL.\n *\n * The `perform` callback runs inside `startTransition` — it should fetch the\n * RSC payload, update router state, and return the wrapped React element.\n * The pending URL shows immediately (urgent update) and reverts\n * to null when the transition commits (atomic with the new tree).\n *\n * Returns a Promise that resolves when the async work completes (note: the\n * React transition may not have committed yet, but all state updates are done).\n *\n * Used for: navigate(), refresh(), popstate with fetch.\n */\nexport function navigateTransition(\n pendingUrl: string,\n perform: () => Promise<{ element: ReactNode; decodePromise: Promise<void> | null }>\n): Promise<void> {\n if (_navigateTransition) {\n return _navigateTransition(pendingUrl, perform);\n }\n // Fallback: no NavigationRoot mounted (shouldn't happen in production)\n return perform().then(() => {});\n}\n\n/**\n * Check if the NavigationRoot is mounted and ready for renders.\n * Used by browser-entry.ts to guard against renders before hydration.\n */\nexport function isNavigationRootReady(): boolean {\n return _transitionRender !== null;\n}\n\n/**\n * Install one-shot deferred callbacks for the no-RSC bootstrap path (TIM-600).\n *\n * When there's no RSC payload, we can't create a React root immediately —\n * `createRoot(document).render(...)` would blank the SSR HTML. Instead,\n * this sets up `_transitionRender` and `_navigateTransition` so that the\n * first client navigation triggers root creation via `createAndMount`.\n *\n * After `createAndMount` runs, NavigationRoot renders and overwrites these\n * callbacks with its real `startTransition`-based implementations.\n */\nexport function installDeferredNavigation(createAndMount: (initial: ReactNode) => void): void {\n let mounted = false;\n const mountOnce = (element: ReactNode) => {\n if (mounted) return;\n mounted = true;\n createAndMount(element);\n };\n _transitionRender = (element: ReactNode) => {\n mountOnce(element);\n };\n _navigateTransition = async (\n _pendingUrl: string,\n perform: () => Promise<{ element: ReactNode; decodePromise: Promise<void> | null }>\n ) => {\n const { element } = await perform();\n mountOnce(element);\n };\n}\n"],"mappings":";;;;AAGA,SAAS,UAAU,eAAuC;CACxD,MAAM,SAAS,gBAAgB;CAC/B,IAAI,CAAC,QAAQ,aAAa,CAAC;CAC3B,OAAO,OAAO,gBAAgB,aAAa;AAC7C;AAEA,SAAS,cAAuB;CAC9B,MAAM,SAAS,gBAAgB;CAC/B,OAAO,SAAS,OAAO,UAAU,IAAI;AACvC;AAEA,IAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;AAuB1B,SAAgB,uBAAgC;CAC9C,OAAO,qBAAqB,WAAW,aAAa,iBAAiB;AACvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AEuCA,IAAM,eAAe,OAAO,IAAI,0BAA0B;AAE1D,SAAS,kBAAsC;CAC7C,MAAM,IAAI;CACV,IAAI,CAAC,EAAE,eACL,EAAE,gBAAgB,EAAE,OAAO,MAAM;CAEnC,OAAO,EAAE;AACX;;;;;;;AAQA,SAAgB,kBAAkB,OAAsB;CACtD,gBAAgB,EAAE,QAAQ;AAC5B"}
@@ -0,0 +1,20 @@
1
+ //#region src/search-params/registry.ts
2
+ var registry = /* @__PURE__ */ new Map();
3
+ /**
4
+ * Register a route's search params definition.
5
+ * Called by the generated route manifest loader when a route's modules load.
6
+ */
7
+ function registerSearchParams(route, definition) {
8
+ registry.set(route, definition);
9
+ }
10
+ /**
11
+ * Look up a route's search params definition.
12
+ * Returns undefined if the route hasn't been loaded yet.
13
+ */
14
+ function getSearchParamsDefinition(route) {
15
+ return registry.get(route);
16
+ }
17
+ //#endregion
18
+ export { registerSearchParams as n, getSearchParamsDefinition as t };
19
+
20
+ //# sourceMappingURL=registry-DbJPKoBp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry-DbJPKoBp.js","names":[],"sources":["../../src/search-params/registry.ts"],"sourcesContent":["/**\n * Runtime registry for route-scoped search params definitions.\n *\n * When a route's modules load, the framework registers its search-params\n * definition here. useQueryStates('/route') resolves codecs from this map.\n *\n * Design doc: design/23-search-params.md §\"Runtime: Registration at Route Load\"\n */\n\nimport type { SearchParamsDefinition } from './define.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst registry = new Map<string, SearchParamsDefinition<any>>();\n\n/**\n * Register a route's search params definition.\n * Called by the generated route manifest loader when a route's modules load.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function registerSearchParams(route: string, definition: SearchParamsDefinition<any>): void {\n registry.set(route, definition);\n}\n\n/**\n * Look up a route's search params definition.\n * Returns undefined if the route hasn't been loaded yet.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function getSearchParamsDefinition(route: string): SearchParamsDefinition<any> | undefined {\n return registry.get(route);\n}\n"],"mappings":";AAYA,IAAM,2BAAW,IAAI,IAAyC;;;;;AAO9D,SAAgB,qBAAqB,OAAe,YAA+C;CACjG,SAAS,IAAI,OAAO,UAAU;AAChC;;;;;AAOA,SAAgB,0BAA0B,OAAwD;CAChG,OAAO,SAAS,IAAI,KAAK;AAC3B"}
@@ -0,0 +1,77 @@
1
+ import { a as validateSync, i as isStandardSchema, r as isCodec } from "./schema-bridge-DK_89h8O.js";
2
+ //#region src/params/resolve-schema.ts
3
+ /**
4
+ * Wrap a Standard Schema into a Codec for route params.
5
+ * Parse throws on failure (invalid param → 404). Serialize returns string.
6
+ */
7
+ function fromParamSchema(fieldName, schema) {
8
+ return {
9
+ parse(value) {
10
+ const result = validateSync(schema, value);
11
+ if (!result.issues) return result.value;
12
+ const messages = result.issues.map((i) => i.message).join(", ");
13
+ throw new Error(`[timber] Param '${fieldName}' coercion failed: ${messages}`);
14
+ },
15
+ serialize(value) {
16
+ if (value === null || value === void 0) return null;
17
+ if (Array.isArray(value)) return value.join("/");
18
+ return String(value);
19
+ }
20
+ };
21
+ }
22
+ /**
23
+ * Resolve a schema entry to a Codec. Accepts Codec<T> or StandardSchemaV1<T>.
24
+ */
25
+ function resolveCodec(fieldName, value) {
26
+ if (isCodec(value)) return value;
27
+ if (isStandardSchema(value)) return fromParamSchema(fieldName, value);
28
+ throw new Error(`[timber] Schema field '${fieldName}' is not a valid codec or Standard Schema.`);
29
+ }
30
+ /**
31
+ * Reconstruct the bracket key for a segment from its type and param name.
32
+ * Used by the coercion layer to look up codecs in the bracket-keyed map.
33
+ *
34
+ * 'dynamic' + 'id' → '[id]'
35
+ * 'catch-all' + 'slug' → '[...slug]'
36
+ * 'optional-catch-all' + 'slug' → '[[...slug]]'
37
+ */
38
+ function toBracketKey(segmentType, paramName) {
39
+ switch (segmentType) {
40
+ case "catch-all": return `[...${paramName}]`;
41
+ case "optional-catch-all": return `[[...${paramName}]]`;
42
+ default: return `[${paramName}]`;
43
+ }
44
+ }
45
+ var CATCH_ALL_RE = /^\[\.\.\..+\]$/;
46
+ var OPTIONAL_CATCH_ALL_RE = /^\[\[\.\.\..+\]\]$/;
47
+ function isCatchAllKey(key) {
48
+ return CATCH_ALL_RE.test(key) || OPTIONAL_CATCH_ALL_RE.test(key);
49
+ }
50
+ function isOptionalCatchAllKey(key) {
51
+ return OPTIONAL_CATCH_ALL_RE.test(key);
52
+ }
53
+ /**
54
+ * Resolve the global schema's segmentParams into a map of bracket-keyed
55
+ * param name → resolved Codec.
56
+ *
57
+ * Keys are preserved exactly as written in `app/schema.ts` so that
58
+ * `[id]`, `[...id]`, and `[[...id]]` remain distinct entries.
59
+ * The coercion layer in `param-coercion.ts` reconstructs bracket keys
60
+ * from matched segment metadata to look up the correct codec.
61
+ *
62
+ * Input: { '[id]': z.coerce.number(), '[...slug]': codec.string }
63
+ * Output: { '[id]': Codec<number>, '[...slug]': Codec<string> }
64
+ */
65
+ function resolveSchemaCodecs(segmentParams) {
66
+ const resolved = Object.create(null);
67
+ for (const [bracketName, value] of Object.entries(segmentParams)) {
68
+ if (isCatchAllKey(bracketName) && isCodec(value) && !("__catchAll" in value)) throw new Error(`[timber] Schema error: '${bracketName}' is a catch-all segment and requires an array codec (e.g. codec.catchAll(codec.string)). Got a scalar codec.`);
69
+ if (isOptionalCatchAllKey(bracketName) && isCodec(value) && "__catchAll" in value && !("__optional" in value)) throw new Error(`[timber] Schema error: '${bracketName}' is an optional catch-all segment and requires codec.optionalCatchAll() (e.g. codec.optionalCatchAll(codec.string)). Got a non-optional catch-all codec.`);
70
+ resolved[bracketName] = resolveCodec(bracketName, value);
71
+ }
72
+ return resolved;
73
+ }
74
+ //#endregion
75
+ export { toBracketKey as n, resolveSchemaCodecs as t };
76
+
77
+ //# sourceMappingURL=resolve-schema-Dj8tQloi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-schema-Dj8tQloi.js","names":[],"sources":["../../src/params/resolve-schema.ts"],"sourcesContent":["/**\n * Schema resolution — resolves the global schema's segmentParams into\n * a runtime-ready codec map keyed by bracket name (e.g. '[id]').\n *\n * Bracket keys are preserved so that `[id]`, `[...id]`, and `[[...id]]`\n * remain distinct entries. The coercion layer reconstructs bracket keys\n * from matched segment metadata to look up the correct codec.\n *\n * Design doc: design/41-global-params.md §Pipeline Integration\n */\n\nimport type { Codec } from '../codec.js';\nimport { isCodec, isStandardSchema, validateSync } from '../schema-bridge.js';\nimport type { StandardSchemaV1 } from '../schema-bridge.js';\n\n/**\n * Wrap a Standard Schema into a Codec for route params.\n * Parse throws on failure (invalid param → 404). Serialize returns string.\n */\nfunction fromParamSchema<T>(fieldName: string, schema: StandardSchemaV1<T>): Codec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n const result = validateSync(schema, value);\n if (!result.issues) {\n return result.value;\n }\n const messages = result.issues.map((i) => i.message).join(', ');\n throw new Error(`[timber] Param '${fieldName}' coercion failed: ${messages}`);\n },\n serialize(value: T): string | null {\n if (value === null || value === undefined) return null;\n if (Array.isArray(value)) return value.join('/');\n return String(value);\n },\n };\n}\n\n/**\n * Resolve a schema entry to a Codec. Accepts Codec<T> or StandardSchemaV1<T>.\n */\nfunction resolveCodec(fieldName: string, value: unknown): Codec<unknown> {\n if (isCodec(value)) return value;\n if (isStandardSchema(value)) return fromParamSchema(fieldName, value);\n throw new Error(`[timber] Schema field '${fieldName}' is not a valid codec or Standard Schema.`);\n}\n\n/**\n * Reconstruct the bracket key for a segment from its type and param name.\n * Used by the coercion layer to look up codecs in the bracket-keyed map.\n *\n * 'dynamic' + 'id' → '[id]'\n * 'catch-all' + 'slug' → '[...slug]'\n * 'optional-catch-all' + 'slug' → '[[...slug]]'\n */\nexport function toBracketKey(segmentType: string, paramName: string): string {\n switch (segmentType) {\n case 'catch-all':\n return `[...${paramName}]`;\n case 'optional-catch-all':\n return `[[...${paramName}]]`;\n default:\n return `[${paramName}]`;\n }\n}\n\nconst CATCH_ALL_RE = /^\\[\\.\\.\\..+\\]$/;\nconst OPTIONAL_CATCH_ALL_RE = /^\\[\\[\\.\\.\\..+\\]\\]$/;\n\nfunction isCatchAllKey(key: string): boolean {\n return CATCH_ALL_RE.test(key) || OPTIONAL_CATCH_ALL_RE.test(key);\n}\n\nfunction isOptionalCatchAllKey(key: string): boolean {\n return OPTIONAL_CATCH_ALL_RE.test(key);\n}\n\n/**\n * Resolve the global schema's segmentParams into a map of bracket-keyed\n * param name → resolved Codec.\n *\n * Keys are preserved exactly as written in `app/schema.ts` so that\n * `[id]`, `[...id]`, and `[[...id]]` remain distinct entries.\n * The coercion layer in `param-coercion.ts` reconstructs bracket keys\n * from matched segment metadata to look up the correct codec.\n *\n * Input: { '[id]': z.coerce.number(), '[...slug]': codec.string }\n * Output: { '[id]': Codec<number>, '[...slug]': Codec<string> }\n */\nexport function resolveSchemaCodecs(\n segmentParams: Record<string, unknown>\n): Record<string, Codec<unknown>> {\n const resolved: Record<string, Codec<unknown>> = Object.create(null);\n\n for (const [bracketName, value] of Object.entries(segmentParams)) {\n if (isCatchAllKey(bracketName) && isCodec(value) && !('__catchAll' in value)) {\n throw new Error(\n `[timber] Schema error: '${bracketName}' is a catch-all segment and requires an array codec ` +\n `(e.g. codec.catchAll(codec.string)). Got a scalar codec.`\n );\n }\n if (\n isOptionalCatchAllKey(bracketName) &&\n isCodec(value) &&\n '__catchAll' in value &&\n !('__optional' in value)\n ) {\n throw new Error(\n `[timber] Schema error: '${bracketName}' is an optional catch-all segment and requires codec.optionalCatchAll() ` +\n `(e.g. codec.optionalCatchAll(codec.string)). Got a non-optional catch-all codec.`\n );\n }\n resolved[bracketName] = resolveCodec(bracketName, value);\n }\n\n return resolved;\n}\n"],"mappings":";;;;;;AAmBA,SAAS,gBAAmB,WAAmB,QAAuC;CACpF,OAAO;EACL,MAAM,OAAyC;GAC7C,MAAM,SAAS,aAAa,QAAQ,KAAK;GACzC,IAAI,CAAC,OAAO,QACV,OAAO,OAAO;GAEhB,MAAM,WAAW,OAAO,OAAO,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI;GAC9D,MAAM,IAAI,MAAM,mBAAmB,UAAU,qBAAqB,UAAU;EAC9E;EACA,UAAU,OAAyB;GACjC,IAAI,UAAU,QAAQ,UAAU,KAAA,GAAW,OAAO;GAClD,IAAI,MAAM,QAAQ,KAAK,GAAG,OAAO,MAAM,KAAK,GAAG;GAC/C,OAAO,OAAO,KAAK;EACrB;CACF;AACF;;;;AAKA,SAAS,aAAa,WAAmB,OAAgC;CACvE,IAAI,QAAQ,KAAK,GAAG,OAAO;CAC3B,IAAI,iBAAiB,KAAK,GAAG,OAAO,gBAAgB,WAAW,KAAK;CACpE,MAAM,IAAI,MAAM,0BAA0B,UAAU,2CAA2C;AACjG;;;;;;;;;AAUA,SAAgB,aAAa,aAAqB,WAA2B;CAC3E,QAAQ,aAAR;EACE,KAAK,aACH,OAAO,OAAO,UAAU;EAC1B,KAAK,sBACH,OAAO,QAAQ,UAAU;EAC3B,SACE,OAAO,IAAI,UAAU;CACzB;AACF;AAEA,IAAM,eAAe;AACrB,IAAM,wBAAwB;AAE9B,SAAS,cAAc,KAAsB;CAC3C,OAAO,aAAa,KAAK,GAAG,KAAK,sBAAsB,KAAK,GAAG;AACjE;AAEA,SAAS,sBAAsB,KAAsB;CACnD,OAAO,sBAAsB,KAAK,GAAG;AACvC;;;;;;;;;;;;;AAcA,SAAgB,oBACd,eACgC;CAChC,MAAM,WAA2C,OAAO,OAAO,IAAI;CAEnE,KAAK,MAAM,CAAC,aAAa,UAAU,OAAO,QAAQ,aAAa,GAAG;EAChE,IAAI,cAAc,WAAW,KAAK,QAAQ,KAAK,KAAK,EAAE,gBAAgB,QACpE,MAAM,IAAI,MACR,2BAA2B,YAAY,8GAEzC;EAEF,IACE,sBAAsB,WAAW,KACjC,QAAQ,KAAK,KACb,gBAAgB,SAChB,EAAE,gBAAgB,QAElB,MAAM,IAAI,MACR,2BAA2B,YAAY,0JAEzC;EAEF,SAAS,eAAe,aAAa,aAAa,KAAK;CACzD;CAEA,OAAO;AACT"}
@@ -0,0 +1,28 @@
1
+ import { o as _setGlobalRouter, u as globalRouter } from "./ssr-data-BOWsq18U.js";
2
+ //#region src/client/router-ref.ts
3
+ /**
4
+ * Set the global router instance. Called once during bootstrap.
5
+ */
6
+ function setGlobalRouter(router) {
7
+ _setGlobalRouter(router);
8
+ }
9
+ /**
10
+ * Get the global router instance. Throws if called before bootstrap.
11
+ * Used by client-side hooks (usePendingNavigation, etc.)
12
+ */
13
+ function getRouter() {
14
+ if (!globalRouter) throw new Error("[timber] Router not initialized. getRouter() was called before bootstrap().");
15
+ return globalRouter;
16
+ }
17
+ /**
18
+ * Get the global router instance or null if not yet initialized.
19
+ * Used by useRouter() methods to avoid silent failures — callers
20
+ * can log a meaningful warning instead of silently no-oping.
21
+ */
22
+ function getRouterOrNull() {
23
+ return globalRouter;
24
+ }
25
+ //#endregion
26
+ export { getRouterOrNull as n, setGlobalRouter as r, getRouter as t };
27
+
28
+ //# sourceMappingURL=router-ref-CtmF-aPv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router-ref-CtmF-aPv.js","names":[],"sources":["../../src/client/router-ref.ts"],"sourcesContent":["// Global router reference — shared between browser-entry and client hooks.\n//\n// Delegates to client/state.ts for the actual module-level variable.\n// This ensures singleton semantics regardless of import path — all\n// callers converge on the same state.ts instance via the barrel.\n//\n// See design/18-build-system.md §\"Module Singleton Strategy\"\n\nimport type { RouterInstance } from './router.js';\nimport { globalRouter, _setGlobalRouter } from './state.js';\n\n/**\n * Set the global router instance. Called once during bootstrap.\n */\nexport function setGlobalRouter(router: RouterInstance): void {\n _setGlobalRouter(router);\n}\n\n/**\n * Get the global router instance. Throws if called before bootstrap.\n * Used by client-side hooks (usePendingNavigation, etc.)\n */\nexport function getRouter(): RouterInstance {\n if (!globalRouter) {\n throw new Error('[timber] Router not initialized. getRouter() was called before bootstrap().');\n }\n return globalRouter;\n}\n\n/**\n * Get the global router instance or null if not yet initialized.\n * Used by useRouter() methods to avoid silent failures — callers\n * can log a meaningful warning instead of silently no-oping.\n */\nexport function getRouterOrNull(): RouterInstance | null {\n return globalRouter;\n}\n\n/**\n * Reset the global router to null. Used only in tests to isolate\n * module-level state between test cases.\n * @internal\n */\nexport function resetGlobalRouter(): void {\n _setGlobalRouter(null);\n}\n"],"mappings":";;;;;AAcA,SAAgB,gBAAgB,QAA8B;CAC5D,iBAAiB,MAAM;AACzB;;;;;AAMA,SAAgB,YAA4B;CAC1C,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,6EAA6E;CAE/F,OAAO;AACT;;;;;;AAOA,SAAgB,kBAAyC;CACvD,OAAO;AACT"}
@@ -0,0 +1,86 @@
1
+ //#region src/schema-bridge.ts
2
+ /**
3
+ * Run a Standard Schema's `~standard.validate()` synchronously.
4
+ *
5
+ * Zod v4's signature includes `Promise` in the return union to satisfy the
6
+ * Standard Schema spec, but in practice Zod always validates synchronously
7
+ * for the schema types we use. We assert the result is sync and throw if
8
+ * it isn't — codec parsing must be synchronous.
9
+ */
10
+ function validateSync(schema, value) {
11
+ const result = schema["~standard"].validate(value);
12
+ if (result instanceof Promise) throw new Error("[timber] fromSchema: schema returned a Promise — only sync schemas are supported.");
13
+ return result;
14
+ }
15
+ /** Check if a value is a Standard Schema object. */
16
+ function isStandardSchema(value) {
17
+ return typeof value === "object" && value !== null && "~standard" in value && typeof value["~standard"]?.validate === "function";
18
+ }
19
+ /** Check if a value is a Codec (has parse + serialize methods). */
20
+ function isCodec(value) {
21
+ return typeof value === "object" && value !== null && typeof value.parse === "function" && typeof value.serialize === "function";
22
+ }
23
+ /**
24
+ * Bridge a Standard Schema-compatible schema (Zod, Valibot, ArkType) to a
25
+ * Codec<T>.
26
+ *
27
+ * Parse: coerces the raw string through the schema. On validation failure,
28
+ * parses `undefined` to get the schema's default value (the schema should have
29
+ * a `.default()` call). If that also fails, returns `undefined`.
30
+ *
31
+ * Serialize: uses `String()` for primitives, `null` for null/undefined.
32
+ *
33
+ * ```ts
34
+ * import { fromSchema } from '@timber-js/app/codec'
35
+ * import { z } from 'zod/v4'
36
+ *
37
+ * const pageCodec = fromSchema(z.coerce.number().int().min(1).default(1))
38
+ * ```
39
+ */
40
+ function fromSchema(schema) {
41
+ return {
42
+ parse(value) {
43
+ const result = validateSync(schema, Array.isArray(value) ? value[0] : value);
44
+ if (!result.issues) return result.value;
45
+ const defaultResult = validateSync(schema, void 0);
46
+ if (!defaultResult.issues) return defaultResult.value;
47
+ },
48
+ serialize(value) {
49
+ if (value === null || value === void 0) return null;
50
+ return String(value);
51
+ }
52
+ };
53
+ }
54
+ /**
55
+ * Bridge a Standard Schema for array values. Handles both single strings
56
+ * and repeated query keys (`?tag=a&tag=b`).
57
+ *
58
+ * ```ts
59
+ * import { fromArraySchema } from '@timber-js/app/codec'
60
+ * import { z } from 'zod/v4'
61
+ *
62
+ * const tagsCodec = fromArraySchema(z.array(z.string()).default([]))
63
+ * ```
64
+ */
65
+ function fromArraySchema(schema) {
66
+ return {
67
+ parse(value) {
68
+ let input = value;
69
+ if (typeof value === "string") input = [value];
70
+ else if (value === void 0) input = void 0;
71
+ const result = validateSync(schema, input);
72
+ if (!result.issues) return result.value;
73
+ const defaultResult = validateSync(schema, void 0);
74
+ if (!defaultResult.issues) return defaultResult.value;
75
+ },
76
+ serialize(value) {
77
+ if (value === null || value === void 0) return null;
78
+ if (Array.isArray(value)) return value.length === 0 ? null : value.join(",");
79
+ return String(value);
80
+ }
81
+ };
82
+ }
83
+ //#endregion
84
+ export { validateSync as a, isStandardSchema as i, fromSchema as n, isCodec as r, fromArraySchema as t };
85
+
86
+ //# sourceMappingURL=schema-bridge-DK_89h8O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-bridge-DK_89h8O.js","names":[],"sources":["../../src/schema-bridge.ts"],"sourcesContent":["/**\n * Standard Schema bridge — shared helpers for bridging Standard Schema-compatible\n * validation libraries (Zod, Valibot, ArkType) to the Codec<T> protocol.\n *\n * This module is the single source of truth for:\n * - StandardSchemaV1 interface (subset of the Standard Schema spec)\n * - validateSync() helper\n * - fromSchema() — bridge from Standard Schema to Codec<T>\n * - fromArraySchema() — bridge for array-valued codecs\n *\n * These are re-exported from @timber-js/app/search-params, @timber-js/app/segment-params,\n * and @timber-js/app/cookies for convenience. The canonical import is\n * @timber-js/app/codec.\n *\n * Design doc: design/23a-search-params-triage.md §\"Unify Codec<T> type\"\n */\n\nimport type { Codec } from './codec.js';\n\n// ---------------------------------------------------------------------------\n// Standard Schema interface (subset)\n//\n// Standard Schema (https://github.com/standard-schema/standard-schema) defines\n// a minimal interface that Zod ≥3.24, Valibot ≥1.0, and ArkType all implement.\n// We depend only on `~standard.validate` to avoid coupling to any specific lib.\n// ---------------------------------------------------------------------------\n\n/** Minimal Standard Schema interface for auto-detection. */\nexport interface StandardSchemaV1<Output = unknown> {\n '~standard': {\n validate(value: unknown): StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;\n };\n}\n\nexport type StandardSchemaResult<Output> =\n | { value: Output; issues?: undefined }\n | { value?: undefined; issues: ReadonlyArray<{ message: string }> };\n\n// ---------------------------------------------------------------------------\n// Sync validate helper\n// ---------------------------------------------------------------------------\n\n/**\n * Run a Standard Schema's `~standard.validate()` synchronously.\n *\n * Zod v4's signature includes `Promise` in the return union to satisfy the\n * Standard Schema spec, but in practice Zod always validates synchronously\n * for the schema types we use. We assert the result is sync and throw if\n * it isn't — codec parsing must be synchronous.\n */\nexport function validateSync<Output>(\n schema: StandardSchemaV1<Output>,\n value: unknown\n): StandardSchemaResult<Output> {\n const result = schema['~standard'].validate(value);\n if (result instanceof Promise) {\n throw new Error(\n '[timber] fromSchema: schema returned a Promise — only sync schemas are supported.'\n );\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Type guards\n// ---------------------------------------------------------------------------\n\n/** Check if a value is a Standard Schema object. */\nexport function isStandardSchema(value: unknown): value is StandardSchemaV1 {\n return (\n typeof value === 'object' &&\n value !== null &&\n '~standard' in value &&\n typeof (value as StandardSchemaV1)['~standard']?.validate === 'function'\n );\n}\n\n/** Check if a value is a Codec (has parse + serialize methods). */\nexport function isCodec(value: unknown): value is Codec<unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as Codec<unknown>).parse === 'function' &&\n typeof (value as Codec<unknown>).serialize === 'function'\n );\n}\n\n// ---------------------------------------------------------------------------\n// fromSchema — bridge from Standard Schema to Codec<T>\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge a Standard Schema-compatible schema (Zod, Valibot, ArkType) to a\n * Codec<T>.\n *\n * Parse: coerces the raw string through the schema. On validation failure,\n * parses `undefined` to get the schema's default value (the schema should have\n * a `.default()` call). If that also fails, returns `undefined`.\n *\n * Serialize: uses `String()` for primitives, `null` for null/undefined.\n *\n * ```ts\n * import { fromSchema } from '@timber-js/app/codec'\n * import { z } from 'zod/v4'\n *\n * const pageCodec = fromSchema(z.coerce.number().int().min(1).default(1))\n * ```\n */\nexport function fromSchema<T>(schema: StandardSchemaV1<T>): Codec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n // For array inputs (duplicate query keys), use the first value.\n // Browsers and URLSearchParams.get() return the first occurrence.\n const input = Array.isArray(value) ? value[0] : value;\n\n // Try parsing the raw value\n const result = validateSync(schema, input);\n if (!result.issues) {\n return result.value;\n }\n\n // On failure, try parsing undefined to get the default\n const defaultResult = validateSync(schema, undefined);\n if (!defaultResult.issues) {\n return defaultResult.value;\n }\n\n // No default available — return undefined (codec design choice)\n return undefined as T;\n },\n\n serialize(value: T): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n return String(value);\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// fromArraySchema — bridge for array-valued codecs\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge a Standard Schema for array values. Handles both single strings\n * and repeated query keys (`?tag=a&tag=b`).\n *\n * ```ts\n * import { fromArraySchema } from '@timber-js/app/codec'\n * import { z } from 'zod/v4'\n *\n * const tagsCodec = fromArraySchema(z.array(z.string()).default([]))\n * ```\n */\nexport function fromArraySchema<T>(schema: StandardSchemaV1<T>): Codec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n // Coerce single string to array for array schemas\n let input: unknown = value;\n if (typeof value === 'string') {\n input = [value];\n } else if (value === undefined) {\n input = undefined;\n }\n\n const result = validateSync(schema, input);\n if (!result.issues) {\n return result.value;\n }\n\n // On failure, try undefined for default\n const defaultResult = validateSync(schema, undefined);\n if (!defaultResult.issues) {\n return defaultResult.value;\n }\n\n return undefined as T;\n },\n\n serialize(value: T): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (Array.isArray(value)) {\n return value.length === 0 ? null : value.join(',');\n }\n return String(value);\n },\n };\n}\n"],"mappings":";;;;;;;;;AAkDA,SAAgB,aACd,QACA,OAC8B;CAC9B,MAAM,SAAS,OAAO,aAAa,SAAS,KAAK;CACjD,IAAI,kBAAkB,SACpB,MAAM,IAAI,MACR,mFACF;CAEF,OAAO;AACT;;AAOA,SAAgB,iBAAiB,OAA2C;CAC1E,OACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACf,OAAQ,MAA2B,cAAc,aAAa;AAElE;;AAGA,SAAgB,QAAQ,OAAyC;CAC/D,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAyB,UAAU,cAC3C,OAAQ,MAAyB,cAAc;AAEnD;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,WAAc,QAAuC;CACnE,OAAO;EACL,MAAM,OAAyC;GAM7C,MAAM,SAAS,aAAa,QAHd,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,KAGP;GACzC,IAAI,CAAC,OAAO,QACV,OAAO,OAAO;GAIhB,MAAM,gBAAgB,aAAa,QAAQ,KAAA,CAAS;GACpD,IAAI,CAAC,cAAc,QACjB,OAAO,cAAc;EAKzB;EAEA,UAAU,OAAyB;GACjC,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,OAAO;GAET,OAAO,OAAO,KAAK;EACrB;CACF;AACF;;;;;;;;;;;;AAiBA,SAAgB,gBAAmB,QAAuC;CACxE,OAAO;EACL,MAAM,OAAyC;GAE7C,IAAI,QAAiB;GACrB,IAAI,OAAO,UAAU,UACnB,QAAQ,CAAC,KAAK;QACT,IAAI,UAAU,KAAA,GACnB,QAAQ,KAAA;GAGV,MAAM,SAAS,aAAa,QAAQ,KAAK;GACzC,IAAI,CAAC,OAAO,QACV,OAAO,OAAO;GAIhB,MAAM,gBAAgB,aAAa,QAAQ,KAAA,CAAS;GACpD,IAAI,CAAC,cAAc,QACjB,OAAO,cAAc;EAIzB;EAEA,UAAU,OAAyB;GACjC,IAAI,UAAU,QAAQ,UAAU,KAAA,GAC9B,OAAO;GAET,IAAI,MAAM,QAAQ,KAAK,GACrB,OAAO,MAAM,WAAW,IAAI,OAAO,MAAM,KAAK,GAAG;GAEnD,OAAO,OAAO,KAAK;EACrB;CACF;AACF"}
@@ -0,0 +1,137 @@
1
+ //#region src/routing/types.ts
2
+ /** All recognized interception markers, ordered longest-first for parsing. */
3
+ var INTERCEPTION_MARKERS = [
4
+ "(..)(..)",
5
+ "(.)",
6
+ "(..)",
7
+ "(...)"
8
+ ];
9
+ /** Default page extensions */
10
+ var DEFAULT_PAGE_EXTENSIONS = [
11
+ "tsx",
12
+ "ts",
13
+ "jsx",
14
+ "js"
15
+ ];
16
+ //#endregion
17
+ //#region src/routing/segment-classify.ts
18
+ /**
19
+ * Classify a URL path segment token.
20
+ *
21
+ * Walks the string left-to-right in one pass:
22
+ * 1. If it doesn't start with '[', it's static.
23
+ * 2. Count opening brackets (1 or 2) to detect optional.
24
+ * 3. Check for '...' to detect catch-all.
25
+ * 4. Read the param name up to the closing bracket.
26
+ * 5. Validate the expected closing sequence (']' or ']]').
27
+ * 6. Reject if there are leftover characters after the close.
28
+ *
29
+ * Any structural violation → static (safe default).
30
+ */
31
+ function classifyUrlSegment(token) {
32
+ const len = token.length;
33
+ if (len === 0 || token[0] !== "[") return {
34
+ kind: "static",
35
+ value: token
36
+ };
37
+ let i = 1;
38
+ const optional = token[i] === "[";
39
+ if (optional) i++;
40
+ const catchAll = i + 2 < len && token[i] === "." && token[i + 1] === "." && token[i + 2] === ".";
41
+ if (catchAll) i += 3;
42
+ const nameStart = i;
43
+ while (i < len && token[i] !== "]") i++;
44
+ if (i >= len || i === nameStart) return {
45
+ kind: "static",
46
+ value: token
47
+ };
48
+ const name = token.slice(nameStart, i);
49
+ i++;
50
+ if (optional) {
51
+ if (i >= len || token[i] !== "]") return {
52
+ kind: "static",
53
+ value: token
54
+ };
55
+ i++;
56
+ }
57
+ if (i !== len) return {
58
+ kind: "static",
59
+ value: token
60
+ };
61
+ if (optional && catchAll) return {
62
+ kind: "optional-catch-all",
63
+ name
64
+ };
65
+ if (catchAll) return {
66
+ kind: "catch-all",
67
+ name
68
+ };
69
+ if (optional) return {
70
+ kind: "static",
71
+ value: token
72
+ };
73
+ return {
74
+ kind: "dynamic",
75
+ name
76
+ };
77
+ }
78
+ /**
79
+ * Classify a directory name into its segment type.
80
+ *
81
+ * Recognizes all timber file-system conventions in priority order:
82
+ * 1. Private folders: `_name` (excluded from routing)
83
+ * 2. Parallel route slots: `@name`
84
+ * 3. Intercepting routes: `(.)name`, `(..)name`, `(...)name`, `(..)(..)name`
85
+ * 4. Route groups: `(name)`
86
+ * 5. Bracket syntax: `[id]`, `[...slug]`, `[[...path]]` (delegated to
87
+ * `classifyUrlSegment`)
88
+ * 6. Static: anything else
89
+ *
90
+ * If you change the bracket syntax, update only `classifyUrlSegment`.
91
+ * If you change the directory-prefix conventions, update this function.
92
+ */
93
+ function classifySegment(dirName) {
94
+ if (dirName.startsWith("_")) return { type: "private" };
95
+ if (dirName.startsWith("@")) return { type: "slot" };
96
+ const interception = parseInterceptionMarker(dirName);
97
+ if (interception) return {
98
+ type: "intercepting",
99
+ interceptionMarker: interception.marker,
100
+ interceptedSegmentName: interception.segmentName
101
+ };
102
+ if (dirName.startsWith("(") && dirName.endsWith(")")) return { type: "group" };
103
+ const urlSeg = classifyUrlSegment(dirName);
104
+ if (urlSeg.kind !== "static") return {
105
+ type: urlSeg.kind,
106
+ paramName: urlSeg.name
107
+ };
108
+ return { type: "static" };
109
+ }
110
+ /**
111
+ * Parse an interception marker from a directory name.
112
+ *
113
+ * Returns the marker and the remaining segment name, or null if not an
114
+ * intercepting route. Markers are checked longest-first to avoid `(..)`
115
+ * matching before `(..)(..)`.
116
+ *
117
+ * Examples:
118
+ * "(.)photo" → { marker: "(.)", segmentName: "photo" }
119
+ * "(..)feed" → { marker: "(..)", segmentName: "feed" }
120
+ * "(...)photos" → { marker: "(...)", segmentName: "photos" }
121
+ * "(..)(..)admin" → { marker: "(..)(..)", segmentName: "admin" }
122
+ * "(marketing)" → null (route group, not interception)
123
+ */
124
+ function parseInterceptionMarker(dirName) {
125
+ for (const marker of INTERCEPTION_MARKERS) if (dirName.startsWith(marker)) {
126
+ const rest = dirName.slice(marker.length);
127
+ if (rest.length > 0 && !rest.endsWith(")")) return {
128
+ marker,
129
+ segmentName: rest
130
+ };
131
+ }
132
+ return null;
133
+ }
134
+ //#endregion
135
+ export { INTERCEPTION_MARKERS as i, classifyUrlSegment as n, DEFAULT_PAGE_EXTENSIONS as r, classifySegment as t };
136
+
137
+ //# sourceMappingURL=segment-classify-CDDRVKs7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segment-classify-CDDRVKs7.js","names":[],"sources":["../../src/routing/types.ts","../../src/routing/segment-classify.ts"],"sourcesContent":["/**\n * Route tree types for timber.js file-system routing.\n *\n * The route tree is built by scanning the app/ directory and recognizing\n * file conventions (page.*, layout.*, middleware.ts, access.ts, route.ts, etc.).\n *\n * **Single shape, two specializations** (TIM-848):\n *\n * `SegmentNode<TFile>` is the one canonical in-memory shape for the\n * timber route tree. The same interface is used at build time (with\n * `TFile = RouteFile`) and at request time (with `TFile = ManifestFile`,\n * see `server/route-matcher.ts`). Walkers parameterized over `TFile`\n * work on either, eliminating the previous duplication between\n * `SegmentNode` (Map-based) and `ManifestSegmentNode` (object-based).\n *\n * Keyed groups (`slots`, `statusFiles`, `jsonStatusFiles`,\n * `legacyStatusFiles`, `metadataRoutes`) are plain `Record<string, …>`\n * objects rather than `Map`s so that the build-time tree can be\n * serialized into the virtual route manifest with no shape transform.\n *\n * See design/07-routing.md §\"Route Tree Shape\" and design/18-build-system.md\n * §\"Route Manifest Shape\".\n */\n\n/** Segment type classification */\nexport type SegmentType =\n | 'static' // e.g. \"dashboard\"\n | 'dynamic' // e.g. \"[id]\"\n | 'catch-all' // e.g. \"[...slug]\"\n | 'optional-catch-all' // e.g. \"[[...slug]]\"\n | 'group' // e.g. \"(marketing)\"\n | 'slot' // e.g. \"@sidebar\"\n | 'intercepting' // e.g. \"(.)photo\", \"(..)photo\", \"(...)photo\"\n | 'private'; // e.g. \"_components\", \"_lib\" — excluded from routing\n\n/**\n * Intercepting route marker — indicates how many levels up to resolve the\n * intercepted route from the intercepting route's location.\n *\n * See design/07-routing.md §\"Intercepting Routes\"\n */\nexport type InterceptionMarker = '(.)' | '(..)' | '(...)' | '(..)(..)';\n\n/** All recognized interception markers, ordered longest-first for parsing. */\nexport const INTERCEPTION_MARKERS: InterceptionMarker[] = ['(..)(..)', '(.)', '(..)', '(...)'];\n\n/**\n * A single file discovered in a route segment at build time.\n *\n * The runtime equivalent (`ManifestFile`, defined in\n * `server/route-matcher.ts`) replaces `extension` with a lazy `load`\n * function. Walkers that only need `filePath` are parameterized over\n * `TFile` and accept either.\n */\nexport interface RouteFile {\n /** Absolute path to the file */\n filePath: string;\n /** File extension without leading dot (e.g. \"tsx\", \"ts\", \"mdx\") */\n extension: string;\n}\n\n/**\n * A node in the segment tree.\n *\n * Generic over `TFile` so the same interface describes both the\n * build-time tree (`SegmentNode<RouteFile>`, the default) and the\n * runtime manifest tree (`SegmentNode<ManifestFile>`, aliased as\n * `ManifestSegmentNode`). All keyed groups use `Record` (not `Map`)\n * so the build-time tree serializes to the virtual route manifest\n * with no shape transform.\n */\nexport interface SegmentNode<TFile = RouteFile> {\n /** The raw directory name (e.g. \"dashboard\", \"[id]\", \"(auth)\", \"@sidebar\") */\n segmentName: string;\n /** Classified segment type */\n segmentType: SegmentType;\n /** The dynamic param name, if dynamic (e.g. \"id\" for \"[id]\", \"slug\" for \"[...slug]\") */\n paramName?: string;\n /** The URL path prefix at this segment level (e.g. \"/dashboard\") */\n urlPath: string;\n /** For intercepting segments: the marker used, e.g. \"(.)\". */\n interceptionMarker?: InterceptionMarker;\n /**\n * For intercepting segments: the segment name after stripping the marker.\n * E.g., for \"(.)photo\" this is \"photo\".\n */\n interceptedSegmentName?: string;\n\n // --- File conventions ---\n page?: TFile;\n layout?: TFile;\n middleware?: TFile;\n access?: TFile;\n route?: TFile;\n /**\n * params.ts — isomorphic convention file exporting segmentParams and/or searchParams.\n * Discovered by the scanner like middleware.ts and access.ts.\n * See design/07-routing.md §\"params.ts Convention File\"\n */\n params?: TFile;\n error?: TFile;\n default?: TFile;\n /** Status-code files: 4xx.tsx, 5xx.tsx, {status}.tsx (component format) */\n statusFiles?: Record<string, TFile>;\n /** JSON status-code files: 4xx.json, 5xx.json, {status}.json */\n jsonStatusFiles?: Record<string, TFile>;\n /** denied.tsx — slot-only denial rendering */\n denied?: TFile;\n /** Legacy compat: not-found.tsx (maps to 404), forbidden.tsx (403), unauthorized.tsx (401) */\n legacyStatusFiles?: Record<string, TFile>;\n\n /** Metadata route files (sitemap.ts, robots.ts, icon.tsx, etc.) keyed by base name */\n metadataRoutes?: Record<string, TFile>;\n\n // --- Children ---\n children: SegmentNode<TFile>[];\n /** Parallel route slots (keyed by slot name without @) */\n slots: Record<string, SegmentNode<TFile>>;\n}\n\n/**\n * The full route tree output from the scanner (or the root of the\n * runtime route manifest, when `TFile = ManifestFile`).\n *\n * Generic so the same wrapper carries app-root metadata for both\n * shapes. The runtime manifest extends this with `viteRoot` (see\n * `ManifestRoot` in `server/route-matcher.ts`).\n */\nexport interface RouteTree<TFile = RouteFile> {\n /** The root segment node (representing app/) */\n root: SegmentNode<TFile>;\n /** All discovered proxy.ts files (should be at most one, in app/) */\n proxy?: TFile;\n /**\n * Global error page: app/global-error.{tsx,ts,jsx,js}\n *\n * Rendered as a standalone full-page replacement (no layout wrapping)\n * when no segment-level error file is found. SSR-only render path.\n * Must provide its own <html> and <body>.\n *\n * See design/10-error-handling.md §\"Tier 2 — Global Error Page\"\n */\n globalError?: TFile;\n}\n\n/** Configuration passed to the scanner */\nexport interface ScannerConfig {\n /** Recognized page/layout extensions (without dots). Default: ['tsx', 'ts', 'jsx', 'js'] */\n pageExtensions?: string[];\n}\n\n/** Default page extensions */\nexport const DEFAULT_PAGE_EXTENSIONS = ['tsx', 'ts', 'jsx', 'js'];\n","/**\n * Shared segment classifier — both URL tokens and filesystem directory names.\n *\n * `classifyUrlSegment(token)` is a pure single-pass character parser that\n * classifies a route segment token (e.g. \"dashboard\", \"[id]\", \"[...slug]\",\n * \"[[...path]]\") into a typed discriminated union. NO regex, NO Node.js-only\n * APIs — safe to import from browser code (used by `Link` interpolation).\n *\n * `classifySegment(dirName)` is the build-time directory-name classifier\n * used by the scanner. It recognizes timber-only conventions (private\n * `_*`, parallel `@*`, route groups `(name)`, intercepting routes\n * `(.)`/`(..)`/`(...)`/`(..)(..)`) and delegates bracket syntax to\n * `classifyUrlSegment`. It is the **single source of truth** for what\n * counts as a routing segment — there is no separate copy in the\n * scanner. (TIM-848.)\n *\n * Malformed input falls through to `{ kind: 'static' }` — the safe default.\n *\n * If you change the bracket syntax, update ONLY this file. Every\n * consumer imports from here.\n *\n * See design/07-routing.md §\"Route Segments\"\n */\n\nimport type { InterceptionMarker, SegmentType } from './types.js';\nimport { INTERCEPTION_MARKERS } from './types.js';\n\nexport type UrlSegment =\n | { kind: 'static'; value: string }\n | { kind: 'dynamic'; name: string }\n | { kind: 'catch-all'; name: string }\n | { kind: 'optional-catch-all'; name: string };\n\n/**\n * Classify a URL path segment token.\n *\n * Walks the string left-to-right in one pass:\n * 1. If it doesn't start with '[', it's static.\n * 2. Count opening brackets (1 or 2) to detect optional.\n * 3. Check for '...' to detect catch-all.\n * 4. Read the param name up to the closing bracket.\n * 5. Validate the expected closing sequence (']' or ']]').\n * 6. Reject if there are leftover characters after the close.\n *\n * Any structural violation → static (safe default).\n */\nexport function classifyUrlSegment(token: string): UrlSegment {\n const len = token.length;\n\n // Must start with '[' to be dynamic\n if (len === 0 || token[0] !== '[') {\n return { kind: 'static', value: token };\n }\n\n let i = 1;\n\n // Check for optional: '[[...'\n const optional = token[i] === '[';\n if (optional) i++;\n\n // Check for catch-all: '...'\n const catchAll = i + 2 < len && token[i] === '.' && token[i + 1] === '.' && token[i + 2] === '.';\n if (catchAll) i += 3;\n\n // Read param name — everything up to ']'\n const nameStart = i;\n while (i < len && token[i] !== ']') i++;\n\n // Must have found a ']' and name must be non-empty\n if (i >= len || i === nameStart) {\n return { kind: 'static', value: token };\n }\n\n const name = token.slice(nameStart, i);\n i++; // skip first ']'\n\n // Optional requires a second ']'\n if (optional) {\n if (i >= len || token[i] !== ']') {\n return { kind: 'static', value: token };\n }\n i++;\n }\n\n // Must be at end of string — no trailing characters\n if (i !== len) {\n return { kind: 'static', value: token };\n }\n\n if (optional && catchAll) return { kind: 'optional-catch-all', name };\n if (catchAll) return { kind: 'catch-all', name };\n if (optional) {\n // '[[name]]' without '...' is malformed — not a valid segment syntax\n return { kind: 'static', value: token };\n }\n return { kind: 'dynamic', name };\n}\n\n// ─── Directory-name classifier (build-time scanner) ─────────────────────────\n\n/** Result of classifying a filesystem directory name. */\nexport interface SegmentClassification {\n type: SegmentType;\n paramName?: string;\n interceptionMarker?: InterceptionMarker;\n interceptedSegmentName?: string;\n}\n\n/**\n * Classify a directory name into its segment type.\n *\n * Recognizes all timber file-system conventions in priority order:\n * 1. Private folders: `_name` (excluded from routing)\n * 2. Parallel route slots: `@name`\n * 3. Intercepting routes: `(.)name`, `(..)name`, `(...)name`, `(..)(..)name`\n * 4. Route groups: `(name)`\n * 5. Bracket syntax: `[id]`, `[...slug]`, `[[...path]]` (delegated to\n * `classifyUrlSegment`)\n * 6. Static: anything else\n *\n * If you change the bracket syntax, update only `classifyUrlSegment`.\n * If you change the directory-prefix conventions, update this function.\n */\nexport function classifySegment(dirName: string): SegmentClassification {\n // Private folder: _name (excluded from routing)\n if (dirName.startsWith('_')) {\n return { type: 'private' };\n }\n\n // Parallel route slot: @name\n if (dirName.startsWith('@')) {\n return { type: 'slot' };\n }\n\n // Intercepting routes: (.)name, (..)name, (...)name, (..)(..)name\n // Check before route groups since intercepting markers also start with (\n const interception = parseInterceptionMarker(dirName);\n if (interception) {\n return {\n type: 'intercepting',\n interceptionMarker: interception.marker,\n interceptedSegmentName: interception.segmentName,\n };\n }\n\n // Route group: (name)\n if (dirName.startsWith('(') && dirName.endsWith(')')) {\n return { type: 'group' };\n }\n\n // Bracket-syntax segments: [param], [...param], [[...param]]\n const urlSeg = classifyUrlSegment(dirName);\n if (urlSeg.kind !== 'static') {\n return { type: urlSeg.kind, paramName: urlSeg.name };\n }\n\n return { type: 'static' };\n}\n\n/**\n * Parse an interception marker from a directory name.\n *\n * Returns the marker and the remaining segment name, or null if not an\n * intercepting route. Markers are checked longest-first to avoid `(..)`\n * matching before `(..)(..)`.\n *\n * Examples:\n * \"(.)photo\" → { marker: \"(.)\", segmentName: \"photo\" }\n * \"(..)feed\" → { marker: \"(..)\", segmentName: \"feed\" }\n * \"(...)photos\" → { marker: \"(...)\", segmentName: \"photos\" }\n * \"(..)(..)admin\" → { marker: \"(..)(..)\", segmentName: \"admin\" }\n * \"(marketing)\" → null (route group, not interception)\n */\nfunction parseInterceptionMarker(\n dirName: string\n): { marker: InterceptionMarker; segmentName: string } | null {\n for (const marker of INTERCEPTION_MARKERS) {\n if (dirName.startsWith(marker)) {\n const rest = dirName.slice(marker.length);\n // Must have a segment name after the marker, and the rest must not\n // be empty or end with ) (which would be a route group like \"(auth)\")\n if (rest.length > 0 && !rest.endsWith(')')) {\n return { marker, segmentName: rest };\n }\n }\n }\n return null;\n}\n"],"mappings":";;AA4CA,IAAa,uBAA6C;CAAC;CAAY;CAAO;CAAQ;AAAO;;AA4G7F,IAAa,0BAA0B;CAAC;CAAO;CAAM;CAAO;AAAI;;;;;;;;;;;;;;;;AC1GhE,SAAgB,mBAAmB,OAA2B;CAC5D,MAAM,MAAM,MAAM;CAGlB,IAAI,QAAQ,KAAK,MAAM,OAAO,KAC5B,OAAO;EAAE,MAAM;EAAU,OAAO;CAAM;CAGxC,IAAI,IAAI;CAGR,MAAM,WAAW,MAAM,OAAO;CAC9B,IAAI,UAAU;CAGd,MAAM,WAAW,IAAI,IAAI,OAAO,MAAM,OAAO,OAAO,MAAM,IAAI,OAAO,OAAO,MAAM,IAAI,OAAO;CAC7F,IAAI,UAAU,KAAK;CAGnB,MAAM,YAAY;CAClB,OAAO,IAAI,OAAO,MAAM,OAAO,KAAK;CAGpC,IAAI,KAAK,OAAO,MAAM,WACpB,OAAO;EAAE,MAAM;EAAU,OAAO;CAAM;CAGxC,MAAM,OAAO,MAAM,MAAM,WAAW,CAAC;CACrC;CAGA,IAAI,UAAU;EACZ,IAAI,KAAK,OAAO,MAAM,OAAO,KAC3B,OAAO;GAAE,MAAM;GAAU,OAAO;EAAM;EAExC;CACF;CAGA,IAAI,MAAM,KACR,OAAO;EAAE,MAAM;EAAU,OAAO;CAAM;CAGxC,IAAI,YAAY,UAAU,OAAO;EAAE,MAAM;EAAsB;CAAK;CACpE,IAAI,UAAU,OAAO;EAAE,MAAM;EAAa;CAAK;CAC/C,IAAI,UAEF,OAAO;EAAE,MAAM;EAAU,OAAO;CAAM;CAExC,OAAO;EAAE,MAAM;EAAW;CAAK;AACjC;;;;;;;;;;;;;;;;AA2BA,SAAgB,gBAAgB,SAAwC;CAEtE,IAAI,QAAQ,WAAW,GAAG,GACxB,OAAO,EAAE,MAAM,UAAU;CAI3B,IAAI,QAAQ,WAAW,GAAG,GACxB,OAAO,EAAE,MAAM,OAAO;CAKxB,MAAM,eAAe,wBAAwB,OAAO;CACpD,IAAI,cACF,OAAO;EACL,MAAM;EACN,oBAAoB,aAAa;EACjC,wBAAwB,aAAa;CACvC;CAIF,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GACjD,OAAO,EAAE,MAAM,QAAQ;CAIzB,MAAM,SAAS,mBAAmB,OAAO;CACzC,IAAI,OAAO,SAAS,UAClB,OAAO;EAAE,MAAM,OAAO;EAAM,WAAW,OAAO;CAAK;CAGrD,OAAO,EAAE,MAAM,SAAS;AAC1B;;;;;;;;;;;;;;;AAgBA,SAAS,wBACP,SAC4D;CAC5D,KAAK,MAAM,UAAU,sBACnB,IAAI,QAAQ,WAAW,MAAM,GAAG;EAC9B,MAAM,OAAO,QAAQ,MAAM,OAAO,MAAM;EAGxC,IAAI,KAAK,SAAS,KAAK,CAAC,KAAK,SAAS,GAAG,GACvC,OAAO;GAAE;GAAQ,aAAa;EAAK;CAEvC;CAEF,OAAO;AACT"}