@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.81
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.
- package/LICENSE +8 -0
- package/dist/_chunks/actions-Dg-ANYHb.js +421 -0
- package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
- package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
- package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
- package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
- package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
- package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
- package/dist/_chunks/define-C77ScO0m.js +106 -0
- package/dist/_chunks/define-C77ScO0m.js.map +1 -0
- package/dist/_chunks/define-CZqDwhSu.js +199 -0
- package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
- package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
- package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
- package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
- package/dist/_chunks/format-CYBGxKtc.js +14 -0
- package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
- package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
- package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
- package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
- package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
- package/dist/_chunks/request-context-qMsWgy9C.js +478 -0
- package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
- package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
- package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
- package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
- package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
- package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
- package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
- package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
- package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
- package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
- package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
- package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
- package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
- package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
- package/dist/adapters/cloudflare-dev.d.ts +109 -0
- package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
- package/dist/adapters/cloudflare-dev.js +73 -0
- package/dist/adapters/cloudflare-dev.js.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
- package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
- package/dist/adapters/cloudflare-kv-cache.js +95 -0
- package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
- package/dist/adapters/cloudflare.d.ts +148 -12
- package/dist/adapters/cloudflare.d.ts.map +1 -1
- package/dist/adapters/cloudflare.js +135 -11
- package/dist/adapters/cloudflare.js.map +1 -1
- package/dist/adapters/compress-module.d.ts.map +1 -1
- package/dist/adapters/nitro.d.ts +17 -1
- package/dist/adapters/nitro.d.ts.map +1 -1
- package/dist/adapters/nitro.js +56 -13
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/cache/cache-api.d.ts +24 -0
- package/dist/cache/cache-api.d.ts.map +1 -0
- package/dist/cache/handler-store.d.ts +31 -0
- package/dist/cache/handler-store.d.ts.map +1 -0
- package/dist/cache/index.d.ts +23 -7
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +142 -80
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/singleflight.d.ts +18 -1
- package/dist/cache/singleflight.d.ts.map +1 -1
- package/dist/cache/sizeof.d.ts +22 -0
- package/dist/cache/sizeof.d.ts.map +1 -0
- package/dist/cache/timber-cache.d.ts +1 -1
- package/dist/cache/timber-cache.d.ts.map +1 -1
- package/dist/cli.d.ts +6 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-dev.d.ts +27 -1
- package/dist/client/browser-dev.d.ts.map +1 -1
- package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
- package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
- package/dist/client/browser-entry/hmr.d.ts +21 -0
- package/dist/client/browser-entry/hmr.d.ts.map +1 -0
- package/dist/client/browser-entry/hydrate.d.ts +46 -0
- package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
- package/dist/client/browser-entry/index.d.ts +30 -0
- package/dist/client/browser-entry/index.d.ts.map +1 -0
- package/dist/client/browser-entry/post-hydration.d.ts +26 -0
- package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
- package/dist/client/browser-entry/router-init.d.ts +23 -0
- package/dist/client/browser-entry/router-init.d.ts.map +1 -0
- package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
- package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
- package/dist/client/browser-entry/scroll.d.ts +19 -0
- package/dist/client/browser-entry/scroll.d.ts.map +1 -0
- package/dist/client/error-boundary.d.ts +12 -5
- package/dist/client/error-boundary.d.ts.map +1 -1
- package/dist/client/error-boundary.js +10 -4
- package/dist/client/error-boundary.js.map +1 -1
- package/dist/client/error-reconstituter.d.ts +54 -0
- package/dist/client/error-reconstituter.d.ts.map +1 -0
- package/dist/client/form.d.ts +3 -3
- package/dist/client/form.d.ts.map +1 -1
- package/dist/client/history.d.ts +19 -4
- package/dist/client/history.d.ts.map +1 -1
- package/dist/client/index.d.ts +7 -21
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +210 -1017
- package/dist/client/index.js.map +1 -1
- package/dist/client/internal.d.ts +18 -0
- package/dist/client/internal.d.ts.map +1 -0
- package/dist/client/internal.js +890 -0
- package/dist/client/internal.js.map +1 -0
- package/dist/client/link-pending-store.d.ts +63 -0
- package/dist/client/link-pending-store.d.ts.map +1 -0
- package/dist/client/link.d.ts +90 -32
- package/dist/client/link.d.ts.map +1 -1
- package/dist/client/nav-link-store.d.ts +36 -0
- package/dist/client/nav-link-store.d.ts.map +1 -0
- package/dist/client/navigation-api-types.d.ts +90 -0
- package/dist/client/navigation-api-types.d.ts.map +1 -0
- package/dist/client/navigation-api.d.ts +115 -0
- package/dist/client/navigation-api.d.ts.map +1 -0
- package/dist/client/navigation-context.d.ts +13 -2
- package/dist/client/navigation-context.d.ts.map +1 -1
- package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
- package/dist/client/navigation-root.d.ts.map +1 -0
- package/dist/client/nuqs-adapter.d.ts.map +1 -1
- package/dist/client/router-ref.d.ts +1 -1
- package/dist/client/router.d.ts +70 -4
- package/dist/client/router.d.ts.map +1 -1
- package/dist/client/rsc-fetch.d.ts +38 -3
- package/dist/client/rsc-fetch.d.ts.map +1 -1
- package/dist/client/segment-cache.d.ts +1 -1
- package/dist/client/segment-cache.d.ts.map +1 -1
- package/dist/client/segment-outlet.d.ts +63 -0
- package/dist/client/segment-outlet.d.ts.map +1 -0
- package/dist/client/ssr-data.d.ts +13 -4
- package/dist/client/ssr-data.d.ts.map +1 -1
- package/dist/client/stale-reload.d.ts +15 -0
- package/dist/client/stale-reload.d.ts.map +1 -1
- package/dist/client/top-loader.d.ts +5 -5
- package/dist/client/top-loader.d.ts.map +1 -1
- package/dist/client/use-link-status.d.ts +5 -5
- package/dist/client/use-link-status.d.ts.map +1 -1
- package/dist/client/use-params.d.ts +6 -4
- package/dist/client/use-params.d.ts.map +1 -1
- package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
- package/dist/client/use-pending-navigation.d.ts.map +1 -0
- package/dist/client/use-query-states.d.ts +1 -1
- package/dist/client/use-query-states.d.ts.map +1 -1
- package/dist/client/use-router.d.ts +1 -1
- package/dist/codec.d.ts +33 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +2 -0
- package/dist/config-types.d.ts +227 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/content/index.d.ts +1 -10
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +0 -2
- package/dist/cookies/define-cookie.d.ts +35 -14
- package/dist/cookies/define-cookie.d.ts.map +1 -1
- package/dist/cookies/index.js +1 -83
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/index.d.ts +45 -192
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12357 -11925
- package/dist/index.js.map +1 -1
- package/dist/plugin-context.d.ts +107 -0
- package/dist/plugin-context.d.ts.map +1 -0
- package/dist/plugins/adapter-build.d.ts +1 -1
- package/dist/plugins/adapter-build.d.ts.map +1 -1
- package/dist/plugins/build-manifest.d.ts +2 -2
- package/dist/plugins/build-manifest.d.ts.map +1 -1
- package/dist/plugins/build-report.d.ts +3 -3
- package/dist/plugins/build-report.d.ts.map +1 -1
- package/dist/plugins/client-chunks.d.ts +32 -0
- package/dist/plugins/client-chunks.d.ts.map +1 -0
- package/dist/plugins/content.d.ts +1 -1
- package/dist/plugins/content.d.ts.map +1 -1
- package/dist/plugins/dev-browser-logs.d.ts +84 -0
- package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
- package/dist/plugins/dev-error-overlay.d.ts +26 -1
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-logs.d.ts +1 -1
- package/dist/plugins/dev-logs.d.ts.map +1 -1
- package/dist/plugins/dev-server.d.ts +1 -1
- package/dist/plugins/dev-server.d.ts.map +1 -1
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +19 -5
- package/dist/plugins/fonts.d.ts.map +1 -1
- package/dist/plugins/mdx.d.ts +1 -1
- package/dist/plugins/mdx.d.ts.map +1 -1
- package/dist/plugins/routing.d.ts +1 -1
- package/dist/plugins/routing.d.ts.map +1 -1
- package/dist/plugins/server-bundle.d.ts.map +1 -1
- package/dist/plugins/shims.d.ts +6 -5
- package/dist/plugins/shims.d.ts.map +1 -1
- package/dist/plugins/static-build.d.ts +4 -4
- package/dist/plugins/static-build.d.ts.map +1 -1
- package/dist/routing/codegen.d.ts +2 -2
- package/dist/routing/codegen.d.ts.map +1 -1
- package/dist/routing/index.d.ts +2 -0
- package/dist/routing/index.d.ts.map +1 -1
- package/dist/routing/index.js +3 -2
- package/dist/routing/scanner.d.ts.map +1 -1
- package/dist/routing/segment-classify.d.ts +46 -0
- package/dist/routing/segment-classify.d.ts.map +1 -0
- package/dist/routing/status-file-lint.d.ts +2 -1
- package/dist/routing/status-file-lint.d.ts.map +1 -1
- package/dist/routing/types.d.ts +16 -4
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/rsc-runtime/rsc.d.ts +1 -1
- package/dist/rsc-runtime/rsc.d.ts.map +1 -1
- package/dist/rsc-runtime/ssr.d.ts +12 -0
- package/dist/rsc-runtime/ssr.d.ts.map +1 -1
- package/dist/schema-bridge.d.ts +76 -0
- package/dist/schema-bridge.d.ts.map +1 -0
- package/dist/search-params/define.d.ts +139 -0
- package/dist/search-params/define.d.ts.map +1 -0
- package/dist/search-params/index.d.ts +4 -7
- package/dist/search-params/index.d.ts.map +1 -1
- package/dist/search-params/index.js +32 -441
- package/dist/search-params/index.js.map +1 -1
- package/dist/search-params/registry.d.ts +2 -2
- package/dist/search-params/registry.d.ts.map +1 -1
- package/dist/search-params/wrappers.d.ts +53 -0
- package/dist/search-params/wrappers.d.ts.map +1 -0
- package/dist/segment-params/define.d.ts +78 -0
- package/dist/segment-params/define.d.ts.map +1 -0
- package/dist/segment-params/index.d.ts +3 -0
- package/dist/segment-params/index.d.ts.map +1 -0
- package/dist/segment-params/index.js +2 -0
- package/dist/server/access-gate.d.ts +4 -0
- package/dist/server/access-gate.d.ts.map +1 -1
- package/dist/server/action-client.d.ts +25 -6
- package/dist/server/action-client.d.ts.map +1 -1
- package/dist/server/action-encryption.d.ts +76 -0
- package/dist/server/action-encryption.d.ts.map +1 -0
- package/dist/server/action-handler.d.ts.map +1 -1
- package/dist/server/actions.d.ts +3 -6
- package/dist/server/actions.d.ts.map +1 -1
- package/dist/server/als-registry.d.ts +32 -4
- package/dist/server/als-registry.d.ts.map +1 -1
- package/dist/server/build-manifest.d.ts +2 -2
- package/dist/server/build-manifest.d.ts.map +1 -1
- package/dist/server/debug.d.ts +1 -1
- package/dist/server/default-logger.d.ts +22 -0
- package/dist/server/default-logger.d.ts.map +1 -0
- package/dist/server/deny-page-resolver.d.ts +52 -0
- package/dist/server/deny-page-resolver.d.ts.map +1 -0
- package/dist/server/deny-renderer.d.ts.map +1 -1
- package/dist/server/dev-holding-server.d.ts +52 -0
- package/dist/server/dev-holding-server.d.ts.map +1 -0
- package/dist/server/dev-warnings.d.ts +1 -21
- package/dist/server/dev-warnings.d.ts.map +1 -1
- package/dist/server/early-hints.d.ts +13 -5
- package/dist/server/early-hints.d.ts.map +1 -1
- package/dist/server/error-boundary-wrapper.d.ts +7 -1
- package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
- package/dist/server/fallback-error.d.ts +4 -3
- package/dist/server/fallback-error.d.ts.map +1 -1
- package/dist/server/flight-injection-state.d.ts +66 -0
- package/dist/server/flight-injection-state.d.ts.map +1 -0
- package/dist/server/flight-scripts.d.ts +42 -0
- package/dist/server/flight-scripts.d.ts.map +1 -0
- package/dist/server/flush.d.ts.map +1 -1
- package/dist/server/form-data.d.ts +29 -0
- package/dist/server/form-data.d.ts.map +1 -1
- package/dist/server/html-injectors.d.ts +51 -11
- package/dist/server/html-injectors.d.ts.map +1 -1
- package/dist/server/index.d.ts +5 -43
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +37 -2798
- package/dist/server/index.js.map +1 -1
- package/dist/server/internal.d.ts +46 -0
- package/dist/server/internal.d.ts.map +1 -0
- package/dist/server/internal.js +2883 -0
- package/dist/server/internal.js.map +1 -0
- package/dist/server/logger.d.ts +25 -7
- package/dist/server/logger.d.ts.map +1 -1
- package/dist/server/middleware-runner.d.ts +19 -4
- package/dist/server/middleware-runner.d.ts.map +1 -1
- package/dist/server/node-stream-transforms.d.ts +113 -0
- package/dist/server/node-stream-transforms.d.ts.map +1 -0
- package/dist/server/page-deny-boundary.d.ts +31 -0
- package/dist/server/page-deny-boundary.d.ts.map +1 -0
- package/dist/server/pipeline-interception.d.ts +1 -1
- package/dist/server/pipeline-interception.d.ts.map +1 -1
- package/dist/server/pipeline-metadata.d.ts +6 -0
- package/dist/server/pipeline-metadata.d.ts.map +1 -1
- package/dist/server/pipeline.d.ts +42 -10
- package/dist/server/pipeline.d.ts.map +1 -1
- package/dist/server/primitives.d.ts +69 -18
- package/dist/server/primitives.d.ts.map +1 -1
- package/dist/server/render-timeout.d.ts +51 -0
- package/dist/server/render-timeout.d.ts.map +1 -0
- package/dist/server/request-context.d.ts +112 -43
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/route-element-builder.d.ts +27 -1
- package/dist/server/route-element-builder.d.ts.map +1 -1
- package/dist/server/route-handler.d.ts.map +1 -1
- package/dist/server/route-matcher.d.ts +9 -2
- package/dist/server/route-matcher.d.ts.map +1 -1
- package/dist/server/rsc-entry/api-handler.d.ts +2 -2
- package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
- package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
- package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
- package/dist/server/rsc-entry/helpers.d.ts +48 -5
- package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
- package/dist/server/rsc-entry/index.d.ts +8 -3
- package/dist/server/rsc-entry/index.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
- package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts +4 -1
- package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
- package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
- package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
- package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
- package/dist/server/safe-load.d.ts +46 -0
- package/dist/server/safe-load.d.ts.map +1 -0
- package/dist/server/sitemap-generator.d.ts +129 -0
- package/dist/server/sitemap-generator.d.ts.map +1 -0
- package/dist/server/sitemap-handler.d.ts +22 -0
- package/dist/server/sitemap-handler.d.ts.map +1 -0
- package/dist/server/slot-resolver.d.ts +1 -1
- package/dist/server/slot-resolver.d.ts.map +1 -1
- package/dist/server/ssr-entry.d.ts +22 -0
- package/dist/server/ssr-entry.d.ts.map +1 -1
- package/dist/server/ssr-render.d.ts +39 -21
- package/dist/server/ssr-render.d.ts.map +1 -1
- package/dist/server/ssr-wrappers.d.ts +50 -0
- package/dist/server/ssr-wrappers.d.ts.map +1 -0
- package/dist/server/status-code-resolver.d.ts +1 -1
- package/dist/server/status-code-resolver.d.ts.map +1 -1
- package/dist/server/stream-utils.d.ts +36 -0
- package/dist/server/stream-utils.d.ts.map +1 -0
- package/dist/server/tracing.d.ts +4 -4
- package/dist/server/tracing.d.ts.map +1 -1
- package/dist/server/tree-builder.d.ts +22 -19
- package/dist/server/tree-builder.d.ts.map +1 -1
- package/dist/server/types.d.ts +1 -4
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/version-skew.d.ts +61 -0
- package/dist/server/version-skew.d.ts.map +1 -0
- package/dist/shared/merge-search-params.d.ts +22 -0
- package/dist/shared/merge-search-params.d.ts.map +1 -0
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.js +42 -0
- package/dist/shims/font-google.js.map +1 -0
- package/dist/shims/font-local.d.ts +26 -0
- package/dist/shims/font-local.d.ts.map +1 -0
- package/dist/shims/font-local.js +20 -0
- package/dist/shims/font-local.js.map +1 -0
- package/dist/shims/headers.d.ts +2 -1
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/navigation-client.d.ts +1 -1
- package/dist/shims/navigation-client.d.ts.map +1 -1
- package/dist/shims/navigation.d.ts +3 -2
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/utils/directive-parser.d.ts +5 -2
- package/dist/utils/directive-parser.d.ts.map +1 -1
- package/dist/utils/state-machine.d.ts +80 -0
- package/dist/utils/state-machine.d.ts.map +1 -0
- package/package.json +56 -22
- package/src/adapters/cloudflare-dev.ts +177 -0
- package/src/adapters/cloudflare-kv-cache.ts +142 -0
- package/src/adapters/cloudflare.ts +342 -28
- package/src/adapters/compress-module.ts +24 -4
- package/src/adapters/nitro.ts +52 -8
- package/src/adapters/wrangler.d.ts +7 -0
- package/src/cache/cache-api.ts +38 -0
- package/src/cache/handler-store.ts +68 -0
- package/src/cache/index.ts +81 -18
- package/src/cache/singleflight.ts +62 -4
- package/src/cache/sizeof.ts +31 -0
- package/src/cache/timber-cache.ts +24 -20
- package/src/cli.ts +16 -6
- package/src/client/browser-dev.ts +128 -1
- package/src/client/browser-entry/action-dispatch.ts +116 -0
- package/src/client/browser-entry/hmr.ts +81 -0
- package/src/client/browser-entry/hydrate.ts +145 -0
- package/src/client/browser-entry/index.ts +138 -0
- package/src/client/browser-entry/post-hydration.ts +119 -0
- package/src/client/browser-entry/router-init.ts +193 -0
- package/src/client/browser-entry/rsc-stream.ts +157 -0
- package/src/client/browser-entry/scroll.ts +27 -0
- package/src/client/error-boundary.tsx +48 -16
- package/src/client/error-reconstituter.tsx +65 -0
- package/src/client/form.tsx +9 -7
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +19 -38
- package/src/client/internal.ts +57 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +329 -97
- package/src/client/nav-link-store.ts +47 -0
- package/src/client/navigation-api-types.ts +112 -0
- package/src/client/navigation-api.ts +332 -0
- package/src/client/navigation-context.ts +31 -6
- package/src/client/navigation-root.tsx +342 -0
- package/src/client/nuqs-adapter.tsx +16 -3
- package/src/client/router-ref.ts +1 -1
- package/src/client/router.ts +299 -72
- package/src/client/rsc-fetch.ts +97 -8
- package/src/client/segment-cache.ts +1 -1
- package/src/client/segment-outlet.tsx +86 -0
- package/src/client/ssr-data.ts +13 -5
- package/src/client/stale-reload.ts +72 -3
- package/src/client/top-loader.tsx +16 -8
- package/src/client/use-link-status.ts +7 -7
- package/src/client/use-params.ts +7 -5
- package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
- package/src/client/use-query-states.ts +3 -3
- package/src/client/use-router.ts +1 -1
- package/src/codec.ts +49 -0
- package/src/config-types.ts +225 -0
- package/src/content/index.ts +5 -13
- package/src/cookies/define-cookie.ts +78 -25
- package/src/cookies/index.ts +8 -0
- package/src/fonts/css.ts +2 -1
- package/src/index.ts +295 -354
- package/src/plugin-context.ts +240 -0
- package/src/plugins/adapter-build.ts +9 -3
- package/src/plugins/build-manifest.ts +13 -2
- package/src/plugins/build-report.ts +3 -3
- package/src/plugins/client-chunks.ts +65 -0
- package/src/plugins/content.ts +1 -1
- package/src/plugins/dev-browser-logs.ts +288 -0
- package/src/plugins/dev-error-overlay.ts +70 -1
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +70 -9
- package/src/plugins/entries.ts +71 -10
- package/src/plugins/fonts.ts +168 -61
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +57 -17
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +135 -35
- package/src/plugins/static-build.ts +17 -11
- package/src/routing/codegen.ts +165 -105
- package/src/routing/index.ts +2 -0
- package/src/routing/scanner.ts +93 -23
- package/src/routing/segment-classify.ts +89 -0
- package/src/routing/status-file-lint.ts +3 -2
- package/src/routing/types.ts +17 -4
- package/src/rsc-runtime/rsc.ts +2 -0
- package/src/rsc-runtime/ssr.ts +50 -0
- package/src/rsc-runtime/vendor-types.d.ts +7 -0
- package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
- package/src/search-params/define.ts +482 -0
- package/src/search-params/index.ts +14 -20
- package/src/search-params/registry.ts +2 -2
- package/src/search-params/wrappers.ts +85 -0
- package/src/segment-params/define.ts +279 -0
- package/src/segment-params/index.ts +9 -0
- package/src/server/access-gate.tsx +70 -29
- package/src/server/action-client.ts +46 -11
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +21 -4
- package/src/server/actions.ts +10 -9
- package/src/server/als-registry.ts +34 -6
- package/src/server/build-manifest.ts +10 -4
- package/src/server/compress.ts +25 -7
- package/src/server/debug.ts +1 -1
- package/src/server/default-logger.ts +99 -0
- package/src/server/deny-page-resolver.ts +154 -0
- package/src/server/deny-renderer.ts +24 -38
- package/src/server/dev-holding-server.ts +185 -0
- package/src/server/dev-warnings.ts +4 -49
- package/src/server/early-hints.ts +36 -15
- package/src/server/error-boundary-wrapper.ts +74 -22
- package/src/server/fallback-error.ts +31 -15
- package/src/server/flight-injection-state.ts +113 -0
- package/src/server/flight-scripts.ts +62 -0
- package/src/server/flush.ts +2 -1
- package/src/server/form-data.ts +76 -0
- package/src/server/html-injectors.ts +280 -120
- package/src/server/index.ts +25 -177
- package/src/server/internal.ts +169 -0
- package/src/server/logger.ts +44 -36
- package/src/server/middleware-runner.ts +31 -4
- package/src/server/node-stream-transforms.ts +509 -0
- package/src/server/page-deny-boundary.tsx +56 -0
- package/src/server/pipeline-interception.ts +17 -16
- package/src/server/pipeline-metadata.ts +13 -0
- package/src/server/pipeline.ts +227 -62
- package/src/server/primitives.ts +111 -28
- package/src/server/render-timeout.ts +108 -0
- package/src/server/request-context.ts +293 -132
- package/src/server/route-element-builder.ts +283 -191
- package/src/server/route-handler.ts +24 -4
- package/src/server/route-matcher.ts +24 -20
- package/src/server/rsc-entry/api-handler.ts +15 -16
- package/src/server/rsc-entry/error-renderer.ts +300 -89
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +200 -112
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +65 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +168 -38
- package/src/server/safe-load.ts +60 -0
- package/src/server/sitemap-generator.ts +338 -0
- package/src/server/sitemap-handler.ts +126 -0
- package/src/server/slot-resolver.ts +244 -229
- package/src/server/ssr-entry.ts +211 -32
- package/src/server/ssr-render.ts +289 -67
- package/src/server/ssr-wrappers.tsx +139 -0
- package/src/server/status-code-resolver.ts +1 -1
- package/src/server/stream-utils.ts +213 -0
- package/src/server/tracing.ts +20 -9
- package/src/server/tree-builder.ts +92 -58
- package/src/server/types.ts +3 -6
- package/src/server/version-skew.ts +104 -0
- package/src/shared/merge-search-params.ts +55 -0
- package/src/shims/font-google.ts +1 -1
- package/src/shims/font-local.ts +34 -0
- package/src/shims/headers.ts +5 -1
- package/src/shims/navigation-client.ts +1 -1
- package/src/shims/navigation.ts +7 -2
- package/src/utils/directive-parser.ts +5 -2
- package/src/utils/state-machine.ts +111 -0
- package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
- package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
- package/dist/_chunks/format-DviM89f0.js.map +0 -1
- package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
- package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
- package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
- package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
- package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
- package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
- package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
- package/dist/cache/register-cached-function.d.ts +0 -17
- package/dist/cache/register-cached-function.d.ts.map +0 -1
- package/dist/client/browser-entry.d.ts +0 -21
- package/dist/client/browser-entry.d.ts.map +0 -1
- package/dist/client/link-status-provider.d.ts +0 -11
- package/dist/client/link-status-provider.d.ts.map +0 -1
- package/dist/client/transition-root.d.ts.map +0 -1
- package/dist/client/use-navigation-pending.d.ts.map +0 -1
- package/dist/cookies/index.js.map +0 -1
- package/dist/plugins/cache-transform.d.ts +0 -36
- package/dist/plugins/cache-transform.d.ts.map +0 -1
- package/dist/plugins/dynamic-transform.d.ts +0 -72
- package/dist/plugins/dynamic-transform.d.ts.map +0 -1
- package/dist/search-params/analyze.d.ts +0 -54
- package/dist/search-params/analyze.d.ts.map +0 -1
- package/dist/search-params/builtin-codecs.d.ts +0 -105
- package/dist/search-params/builtin-codecs.d.ts.map +0 -1
- package/dist/search-params/codecs.d.ts +0 -53
- package/dist/search-params/codecs.d.ts.map +0 -1
- package/dist/search-params/create.d.ts +0 -106
- package/dist/search-params/create.d.ts.map +0 -1
- package/dist/server/prerender.d.ts +0 -77
- package/dist/server/prerender.d.ts.map +0 -1
- package/dist/server/response-cache.d.ts +0 -54
- package/dist/server/response-cache.d.ts.map +0 -1
- package/src/cache/register-cached-function.ts +0 -103
- package/src/client/browser-entry.ts +0 -678
- package/src/client/link-status-provider.tsx +0 -30
- package/src/client/transition-root.tsx +0 -166
- package/src/plugins/cache-transform.ts +0 -199
- package/src/plugins/dynamic-transform.ts +0 -161
- package/src/search-params/analyze.ts +0 -192
- package/src/search-params/builtin-codecs.ts +0 -228
- package/src/search-params/create.ts +0 -321
- package/src/server/prerender.ts +0 -139
- package/src/server/response-cache.ts +0 -410
|
@@ -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
|
-
*
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
322
|
+
* between HTML chunks at safe boundaries.
|
|
166
323
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
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
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
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
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
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
|
|
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
|
-
//
|
|
205
|
-
// transform()
|
|
206
|
-
|
|
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
|
-
|
|
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
|
-
|
|
377
|
+
machine.send({ type: 'PULL_DONE' });
|
|
214
378
|
return;
|
|
215
379
|
}
|
|
216
380
|
pending.push(value);
|
|
217
|
-
// Yield between reads so HTML chunks get
|
|
218
|
-
//
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
225
|
-
|
|
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 (
|
|
235
|
-
|
|
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
|
-
|
|
244
|
-
if (!pullPromise) {
|
|
245
|
-
pullPromise = pullLoop();
|
|
246
|
-
}
|
|
415
|
+
_controller = controller;
|
|
247
416
|
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
//
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
|
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 (
|
|
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
|
-
//
|
|
325
|
-
//
|
|
326
|
-
|
|
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
|
/**
|
|
@@ -344,7 +504,7 @@ export interface ClientBootstrapConfig {
|
|
|
344
504
|
preloadLinks: string;
|
|
345
505
|
}
|
|
346
506
|
|
|
347
|
-
/** Find a manifest entry by matching the key suffix (e.g. 'client/browser-entry.ts'). */
|
|
507
|
+
/** Find a manifest entry by matching the key suffix (e.g. 'client/browser-entry/index.ts'). */
|
|
348
508
|
function findManifestEntry(map: Record<string, string>, suffix: string): string | undefined {
|
|
349
509
|
for (const [key, value] of Object.entries(map)) {
|
|
350
510
|
if (key.endsWith(suffix)) return value;
|
|
@@ -425,7 +585,7 @@ export function buildClientScripts(runtimeConfig: {
|
|
|
425
585
|
// a monorepo). Match by suffix to handle both cases.
|
|
426
586
|
const manifest = runtimeConfig.buildManifest;
|
|
427
587
|
const browserEntryUrl = manifest
|
|
428
|
-
? findManifestEntry(manifest.js, 'client/browser-entry.ts')
|
|
588
|
+
? findManifestEntry(manifest.js, 'client/browser-entry/index.ts')
|
|
429
589
|
: undefined;
|
|
430
590
|
|
|
431
591
|
let preloadLinks = '';
|
|
@@ -435,7 +595,7 @@ export function buildClientScripts(runtimeConfig: {
|
|
|
435
595
|
// Modulepreload hints for browser entry dependencies
|
|
436
596
|
const preloads =
|
|
437
597
|
(manifest
|
|
438
|
-
? findManifestEntryArray(manifest.modulepreload, 'client/browser-entry.ts')
|
|
598
|
+
? findManifestEntryArray(manifest.modulepreload, 'client/browser-entry/index.ts')
|
|
439
599
|
: undefined) ?? [];
|
|
440
600
|
for (const url of preloads) {
|
|
441
601
|
preloadLinks += `<link rel="modulepreload" href="${url}">`;
|