@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":"prerender.d.ts","sourceRoot":"","sources":["../../src/server/prerender.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IAEpF;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEtB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAEhB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAMD,MAAM,WAAW,uBAAuB;IACtC,2CAA2C;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACpF,wBAAwB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,eAAe,GAAG,uBAAuB,CAsBpF;AAMD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,2BAA2B,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,OAAO,EAClB,iBAAiB,EAAE,OAAO,EAC1B,QAAQ,CAAC,EAAE,OAAO,GACjB,mBAAmB,GAAG,IAAI,CAc5B"}
@@ -1,53 +0,0 @@
1
- /**
2
- * Render-level response deduplication and short-TTL LRU cache.
3
- *
4
- * Two layers of optimization:
5
- *
6
- * 1. **Singleflight** — concurrent requests to the same URL share a single
7
- * render. Uses createSingleflight() from cache/singleflight.ts.
8
- *
9
- * 2. **LRU cache** — recently rendered responses are reused without
10
- * re-executing the RSC-to-SSR pipeline. Entries have a short TTL
11
- * (default 5s) and the cache has a bounded size (default 150 entries).
12
- *
13
- * Cache keys are compound: method + pathname + isRscPayload. Responses
14
- * with Set-Cookie headers are never cached (they contain user-specific
15
- * state). When `publicOnly` is true (default), requests with Cookie or
16
- * Authorization headers bypass the cache entirely.
17
- *
18
- * See design/02-rendering-pipeline.md, design/31-benchmarking.md.
19
- */
20
- export interface ResponseCacheConfig {
21
- /** Maximum number of entries in the LRU cache. Default: 150. */
22
- maxSize?: number;
23
- /** TTL for cached entries in milliseconds. Default: 5000 (5s). */
24
- ttlMs?: number;
25
- /**
26
- * When true (default), requests with Cookie or Authorization headers
27
- * bypass the cache entirely. This prevents sharing user-specific
28
- * responses across requests.
29
- */
30
- publicOnly?: boolean;
31
- }
32
- export interface ResolvedResponseCacheConfig {
33
- maxSize: number;
34
- ttlMs: number;
35
- publicOnly: boolean;
36
- }
37
- export declare function resolveResponseCacheConfig(config?: ResponseCacheConfig | false): ResolvedResponseCacheConfig | null;
38
- export interface ResponseCache {
39
- /**
40
- * Wrap a render function with singleflight dedup + LRU caching.
41
- * Returns the cached Response or executes the render function.
42
- */
43
- getOrRender(req: Request, isRscPayload: boolean, renderFn: () => Promise<Response>): Promise<Response>;
44
- /** Number of entries currently in the LRU cache. */
45
- readonly size: number;
46
- /** Clear all cached entries. */
47
- clear(): void;
48
- }
49
- /**
50
- * Create a response cache with singleflight deduplication and LRU caching.
51
- */
52
- export declare function createResponseCache(config: ResolvedResponseCacheConfig): ResponseCache;
53
- //# sourceMappingURL=response-cache.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"response-cache.d.ts","sourceRoot":"","sources":["../../src/server/response-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,0BAA0B,CACxC,MAAM,CAAC,EAAE,mBAAmB,GAAG,KAAK,GACnC,2BAA2B,GAAG,IAAI,CASpC;AAoFD,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,WAAW,CACT,GAAG,EAAE,OAAO,EACZ,YAAY,EAAE,OAAO,EACrB,QAAQ,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GAChC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAErB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,gCAAgC;IAChC,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,2BAA2B,GAAG,aAAa,CAqHtF"}
@@ -1,30 +0,0 @@
1
- 'use client';
2
-
3
- // LinkStatusProvider — client component that provides per-link pending status
4
- // via React context. Used inside <Link> to power useLinkStatus().
5
- //
6
- // Reads pendingUrl from PendingNavigationContext (provided by TransitionRoot).
7
- // The pending URL is set as an URGENT update at navigation start (shows
8
- // immediately) and cleared inside startTransition when the new tree commits
9
- // (atomic with params/pathname). This eliminates both:
10
- // 1. The delay before showing the spinner (urgent update, not deferred)
11
- // 2. The gap between spinner disappearing and active state updating (same commit)
12
-
13
- import type { ReactNode } from 'react';
14
- import { LinkStatusContext, type LinkStatus } from './use-link-status.js';
15
- import { usePendingNavigationUrl } from './navigation-context.js';
16
-
17
- const NOT_PENDING: LinkStatus = { pending: false };
18
- const IS_PENDING: LinkStatus = { pending: true };
19
-
20
- /**
21
- * Client component that reads the pending URL from PendingNavigationContext
22
- * and provides a scoped LinkStatusContext to children. Renders no extra DOM —
23
- * just a context provider around children.
24
- */
25
- export function LinkStatusProvider({ href, children }: { href: string; children?: ReactNode }) {
26
- const pendingUrl = usePendingNavigationUrl();
27
- const status = pendingUrl === href ? IS_PENDING : NOT_PENDING;
28
-
29
- return <LinkStatusContext.Provider value={status}>{children}</LinkStatusContext.Provider>;
30
- }
@@ -1,161 +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
-
17
- import type { Plugin } from 'vite';
18
- import type { PluginContext } from '#/index.js';
19
- import { findFunctionsWithDirective, containsDirective } from '#/utils/directive-parser.js';
20
-
21
- // ---------------------------------------------------------------------------
22
- // Detection
23
- // ---------------------------------------------------------------------------
24
-
25
- /**
26
- * Quick check: does this source file contain 'use dynamic' anywhere?
27
- * Used as a fast bail-out before doing expensive AST parsing.
28
- */
29
- export function containsUseDynamic(code: string): boolean {
30
- return containsDirective(code, 'use dynamic');
31
- }
32
-
33
- // ---------------------------------------------------------------------------
34
- // Transform
35
- // ---------------------------------------------------------------------------
36
-
37
- interface TransformResult {
38
- code: string;
39
- map?: null;
40
- }
41
-
42
- /**
43
- * Find function declarations/expressions containing 'use dynamic' and
44
- * transform them into markDynamic() calls.
45
- *
46
- * Input:
47
- * ```tsx
48
- * export default async function AddToCartButton({ productId }) {
49
- * 'use dynamic'
50
- * const user = await getUser()
51
- * return <button>Add to cart</button>
52
- * }
53
- * ```
54
- *
55
- * Output:
56
- * ```tsx
57
- * import { markDynamic as __markDynamic } from '@timber-js/app/runtime';
58
- * export default async function AddToCartButton({ productId }) {
59
- * __markDynamic();
60
- * const user = await getUser()
61
- * return <button>Add to cart</button>
62
- * }
63
- * ```
64
- *
65
- * The markDynamic() call registers the component boundary as dynamic
66
- * at render time. The pre-render pass uses this to know which subtrees
67
- * to skip and leave as holes for per-request rendering.
68
- */
69
- export function transformUseDynamic(code: string): TransformResult | null {
70
- if (!containsUseDynamic(code)) return null;
71
-
72
- const functions = findFunctionsWithDirective(code, 'use dynamic');
73
- if (functions.length === 0) return null;
74
-
75
- // Replace directive strings with __markDynamic() calls, processing
76
- // from end to start to preserve source offsets
77
- let result = code;
78
- for (const fn of functions) {
79
- // Replace the directive in the body content
80
- const cleanBody = fn.bodyContent.replace(/['"]use dynamic['"];?/, '__markDynamic();');
81
- // Reconstruct: replace the body content between braces
82
- result = result.slice(0, fn.bodyStart) + cleanBody + result.slice(fn.bodyEnd);
83
- }
84
-
85
- // Add the import at the top
86
- result = `import { markDynamic as __markDynamic } from '@timber-js/app/runtime';\n` + result;
87
-
88
- return { code: result, map: null };
89
- }
90
-
91
- // ---------------------------------------------------------------------------
92
- // Static mode validation
93
- // ---------------------------------------------------------------------------
94
-
95
- /**
96
- * In `output: 'static'` mode, `'use dynamic'` is a build error.
97
- * Static mode renders everything at build time — there is no per-request
98
- * rendering to opt into.
99
- */
100
- export function validateNoDynamicInStaticMode(
101
- code: string
102
- ): { message: string; line?: number } | null {
103
- if (!containsUseDynamic(code)) return null;
104
-
105
- const functions = findFunctionsWithDirective(code, 'use dynamic');
106
- if (functions.length === 0) return null;
107
-
108
- return {
109
- message:
110
- `'use dynamic' cannot be used in static mode (output: 'static'). ` +
111
- `Static mode renders all content at build time — there is no per-request rendering. ` +
112
- `Remove the directive or switch to output: 'server'.`,
113
- line: functions[functions.length - 1].directiveLine, // First occurrence (sorted descending)
114
- };
115
- }
116
-
117
- // ---------------------------------------------------------------------------
118
- // Vite Plugin
119
- // ---------------------------------------------------------------------------
120
-
121
- /**
122
- * Create the timber-dynamic-transform Vite plugin.
123
- *
124
- * In server mode: transforms 'use dynamic' into markDynamic() calls.
125
- * In static mode: rejects 'use dynamic' as a build error.
126
- */
127
- export function timberDynamicTransform(ctx: PluginContext): Plugin {
128
- const isStatic = ctx.config.output === 'static';
129
-
130
- return {
131
- name: 'timber-dynamic-transform',
132
-
133
- transform(code: string, id: string) {
134
- // Skip node_modules
135
- if (id.includes('node_modules')) return null;
136
-
137
- // Only check files in the app directory
138
- if (!id.includes('/app/') && !id.startsWith('app/')) return null;
139
-
140
- // Only check JS/TS files
141
- if (!/\.[jt]sx?$/.test(id)) return null;
142
-
143
- // Quick bail-out
144
- if (!containsUseDynamic(code)) return null;
145
-
146
- // In static mode, 'use dynamic' is a build error
147
- if (isStatic) {
148
- const error = validateNoDynamicInStaticMode(code);
149
- if (error) {
150
- this.error(
151
- `[timber] Static mode error in ${id}${error.line ? `:${error.line}` : ''}: ${error.message}`
152
- );
153
- }
154
- return null;
155
- }
156
-
157
- // In server mode, transform the directive
158
- return transformUseDynamic(code);
159
- },
160
- };
161
- }
@@ -1,192 +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
-
13
- // ---------------------------------------------------------------------------
14
- // Types
15
- // ---------------------------------------------------------------------------
16
-
17
- /** Result of analyzing a search-params.ts file. */
18
- export interface AnalyzeResult {
19
- /** Whether the file is statically analyzable. */
20
- valid: boolean;
21
- /** Error details when valid is false. */
22
- error?: AnalyzeError;
23
- }
24
-
25
- /** Diagnostic error for non-analyzable search-params.ts. */
26
- export interface AnalyzeError {
27
- /** Absolute file path. */
28
- filePath: string;
29
- /** Description of the non-analyzable expression. */
30
- expression: string;
31
- /** Suggested fix. */
32
- suggestion: string;
33
- }
34
-
35
- // ---------------------------------------------------------------------------
36
- // AST-free source analysis
37
- //
38
- // We use a lightweight regex-based approach to validate the structure of the
39
- // default export. This avoids requiring a TypeScript compiler instance at
40
- // build time for the initial validation pass. The full type extraction
41
- // (reading T from SearchParamsDefinition<T>) still happens via the TypeScript
42
- // compiler in the codegen step — this module just validates the *shape*.
43
- // ---------------------------------------------------------------------------
44
-
45
- /**
46
- * Patterns that indicate a valid default export:
47
- *
48
- * 1. `export default createSearchParams(...)`
49
- * 2. `export default someVar.extend(...)`
50
- * 3. `export default someVar.pick(...)`
51
- * 4. `export default someVar.extend(...).extend(...)` (chained)
52
- * 5. `export default someVar.extend(...).pick(...)` (chained)
53
- * 6. `export default createSearchParams(...).extend(...)`
54
- *
55
- * Invalid patterns:
56
- * - `export default someFunction(...)` (arbitrary factory)
57
- * - `export default condition ? a : b` (runtime conditional)
58
- * - `export default variable` (opaque reference without call)
59
- */
60
-
61
- /**
62
- * Analyze a search-params.ts file source for static analyzability.
63
- *
64
- * @param source - The file content as a string
65
- * @param filePath - Absolute path to the file (for diagnostics)
66
- */
67
- export function analyzeSearchParams(source: string, filePath: string): AnalyzeResult {
68
- // Strip comments to avoid false matches
69
- const stripped = stripComments(source);
70
-
71
- // Find the default export
72
- const defaultExport = extractDefaultExport(stripped);
73
-
74
- if (!defaultExport) {
75
- return {
76
- valid: false,
77
- error: {
78
- filePath,
79
- expression: '(no default export found)',
80
- suggestion:
81
- 'search-params.ts must have a default export. Use: export default createSearchParams({ ... })',
82
- },
83
- };
84
- }
85
-
86
- // Validate the expression
87
- if (isValidExpression(defaultExport.trim())) {
88
- return { valid: true };
89
- }
90
-
91
- return {
92
- valid: false,
93
- error: {
94
- filePath,
95
- expression: defaultExport.trim(),
96
- suggestion:
97
- 'The default export must be a createSearchParams() call, or a chain of ' +
98
- '.extend() / .pick() calls on a SearchParamsDefinition. Arbitrary factory ' +
99
- 'functions and runtime conditionals are not supported.',
100
- },
101
- };
102
- }
103
-
104
- // ---------------------------------------------------------------------------
105
- // Internal helpers
106
- // ---------------------------------------------------------------------------
107
-
108
- /** Strip single-line and multi-line comments from source. */
109
- function stripComments(source: string): string {
110
- // Remove multi-line comments
111
- let result = source.replace(/\/\*[\s\S]*?\*\//g, '');
112
- // Remove single-line comments
113
- result = result.replace(/\/\/.*$/gm, '');
114
- return result;
115
- }
116
-
117
- /**
118
- * Extract the expression from `export default <expr>`.
119
- *
120
- * Handles both:
121
- * export default createSearchParams(...)
122
- * export default expr\n (terminated by newline or semicolon before next statement)
123
- */
124
- function extractDefaultExport(source: string): string | undefined {
125
- // Match `export default` followed by the expression
126
- const match = source.match(
127
- /export\s+default\s+([\s\S]+?)(?:;|\n(?=export|import|const|let|var|function|class|type|interface|declare))/
128
- );
129
- if (match) {
130
- return match[1];
131
- }
132
-
133
- // Fallback: match everything after `export default` to end of file
134
- const fallback = source.match(/export\s+default\s+([\s\S]+)$/);
135
- if (fallback) {
136
- return fallback[1].replace(/;\s*$/, '');
137
- }
138
-
139
- return undefined;
140
- }
141
-
142
- /**
143
- * Check if an expression is a valid statically-analyzable pattern.
144
- *
145
- * Valid patterns:
146
- * - Starts with `createSearchParams(`
147
- * - Contains `.extend(` or `.pick(` chains (possibly starting with createSearchParams or a variable)
148
- * - A variable identifier followed by chaining
149
- */
150
- function isValidExpression(expr: string): boolean {
151
- // Normalize whitespace
152
- const normalized = expr.replace(/\s+/g, ' ').trim();
153
-
154
- // Pattern 1: starts with createSearchParams(
155
- if (normalized.startsWith('createSearchParams(')) {
156
- return true;
157
- }
158
-
159
- // Pattern 2: chain ending with .extend(...) or .pick(...)
160
- // This covers: someVar.extend(...), createSearchParams(...).extend(...).pick(...), etc.
161
- if (/\.(extend|pick)\s*\(/.test(normalized)) {
162
- // Reject ternaries and other conditional patterns
163
- if (/\?/.test(normalized) && /:/.test(normalized)) {
164
- return false;
165
- }
166
- // Reject function declarations/expressions
167
- if (/^\s*(function|=>|\()/.test(normalized)) {
168
- return false;
169
- }
170
- return true;
171
- }
172
-
173
- return false;
174
- }
175
-
176
- /**
177
- * Format an AnalyzeError into a human-readable build error message.
178
- */
179
- export function formatAnalyzeError(error: AnalyzeError): string {
180
- return [
181
- `[timber] Non-analyzable search-params.ts`,
182
- ``,
183
- ` File: ${error.filePath}`,
184
- ` Expression: ${error.expression}`,
185
- ``,
186
- ` ${error.suggestion}`,
187
- ``,
188
- ` The framework must be able to statically extract the type from your`,
189
- ` search-params.ts at build time. Dynamic values, conditionals, and`,
190
- ` arbitrary factory functions prevent this analysis.`,
191
- ].join('\n');
192
- }
@@ -1,228 +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
-
15
- import type { SearchParamCodec } from './create.js';
16
-
17
- // ---------------------------------------------------------------------------
18
- // Helpers
19
- // ---------------------------------------------------------------------------
20
-
21
- /**
22
- * Normalize array inputs to a single string (last value wins, matching
23
- * URLSearchParams.get() semantics). Returns undefined if absent or empty.
24
- */
25
- function normalizeInput(value: string | string[] | undefined): string | undefined {
26
- if (Array.isArray(value)) {
27
- return value.length > 0 ? value[value.length - 1] : undefined;
28
- }
29
- return value;
30
- }
31
-
32
- // ---------------------------------------------------------------------------
33
- // parseAsString
34
- // ---------------------------------------------------------------------------
35
-
36
- /**
37
- * String codec. Returns the raw string value, or null if absent.
38
- *
39
- * ```ts
40
- * import { parseAsString } from '@timber-js/app/search-params'
41
- *
42
- * const def = createSearchParams({ q: parseAsString })
43
- * // ?q=shoes → { q: 'shoes' }
44
- * // (absent) → { q: null }
45
- * ```
46
- */
47
- export const parseAsString: SearchParamCodec<string | null> = {
48
- parse(value: string | string[] | undefined): string | null {
49
- const v = normalizeInput(value);
50
- return v !== undefined ? v : null;
51
- },
52
- serialize(value: string | null): string | null {
53
- return value;
54
- },
55
- };
56
-
57
- // ---------------------------------------------------------------------------
58
- // parseAsInteger
59
- // ---------------------------------------------------------------------------
60
-
61
- /**
62
- * Integer codec. Parses a base-10 integer, or returns null if absent or
63
- * not a valid integer. Rejects floats, NaN, Infinity, and non-numeric strings.
64
- *
65
- * ```ts
66
- * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'
67
- *
68
- * const def = createSearchParams({ page: withDefault(parseAsInteger, 1) })
69
- * // ?page=2 → { page: 2 }
70
- * // ?page=abc → { page: 1 }
71
- * // (absent) → { page: 1 }
72
- * ```
73
- */
74
- export const parseAsInteger: SearchParamCodec<number | null> = {
75
- parse(value: string | string[] | undefined): number | null {
76
- const v = normalizeInput(value);
77
- if (v === undefined || v === '') return null;
78
- const n = Number(v);
79
- if (!Number.isFinite(n) || !Number.isInteger(n)) return null;
80
- return n;
81
- },
82
- serialize(value: number | null): string | null {
83
- return value === null ? null : String(value);
84
- },
85
- };
86
-
87
- // ---------------------------------------------------------------------------
88
- // parseAsFloat
89
- // ---------------------------------------------------------------------------
90
-
91
- /**
92
- * Float codec. Parses a finite number, or returns null if absent or invalid.
93
- * Rejects NaN and Infinity.
94
- *
95
- * ```ts
96
- * import { parseAsFloat, withDefault } from '@timber-js/app/search-params'
97
- *
98
- * const def = createSearchParams({ price: withDefault(parseAsFloat, 0) })
99
- * ```
100
- */
101
- export const parseAsFloat: SearchParamCodec<number | null> = {
102
- parse(value: string | string[] | undefined): number | null {
103
- const v = normalizeInput(value);
104
- if (v === undefined || v === '') return null;
105
- const n = Number(v);
106
- if (!Number.isFinite(n)) return null;
107
- return n;
108
- },
109
- serialize(value: number | null): string | null {
110
- return value === null ? null : String(value);
111
- },
112
- };
113
-
114
- // ---------------------------------------------------------------------------
115
- // parseAsBoolean
116
- // ---------------------------------------------------------------------------
117
-
118
- /**
119
- * Boolean codec. Accepts "true"/"1" as true, "false"/"0" as false.
120
- * Returns null for absent or unrecognized values.
121
- *
122
- * ```ts
123
- * import { parseAsBoolean, withDefault } from '@timber-js/app/search-params'
124
- *
125
- * const def = createSearchParams({ debug: withDefault(parseAsBoolean, false) })
126
- * // ?debug=true → { debug: true }
127
- * // ?debug=0 → { debug: false }
128
- * ```
129
- */
130
- export const parseAsBoolean: SearchParamCodec<boolean | null> = {
131
- parse(value: string | string[] | undefined): boolean | null {
132
- const v = normalizeInput(value);
133
- if (v === undefined) return null;
134
- if (v === 'true' || v === '1') return true;
135
- if (v === 'false' || v === '0') return false;
136
- return null;
137
- },
138
- serialize(value: boolean | null): string | null {
139
- return value === null ? null : String(value);
140
- },
141
- };
142
-
143
- // ---------------------------------------------------------------------------
144
- // parseAsStringEnum
145
- // ---------------------------------------------------------------------------
146
-
147
- /**
148
- * String enum codec. Accepts only values in the provided list.
149
- * Returns null for absent or invalid values.
150
- *
151
- * ```ts
152
- * import { parseAsStringEnum, withDefault } from '@timber-js/app/search-params'
153
- *
154
- * const sortCodec = withDefault(
155
- * parseAsStringEnum(['price', 'name', 'date']),
156
- * 'date'
157
- * )
158
- * ```
159
- */
160
- export function parseAsStringEnum<T extends string>(
161
- values: readonly T[]
162
- ): SearchParamCodec<T | null> {
163
- const allowed = new Set<string>(values);
164
- return {
165
- parse(value: string | string[] | undefined): T | null {
166
- const v = normalizeInput(value);
167
- if (v === undefined) return null;
168
- return allowed.has(v) ? (v as T) : null;
169
- },
170
- serialize(value: T | null): string | null {
171
- return value;
172
- },
173
- };
174
- }
175
-
176
- // ---------------------------------------------------------------------------
177
- // parseAsStringLiteral
178
- // ---------------------------------------------------------------------------
179
-
180
- /**
181
- * String literal codec. Functionally identical to parseAsStringEnum but
182
- * accepts `as const` tuples for narrower type inference.
183
- *
184
- * ```ts
185
- * import { parseAsStringLiteral } from '@timber-js/app/search-params'
186
- *
187
- * const sizes = ['sm', 'md', 'lg', 'xl'] as const
188
- * const codec = parseAsStringLiteral(sizes)
189
- * // Type: SearchParamCodec<'sm' | 'md' | 'lg' | 'xl' | null>
190
- * ```
191
- */
192
- export function parseAsStringLiteral<const T extends readonly string[]>(
193
- values: T
194
- ): SearchParamCodec<T[number] | null> {
195
- // Delegates to parseAsStringEnum — same runtime behavior, different type
196
- return parseAsStringEnum<T[number]>(values);
197
- }
198
-
199
- // ---------------------------------------------------------------------------
200
- // withDefault
201
- // ---------------------------------------------------------------------------
202
-
203
- /**
204
- * Wrap a nullable codec with a default value. When the inner codec returns
205
- * null, the default is used instead. The output type becomes non-nullable.
206
- *
207
- * ```ts
208
- * import { parseAsInteger, withDefault } from '@timber-js/app/search-params'
209
- *
210
- * const page = withDefault(parseAsInteger, 1)
211
- * // page.parse(undefined) → 1 (not null)
212
- * // page.parse('5') → 5
213
- * ```
214
- */
215
- export function withDefault<T>(
216
- codec: SearchParamCodec<T | null>,
217
- defaultValue: T
218
- ): SearchParamCodec<T> {
219
- return {
220
- parse(value: string | string[] | undefined): T {
221
- const result = codec.parse(value);
222
- return result === null ? defaultValue : result;
223
- },
224
- serialize(value: T): string | null {
225
- return codec.serialize(value);
226
- },
227
- };
228
- }