@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.71

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 (500) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-BJARkOcu.js} +1 -1
  3. package/dist/_chunks/als-registry-BJARkOcu.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-CGuYoRHU.js +199 -0
  8. package/dist/_chunks/define-CGuYoRHU.js.map +1 -0
  9. package/dist/_chunks/define-Dz1bqwaS.js +106 -0
  10. package/dist/_chunks/define-Dz1bqwaS.js.map +1 -0
  11. package/dist/_chunks/define-cookie-B5mewxwM.js +93 -0
  12. package/dist/_chunks/define-cookie-B5mewxwM.js.map +1 -0
  13. package/dist/_chunks/error-boundary-D9hzsveV.js +216 -0
  14. package/dist/_chunks/error-boundary-D9hzsveV.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → format-Rn922VH2.js} +3 -20
  16. package/dist/_chunks/format-Rn922VH2.js.map +1 -0
  17. package/dist/_chunks/{tracing-Cwn7697K.js → handler-store-BVePM7hp.js} +68 -3
  18. package/dist/_chunks/handler-store-BVePM7hp.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-CEdHHviP.js} +171 -97
  20. package/dist/_chunks/interception-CEdHHviP.js.map +1 -0
  21. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  23. package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-CywiO4jV.js} +181 -69
  24. package/dist/_chunks/request-context-CywiO4jV.js.map +1 -0
  25. package/dist/_chunks/schema-bridge-C4SwjCQD.js +86 -0
  26. package/dist/_chunks/schema-bridge-C4SwjCQD.js.map +1 -0
  27. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  29. package/dist/_chunks/segment-context-hzuJ048X.js +72 -0
  30. package/dist/_chunks/segment-context-hzuJ048X.js.map +1 -0
  31. package/dist/_chunks/stale-reload-BLUC_Pl_.js +64 -0
  32. package/dist/_chunks/stale-reload-BLUC_Pl_.js.map +1 -0
  33. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DAhgj8Gx.js} +1 -1
  34. package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +1 -0
  35. package/dist/_chunks/wrappers-LZbghvn0.js +63 -0
  36. package/dist/_chunks/wrappers-LZbghvn0.js.map +1 -0
  37. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  38. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  39. package/dist/adapters/cloudflare-dev.js +73 -0
  40. package/dist/adapters/cloudflare-dev.js.map +1 -0
  41. package/dist/adapters/cloudflare.d.ts +148 -12
  42. package/dist/adapters/cloudflare.d.ts.map +1 -1
  43. package/dist/adapters/cloudflare.js +135 -11
  44. package/dist/adapters/cloudflare.js.map +1 -1
  45. package/dist/adapters/compress-module.d.ts.map +1 -1
  46. package/dist/adapters/nitro.d.ts +17 -1
  47. package/dist/adapters/nitro.d.ts.map +1 -1
  48. package/dist/adapters/nitro.js +56 -13
  49. package/dist/adapters/nitro.js.map +1 -1
  50. package/dist/cache/cache-api.d.ts +24 -0
  51. package/dist/cache/cache-api.d.ts.map +1 -0
  52. package/dist/cache/fast-hash.d.ts +22 -0
  53. package/dist/cache/fast-hash.d.ts.map +1 -0
  54. package/dist/cache/handler-store.d.ts +31 -0
  55. package/dist/cache/handler-store.d.ts.map +1 -0
  56. package/dist/cache/index.d.ts +7 -5
  57. package/dist/cache/index.d.ts.map +1 -1
  58. package/dist/cache/index.js +111 -73
  59. package/dist/cache/index.js.map +1 -1
  60. package/dist/cache/singleflight.d.ts +18 -1
  61. package/dist/cache/singleflight.d.ts.map +1 -1
  62. package/dist/cache/timber-cache.d.ts +1 -1
  63. package/dist/cache/timber-cache.d.ts.map +1 -1
  64. package/dist/client/error-boundary.d.ts +12 -5
  65. package/dist/client/error-boundary.d.ts.map +1 -1
  66. package/dist/client/error-boundary.js +1 -125
  67. package/dist/client/error-reconstituter.d.ts +54 -0
  68. package/dist/client/error-reconstituter.d.ts.map +1 -0
  69. package/dist/client/form.d.ts +2 -2
  70. package/dist/client/form.d.ts.map +1 -1
  71. package/dist/client/history.d.ts +19 -4
  72. package/dist/client/history.d.ts.map +1 -1
  73. package/dist/client/index.d.ts +6 -5
  74. package/dist/client/index.d.ts.map +1 -1
  75. package/dist/client/index.js +537 -166
  76. package/dist/client/index.js.map +1 -1
  77. package/dist/client/link-pending-store.d.ts +78 -0
  78. package/dist/client/link-pending-store.d.ts.map +1 -0
  79. package/dist/client/link.d.ts +90 -32
  80. package/dist/client/link.d.ts.map +1 -1
  81. package/dist/client/nav-link-store.d.ts +36 -0
  82. package/dist/client/nav-link-store.d.ts.map +1 -0
  83. package/dist/client/navigation-api-types.d.ts +90 -0
  84. package/dist/client/navigation-api-types.d.ts.map +1 -0
  85. package/dist/client/navigation-api.d.ts +115 -0
  86. package/dist/client/navigation-api.d.ts.map +1 -0
  87. package/dist/client/navigation-context.d.ts +13 -2
  88. package/dist/client/navigation-context.d.ts.map +1 -1
  89. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  90. package/dist/client/navigation-root.d.ts.map +1 -0
  91. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  92. package/dist/client/router.d.ts +70 -4
  93. package/dist/client/router.d.ts.map +1 -1
  94. package/dist/client/rsc-fetch.d.ts +38 -3
  95. package/dist/client/rsc-fetch.d.ts.map +1 -1
  96. package/dist/client/segment-cache.d.ts +1 -1
  97. package/dist/client/segment-cache.d.ts.map +1 -1
  98. package/dist/client/segment-context.d.ts +1 -1
  99. package/dist/client/segment-context.d.ts.map +1 -1
  100. package/dist/client/segment-merger.d.ts.map +1 -1
  101. package/dist/client/segment-outlet.d.ts +63 -0
  102. package/dist/client/segment-outlet.d.ts.map +1 -0
  103. package/dist/client/ssr-data.d.ts +13 -4
  104. package/dist/client/ssr-data.d.ts.map +1 -1
  105. package/dist/client/stale-reload.d.ts +15 -0
  106. package/dist/client/stale-reload.d.ts.map +1 -1
  107. package/dist/client/top-loader.d.ts +3 -3
  108. package/dist/client/top-loader.d.ts.map +1 -1
  109. package/dist/client/use-params.d.ts +6 -4
  110. package/dist/client/use-params.d.ts.map +1 -1
  111. package/dist/client/use-query-states.d.ts +1 -1
  112. package/dist/client/use-query-states.d.ts.map +1 -1
  113. package/dist/codec.d.ts +23 -0
  114. package/dist/codec.d.ts.map +1 -0
  115. package/dist/codec.js +2 -0
  116. package/dist/cookies/define-cookie.d.ts +35 -14
  117. package/dist/cookies/define-cookie.d.ts.map +1 -1
  118. package/dist/cookies/index.d.ts +2 -0
  119. package/dist/cookies/index.d.ts.map +1 -1
  120. package/dist/cookies/index.js +3 -84
  121. package/dist/fonts/css.d.ts +1 -0
  122. package/dist/fonts/css.d.ts.map +1 -1
  123. package/dist/index.d.ts +154 -38
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +12092 -11916
  126. package/dist/index.js.map +1 -1
  127. package/dist/plugins/adapter-build.d.ts +1 -1
  128. package/dist/plugins/adapter-build.d.ts.map +1 -1
  129. package/dist/plugins/build-manifest.d.ts +2 -2
  130. package/dist/plugins/build-manifest.d.ts.map +1 -1
  131. package/dist/plugins/build-report.d.ts +3 -3
  132. package/dist/plugins/build-report.d.ts.map +1 -1
  133. package/dist/plugins/client-chunks.d.ts +32 -0
  134. package/dist/plugins/client-chunks.d.ts.map +1 -0
  135. package/dist/plugins/content.d.ts +1 -1
  136. package/dist/plugins/content.d.ts.map +1 -1
  137. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  138. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  139. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  140. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  141. package/dist/plugins/dev-logs.d.ts +1 -1
  142. package/dist/plugins/dev-logs.d.ts.map +1 -1
  143. package/dist/plugins/dev-server.d.ts +1 -1
  144. package/dist/plugins/dev-server.d.ts.map +1 -1
  145. package/dist/plugins/entries.d.ts +1 -1
  146. package/dist/plugins/entries.d.ts.map +1 -1
  147. package/dist/plugins/fonts.d.ts +19 -5
  148. package/dist/plugins/fonts.d.ts.map +1 -1
  149. package/dist/plugins/mdx.d.ts +1 -1
  150. package/dist/plugins/mdx.d.ts.map +1 -1
  151. package/dist/plugins/routing.d.ts +1 -1
  152. package/dist/plugins/routing.d.ts.map +1 -1
  153. package/dist/plugins/server-bundle.d.ts.map +1 -1
  154. package/dist/plugins/shims.d.ts +6 -5
  155. package/dist/plugins/shims.d.ts.map +1 -1
  156. package/dist/plugins/static-build.d.ts +1 -1
  157. package/dist/plugins/static-build.d.ts.map +1 -1
  158. package/dist/routing/codegen.d.ts +2 -2
  159. package/dist/routing/codegen.d.ts.map +1 -1
  160. package/dist/routing/index.d.ts +2 -0
  161. package/dist/routing/index.d.ts.map +1 -1
  162. package/dist/routing/index.js +3 -2
  163. package/dist/routing/scanner.d.ts.map +1 -1
  164. package/dist/routing/segment-classify.d.ts +46 -0
  165. package/dist/routing/segment-classify.d.ts.map +1 -0
  166. package/dist/routing/status-file-lint.d.ts +2 -1
  167. package/dist/routing/status-file-lint.d.ts.map +1 -1
  168. package/dist/routing/types.d.ts +16 -4
  169. package/dist/routing/types.d.ts.map +1 -1
  170. package/dist/rsc-runtime/rsc.d.ts +1 -1
  171. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  172. package/dist/rsc-runtime/ssr.d.ts +12 -0
  173. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  174. package/dist/schema-bridge.d.ts +76 -0
  175. package/dist/schema-bridge.d.ts.map +1 -0
  176. package/dist/search-params/define.d.ts +139 -0
  177. package/dist/search-params/define.d.ts.map +1 -0
  178. package/dist/search-params/index.d.ts +4 -6
  179. package/dist/search-params/index.d.ts.map +1 -1
  180. package/dist/search-params/index.js +4 -474
  181. package/dist/search-params/registry.d.ts +1 -1
  182. package/dist/search-params/wrappers.d.ts +53 -0
  183. package/dist/search-params/wrappers.d.ts.map +1 -0
  184. package/dist/segment-params/define.d.ts +78 -0
  185. package/dist/segment-params/define.d.ts.map +1 -0
  186. package/dist/segment-params/index.d.ts +7 -0
  187. package/dist/segment-params/index.d.ts.map +1 -0
  188. package/dist/segment-params/index.js +4 -0
  189. package/dist/server/access-gate.d.ts +4 -0
  190. package/dist/server/access-gate.d.ts.map +1 -1
  191. package/dist/server/action-client.d.ts +12 -1
  192. package/dist/server/action-client.d.ts.map +1 -1
  193. package/dist/server/action-encryption.d.ts +76 -0
  194. package/dist/server/action-encryption.d.ts.map +1 -0
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +3 -6
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +32 -4
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/build-manifest.d.ts +2 -2
  201. package/dist/server/build-manifest.d.ts.map +1 -1
  202. package/dist/server/debug.d.ts +1 -1
  203. package/dist/server/default-logger.d.ts +22 -0
  204. package/dist/server/default-logger.d.ts.map +1 -0
  205. package/dist/server/deny-page-resolver.d.ts +52 -0
  206. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  207. package/dist/server/deny-renderer.d.ts.map +1 -1
  208. package/dist/server/dev-warnings.d.ts +0 -14
  209. package/dist/server/dev-warnings.d.ts.map +1 -1
  210. package/dist/server/early-hints.d.ts +13 -5
  211. package/dist/server/early-hints.d.ts.map +1 -1
  212. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  213. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  214. package/dist/server/fallback-error.d.ts +4 -3
  215. package/dist/server/fallback-error.d.ts.map +1 -1
  216. package/dist/server/flight-injection-state.d.ts +66 -0
  217. package/dist/server/flight-injection-state.d.ts.map +1 -0
  218. package/dist/server/flight-scripts.d.ts +42 -0
  219. package/dist/server/flight-scripts.d.ts.map +1 -0
  220. package/dist/server/flush.d.ts.map +1 -1
  221. package/dist/server/form-data.d.ts +29 -0
  222. package/dist/server/form-data.d.ts.map +1 -1
  223. package/dist/server/html-injectors.d.ts +51 -11
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +5 -3
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +2176 -1663
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/logger.d.ts +25 -7
  230. package/dist/server/logger.d.ts.map +1 -1
  231. package/dist/server/middleware-runner.d.ts +19 -4
  232. package/dist/server/middleware-runner.d.ts.map +1 -1
  233. package/dist/server/node-stream-transforms.d.ts +113 -0
  234. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  235. package/dist/server/page-deny-boundary.d.ts +31 -0
  236. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  237. package/dist/server/pipeline-interception.d.ts +1 -1
  238. package/dist/server/pipeline-interception.d.ts.map +1 -1
  239. package/dist/server/pipeline-metadata.d.ts +6 -0
  240. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  241. package/dist/server/pipeline.d.ts +32 -10
  242. package/dist/server/pipeline.d.ts.map +1 -1
  243. package/dist/server/primitives.d.ts +30 -3
  244. package/dist/server/primitives.d.ts.map +1 -1
  245. package/dist/server/render-timeout.d.ts +51 -0
  246. package/dist/server/render-timeout.d.ts.map +1 -0
  247. package/dist/server/request-context.d.ts +76 -37
  248. package/dist/server/request-context.d.ts.map +1 -1
  249. package/dist/server/route-element-builder.d.ts +27 -1
  250. package/dist/server/route-element-builder.d.ts.map +1 -1
  251. package/dist/server/route-handler.d.ts.map +1 -1
  252. package/dist/server/route-matcher.d.ts +9 -2
  253. package/dist/server/route-matcher.d.ts.map +1 -1
  254. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  255. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  256. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  257. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  258. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  259. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  260. package/dist/server/rsc-entry/index.d.ts +8 -3
  261. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  262. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  263. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  264. package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
  265. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  266. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  267. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  268. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  269. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  270. package/dist/server/safe-load.d.ts +46 -0
  271. package/dist/server/safe-load.d.ts.map +1 -0
  272. package/dist/server/sitemap-generator.d.ts +129 -0
  273. package/dist/server/sitemap-generator.d.ts.map +1 -0
  274. package/dist/server/sitemap-handler.d.ts +22 -0
  275. package/dist/server/sitemap-handler.d.ts.map +1 -0
  276. package/dist/server/slot-resolver.d.ts +1 -1
  277. package/dist/server/slot-resolver.d.ts.map +1 -1
  278. package/dist/server/ssr-entry.d.ts +22 -0
  279. package/dist/server/ssr-entry.d.ts.map +1 -1
  280. package/dist/server/ssr-render.d.ts +39 -21
  281. package/dist/server/ssr-render.d.ts.map +1 -1
  282. package/dist/server/ssr-wrappers.d.ts +50 -0
  283. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  284. package/dist/server/status-code-resolver.d.ts +1 -1
  285. package/dist/server/status-code-resolver.d.ts.map +1 -1
  286. package/dist/server/stream-utils.d.ts +36 -0
  287. package/dist/server/stream-utils.d.ts.map +1 -0
  288. package/dist/server/tracing.d.ts +10 -0
  289. package/dist/server/tracing.d.ts.map +1 -1
  290. package/dist/server/tree-builder.d.ts +22 -19
  291. package/dist/server/tree-builder.d.ts.map +1 -1
  292. package/dist/server/types.d.ts +1 -4
  293. package/dist/server/types.d.ts.map +1 -1
  294. package/dist/server/version-skew.d.ts +61 -0
  295. package/dist/server/version-skew.d.ts.map +1 -0
  296. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  297. package/dist/shared/merge-search-params.d.ts +22 -0
  298. package/dist/shared/merge-search-params.d.ts.map +1 -0
  299. package/dist/shims/font-google.d.ts +1 -1
  300. package/dist/shims/font-google.d.ts.map +1 -1
  301. package/dist/shims/font-google.js +42 -0
  302. package/dist/shims/font-google.js.map +1 -0
  303. package/dist/shims/font-local.d.ts +26 -0
  304. package/dist/shims/font-local.d.ts.map +1 -0
  305. package/dist/shims/font-local.js +20 -0
  306. package/dist/shims/font-local.js.map +1 -0
  307. package/dist/shims/navigation-client.d.ts +1 -1
  308. package/dist/shims/navigation-client.d.ts.map +1 -1
  309. package/dist/shims/navigation.d.ts +1 -1
  310. package/dist/shims/navigation.d.ts.map +1 -1
  311. package/dist/utils/directive-parser.d.ts +5 -2
  312. package/dist/utils/directive-parser.d.ts.map +1 -1
  313. package/dist/utils/state-machine.d.ts +80 -0
  314. package/dist/utils/state-machine.d.ts.map +1 -0
  315. package/package.json +37 -17
  316. package/src/adapters/cloudflare-dev.ts +177 -0
  317. package/src/adapters/cloudflare.ts +342 -28
  318. package/src/adapters/compress-module.ts +24 -4
  319. package/src/adapters/nitro.ts +58 -9
  320. package/src/adapters/wrangler.d.ts +7 -0
  321. package/src/cache/cache-api.ts +38 -0
  322. package/src/cache/fast-hash.ts +34 -0
  323. package/src/cache/handler-store.ts +68 -0
  324. package/src/cache/index.ts +9 -5
  325. package/src/cache/singleflight.ts +62 -4
  326. package/src/cache/timber-cache.ts +40 -29
  327. package/src/cli.ts +0 -0
  328. package/src/client/browser-entry.ts +314 -142
  329. package/src/client/error-boundary.tsx +48 -16
  330. package/src/client/error-reconstituter.tsx +65 -0
  331. package/src/client/form.tsx +2 -2
  332. package/src/client/history.ts +26 -4
  333. package/src/client/index.ts +13 -4
  334. package/src/client/link-pending-store.ts +136 -0
  335. package/src/client/link.tsx +346 -105
  336. package/src/client/nav-link-store.ts +47 -0
  337. package/src/client/navigation-api-types.ts +112 -0
  338. package/src/client/navigation-api.ts +332 -0
  339. package/src/client/navigation-context.ts +27 -6
  340. package/src/client/navigation-root.tsx +346 -0
  341. package/src/client/nuqs-adapter.tsx +16 -3
  342. package/src/client/router.ts +302 -77
  343. package/src/client/rsc-fetch.ts +93 -5
  344. package/src/client/segment-cache.ts +1 -1
  345. package/src/client/segment-context.ts +6 -1
  346. package/src/client/segment-merger.ts +2 -8
  347. package/src/client/segment-outlet.tsx +86 -0
  348. package/src/client/ssr-data.ts +13 -5
  349. package/src/client/stale-reload.ts +73 -6
  350. package/src/client/top-loader.tsx +22 -13
  351. package/src/client/use-navigation-pending.ts +1 -1
  352. package/src/client/use-params.ts +7 -5
  353. package/src/client/use-query-states.ts +2 -2
  354. package/src/codec.ts +34 -0
  355. package/src/cookies/define-cookie.ts +72 -21
  356. package/src/cookies/index.ts +7 -0
  357. package/src/fonts/css.ts +2 -1
  358. package/src/index.ts +328 -92
  359. package/src/plugins/adapter-build.ts +8 -2
  360. package/src/plugins/build-manifest.ts +13 -2
  361. package/src/plugins/build-report.ts +3 -3
  362. package/src/plugins/client-chunks.ts +65 -0
  363. package/src/plugins/content.ts +1 -1
  364. package/src/plugins/dev-browser-logs.ts +288 -0
  365. package/src/plugins/dev-error-overlay.ts +70 -1
  366. package/src/plugins/dev-logs.ts +1 -1
  367. package/src/plugins/dev-server.ts +55 -9
  368. package/src/plugins/entries.ts +70 -9
  369. package/src/plugins/fonts.ts +167 -61
  370. package/src/plugins/mdx.ts +1 -1
  371. package/src/plugins/routing.ts +57 -17
  372. package/src/plugins/server-action-exports.ts +1 -1
  373. package/src/plugins/server-bundle.ts +32 -1
  374. package/src/plugins/shims.ts +76 -33
  375. package/src/plugins/static-build.ts +10 -6
  376. package/src/routing/codegen.ts +165 -105
  377. package/src/routing/index.ts +2 -0
  378. package/src/routing/scanner.ts +93 -23
  379. package/src/routing/segment-classify.ts +89 -0
  380. package/src/routing/status-file-lint.ts +3 -2
  381. package/src/routing/types.ts +17 -4
  382. package/src/rsc-runtime/rsc.ts +2 -0
  383. package/src/rsc-runtime/ssr.ts +50 -0
  384. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  385. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  386. package/src/search-params/define.ts +482 -0
  387. package/src/search-params/index.ts +13 -19
  388. package/src/search-params/registry.ts +1 -1
  389. package/src/search-params/wrappers.ts +85 -0
  390. package/src/segment-params/define.ts +279 -0
  391. package/src/segment-params/index.ts +28 -0
  392. package/src/server/access-gate.tsx +70 -29
  393. package/src/server/action-client.ts +28 -3
  394. package/src/server/action-encryption.ts +144 -0
  395. package/src/server/action-handler.ts +20 -3
  396. package/src/server/actions.ts +10 -9
  397. package/src/server/als-registry.ts +32 -4
  398. package/src/server/build-manifest.ts +10 -4
  399. package/src/server/compress.ts +25 -7
  400. package/src/server/debug.ts +1 -1
  401. package/src/server/default-logger.ts +99 -0
  402. package/src/server/deny-page-resolver.ts +154 -0
  403. package/src/server/deny-renderer.ts +24 -38
  404. package/src/server/dev-warnings.ts +2 -28
  405. package/src/server/early-hints.ts +36 -15
  406. package/src/server/error-boundary-wrapper.ts +74 -22
  407. package/src/server/fallback-error.ts +31 -15
  408. package/src/server/flight-injection-state.ts +113 -0
  409. package/src/server/flight-scripts.ts +62 -0
  410. package/src/server/flush.ts +2 -1
  411. package/src/server/form-data.ts +76 -0
  412. package/src/server/html-injectors.ts +277 -117
  413. package/src/server/index.ts +9 -5
  414. package/src/server/logger.ts +44 -36
  415. package/src/server/middleware-runner.ts +31 -4
  416. package/src/server/node-stream-transforms.ts +509 -0
  417. package/src/server/page-deny-boundary.tsx +56 -0
  418. package/src/server/pipeline-interception.ts +17 -16
  419. package/src/server/pipeline-metadata.ts +13 -0
  420. package/src/server/pipeline.ts +195 -51
  421. package/src/server/primitives.ts +47 -5
  422. package/src/server/render-timeout.ts +108 -0
  423. package/src/server/request-context.ts +240 -117
  424. package/src/server/route-element-builder.ts +284 -197
  425. package/src/server/route-handler.ts +24 -4
  426. package/src/server/route-matcher.ts +24 -20
  427. package/src/server/rsc-entry/api-handler.ts +15 -16
  428. package/src/server/rsc-entry/error-renderer.ts +300 -89
  429. package/src/server/rsc-entry/helpers.ts +134 -5
  430. package/src/server/rsc-entry/index.ts +202 -113
  431. package/src/server/rsc-entry/rsc-payload.ts +100 -21
  432. package/src/server/rsc-entry/rsc-stream.ts +74 -18
  433. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  434. package/src/server/rsc-entry/ssr-renderer.ts +173 -40
  435. package/src/server/safe-load.ts +60 -0
  436. package/src/server/sitemap-generator.ts +338 -0
  437. package/src/server/sitemap-handler.ts +126 -0
  438. package/src/server/slot-resolver.ts +243 -228
  439. package/src/server/ssr-entry.ts +211 -32
  440. package/src/server/ssr-render.ts +289 -67
  441. package/src/server/ssr-wrappers.tsx +139 -0
  442. package/src/server/status-code-resolver.ts +1 -1
  443. package/src/server/stream-utils.ts +213 -0
  444. package/src/server/tracing.ts +37 -3
  445. package/src/server/tree-builder.ts +92 -58
  446. package/src/server/types.ts +3 -6
  447. package/src/server/version-skew.ts +104 -0
  448. package/src/server/waituntil-bridge.ts +4 -1
  449. package/src/shared/merge-search-params.ts +55 -0
  450. package/src/shims/font-google.ts +1 -1
  451. package/src/shims/font-local.ts +34 -0
  452. package/src/shims/navigation-client.ts +1 -1
  453. package/src/shims/navigation.ts +2 -1
  454. package/src/utils/directive-parser.ts +5 -2
  455. package/src/utils/state-machine.ts +111 -0
  456. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  457. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  458. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  459. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  460. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  461. package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
  462. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  463. package/dist/_chunks/tracing-Cwn7697K.js.map +0 -1
  464. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  465. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  466. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  467. package/dist/cache/register-cached-function.d.ts +0 -17
  468. package/dist/cache/register-cached-function.d.ts.map +0 -1
  469. package/dist/client/error-boundary.js.map +0 -1
  470. package/dist/client/link-status-provider.d.ts +0 -11
  471. package/dist/client/link-status-provider.d.ts.map +0 -1
  472. package/dist/client/transition-root.d.ts.map +0 -1
  473. package/dist/cookies/index.js.map +0 -1
  474. package/dist/plugins/cache-transform.d.ts +0 -36
  475. package/dist/plugins/cache-transform.d.ts.map +0 -1
  476. package/dist/plugins/dynamic-transform.d.ts +0 -72
  477. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  478. package/dist/search-params/analyze.d.ts +0 -54
  479. package/dist/search-params/analyze.d.ts.map +0 -1
  480. package/dist/search-params/builtin-codecs.d.ts +0 -105
  481. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  482. package/dist/search-params/codecs.d.ts +0 -53
  483. package/dist/search-params/codecs.d.ts.map +0 -1
  484. package/dist/search-params/create.d.ts +0 -106
  485. package/dist/search-params/create.d.ts.map +0 -1
  486. package/dist/search-params/index.js.map +0 -1
  487. package/dist/server/prerender.d.ts +0 -77
  488. package/dist/server/prerender.d.ts.map +0 -1
  489. package/dist/server/response-cache.d.ts +0 -53
  490. package/dist/server/response-cache.d.ts.map +0 -1
  491. package/src/cache/register-cached-function.ts +0 -99
  492. package/src/client/link-status-provider.tsx +0 -30
  493. package/src/client/transition-root.tsx +0 -160
  494. package/src/plugins/cache-transform.ts +0 -199
  495. package/src/plugins/dynamic-transform.ts +0 -161
  496. package/src/search-params/analyze.ts +0 -192
  497. package/src/search-params/builtin-codecs.ts +0 -228
  498. package/src/search-params/create.ts +0 -321
  499. package/src/server/prerender.ts +0 -139
  500. package/src/server/response-cache.ts +0 -277
@@ -7,6 +7,179 @@
7
7
  * Design docs: 02-rendering-pipeline.md, 18-build-system.md §"Entry Files"
8
8
  */
9
9
 
10
+ // ─── Buffered Transform ──────────────────────────────────────────────────────
11
+
12
+ /**
13
+ * Options for the buffered transform stream.
14
+ */
15
+ export interface BufferedTransformOptions {
16
+ /**
17
+ * Flush synchronously once the buffer reaches this many bytes.
18
+ * Prevents unbounded memory growth for very large Fizz flushes.
19
+ * Default: Infinity (no byte limit — flush only on tick boundary).
20
+ */
21
+ readonly maxBufferByteLength?: number;
22
+ }
23
+
24
+ /**
25
+ * Buffer incoming chunks and coalesce them within a single event loop tick.
26
+ *
27
+ * React Fizz may emit multiple micro-chunks within a single flush (e.g.,
28
+ * opening tags, attributes, closing tags as separate writes). Without
29
+ * buffering, downstream transforms (especially flight injection) could
30
+ * see chunk boundaries in the middle of HTML tags or attribute values.
31
+ *
32
+ * This transform collects all chunks that arrive in the same tick and
33
+ * emits them as a single concatenated chunk on the next `setImmediate`.
34
+ * This ensures each output chunk represents a coherent HTML fragment
35
+ * from a single Fizz flush — safe for downstream script injection at
36
+ * chunk boundaries.
37
+ *
38
+ * **Not a polling loop.** Uses a single-shot `setImmediate` per flush
39
+ * cycle — no recursive scheduling, no busy-wait. See design/02 §"No Polling".
40
+ *
41
+ * Inspired by Next.js `createBufferedTransformStream`.
42
+ */
43
+ export function createBufferedTransformStream(
44
+ options: BufferedTransformOptions = {}
45
+ ): TransformStream<Uint8Array, Uint8Array> {
46
+ const { maxBufferByteLength = Infinity } = options;
47
+
48
+ let bufferedChunks: Uint8Array[] = [];
49
+ let bufferByteLength = 0;
50
+ let pendingFlush: Promise<void> | undefined;
51
+
52
+ const flush = (controller: TransformStreamDefaultController<Uint8Array>) => {
53
+ if (bufferedChunks.length === 0) return;
54
+
55
+ // Concatenate all buffered chunks into a single output chunk
56
+ const merged = new Uint8Array(bufferByteLength);
57
+ let offset = 0;
58
+ for (const chunk of bufferedChunks) {
59
+ merged.set(chunk, offset);
60
+ offset += chunk.byteLength;
61
+ }
62
+
63
+ bufferedChunks = [];
64
+ bufferByteLength = 0;
65
+
66
+ try {
67
+ controller.enqueue(merged);
68
+ } catch {
69
+ // Controller may be errored (e.g., stream cancelled) — ignore
70
+ }
71
+ };
72
+
73
+ const scheduleFlush = (controller: TransformStreamDefaultController<Uint8Array>) => {
74
+ if (pendingFlush) return;
75
+
76
+ // Single-shot setImmediate — fires once at the end of the current
77
+ // event loop iteration (check phase), then the promise resolves.
78
+ // NOT a recursive loop — no CPU spin risk.
79
+ pendingFlush = new Promise<void>((resolve) => {
80
+ setImmediate(() => {
81
+ try {
82
+ flush(controller);
83
+ } finally {
84
+ pendingFlush = undefined;
85
+ resolve();
86
+ }
87
+ });
88
+ });
89
+ };
90
+
91
+ return new TransformStream<Uint8Array, Uint8Array>({
92
+ transform(chunk, controller) {
93
+ bufferedChunks.push(chunk);
94
+ bufferByteLength += chunk.byteLength;
95
+
96
+ if (bufferByteLength >= maxBufferByteLength) {
97
+ // Synchronous flush — buffer is too large to hold
98
+ flush(controller);
99
+ } else {
100
+ // Schedule a deferred flush for end of this tick
101
+ scheduleFlush(controller);
102
+ }
103
+ },
104
+ flush() {
105
+ // Wait for any pending scheduled flush to complete
106
+ return pendingFlush;
107
+ },
108
+ });
109
+ }
110
+
111
+ // ─── Move Suffix Transform ───────────────────────────────────────────────────
112
+
113
+ const SUFFIX = '</body></html>';
114
+
115
+ /**
116
+ * Move `</body></html>` to the end of the stream.
117
+ *
118
+ * React's renderToReadableStream emits `</body></html>` as part of the
119
+ * shell chunk. Content that arrives after the shell (Suspense resolutions,
120
+ * RSC script tags) would appear after the closing tags, producing invalid
121
+ * HTML like `</body></html><script>...</script>`.
122
+ *
123
+ * This transform strips the suffix when first encountered and re-emits
124
+ * it in `flush()` — after all content has passed through. If no suffix
125
+ * is found, it's appended anyway to ensure well-formed HTML.
126
+ *
127
+ * Equivalent to Next.js's `createMoveSuffixStream`.
128
+ */
129
+ export function createMoveSuffixStream(): TransformStream<Uint8Array, Uint8Array> {
130
+ const encoder = new TextEncoder();
131
+ const suffixBytes = encoder.encode(SUFFIX);
132
+ let foundSuffix = false;
133
+
134
+ return new TransformStream<Uint8Array, Uint8Array>({
135
+ transform(chunk, controller) {
136
+ if (foundSuffix) {
137
+ controller.enqueue(chunk);
138
+ return;
139
+ }
140
+
141
+ // Search for the suffix in this chunk
142
+ const text = new TextDecoder().decode(chunk, { stream: true });
143
+ const idx = text.indexOf(SUFFIX);
144
+ if (idx === -1) {
145
+ controller.enqueue(chunk);
146
+ return;
147
+ }
148
+
149
+ foundSuffix = true;
150
+
151
+ // If the entire chunk is exactly the suffix, skip it
152
+ if (chunk.byteLength === suffixBytes.byteLength) return;
153
+
154
+ // Emit content before the suffix
155
+ const before = text.slice(0, idx);
156
+ const after = text.slice(idx + SUFFIX.length);
157
+ if (before) controller.enqueue(encoder.encode(before));
158
+ // Emit content after the suffix (shouldn't normally exist,
159
+ // but handle it for robustness)
160
+ if (after) controller.enqueue(encoder.encode(after));
161
+ },
162
+ flush(controller) {
163
+ // Always emit the suffix at the very end — even if we didn't
164
+ // find it in the input (ensures well-formed HTML).
165
+ controller.enqueue(suffixBytes);
166
+ },
167
+ });
168
+ }
169
+
170
+ // ─── Injection Transforms ────────────────────────────────────────────────────
171
+
172
+ import { createMachine } from '../utils/state-machine.js';
173
+ import { flightChunkScript } from './flight-scripts.js';
174
+ import {
175
+ flightInjectionTransitions,
176
+ isHtmlDone,
177
+ isPullDone,
178
+ type FlightInjectionState,
179
+ type FlightInjectionEvent,
180
+ } from './flight-injection-state.js';
181
+ import { withTimeout, RenderTimeoutError } from './render-timeout.js';
182
+
10
183
  /**
11
184
  * Inject HTML content before a closing tag in the stream.
12
185
  *
@@ -95,22 +268,6 @@ export function injectScripts(
95
268
  return createInjector(stream, scriptsHtml, '</body>');
96
269
  }
97
270
 
98
- /**
99
- * Escape a string for safe embedding inside a `<script>` tag within
100
- * a JSON-encoded value.
101
- *
102
- * Only needs to prevent `</script>` from closing the tag early and
103
- * handle U+2028/U+2029 (line/paragraph separators valid in JSON but
104
- * historically problematic in JS). Since we use JSON.stringify for the
105
- * outer encoding, we only escape `<` and the line separators.
106
- */
107
- function htmlEscapeJsonString(str: string): string {
108
- return str
109
- .replace(/</g, '\\u003c')
110
- .replace(/\u2028/g, '\\u2028')
111
- .replace(/\u2029/g, '\\u2029');
112
- }
113
-
114
271
  /**
115
272
  * Transform an RSC Flight stream into a stream of inline `<script>` tags.
116
273
  *
@@ -118,42 +275,42 @@ function htmlEscapeJsonString(str: string): string {
118
275
  * transform) drives reads from the RSC stream on demand. No background
119
276
  * reader, no shared mutable arrays, no race conditions.
120
277
  *
121
- * Each RSC chunk becomes:
122
- * <script>(self.__timber_f=self.__timber_f||[]).push([1,"escaped_chunk"])</script>
123
- *
124
- * The first chunk emitted is the bootstrap signal [0] which the client
125
- * uses to initialize its buffer.
126
- *
127
- * Uses JSON-encoded typed tuples matching the pattern from Next.js:
128
- * [0] — bootstrap signal
129
- * [1, data] — RSC Flight data chunk (UTF-8 string)
278
+ * Each RSC chunk becomes a `<script>self.__timber_f.push([1,"data"])</script>`.
279
+ * The init script (which creates __timber_f) is in `<head>` via
280
+ * flightInitScript() — see flight-scripts.ts.
130
281
  */
131
282
  export function createInlinedRscStream(
132
- rscStream: ReadableStream<Uint8Array>
283
+ rscStream: ReadableStream<Uint8Array>,
284
+ renderTimeoutMs?: number
133
285
  ): ReadableStream<Uint8Array> {
134
286
  const encoder = new TextEncoder();
135
287
  const rscReader = rscStream.getReader();
136
288
  const decoder = new TextDecoder('utf-8', { fatal: true });
289
+ const timeoutMs = renderTimeoutMs ?? 30_000;
137
290
 
138
291
  return new ReadableStream<Uint8Array>({
139
- start(controller) {
140
- // Emit bootstrap signal tells the client that __timber_f is active
141
- const bootstrap = `<script>(self.__timber_f=self.__timber_f||[]).push(${htmlEscapeJsonString(JSON.stringify([0]))})</script>`;
142
- controller.enqueue(encoder.encode(bootstrap));
143
- },
292
+ // No bootstrap signal here — the init script is in <head> via
293
+ // flightInitScript() (see flight-scripts.ts). This ensures the
294
+ // __timber_f array exists before any chunk scripts execute.
144
295
  async pull(controller) {
145
296
  try {
146
- const { done, value } = await rscReader.read();
297
+ const readPromise = rscReader.read();
298
+ const { done, value } =
299
+ timeoutMs > 0
300
+ ? await withTimeout(readPromise, timeoutMs, 'RSC stream read timed out')
301
+ : await readPromise;
147
302
  if (done) {
148
303
  controller.close();
149
304
  return;
150
305
  }
151
306
  if (value) {
152
307
  const decoded = decoder.decode(value, { stream: true });
153
- const escaped = htmlEscapeJsonString(JSON.stringify([1, decoded]));
154
- controller.enqueue(encoder.encode(`<script>self.__timber_f.push(${escaped})</script>`));
308
+ controller.enqueue(encoder.encode(flightChunkScript(decoded)));
155
309
  }
156
310
  } catch (error) {
311
+ if (error instanceof RenderTimeoutError) {
312
+ rscReader.cancel(error).catch(() => {});
313
+ }
157
314
  controller.error(error);
158
315
  }
159
316
  },
@@ -162,67 +319,84 @@ export function createInlinedRscStream(
162
319
 
163
320
  /**
164
321
  * Merge RSC script stream into the HTML stream, injecting scripts
165
- * only as direct children of `<body>`.
322
+ * between HTML chunks at safe boundaries.
166
323
  *
167
- * This single transform replaces the previous two-stage pipeline
168
- * (createFlightInjectionTransform + createMoveSuffixStream). It:
324
+ * Suffix stripping (</body></html>) is handled upstream by
325
+ * createMoveSuffixStream. This transform only interleaves RSC
326
+ * scripts — no suffix tracking needed.
169
327
  *
170
- * 1. Strips `</body></html>` from the shell chunk so all subsequent
171
- * content is at the `<body>` level.
172
- * 2. Buffers RSC `<script>` tags and drains them after the suffix
173
- * has been stripped — guaranteeing body-level injection.
174
- * 3. Re-emits `</body></html>` at the very end after all RSC scripts.
328
+ * RSC scripts are buffered in pending[] by pullLoop and only
329
+ * drained from transform() (after a complete HTML chunk) or
330
+ * flush(). Never pushed directly from pullLoop to avoid mid-tag
331
+ * injection (TIM-527).
175
332
  *
176
- * Because the suffix is stripped before any scripts are injected,
177
- * scripts are always direct children of `<body>` regardless of how
178
- * React's renderToReadableStream chunks the HTML. No HTML structure
179
- * scanning or depth tracking needed — the suffix removal is the
180
- * structural guarantee.
333
+ * State machine phases:
334
+ * init streaming flushing done
335
+ * (any) error
181
336
  *
182
337
  * Inspired by Next.js createFlightDataInjectionTransformStream.
183
338
  */
184
339
  function createFlightInjectionTransform(
185
- rscScriptStream: ReadableStream<Uint8Array>
340
+ rscScriptStream: ReadableStream<Uint8Array>,
341
+ renderTimeoutMs?: number
186
342
  ): TransformStream<Uint8Array, Uint8Array> {
187
- const encoder = new TextEncoder();
188
- const decoder = new TextDecoder();
189
- const suffix = '</body></html>';
190
- const suffixBytes = encoder.encode(suffix);
191
-
192
343
  const rscReader = rscScriptStream.getReader();
344
+ const timeoutMs = renderTimeoutMs ?? 30_000;
345
+
346
+ const machine = createMachine<FlightInjectionState, FlightInjectionEvent>({
347
+ initial: { phase: 'init' },
348
+ transitions: flightInjectionTransitions,
349
+ });
350
+
193
351
  let pullPromise: Promise<void> | null = null;
194
- let donePulling = false;
195
- let pullError: unknown = null;
196
- // Once the suffix is stripped, all content is body-level and
197
- // scripts can safely be drained after any HTML chunk.
198
- let foundSuffix = false;
199
352
 
200
- // RSC script chunks waiting to be injected at the body level.
353
+ // RSC script chunks waiting to be drained at a safe boundary.
354
+ // pullLoop buffers here; transform(), flush(), and pullLoop's
355
+ // post-yield drain all consume from this buffer.
201
356
  const pending: Uint8Array[] = [];
202
357
 
358
+ // Controller reference — set on first transform() call so pullLoop
359
+ // can drain pending scripts between HTML chunks (after yielding).
360
+ let _controller: TransformStreamDefaultController<Uint8Array> | null = null;
361
+
203
362
  async function pullLoop(): Promise<void> {
204
- // Wait one macrotask so the HTML shell chunk flows through
205
- // transform() first. The browser needs the shell HTML before
206
- // RSC data script tags arrive.
207
- await new Promise<void>((r) => setTimeout(r, 0));
363
+ // Yield once so the first HTML shell chunk flows through
364
+ // transform() before we start reading RSC data.
365
+ await new Promise<void>((r) => setImmediate(r));
208
366
 
209
367
  try {
210
368
  for (;;) {
211
- const { done, value } = await rscReader.read();
369
+ // Guard each RSC read with a timeout.
370
+ // See design/02 §"Streaming Constraints".
371
+ const readPromise = rscReader.read();
372
+ const { done, value } =
373
+ timeoutMs > 0
374
+ ? await withTimeout(readPromise, timeoutMs, 'RSC stream read timed out')
375
+ : await readPromise;
212
376
  if (done) {
213
- donePulling = true;
377
+ machine.send({ type: 'PULL_DONE' });
214
378
  return;
215
379
  }
216
380
  pending.push(value);
217
- // Yield between reads so HTML chunks get a chance to flow
218
- // through transform() first. RSC and HTML are driven by the
219
- // same source — each RSC chunk typically produces a
220
- // corresponding HTML chunk from SSR.
221
- await new Promise<void>((r) => setTimeout(r, 0));
381
+ // Yield between reads so HTML chunks get priority.
382
+ // Once flush() fires, drain without yielding.
383
+ if (!isHtmlDone(machine.state)) {
384
+ await new Promise<void>((r) => setImmediate(r));
385
+ // After yielding, drain pending scripts. This ensures RSC
386
+ // flight data reaches the client at shell-flush time — without
387
+ // this, hydration blocks waiting for data stuck in pending[].
388
+ // Safe because the upstream buffered transform (TIM-528)
389
+ // guarantees chunks end at tag boundaries.
390
+ if (pending.length > 0 && _controller) {
391
+ drainPending(_controller);
392
+ }
393
+ }
222
394
  }
223
395
  } catch (err) {
224
- pullError = err;
225
- donePulling = true;
396
+ if (err instanceof RenderTimeoutError) {
397
+ rscReader.cancel(err).catch(() => {});
398
+ }
399
+ machine.send({ type: 'PULL_ERROR', error: err });
226
400
  }
227
401
  }
228
402
 
@@ -231,59 +405,36 @@ function createFlightInjectionTransform(
231
405
  while (pending.length > 0) {
232
406
  controller.enqueue(pending.shift()!);
233
407
  }
234
- if (pullError) {
235
- const err = pullError;
236
- pullError = null;
237
- controller.error(err);
408
+ if (machine.state.phase === 'error') {
409
+ controller.error(machine.state.error);
238
410
  }
239
411
  }
240
412
 
241
413
  return new TransformStream<Uint8Array, Uint8Array>({
242
414
  transform(chunk, controller) {
243
- // Start pulling RSC scripts into the buffer (if not started)
244
- if (!pullPromise) {
245
- pullPromise = pullLoop();
246
- }
415
+ _controller = controller;
247
416
 
248
- if (foundSuffix) {
249
- // Post-suffix: everything is body-level (Suspense chunks).
250
- // Emit HTML, then drain any buffered scripts.
251
- controller.enqueue(chunk);
252
- if (pending.length > 0) drainPending(controller);
253
- return;
417
+ if (machine.state.phase === 'init') {
418
+ machine.send({ type: 'FIRST_CHUNK' });
419
+ pullPromise = pullLoop();
254
420
  }
255
421
 
256
- // Look for </body></html> in the shell chunk.
257
- const text = decoder.decode(chunk, { stream: true });
258
- const idx = text.indexOf(suffix);
259
- if (idx !== -1) {
260
- foundSuffix = true;
261
- // Emit everything before the suffix (still inside <body>'s
262
- // child elements — don't inject scripts here).
263
- const before = text.slice(0, idx);
264
- const after = text.slice(idx + suffix.length);
265
- if (before) controller.enqueue(encoder.encode(before));
266
- // Now we're at body level — drain buffered scripts
267
- if (pending.length > 0) drainPending(controller);
268
- // Emit any content after the suffix (shouldn't normally exist)
269
- if (after) controller.enqueue(encoder.encode(after));
270
- } else {
271
- // Pre-suffix: inside nested elements. Pass through, don't
272
- // inject scripts (they'd become children of nested elements).
273
- controller.enqueue(chunk);
274
- }
422
+ // Emit the HTML chunk, then drain any buffered RSC scripts.
423
+ // Scripts always come AFTER a complete HTML chunk never mid-tag.
424
+ // The buffered transform upstream (TIM-528) ensures coherent chunks.
425
+ // Suffix stripping is upstream via createMoveSuffixStream (TIM-530).
426
+ controller.enqueue(chunk);
427
+ if (pending.length > 0) drainPending(controller);
275
428
  },
276
429
  flush(controller) {
277
- // HTML stream is done drain remaining RSC chunks at body level
430
+ // All HTML chunks emitted. Pull loop stops yielding.
431
+ machine.send({ type: 'HTML_DONE' });
432
+
278
433
  const finish = () => {
279
434
  drainPending(controller);
280
- // Re-emit the suffix at the very end so HTML is well-formed
281
- if (foundSuffix) {
282
- controller.enqueue(suffixBytes);
283
- }
284
435
  };
285
436
 
286
- if (donePulling) {
437
+ if (isPullDone(machine.state)) {
287
438
  finish();
288
439
  return;
289
440
  }
@@ -314,16 +465,25 @@ function createFlightInjectionTransform(
314
465
  */
315
466
  export function injectRscPayload(
316
467
  htmlStream: ReadableStream<Uint8Array>,
317
- rscStream: ReadableStream<Uint8Array> | undefined
468
+ rscStream: ReadableStream<Uint8Array> | undefined,
469
+ renderTimeoutMs?: number
318
470
  ): ReadableStream<Uint8Array> {
319
471
  if (!rscStream) return htmlStream;
320
472
 
321
473
  // Transform RSC binary stream → stream of <script> tags
322
- const rscScriptStream = createInlinedRscStream(rscStream);
323
-
324
- // Single transform: strip </body></html>, inject RSC scripts at
325
- // body level, re-emit suffix at the very end.
326
- return htmlStream.pipeThrough(createFlightInjectionTransform(rscScriptStream));
474
+ const rscScriptStream = createInlinedRscStream(rscStream, renderTimeoutMs);
475
+
476
+ // Pipeline: flightInjection moveSuffix
477
+ //
478
+ // 1. flightInjection interleaves RSC scripts between HTML chunks
479
+ // 2. moveSuffix strips </body></html> and re-emits at end
480
+ //
481
+ // The flight injector is upstream and interleaves scripts between
482
+ // HTML chunks. The moveSuffix transform then ensures </body></html>
483
+ // appears after all injected scripts, producing well-formed HTML.
484
+ return htmlStream
485
+ .pipeThrough(createFlightInjectionTransform(rscScriptStream, renderTimeoutMs))
486
+ .pipeThrough(createMoveSuffixStream());
327
487
  }
328
488
 
329
489
  /**
@@ -6,19 +6,19 @@ export type { MiddlewareContext } from './types';
6
6
  export type { RouteContext } from './types';
7
7
  export type { Metadata, MetadataRoute } from './types';
8
8
 
9
- // Request Context — ALS-backed headers(), cookies(), and searchParams()
9
+ // Request Context — ALS-backed headers(), cookies(), and rawSearchParams()
10
10
  // Design doc: design/04-authorization.md §"AccessContext does not include cookies or headers"
11
11
  // Design doc: design/23-search-params.md §"Server Integration"
12
12
  export {
13
13
  headers,
14
14
  cookies,
15
- searchParams,
16
- setParsedSearchParams,
15
+ rawSearchParams,
16
+ rawSegmentParams,
17
+ setSegmentParams,
17
18
  runWithRequestContext,
18
19
  setMutableCookieContext,
19
20
  markResponseFlushed,
20
21
  getSetCookieHeaders,
21
- setCookieSecrets,
22
22
  } from './request-context';
23
23
  export type { ReadonlyHeaders, RequestCookies, CookieOptions } from './request-context';
24
24
 
@@ -34,6 +34,7 @@ export {
34
34
  waitUntil,
35
35
  DenySignal,
36
36
  RedirectSignal,
37
+ type RedirectOptions,
37
38
  } from './primitives';
38
39
  export type { RenderErrorDigest, WaitUntilAdapter } from './primitives';
39
40
  export type { JsonSerializable } from './types';
@@ -206,7 +207,6 @@ export {
206
207
  warnRedirectInSuspense,
207
208
  warnRedirectInAccess,
208
209
  warnStaticRequestApi,
209
- warnCacheRequestProps,
210
210
  warnSlowSlotWithoutSuspense,
211
211
  setViteServer,
212
212
  WarningId,
@@ -221,3 +221,7 @@ export type { DevWarningConfig } from './dev-warnings';
221
221
  // Design doc: design/07-routing.md §"route.ts — API Endpoints"
222
222
  export { handleRouteRequest, resolveAllowedMethods } from './route-handler';
223
223
  export type { RouteModule, RouteHandler, HttpMethod } from './route-handler';
224
+
225
+ // Render timeout — design doc: 02-rendering-pipeline.md §"Streaming Constraints"
226
+ export { RenderTimeoutError } from './render-timeout';
227
+ export type { RenderTimeout } from './render-timeout';