@timber-js/app 0.2.0-alpha.9 → 0.2.0-alpha.90
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/dist/_chunks/actions-DLnUaR65.js +421 -0
- package/dist/_chunks/actions-DLnUaR65.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-BYIpzuS7.js +39 -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-Itxvcd7F.js +199 -0
- package/dist/_chunks/define-Itxvcd7F.js.map +1 -0
- package/dist/_chunks/define-cookie-BowvzoP0.js +94 -0
- package/dist/_chunks/define-cookie-BowvzoP0.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-DRlhJWbu.js} +219 -97
- package/dist/_chunks/interception-DRlhJWbu.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-CK5tZqIP.js +478 -0
- package/dist/_chunks/request-context-CK5tZqIP.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-BiV5GJgm.js} +7 -4
- package/dist/_chunks/use-query-states-BiV5GJgm.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 +6 -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 +9 -21
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +229 -1018
- 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 +62 -55
- 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 +266 -0
- package/dist/config-types.d.ts.map +1 -0
- package/dist/config-validation.d.ts +51 -0
- package/dist/config-validation.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/bundle.d.ts +48 -0
- package/dist/fonts/bundle.d.ts.map +1 -0
- package/dist/fonts/css.d.ts +1 -0
- package/dist/fonts/css.d.ts.map +1 -1
- package/dist/fonts/dev-middleware.d.ts +22 -0
- package/dist/fonts/dev-middleware.d.ts.map +1 -0
- package/dist/fonts/pipeline.d.ts +138 -0
- package/dist/fonts/pipeline.d.ts.map +1 -0
- package/dist/fonts/transform.d.ts +72 -0
- package/dist/fonts/transform.d.ts.map +1 -0
- package/dist/fonts/types.d.ts +45 -1
- package/dist/fonts/types.d.ts.map +1 -1
- package/dist/fonts/virtual-modules.d.ts +59 -0
- package/dist/fonts/virtual-modules.d.ts.map +1 -0
- package/dist/index.d.ts +45 -190
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4294 -2453
- 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-404-page.d.ts +56 -0
- package/dist/plugins/dev-404-page.d.ts.map +1 -0
- 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 +49 -9
- package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
- package/dist/plugins/dev-error-page.d.ts +58 -0
- package/dist/plugins/dev-error-page.d.ts.map +1 -0
- 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/dev-terminal-error.d.ts +28 -0
- package/dist/plugins/dev-terminal-error.d.ts.map +1 -0
- package/dist/plugins/entries.d.ts +1 -1
- package/dist/plugins/entries.d.ts.map +1 -1
- package/dist/plugins/fonts.d.ts +17 -73
- 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/convention-lint.d.ts +41 -0
- package/dist/routing/convention-lint.d.ts.map +1 -0
- 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 +41 -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 +7 -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-source-map.d.ts +22 -0
- package/dist/server/dev-source-map.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 +12 -7
- 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 +195 -2800
- 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 +2900 -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 +52 -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 +16 -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 +20 -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 +14 -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/sensitive-fields.d.ts +74 -0
- package/dist/server/sensitive-fields.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 +23 -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 +51 -16
- 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 +143 -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 +14 -7
- package/src/client/history.ts +26 -4
- package/src/client/index.ts +65 -38
- package/src/client/internal.ts +57 -0
- package/src/client/link-pending-store.ts +111 -0
- package/src/client/link.tsx +342 -113
- 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 +18 -6
- 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 +9 -3
- package/src/client/use-router.ts +1 -1
- package/src/codec.ts +49 -0
- package/src/config-types.ts +264 -0
- package/src/config-validation.ts +303 -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/bundle.ts +142 -0
- package/src/fonts/css.ts +2 -1
- package/src/fonts/dev-middleware.ts +74 -0
- package/src/fonts/pipeline.ts +275 -0
- package/src/fonts/transform.ts +353 -0
- package/src/fonts/types.ts +50 -1
- package/src/fonts/virtual-modules.ts +159 -0
- package/src/index.ts +314 -355
- 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-404-page.ts +418 -0
- package/src/plugins/dev-browser-logs.ts +288 -0
- package/src/plugins/dev-error-overlay.ts +286 -42
- package/src/plugins/dev-error-page.ts +536 -0
- package/src/plugins/dev-logs.ts +1 -1
- package/src/plugins/dev-server.ts +146 -19
- package/src/plugins/dev-terminal-error.ts +217 -0
- package/src/plugins/entries.ts +111 -10
- package/src/plugins/fonts.ts +133 -638
- package/src/plugins/mdx.ts +1 -1
- package/src/plugins/routing.ts +213 -31
- package/src/plugins/server-action-exports.ts +1 -1
- package/src/plugins/server-bundle.ts +32 -1
- package/src/plugins/shims.ts +136 -35
- package/src/plugins/static-build.ts +17 -11
- package/src/routing/codegen.ts +273 -105
- package/src/routing/convention-lint.ts +356 -0
- 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 +88 -15
- package/src/server/action-encryption.ts +144 -0
- package/src/server/action-handler.ts +53 -6
- 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-source-map.ts +31 -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 +74 -102
- 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 +261 -66
- 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 +31 -20
- package/src/server/rsc-entry/api-handler.ts +15 -16
- package/src/server/rsc-entry/error-renderer.ts +305 -89
- package/src/server/rsc-entry/helpers.ts +134 -5
- package/src/server/rsc-entry/index.ts +304 -111
- package/src/server/rsc-entry/rsc-payload.ts +65 -18
- package/src/server/rsc-entry/rsc-stream.ts +81 -13
- package/src/server/rsc-entry/ssr-bridge.ts +14 -5
- package/src/server/rsc-entry/ssr-renderer.ts +171 -38
- package/src/server/safe-load.ts +60 -0
- package/src/server/sensitive-fields.ts +230 -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 +215 -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
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js native stream transforms for SSR HTML post-processing.
|
|
3
|
+
*
|
|
4
|
+
* These are Node.js Transform stream equivalents of the Web Stream
|
|
5
|
+
* transforms in html-injectors.ts. Used on Node.js/Bun where native
|
|
6
|
+
* streams (C++ backed) are faster than Web Streams (JS reimplementation).
|
|
7
|
+
*
|
|
8
|
+
* The transforms are pure string operations on HTML chunks — the same
|
|
9
|
+
* logic as the Web Stream versions, just wrapped in Node.js Transform
|
|
10
|
+
* instead of Web TransformStream.
|
|
11
|
+
*
|
|
12
|
+
* Architecture:
|
|
13
|
+
* renderToPipeableStream → pipe(errorHandler) → pipe(headInjector)
|
|
14
|
+
* → pipe(flightInjector) → Readable.toWeb() → Response
|
|
15
|
+
*
|
|
16
|
+
* All chunks stay in C++ Node.js stream buffers until the final
|
|
17
|
+
* Readable.toWeb() conversion for the Response body.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { Transform } from 'node:stream';
|
|
21
|
+
import { createGzip, constants } from 'node:zlib';
|
|
22
|
+
|
|
23
|
+
// ─── Buffered Transform ──────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Options for the Node.js buffered transform.
|
|
27
|
+
*/
|
|
28
|
+
export interface NodeBufferedTransformOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Flush synchronously once the buffer reaches this many bytes.
|
|
31
|
+
* Prevents unbounded memory growth for very large Fizz flushes.
|
|
32
|
+
* Default: Infinity (no byte limit — flush only on tick boundary).
|
|
33
|
+
*/
|
|
34
|
+
readonly maxBufferByteLength?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Node.js Transform that buffers incoming chunks and coalesces them
|
|
39
|
+
* within a single event loop tick.
|
|
40
|
+
*
|
|
41
|
+
* Equivalent to createBufferedTransformStream() in html-injectors.ts.
|
|
42
|
+
* React Fizz may emit multiple micro-chunks within a single flush.
|
|
43
|
+
* Without buffering, downstream transforms (especially flight injection)
|
|
44
|
+
* could see chunk boundaries in the middle of HTML tags or attributes.
|
|
45
|
+
*
|
|
46
|
+
* This transform collects all chunks that arrive in the same tick and
|
|
47
|
+
* emits them as a single concatenated Buffer on the next `setImmediate`.
|
|
48
|
+
*
|
|
49
|
+
* **Not a polling loop.** Uses a single-shot `setImmediate` per flush
|
|
50
|
+
* cycle — no recursive scheduling, no busy-wait. See design/02 §"No Polling".
|
|
51
|
+
*
|
|
52
|
+
* Inspired by Next.js `createBufferedTransformStream`.
|
|
53
|
+
*/
|
|
54
|
+
export function createNodeBufferedTransform(options: NodeBufferedTransformOptions = {}): Transform {
|
|
55
|
+
const { maxBufferByteLength = Infinity } = options;
|
|
56
|
+
|
|
57
|
+
let bufferedChunks: Buffer[] = [];
|
|
58
|
+
let bufferByteLength = 0;
|
|
59
|
+
let pendingImmediate: ReturnType<typeof setImmediate> | null = null;
|
|
60
|
+
|
|
61
|
+
const transform = new Transform({
|
|
62
|
+
transform(chunk: Buffer, _encoding, callback) {
|
|
63
|
+
bufferedChunks.push(chunk);
|
|
64
|
+
bufferByteLength += chunk.byteLength;
|
|
65
|
+
|
|
66
|
+
if (bufferByteLength >= maxBufferByteLength) {
|
|
67
|
+
// Synchronous flush — buffer is too large to hold
|
|
68
|
+
flushBuffer();
|
|
69
|
+
} else if (!pendingImmediate) {
|
|
70
|
+
// Schedule a deferred flush for end of this tick.
|
|
71
|
+
// Single-shot setImmediate — NOT a recursive loop.
|
|
72
|
+
// See design/02 §"No Polling".
|
|
73
|
+
pendingImmediate = setImmediate(() => {
|
|
74
|
+
pendingImmediate = null;
|
|
75
|
+
flushBuffer();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
callback();
|
|
80
|
+
},
|
|
81
|
+
flush(callback) {
|
|
82
|
+
// Cancel any pending deferred flush and flush synchronously
|
|
83
|
+
if (pendingImmediate) {
|
|
84
|
+
clearImmediate(pendingImmediate);
|
|
85
|
+
pendingImmediate = null;
|
|
86
|
+
}
|
|
87
|
+
flushBuffer();
|
|
88
|
+
callback();
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
function flushBuffer() {
|
|
93
|
+
if (bufferedChunks.length === 0) return;
|
|
94
|
+
|
|
95
|
+
const merged = Buffer.concat(bufferedChunks, bufferByteLength);
|
|
96
|
+
bufferedChunks = [];
|
|
97
|
+
bufferByteLength = 0;
|
|
98
|
+
transform.push(merged);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return transform;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── Injection Transforms ────────────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
import { createMachine } from '../utils/state-machine.js';
|
|
107
|
+
import { flightChunkScript } from './flight-scripts.js';
|
|
108
|
+
import {
|
|
109
|
+
flightInjectionTransitions,
|
|
110
|
+
isHtmlDone,
|
|
111
|
+
isPullDone,
|
|
112
|
+
type FlightInjectionState,
|
|
113
|
+
type FlightInjectionEvent,
|
|
114
|
+
} from './flight-injection-state.js';
|
|
115
|
+
import { withTimeout, RenderTimeoutError } from './render-timeout.js';
|
|
116
|
+
import { logStreamingError } from './logger.js';
|
|
117
|
+
|
|
118
|
+
// ─── Move Suffix Transform ───────────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
const SUFFIX = '</body></html>';
|
|
121
|
+
const SUFFIX_BUF = Buffer.from(SUFFIX, 'utf-8');
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Node.js Transform that moves `</body></html>` to the end of the stream.
|
|
125
|
+
*
|
|
126
|
+
* Equivalent to createMoveSuffixStream() in html-injectors.ts.
|
|
127
|
+
* Strips the suffix when first encountered and re-emits it in flush().
|
|
128
|
+
* If no suffix is found, it's appended anyway for well-formed HTML.
|
|
129
|
+
*/
|
|
130
|
+
export function createNodeMoveSuffixTransform(): Transform {
|
|
131
|
+
let foundSuffix = false;
|
|
132
|
+
|
|
133
|
+
return new Transform({
|
|
134
|
+
transform(chunk: Buffer, _encoding, callback) {
|
|
135
|
+
if (foundSuffix) {
|
|
136
|
+
this.push(chunk);
|
|
137
|
+
callback();
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const text = chunk.toString('utf-8');
|
|
142
|
+
const idx = text.indexOf(SUFFIX);
|
|
143
|
+
if (idx === -1) {
|
|
144
|
+
this.push(chunk);
|
|
145
|
+
callback();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
foundSuffix = true;
|
|
150
|
+
|
|
151
|
+
// If the entire chunk is exactly the suffix, skip it
|
|
152
|
+
if (chunk.byteLength === SUFFIX_BUF.byteLength) {
|
|
153
|
+
callback();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Emit content before the suffix
|
|
158
|
+
const before = text.slice(0, idx);
|
|
159
|
+
const after = text.slice(idx + SUFFIX.length);
|
|
160
|
+
if (before) this.push(Buffer.from(before, 'utf-8'));
|
|
161
|
+
if (after) this.push(Buffer.from(after, 'utf-8'));
|
|
162
|
+
callback();
|
|
163
|
+
},
|
|
164
|
+
flush(callback) {
|
|
165
|
+
// Always emit the suffix at the very end
|
|
166
|
+
this.push(SUFFIX_BUF);
|
|
167
|
+
callback();
|
|
168
|
+
},
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ─── Head Injection ──────────────────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Node.js Transform that injects HTML content before </head>.
|
|
176
|
+
*
|
|
177
|
+
* Equivalent to injectHead() in html-injectors.ts. Streams chunks
|
|
178
|
+
* through immediately, keeping only a small trailing buffer to handle
|
|
179
|
+
* </head> split across chunk boundaries.
|
|
180
|
+
*/
|
|
181
|
+
export function createNodeHeadInjector(headHtml: string): Transform {
|
|
182
|
+
if (!headHtml) {
|
|
183
|
+
return new Transform({
|
|
184
|
+
transform(chunk, _enc, cb) {
|
|
185
|
+
cb(null, chunk);
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const target = '</head>';
|
|
191
|
+
const tailLen = target.length - 1;
|
|
192
|
+
let injected = false;
|
|
193
|
+
let tail = '';
|
|
194
|
+
|
|
195
|
+
return new Transform({
|
|
196
|
+
transform(chunk: Buffer, _encoding, callback) {
|
|
197
|
+
if (injected) {
|
|
198
|
+
callback(null, chunk);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const text = tail + chunk.toString('utf-8');
|
|
203
|
+
const tagIndex = text.indexOf(target);
|
|
204
|
+
|
|
205
|
+
if (tagIndex !== -1) {
|
|
206
|
+
const before = text.slice(0, tagIndex);
|
|
207
|
+
const after = text.slice(tagIndex);
|
|
208
|
+
this.push(Buffer.from(before + headHtml + after, 'utf-8'));
|
|
209
|
+
injected = true;
|
|
210
|
+
tail = '';
|
|
211
|
+
callback();
|
|
212
|
+
} else {
|
|
213
|
+
const safeEnd = Math.max(0, text.length - tailLen);
|
|
214
|
+
if (safeEnd > 0) {
|
|
215
|
+
this.push(Buffer.from(text.slice(0, safeEnd), 'utf-8'));
|
|
216
|
+
}
|
|
217
|
+
tail = text.slice(safeEnd);
|
|
218
|
+
callback();
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
flush(callback) {
|
|
222
|
+
if (!injected && tail) {
|
|
223
|
+
this.push(Buffer.from(tail, 'utf-8'));
|
|
224
|
+
}
|
|
225
|
+
callback();
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ─── RSC Flight Injection ────────────────────────────────────────────────────
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Node.js Transform that merges RSC script tags into the HTML stream.
|
|
234
|
+
*
|
|
235
|
+
* Reads RSC chunks from the provided ReadableStream and injects them
|
|
236
|
+
* as `<script>` tags between HTML chunks. Scripts are buffered in
|
|
237
|
+
* pending[] and only drained from transform() (after a complete HTML
|
|
238
|
+
* chunk) or flush() — never pushed directly from the pull loop.
|
|
239
|
+
*
|
|
240
|
+
* Suffix stripping (</body></html>) is handled upstream by
|
|
241
|
+
* createNodeMoveSuffixTransform. This transform only interleaves
|
|
242
|
+
* RSC scripts at safe chunk boundaries.
|
|
243
|
+
*
|
|
244
|
+
* The RSC stream is a Web ReadableStream (from the tee'd RSC Flight
|
|
245
|
+
* stream). We read from it using the Web API — this is the one bridge
|
|
246
|
+
* point between Web Streams and Node.js streams in the pipeline.
|
|
247
|
+
*/
|
|
248
|
+
/**
|
|
249
|
+
* Options for the Node.js flight injector.
|
|
250
|
+
*/
|
|
251
|
+
export interface NodeFlightInjectorOptions {
|
|
252
|
+
/**
|
|
253
|
+
* Timeout in milliseconds for individual RSC stream reads.
|
|
254
|
+
* If a single `rscReader.read()` call does not resolve within
|
|
255
|
+
* this duration, the read is aborted and the stream errors with
|
|
256
|
+
* a RenderTimeoutError. Default: 30000 (30s).
|
|
257
|
+
*/
|
|
258
|
+
renderTimeoutMs?: number;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function createNodeFlightInjector(
|
|
262
|
+
rscStream: ReadableStream<Uint8Array> | undefined,
|
|
263
|
+
options?: NodeFlightInjectorOptions
|
|
264
|
+
): Transform {
|
|
265
|
+
if (!rscStream) {
|
|
266
|
+
return new Transform({
|
|
267
|
+
transform(chunk, _enc, cb) {
|
|
268
|
+
cb(null, chunk);
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const timeoutMs = options?.renderTimeoutMs ?? 30_000;
|
|
274
|
+
const rscReader = rscStream.getReader();
|
|
275
|
+
const decoder = new TextDecoder('utf-8', { fatal: true });
|
|
276
|
+
|
|
277
|
+
const machine = createMachine<FlightInjectionState, FlightInjectionEvent>({
|
|
278
|
+
initial: { phase: 'init' },
|
|
279
|
+
transitions: flightInjectionTransitions,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Stored promise from pullLoop — awaited in flush() via .then()
|
|
283
|
+
// instead of polling. See design/02 §"No Polling".
|
|
284
|
+
let pullPromise: Promise<void> | null = null;
|
|
285
|
+
|
|
286
|
+
// RSC script chunks waiting to be drained at a safe boundary.
|
|
287
|
+
// pullLoop buffers here; transform() and flush() drain.
|
|
288
|
+
// RSC script chunks waiting to be drained at a safe boundary.
|
|
289
|
+
// pullLoop buffers here; transform(), flush(), and pullLoop's
|
|
290
|
+
// post-yield drain all consume from this buffer.
|
|
291
|
+
const pending: Buffer[] = [];
|
|
292
|
+
async function pullLoop(): Promise<void> {
|
|
293
|
+
// Yield once so the first transform() call can process the shell
|
|
294
|
+
// HTML chunk before we start reading RSC data.
|
|
295
|
+
await new Promise<void>((r) => setImmediate(r));
|
|
296
|
+
try {
|
|
297
|
+
for (;;) {
|
|
298
|
+
// Guard each RSC read with a timeout so a permanently hung
|
|
299
|
+
// RSC stream eventually aborts instead of blocking forever.
|
|
300
|
+
// See design/02-rendering-pipeline.md §"Streaming Constraints".
|
|
301
|
+
const readPromise = rscReader.read();
|
|
302
|
+
const { done, value } =
|
|
303
|
+
timeoutMs > 0
|
|
304
|
+
? await withTimeout(readPromise, timeoutMs, 'RSC stream read timed out')
|
|
305
|
+
: await readPromise;
|
|
306
|
+
if (done) {
|
|
307
|
+
machine.send({ type: 'PULL_DONE' });
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const decoded = decoder.decode(value, { stream: true });
|
|
311
|
+
const scriptBuf = Buffer.from(flightChunkScript(decoded), 'utf-8');
|
|
312
|
+
// Buffer the script — drained by the next transform() call,
|
|
313
|
+
// flush(), or by the scheduled drain below.
|
|
314
|
+
pending.push(scriptBuf);
|
|
315
|
+
// Yield between reads so HTML chunks get priority in the event
|
|
316
|
+
// loop — but only while HTML is still streaming. Once flush()
|
|
317
|
+
// fires, read without yielding to drain remaining RSC data.
|
|
318
|
+
if (!isHtmlDone(machine.state)) {
|
|
319
|
+
await new Promise<void>((r) => setImmediate(r));
|
|
320
|
+
// After yielding, if no transform() call drained the buffer
|
|
321
|
+
// (i.e., no new HTML chunk arrived), drain now. This ensures
|
|
322
|
+
// RSC flight data reaches the client at shell-flush time —
|
|
323
|
+
// without this, hydration blocks on createFromReadableStream
|
|
324
|
+
// waiting for data that's stuck in pending[].
|
|
325
|
+
// This is safe: we're between event loop ticks, so no
|
|
326
|
+
// transform() call is mid-execution (no mid-tag risk).
|
|
327
|
+
if (pending.length > 0) {
|
|
328
|
+
drainPending();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} catch (err) {
|
|
333
|
+
// On timeout, cancel the RSC reader to release resources.
|
|
334
|
+
if (err instanceof RenderTimeoutError) {
|
|
335
|
+
rscReader.cancel(err).catch(() => {});
|
|
336
|
+
}
|
|
337
|
+
machine.send({ type: 'PULL_ERROR', error: err });
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** Drain all buffered RSC script chunks to the transform output. */
|
|
342
|
+
function drainPending(): void {
|
|
343
|
+
while (pending.length > 0) {
|
|
344
|
+
transform.push(pending.shift()!);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// No bootstrap script here — the init script is in <head> via
|
|
349
|
+
// flightInitScript() (see flight-scripts.ts). This ensures __timber_f
|
|
350
|
+
// exists before any chunk scripts execute.
|
|
351
|
+
|
|
352
|
+
const transform = new Transform({
|
|
353
|
+
transform(chunk: Buffer, _encoding, callback) {
|
|
354
|
+
const isFirst = machine.state.phase === 'init';
|
|
355
|
+
if (isFirst) {
|
|
356
|
+
machine.send({ type: 'FIRST_CHUNK' });
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Emit the HTML chunk, then drain any buffered RSC scripts.
|
|
360
|
+
// Scripts always come AFTER a complete HTML chunk — never mid-tag.
|
|
361
|
+
// The buffered transform upstream (TIM-528) ensures each chunk is
|
|
362
|
+
// a coherent HTML fragment. Suffix stripping is handled upstream
|
|
363
|
+
// by createNodeMoveSuffixTransform (TIM-530).
|
|
364
|
+
transform.push(chunk);
|
|
365
|
+
drainPending();
|
|
366
|
+
|
|
367
|
+
// Start the pull loop on the first HTML chunk.
|
|
368
|
+
if (isFirst) {
|
|
369
|
+
pullPromise = pullLoop();
|
|
370
|
+
}
|
|
371
|
+
callback();
|
|
372
|
+
},
|
|
373
|
+
flush(callback) {
|
|
374
|
+
// All HTML chunks have been emitted. Transition to flushing —
|
|
375
|
+
// the pull loop will stop yielding between RSC reads since
|
|
376
|
+
// isHtmlDone() now returns true.
|
|
377
|
+
machine.send({ type: 'HTML_DONE' });
|
|
378
|
+
|
|
379
|
+
const finish = () => {
|
|
380
|
+
// Drain any remaining buffered RSC scripts
|
|
381
|
+
drainPending();
|
|
382
|
+
if (machine.state.phase === 'error') {
|
|
383
|
+
const err = machine.state.error;
|
|
384
|
+
transform.destroy(err instanceof Error ? err : new Error(String(err)));
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
callback();
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
if (isPullDone(machine.state)) {
|
|
391
|
+
finish();
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
// Wait for the RSC pull loop promise to resolve instead of
|
|
395
|
+
// polling with setImmediate. No CPU spin, no busy-poll —
|
|
396
|
+
// just a Promise chain. See design/02 §"No Polling".
|
|
397
|
+
if (!pullPromise) {
|
|
398
|
+
pullPromise = pullLoop();
|
|
399
|
+
}
|
|
400
|
+
pullPromise.then(finish, (err) => {
|
|
401
|
+
machine.send({ type: 'PULL_ERROR', error: err });
|
|
402
|
+
finish();
|
|
403
|
+
});
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return transform;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ─── Error Handling ──────────────────────────────────────────────────────────
|
|
411
|
+
|
|
412
|
+
const NOINDEX_SCRIPT =
|
|
413
|
+
'<script>document.head.appendChild(Object.assign(document.createElement("meta"),{name:"robots",content:"noindex"}))</script>';
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Node.js Transform that catches post-shell streaming errors.
|
|
417
|
+
*
|
|
418
|
+
* Equivalent to wrapStreamWithErrorHandling() in ssr-render.ts.
|
|
419
|
+
* Catches errors from React's streaming phase (deny/throw inside Suspense
|
|
420
|
+
* after the shell has flushed) and closes the stream cleanly.
|
|
421
|
+
*/
|
|
422
|
+
export function createNodeErrorHandler(signal?: AbortSignal): Transform {
|
|
423
|
+
const transform = new Transform({
|
|
424
|
+
transform(chunk, _encoding, callback) {
|
|
425
|
+
callback(null, chunk);
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
transform.on('error', (error) => {
|
|
430
|
+
const isAbort =
|
|
431
|
+
(error instanceof DOMException && error.name === 'AbortError') ||
|
|
432
|
+
(error instanceof Error && error.name === 'AbortError') ||
|
|
433
|
+
signal?.aborted;
|
|
434
|
+
|
|
435
|
+
if (isAbort) {
|
|
436
|
+
transform.end();
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
logStreamingError({ error });
|
|
441
|
+
transform.push(Buffer.from(NOINDEX_SCRIPT, 'utf-8'));
|
|
442
|
+
transform.end();
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
return transform;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// ─── Compression ─────────────────────────────────────────────────────────────
|
|
449
|
+
|
|
450
|
+
const COMPRESSIBLE_TYPES = new Set([
|
|
451
|
+
'text/html',
|
|
452
|
+
'text/css',
|
|
453
|
+
'text/plain',
|
|
454
|
+
'text/xml',
|
|
455
|
+
'text/javascript',
|
|
456
|
+
'text/x-component',
|
|
457
|
+
'application/json',
|
|
458
|
+
'application/javascript',
|
|
459
|
+
'application/xml',
|
|
460
|
+
'application/xhtml+xml',
|
|
461
|
+
'application/rss+xml',
|
|
462
|
+
'application/atom+xml',
|
|
463
|
+
'image/svg+xml',
|
|
464
|
+
]);
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Create a Node.js gzip Transform using native node:zlib.
|
|
468
|
+
*
|
|
469
|
+
* Uses `createGzip()` which is backed by C++ zlib — significantly faster
|
|
470
|
+
* than the Web Streams `CompressionStream` API (which is a JS wrapper
|
|
471
|
+
* around the same zlib but with per-chunk Promise overhead).
|
|
472
|
+
*
|
|
473
|
+
* Returns null if the response shouldn't be compressed (wrong content type,
|
|
474
|
+
* client doesn't accept gzip, already encoded, etc.).
|
|
475
|
+
*/
|
|
476
|
+
export function createNodeGzipCompressor(
|
|
477
|
+
requestHeaders: Headers,
|
|
478
|
+
responseHeaders: Headers
|
|
479
|
+
): Transform | null {
|
|
480
|
+
// Check Accept-Encoding
|
|
481
|
+
const acceptEncoding = requestHeaders.get('accept-encoding') || '';
|
|
482
|
+
if (!acceptEncoding.includes('gzip')) return null;
|
|
483
|
+
|
|
484
|
+
// Check content type is compressible
|
|
485
|
+
const contentType = responseHeaders.get('content-type') || '';
|
|
486
|
+
const mimeType = contentType.split(';')[0].trim().toLowerCase();
|
|
487
|
+
if (!COMPRESSIBLE_TYPES.has(mimeType)) return null;
|
|
488
|
+
|
|
489
|
+
// Don't double-compress
|
|
490
|
+
if (responseHeaders.has('content-encoding')) return null;
|
|
491
|
+
|
|
492
|
+
// Set response headers for gzip
|
|
493
|
+
responseHeaders.set('content-encoding', 'gzip');
|
|
494
|
+
responseHeaders.delete('content-length');
|
|
495
|
+
const existingVary = responseHeaders.get('vary');
|
|
496
|
+
if (existingVary) {
|
|
497
|
+
if (!existingVary.toLowerCase().includes('accept-encoding')) {
|
|
498
|
+
responseHeaders.set('vary', existingVary + ', Accept-Encoding');
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
responseHeaders.set('vary', 'Accept-Encoding');
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Z_SYNC_FLUSH ensures each chunk is flushed to the output immediately.
|
|
505
|
+
// Without it, gzip buffers internally and the browser doesn't receive
|
|
506
|
+
// the HTML shell until the gzip stream closes — breaking streaming.
|
|
507
|
+
// ~2–5% size overhead vs Z_NO_FLUSH but preserves correct streaming.
|
|
508
|
+
return createGzip({ flush: constants.Z_SYNC_FLUSH });
|
|
509
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PageDenyBoundary — catches DenySignal from page components server-side.
|
|
3
|
+
*
|
|
4
|
+
* Wraps a server component page by calling it as an async function (the same
|
|
5
|
+
* thing React Flight does internally). If the page throws DenySignal, the
|
|
6
|
+
* boundary catches it and renders the matching deny page as a normal element.
|
|
7
|
+
* No error reaches React Flight — the Flight stream is clean, SSR succeeds,
|
|
8
|
+
* and the entire request uses a single renderToReadableStream call.
|
|
9
|
+
*
|
|
10
|
+
* Client component pages ('use client') are NOT wrapped — they can't call
|
|
11
|
+
* deny() (server-only API) and must go through createElement normally.
|
|
12
|
+
*
|
|
13
|
+
* See design/04-authorization.md, design/10-error-handling.md, TIM-666.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { DenySignal } from './primitives.js';
|
|
17
|
+
import type { DenyPageEntry } from './deny-page-resolver.js';
|
|
18
|
+
import { renderMatchingDenyPage, setDenyStatus } from './deny-page-resolver.js';
|
|
19
|
+
import { withSpan } from './tracing.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Async server component that wraps a page call with DenySignal catching.
|
|
23
|
+
*
|
|
24
|
+
* Calls the page component as an async function, awaits it, and catches
|
|
25
|
+
* DenySignal. On catch, renders the deny page in-tree. On success, returns
|
|
26
|
+
* the page's rendered output normally.
|
|
27
|
+
*/
|
|
28
|
+
export async function PageDenyBoundary({
|
|
29
|
+
Page,
|
|
30
|
+
route,
|
|
31
|
+
denyPages,
|
|
32
|
+
}: {
|
|
33
|
+
/** The page server component function. */
|
|
34
|
+
Page: (...args: unknown[]) => unknown;
|
|
35
|
+
/** Route path for OTEL tracing. */
|
|
36
|
+
route: string;
|
|
37
|
+
/** Deny page fallback chain from the segment chain. */
|
|
38
|
+
denyPages: DenyPageEntry[];
|
|
39
|
+
}): Promise<React.ReactElement> {
|
|
40
|
+
try {
|
|
41
|
+
// Call the page as an async function — same as React Flight does.
|
|
42
|
+
// Wrap in OTEL span for tracing (replaces the TracedPage wrapper).
|
|
43
|
+
const result = await withSpan('timber.page', { 'timber.route': route }, () => Page({}));
|
|
44
|
+
return result as React.ReactElement;
|
|
45
|
+
} catch (error: unknown) {
|
|
46
|
+
if (error instanceof DenySignal) {
|
|
47
|
+
const denyElement = renderMatchingDenyPage(denyPages, error.status, error.data);
|
|
48
|
+
if (denyElement) {
|
|
49
|
+
setDenyStatus(error.status);
|
|
50
|
+
return denyElement;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Non-deny errors (RedirectSignal, runtime errors) propagate normally.
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* See design/07-routing.md §"Intercepting Routes"
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { classifyUrlSegment } from '../routing/segment-classify.js';
|
|
13
|
+
|
|
12
14
|
/** Result of a successful interception match. */
|
|
13
15
|
export interface InterceptionMatchResult {
|
|
14
16
|
/** The pathname to re-match (the source/intercepting route's parent). */
|
|
@@ -26,7 +28,7 @@ export interface InterceptionMatchResult {
|
|
|
26
28
|
export function findInterceptionMatch(
|
|
27
29
|
targetPathname: string,
|
|
28
30
|
sourceUrl: string,
|
|
29
|
-
rewrites: import('
|
|
31
|
+
rewrites: import('../routing/interception.js').InterceptionRewrite[]
|
|
30
32
|
): InterceptionMatchResult | null {
|
|
31
33
|
for (const rewrite of rewrites) {
|
|
32
34
|
// Check if the source URL starts with the intercepting prefix
|
|
@@ -53,23 +55,22 @@ export function pathnameMatchesPattern(pathname: string, pattern: string): boole
|
|
|
53
55
|
|
|
54
56
|
let pi = 0;
|
|
55
57
|
for (let i = 0; i < patternParts.length; i++) {
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
// Catch-all: [...param] or [[...param]] — matches rest of URL
|
|
59
|
-
if (segment.startsWith('[...') || segment.startsWith('[[...')) {
|
|
60
|
-
return pi < pathParts.length || segment.startsWith('[[...');
|
|
61
|
-
}
|
|
58
|
+
const seg = classifyUrlSegment(patternParts[i]);
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
switch (seg.kind) {
|
|
61
|
+
case 'catch-all':
|
|
62
|
+
return pi < pathParts.length;
|
|
63
|
+
case 'optional-catch-all':
|
|
64
|
+
return true;
|
|
65
|
+
case 'dynamic':
|
|
66
|
+
if (pi >= pathParts.length) return false;
|
|
67
|
+
pi++;
|
|
68
|
+
continue;
|
|
69
|
+
case 'static':
|
|
70
|
+
if (pi >= pathParts.length || pathParts[pi] !== seg.value) return false;
|
|
71
|
+
pi++;
|
|
72
|
+
continue;
|
|
68
73
|
}
|
|
69
|
-
|
|
70
|
-
// Static — must match exactly
|
|
71
|
-
if (pi >= pathParts.length || pathParts[pi] !== segment) return false;
|
|
72
|
-
pi++;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
return pi === pathParts.length;
|
|
@@ -79,6 +79,19 @@ export function serializeSitemap(
|
|
|
79
79
|
return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls}\n</urlset>`;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Serialize a sitemap index (list of sub-sitemap URLs) to XML.
|
|
84
|
+
* Used for pagination when the total URL count exceeds 50,000.
|
|
85
|
+
* Follows the sitemap.org protocol: https://www.sitemaps.org/protocol.html
|
|
86
|
+
*/
|
|
87
|
+
export function serializeSitemapIndex(sitemapUrls: string[]): string {
|
|
88
|
+
const sitemaps = sitemapUrls
|
|
89
|
+
.map((url) => ` <sitemap>\n <loc>${escapeXml(url)}</loc>\n </sitemap>`)
|
|
90
|
+
.join('\n');
|
|
91
|
+
|
|
92
|
+
return `<?xml version="1.0" encoding="UTF-8"?>\n<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${sitemaps}\n</sitemapindex>`;
|
|
93
|
+
}
|
|
94
|
+
|
|
82
95
|
/** Escape special XML characters. */
|
|
83
96
|
export function escapeXml(str: string): string {
|
|
84
97
|
return str
|