@timber-js/app 0.2.0-alpha.6 → 0.2.0-alpha.61

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 (406) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-Ba7URUIn.js} +1 -1
  3. package/dist/_chunks/als-registry-Ba7URUIn.js.map +1 -0
  4. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  5. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  6. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  7. package/dist/_chunks/define-CT98cU9c.js +121 -0
  8. package/dist/_chunks/define-CT98cU9c.js.map +1 -0
  9. package/dist/_chunks/define-TK8C1M3x.js +279 -0
  10. package/dist/_chunks/define-TK8C1M3x.js.map +1 -0
  11. package/dist/_chunks/define-cookie-BWr_52kY.js +93 -0
  12. package/dist/_chunks/define-cookie-BWr_52kY.js.map +1 -0
  13. package/dist/_chunks/error-boundary-DpZJBCqh.js +211 -0
  14. package/dist/_chunks/error-boundary-DpZJBCqh.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → format-cX7wzEp2.js} +2 -2
  16. package/dist/_chunks/{format-DviM89f0.js.map → format-cX7wzEp2.js.map} +1 -1
  17. package/dist/_chunks/{interception-BOoWmLUA.js → interception-Cey5DCGr.js} +129 -77
  18. package/dist/_chunks/interception-Cey5DCGr.js.map +1 -0
  19. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BU684ls2.js} +1 -1
  20. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-BU684ls2.js.map} +1 -1
  21. package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-rju2rbga.js} +97 -69
  22. package/dist/_chunks/request-context-rju2rbga.js.map +1 -0
  23. package/dist/_chunks/segment-context-CyaM1mrD.js +72 -0
  24. package/dist/_chunks/segment-context-CyaM1mrD.js.map +1 -0
  25. package/dist/_chunks/stale-reload-BSSym1MJ.js +64 -0
  26. package/dist/_chunks/stale-reload-BSSym1MJ.js.map +1 -0
  27. package/dist/_chunks/{tracing-Cwn7697K.js → tracing-VYETCQsg.js} +17 -3
  28. package/dist/_chunks/{tracing-Cwn7697K.js.map → tracing-VYETCQsg.js.map} +1 -1
  29. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-wEXY2JQB.js} +1 -1
  30. package/dist/_chunks/use-query-states-wEXY2JQB.js.map +1 -0
  31. package/dist/_chunks/wrappers-BaG1bnM3.js +63 -0
  32. package/dist/_chunks/wrappers-BaG1bnM3.js.map +1 -0
  33. package/dist/adapters/compress-module.d.ts.map +1 -1
  34. package/dist/adapters/nitro.d.ts +17 -1
  35. package/dist/adapters/nitro.d.ts.map +1 -1
  36. package/dist/adapters/nitro.js +56 -13
  37. package/dist/adapters/nitro.js.map +1 -1
  38. package/dist/cache/fast-hash.d.ts +22 -0
  39. package/dist/cache/fast-hash.d.ts.map +1 -0
  40. package/dist/cache/index.d.ts +5 -2
  41. package/dist/cache/index.d.ts.map +1 -1
  42. package/dist/cache/index.js +90 -20
  43. package/dist/cache/index.js.map +1 -1
  44. package/dist/cache/register-cached-function.d.ts.map +1 -1
  45. package/dist/cache/singleflight.d.ts +18 -1
  46. package/dist/cache/singleflight.d.ts.map +1 -1
  47. package/dist/cache/timber-cache.d.ts +1 -1
  48. package/dist/cache/timber-cache.d.ts.map +1 -1
  49. package/dist/client/error-boundary.d.ts +10 -1
  50. package/dist/client/error-boundary.d.ts.map +1 -1
  51. package/dist/client/error-boundary.js +1 -125
  52. package/dist/client/error-reconstituter.d.ts +54 -0
  53. package/dist/client/error-reconstituter.d.ts.map +1 -0
  54. package/dist/client/form.d.ts +2 -2
  55. package/dist/client/form.d.ts.map +1 -1
  56. package/dist/client/index.d.ts +3 -2
  57. package/dist/client/index.d.ts.map +1 -1
  58. package/dist/client/index.js +433 -252
  59. package/dist/client/index.js.map +1 -1
  60. package/dist/client/link-pending-store.d.ts +78 -0
  61. package/dist/client/link-pending-store.d.ts.map +1 -0
  62. package/dist/client/link.d.ts +23 -9
  63. package/dist/client/link.d.ts.map +1 -1
  64. package/dist/client/navigation-context.d.ts +2 -2
  65. package/dist/client/navigation-context.d.ts.map +1 -1
  66. package/dist/client/router.d.ts +25 -3
  67. package/dist/client/router.d.ts.map +1 -1
  68. package/dist/client/rsc-fetch.d.ts +36 -2
  69. package/dist/client/rsc-fetch.d.ts.map +1 -1
  70. package/dist/client/segment-cache.d.ts +1 -1
  71. package/dist/client/segment-cache.d.ts.map +1 -1
  72. package/dist/client/segment-context.d.ts +1 -1
  73. package/dist/client/segment-context.d.ts.map +1 -1
  74. package/dist/client/segment-merger.d.ts.map +1 -1
  75. package/dist/client/segment-outlet.d.ts +63 -0
  76. package/dist/client/segment-outlet.d.ts.map +1 -0
  77. package/dist/client/stale-reload.d.ts +15 -0
  78. package/dist/client/stale-reload.d.ts.map +1 -1
  79. package/dist/client/top-loader.d.ts +1 -1
  80. package/dist/client/top-loader.d.ts.map +1 -1
  81. package/dist/client/transition-root.d.ts +1 -1
  82. package/dist/client/transition-root.d.ts.map +1 -1
  83. package/dist/client/use-params.d.ts +3 -3
  84. package/dist/client/use-params.d.ts.map +1 -1
  85. package/dist/client/use-query-states.d.ts +1 -1
  86. package/dist/client/use-query-states.d.ts.map +1 -1
  87. package/dist/codec.d.ts +21 -0
  88. package/dist/codec.d.ts.map +1 -0
  89. package/dist/cookies/define-cookie.d.ts +34 -13
  90. package/dist/cookies/define-cookie.d.ts.map +1 -1
  91. package/dist/cookies/index.js +1 -83
  92. package/dist/fonts/css.d.ts +1 -0
  93. package/dist/fonts/css.d.ts.map +1 -1
  94. package/dist/index.d.ts +127 -35
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +665 -242
  97. package/dist/index.js.map +1 -1
  98. package/dist/params/define.d.ts +100 -0
  99. package/dist/params/define.d.ts.map +1 -0
  100. package/dist/params/index.d.ts +8 -0
  101. package/dist/params/index.d.ts.map +1 -0
  102. package/dist/params/index.js +4 -0
  103. package/dist/plugins/adapter-build.d.ts +1 -1
  104. package/dist/plugins/adapter-build.d.ts.map +1 -1
  105. package/dist/plugins/build-manifest.d.ts +2 -2
  106. package/dist/plugins/build-manifest.d.ts.map +1 -1
  107. package/dist/plugins/build-report.d.ts +3 -3
  108. package/dist/plugins/build-report.d.ts.map +1 -1
  109. package/dist/plugins/client-chunks.d.ts +32 -0
  110. package/dist/plugins/client-chunks.d.ts.map +1 -0
  111. package/dist/plugins/content.d.ts +1 -1
  112. package/dist/plugins/content.d.ts.map +1 -1
  113. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  114. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  115. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  116. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  117. package/dist/plugins/dev-logs.d.ts +1 -1
  118. package/dist/plugins/dev-logs.d.ts.map +1 -1
  119. package/dist/plugins/dev-server.d.ts +1 -1
  120. package/dist/plugins/dev-server.d.ts.map +1 -1
  121. package/dist/plugins/entries.d.ts +1 -1
  122. package/dist/plugins/entries.d.ts.map +1 -1
  123. package/dist/plugins/fonts.d.ts +9 -2
  124. package/dist/plugins/fonts.d.ts.map +1 -1
  125. package/dist/plugins/mdx.d.ts +1 -1
  126. package/dist/plugins/mdx.d.ts.map +1 -1
  127. package/dist/plugins/routing.d.ts +1 -1
  128. package/dist/plugins/routing.d.ts.map +1 -1
  129. package/dist/plugins/server-bundle.d.ts.map +1 -1
  130. package/dist/plugins/shims.d.ts +6 -5
  131. package/dist/plugins/shims.d.ts.map +1 -1
  132. package/dist/plugins/static-build.d.ts +1 -1
  133. package/dist/plugins/static-build.d.ts.map +1 -1
  134. package/dist/routing/codegen.d.ts +2 -2
  135. package/dist/routing/codegen.d.ts.map +1 -1
  136. package/dist/routing/index.js +1 -1
  137. package/dist/routing/scanner.d.ts.map +1 -1
  138. package/dist/routing/status-file-lint.d.ts +2 -1
  139. package/dist/routing/status-file-lint.d.ts.map +1 -1
  140. package/dist/routing/types.d.ts +16 -4
  141. package/dist/routing/types.d.ts.map +1 -1
  142. package/dist/rsc-runtime/rsc.d.ts +1 -1
  143. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  144. package/dist/rsc-runtime/ssr.d.ts +12 -0
  145. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  146. package/dist/search-params/codecs.d.ts +1 -1
  147. package/dist/search-params/define.d.ts +159 -0
  148. package/dist/search-params/define.d.ts.map +1 -0
  149. package/dist/search-params/index.d.ts +4 -5
  150. package/dist/search-params/index.d.ts.map +1 -1
  151. package/dist/search-params/index.js +4 -474
  152. package/dist/search-params/registry.d.ts +1 -1
  153. package/dist/search-params/wrappers.d.ts +53 -0
  154. package/dist/search-params/wrappers.d.ts.map +1 -0
  155. package/dist/server/access-gate.d.ts +4 -0
  156. package/dist/server/access-gate.d.ts.map +1 -1
  157. package/dist/server/action-client.d.ts.map +1 -1
  158. package/dist/server/action-encryption.d.ts +76 -0
  159. package/dist/server/action-encryption.d.ts.map +1 -0
  160. package/dist/server/action-handler.d.ts.map +1 -1
  161. package/dist/server/actions.d.ts +1 -1
  162. package/dist/server/actions.d.ts.map +1 -1
  163. package/dist/server/als-registry.d.ts +25 -4
  164. package/dist/server/als-registry.d.ts.map +1 -1
  165. package/dist/server/build-manifest.d.ts +2 -2
  166. package/dist/server/build-manifest.d.ts.map +1 -1
  167. package/dist/server/debug.d.ts +1 -1
  168. package/dist/server/default-logger.d.ts +22 -0
  169. package/dist/server/default-logger.d.ts.map +1 -0
  170. package/dist/server/deny-renderer.d.ts.map +1 -1
  171. package/dist/server/early-hints.d.ts +13 -5
  172. package/dist/server/early-hints.d.ts.map +1 -1
  173. package/dist/server/error-boundary-wrapper.d.ts +4 -0
  174. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  175. package/dist/server/fallback-error.d.ts +4 -3
  176. package/dist/server/fallback-error.d.ts.map +1 -1
  177. package/dist/server/flight-injection-state.d.ts +66 -0
  178. package/dist/server/flight-injection-state.d.ts.map +1 -0
  179. package/dist/server/flight-scripts.d.ts +42 -0
  180. package/dist/server/flight-scripts.d.ts.map +1 -0
  181. package/dist/server/flush.d.ts.map +1 -1
  182. package/dist/server/form-data.d.ts +29 -0
  183. package/dist/server/form-data.d.ts.map +1 -1
  184. package/dist/server/html-injectors.d.ts +51 -11
  185. package/dist/server/html-injectors.d.ts.map +1 -1
  186. package/dist/server/index.d.ts +4 -2
  187. package/dist/server/index.d.ts.map +1 -1
  188. package/dist/server/index.js +1977 -1648
  189. package/dist/server/index.js.map +1 -1
  190. package/dist/server/logger.d.ts +25 -7
  191. package/dist/server/logger.d.ts.map +1 -1
  192. package/dist/server/node-stream-transforms.d.ts +113 -0
  193. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  194. package/dist/server/pipeline-interception.d.ts +1 -1
  195. package/dist/server/pipeline-interception.d.ts.map +1 -1
  196. package/dist/server/pipeline.d.ts +20 -6
  197. package/dist/server/pipeline.d.ts.map +1 -1
  198. package/dist/server/primitives.d.ts +30 -3
  199. package/dist/server/primitives.d.ts.map +1 -1
  200. package/dist/server/render-timeout.d.ts +51 -0
  201. package/dist/server/render-timeout.d.ts.map +1 -0
  202. package/dist/server/request-context.d.ts +65 -38
  203. package/dist/server/request-context.d.ts.map +1 -1
  204. package/dist/server/route-element-builder.d.ts +7 -0
  205. package/dist/server/route-element-builder.d.ts.map +1 -1
  206. package/dist/server/route-handler.d.ts.map +1 -1
  207. package/dist/server/route-matcher.d.ts +9 -2
  208. package/dist/server/route-matcher.d.ts.map +1 -1
  209. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  210. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  211. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  212. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  213. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  214. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  215. package/dist/server/rsc-entry/index.d.ts +8 -3
  216. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  217. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  218. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  219. package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
  220. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  221. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  222. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  223. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  224. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  225. package/dist/server/slot-resolver.d.ts +1 -1
  226. package/dist/server/slot-resolver.d.ts.map +1 -1
  227. package/dist/server/ssr-entry.d.ts +22 -0
  228. package/dist/server/ssr-entry.d.ts.map +1 -1
  229. package/dist/server/ssr-render.d.ts +39 -21
  230. package/dist/server/ssr-render.d.ts.map +1 -1
  231. package/dist/server/ssr-wrappers.d.ts +50 -0
  232. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  233. package/dist/server/status-code-resolver.d.ts +1 -1
  234. package/dist/server/status-code-resolver.d.ts.map +1 -1
  235. package/dist/server/stream-utils.d.ts +36 -0
  236. package/dist/server/stream-utils.d.ts.map +1 -0
  237. package/dist/server/tracing.d.ts +10 -0
  238. package/dist/server/tracing.d.ts.map +1 -1
  239. package/dist/server/tree-builder.d.ts +20 -13
  240. package/dist/server/tree-builder.d.ts.map +1 -1
  241. package/dist/server/types.d.ts +1 -3
  242. package/dist/server/types.d.ts.map +1 -1
  243. package/dist/server/version-skew.d.ts +61 -0
  244. package/dist/server/version-skew.d.ts.map +1 -0
  245. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  246. package/dist/shared/merge-search-params.d.ts +22 -0
  247. package/dist/shared/merge-search-params.d.ts.map +1 -0
  248. package/dist/shims/font-google.d.ts +1 -1
  249. package/dist/shims/font-google.d.ts.map +1 -1
  250. package/dist/shims/navigation-client.d.ts +1 -1
  251. package/dist/shims/navigation-client.d.ts.map +1 -1
  252. package/dist/shims/navigation.d.ts +1 -1
  253. package/dist/shims/navigation.d.ts.map +1 -1
  254. package/dist/utils/state-machine.d.ts +80 -0
  255. package/dist/utils/state-machine.d.ts.map +1 -0
  256. package/package.json +17 -17
  257. package/src/adapters/compress-module.ts +24 -4
  258. package/src/adapters/nitro.ts +58 -9
  259. package/src/cache/fast-hash.ts +34 -0
  260. package/src/cache/index.ts +5 -2
  261. package/src/cache/register-cached-function.ts +7 -3
  262. package/src/cache/singleflight.ts +62 -4
  263. package/src/cache/timber-cache.ts +40 -29
  264. package/src/cli.ts +0 -0
  265. package/src/client/browser-entry.ts +151 -99
  266. package/src/client/error-boundary.tsx +18 -1
  267. package/src/client/error-reconstituter.tsx +65 -0
  268. package/src/client/form.tsx +2 -2
  269. package/src/client/index.ts +10 -1
  270. package/src/client/link-pending-store.ts +136 -0
  271. package/src/client/link.tsx +137 -22
  272. package/src/client/navigation-context.ts +6 -5
  273. package/src/client/router.ts +117 -60
  274. package/src/client/rsc-fetch.ts +90 -2
  275. package/src/client/segment-cache.ts +1 -1
  276. package/src/client/segment-context.ts +6 -1
  277. package/src/client/segment-merger.ts +2 -8
  278. package/src/client/segment-outlet.tsx +86 -0
  279. package/src/client/stale-reload.ts +73 -6
  280. package/src/client/top-loader.tsx +10 -9
  281. package/src/client/transition-root.tsx +20 -2
  282. package/src/client/use-params.ts +4 -4
  283. package/src/client/use-query-states.ts +2 -2
  284. package/src/codec.ts +21 -0
  285. package/src/cookies/define-cookie.ts +71 -20
  286. package/src/fonts/css.ts +2 -1
  287. package/src/index.ts +297 -85
  288. package/src/params/define.ts +327 -0
  289. package/src/params/index.ts +28 -0
  290. package/src/plugins/adapter-build.ts +8 -2
  291. package/src/plugins/build-manifest.ts +13 -2
  292. package/src/plugins/build-report.ts +3 -3
  293. package/src/plugins/cache-transform.ts +1 -1
  294. package/src/plugins/client-chunks.ts +65 -0
  295. package/src/plugins/content.ts +1 -1
  296. package/src/plugins/dev-browser-logs.ts +284 -0
  297. package/src/plugins/dev-error-overlay.ts +70 -1
  298. package/src/plugins/dev-logs.ts +1 -1
  299. package/src/plugins/dev-server.ts +41 -7
  300. package/src/plugins/entries.ts +6 -8
  301. package/src/plugins/fonts.ts +102 -55
  302. package/src/plugins/mdx.ts +1 -1
  303. package/src/plugins/routing.ts +57 -17
  304. package/src/plugins/server-action-exports.ts +1 -1
  305. package/src/plugins/server-bundle.ts +32 -1
  306. package/src/plugins/shims.ts +69 -31
  307. package/src/plugins/static-build.ts +10 -6
  308. package/src/routing/codegen.ts +109 -88
  309. package/src/routing/scanner.ts +86 -7
  310. package/src/routing/status-file-lint.ts +3 -2
  311. package/src/routing/types.ts +17 -4
  312. package/src/rsc-runtime/rsc.ts +2 -0
  313. package/src/rsc-runtime/ssr.ts +50 -0
  314. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  315. package/src/search-params/codecs.ts +1 -1
  316. package/src/search-params/define.ts +518 -0
  317. package/src/search-params/index.ts +12 -18
  318. package/src/search-params/registry.ts +1 -1
  319. package/src/search-params/wrappers.ts +85 -0
  320. package/src/server/access-gate.tsx +40 -9
  321. package/src/server/action-client.ts +8 -2
  322. package/src/server/action-encryption.ts +144 -0
  323. package/src/server/action-handler.ts +20 -3
  324. package/src/server/actions.ts +1 -1
  325. package/src/server/als-registry.ts +25 -4
  326. package/src/server/build-manifest.ts +10 -4
  327. package/src/server/compress.ts +25 -7
  328. package/src/server/debug.ts +1 -1
  329. package/src/server/default-logger.ts +99 -0
  330. package/src/server/deny-renderer.ts +5 -3
  331. package/src/server/early-hints.ts +36 -15
  332. package/src/server/error-boundary-wrapper.ts +58 -15
  333. package/src/server/fallback-error.ts +29 -14
  334. package/src/server/flight-injection-state.ts +113 -0
  335. package/src/server/flight-scripts.ts +62 -0
  336. package/src/server/flush.ts +2 -1
  337. package/src/server/form-data.ts +76 -0
  338. package/src/server/html-injectors.ts +277 -117
  339. package/src/server/index.ts +9 -4
  340. package/src/server/logger.ts +44 -36
  341. package/src/server/node-stream-transforms.ts +509 -0
  342. package/src/server/pipeline-interception.ts +1 -1
  343. package/src/server/pipeline.ts +148 -41
  344. package/src/server/primitives.ts +47 -5
  345. package/src/server/render-timeout.ts +108 -0
  346. package/src/server/request-context.ts +125 -119
  347. package/src/server/route-element-builder.ts +107 -115
  348. package/src/server/route-handler.ts +2 -1
  349. package/src/server/route-matcher.ts +9 -2
  350. package/src/server/rsc-entry/api-handler.ts +8 -8
  351. package/src/server/rsc-entry/error-renderer.ts +286 -81
  352. package/src/server/rsc-entry/helpers.ts +134 -5
  353. package/src/server/rsc-entry/index.ts +177 -76
  354. package/src/server/rsc-entry/rsc-payload.ts +91 -18
  355. package/src/server/rsc-entry/rsc-stream.ts +74 -18
  356. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  357. package/src/server/rsc-entry/ssr-renderer.ts +152 -34
  358. package/src/server/slot-resolver.ts +231 -220
  359. package/src/server/ssr-entry.ts +211 -32
  360. package/src/server/ssr-render.ts +289 -67
  361. package/src/server/ssr-wrappers.tsx +139 -0
  362. package/src/server/status-code-resolver.ts +1 -1
  363. package/src/server/stream-utils.ts +213 -0
  364. package/src/server/tracing.ts +23 -0
  365. package/src/server/tree-builder.ts +92 -58
  366. package/src/server/types.ts +1 -3
  367. package/src/server/version-skew.ts +104 -0
  368. package/src/server/waituntil-bridge.ts +4 -1
  369. package/src/shared/merge-search-params.ts +55 -0
  370. package/src/shims/font-google.ts +1 -1
  371. package/src/shims/navigation-client.ts +1 -1
  372. package/src/shims/navigation.ts +2 -1
  373. package/src/utils/state-machine.ts +111 -0
  374. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  375. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  376. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  377. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  378. package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
  379. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  380. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  381. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  382. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  383. package/dist/client/error-boundary.js.map +0 -1
  384. package/dist/client/link-status-provider.d.ts +0 -11
  385. package/dist/client/link-status-provider.d.ts.map +0 -1
  386. package/dist/cookies/index.js.map +0 -1
  387. package/dist/plugins/dynamic-transform.d.ts +0 -72
  388. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  389. package/dist/search-params/analyze.d.ts +0 -54
  390. package/dist/search-params/analyze.d.ts.map +0 -1
  391. package/dist/search-params/builtin-codecs.d.ts +0 -105
  392. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  393. package/dist/search-params/create.d.ts +0 -106
  394. package/dist/search-params/create.d.ts.map +0 -1
  395. package/dist/search-params/index.js.map +0 -1
  396. package/dist/server/prerender.d.ts +0 -77
  397. package/dist/server/prerender.d.ts.map +0 -1
  398. package/dist/server/response-cache.d.ts +0 -53
  399. package/dist/server/response-cache.d.ts.map +0 -1
  400. package/src/client/link-status-provider.tsx +0 -30
  401. package/src/plugins/dynamic-transform.ts +0 -161
  402. package/src/search-params/analyze.ts +0 -192
  403. package/src/search-params/builtin-codecs.ts +0 -228
  404. package/src/search-params/create.ts +0 -321
  405. package/src/server/prerender.ts +0 -139
  406. package/src/server/response-cache.ts +0 -277
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-cookie-DX-l1_5E.js","names":[],"sources":["../../src/client/use-cookie.ts"],"sourcesContent":["/**\n * useCookie — reactive client-side cookie hook.\n *\n * Uses useSyncExternalStore for SSR-safe, reactive cookie access.\n * All components reading the same cookie name re-render on change.\n * No cross-tab sync (intentional — see design/29-cookies.md).\n *\n * See design/29-cookies.md §\"useCookie(name) Hook\"\n */\n\nimport { useSyncExternalStore } from 'react';\nimport { getSsrData } from './ssr-data.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\nexport interface ClientCookieOptions {\n /** URL path scope. Default: '/'. */\n path?: string;\n /** Domain scope. Default: omitted (current domain). */\n domain?: string;\n /** Max age in seconds. */\n maxAge?: number;\n /** Expiration date. */\n expires?: Date;\n /** Cross-site policy. Default: 'lax'. */\n sameSite?: 'strict' | 'lax' | 'none';\n /** Only send over HTTPS. Default: true in production. */\n secure?: boolean;\n}\n\nexport type CookieSetter = (value: string, options?: ClientCookieOptions) => void;\n\n// ─── Module-Level Cookie Store ────────────────────────────────────────────\n\ntype Listener = () => void;\n\n/** Per-name subscriber sets. */\nconst listeners = new Map<string, Set<Listener>>();\n\n/** Parse a cookie name from document.cookie. */\nfunction getCookieValue(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined;\n const match = document.cookie.match(\n new RegExp('(?:^|;\\\\s*)' + name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '\\\\s*=\\\\s*([^;]*)')\n );\n return match ? decodeURIComponent(match[1]) : undefined;\n}\n\n/** Serialize options into a cookie string suffix. */\nfunction serializeOptions(options?: ClientCookieOptions): string {\n if (!options) return '; Path=/; SameSite=Lax';\n const parts: string[] = [];\n parts.push(`Path=${options.path ?? '/'}`);\n if (options.domain) parts.push(`Domain=${options.domain}`);\n if (options.maxAge !== undefined) parts.push(`Max-Age=${options.maxAge}`);\n if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);\n const sameSite = options.sameSite ?? 'lax';\n parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);\n if (options.secure) parts.push('Secure');\n return '; ' + parts.join('; ');\n}\n\n/** Notify all subscribers for a given cookie name. */\nfunction notify(name: string): void {\n const subs = listeners.get(name);\n if (subs) {\n for (const fn of subs) fn();\n }\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────────────\n\n/**\n * Reactive hook for reading/writing a client-side cookie.\n *\n * Returns `[value, setCookie, deleteCookie]`:\n * - `value`: current cookie value (string | undefined)\n * - `setCookie`: sets the cookie and triggers re-renders\n * - `deleteCookie`: deletes the cookie and triggers re-renders\n *\n * @param name - Cookie name.\n * @param defaultOptions - Default options for setCookie calls.\n */\nexport function useCookie(\n name: string,\n defaultOptions?: ClientCookieOptions\n): [value: string | undefined, setCookie: CookieSetter, deleteCookie: () => void] {\n const subscribe = (callback: Listener): (() => void) => {\n let subs = listeners.get(name);\n if (!subs) {\n subs = new Set();\n listeners.set(name, subs);\n }\n subs.add(callback);\n return () => {\n subs!.delete(callback);\n if (subs!.size === 0) listeners.delete(name);\n };\n };\n\n const getSnapshot = (): string | undefined => getCookieValue(name);\n const getServerSnapshot = (): string | undefined => getSsrData()?.cookies.get(name);\n\n const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n\n const setCookie: CookieSetter = (newValue: string, options?: ClientCookieOptions) => {\n const merged = { ...defaultOptions, ...options };\n document.cookie = `${name}=${encodeURIComponent(newValue)}${serializeOptions(merged)}`;\n notify(name);\n };\n\n const deleteCookie = (): void => {\n const path = defaultOptions?.path ?? '/';\n const domain = defaultOptions?.domain;\n let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;\n if (domain) cookieStr += `; Domain=${domain}`;\n document.cookie = cookieStr;\n notify(name);\n };\n\n return [value, setCookie, deleteCookie];\n}\n"],"mappings":";;;;;;;;;;;;;AAqCA,IAAM,4BAAY,IAAI,KAA4B;;AAGlD,SAAS,eAAe,MAAkC;AACxD,KAAI,OAAO,aAAa,YAAa,QAAO,KAAA;CAC5C,MAAM,QAAQ,SAAS,OAAO,MAC5B,IAAI,OAAO,gBAAgB,KAAK,QAAQ,uBAAuB,OAAO,GAAG,mBAAmB,CAC7F;AACD,QAAO,QAAQ,mBAAmB,MAAM,GAAG,GAAG,KAAA;;;AAIhD,SAAS,iBAAiB,SAAuC;AAC/D,KAAI,CAAC,QAAS,QAAO;CACrB,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,QAAQ,QAAQ,QAAQ,MAAM;AACzC,KAAI,QAAQ,OAAQ,OAAM,KAAK,UAAU,QAAQ,SAAS;AAC1D,KAAI,QAAQ,WAAW,KAAA,EAAW,OAAM,KAAK,WAAW,QAAQ,SAAS;AACzE,KAAI,QAAQ,QAAS,OAAM,KAAK,WAAW,QAAQ,QAAQ,aAAa,GAAG;CAC3E,MAAM,WAAW,QAAQ,YAAY;AACrC,OAAM,KAAK,YAAY,SAAS,OAAO,EAAE,CAAC,aAAa,GAAG,SAAS,MAAM,EAAE,GAAG;AAC9E,KAAI,QAAQ,OAAQ,OAAM,KAAK,SAAS;AACxC,QAAO,OAAO,MAAM,KAAK,KAAK;;;AAIhC,SAAS,OAAO,MAAoB;CAClC,MAAM,OAAO,UAAU,IAAI,KAAK;AAChC,KAAI,KACF,MAAK,MAAM,MAAM,KAAM,KAAI;;;;;;;;;;;;;AAiB/B,SAAgB,UACd,MACA,gBACgF;CAChF,MAAM,aAAa,aAAqC;EACtD,IAAI,OAAO,UAAU,IAAI,KAAK;AAC9B,MAAI,CAAC,MAAM;AACT,0BAAO,IAAI,KAAK;AAChB,aAAU,IAAI,MAAM,KAAK;;AAE3B,OAAK,IAAI,SAAS;AAClB,eAAa;AACX,QAAM,OAAO,SAAS;AACtB,OAAI,KAAM,SAAS,EAAG,WAAU,OAAO,KAAK;;;CAIhD,MAAM,oBAAwC,eAAe,KAAK;CAClE,MAAM,0BAA8C,YAAY,EAAE,QAAQ,IAAI,KAAK;CAEnF,MAAM,QAAQ,qBAAqB,WAAW,aAAa,kBAAkB;CAE7E,MAAM,aAA2B,UAAkB,YAAkC;EACnF,MAAM,SAAS;GAAE,GAAG;GAAgB,GAAG;GAAS;AAChD,WAAS,SAAS,GAAG,KAAK,GAAG,mBAAmB,SAAS,GAAG,iBAAiB,OAAO;AACpF,SAAO,KAAK;;CAGd,MAAM,qBAA2B;EAC/B,MAAM,OAAO,gBAAgB,QAAQ;EACrC,MAAM,SAAS,gBAAgB;EAC/B,IAAI,YAAY,GAAG,KAAK,4DAA4D;AACpF,MAAI,OAAQ,cAAa,YAAY;AACrC,WAAS,SAAS;AAClB,SAAO,KAAK;;AAGd,QAAO;EAAC;EAAO;EAAW;EAAa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-query-states-D5KaffOK.js","names":[],"sources":["../../src/search-params/registry.ts","../../src/client/use-query-states.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 './create.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 getSearchParams(route: string): SearchParamsDefinition<any> | undefined {\n return registry.get(route);\n}\n","/**\n * useQueryStates — client-side hook for URL-synced search params.\n *\n * Delegates to nuqs for URL synchronization, batching, React 19 transitions,\n * and throttled URL writes. Bridges timber's SearchParamCodec protocol to\n * nuqs-compatible parsers.\n *\n * Design doc: design/23-search-params.md §\"Codec Bridge\"\n */\n\n'use client';\n\nimport { useQueryStates as nuqsUseQueryStates } from 'nuqs';\nimport type { SingleParser } from 'nuqs';\nimport type {\n SearchParamCodec,\n SearchParamsDefinition,\n SetParams,\n QueryStatesOptions,\n} from '#/search-params/create.js';\nimport { getSearchParams } from '#/search-params/registry.js';\n\n// ─── Codec Bridge ─────────────────────────────────────────────────\n\n/**\n * Bridge a timber SearchParamCodec to a nuqs-compatible SingleParser.\n *\n * nuqs parsers: { parse(string) → T|null, serialize?(T) → string, eq?, defaultValue? }\n * timber codecs: { parse(string|string[]|undefined) → T, serialize(T) → string|null }\n */\nfunction bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { defaultValue: T } {\n return {\n parse: (v: string) => codec.parse(v),\n serialize: (v: T) => codec.serialize(v) ?? '',\n defaultValue: codec.parse(undefined) as T,\n eq: (a: T, b: T) => codec.serialize(a) === codec.serialize(b),\n };\n}\n\n/**\n * Bridge an entire codec map to nuqs-compatible parsers.\n */\nfunction bridgeCodecs<T extends Record<string, unknown>>(codecs: {\n [K in keyof T]: SearchParamCodec<T[K]>;\n}) {\n const result: Record<string, SingleParser<unknown> & { defaultValue: unknown }> = {};\n for (const key of Object.keys(codecs)) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n result[key] = bridgeCodec(codecs[key as keyof T]) as any;\n }\n return result as { [K in keyof T]: SingleParser<T[K]> & { defaultValue: T[K] } };\n}\n\n// ─── Hook ─────────────────────────────────────────────────────────\n\n/**\n * Read and write typed search params from/to the URL.\n *\n * Delegates to nuqs internally. The timber nuqs adapter (auto-injected in\n * browser-entry.ts) handles RSC navigation on non-shallow updates.\n *\n * Usage:\n * ```ts\n * // Via a SearchParamsDefinition\n * const [params, setParams] = definition.useQueryStates()\n *\n * // Standalone with inline codecs\n * const [params, setParams] = useQueryStates({\n * page: fromSchema(z.coerce.number().int().min(1).default(1)),\n * })\n * ```\n */\nexport function useQueryStates<T extends Record<string, unknown>>(\n codecsOrRoute: { [K in keyof T]: SearchParamCodec<T[K]> } | string,\n _options?: QueryStatesOptions,\n urlKeys?: Readonly<Record<string, string>>\n): [T, SetParams<T>] {\n // Route-string overload: resolve codecs from the registry\n let codecs: { [K in keyof T]: SearchParamCodec<T[K]> };\n let resolvedUrlKeys = urlKeys;\n if (typeof codecsOrRoute === 'string') {\n const definition = getSearchParams(codecsOrRoute);\n if (!definition) {\n throw new Error(\n `useQueryStates('${codecsOrRoute}'): no search params registered for this route. ` +\n `Either the route has no search-params.ts file, or it hasn't been loaded yet. ` +\n `For cross-route usage, import the definition explicitly.`\n );\n }\n codecs = definition.codecs as { [K in keyof T]: SearchParamCodec<T[K]> };\n resolvedUrlKeys = definition.urlKeys;\n } else {\n codecs = codecsOrRoute;\n }\n\n const bridged = bridgeCodecs(codecs);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nuqsOptions: any = {};\n if (resolvedUrlKeys && Object.keys(resolvedUrlKeys).length > 0) {\n nuqsOptions.urlKeys = resolvedUrlKeys;\n }\n\n let values: Record<string, unknown>;\n let setValues: Function;\n try {\n [values, setValues] = nuqsUseQueryStates(bridged, nuqsOptions);\n } catch (err) {\n if (\n err instanceof Error &&\n /Invalid hook call|cannot be called|Cannot read properties of null/i.test(err.message)\n ) {\n throw new Error(\n 'useQueryStates is a client component hook and cannot be called outside a React component. ' +\n 'Use definition.parse(searchParams) in server components instead.'\n );\n }\n throw err;\n }\n\n // Wrap the nuqs setter to match timber's SetParams<T> signature.\n // nuqs's setter accepts Partial<Nullable<Values>> | UpdaterFn | null.\n // timber's setter accepts Partial<T> with optional SetParamsOptions.\n const setParams: SetParams<T> = (partial, setOptions?) => {\n const nuqsSetOptions: Record<string, unknown> = {};\n if (setOptions?.shallow !== undefined) nuqsSetOptions.shallow = setOptions.shallow;\n if (setOptions?.scroll !== undefined) nuqsSetOptions.scroll = setOptions.scroll;\n if (setOptions?.history !== undefined) nuqsSetOptions.history = setOptions.history;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n void setValues(partial as any, nuqsSetOptions);\n };\n\n return [values as T, setParams];\n}\n\n// ─── Definition binding ───────────────────────────────────────────\n\n/**\n * Create a useQueryStates binding for a SearchParamsDefinition.\n * This is used internally by SearchParamsDefinition.useQueryStates().\n */\nexport function bindUseQueryStates<T extends Record<string, unknown>>(\n definition: SearchParamsDefinition<T>\n): (options?: QueryStatesOptions) => [T, SetParams<T>] {\n return (options?: QueryStatesOptions) => {\n return useQueryStates<T>(definition.codecs, options, definition.urlKeys);\n };\n}\n"],"mappings":";;AAYA,IAAM,2BAAW,IAAI,KAA0C;;;;;AAO/D,SAAgB,qBAAqB,OAAe,YAA+C;AACjG,UAAS,IAAI,OAAO,WAAW;;;;;;AAQjC,SAAgB,gBAAgB,OAAwD;AACtF,QAAO,SAAS,IAAI,MAAM;;;;;;;;;;;;;;;;;;;ACC5B,SAAS,YAAe,OAAmE;AACzF,QAAO;EACL,QAAQ,MAAc,MAAM,MAAM,EAAE;EACpC,YAAY,MAAS,MAAM,UAAU,EAAE,IAAI;EAC3C,cAAc,MAAM,MAAM,KAAA,EAAU;EACpC,KAAK,GAAM,MAAS,MAAM,UAAU,EAAE,KAAK,MAAM,UAAU,EAAE;EAC9D;;;;;AAMH,SAAS,aAAgD,QAEtD;CACD,MAAM,SAA4E,EAAE;AACpF,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CAEnC,QAAO,OAAO,YAAY,OAAO,KAAgB;AAEnD,QAAO;;;;;;;;;;;;;;;;;;;AAsBT,SAAgB,iBACd,eACA,UACA,SACmB;CAEnB,IAAI;CACJ,IAAI,kBAAkB;AACtB,KAAI,OAAO,kBAAkB,UAAU;EACrC,MAAM,aAAa,gBAAgB,cAAc;AACjD,MAAI,CAAC,WACH,OAAM,IAAI,MACR,mBAAmB,cAAc,uLAGlC;AAEH,WAAS,WAAW;AACpB,oBAAkB,WAAW;OAE7B,UAAS;CAGX,MAAM,UAAU,aAAa,OAAO;CAGpC,MAAM,cAAmB,EAAE;AAC3B,KAAI,mBAAmB,OAAO,KAAK,gBAAgB,CAAC,SAAS,EAC3D,aAAY,UAAU;CAGxB,IAAI;CACJ,IAAI;AACJ,KAAI;AACF,GAAC,QAAQ,aAAa,eAAmB,SAAS,YAAY;UACvD,KAAK;AACZ,MACE,eAAe,SACf,qEAAqE,KAAK,IAAI,QAAQ,CAEtF,OAAM,IAAI,MACR,6JAED;AAEH,QAAM;;CAMR,MAAM,aAA2B,SAAS,eAAgB;EACxD,MAAM,iBAA0C,EAAE;AAClD,MAAI,YAAY,YAAY,KAAA,EAAW,gBAAe,UAAU,WAAW;AAC3E,MAAI,YAAY,WAAW,KAAA,EAAW,gBAAe,SAAS,WAAW;AACzE,MAAI,YAAY,YAAY,KAAA,EAAW,gBAAe,UAAU,WAAW;AAEtE,YAAU,SAAgB,eAAe;;AAGhD,QAAO,CAAC,QAAa,UAAU;;;;;;AASjC,SAAgB,mBACd,YACqD;AACrD,SAAQ,YAAiC;AACvC,SAAO,iBAAkB,WAAW,QAAQ,SAAS,WAAW,QAAQ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-boundary.js","names":[],"sources":["../../src/client/error-boundary.tsx"],"sourcesContent":["'use client';\n\n/**\n * Framework-injected React error boundary.\n *\n * Catches errors thrown by children and renders a fallback component\n * with the appropriate props based on error type:\n * - DenySignal (4xx) → { status, dangerouslyPassData }\n * - RenderError (5xx) → { error, digest, reset }\n * - Unhandled error → { error, digest: null, reset }\n *\n * The `status` prop controls which errors this boundary catches:\n * - Specific code (e.g. 403) → only that status\n * - Category (400) → any 4xx\n * - Category (500) → any 5xx\n * - Omitted → catches everything (error.tsx behavior)\n *\n * See design/10-error-handling.md §\"Status-Code Files\"\n */\n\nimport { Component, createElement, type ReactNode } from 'react';\nimport { getSsrData } from './ssr-data.js';\n\n// ─── Page Unload Detection ───────────────────────────────────────────────────\n// Track whether the page is being unloaded (user refreshed or navigated away).\n// When this is true, error boundaries suppress activation — the error is from\n// the aborted connection, not an application error.\nlet _isUnloading = false;\nif (typeof window !== 'undefined') {\n window.addEventListener('beforeunload', () => {\n _isUnloading = true;\n });\n window.addEventListener('pagehide', () => {\n _isUnloading = true;\n });\n}\n\n// ─── Digest Types ────────────────────────────────────────────────────────────\n\n/** Structured digest returned by RSC onError for DenySignal. */\ninterface DenyDigest {\n type: 'deny';\n status: number;\n data: unknown;\n}\n\n/** Structured digest returned by RSC onError for RenderError. */\ninterface RenderErrorDigest {\n type: 'render-error';\n code: string;\n data: unknown;\n status: number;\n}\n\n/** Structured digest returned by RSC onError for RedirectSignal. */\ninterface RedirectDigest {\n type: 'redirect';\n location: string;\n status: number;\n}\n\ntype ParsedDigest = DenyDigest | RenderErrorDigest | RedirectDigest;\n\n// ─── Props & State ───────────────────────────────────────────────────────────\n\nexport interface TimberErrorBoundaryProps {\n /** The component to render when an error is caught. */\n fallbackComponent: (...args: unknown[]) => ReactNode;\n /**\n * Status code filter. If set, only catches errors matching this status.\n * 400 = any 4xx, 500 = any 5xx, specific number = exact match.\n */\n status?: number;\n /**\n * When true, catching a DenySignal sets _denyHandledByBoundary on the\n * nav context to prevent page-level deny promotion. Only slot catch-all\n * boundaries should set this — segment boundaries (403.tsx, 4xx.tsx,\n * error.tsx) must NOT, otherwise normal page denies get swallowed.\n */\n isSlotBoundary?: boolean;\n children: ReactNode;\n}\n\ninterface TimberErrorBoundaryState {\n hasError: boolean;\n error: Error | null;\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\nexport class TimberErrorBoundary extends Component<\n TimberErrorBoundaryProps,\n TimberErrorBoundaryState\n> {\n constructor(props: TimberErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: null };\n }\n\n static getDerivedStateFromError(error: Error): TimberErrorBoundaryState {\n // Suppress error boundaries during page unload (refresh/navigate away).\n // The aborted connection causes React's streaming hydration to error,\n // but the page is about to be replaced — showing an error boundary\n // would be a jarring flash for the user.\n if (_isUnloading) {\n return { hasError: false, error: null };\n }\n\n return { hasError: true, error };\n }\n\n componentDidUpdate(prevProps: TimberErrorBoundaryProps): void {\n // Reset error state when children change (e.g. client-side navigation).\n // Without this, navigating from one error page to another keeps the\n // stale error — getDerivedStateFromError doesn't re-fire for new children.\n if (this.state.hasError && prevProps.children !== this.props.children) {\n this.setState({ hasError: false, error: null });\n }\n }\n\n /** Reset the error state so children re-render. */\n private reset = () => {\n this.setState({ hasError: false, error: null });\n };\n\n render(): ReactNode {\n if (!this.state.hasError || !this.state.error) {\n return this.props.children;\n }\n\n const error = this.state.error;\n const parsed = parseDigest(error);\n\n // RedirectSignal errors must propagate through all error boundaries\n // so the SSR shell fails and the pipeline catch block can produce a\n // proper HTTP redirect response. See design/04-authorization.md.\n if (parsed?.type === 'redirect') {\n throw error;\n }\n\n // If this boundary has a status filter, check whether the error matches.\n // Non-matching errors re-throw so an outer boundary can catch them.\n if (this.props.status != null) {\n const errorStatus = getErrorStatus(parsed, error);\n if (errorStatus == null || !statusMatches(this.props.status, errorStatus)) {\n // Re-throw: this boundary doesn't handle this error.\n throw error;\n }\n }\n\n // Report DenySignal handling to prevent page-level promotion — but only\n // for slot boundaries. Segment boundaries (403.tsx, 4xx.tsx, error.tsx)\n // must NOT set this flag, otherwise normal page/hold-window denies get\n // swallowed as 200 with boundary HTML instead of the intended 4xx.\n // Runs here in render() (not getDerivedStateFromError) so the status\n // filter has already been applied — non-matching boundaries re-threw above.\n // See LOCAL-298.\n if (parsed?.type === 'deny' && this.props.isSlotBoundary) {\n const ssrData = getSsrData();\n if (ssrData?._navContext) {\n ssrData._navContext._denyHandledByBoundary = true;\n }\n }\n\n // Render the fallback component with the right props shape.\n if (parsed?.type === 'deny') {\n return createElement(this.props.fallbackComponent as never, {\n status: parsed.status,\n dangerouslyPassData: parsed.data,\n });\n }\n\n // 5xx / RenderError / unhandled error\n const digest =\n parsed?.type === 'render-error' ? { code: parsed.code, data: parsed.data } : null;\n\n return createElement(this.props.fallbackComponent as never, {\n error,\n digest,\n reset: this.reset,\n });\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/**\n * Parse the structured digest from the error.\n * React sets `error.digest` from the string returned by RSC's onError.\n */\nfunction parseDigest(error: Error): ParsedDigest | null {\n const raw = (error as { digest?: string }).digest;\n if (typeof raw !== 'string') return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object' && typeof parsed.type === 'string') {\n return parsed as ParsedDigest;\n }\n } catch {\n // Not JSON — legacy or unknown digest format\n }\n return null;\n}\n\n/**\n * Extract the HTTP status code from a parsed digest or error message.\n * Falls back to message pattern matching for errors without a digest.\n */\nfunction getErrorStatus(parsed: ParsedDigest | null, error: Error): number | null {\n if (parsed?.type === 'deny') return parsed.status;\n if (parsed?.type === 'render-error') return parsed.status;\n if (parsed?.type === 'redirect') return parsed.status;\n\n // Fallback: parse DenySignal message pattern for errors that lost their digest\n const match = error.message.match(/^Access denied with status (\\d+)$/);\n if (match) return parseInt(match[1], 10);\n\n // Unhandled errors are implicitly 500\n return 500;\n}\n\n/**\n * Check whether an error's status matches the boundary's status filter.\n * Category markers (400, 500) match any status in that range.\n */\nfunction statusMatches(boundaryStatus: number, errorStatus: number): boolean {\n // Category catch-all: 400 matches any 4xx, 500 matches any 5xx\n if (boundaryStatus === 400) return errorStatus >= 400 && errorStatus <= 499;\n if (boundaryStatus === 500) return errorStatus >= 500 && errorStatus <= 599;\n // Exact match\n return boundaryStatus === errorStatus;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA2BA,IAAI,eAAe;AACnB,IAAI,OAAO,WAAW,aAAa;AACjC,QAAO,iBAAiB,sBAAsB;AAC5C,iBAAe;GACf;AACF,QAAO,iBAAiB,kBAAkB;AACxC,iBAAe;GACf;;AAwDJ,IAAa,sBAAb,cAAyC,UAGvC;CACA,YAAY,OAAiC;AAC3C,QAAM,MAAM;AACZ,OAAK,QAAQ;GAAE,UAAU;GAAO,OAAO;GAAM;;CAG/C,OAAO,yBAAyB,OAAwC;AAKtE,MAAI,aACF,QAAO;GAAE,UAAU;GAAO,OAAO;GAAM;AAGzC,SAAO;GAAE,UAAU;GAAM;GAAO;;CAGlC,mBAAmB,WAA2C;AAI5D,MAAI,KAAK,MAAM,YAAY,UAAU,aAAa,KAAK,MAAM,SAC3D,MAAK,SAAS;GAAE,UAAU;GAAO,OAAO;GAAM,CAAC;;;CAKnD,cAAsB;AACpB,OAAK,SAAS;GAAE,UAAU;GAAO,OAAO;GAAM,CAAC;;CAGjD,SAAoB;AAClB,MAAI,CAAC,KAAK,MAAM,YAAY,CAAC,KAAK,MAAM,MACtC,QAAO,KAAK,MAAM;EAGpB,MAAM,QAAQ,KAAK,MAAM;EACzB,MAAM,SAAS,YAAY,MAAM;AAKjC,MAAI,QAAQ,SAAS,WACnB,OAAM;AAKR,MAAI,KAAK,MAAM,UAAU,MAAM;GAC7B,MAAM,cAAc,eAAe,QAAQ,MAAM;AACjD,OAAI,eAAe,QAAQ,CAAC,cAAc,KAAK,MAAM,QAAQ,YAAY,CAEvE,OAAM;;AAWV,MAAI,QAAQ,SAAS,UAAU,KAAK,MAAM,gBAAgB;GACxD,MAAM,UAAU,YAAY;AAC5B,OAAI,SAAS,YACX,SAAQ,YAAY,yBAAyB;;AAKjD,MAAI,QAAQ,SAAS,OACnB,QAAO,cAAc,KAAK,MAAM,mBAA4B;GAC1D,QAAQ,OAAO;GACf,qBAAqB,OAAO;GAC7B,CAAC;EAIJ,MAAM,SACJ,QAAQ,SAAS,iBAAiB;GAAE,MAAM,OAAO;GAAM,MAAM,OAAO;GAAM,GAAG;AAE/E,SAAO,cAAc,KAAK,MAAM,mBAA4B;GAC1D;GACA;GACA,OAAO,KAAK;GACb,CAAC;;;;;;;AAUN,SAAS,YAAY,OAAmC;CACtD,MAAM,MAAO,MAA8B;AAC3C,KAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,KAAI;EACF,MAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,MAAI,UAAU,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS,SACjE,QAAO;SAEH;AAGR,QAAO;;;;;;AAOT,SAAS,eAAe,QAA6B,OAA6B;AAChF,KAAI,QAAQ,SAAS,OAAQ,QAAO,OAAO;AAC3C,KAAI,QAAQ,SAAS,eAAgB,QAAO,OAAO;AACnD,KAAI,QAAQ,SAAS,WAAY,QAAO,OAAO;CAG/C,MAAM,QAAQ,MAAM,QAAQ,MAAM,oCAAoC;AACtE,KAAI,MAAO,QAAO,SAAS,MAAM,IAAI,GAAG;AAGxC,QAAO;;;;;;AAOT,SAAS,cAAc,gBAAwB,aAA8B;AAE3E,KAAI,mBAAmB,IAAK,QAAO,eAAe,OAAO,eAAe;AACxE,KAAI,mBAAmB,IAAK,QAAO,eAAe,OAAO,eAAe;AAExE,QAAO,mBAAmB"}
@@ -1,11 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- /**
3
- * Client component that reads the pending URL from PendingNavigationContext
4
- * and provides a scoped LinkStatusContext to children. Renders no extra DOM —
5
- * just a context provider around children.
6
- */
7
- export declare function LinkStatusProvider({ href, children }: {
8
- href: string;
9
- children?: ReactNode;
10
- }): import("react/jsx-runtime").JSX.Element;
11
- //# sourceMappingURL=link-status-provider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"link-status-provider.d.ts","sourceRoot":"","sources":["../../src/client/link-status-provider.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,2CAK5F"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/cookies/define-cookie.ts"],"sourcesContent":["/**\n * defineCookie — typed cookie definitions.\n *\n * Bundles name + codec + options into a reusable CookieDefinition<T>\n * with .get(), .set(), .delete() server methods and a .useCookie() client hook.\n *\n * Reuses the SearchParamCodec protocol via fromSchema() bridge.\n * Validation on read returns the codec default (never throws).\n *\n * See design/29-cookies.md §\"Typed Cookies with Schema Validation\"\n */\n\nimport { cookies } from '#/server/request-context.js';\nimport type { CookieOptions } from '#/server/request-context.js';\nimport { useCookie as useRawCookie } from '#/client/use-cookie.js';\nimport type { ClientCookieOptions } from '#/client/use-cookie.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * A codec that converts between string cookie values and typed values.\n * Intentionally identical to SearchParamCodec<T>.\n */\nexport interface CookieCodec<T> {\n parse(value: string | string[] | undefined): T;\n serialize(value: T): string | null;\n}\n\n/** Options for defineCookie: codec + CookieOptions merged. */\nexport interface DefineCookieOptions<T> extends Omit<CookieOptions, 'signed'> {\n /** Codec for parsing/serializing the cookie value. */\n codec: CookieCodec<T>;\n /** Sign the cookie with HMAC-SHA256. */\n signed?: boolean;\n}\n\n/** A fully typed cookie definition with server and client methods. */\nexport interface CookieDefinition<T> {\n /** The cookie name. */\n readonly name: string;\n /** The resolved cookie options (without codec). */\n readonly options: CookieOptions;\n /** The codec used for parsing/serializing. */\n readonly codec: CookieCodec<T>;\n\n /** Server: read the typed value from the current request. */\n get(): T;\n /** Server: set the typed value on the response. */\n set(value: T): void;\n /** Server: delete the cookie. */\n delete(): void;\n\n /** Client: React hook for reading/writing this cookie. Returns [value, setter, deleter]. */\n useCookie(): [T, (value: T) => void, () => void];\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────\n\n/**\n * Define a typed cookie.\n *\n * ```ts\n * import { defineCookie } from '@timber-js/app/cookies';\n * import { fromSchema } from '@timber-js/app/search-params';\n * import { z } from 'zod/v4';\n *\n * export const themeCookie = defineCookie('theme', {\n * codec: fromSchema(z.enum(['light', 'dark', 'system']).default('system')),\n * httpOnly: false,\n * maxAge: 60 * 60 * 24 * 365,\n * });\n * ```\n */\nexport function defineCookie<T>(\n name: string,\n options: DefineCookieOptions<T>\n): CookieDefinition<T> {\n const { codec, ...cookieOpts } = options;\n const resolvedOptions: CookieOptions = { ...cookieOpts };\n\n return {\n name,\n options: resolvedOptions,\n codec,\n\n get(): T {\n const jar = cookies();\n const raw = resolvedOptions.signed ? jar.getSigned(name) : jar.get(name);\n return codec.parse(raw);\n },\n\n set(value: T): void {\n const serialized = codec.serialize(value);\n if (serialized === null) {\n cookies().delete(name, {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n });\n } else {\n cookies().set(name, serialized, resolvedOptions);\n }\n },\n\n delete(): void {\n cookies().delete(name, {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n });\n },\n\n useCookie(): [T, (value: T) => void, () => void] {\n // Extract client-safe options (no httpOnly — client cookies can't be httpOnly)\n const clientOpts: ClientCookieOptions = {\n path: resolvedOptions.path,\n domain: resolvedOptions.domain,\n maxAge: resolvedOptions.maxAge,\n expires: resolvedOptions.expires,\n sameSite: resolvedOptions.sameSite,\n secure: resolvedOptions.secure,\n };\n\n const [raw, setRaw, deleteRaw] = useRawCookie(name, clientOpts);\n const parsed = codec.parse(raw);\n\n const setTyped = (value: T): void => {\n const serialized = codec.serialize(value);\n if (serialized === null) {\n deleteRaw();\n } else {\n setRaw(serialized);\n }\n };\n\n return [parsed, setTyped, deleteRaw];\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,SAAgB,aACd,MACA,SACqB;CACrB,MAAM,EAAE,OAAO,GAAG,eAAe;CACjC,MAAM,kBAAiC,EAAE,GAAG,YAAY;AAExD,QAAO;EACL;EACA,SAAS;EACT;EAEA,MAAS;GACP,MAAM,MAAM,SAAS;GACrB,MAAM,MAAM,gBAAgB,SAAS,IAAI,UAAU,KAAK,GAAG,IAAI,IAAI,KAAK;AACxE,UAAO,MAAM,MAAM,IAAI;;EAGzB,IAAI,OAAgB;GAClB,MAAM,aAAa,MAAM,UAAU,MAAM;AACzC,OAAI,eAAe,KACjB,UAAS,CAAC,OAAO,MAAM;IACrB,MAAM,gBAAgB;IACtB,QAAQ,gBAAgB;IACzB,CAAC;OAEF,UAAS,CAAC,IAAI,MAAM,YAAY,gBAAgB;;EAIpD,SAAe;AACb,YAAS,CAAC,OAAO,MAAM;IACrB,MAAM,gBAAgB;IACtB,QAAQ,gBAAgB;IACzB,CAAC;;EAGJ,YAAiD;GAW/C,MAAM,CAAC,KAAK,QAAQ,aAAa,UAAa,MATN;IACtC,MAAM,gBAAgB;IACtB,QAAQ,gBAAgB;IACxB,QAAQ,gBAAgB;IACxB,SAAS,gBAAgB;IACzB,UAAU,gBAAgB;IAC1B,QAAQ,gBAAgB;IACzB,CAE8D;GAC/D,MAAM,SAAS,MAAM,MAAM,IAAI;GAE/B,MAAM,YAAY,UAAmB;IACnC,MAAM,aAAa,MAAM,UAAU,MAAM;AACzC,QAAI,eAAe,KACjB,YAAW;QAEX,QAAO,WAAW;;AAItB,UAAO;IAAC;IAAQ;IAAU;IAAU;;EAEvC"}
@@ -1,72 +0,0 @@
1
- /**
2
- * timber-dynamic-transform — Vite sub-plugin for 'use dynamic' directive.
3
- *
4
- * Detects `'use dynamic'` directives in server component function bodies
5
- * and transforms them into `markDynamic()` runtime calls. The directive
6
- * declares a dynamic boundary — the component and its subtree opt out of
7
- * the pre-rendered shell and render per-request.
8
- *
9
- * - In `output: 'static'` mode, `'use dynamic'` is a build error.
10
- * - In standard SSR routes (no prerender.ts), the directive is a no-op
11
- * (everything is already per-request), but the transform still runs
12
- * so the runtime can skip unnecessary work.
13
- *
14
- * Design doc: design/15-future-prerendering.md §"'use dynamic'"
15
- */
16
- import type { Plugin } from 'vite';
17
- import type { PluginContext } from '#/index.js';
18
- /**
19
- * Quick check: does this source file contain 'use dynamic' anywhere?
20
- * Used as a fast bail-out before doing expensive AST parsing.
21
- */
22
- export declare function containsUseDynamic(code: string): boolean;
23
- interface TransformResult {
24
- code: string;
25
- map?: null;
26
- }
27
- /**
28
- * Find function declarations/expressions containing 'use dynamic' and
29
- * transform them into markDynamic() calls.
30
- *
31
- * Input:
32
- * ```tsx
33
- * export default async function AddToCartButton({ productId }) {
34
- * 'use dynamic'
35
- * const user = await getUser()
36
- * return <button>Add to cart</button>
37
- * }
38
- * ```
39
- *
40
- * Output:
41
- * ```tsx
42
- * import { markDynamic as __markDynamic } from '@timber-js/app/runtime';
43
- * export default async function AddToCartButton({ productId }) {
44
- * __markDynamic();
45
- * const user = await getUser()
46
- * return <button>Add to cart</button>
47
- * }
48
- * ```
49
- *
50
- * The markDynamic() call registers the component boundary as dynamic
51
- * at render time. The pre-render pass uses this to know which subtrees
52
- * to skip and leave as holes for per-request rendering.
53
- */
54
- export declare function transformUseDynamic(code: string): TransformResult | null;
55
- /**
56
- * In `output: 'static'` mode, `'use dynamic'` is a build error.
57
- * Static mode renders everything at build time — there is no per-request
58
- * rendering to opt into.
59
- */
60
- export declare function validateNoDynamicInStaticMode(code: string): {
61
- message: string;
62
- line?: number;
63
- } | null;
64
- /**
65
- * Create the timber-dynamic-transform Vite plugin.
66
- *
67
- * In server mode: transforms 'use dynamic' into markDynamic() calls.
68
- * In static mode: rejects 'use dynamic' as a build error.
69
- */
70
- export declare function timberDynamicTransform(ctx: PluginContext): Plugin;
71
- export {};
72
- //# sourceMappingURL=dynamic-transform.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"dynamic-transform.d.ts","sourceRoot":"","sources":["../../src/plugins/dynamic-transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAMD,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAoBxE;AAMD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,MAAM,GACX;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAa3C;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAkCjE"}
@@ -1,54 +0,0 @@
1
- /**
2
- * Static analyzability checker for search-params.ts files.
3
- *
4
- * Validates that a search-params.ts file's default export is statically
5
- * analyzable — a createSearchParams() call or a chain of .extend()/.pick()
6
- * calls on a SearchParamsDefinition.
7
- *
8
- * Non-analyzable files produce a hard build error with a diagnostic.
9
- *
10
- * Design doc: design/09-typescript.md §"Static Analyzability"
11
- */
12
- /** Result of analyzing a search-params.ts file. */
13
- export interface AnalyzeResult {
14
- /** Whether the file is statically analyzable. */
15
- valid: boolean;
16
- /** Error details when valid is false. */
17
- error?: AnalyzeError;
18
- }
19
- /** Diagnostic error for non-analyzable search-params.ts. */
20
- export interface AnalyzeError {
21
- /** Absolute file path. */
22
- filePath: string;
23
- /** Description of the non-analyzable expression. */
24
- expression: string;
25
- /** Suggested fix. */
26
- suggestion: string;
27
- }
28
- /**
29
- * Patterns that indicate a valid default export:
30
- *
31
- * 1. `export default createSearchParams(...)`
32
- * 2. `export default someVar.extend(...)`
33
- * 3. `export default someVar.pick(...)`
34
- * 4. `export default someVar.extend(...).extend(...)` (chained)
35
- * 5. `export default someVar.extend(...).pick(...)` (chained)
36
- * 6. `export default createSearchParams(...).extend(...)`
37
- *
38
- * Invalid patterns:
39
- * - `export default someFunction(...)` (arbitrary factory)
40
- * - `export default condition ? a : b` (runtime conditional)
41
- * - `export default variable` (opaque reference without call)
42
- */
43
- /**
44
- * Analyze a search-params.ts file source for static analyzability.
45
- *
46
- * @param source - The file content as a string
47
- * @param filePath - Absolute path to the file (for diagnostics)
48
- */
49
- export declare function analyzeSearchParams(source: string, filePath: string): AnalyzeResult;
50
- /**
51
- * Format an AnalyzeError into a human-readable build error message.
52
- */
53
- export declare function formatAnalyzeError(error: AnalyzeError): string;
54
- //# sourceMappingURL=analyze.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/search-params/analyze.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,mDAAmD;AACnD,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,KAAK,EAAE,OAAO,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,4DAA4D;AAC5D,MAAM,WAAW,YAAY;IAC3B,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAYD;;;;;;;;;;;;;;GAcG;AAEH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAmCnF;AA0ED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAa9D"}
@@ -1,105 +0,0 @@
1
- /**
2
- * Built-in search param codecs for common types.
3
- *
4
- * These provide zero-dependency alternatives to nuqs parsers for the most
5
- * common cases: strings, integers, floats, booleans, and string enums.
6
- *
7
- * All codecs implement SearchParamCodec<T | null> — returning null when the
8
- * param is absent or unparseable. Use withDefault() to replace null with a
9
- * concrete fallback value.
10
- *
11
- * Design doc: design/23-search-params.md §"Identified Gaps" #1
12
- * Task: TIM-362
13
- */
14
- import type { SearchParamCodec } from './create.js';
15
- /**
16
- * String codec. Returns the raw string value, or null if absent.
17
- *
18
- * ```ts
19
- * import { parseAsString } from '@timber-js/app/search-params'
20
- *
21
- * const def = createSearchParams({ q: parseAsString })
22
- * // ?q=shoes → { q: 'shoes' }
23
- * // (absent) → { q: null }
24
- * ```
25
- */
26
- export declare const parseAsString: SearchParamCodec<string | null>;
27
- /**
28
- * Integer codec. Parses a base-10 integer, or returns null if absent or
29
- * not a valid integer. Rejects floats, NaN, Infinity, and non-numeric strings.
30
- *
31
- * ```ts
32
- * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'
33
- *
34
- * const def = createSearchParams({ page: withDefault(parseAsInteger, 1) })
35
- * // ?page=2 → { page: 2 }
36
- * // ?page=abc → { page: 1 }
37
- * // (absent) → { page: 1 }
38
- * ```
39
- */
40
- export declare const parseAsInteger: SearchParamCodec<number | null>;
41
- /**
42
- * Float codec. Parses a finite number, or returns null if absent or invalid.
43
- * Rejects NaN and Infinity.
44
- *
45
- * ```ts
46
- * import { parseAsFloat, withDefault } from '@timber-js/app/search-params'
47
- *
48
- * const def = createSearchParams({ price: withDefault(parseAsFloat, 0) })
49
- * ```
50
- */
51
- export declare const parseAsFloat: SearchParamCodec<number | null>;
52
- /**
53
- * Boolean codec. Accepts "true"/"1" as true, "false"/"0" as false.
54
- * Returns null for absent or unrecognized values.
55
- *
56
- * ```ts
57
- * import { parseAsBoolean, withDefault } from '@timber-js/app/search-params'
58
- *
59
- * const def = createSearchParams({ debug: withDefault(parseAsBoolean, false) })
60
- * // ?debug=true → { debug: true }
61
- * // ?debug=0 → { debug: false }
62
- * ```
63
- */
64
- export declare const parseAsBoolean: SearchParamCodec<boolean | null>;
65
- /**
66
- * String enum codec. Accepts only values in the provided list.
67
- * Returns null for absent or invalid values.
68
- *
69
- * ```ts
70
- * import { parseAsStringEnum, withDefault } from '@timber-js/app/search-params'
71
- *
72
- * const sortCodec = withDefault(
73
- * parseAsStringEnum(['price', 'name', 'date']),
74
- * 'date'
75
- * )
76
- * ```
77
- */
78
- export declare function parseAsStringEnum<T extends string>(values: readonly T[]): SearchParamCodec<T | null>;
79
- /**
80
- * String literal codec. Functionally identical to parseAsStringEnum but
81
- * accepts `as const` tuples for narrower type inference.
82
- *
83
- * ```ts
84
- * import { parseAsStringLiteral } from '@timber-js/app/search-params'
85
- *
86
- * const sizes = ['sm', 'md', 'lg', 'xl'] as const
87
- * const codec = parseAsStringLiteral(sizes)
88
- * // Type: SearchParamCodec<'sm' | 'md' | 'lg' | 'xl' | null>
89
- * ```
90
- */
91
- export declare function parseAsStringLiteral<const T extends readonly string[]>(values: T): SearchParamCodec<T[number] | null>;
92
- /**
93
- * Wrap a nullable codec with a default value. When the inner codec returns
94
- * null, the default is used instead. The output type becomes non-nullable.
95
- *
96
- * ```ts
97
- * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'
98
- *
99
- * const page = withDefault(parseAsInteger, 1)
100
- * // page.parse(undefined) → 1 (not null)
101
- * // page.parse('5') → 5
102
- * ```
103
- */
104
- export declare function withDefault<T>(codec: SearchParamCodec<T | null>, defaultValue: T): SearchParamCodec<T>;
105
- //# sourceMappingURL=builtin-codecs.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"builtin-codecs.d.ts","sourceRoot":"","sources":["../../src/search-params/builtin-codecs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqBpD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,aAAa,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAQzD,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAW1D,CAAC;AAMF;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,EAAE,gBAAgB,CAAC,MAAM,GAAG,IAAI,CAWxD,CAAC;AAMF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,EAAE,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAW3D,CAAC;AAMF;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,MAAM,EAAE,SAAS,CAAC,EAAE,GACnB,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC,CAY5B;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,CAAC,SAAS,SAAS,MAAM,EAAE,EACpE,MAAM,EAAE,CAAC,GACR,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAGpC;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,KAAK,EAAE,gBAAgB,CAAC,CAAC,GAAG,IAAI,CAAC,EACjC,YAAY,EAAE,CAAC,GACd,gBAAgB,CAAC,CAAC,CAAC,CAUrB"}
@@ -1,106 +0,0 @@
1
- /**
2
- * createSearchParams — factory for SearchParamsDefinition<T>.
3
- *
4
- * Creates a typed, composable definition for a route's search parameters.
5
- * Supports codec protocol, URL key aliasing, default-omission serialization,
6
- * and composition via .extend() / .pick().
7
- *
8
- * Design doc: design/09-typescript.md §"Typed searchParams — search-params.ts"
9
- */
10
- /**
11
- * A codec that converts between URL string values and typed values.
12
- *
13
- * nuqs parsers (parseAsInteger, parseAsString, etc.) implement this
14
- * interface natively — no adapter needed.
15
- */
16
- export interface SearchParamCodec<T> {
17
- /** URL string → typed value. Receives undefined when the param is absent. */
18
- parse(value: string | string[] | undefined): T;
19
- /** Typed value → URL string. Return null to omit from URL. */
20
- serialize(value: T): string | null;
21
- }
22
- /** Infer the output type of a codec. */
23
- export type InferCodec<C> = C extends SearchParamCodec<infer T> ? T : never;
24
- /** Map of property names to codecs. */
25
- export type CodecMap<T extends Record<string, unknown>> = {
26
- [K in keyof T]: SearchParamCodec<T[K]>;
27
- };
28
- /** Options for useQueryStates setter. */
29
- export interface SetParamsOptions {
30
- /** Update URL without server roundtrip (default: false). */
31
- shallow?: boolean;
32
- /** Scroll to top after update (default: true). */
33
- scroll?: boolean;
34
- /** 'push' (default) or 'replace' for history state. */
35
- history?: 'push' | 'replace';
36
- }
37
- /** Setter function returned by useQueryStates. */
38
- export type SetParams<T> = (values: Partial<T>, options?: SetParamsOptions) => void;
39
- /** Options for useQueryStates hook. */
40
- export interface QueryStatesOptions {
41
- /** Update URL without server roundtrip (default: false). */
42
- shallow?: boolean;
43
- /** Scroll to top after update (default: true). */
44
- scroll?: boolean;
45
- /** 'push' (default) or 'replace' for history state. */
46
- history?: 'push' | 'replace';
47
- }
48
- /** Options for createSearchParams and .extend(). */
49
- export interface SearchParamsOptions<Keys extends string = string> {
50
- /** Map property names to different URL query parameter keys. */
51
- urlKeys?: Partial<Record<Keys, string>>;
52
- }
53
- /**
54
- * A fully typed, composable search params definition.
55
- *
56
- * Returned by createSearchParams(). Carries a phantom _type property
57
- * for build-time type extraction.
58
- */
59
- export interface SearchParamsDefinition<T extends Record<string, unknown>> {
60
- /** Parse raw URL search params into typed values. */
61
- parse(raw: URLSearchParams | Record<string, string | string[] | undefined>): T;
62
- /** Client hook — reads current URL params and returns typed values + setter. */
63
- useQueryStates(options?: QueryStatesOptions): [T, SetParams<T>];
64
- /** Extend with additional codecs. Key collisions are a type error. */
65
- extend<U extends Record<string, SearchParamCodec<unknown>>>(codecs: U, options?: SearchParamsOptions<string>): SearchParamsDefinition<T & {
66
- [K in keyof U]: InferCodec<U[K]>;
67
- }>;
68
- /** Pick a subset of keys. Preserves codecs and aliases. */
69
- pick<K extends keyof T & string>(...keys: K[]): SearchParamsDefinition<Pick<T, K>>;
70
- /** Serialize values to a query string (no leading '?'), omitting defaults. */
71
- serialize(values: Partial<T>): string;
72
- /** Build a full path with query string, omitting defaults. */
73
- href(pathname: string, values: Partial<T>): string;
74
- /** Build a URLSearchParams instance, omitting defaults. */
75
- toSearchParams(values: Partial<T>): URLSearchParams;
76
- /** Read-only codec map for spreading into .extend(). Aliases NOT carried. */
77
- codecs: {
78
- [K in keyof T]: SearchParamCodec<T[K]>;
79
- };
80
- /** Read-only URL key alias map. Maps property names to URL query parameter keys. */
81
- readonly urlKeys: Readonly<Record<string, string>>;
82
- /**
83
- * Phantom property for build-time type extraction.
84
- * Never set at runtime — exists only in the type system.
85
- */
86
- readonly _type?: T;
87
- }
88
- /**
89
- * Create a SearchParamsDefinition from a codec map and optional URL key aliases.
90
- *
91
- * ```ts
92
- * import { createSearchParams, fromSchema } from '@timber-js/app/search-params'
93
- * import { z } from 'zod/v4'
94
- *
95
- * export default createSearchParams({
96
- * page: fromSchema(z.coerce.number().int().min(1).default(1)),
97
- * q: { parse: (v) => v ?? null, serialize: (v) => v },
98
- * }, {
99
- * urlKeys: { q: 'search' },
100
- * })
101
- * ```
102
- */
103
- export declare function createSearchParams<C extends Record<string, SearchParamCodec<unknown>>>(codecs: C, options?: SearchParamsOptions<Extract<keyof C, string>>): SearchParamsDefinition<{
104
- [K in keyof C]: InferCodec<C[K]>;
105
- }>;
106
- //# sourceMappingURL=create.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/search-params/create.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/search-params/create.ts","../../src/search-params/codecs.ts","../../src/search-params/builtin-codecs.ts","../../src/search-params/analyze.ts"],"sourcesContent":["/**\n * createSearchParams — factory for SearchParamsDefinition<T>.\n *\n * Creates a typed, composable definition for a route's search parameters.\n * Supports codec protocol, URL key aliasing, default-omission serialization,\n * and composition via .extend() / .pick().\n *\n * Design doc: design/09-typescript.md §\"Typed searchParams — search-params.ts\"\n */\n\nimport { useQueryStates as clientUseQueryStates } from '#/client/use-query-states.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * A codec that converts between URL string values and typed values.\n *\n * nuqs parsers (parseAsInteger, parseAsString, etc.) implement this\n * interface natively — no adapter needed.\n */\nexport interface SearchParamCodec<T> {\n /** URL string → typed value. Receives undefined when the param is absent. */\n parse(value: string | string[] | undefined): T;\n /** Typed value → URL string. Return null to omit from URL. */\n serialize(value: T): string | null;\n}\n\n/** Infer the output type of a codec. */\nexport type InferCodec<C> = C extends SearchParamCodec<infer T> ? T : never;\n\n/** Map of property names to codecs. */\nexport type CodecMap<T extends Record<string, unknown>> = {\n [K in keyof T]: SearchParamCodec<T[K]>;\n};\n\n/** Options for useQueryStates setter. */\nexport interface SetParamsOptions {\n /** Update URL without server roundtrip (default: false). */\n shallow?: boolean;\n /** Scroll to top after update (default: true). */\n scroll?: boolean;\n /** 'push' (default) or 'replace' for history state. */\n history?: 'push' | 'replace';\n}\n\n/** Setter function returned by useQueryStates. */\nexport type SetParams<T> = (values: Partial<T>, options?: SetParamsOptions) => void;\n\n/** Options for useQueryStates hook. */\nexport interface QueryStatesOptions {\n /** Update URL without server roundtrip (default: false). */\n shallow?: boolean;\n /** Scroll to top after update (default: true). */\n scroll?: boolean;\n /** 'push' (default) or 'replace' for history state. */\n history?: 'push' | 'replace';\n}\n\n/** Options for createSearchParams and .extend(). */\nexport interface SearchParamsOptions<Keys extends string = string> {\n /** Map property names to different URL query parameter keys. */\n urlKeys?: Partial<Record<Keys, string>>;\n}\n\n/**\n * A fully typed, composable search params definition.\n *\n * Returned by createSearchParams(). Carries a phantom _type property\n * for build-time type extraction.\n */\nexport interface SearchParamsDefinition<T extends Record<string, unknown>> {\n /** Parse raw URL search params into typed values. */\n parse(raw: URLSearchParams | Record<string, string | string[] | undefined>): T;\n\n /** Client hook — reads current URL params and returns typed values + setter. */\n useQueryStates(options?: QueryStatesOptions): [T, SetParams<T>];\n\n /** Extend with additional codecs. Key collisions are a type error. */\n extend<U extends Record<string, SearchParamCodec<unknown>>>(\n codecs: U,\n options?: SearchParamsOptions<string>\n ): SearchParamsDefinition<T & { [K in keyof U]: InferCodec<U[K]> }>;\n\n /** Pick a subset of keys. Preserves codecs and aliases. */\n pick<K extends keyof T & string>(...keys: K[]): SearchParamsDefinition<Pick<T, K>>;\n\n /** Serialize values to a query string (no leading '?'), omitting defaults. */\n serialize(values: Partial<T>): string;\n\n /** Build a full path with query string, omitting defaults. */\n href(pathname: string, values: Partial<T>): string;\n\n /** Build a URLSearchParams instance, omitting defaults. */\n toSearchParams(values: Partial<T>): URLSearchParams;\n\n /** Read-only codec map for spreading into .extend(). Aliases NOT carried. */\n codecs: { [K in keyof T]: SearchParamCodec<T[K]> };\n\n /** Read-only URL key alias map. Maps property names to URL query parameter keys. */\n readonly urlKeys: Readonly<Record<string, string>>;\n\n /**\n * Phantom property for build-time type extraction.\n * Never set at runtime — exists only in the type system.\n */\n readonly _type?: T;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Convert URLSearchParams or a plain record to a normalized record\n * where repeated keys produce arrays.\n */\nfunction normalizeRaw(\n raw: URLSearchParams | Record<string, string | string[] | undefined>\n): Record<string, string | string[] | undefined> {\n if (raw instanceof URLSearchParams) {\n const result: Record<string, string | string[] | undefined> = {};\n for (const key of new Set(raw.keys())) {\n const values = raw.getAll(key);\n result[key] = values.length === 1 ? values[0] : values;\n }\n return result;\n }\n return raw;\n}\n\n/**\n * Compute the serialized default value for a codec. Used for\n * default-omission: when serialize(value) === serialize(parse(undefined)),\n * the field is omitted from the URL.\n */\nfunction getDefaultSerialized<T>(codec: SearchParamCodec<T>): string | null {\n return codec.serialize(codec.parse(undefined));\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Create a SearchParamsDefinition from a codec map and optional URL key aliases.\n *\n * ```ts\n * import { createSearchParams, fromSchema } from '@timber-js/app/search-params'\n * import { z } from 'zod/v4'\n *\n * export default createSearchParams({\n * page: fromSchema(z.coerce.number().int().min(1).default(1)),\n * q: { parse: (v) => v ?? null, serialize: (v) => v },\n * }, {\n * urlKeys: { q: 'search' },\n * })\n * ```\n */\nexport function createSearchParams<C extends Record<string, SearchParamCodec<unknown>>>(\n codecs: C,\n options?: SearchParamsOptions<Extract<keyof C, string>>\n): SearchParamsDefinition<{ [K in keyof C]: InferCodec<C[K]> }> {\n type T = { [K in keyof C]: InferCodec<C[K]> };\n const urlKeys: Record<string, string> = {};\n if (options?.urlKeys) {\n for (const [k, v] of Object.entries(options.urlKeys)) {\n if (v !== undefined) urlKeys[k] = v;\n }\n }\n\n return buildDefinition<T>(codecs as unknown as CodecMap<T>, urlKeys);\n}\n\n/**\n * Internal: build a SearchParamsDefinition from a typed codec map and url keys.\n */\nfunction buildDefinition<T extends Record<string, unknown>>(\n codecMap: CodecMap<T>,\n urlKeys: Record<string, string>\n): SearchParamsDefinition<T> {\n // Pre-compute default serialized values for omission check\n const defaultSerialized: Record<string, string | null> = {};\n for (const key of Object.keys(codecMap)) {\n defaultSerialized[key] = getDefaultSerialized(codecMap[key as keyof T]);\n }\n\n function getUrlKey(prop: string): string {\n return urlKeys[prop] ?? prop;\n }\n\n // ---- parse ----\n function parse(raw: URLSearchParams | Record<string, string | string[] | undefined>): T {\n const normalized = normalizeRaw(raw);\n const result: Record<string, unknown> = {};\n\n for (const prop of Object.keys(codecMap)) {\n const urlKey = getUrlKey(prop);\n const rawValue = normalized[urlKey];\n result[prop] = (codecMap[prop as keyof T] as SearchParamCodec<unknown>).parse(rawValue);\n }\n\n return result as T;\n }\n\n // ---- serialize ----\n function serialize(values: Partial<T>): string {\n const parts: string[] = [];\n\n for (const prop of Object.keys(codecMap)) {\n if (!(prop in values)) continue;\n const codec = codecMap[prop as keyof T] as SearchParamCodec<unknown>;\n const serialized = codec.serialize(values[prop as keyof T] as unknown);\n\n // Omit if serialized value matches the default\n if (serialized === defaultSerialized[prop]) continue;\n if (serialized === null) continue;\n\n parts.push(`${encodeURIComponent(getUrlKey(prop))}=${encodeURIComponent(serialized)}`);\n }\n\n return parts.join('&');\n }\n\n // ---- href ----\n function href(pathname: string, values: Partial<T>): string {\n const qs = serialize(values);\n return qs ? `${pathname}?${qs}` : pathname;\n }\n\n // ---- toSearchParams ----\n function toSearchParams(values: Partial<T>): URLSearchParams {\n const usp = new URLSearchParams();\n\n for (const prop of Object.keys(codecMap)) {\n if (!(prop in values)) continue;\n const codec = codecMap[prop as keyof T] as SearchParamCodec<unknown>;\n const serialized = codec.serialize(values[prop as keyof T] as unknown);\n\n if (serialized === defaultSerialized[prop]) continue;\n if (serialized === null) continue;\n\n usp.set(getUrlKey(prop), serialized);\n }\n\n return usp;\n }\n\n // ---- extend ----\n function extend<U extends Record<string, SearchParamCodec<unknown>>>(\n newCodecs: U,\n extendOptions?: SearchParamsOptions<string>\n ): SearchParamsDefinition<T & { [K in keyof U]: InferCodec<U[K]> }> {\n type Combined = T & { [K in keyof U]: InferCodec<U[K]> };\n\n const combinedCodecs = {\n ...codecMap,\n ...newCodecs,\n } as unknown as CodecMap<Combined>;\n\n // Merge URL keys: extend options override, but do NOT inherit from base\n // (aliases are route-level, not carried through .codecs)\n const combinedUrlKeys: Record<string, string> = { ...urlKeys };\n if (extendOptions?.urlKeys) {\n for (const [k, v] of Object.entries(extendOptions.urlKeys)) {\n if (v !== undefined) combinedUrlKeys[k] = v;\n }\n }\n\n return buildDefinition<Combined>(combinedCodecs, combinedUrlKeys);\n }\n\n // ---- pick ----\n function pick<K extends keyof T & string>(...keys: K[]): SearchParamsDefinition<Pick<T, K>> {\n const pickedCodecs: Record<string, SearchParamCodec<unknown>> = {};\n const pickedUrlKeys: Record<string, string> = {};\n\n for (const key of keys) {\n pickedCodecs[key] = codecMap[key] as SearchParamCodec<unknown>;\n if (key in urlKeys) {\n pickedUrlKeys[key] = urlKeys[key];\n }\n }\n\n return buildDefinition<Pick<T, K>>(\n pickedCodecs as unknown as CodecMap<Pick<T, K>>,\n pickedUrlKeys\n );\n }\n\n // ---- useQueryStates ----\n // Delegates to the 'use client' implementation from use-query-states.ts.\n //\n // In the RSC environment: use-query-states.ts is transformed by the RSC\n // plugin into a client reference proxy. Calling it throws — correct,\n // because hooks can't run during server component rendering.\n // In SSR: use-query-states.ts is the real nuqs-backed function. Hooks\n // work during SSR's renderToReadableStream, so this works correctly.\n // On the client: same as SSR — the real function is available.\n function useQueryStates(options?: QueryStatesOptions): [T, SetParams<T>] {\n return clientUseQueryStates(codecMap, options, Object.freeze({ ...urlKeys })) as [\n T,\n SetParams<T>,\n ];\n }\n\n const definition: SearchParamsDefinition<T> = {\n parse,\n useQueryStates,\n extend,\n pick,\n serialize,\n href,\n toSearchParams,\n codecs: codecMap,\n urlKeys: Object.freeze({ ...urlKeys }),\n };\n\n return definition;\n}\n","/**\n * Built-in codecs and the fromSchema bridge for Standard Schema-compatible\n * validation libraries (Zod, Valibot, ArkType).\n *\n * Design doc: design/09-typescript.md §\"The SearchParamCodec Protocol\"\n */\n\nimport type { SearchParamCodec } from './create.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\ninterface StandardSchemaV1<Output = unknown> {\n '~standard': {\n validate(value: unknown): StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;\n };\n}\n\ntype StandardSchemaResult<Output> =\n | { value: Output; issues?: undefined }\n | { value?: undefined; issues: ReadonlyArray<{ message: string }> };\n\n// ---------------------------------------------------------------------------\n// Sync validate helper\n// ---------------------------------------------------------------------------\n\n/**\n * Zod v4's ~standard.validate() signature includes Promise in the return union\n * to satisfy the Standard Schema spec, but in practice Zod always validates\n * synchronously for the schema types we use. We assert the result is sync and\n * throw if it isn't — search params parsing must be synchronous.\n */\nfunction 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 for search params.'\n );\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// fromSchema — bridge from Standard Schema to SearchParamCodec\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge a Standard Schema-compatible schema (Zod, Valibot, ArkType) to a\n * SearchParamCodec.\n *\n * Parse: coerces the raw URL 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/search-params'\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>): SearchParamCodec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n // For array inputs, take the last value (consistent with URLSearchParams.get())\n const input = Array.isArray(value) ? value[value.length - 1] : 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 search params\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/search-params'\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>): SearchParamCodec<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","/**\n * Built-in search param codecs for common types.\n *\n * These provide zero-dependency alternatives to nuqs parsers for the most\n * common cases: strings, integers, floats, booleans, and string enums.\n *\n * All codecs implement SearchParamCodec<T | null> — returning null when the\n * param is absent or unparseable. Use withDefault() to replace null with a\n * concrete fallback value.\n *\n * Design doc: design/23-search-params.md §\"Identified Gaps\" #1\n * Task: TIM-362\n */\n\nimport type { SearchParamCodec } from './create.js';\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize array inputs to a single string (last value wins, matching\n * URLSearchParams.get() semantics). Returns undefined if absent or empty.\n */\nfunction normalizeInput(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) {\n return value.length > 0 ? value[value.length - 1] : undefined;\n }\n return value;\n}\n\n// ---------------------------------------------------------------------------\n// parseAsString\n// ---------------------------------------------------------------------------\n\n/**\n * String codec. Returns the raw string value, or null if absent.\n *\n * ```ts\n * import { parseAsString } from '@timber-js/app/search-params'\n *\n * const def = createSearchParams({ q: parseAsString })\n * // ?q=shoes → { q: 'shoes' }\n * // (absent) → { q: null }\n * ```\n */\nexport const parseAsString: SearchParamCodec<string | null> = {\n parse(value: string | string[] | undefined): string | null {\n const v = normalizeInput(value);\n return v !== undefined ? v : null;\n },\n serialize(value: string | null): string | null {\n return value;\n },\n};\n\n// ---------------------------------------------------------------------------\n// parseAsInteger\n// ---------------------------------------------------------------------------\n\n/**\n * Integer codec. Parses a base-10 integer, or returns null if absent or\n * not a valid integer. Rejects floats, NaN, Infinity, and non-numeric strings.\n *\n * ```ts\n * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'\n *\n * const def = createSearchParams({ page: withDefault(parseAsInteger, 1) })\n * // ?page=2 → { page: 2 }\n * // ?page=abc → { page: 1 }\n * // (absent) → { page: 1 }\n * ```\n */\nexport const parseAsInteger: SearchParamCodec<number | null> = {\n parse(value: string | string[] | undefined): number | null {\n const v = normalizeInput(value);\n if (v === undefined || v === '') return null;\n const n = Number(v);\n if (!Number.isFinite(n) || !Number.isInteger(n)) return null;\n return n;\n },\n serialize(value: number | null): string | null {\n return value === null ? null : String(value);\n },\n};\n\n// ---------------------------------------------------------------------------\n// parseAsFloat\n// ---------------------------------------------------------------------------\n\n/**\n * Float codec. Parses a finite number, or returns null if absent or invalid.\n * Rejects NaN and Infinity.\n *\n * ```ts\n * import { parseAsFloat, withDefault } from '@timber-js/app/search-params'\n *\n * const def = createSearchParams({ price: withDefault(parseAsFloat, 0) })\n * ```\n */\nexport const parseAsFloat: SearchParamCodec<number | null> = {\n parse(value: string | string[] | undefined): number | null {\n const v = normalizeInput(value);\n if (v === undefined || v === '') return null;\n const n = Number(v);\n if (!Number.isFinite(n)) return null;\n return n;\n },\n serialize(value: number | null): string | null {\n return value === null ? null : String(value);\n },\n};\n\n// ---------------------------------------------------------------------------\n// parseAsBoolean\n// ---------------------------------------------------------------------------\n\n/**\n * Boolean codec. Accepts \"true\"/\"1\" as true, \"false\"/\"0\" as false.\n * Returns null for absent or unrecognized values.\n *\n * ```ts\n * import { parseAsBoolean, withDefault } from '@timber-js/app/search-params'\n *\n * const def = createSearchParams({ debug: withDefault(parseAsBoolean, false) })\n * // ?debug=true → { debug: true }\n * // ?debug=0 → { debug: false }\n * ```\n */\nexport const parseAsBoolean: SearchParamCodec<boolean | null> = {\n parse(value: string | string[] | undefined): boolean | null {\n const v = normalizeInput(value);\n if (v === undefined) return null;\n if (v === 'true' || v === '1') return true;\n if (v === 'false' || v === '0') return false;\n return null;\n },\n serialize(value: boolean | null): string | null {\n return value === null ? null : String(value);\n },\n};\n\n// ---------------------------------------------------------------------------\n// parseAsStringEnum\n// ---------------------------------------------------------------------------\n\n/**\n * String enum codec. Accepts only values in the provided list.\n * Returns null for absent or invalid values.\n *\n * ```ts\n * import { parseAsStringEnum, withDefault } from '@timber-js/app/search-params'\n *\n * const sortCodec = withDefault(\n * parseAsStringEnum(['price', 'name', 'date']),\n * 'date'\n * )\n * ```\n */\nexport function parseAsStringEnum<T extends string>(\n values: readonly T[]\n): SearchParamCodec<T | null> {\n const allowed = new Set<string>(values);\n return {\n parse(value: string | string[] | undefined): T | null {\n const v = normalizeInput(value);\n if (v === undefined) return null;\n return allowed.has(v) ? (v as T) : null;\n },\n serialize(value: T | null): string | null {\n return value;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// parseAsStringLiteral\n// ---------------------------------------------------------------------------\n\n/**\n * String literal codec. Functionally identical to parseAsStringEnum but\n * accepts `as const` tuples for narrower type inference.\n *\n * ```ts\n * import { parseAsStringLiteral } from '@timber-js/app/search-params'\n *\n * const sizes = ['sm', 'md', 'lg', 'xl'] as const\n * const codec = parseAsStringLiteral(sizes)\n * // Type: SearchParamCodec<'sm' | 'md' | 'lg' | 'xl' | null>\n * ```\n */\nexport function parseAsStringLiteral<const T extends readonly string[]>(\n values: T\n): SearchParamCodec<T[number] | null> {\n // Delegates to parseAsStringEnum — same runtime behavior, different type\n return parseAsStringEnum<T[number]>(values);\n}\n\n// ---------------------------------------------------------------------------\n// withDefault\n// ---------------------------------------------------------------------------\n\n/**\n * Wrap a nullable codec with a default value. When the inner codec returns\n * null, the default is used instead. The output type becomes non-nullable.\n *\n * ```ts\n * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'\n *\n * const page = withDefault(parseAsInteger, 1)\n * // page.parse(undefined) → 1 (not null)\n * // page.parse('5') → 5\n * ```\n */\nexport function withDefault<T>(\n codec: SearchParamCodec<T | null>,\n defaultValue: T\n): SearchParamCodec<T> {\n return {\n parse(value: string | string[] | undefined): T {\n const result = codec.parse(value);\n return result === null ? defaultValue : result;\n },\n serialize(value: T): string | null {\n return codec.serialize(value);\n },\n };\n}\n","/**\n * Static analyzability checker for search-params.ts files.\n *\n * Validates that a search-params.ts file's default export is statically\n * analyzable — a createSearchParams() call or a chain of .extend()/.pick()\n * calls on a SearchParamsDefinition.\n *\n * Non-analyzable files produce a hard build error with a diagnostic.\n *\n * Design doc: design/09-typescript.md §\"Static Analyzability\"\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Result of analyzing a search-params.ts file. */\nexport interface AnalyzeResult {\n /** Whether the file is statically analyzable. */\n valid: boolean;\n /** Error details when valid is false. */\n error?: AnalyzeError;\n}\n\n/** Diagnostic error for non-analyzable search-params.ts. */\nexport interface AnalyzeError {\n /** Absolute file path. */\n filePath: string;\n /** Description of the non-analyzable expression. */\n expression: string;\n /** Suggested fix. */\n suggestion: string;\n}\n\n// ---------------------------------------------------------------------------\n// AST-free source analysis\n//\n// We use a lightweight regex-based approach to validate the structure of the\n// default export. This avoids requiring a TypeScript compiler instance at\n// build time for the initial validation pass. The full type extraction\n// (reading T from SearchParamsDefinition<T>) still happens via the TypeScript\n// compiler in the codegen step — this module just validates the *shape*.\n// ---------------------------------------------------------------------------\n\n/**\n * Patterns that indicate a valid default export:\n *\n * 1. `export default createSearchParams(...)`\n * 2. `export default someVar.extend(...)`\n * 3. `export default someVar.pick(...)`\n * 4. `export default someVar.extend(...).extend(...)` (chained)\n * 5. `export default someVar.extend(...).pick(...)` (chained)\n * 6. `export default createSearchParams(...).extend(...)`\n *\n * Invalid patterns:\n * - `export default someFunction(...)` (arbitrary factory)\n * - `export default condition ? a : b` (runtime conditional)\n * - `export default variable` (opaque reference without call)\n */\n\n/**\n * Analyze a search-params.ts file source for static analyzability.\n *\n * @param source - The file content as a string\n * @param filePath - Absolute path to the file (for diagnostics)\n */\nexport function analyzeSearchParams(source: string, filePath: string): AnalyzeResult {\n // Strip comments to avoid false matches\n const stripped = stripComments(source);\n\n // Find the default export\n const defaultExport = extractDefaultExport(stripped);\n\n if (!defaultExport) {\n return {\n valid: false,\n error: {\n filePath,\n expression: '(no default export found)',\n suggestion:\n 'search-params.ts must have a default export. Use: export default createSearchParams({ ... })',\n },\n };\n }\n\n // Validate the expression\n if (isValidExpression(defaultExport.trim())) {\n return { valid: true };\n }\n\n return {\n valid: false,\n error: {\n filePath,\n expression: defaultExport.trim(),\n suggestion:\n 'The default export must be a createSearchParams() call, or a chain of ' +\n '.extend() / .pick() calls on a SearchParamsDefinition. Arbitrary factory ' +\n 'functions and runtime conditionals are not supported.',\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/** Strip single-line and multi-line comments from source. */\nfunction stripComments(source: string): string {\n // Remove multi-line comments\n let result = source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '');\n // Remove single-line comments\n result = result.replace(/\\/\\/.*$/gm, '');\n return result;\n}\n\n/**\n * Extract the expression from `export default <expr>`.\n *\n * Handles both:\n * export default createSearchParams(...)\n * export default expr\\n (terminated by newline or semicolon before next statement)\n */\nfunction extractDefaultExport(source: string): string | undefined {\n // Match `export default` followed by the expression\n const match = source.match(\n /export\\s+default\\s+([\\s\\S]+?)(?:;|\\n(?=export|import|const|let|var|function|class|type|interface|declare))/\n );\n if (match) {\n return match[1];\n }\n\n // Fallback: match everything after `export default` to end of file\n const fallback = source.match(/export\\s+default\\s+([\\s\\S]+)$/);\n if (fallback) {\n return fallback[1].replace(/;\\s*$/, '');\n }\n\n return undefined;\n}\n\n/**\n * Check if an expression is a valid statically-analyzable pattern.\n *\n * Valid patterns:\n * - Starts with `createSearchParams(`\n * - Contains `.extend(` or `.pick(` chains (possibly starting with createSearchParams or a variable)\n * - A variable identifier followed by chaining\n */\nfunction isValidExpression(expr: string): boolean {\n // Normalize whitespace\n const normalized = expr.replace(/\\s+/g, ' ').trim();\n\n // Pattern 1: starts with createSearchParams(\n if (normalized.startsWith('createSearchParams(')) {\n return true;\n }\n\n // Pattern 2: chain ending with .extend(...) or .pick(...)\n // This covers: someVar.extend(...), createSearchParams(...).extend(...).pick(...), etc.\n if (/\\.(extend|pick)\\s*\\(/.test(normalized)) {\n // Reject ternaries and other conditional patterns\n if (/\\?/.test(normalized) && /:/.test(normalized)) {\n return false;\n }\n // Reject function declarations/expressions\n if (/^\\s*(function|=>|\\()/.test(normalized)) {\n return false;\n }\n return true;\n }\n\n return false;\n}\n\n/**\n * Format an AnalyzeError into a human-readable build error message.\n */\nexport function formatAnalyzeError(error: AnalyzeError): string {\n return [\n `[timber] Non-analyzable search-params.ts`,\n ``,\n ` File: ${error.filePath}`,\n ` Expression: ${error.expression}`,\n ``,\n ` ${error.suggestion}`,\n ``,\n ` The framework must be able to statically extract the type from your`,\n ` search-params.ts at build time. Dynamic values, conditionals, and`,\n ` arbitrary factory functions prevent this analysis.`,\n ].join('\\n');\n}\n"],"mappings":";;;;;;;;;;;;;;;AAsHA,SAAS,aACP,KAC+C;AAC/C,KAAI,eAAe,iBAAiB;EAClC,MAAM,SAAwD,EAAE;AAChE,OAAK,MAAM,OAAO,IAAI,IAAI,IAAI,MAAM,CAAC,EAAE;GACrC,MAAM,SAAS,IAAI,OAAO,IAAI;AAC9B,UAAO,OAAO,OAAO,WAAW,IAAI,OAAO,KAAK;;AAElD,SAAO;;AAET,QAAO;;;;;;;AAQT,SAAS,qBAAwB,OAA2C;AAC1E,QAAO,MAAM,UAAU,MAAM,MAAM,KAAA,EAAU,CAAC;;;;;;;;;;;;;;;;;AAsBhD,SAAgB,mBACd,QACA,SAC8D;CAE9D,MAAM,UAAkC,EAAE;AAC1C,KAAI,SAAS;OACN,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,QAAQ,QAAQ,CAClD,KAAI,MAAM,KAAA,EAAW,SAAQ,KAAK;;AAItC,QAAO,gBAAmB,QAAkC,QAAQ;;;;;AAMtE,SAAS,gBACP,UACA,SAC2B;CAE3B,MAAM,oBAAmD,EAAE;AAC3D,MAAK,MAAM,OAAO,OAAO,KAAK,SAAS,CACrC,mBAAkB,OAAO,qBAAqB,SAAS,KAAgB;CAGzE,SAAS,UAAU,MAAsB;AACvC,SAAO,QAAQ,SAAS;;CAI1B,SAAS,MAAM,KAAyE;EACtF,MAAM,aAAa,aAAa,IAAI;EACpC,MAAM,SAAkC,EAAE;AAE1C,OAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,EAAE;GAExC,MAAM,WAAW,WADF,UAAU,KAAK;AAE9B,UAAO,QAAS,SAAS,MAA+C,MAAM,SAAS;;AAGzF,SAAO;;CAIT,SAAS,UAAU,QAA4B;EAC7C,MAAM,QAAkB,EAAE;AAE1B,OAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,EAAE;AACxC,OAAI,EAAE,QAAQ,QAAS;GAEvB,MAAM,aADQ,SAAS,MACE,UAAU,OAAO,MAA4B;AAGtE,OAAI,eAAe,kBAAkB,MAAO;AAC5C,OAAI,eAAe,KAAM;AAEzB,SAAM,KAAK,GAAG,mBAAmB,UAAU,KAAK,CAAC,CAAC,GAAG,mBAAmB,WAAW,GAAG;;AAGxF,SAAO,MAAM,KAAK,IAAI;;CAIxB,SAAS,KAAK,UAAkB,QAA4B;EAC1D,MAAM,KAAK,UAAU,OAAO;AAC5B,SAAO,KAAK,GAAG,SAAS,GAAG,OAAO;;CAIpC,SAAS,eAAe,QAAqC;EAC3D,MAAM,MAAM,IAAI,iBAAiB;AAEjC,OAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,EAAE;AACxC,OAAI,EAAE,QAAQ,QAAS;GAEvB,MAAM,aADQ,SAAS,MACE,UAAU,OAAO,MAA4B;AAEtE,OAAI,eAAe,kBAAkB,MAAO;AAC5C,OAAI,eAAe,KAAM;AAEzB,OAAI,IAAI,UAAU,KAAK,EAAE,WAAW;;AAGtC,SAAO;;CAIT,SAAS,OACP,WACA,eACkE;EAGlE,MAAM,iBAAiB;GACrB,GAAG;GACH,GAAG;GACJ;EAID,MAAM,kBAA0C,EAAE,GAAG,SAAS;AAC9D,MAAI,eAAe;QACZ,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,cAAc,QAAQ,CACxD,KAAI,MAAM,KAAA,EAAW,iBAAgB,KAAK;;AAI9C,SAAO,gBAA0B,gBAAgB,gBAAgB;;CAInE,SAAS,KAAiC,GAAG,MAA+C;EAC1F,MAAM,eAA0D,EAAE;EAClE,MAAM,gBAAwC,EAAE;AAEhD,OAAK,MAAM,OAAO,MAAM;AACtB,gBAAa,OAAO,SAAS;AAC7B,OAAI,OAAO,QACT,eAAc,OAAO,QAAQ;;AAIjC,SAAO,gBACL,cACA,cACD;;CAYH,SAAS,iBAAe,SAAiD;AACvE,SAAO,eAAqB,UAAU,SAAS,OAAO,OAAO,EAAE,GAAG,SAAS,CAAC,CAAC;;AAkB/E,QAZ8C;EAC5C;EACA,gBAAA;EACA;EACA;EACA;EACA;EACA;EACA,QAAQ;EACR,SAAS,OAAO,OAAO,EAAE,GAAG,SAAS,CAAC;EACvC;;;;;;;;;;ACxRH,SAAS,aACP,QACA,OAC8B;CAC9B,MAAM,SAAS,OAAO,aAAa,SAAS,MAAM;AAClD,KAAI,kBAAkB,QACpB,OAAM,IAAI,MACR,sGACD;AAEH,QAAO;;;;;;;;;;;;;;;;;;;AAwBT,SAAgB,WAAc,QAAkD;AAC9E,QAAO;EACL,MAAM,OAAyC;GAK7C,MAAM,SAAS,aAAa,QAHd,MAAM,QAAQ,MAAM,GAAG,MAAM,MAAM,SAAS,KAAK,MAGrB;AAC1C,OAAI,CAAC,OAAO,OACV,QAAO,OAAO;GAIhB,MAAM,gBAAgB,aAAa,QAAQ,KAAA,EAAU;AACrD,OAAI,CAAC,cAAc,OACjB,QAAO,cAAc;;EAOzB,UAAU,OAAyB;AACjC,OAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO;AAET,UAAO,OAAO,MAAM;;EAEvB;;;;;;;;;;;;;AAkBH,SAAgB,gBAAmB,QAAkD;AACnF,QAAO;EACL,MAAM,OAAyC;GAE7C,IAAI,QAAiB;AACrB,OAAI,OAAO,UAAU,SACnB,SAAQ,CAAC,MAAM;YACN,UAAU,KAAA,EACnB,SAAQ,KAAA;GAGV,MAAM,SAAS,aAAa,QAAQ,MAAM;AAC1C,OAAI,CAAC,OAAO,OACV,QAAO,OAAO;GAIhB,MAAM,gBAAgB,aAAa,QAAQ,KAAA,EAAU;AACrD,OAAI,CAAC,cAAc,OACjB,QAAO,cAAc;;EAMzB,UAAU,OAAyB;AACjC,OAAI,UAAU,QAAQ,UAAU,KAAA,EAC9B,QAAO;AAET,OAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,WAAW,IAAI,OAAO,MAAM,KAAK,IAAI;AAEpD,UAAO,OAAO,MAAM;;EAEvB;;;;;;;;AC/HH,SAAS,eAAe,OAA0D;AAChF,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,MAAM,SAAS,IAAI,MAAM,MAAM,SAAS,KAAK,KAAA;AAEtD,QAAO;;;;;;;;;;;;;AAkBT,IAAa,gBAAiD;CAC5D,MAAM,OAAqD;EACzD,MAAM,IAAI,eAAe,MAAM;AAC/B,SAAO,MAAM,KAAA,IAAY,IAAI;;CAE/B,UAAU,OAAqC;AAC7C,SAAO;;CAEV;;;;;;;;;;;;;;AAmBD,IAAa,iBAAkD;CAC7D,MAAM,OAAqD;EACzD,MAAM,IAAI,eAAe,MAAM;AAC/B,MAAI,MAAM,KAAA,KAAa,MAAM,GAAI,QAAO;EACxC,MAAM,IAAI,OAAO,EAAE;AACnB,MAAI,CAAC,OAAO,SAAS,EAAE,IAAI,CAAC,OAAO,UAAU,EAAE,CAAE,QAAO;AACxD,SAAO;;CAET,UAAU,OAAqC;AAC7C,SAAO,UAAU,OAAO,OAAO,OAAO,MAAM;;CAE/C;;;;;;;;;;;AAgBD,IAAa,eAAgD;CAC3D,MAAM,OAAqD;EACzD,MAAM,IAAI,eAAe,MAAM;AAC/B,MAAI,MAAM,KAAA,KAAa,MAAM,GAAI,QAAO;EACxC,MAAM,IAAI,OAAO,EAAE;AACnB,MAAI,CAAC,OAAO,SAAS,EAAE,CAAE,QAAO;AAChC,SAAO;;CAET,UAAU,OAAqC;AAC7C,SAAO,UAAU,OAAO,OAAO,OAAO,MAAM;;CAE/C;;;;;;;;;;;;;AAkBD,IAAa,iBAAmD;CAC9D,MAAM,OAAsD;EAC1D,MAAM,IAAI,eAAe,MAAM;AAC/B,MAAI,MAAM,KAAA,EAAW,QAAO;AAC5B,MAAI,MAAM,UAAU,MAAM,IAAK,QAAO;AACtC,MAAI,MAAM,WAAW,MAAM,IAAK,QAAO;AACvC,SAAO;;CAET,UAAU,OAAsC;AAC9C,SAAO,UAAU,OAAO,OAAO,OAAO,MAAM;;CAE/C;;;;;;;;;;;;;;AAmBD,SAAgB,kBACd,QAC4B;CAC5B,MAAM,UAAU,IAAI,IAAY,OAAO;AACvC,QAAO;EACL,MAAM,OAAgD;GACpD,MAAM,IAAI,eAAe,MAAM;AAC/B,OAAI,MAAM,KAAA,EAAW,QAAO;AAC5B,UAAO,QAAQ,IAAI,EAAE,GAAI,IAAU;;EAErC,UAAU,OAAgC;AACxC,UAAO;;EAEV;;;;;;;;;;;;;;AAmBH,SAAgB,qBACd,QACoC;AAEpC,QAAO,kBAA6B,OAAO;;;;;;;;;;;;;;AAmB7C,SAAgB,YACd,OACA,cACqB;AACrB,QAAO;EACL,MAAM,OAAyC;GAC7C,MAAM,SAAS,MAAM,MAAM,MAAM;AACjC,UAAO,WAAW,OAAO,eAAe;;EAE1C,UAAU,OAAyB;AACjC,UAAO,MAAM,UAAU,MAAM;;EAEhC;;;;;;;;;;;;;;;;;;;;;;;;;AChKH,SAAgB,oBAAoB,QAAgB,UAAiC;CAKnF,MAAM,gBAAgB,qBAHL,cAAc,OAAO,CAGc;AAEpD,KAAI,CAAC,cACH,QAAO;EACL,OAAO;EACP,OAAO;GACL;GACA,YAAY;GACZ,YACE;GACH;EACF;AAIH,KAAI,kBAAkB,cAAc,MAAM,CAAC,CACzC,QAAO,EAAE,OAAO,MAAM;AAGxB,QAAO;EACL,OAAO;EACP,OAAO;GACL;GACA,YAAY,cAAc,MAAM;GAChC,YACE;GAGH;EACF;;;AAQH,SAAS,cAAc,QAAwB;CAE7C,IAAI,SAAS,OAAO,QAAQ,qBAAqB,GAAG;AAEpD,UAAS,OAAO,QAAQ,aAAa,GAAG;AACxC,QAAO;;;;;;;;;AAUT,SAAS,qBAAqB,QAAoC;CAEhE,MAAM,QAAQ,OAAO,MACnB,6GACD;AACD,KAAI,MACF,QAAO,MAAM;CAIf,MAAM,WAAW,OAAO,MAAM,gCAAgC;AAC9D,KAAI,SACF,QAAO,SAAS,GAAG,QAAQ,SAAS,GAAG;;;;;;;;;;AAc3C,SAAS,kBAAkB,MAAuB;CAEhD,MAAM,aAAa,KAAK,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAGnD,KAAI,WAAW,WAAW,sBAAsB,CAC9C,QAAO;AAKT,KAAI,uBAAuB,KAAK,WAAW,EAAE;AAE3C,MAAI,KAAK,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,CAC/C,QAAO;AAGT,MAAI,uBAAuB,KAAK,WAAW,CACzC,QAAO;AAET,SAAO;;AAGT,QAAO;;;;;AAMT,SAAgB,mBAAmB,OAA6B;AAC9D,QAAO;EACL;EACA;EACA,WAAW,MAAM;EACjB,iBAAiB,MAAM;EACvB;EACA,KAAK,MAAM;EACX;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK"}
@@ -1,77 +0,0 @@
1
- /**
2
- * Pre-rendering types and utilities.
3
- *
4
- * A `prerender.ts` file in a route segment signals the framework to
5
- * pre-render the route's shell at build time. This module defines the
6
- * types that a user exports from `prerender.ts` and utilities for
7
- * loading and validating those exports.
8
- *
9
- * Design doc: design/15-future-prerendering.md
10
- */
11
- /**
12
- * The shape of a prerender.ts module's exports.
13
- *
14
- * ```ts
15
- * // app/docs/[slug]/prerender.ts
16
- * export async function generateParams() {
17
- * return docs.map(d => ({ slug: d.slug }))
18
- * }
19
- * export const ttl = '1h'
20
- * export const tags = ['docs']
21
- * ```
22
- */
23
- export interface PrerenderConfig {
24
- /**
25
- * Generate the set of params to pre-render at build time.
26
- * Required for dynamic segments (`[param]`).
27
- * Optional for static segments (the single URL is pre-rendered automatically).
28
- */
29
- generateParams?: () => Promise<Record<string, string>[]> | Record<string, string>[];
30
- /**
31
- * How long the pre-rendered shell is considered fresh.
32
- * Accepts duration strings ('30s', '5m', '1h', '2d', '1w') or seconds as a number.
33
- * Default: Infinity (cache until explicit invalidation).
34
- */
35
- ttl?: string | number;
36
- /**
37
- * Invalidation tags. Calling `revalidateTag('docs')` purges all
38
- * pre-rendered shells with that tag.
39
- */
40
- tags?: string[];
41
- /**
42
- * Fallback strategy for dynamic routes without `generateParams`.
43
- * Only valid in `output: 'static'` mode.
44
- * - `'shell'`: emit a single pre-rendered shell that serves as client-side fallback
45
- */
46
- fallback?: 'shell';
47
- }
48
- export interface ResolvedPrerenderConfig {
49
- /** TTL in seconds. Infinity if not set. */
50
- ttlSeconds: number;
51
- /** Invalidation tags */
52
- tags: string[];
53
- /** The generateParams function, if provided */
54
- generateParams?: () => Promise<Record<string, string>[]> | Record<string, string>[];
55
- /** Fallback strategy */
56
- fallback?: 'shell';
57
- }
58
- /**
59
- * Resolve raw prerender.ts exports into a normalized config.
60
- *
61
- * Validates:
62
- * - `ttl` is a valid duration string or number
63
- * - `tags` is an array of strings
64
- * - `fallback` is 'shell' or undefined
65
- */
66
- export declare function resolvePrerenderConfig(raw: PrerenderConfig): ResolvedPrerenderConfig;
67
- export interface PrerenderDiagnostic {
68
- type: 'DYNAMIC_SEGMENT_NO_PARAMS';
69
- segmentPath: string;
70
- message: string;
71
- }
72
- /**
73
- * Check if a dynamic segment has `generateParams` when prerender.ts is present.
74
- * If not, emit a diagnostic — the route falls back to SSR.
75
- */
76
- export declare function checkDynamicSegmentParams(segmentPath: string, isDynamic: boolean, hasGenerateParams: boolean, fallback?: 'shell'): PrerenderDiagnostic | null;
77
- //# sourceMappingURL=prerender.d.ts.map