@rangojs/router 0.0.0-experimental.9 → 0.0.0-experimental.a06372ef
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/AGENTS.md +9 -0
- package/README.md +884 -4
- package/dist/__internal.d.ts +83 -0
- package/dist/__internal.d.ts.map +1 -0
- package/dist/__internal.js +19 -0
- package/dist/__internal.js.map +1 -0
- package/dist/__mocks__/version.d.ts +7 -0
- package/dist/__mocks__/version.d.ts.map +1 -0
- package/dist/__mocks__/version.js +7 -0
- package/dist/__mocks__/version.js.map +1 -0
- package/dist/__tests__/client-href.test.d.ts +2 -0
- package/dist/__tests__/client-href.test.d.ts.map +1 -0
- package/dist/__tests__/client-href.test.js +74 -0
- package/dist/__tests__/client-href.test.js.map +1 -0
- package/dist/__tests__/component-utils.test.d.ts +2 -0
- package/dist/__tests__/component-utils.test.d.ts.map +1 -0
- package/dist/__tests__/component-utils.test.js +51 -0
- package/dist/__tests__/component-utils.test.js.map +1 -0
- package/dist/__tests__/event-controller.test.d.ts +2 -0
- package/dist/__tests__/event-controller.test.d.ts.map +1 -0
- package/dist/__tests__/event-controller.test.js +538 -0
- package/dist/__tests__/event-controller.test.js.map +1 -0
- package/dist/__tests__/helpers/route-tree.d.ts +118 -0
- package/dist/__tests__/helpers/route-tree.d.ts.map +1 -0
- package/dist/__tests__/helpers/route-tree.js +374 -0
- package/dist/__tests__/helpers/route-tree.js.map +1 -0
- package/dist/__tests__/match-result.test.d.ts +2 -0
- package/dist/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/__tests__/match-result.test.js +154 -0
- package/dist/__tests__/match-result.test.js.map +1 -0
- package/dist/__tests__/navigation-store.test.d.ts +2 -0
- package/dist/__tests__/navigation-store.test.d.ts.map +1 -0
- package/dist/__tests__/navigation-store.test.js +440 -0
- package/dist/__tests__/navigation-store.test.js.map +1 -0
- package/dist/__tests__/partial-update.test.d.ts +2 -0
- package/dist/__tests__/partial-update.test.d.ts.map +1 -0
- package/dist/__tests__/partial-update.test.js +1009 -0
- package/dist/__tests__/partial-update.test.js.map +1 -0
- package/dist/__tests__/reverse-types.test.d.ts +8 -0
- package/dist/__tests__/reverse-types.test.d.ts.map +1 -0
- package/dist/__tests__/reverse-types.test.js +656 -0
- package/dist/__tests__/reverse-types.test.js.map +1 -0
- package/dist/__tests__/route-definition.test.d.ts +2 -0
- package/dist/__tests__/route-definition.test.d.ts.map +1 -0
- package/dist/__tests__/route-definition.test.js +55 -0
- package/dist/__tests__/route-definition.test.js.map +1 -0
- package/dist/__tests__/router-helpers.test.d.ts +2 -0
- package/dist/__tests__/router-helpers.test.d.ts.map +1 -0
- package/dist/__tests__/router-helpers.test.js +377 -0
- package/dist/__tests__/router-helpers.test.js.map +1 -0
- package/dist/__tests__/router-integration-2.test.d.ts +2 -0
- package/dist/__tests__/router-integration-2.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration-2.test.js +426 -0
- package/dist/__tests__/router-integration-2.test.js.map +1 -0
- package/dist/__tests__/router-integration.test.d.ts +2 -0
- package/dist/__tests__/router-integration.test.d.ts.map +1 -0
- package/dist/__tests__/router-integration.test.js +1051 -0
- package/dist/__tests__/router-integration.test.js.map +1 -0
- package/dist/__tests__/search-params.test.d.ts +5 -0
- package/dist/__tests__/search-params.test.d.ts.map +1 -0
- package/dist/__tests__/search-params.test.js +306 -0
- package/dist/__tests__/search-params.test.js.map +1 -0
- package/dist/__tests__/segment-system.test.d.ts +2 -0
- package/dist/__tests__/segment-system.test.d.ts.map +1 -0
- package/dist/__tests__/segment-system.test.js +627 -0
- package/dist/__tests__/segment-system.test.js.map +1 -0
- package/dist/__tests__/static-handler-types.test.d.ts +8 -0
- package/dist/__tests__/static-handler-types.test.d.ts.map +1 -0
- package/dist/__tests__/static-handler-types.test.js +63 -0
- package/dist/__tests__/static-handler-types.test.js.map +1 -0
- package/dist/__tests__/urls.test.d.ts +2 -0
- package/dist/__tests__/urls.test.d.ts.map +1 -0
- package/dist/__tests__/urls.test.js +421 -0
- package/dist/__tests__/urls.test.js.map +1 -0
- package/dist/__tests__/use-mount.test.d.ts +2 -0
- package/dist/__tests__/use-mount.test.d.ts.map +1 -0
- package/dist/__tests__/use-mount.test.js +35 -0
- package/dist/__tests__/use-mount.test.js.map +1 -0
- package/dist/bin/rango.d.ts +2 -0
- package/dist/bin/rango.d.ts.map +1 -0
- package/dist/bin/rango.js +1531 -155
- package/dist/bin/rango.js.map +1 -0
- package/dist/browser/event-controller.d.ts +191 -0
- package/dist/browser/event-controller.d.ts.map +1 -0
- package/dist/browser/event-controller.js +559 -0
- package/dist/browser/event-controller.js.map +1 -0
- package/dist/browser/index.d.ts +2 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +14 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/link-interceptor.d.ts +38 -0
- package/dist/browser/link-interceptor.d.ts.map +1 -0
- package/dist/browser/link-interceptor.js +99 -0
- package/dist/browser/link-interceptor.js.map +1 -0
- package/dist/browser/logging.d.ts +10 -0
- package/dist/browser/logging.d.ts.map +1 -0
- package/dist/browser/logging.js +29 -0
- package/dist/browser/logging.js.map +1 -0
- package/dist/browser/lru-cache.d.ts +17 -0
- package/dist/browser/lru-cache.d.ts.map +1 -0
- package/dist/browser/lru-cache.js +50 -0
- package/dist/browser/lru-cache.js.map +1 -0
- package/dist/browser/merge-segment-loaders.d.ts +39 -0
- package/dist/browser/merge-segment-loaders.d.ts.map +1 -0
- package/dist/browser/merge-segment-loaders.js +102 -0
- package/dist/browser/merge-segment-loaders.js.map +1 -0
- package/dist/browser/navigation-bridge.d.ts +102 -0
- package/dist/browser/navigation-bridge.d.ts.map +1 -0
- package/dist/browser/navigation-bridge.js +708 -0
- package/dist/browser/navigation-bridge.js.map +1 -0
- package/dist/browser/navigation-client.d.ts +25 -0
- package/dist/browser/navigation-client.d.ts.map +1 -0
- package/dist/browser/navigation-client.js +157 -0
- package/dist/browser/navigation-client.js.map +1 -0
- package/dist/browser/navigation-store.d.ts +101 -0
- package/dist/browser/navigation-store.d.ts.map +1 -0
- package/dist/browser/navigation-store.js +625 -0
- package/dist/browser/navigation-store.js.map +1 -0
- package/dist/browser/partial-update.d.ts +75 -0
- package/dist/browser/partial-update.d.ts.map +1 -0
- package/dist/browser/partial-update.js +426 -0
- package/dist/browser/partial-update.js.map +1 -0
- package/dist/browser/react/Link.d.ts +86 -0
- package/dist/browser/react/Link.d.ts.map +1 -0
- package/dist/browser/react/Link.js +128 -0
- package/dist/browser/react/Link.js.map +1 -0
- package/dist/browser/react/NavigationProvider.d.ts +63 -0
- package/dist/browser/react/NavigationProvider.d.ts.map +1 -0
- package/dist/browser/react/NavigationProvider.js +216 -0
- package/dist/browser/react/NavigationProvider.js.map +1 -0
- package/dist/browser/react/ScrollRestoration.d.ts +75 -0
- package/dist/browser/react/ScrollRestoration.d.ts.map +1 -0
- package/dist/browser/react/ScrollRestoration.js +57 -0
- package/dist/browser/react/ScrollRestoration.js.map +1 -0
- package/dist/browser/react/context.d.ts +46 -0
- package/dist/browser/react/context.d.ts.map +1 -0
- package/dist/browser/react/context.js +10 -0
- package/dist/browser/react/context.js.map +1 -0
- package/dist/browser/react/index.d.ts +11 -0
- package/dist/browser/react/index.d.ts.map +1 -0
- package/dist/browser/react/index.js +22 -0
- package/dist/browser/react/index.js.map +1 -0
- package/dist/browser/react/location-state-shared.d.ts +63 -0
- package/dist/browser/react/location-state-shared.d.ts.map +1 -0
- package/dist/browser/react/location-state-shared.js +81 -0
- package/dist/browser/react/location-state-shared.js.map +1 -0
- package/dist/browser/react/location-state.d.ts +23 -0
- package/dist/browser/react/location-state.d.ts.map +1 -0
- package/dist/browser/react/location-state.js +29 -0
- package/dist/browser/react/location-state.js.map +1 -0
- package/dist/browser/react/mount-context.d.ts +24 -0
- package/dist/browser/react/mount-context.d.ts.map +1 -0
- package/dist/browser/react/mount-context.js +24 -0
- package/dist/browser/react/mount-context.js.map +1 -0
- package/dist/browser/react/use-action.d.ts +64 -0
- package/dist/browser/react/use-action.d.ts.map +1 -0
- package/dist/browser/react/use-action.js +134 -0
- package/dist/browser/react/use-action.js.map +1 -0
- package/dist/browser/react/use-client-cache.d.ts +41 -0
- package/dist/browser/react/use-client-cache.d.ts.map +1 -0
- package/dist/browser/react/use-client-cache.js +39 -0
- package/dist/browser/react/use-client-cache.js.map +1 -0
- package/dist/browser/react/use-handle.d.ts +31 -0
- package/dist/browser/react/use-handle.d.ts.map +1 -0
- package/dist/browser/react/use-handle.js +144 -0
- package/dist/browser/react/use-handle.js.map +1 -0
- package/dist/browser/react/use-href.d.ts +33 -0
- package/dist/browser/react/use-href.d.ts.map +1 -0
- package/dist/browser/react/use-href.js +39 -0
- package/dist/browser/react/use-href.js.map +1 -0
- package/dist/browser/react/use-link-status.d.ts +37 -0
- package/dist/browser/react/use-link-status.d.ts.map +1 -0
- package/dist/browser/react/use-link-status.js +99 -0
- package/dist/browser/react/use-link-status.js.map +1 -0
- package/dist/browser/react/use-mount.d.ts +25 -0
- package/dist/browser/react/use-mount.d.ts.map +1 -0
- package/dist/browser/react/use-mount.js +30 -0
- package/dist/browser/react/use-mount.js.map +1 -0
- package/dist/browser/react/use-navigation.d.ts +27 -0
- package/dist/browser/react/use-navigation.d.ts.map +1 -0
- package/dist/browser/react/use-navigation.js +87 -0
- package/dist/browser/react/use-navigation.js.map +1 -0
- package/dist/browser/react/use-segments.d.ts +38 -0
- package/dist/browser/react/use-segments.d.ts.map +1 -0
- package/dist/browser/react/use-segments.js +130 -0
- package/dist/browser/react/use-segments.js.map +1 -0
- package/dist/browser/request-controller.d.ts +26 -0
- package/dist/browser/request-controller.d.ts.map +1 -0
- package/dist/browser/request-controller.js +147 -0
- package/dist/browser/request-controller.js.map +1 -0
- package/dist/browser/rsc-router.d.ts +129 -0
- package/dist/browser/rsc-router.d.ts.map +1 -0
- package/dist/browser/rsc-router.js +195 -0
- package/dist/browser/rsc-router.js.map +1 -0
- package/dist/browser/scroll-restoration.d.ts +93 -0
- package/dist/browser/scroll-restoration.d.ts.map +1 -0
- package/dist/browser/scroll-restoration.js +321 -0
- package/dist/browser/scroll-restoration.js.map +1 -0
- package/dist/browser/segment-structure-assert.d.ts +17 -0
- package/dist/browser/segment-structure-assert.d.ts.map +1 -0
- package/dist/browser/segment-structure-assert.js +59 -0
- package/dist/browser/segment-structure-assert.js.map +1 -0
- package/dist/browser/server-action-bridge.d.ts +26 -0
- package/dist/browser/server-action-bridge.d.ts.map +1 -0
- package/dist/browser/server-action-bridge.js +668 -0
- package/dist/browser/server-action-bridge.js.map +1 -0
- package/dist/browser/shallow.d.ts +12 -0
- package/dist/browser/shallow.d.ts.map +1 -0
- package/dist/browser/shallow.js +34 -0
- package/dist/browser/shallow.js.map +1 -0
- package/dist/browser/types.d.ts +369 -0
- package/dist/browser/types.d.ts.map +1 -0
- package/dist/browser/types.js +2 -0
- package/dist/browser/types.js.map +1 -0
- package/dist/build/__tests__/generate-cli.test.d.ts +2 -0
- package/dist/build/__tests__/generate-cli.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-cli.test.js +237 -0
- package/dist/build/__tests__/generate-cli.test.js.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/generate-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-manifest.test.js +119 -0
- package/dist/build/__tests__/generate-manifest.test.js.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts +2 -0
- package/dist/build/__tests__/generate-route-types.test.d.ts.map +1 -0
- package/dist/build/__tests__/generate-route-types.test.js +620 -0
- package/dist/build/__tests__/generate-route-types.test.js.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts +2 -0
- package/dist/build/__tests__/per-router-manifest.test.d.ts.map +1 -0
- package/dist/build/__tests__/per-router-manifest.test.js +308 -0
- package/dist/build/__tests__/per-router-manifest.test.js.map +1 -0
- package/dist/build/generate-manifest.d.ts +81 -0
- package/dist/build/generate-manifest.d.ts.map +1 -0
- package/dist/build/generate-manifest.js +276 -0
- package/dist/build/generate-manifest.js.map +1 -0
- package/dist/build/generate-route-types.d.ts +115 -0
- package/dist/build/generate-route-types.d.ts.map +1 -0
- package/dist/build/generate-route-types.js +740 -0
- package/dist/build/generate-route-types.js.map +1 -0
- package/dist/build/index.d.ts +21 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +21 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/route-trie.d.ts +71 -0
- package/dist/build/route-trie.d.ts.map +1 -0
- package/dist/build/route-trie.js +175 -0
- package/dist/build/route-trie.js.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts +2 -0
- package/dist/cache/__tests__/cache-scope.test.d.ts.map +1 -0
- package/dist/cache/__tests__/cache-scope.test.js +208 -0
- package/dist/cache/__tests__/cache-scope.test.js.map +1 -0
- package/dist/cache/__tests__/document-cache.test.d.ts +2 -0
- package/dist/cache/__tests__/document-cache.test.d.ts.map +1 -0
- package/dist/cache/__tests__/document-cache.test.js +345 -0
- package/dist/cache/__tests__/document-cache.test.js.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-segment-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-segment-store.test.js +425 -0
- package/dist/cache/__tests__/memory-segment-store.test.js.map +1 -0
- package/dist/cache/__tests__/memory-store.test.d.ts +2 -0
- package/dist/cache/__tests__/memory-store.test.d.ts.map +1 -0
- package/dist/cache/__tests__/memory-store.test.js +367 -0
- package/dist/cache/__tests__/memory-store.test.js.map +1 -0
- package/dist/cache/cache-scope.d.ts +102 -0
- package/dist/cache/cache-scope.d.ts.map +1 -0
- package/dist/cache/cache-scope.js +440 -0
- package/dist/cache/cache-scope.js.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts +2 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.d.ts.map +1 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js +330 -0
- package/dist/cache/cf/__tests__/cf-cache-store.test.js.map +1 -0
- package/dist/cache/cf/cf-cache-store.d.ts +165 -0
- package/dist/cache/cf/cf-cache-store.d.ts.map +1 -0
- package/dist/cache/cf/cf-cache-store.js +242 -0
- package/dist/cache/cf/cf-cache-store.js.map +1 -0
- package/dist/cache/cf/index.d.ts +14 -0
- package/dist/cache/cf/index.d.ts.map +1 -0
- package/dist/cache/cf/index.js +17 -0
- package/dist/cache/cf/index.js.map +1 -0
- package/dist/cache/document-cache.d.ts +64 -0
- package/dist/cache/document-cache.d.ts.map +1 -0
- package/dist/cache/document-cache.js +228 -0
- package/dist/cache/document-cache.js.map +1 -0
- package/dist/cache/index.d.ts +19 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +21 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/memory-segment-store.d.ts +110 -0
- package/dist/cache/memory-segment-store.d.ts.map +1 -0
- package/dist/cache/memory-segment-store.js +117 -0
- package/dist/cache/memory-segment-store.js.map +1 -0
- package/dist/cache/memory-store.d.ts +41 -0
- package/dist/cache/memory-store.d.ts.map +1 -0
- package/dist/cache/memory-store.js +191 -0
- package/dist/cache/memory-store.js.map +1 -0
- package/dist/cache/types.d.ts +317 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +12 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/client.d.ts +248 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +367 -0
- package/dist/client.js.map +1 -0
- package/dist/client.rsc.d.ts +26 -0
- package/dist/client.rsc.d.ts.map +1 -0
- package/dist/client.rsc.js +46 -0
- package/dist/client.rsc.js.map +1 -0
- package/dist/component-utils.d.ts +36 -0
- package/dist/component-utils.d.ts.map +1 -0
- package/dist/component-utils.js +61 -0
- package/dist/component-utils.js.map +1 -0
- package/dist/components/DefaultDocument.d.ts +13 -0
- package/dist/components/DefaultDocument.d.ts.map +1 -0
- package/dist/components/DefaultDocument.js +15 -0
- package/dist/components/DefaultDocument.js.map +1 -0
- package/dist/debug.d.ts +58 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/debug.js +157 -0
- package/dist/debug.js.map +1 -0
- package/dist/default-error-boundary.d.ts +11 -0
- package/dist/default-error-boundary.d.ts.map +1 -0
- package/dist/default-error-boundary.js +45 -0
- package/dist/default-error-boundary.js.map +1 -0
- package/dist/deps/browser.d.ts +2 -0
- package/dist/deps/browser.d.ts.map +1 -0
- package/dist/deps/browser.js +3 -0
- package/dist/deps/browser.js.map +1 -0
- package/dist/deps/html-stream-client.d.ts +2 -0
- package/dist/deps/html-stream-client.d.ts.map +1 -0
- package/dist/deps/html-stream-client.js +3 -0
- package/dist/deps/html-stream-client.js.map +1 -0
- package/dist/deps/html-stream-server.d.ts +2 -0
- package/dist/deps/html-stream-server.d.ts.map +1 -0
- package/dist/deps/html-stream-server.js +3 -0
- package/dist/deps/html-stream-server.js.map +1 -0
- package/dist/deps/rsc.d.ts +2 -0
- package/dist/deps/rsc.d.ts.map +1 -0
- package/dist/deps/rsc.js +4 -0
- package/dist/deps/rsc.js.map +1 -0
- package/dist/deps/ssr.d.ts +2 -0
- package/dist/deps/ssr.d.ts.map +1 -0
- package/dist/deps/ssr.js +3 -0
- package/dist/deps/ssr.js.map +1 -0
- package/dist/errors.d.ts +174 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +241 -0
- package/dist/errors.js.map +1 -0
- package/dist/handle.d.ts +78 -0
- package/dist/handle.d.ts.map +1 -0
- package/dist/handle.js +82 -0
- package/dist/handle.js.map +1 -0
- package/dist/handles/MetaTags.d.ts +14 -0
- package/dist/handles/MetaTags.d.ts.map +1 -0
- package/dist/handles/MetaTags.js +136 -0
- package/dist/handles/MetaTags.js.map +1 -0
- package/dist/handles/index.d.ts +6 -0
- package/dist/handles/index.d.ts.map +1 -0
- package/dist/handles/index.js +6 -0
- package/dist/handles/index.js.map +1 -0
- package/dist/handles/meta.d.ts +39 -0
- package/dist/handles/meta.d.ts.map +1 -0
- package/dist/handles/meta.js +202 -0
- package/dist/handles/meta.js.map +1 -0
- package/dist/host/__tests__/errors.test.d.ts +2 -0
- package/dist/host/__tests__/errors.test.d.ts.map +1 -0
- package/dist/host/__tests__/errors.test.js +76 -0
- package/dist/host/__tests__/errors.test.js.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-comprehensive.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js +732 -0
- package/dist/host/__tests__/pattern-comprehensive.test.js.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts +2 -0
- package/dist/host/__tests__/pattern-matcher.test.d.ts.map +1 -0
- package/dist/host/__tests__/pattern-matcher.test.js +251 -0
- package/dist/host/__tests__/pattern-matcher.test.js.map +1 -0
- package/dist/host/__tests__/router.test.d.ts +2 -0
- package/dist/host/__tests__/router.test.d.ts.map +1 -0
- package/dist/host/__tests__/router.test.js +241 -0
- package/dist/host/__tests__/router.test.js.map +1 -0
- package/dist/host/__tests__/testing.test.d.ts +2 -0
- package/dist/host/__tests__/testing.test.d.ts.map +1 -0
- package/dist/host/__tests__/testing.test.js +64 -0
- package/dist/host/__tests__/testing.test.js.map +1 -0
- package/dist/host/__tests__/utils.test.d.ts +2 -0
- package/dist/host/__tests__/utils.test.d.ts.map +1 -0
- package/dist/host/__tests__/utils.test.js +29 -0
- package/dist/host/__tests__/utils.test.js.map +1 -0
- package/dist/host/cookie-handler.d.ts +34 -0
- package/dist/host/cookie-handler.d.ts.map +1 -0
- package/dist/host/cookie-handler.js +124 -0
- package/dist/host/cookie-handler.js.map +1 -0
- package/dist/host/errors.d.ts +56 -0
- package/dist/host/errors.d.ts.map +1 -0
- package/dist/host/errors.js +79 -0
- package/dist/host/errors.js.map +1 -0
- package/dist/host/index.d.ts +29 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +32 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/pattern-matcher.d.ts +36 -0
- package/dist/host/pattern-matcher.d.ts.map +1 -0
- package/dist/host/pattern-matcher.js +172 -0
- package/dist/host/pattern-matcher.js.map +1 -0
- package/dist/host/router.d.ts +26 -0
- package/dist/host/router.d.ts.map +1 -0
- package/dist/host/router.js +218 -0
- package/dist/host/router.js.map +1 -0
- package/dist/host/testing.d.ts +36 -0
- package/dist/host/testing.d.ts.map +1 -0
- package/dist/host/testing.js +55 -0
- package/dist/host/testing.js.map +1 -0
- package/dist/host/types.d.ts +115 -0
- package/dist/host/types.d.ts.map +1 -0
- package/dist/host/types.js +7 -0
- package/dist/host/types.js.map +1 -0
- package/dist/host/utils.d.ts +21 -0
- package/dist/host/utils.d.ts.map +1 -0
- package/dist/host/utils.js +23 -0
- package/dist/host/utils.js.map +1 -0
- package/dist/href-client.d.ts +131 -0
- package/dist/href-client.d.ts.map +1 -0
- package/dist/href-client.js +64 -0
- package/dist/href-client.js.map +1 -0
- package/{src/href-context.ts → dist/href-context.d.ts} +7 -11
- package/dist/href-context.d.ts.map +1 -0
- package/dist/href-context.js +21 -0
- package/dist/href-context.js.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/index.rsc.d.ts +32 -0
- package/dist/index.rsc.d.ts.map +1 -0
- package/dist/index.rsc.js +40 -0
- package/dist/index.rsc.js.map +1 -0
- package/dist/internal-debug.d.ts +2 -0
- package/dist/internal-debug.d.ts.map +1 -0
- package/dist/internal-debug.js +5 -0
- package/dist/internal-debug.js.map +1 -0
- package/dist/loader.d.ts +14 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +20 -0
- package/dist/loader.js.map +1 -0
- package/dist/loader.rsc.d.ts +19 -0
- package/dist/loader.rsc.d.ts.map +1 -0
- package/dist/loader.rsc.js +99 -0
- package/dist/loader.rsc.js.map +1 -0
- package/dist/network-error-thrower.d.ts +17 -0
- package/dist/network-error-thrower.d.ts.map +1 -0
- package/dist/network-error-thrower.js +14 -0
- package/dist/network-error-thrower.js.map +1 -0
- package/dist/outlet-context.d.ts +13 -0
- package/dist/outlet-context.d.ts.map +1 -0
- package/dist/outlet-context.js +3 -0
- package/dist/outlet-context.js.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts +2 -0
- package/dist/prerender/__tests__/param-hash.test.d.ts.map +1 -0
- package/dist/prerender/__tests__/param-hash.test.js +148 -0
- package/dist/prerender/__tests__/param-hash.test.js.map +1 -0
- package/dist/prerender/param-hash.d.ts +16 -0
- package/dist/prerender/param-hash.d.ts.map +1 -0
- package/dist/prerender/param-hash.js +36 -0
- package/dist/prerender/param-hash.js.map +1 -0
- package/dist/prerender/store.d.ts +38 -0
- package/dist/prerender/store.d.ts.map +1 -0
- package/dist/prerender/store.js +61 -0
- package/dist/prerender/store.js.map +1 -0
- package/dist/prerender.d.ts +66 -0
- package/dist/prerender.d.ts.map +1 -0
- package/dist/prerender.js +57 -0
- package/dist/prerender.js.map +1 -0
- package/dist/reverse.d.ts +196 -0
- package/dist/reverse.d.ts.map +1 -0
- package/dist/reverse.js +78 -0
- package/dist/reverse.js.map +1 -0
- package/dist/root-error-boundary.d.ts +33 -0
- package/dist/root-error-boundary.d.ts.map +1 -0
- package/dist/root-error-boundary.js +165 -0
- package/dist/root-error-boundary.js.map +1 -0
- package/dist/route-content-wrapper.d.ts +46 -0
- package/dist/route-content-wrapper.d.ts.map +1 -0
- package/dist/route-content-wrapper.js +77 -0
- package/dist/route-content-wrapper.js.map +1 -0
- package/dist/route-definition.d.ts +421 -0
- package/dist/route-definition.d.ts.map +1 -0
- package/dist/route-definition.js +868 -0
- package/dist/route-definition.js.map +1 -0
- package/dist/route-map-builder.d.ts +155 -0
- package/dist/route-map-builder.d.ts.map +1 -0
- package/dist/route-map-builder.js +237 -0
- package/dist/route-map-builder.js.map +1 -0
- package/dist/route-types.d.ts +165 -0
- package/dist/route-types.d.ts.map +1 -0
- package/dist/route-types.js +7 -0
- package/dist/route-types.js.map +1 -0
- package/dist/router/__tests__/handler-context.test.d.ts +2 -0
- package/dist/router/__tests__/handler-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/handler-context.test.js +65 -0
- package/dist/router/__tests__/handler-context.test.js.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts +2 -0
- package/dist/router/__tests__/loader-cycle-detection.test.d.ts.map +1 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js +221 -0
- package/dist/router/__tests__/loader-cycle-detection.test.js.map +1 -0
- package/dist/router/__tests__/match-context.test.d.ts +2 -0
- package/dist/router/__tests__/match-context.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-context.test.js +92 -0
- package/dist/router/__tests__/match-context.test.js.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts +2 -0
- package/dist/router/__tests__/match-pipelines.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-pipelines.test.js +417 -0
- package/dist/router/__tests__/match-pipelines.test.js.map +1 -0
- package/dist/router/__tests__/match-result.test.d.ts +2 -0
- package/dist/router/__tests__/match-result.test.d.ts.map +1 -0
- package/dist/router/__tests__/match-result.test.js +457 -0
- package/dist/router/__tests__/match-result.test.js.map +1 -0
- package/dist/router/__tests__/on-error.test.d.ts +2 -0
- package/dist/router/__tests__/on-error.test.d.ts.map +1 -0
- package/dist/router/__tests__/on-error.test.js +678 -0
- package/dist/router/__tests__/on-error.test.js.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts +2 -0
- package/dist/router/__tests__/pattern-matching.test.d.ts.map +1 -0
- package/dist/router/__tests__/pattern-matching.test.js +629 -0
- package/dist/router/__tests__/pattern-matching.test.js.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts +2 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.d.ts.map +1 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js +155 -0
- package/dist/router/__tests__/segment-resolution-parallel-loading.test.js.map +1 -0
- package/dist/router/error-handling.d.ts +77 -0
- package/dist/router/error-handling.d.ts.map +1 -0
- package/dist/router/error-handling.js +202 -0
- package/dist/router/error-handling.js.map +1 -0
- package/dist/router/handler-context.d.ts +20 -0
- package/dist/router/handler-context.d.ts.map +1 -0
- package/dist/router/handler-context.js +198 -0
- package/dist/router/handler-context.js.map +1 -0
- package/dist/router/intercept-resolution.d.ts +66 -0
- package/dist/router/intercept-resolution.d.ts.map +1 -0
- package/dist/router/intercept-resolution.js +246 -0
- package/dist/router/intercept-resolution.js.map +1 -0
- package/dist/router/loader-resolution.d.ts +64 -0
- package/dist/router/loader-resolution.d.ts.map +1 -0
- package/dist/router/loader-resolution.js +284 -0
- package/dist/router/loader-resolution.js.map +1 -0
- package/dist/router/logging.d.ts +15 -0
- package/dist/router/logging.d.ts.map +1 -0
- package/dist/router/logging.js +99 -0
- package/dist/router/logging.js.map +1 -0
- package/dist/router/manifest.d.ts +22 -0
- package/dist/router/manifest.d.ts.map +1 -0
- package/dist/router/manifest.js +181 -0
- package/dist/router/manifest.js.map +1 -0
- package/dist/router/match-api.d.ts +35 -0
- package/dist/router/match-api.d.ts.map +1 -0
- package/dist/router/match-api.js +406 -0
- package/dist/router/match-api.js.map +1 -0
- package/dist/router/match-context.d.ts +206 -0
- package/dist/router/match-context.d.ts.map +1 -0
- package/dist/router/match-context.js +17 -0
- package/dist/router/match-context.js.map +1 -0
- package/dist/router/match-middleware/background-revalidation.d.ts +127 -0
- package/dist/router/match-middleware/background-revalidation.d.ts.map +1 -0
- package/dist/router/match-middleware/background-revalidation.js +75 -0
- package/dist/router/match-middleware/background-revalidation.js.map +1 -0
- package/dist/router/match-middleware/cache-lookup.d.ts +112 -0
- package/dist/router/match-middleware/cache-lookup.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-lookup.js +257 -0
- package/dist/router/match-middleware/cache-lookup.js.map +1 -0
- package/dist/router/match-middleware/cache-store.d.ts +113 -0
- package/dist/router/match-middleware/cache-store.d.ts.map +1 -0
- package/dist/router/match-middleware/cache-store.js +108 -0
- package/dist/router/match-middleware/cache-store.js.map +1 -0
- package/dist/router/match-middleware/index.d.ts +81 -0
- package/dist/router/match-middleware/index.d.ts.map +1 -0
- package/dist/router/match-middleware/index.js +80 -0
- package/dist/router/match-middleware/index.js.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts +117 -0
- package/dist/router/match-middleware/intercept-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/intercept-resolution.js +134 -0
- package/dist/router/match-middleware/intercept-resolution.js.map +1 -0
- package/dist/router/match-middleware/segment-resolution.d.ts +99 -0
- package/dist/router/match-middleware/segment-resolution.d.ts.map +1 -0
- package/dist/router/match-middleware/segment-resolution.js +53 -0
- package/dist/router/match-middleware/segment-resolution.js.map +1 -0
- package/dist/router/match-pipelines.d.ts +147 -0
- package/dist/router/match-pipelines.d.ts.map +1 -0
- package/dist/router/match-pipelines.js +82 -0
- package/dist/router/match-pipelines.js.map +1 -0
- package/dist/router/match-result.d.ts +126 -0
- package/dist/router/match-result.d.ts.map +1 -0
- package/dist/router/match-result.js +93 -0
- package/dist/router/match-result.js.map +1 -0
- package/dist/router/metrics.d.ts +20 -0
- package/dist/router/metrics.d.ts.map +1 -0
- package/dist/router/metrics.js +47 -0
- package/dist/router/metrics.js.map +1 -0
- package/dist/router/middleware.d.ts +249 -0
- package/dist/router/middleware.d.ts.map +1 -0
- package/dist/router/middleware.js +434 -0
- package/dist/router/middleware.js.map +1 -0
- package/dist/router/middleware.test.d.ts +2 -0
- package/dist/router/middleware.test.d.ts.map +1 -0
- package/dist/router/middleware.test.js +816 -0
- package/dist/router/middleware.test.js.map +1 -0
- package/dist/router/pattern-matching.d.ts +149 -0
- package/dist/router/pattern-matching.d.ts.map +1 -0
- package/dist/router/pattern-matching.js +349 -0
- package/dist/router/pattern-matching.js.map +1 -0
- package/dist/router/revalidation.d.ts +44 -0
- package/dist/router/revalidation.d.ts.map +1 -0
- package/dist/router/revalidation.js +147 -0
- package/dist/router/revalidation.js.map +1 -0
- package/dist/router/router-context.d.ts +135 -0
- package/dist/router/router-context.d.ts.map +1 -0
- package/dist/router/router-context.js +36 -0
- package/dist/router/router-context.js.map +1 -0
- package/dist/router/segment-resolution.d.ts +127 -0
- package/dist/router/segment-resolution.d.ts.map +1 -0
- package/dist/router/segment-resolution.js +919 -0
- package/dist/router/segment-resolution.js.map +1 -0
- package/dist/router/trie-matching.d.ts +40 -0
- package/dist/router/trie-matching.d.ts.map +1 -0
- package/dist/router/trie-matching.js +127 -0
- package/dist/router/trie-matching.js.map +1 -0
- package/dist/router/types.d.ts +136 -0
- package/dist/router/types.d.ts.map +1 -0
- package/dist/router/types.js +7 -0
- package/dist/router/types.js.map +1 -0
- package/dist/router.d.ts +753 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.gen.d.ts +6 -0
- package/dist/router.gen.d.ts.map +1 -0
- package/dist/router.gen.js +6 -0
- package/dist/router.gen.js.map +1 -0
- package/dist/router.js +1304 -0
- package/dist/router.js.map +1 -0
- package/dist/rsc/__tests__/helpers.test.d.ts +2 -0
- package/dist/rsc/__tests__/helpers.test.d.ts.map +1 -0
- package/dist/rsc/__tests__/helpers.test.js +140 -0
- package/dist/rsc/__tests__/helpers.test.js.map +1 -0
- package/dist/rsc/handler.d.ts +45 -0
- package/dist/rsc/handler.d.ts.map +1 -0
- package/dist/rsc/handler.js +1172 -0
- package/dist/rsc/handler.js.map +1 -0
- package/dist/rsc/helpers.d.ts +16 -0
- package/dist/rsc/helpers.d.ts.map +1 -0
- package/dist/rsc/helpers.js +55 -0
- package/dist/rsc/helpers.js.map +1 -0
- package/dist/rsc/index.d.ts +22 -0
- package/dist/rsc/index.d.ts.map +1 -0
- package/dist/rsc/index.js +23 -0
- package/dist/rsc/index.js.map +1 -0
- package/dist/rsc/nonce.d.ts +9 -0
- package/dist/rsc/nonce.d.ts.map +1 -0
- package/dist/rsc/nonce.js +18 -0
- package/dist/rsc/nonce.js.map +1 -0
- package/dist/rsc/types.d.ts +206 -0
- package/dist/rsc/types.d.ts.map +1 -0
- package/dist/rsc/types.js +8 -0
- package/dist/rsc/types.js.map +1 -0
- package/dist/search-params.d.ts +103 -0
- package/dist/search-params.d.ts.map +1 -0
- package/dist/search-params.js +74 -0
- package/dist/search-params.js.map +1 -0
- package/dist/segment-system.d.ts +75 -0
- package/dist/segment-system.d.ts.map +1 -0
- package/dist/segment-system.js +336 -0
- package/dist/segment-system.js.map +1 -0
- package/dist/server/context.d.ts +245 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +197 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/fetchable-loader-store.d.ts +18 -0
- package/dist/server/fetchable-loader-store.d.ts.map +1 -0
- package/dist/server/fetchable-loader-store.js +18 -0
- package/dist/server/fetchable-loader-store.js.map +1 -0
- package/dist/server/handle-store.d.ts +85 -0
- package/dist/server/handle-store.d.ts.map +1 -0
- package/dist/server/handle-store.js +142 -0
- package/dist/server/handle-store.js.map +1 -0
- package/dist/server/loader-registry.d.ts +55 -0
- package/dist/server/loader-registry.d.ts.map +1 -0
- package/dist/server/loader-registry.js +132 -0
- package/dist/server/loader-registry.js.map +1 -0
- package/dist/server/request-context.d.ts +226 -0
- package/dist/server/request-context.d.ts.map +1 -0
- package/dist/server/request-context.js +290 -0
- package/dist/server/request-context.js.map +1 -0
- package/dist/server/root-layout.d.ts +4 -0
- package/dist/server/root-layout.d.ts.map +1 -0
- package/dist/server/root-layout.js +5 -0
- package/dist/server/root-layout.js.map +1 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +20 -0
- package/dist/server.js.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts +2 -0
- package/dist/ssr/__tests__/ssr-handler.test.d.ts.map +1 -0
- package/dist/ssr/__tests__/ssr-handler.test.js +132 -0
- package/dist/ssr/__tests__/ssr-handler.test.js.map +1 -0
- package/dist/ssr/index.d.ts +98 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +158 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/static-handler.d.ts +50 -0
- package/dist/static-handler.d.ts.map +1 -0
- package/dist/static-handler.gen.d.ts +5 -0
- package/dist/static-handler.gen.d.ts.map +1 -0
- package/dist/static-handler.gen.js +5 -0
- package/dist/static-handler.gen.js.map +1 -0
- package/dist/static-handler.js +29 -0
- package/dist/static-handler.js.map +1 -0
- package/dist/theme/ThemeProvider.d.ts +20 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +240 -0
- package/dist/theme/ThemeProvider.js.map +1 -0
- package/dist/theme/ThemeScript.d.ts +48 -0
- package/dist/theme/ThemeScript.d.ts.map +1 -0
- package/dist/theme/ThemeScript.js +13 -0
- package/dist/theme/ThemeScript.js.map +1 -0
- package/dist/theme/__tests__/theme.test.d.ts +2 -0
- package/dist/theme/__tests__/theme.test.d.ts.map +1 -0
- package/dist/theme/__tests__/theme.test.js +103 -0
- package/dist/theme/__tests__/theme.test.js.map +1 -0
- package/dist/theme/constants.d.ts +29 -0
- package/dist/theme/constants.d.ts.map +1 -0
- package/dist/theme/constants.js +48 -0
- package/dist/theme/constants.js.map +1 -0
- package/dist/theme/index.d.ts +31 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +36 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-context.d.ts +40 -0
- package/dist/theme/theme-context.d.ts.map +1 -0
- package/dist/theme/theme-context.js +60 -0
- package/dist/theme/theme-context.js.map +1 -0
- package/dist/theme/theme-script.d.ts +27 -0
- package/dist/theme/theme-script.d.ts.map +1 -0
- package/dist/theme/theme-script.js +147 -0
- package/dist/theme/theme-script.js.map +1 -0
- package/dist/theme/types.d.ts +163 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +11 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/theme/use-theme.d.ts +12 -0
- package/dist/theme/use-theme.d.ts.map +1 -0
- package/dist/theme/use-theme.js +40 -0
- package/dist/theme/use-theme.js.map +1 -0
- package/dist/types.d.ts +1479 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/dist/urls.d.ts +441 -0
- package/dist/urls.d.ts.map +1 -0
- package/dist/urls.gen.d.ts +8 -0
- package/dist/urls.gen.d.ts.map +1 -0
- package/dist/urls.gen.js +8 -0
- package/dist/urls.gen.js.map +1 -0
- package/dist/urls.js +443 -0
- package/dist/urls.js.map +1 -0
- package/dist/use-loader.d.ts +127 -0
- package/dist/use-loader.d.ts.map +1 -0
- package/dist/use-loader.js +237 -0
- package/dist/use-loader.js.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts +2 -0
- package/dist/vite/__tests__/ast-handler-extract.test.d.ts.map +1 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js +294 -0
- package/dist/vite/__tests__/ast-handler-extract.test.js.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-id-utils.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-id-utils.test.js +224 -0
- package/dist/vite/__tests__/expose-id-utils.test.js.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-internal-ids.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js +647 -0
- package/dist/vite/__tests__/expose-internal-ids.test.js.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts +2 -0
- package/dist/vite/__tests__/expose-router-id.test.d.ts.map +1 -0
- package/dist/vite/__tests__/expose-router-id.test.js +39 -0
- package/dist/vite/__tests__/expose-router-id.test.js.map +1 -0
- package/dist/vite/ast-handler-extract.d.ts +49 -0
- package/dist/vite/ast-handler-extract.d.ts.map +1 -0
- package/dist/vite/ast-handler-extract.js +249 -0
- package/dist/vite/ast-handler-extract.js.map +1 -0
- package/dist/vite/expose-action-id.d.ts +19 -0
- package/dist/vite/expose-action-id.d.ts.map +1 -0
- package/dist/vite/expose-action-id.js +250 -0
- package/dist/vite/expose-action-id.js.map +1 -0
- package/dist/vite/expose-id-utils.d.ts +69 -0
- package/dist/vite/expose-id-utils.d.ts.map +1 -0
- package/dist/vite/expose-id-utils.js +289 -0
- package/dist/vite/expose-id-utils.js.map +1 -0
- package/dist/vite/expose-internal-ids.d.ts +22 -0
- package/dist/vite/expose-internal-ids.d.ts.map +1 -0
- package/dist/vite/expose-internal-ids.js +886 -0
- package/dist/vite/expose-internal-ids.js.map +1 -0
- package/dist/vite/index.d.ts +149 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +4440 -2170
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/index.named-routes.gen.ts +103 -0
- package/dist/vite/package-resolution.d.ts +43 -0
- package/dist/vite/package-resolution.d.ts.map +1 -0
- package/dist/vite/package-resolution.js +112 -0
- package/dist/vite/package-resolution.js.map +1 -0
- package/dist/vite/virtual-entries.d.ts +25 -0
- package/dist/vite/virtual-entries.d.ts.map +1 -0
- package/{src/vite/virtual-entries.ts → dist/vite/virtual-entries.js} +12 -16
- package/dist/vite/virtual-entries.js.map +1 -0
- package/package.json +69 -62
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +262 -0
- package/skills/caching/SKILL.md +50 -21
- package/skills/composability/SKILL.md +172 -0
- package/skills/debug-manifest/SKILL.md +12 -8
- package/skills/document-cache/SKILL.md +18 -16
- package/skills/fonts/SKILL.md +6 -4
- package/skills/hooks/SKILL.md +333 -71
- package/skills/host-router/SKILL.md +218 -0
- package/skills/intercept/SKILL.md +131 -8
- package/skills/layout/SKILL.md +100 -3
- package/skills/links/SKILL.md +74 -15
- package/skills/loader/SKILL.md +388 -38
- package/skills/middleware/SKILL.md +171 -34
- package/skills/mime-routes/SKILL.md +15 -11
- package/skills/parallel/SKILL.md +78 -1
- package/skills/prerender/SKILL.md +405 -45
- package/skills/rango/SKILL.md +85 -21
- package/skills/response-routes/SKILL.md +144 -91
- package/skills/route/SKILL.md +226 -14
- package/skills/router-setup/SKILL.md +123 -30
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +316 -87
- package/skills/use-cache/SKILL.md +324 -0
- package/src/__internal.ts +102 -4
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +97 -0
- package/src/browser/action-response-classifier.ts +99 -0
- package/src/browser/event-controller.ts +87 -64
- package/src/browser/history-state.ts +80 -0
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +55 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +281 -554
- package/src/browser/navigation-client.ts +123 -73
- package/src/browser/navigation-store.ts +33 -50
- package/src/browser/navigation-transaction.ts +295 -0
- package/src/browser/network-error-handler.ts +61 -0
- package/src/browser/partial-update.ts +261 -309
- package/src/browser/prefetch/cache.ts +154 -0
- package/src/browser/prefetch/fetch.ts +135 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +88 -0
- package/src/browser/rango-state.ts +112 -0
- package/src/browser/react/Link.tsx +182 -70
- package/src/browser/react/NavigationProvider.tsx +51 -11
- package/src/browser/react/context.ts +6 -0
- package/src/browser/react/filter-segment-order.ts +11 -0
- package/src/browser/react/index.ts +12 -12
- package/src/browser/react/location-state-shared.ts +95 -53
- package/src/browser/react/location-state.ts +60 -15
- package/src/browser/react/mount-context.ts +6 -1
- package/src/browser/react/nonce-context.ts +23 -0
- package/src/browser/react/shallow-equal.ts +27 -0
- package/src/browser/react/use-action.ts +29 -51
- package/src/browser/react/use-client-cache.ts +5 -3
- package/src/browser/react/use-handle.ts +29 -70
- package/src/browser/react/use-link-status.ts +6 -5
- package/src/browser/react/use-navigation.ts +22 -63
- package/src/browser/react/use-params.ts +65 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-router.ts +63 -0
- package/src/browser/react/use-search-params.ts +56 -0
- package/src/browser/react/use-segments.ts +80 -97
- package/src/browser/response-adapter.ts +73 -0
- package/src/browser/rsc-router.tsx +106 -27
- package/src/browser/scroll-restoration.ts +98 -38
- package/src/browser/segment-reconciler.ts +216 -0
- package/src/browser/segment-structure-assert.ts +16 -0
- package/src/browser/server-action-bridge.ts +504 -599
- package/src/browser/shallow.ts +6 -1
- package/src/browser/types.ts +107 -47
- package/src/browser/validate-redirect-origin.ts +29 -0
- package/src/build/generate-manifest.ts +82 -21
- package/src/build/generate-route-types.ts +36 -752
- package/src/build/index.ts +6 -5
- package/src/build/route-trie.ts +39 -13
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +98 -0
- package/src/build/route-types/codegen.ts +102 -0
- package/src/build/route-types/include-resolution.ts +411 -0
- package/src/build/route-types/param-extraction.ts +48 -0
- package/src/build/route-types/per-module-writer.ts +128 -0
- package/src/build/route-types/router-processing.ts +469 -0
- package/src/build/route-types/scan-filter.ts +78 -0
- package/src/build/runtime-discovery.ts +231 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-key-utils.ts +44 -0
- package/src/cache/cache-policy.ts +125 -0
- package/src/cache/cache-runtime.ts +338 -0
- package/src/cache/cache-scope.ts +120 -301
- package/src/cache/cf/cf-cache-store.ts +119 -7
- package/src/cache/cf/index.ts +8 -2
- package/src/cache/document-cache.ts +101 -72
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +41 -0
- package/src/cache/index.ts +0 -15
- package/src/cache/memory-segment-store.ts +191 -13
- package/src/cache/profile-registry.ts +73 -0
- package/src/cache/read-through-swr.ts +134 -0
- package/src/cache/segment-codec.ts +256 -0
- package/src/cache/taint.ts +98 -0
- package/src/cache/types.ts +72 -122
- package/src/client.rsc.tsx +3 -1
- package/src/client.tsx +84 -126
- package/src/component-utils.ts +4 -4
- package/src/components/DefaultDocument.tsx +5 -1
- package/src/context-var.ts +86 -0
- package/src/debug.ts +17 -7
- package/src/errors.ts +77 -7
- package/src/handle.ts +15 -10
- package/src/handles/MetaTags.tsx +73 -20
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/handles/meta.ts +30 -13
- package/src/host/cookie-handler.ts +21 -15
- package/src/host/errors.ts +8 -8
- package/src/host/index.ts +4 -7
- package/src/host/pattern-matcher.ts +27 -27
- package/src/host/router.ts +61 -39
- package/src/host/testing.ts +8 -8
- package/src/host/types.ts +15 -7
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +65 -45
- package/src/index.rsc.ts +133 -21
- package/src/index.ts +164 -52
- package/src/internal-debug.ts +11 -0
- package/src/loader.rsc.ts +25 -143
- package/src/loader.ts +27 -10
- package/src/network-error-thrower.tsx +3 -1
- package/src/outlet-provider.tsx +45 -0
- package/src/prerender/param-hash.ts +4 -2
- package/src/prerender/store.ts +158 -13
- package/src/prerender.ts +333 -26
- package/src/reverse.ts +184 -121
- package/src/root-error-boundary.tsx +41 -29
- package/src/route-content-wrapper.tsx +7 -4
- package/src/route-definition/dsl-helpers.ts +934 -0
- package/src/route-definition/helper-factories.ts +200 -0
- package/src/route-definition/helpers-types.ts +430 -0
- package/src/route-definition/index.ts +52 -0
- package/src/route-definition/redirect.ts +93 -0
- package/src/route-definition.ts +1 -1431
- package/src/route-map-builder.ts +156 -123
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +48 -9
- package/src/router/content-negotiation.ts +116 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +9 -9
- package/src/router/find-match.ts +158 -0
- package/src/router/handler-context.ts +374 -81
- package/src/router/intercept-resolution.ts +26 -16
- package/src/router/lazy-includes.ts +234 -0
- package/src/router/loader-resolution.ts +215 -122
- package/src/router/logging.ts +251 -0
- package/src/router/manifest.ts +83 -32
- package/src/router/match-api.ts +118 -119
- package/src/router/match-context.ts +4 -2
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +80 -93
- package/src/router/match-middleware/cache-lookup.ts +336 -84
- package/src/router/match-middleware/cache-store.ts +43 -24
- package/src/router/match-middleware/intercept-resolution.ts +45 -20
- package/src/router/match-middleware/segment-resolution.ts +17 -8
- package/src/router/match-pipelines.ts +10 -45
- package/src/router/match-result.ts +34 -28
- package/src/router/metrics.ts +235 -15
- package/src/router/middleware-cookies.ts +55 -0
- package/src/router/middleware-types.ts +222 -0
- package/src/router/middleware.ts +324 -367
- package/src/router/pattern-matching.ts +197 -41
- package/src/router/prerender-match.ts +402 -0
- package/src/router/preview-match.ts +170 -0
- package/src/router/revalidation.ts +137 -38
- package/src/router/router-context.ts +40 -21
- package/src/router/router-interfaces.ts +452 -0
- package/src/router/router-options.ts +592 -0
- package/src/router/router-registry.ts +24 -0
- package/src/router/segment-resolution/fresh.ts +570 -0
- package/src/router/segment-resolution/helpers.ts +263 -0
- package/src/router/segment-resolution/loader-cache.ts +198 -0
- package/src/router/segment-resolution/revalidation.ts +1242 -0
- package/src/router/segment-resolution/static-store.ts +67 -0
- package/src/router/segment-resolution.ts +21 -1315
- package/src/router/segment-wrappers.ts +291 -0
- package/src/router/telemetry-otel.ts +299 -0
- package/src/router/telemetry.ts +300 -0
- package/src/router/timeout.ts +148 -0
- package/src/router/trie-matching.ts +96 -29
- package/src/router/types.ts +16 -9
- package/src/router.ts +590 -1983
- package/src/rsc/handler-context.ts +45 -0
- package/src/rsc/handler.ts +652 -1015
- package/src/rsc/helpers.ts +140 -6
- package/src/rsc/index.ts +0 -20
- package/src/rsc/loader-fetch.ts +209 -0
- package/src/rsc/manifest-init.ts +86 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +141 -0
- package/src/rsc/progressive-enhancement.ts +379 -0
- package/src/rsc/response-error.ts +37 -0
- package/src/rsc/response-route-handler.ts +347 -0
- package/src/rsc/rsc-rendering.ts +237 -0
- package/src/rsc/runtime-warnings.ts +42 -0
- package/src/rsc/server-action.ts +348 -0
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +38 -11
- package/src/search-params.ts +230 -0
- package/src/segment-system.tsx +25 -13
- package/src/server/context.ts +173 -48
- package/src/server/cookie-store.ts +190 -0
- package/src/server/fetchable-loader-store.ts +37 -0
- package/src/server/handle-store.ts +94 -15
- package/src/server/loader-registry.ts +15 -56
- package/src/server/request-context.ts +430 -70
- package/src/server.ts +35 -155
- package/src/ssr/index.tsx +100 -31
- package/src/static-handler.ts +114 -0
- package/src/theme/ThemeProvider.tsx +21 -15
- package/src/theme/ThemeScript.tsx +5 -5
- package/src/theme/constants.ts +5 -2
- package/src/theme/index.ts +4 -14
- package/src/theme/theme-context.ts +4 -30
- package/src/theme/theme-script.ts +21 -18
- package/src/types/boundaries.ts +158 -0
- package/src/types/cache-types.ts +198 -0
- package/src/types/error-types.ts +192 -0
- package/src/types/global-namespace.ts +100 -0
- package/src/types/handler-context.ts +687 -0
- package/src/types/index.ts +88 -0
- package/src/types/loader-types.ts +183 -0
- package/src/types/route-config.ts +170 -0
- package/src/types/route-entry.ts +102 -0
- package/src/types/segments.ts +148 -0
- package/src/types.ts +1 -1757
- package/src/urls/include-helper.ts +197 -0
- package/src/urls/index.ts +53 -0
- package/src/urls/path-helper-types.ts +339 -0
- package/src/urls/path-helper.ts +329 -0
- package/src/urls/pattern-types.ts +95 -0
- package/src/urls/response-types.ts +106 -0
- package/src/urls/type-extraction.ts +372 -0
- package/src/urls/urls-function.ts +98 -0
- package/src/urls.ts +1 -1282
- package/src/use-loader.tsx +85 -77
- package/src/vite/discovery/bundle-postprocess.ts +184 -0
- package/src/vite/discovery/discover-routers.ts +344 -0
- package/src/vite/discovery/prerender-collection.ts +385 -0
- package/src/vite/discovery/route-types-writer.ts +258 -0
- package/src/vite/discovery/self-gen-tracking.ts +47 -0
- package/src/vite/discovery/state.ts +110 -0
- package/src/vite/discovery/virtual-module-codegen.ts +203 -0
- package/src/vite/index.ts +11 -1963
- package/src/vite/plugin-types.ts +131 -0
- package/src/vite/plugins/cjs-to-esm.ts +93 -0
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/client-ref-hashing.ts +105 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +72 -51
- package/src/vite/plugins/expose-id-utils.ts +287 -0
- package/src/vite/plugins/expose-ids/export-analysis.ts +296 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +179 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +74 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +110 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +569 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/plugins/use-cache-transform.ts +323 -0
- package/src/vite/plugins/version-injector.ts +83 -0
- package/src/vite/plugins/version-plugin.ts +254 -0
- package/src/vite/plugins/virtual-entries.ts +123 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +510 -0
- package/src/vite/router-discovery.ts +785 -0
- package/src/vite/utils/ast-handler-extract.ts +517 -0
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +137 -0
- package/src/vite/utils/manifest-utils.ts +70 -0
- package/src/vite/{package-resolution.ts → utils/package-resolution.ts} +25 -29
- package/src/vite/utils/prerender-utils.ts +189 -0
- package/src/vite/utils/shared-utils.ts +169 -0
- package/CLAUDE.md +0 -43
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/request-controller.ts +0 -164
- package/src/cache/memory-store.ts +0 -253
- package/src/router.gen.ts +0 -6
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-handle-id.ts +0 -209
- package/src/vite/expose-loader-id.ts +0 -426
- package/src/vite/expose-location-state-id.ts +0 -177
- package/src/vite/expose-prerender-handler-id.ts +0 -429
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
package/src/rsc/handler.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/// <reference types="@vitejs/plugin-rsc/types" />
|
|
2
|
-
/// <reference path="../vite/version.d.ts" />
|
|
2
|
+
/// <reference path="../vite/plugins/version.d.ts" />
|
|
3
3
|
/**
|
|
4
4
|
* RSC Request Handler
|
|
5
5
|
*
|
|
@@ -8,68 +8,79 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { createElement } from "react";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import type { ResponseError } from "../urls.js";
|
|
14
|
-
import { getLoaderLazy } from "../server/loader-registry.js";
|
|
15
|
-
import {
|
|
16
|
-
matchMiddleware,
|
|
17
|
-
executeMiddleware,
|
|
18
|
-
executeLoaderMiddleware,
|
|
19
|
-
} from "../router/middleware.js";
|
|
11
|
+
import { RouteNotFoundError } from "../errors.js";
|
|
12
|
+
import { matchMiddleware, executeMiddleware } from "../router/middleware.js";
|
|
20
13
|
import {
|
|
21
14
|
runWithRequestContext,
|
|
22
15
|
setRequestContextParams,
|
|
23
16
|
requireRequestContext,
|
|
24
17
|
createRequestContext,
|
|
25
|
-
type ExecutionContext,
|
|
26
18
|
} from "../server/request-context.js";
|
|
27
19
|
import * as rscDeps from "@vitejs/plugin-rsc/rsc";
|
|
28
20
|
|
|
29
21
|
import type {
|
|
30
22
|
RscPayload,
|
|
31
|
-
ReactFormState,
|
|
32
23
|
CreateRSCHandlerOptions,
|
|
24
|
+
LoadSSRModule,
|
|
33
25
|
} from "./types.js";
|
|
34
|
-
import {
|
|
35
|
-
|
|
26
|
+
import {
|
|
27
|
+
createResponseWithMergedHeaders,
|
|
28
|
+
finalizeResponse,
|
|
29
|
+
interceptRedirectForPartial,
|
|
30
|
+
buildRouteMiddlewareEntries,
|
|
31
|
+
} from "./helpers.js";
|
|
32
|
+
import {
|
|
33
|
+
handleResponseRoute,
|
|
34
|
+
type ResponseRouteMatch,
|
|
35
|
+
} from "./response-route-handler.js";
|
|
36
|
+
import { generateNonce, nonce as nonceToken } from "./nonce.js";
|
|
36
37
|
import { VERSION } from "@rangojs/router:version";
|
|
37
38
|
import type { ErrorPhase } from "../types.js";
|
|
39
|
+
import type { RouterRequestInput } from "../router/router-interfaces.js";
|
|
38
40
|
import { invokeOnError } from "../router/error-handling.js";
|
|
39
41
|
import {
|
|
40
|
-
|
|
42
|
+
createReverseFunction,
|
|
43
|
+
stripInternalParams,
|
|
44
|
+
} from "../router/handler-context.js";
|
|
45
|
+
import { getRouterContext } from "../router/router-context.js";
|
|
46
|
+
import { resolveSink, safeEmit } from "../router/telemetry.js";
|
|
47
|
+
import { contextSet } from "../context-var.js";
|
|
48
|
+
import {
|
|
41
49
|
hasCachedManifest,
|
|
42
|
-
setCachedManifest,
|
|
43
50
|
getRouteTrie,
|
|
44
|
-
setRouteTrie,
|
|
45
51
|
getPrecomputedEntries,
|
|
46
52
|
waitForManifestReady,
|
|
53
|
+
getRouterManifest,
|
|
54
|
+
getRouterTrie,
|
|
47
55
|
} from "../route-map-builder.js";
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
56
|
+
import type { HandlerContext } from "./handler-context.js";
|
|
57
|
+
import { buildRouterTrieFromUrlpatterns } from "./manifest-init.js";
|
|
58
|
+
import { handleProgressiveEnhancement } from "./progressive-enhancement.js";
|
|
59
|
+
import {
|
|
60
|
+
executeServerAction,
|
|
61
|
+
revalidateAfterAction,
|
|
62
|
+
type ActionContinuation,
|
|
63
|
+
} from "./server-action.js";
|
|
64
|
+
import { handleLoaderFetch } from "./loader-fetch.js";
|
|
65
|
+
import { checkRequestOrigin, type OriginCheckPhase } from "./origin-guard.js";
|
|
66
|
+
import { handleRscRendering } from "./rsc-rendering.js";
|
|
67
|
+
import {
|
|
68
|
+
withTimeout,
|
|
69
|
+
RouterTimeoutError,
|
|
70
|
+
createDefaultTimeoutResponse,
|
|
71
|
+
type TimeoutPhase,
|
|
72
|
+
} from "../router/timeout.js";
|
|
73
|
+
import {
|
|
74
|
+
createMetricsStore,
|
|
75
|
+
appendMetric,
|
|
76
|
+
buildMetricsTiming,
|
|
77
|
+
} from "../router/metrics.js";
|
|
78
|
+
import {
|
|
79
|
+
startSSRSetup,
|
|
80
|
+
getSSRSetup,
|
|
81
|
+
mayNeedSSR,
|
|
82
|
+
SSR_SETUP_VAR,
|
|
83
|
+
} from "./ssr-setup.js";
|
|
73
84
|
|
|
74
85
|
/**
|
|
75
86
|
* Create an RSC request handler.
|
|
@@ -121,33 +132,171 @@ export function createRSCHandler<
|
|
|
121
132
|
decodeFormState,
|
|
122
133
|
} = deps;
|
|
123
134
|
|
|
124
|
-
// Use provided loadSSRModule or default to vite RSC module loader
|
|
125
|
-
|
|
135
|
+
// Use provided loadSSRModule or default to vite RSC module loader.
|
|
136
|
+
// No memoization: ES module caching in the runtime already avoids
|
|
137
|
+
// repeated resolution, and memoizing here can break multi-router
|
|
138
|
+
// setups (host routing) where different routers share the same
|
|
139
|
+
// process but need independent SSR module lifecycle.
|
|
140
|
+
const loadSSRModule: LoadSSRModule =
|
|
126
141
|
options.loadSSRModule ??
|
|
127
142
|
(() => import.meta.viteRsc.loadModule("ssr", "index"));
|
|
128
143
|
|
|
129
144
|
/**
|
|
130
|
-
*
|
|
131
|
-
*
|
|
145
|
+
* Per-request error reporter that deduplicates via the ALS request context.
|
|
146
|
+
*
|
|
147
|
+
* Uses the same _reportedErrors WeakSet as the router layer so errors
|
|
148
|
+
* that propagate across layers are only reported once per request.
|
|
132
149
|
*/
|
|
133
150
|
function callOnError(
|
|
134
151
|
error: unknown,
|
|
135
152
|
phase: ErrorPhase,
|
|
136
153
|
context: Parameters<typeof invokeOnError<TEnv>>[3],
|
|
137
154
|
): void {
|
|
155
|
+
if (error != null && typeof error === "object") {
|
|
156
|
+
const reportedErrors = requireRequestContext()._reportedErrors;
|
|
157
|
+
if (reportedErrors.has(error)) return;
|
|
158
|
+
reportedErrors.add(error);
|
|
159
|
+
}
|
|
138
160
|
invokeOnError(router.onError, error, phase, context, "RSC");
|
|
139
161
|
}
|
|
140
162
|
|
|
141
|
-
|
|
163
|
+
function getRequiredRouteMap(): Record<string, string> {
|
|
164
|
+
const routeMap = getRouterManifest(router.id);
|
|
165
|
+
if (!routeMap) {
|
|
166
|
+
throw new Error(
|
|
167
|
+
`Route manifest for router "${router.id}" is not available.`,
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return routeMap;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Handle a timeout by reporting the error, emitting telemetry,
|
|
175
|
+
* and returning either the custom onTimeout response or a default 504.
|
|
176
|
+
*/
|
|
177
|
+
async function handleTimeoutResponse(
|
|
142
178
|
request: Request,
|
|
143
|
-
env: TEnv
|
|
144
|
-
|
|
179
|
+
env: TEnv,
|
|
180
|
+
url: URL,
|
|
181
|
+
phase: TimeoutPhase,
|
|
182
|
+
durationMs: number,
|
|
183
|
+
routeKey?: string,
|
|
184
|
+
actionId?: string,
|
|
185
|
+
): Promise<Response> {
|
|
186
|
+
const timeoutError = new RouterTimeoutError(phase, durationMs);
|
|
187
|
+
|
|
188
|
+
callOnError(timeoutError, phase === "action" ? "action" : "handler", {
|
|
189
|
+
request,
|
|
190
|
+
url,
|
|
191
|
+
env,
|
|
192
|
+
routeKey,
|
|
193
|
+
actionId,
|
|
194
|
+
handledByBoundary: false,
|
|
195
|
+
metadata: { timeout: true, phase, durationMs },
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const routerCtx = getRouterContext();
|
|
200
|
+
if (routerCtx?.telemetry) {
|
|
201
|
+
safeEmit(resolveSink(routerCtx.telemetry), {
|
|
202
|
+
type: "request.timeout" as const,
|
|
203
|
+
timestamp: performance.now(),
|
|
204
|
+
requestId: routerCtx.requestId,
|
|
205
|
+
phase,
|
|
206
|
+
pathname: url.pathname,
|
|
207
|
+
routeKey,
|
|
208
|
+
actionId,
|
|
209
|
+
durationMs,
|
|
210
|
+
customHandler: !!router.onTimeout,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
} catch {
|
|
214
|
+
// Router context may not be available
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (router.onTimeout) {
|
|
218
|
+
try {
|
|
219
|
+
return await router.onTimeout({
|
|
220
|
+
phase,
|
|
221
|
+
request,
|
|
222
|
+
url,
|
|
223
|
+
env,
|
|
224
|
+
routeKey,
|
|
225
|
+
actionId,
|
|
226
|
+
durationMs,
|
|
227
|
+
});
|
|
228
|
+
} catch (e) {
|
|
229
|
+
if (process.env.NODE_ENV !== "production") {
|
|
230
|
+
console.error("[RSC] onTimeout callback error:", e);
|
|
231
|
+
}
|
|
232
|
+
return createDefaultTimeoutResponse(phase);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return createDefaultTimeoutResponse(phase);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Build a 200 Flight response that carries a redirect URL and optional state.
|
|
241
|
+
* Used when a partial/action request results in a redirect -- fetch
|
|
242
|
+
* auto-follows 3xx so we send the redirect as payload metadata instead.
|
|
243
|
+
*/
|
|
244
|
+
function createRedirectFlightResponse(
|
|
245
|
+
redirectUrl: string,
|
|
246
|
+
locationState?: Record<string, unknown>,
|
|
247
|
+
): Response {
|
|
248
|
+
const redirectPayload: RscPayload = {
|
|
249
|
+
metadata: {
|
|
250
|
+
pathname: redirectUrl,
|
|
251
|
+
segments: [],
|
|
252
|
+
redirect: { url: redirectUrl },
|
|
253
|
+
...(locationState && { locationState }),
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
const rscStream = renderToReadableStream<RscPayload>(redirectPayload);
|
|
257
|
+
return createResponseWithMergedHeaders(rscStream, {
|
|
258
|
+
status: 200,
|
|
259
|
+
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Bundle shared dependencies for extracted handler functions.
|
|
264
|
+
// callOnError reads from ALS so it's inherently per-request scoped.
|
|
265
|
+
const handlerCtx: HandlerContext<TEnv> = {
|
|
266
|
+
router,
|
|
267
|
+
version,
|
|
268
|
+
renderToReadableStream,
|
|
269
|
+
decodeReply,
|
|
270
|
+
createTemporaryReferenceSet,
|
|
271
|
+
loadServerAction,
|
|
272
|
+
decodeAction,
|
|
273
|
+
decodeFormState,
|
|
274
|
+
loadSSRModule,
|
|
275
|
+
callOnError,
|
|
276
|
+
getRequiredRouteMap,
|
|
277
|
+
createRedirectFlightResponse,
|
|
278
|
+
resolveStreamMode: async (request, env, url) => {
|
|
279
|
+
const resolver = router.ssr?.resolveStreaming;
|
|
280
|
+
if (!resolver) return "stream";
|
|
281
|
+
return resolver({ request, env, url });
|
|
145
282
|
},
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
return async function handler(
|
|
286
|
+
request: Request,
|
|
287
|
+
input: RouterRequestInput<TEnv> = {},
|
|
146
288
|
): Promise<Response> {
|
|
147
289
|
const handlerStart = performance.now();
|
|
290
|
+
// Create the metrics store at handler start so handler:total has startTime=0
|
|
291
|
+
// and all metrics are relative to the request entry point.
|
|
292
|
+
const earlyMetricsStore = router.debugPerformance
|
|
293
|
+
? createMetricsStore(true, handlerStart)
|
|
294
|
+
: undefined;
|
|
295
|
+
|
|
296
|
+
const { env = {} as TEnv, vars: initialVars, ctx: executionCtx } = input;
|
|
148
297
|
|
|
149
298
|
// Connection warmup: return 204 immediately before any processing
|
|
150
|
-
if (router
|
|
299
|
+
if (router?.warmupEnabled && request.method === "HEAD") {
|
|
151
300
|
const warmupUrl = new URL(request.url);
|
|
152
301
|
if (warmupUrl.searchParams.has("_rsc_warmup")) {
|
|
153
302
|
return new Response(null, { status: 204 });
|
|
@@ -171,13 +320,14 @@ export function createRSCHandler<
|
|
|
171
320
|
const mwMatchDur = performance.now() - mwMatchStart;
|
|
172
321
|
|
|
173
322
|
// Shared variables between middleware and route handlers
|
|
174
|
-
// Initialize from
|
|
175
|
-
const variables: Record<string, any> =
|
|
176
|
-
|
|
177
|
-
|
|
323
|
+
// Initialize from input.vars if provided (allows pre-seeding from worker entry)
|
|
324
|
+
const variables: Record<string, any> = initialVars
|
|
325
|
+
? { ...initialVars }
|
|
326
|
+
: {};
|
|
178
327
|
|
|
179
|
-
// Store nonce
|
|
328
|
+
// Store nonce via ContextVar token and string key for backward compat
|
|
180
329
|
if (nonce) {
|
|
330
|
+
contextSet(variables, nonceToken, nonce);
|
|
181
331
|
variables.nonce = nonce;
|
|
182
332
|
}
|
|
183
333
|
|
|
@@ -188,7 +338,9 @@ export function createRSCHandler<
|
|
|
188
338
|
const cacheOption = options.cache ?? router.cache;
|
|
189
339
|
if (cacheOption && !url.searchParams.has("__no_cache")) {
|
|
190
340
|
const cacheConfig =
|
|
191
|
-
typeof cacheOption === "function"
|
|
341
|
+
typeof cacheOption === "function"
|
|
342
|
+
? cacheOption(env, executionCtx)
|
|
343
|
+
: cacheOption;
|
|
192
344
|
|
|
193
345
|
if (cacheConfig.enabled !== false) {
|
|
194
346
|
cacheStore = cacheConfig.store;
|
|
@@ -201,60 +353,43 @@ export function createRSCHandler<
|
|
|
201
353
|
// via setManifestReadyPromise(). In dev mode (Cloudflare), Miniflare runs
|
|
202
354
|
// in a separate isolate where module-level state doesn't carry over, so
|
|
203
355
|
// we generate inline from the router's urlpatterns.
|
|
356
|
+
//
|
|
357
|
+
// In multi-router setups (e.g. createHostRouter), each router must have
|
|
358
|
+
// its own per-router manifest. We check per-router data first: even if
|
|
359
|
+
// the global manifest was set by a different router, this router still
|
|
360
|
+
// needs its own trie and manifest for correct matching.
|
|
204
361
|
const manifestCacheStart = performance.now();
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
// Cloudflare dev: generate manifest inline (no caching needed)
|
|
212
|
-
const { generateManifest } =
|
|
213
|
-
await import("../build/generate-manifest.js");
|
|
214
|
-
const generated = generateManifest(router.urlpatterns);
|
|
215
|
-
setCachedManifest(generated.routeManifest);
|
|
216
|
-
if (
|
|
217
|
-
generated._routeAncestry &&
|
|
218
|
-
Object.keys(generated._routeAncestry).length > 0
|
|
219
|
-
) {
|
|
220
|
-
const { buildRouteTrie } = await import("../build/route-trie.js");
|
|
221
|
-
// Map each route to its include() staticPrefix so the trie
|
|
222
|
-
// returns the correct sp for lazy entry lookup in findMatch.
|
|
223
|
-
const routeToStaticPrefix: Record<string, string> = {};
|
|
224
|
-
for (const name of Object.keys(generated.routeManifest)) {
|
|
225
|
-
routeToStaticPrefix[name] = "";
|
|
226
|
-
}
|
|
227
|
-
// Override with prefix from include() entries so the trie
|
|
228
|
-
// returns the correct sp for lazy entry lookup in findMatch.
|
|
229
|
-
if (generated.prefixTree) {
|
|
230
|
-
for (const [prefix, node] of Object.entries(generated.prefixTree)) {
|
|
231
|
-
for (const route of (node as { routes: string[] }).routes) {
|
|
232
|
-
routeToStaticPrefix[route] = prefix;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
const trie = buildRouteTrie(
|
|
237
|
-
generated.routeManifest,
|
|
238
|
-
generated._routeAncestry,
|
|
239
|
-
routeToStaticPrefix,
|
|
240
|
-
generated.routeTrailingSlash,
|
|
241
|
-
undefined, // prerenderRouteNames
|
|
242
|
-
undefined, // passthroughRouteNames
|
|
243
|
-
generated.responseTypeRoutes,
|
|
244
|
-
);
|
|
245
|
-
setRouteTrie(trie);
|
|
362
|
+
const hasRouterData = getRouterManifest(router.id) !== undefined;
|
|
363
|
+
if (!hasRouterData) {
|
|
364
|
+
if (!hasCachedManifest()) {
|
|
365
|
+
const readyPromise = waitForManifestReady();
|
|
366
|
+
if (readyPromise) {
|
|
367
|
+
await readyPromise;
|
|
246
368
|
}
|
|
247
369
|
}
|
|
248
|
-
if (!
|
|
370
|
+
if (!getRouterManifest(router.id) && router.urlpatterns) {
|
|
371
|
+
// Cloudflare dev: generate manifest inline for this router.
|
|
372
|
+
// Each router generates its own manifest independently so
|
|
373
|
+
// multi-router setups (host routing) work correctly.
|
|
374
|
+
await buildRouterTrieFromUrlpatterns(router);
|
|
375
|
+
}
|
|
376
|
+
if (!getRouterManifest(router.id) && !hasCachedManifest()) {
|
|
249
377
|
throw new Error(
|
|
250
378
|
'Route manifest not available. Ensure "virtual:rsc-router/routes-manifest" is imported in your entry file.',
|
|
251
379
|
);
|
|
252
380
|
}
|
|
253
381
|
}
|
|
254
|
-
const manifestCacheDur = performance.now() - manifestCacheStart;
|
|
255
382
|
|
|
256
|
-
//
|
|
257
|
-
// This
|
|
383
|
+
// Rebuild the trie when the manifest exists but the per-router trie is
|
|
384
|
+
// missing. This happens in dev mode after HMR: the virtual module sets
|
|
385
|
+
// the manifest (from fresh gen files) but the trie is intentionally not
|
|
386
|
+
// injected to avoid stale discovery-time data. Without the trie, route
|
|
387
|
+
// matching falls back to regex iteration which does not handle wildcard
|
|
388
|
+
// priority correctly (catch-all patterns match before specific routes).
|
|
389
|
+
if (!getRouterTrie(router.id) && router.urlpatterns) {
|
|
390
|
+
await buildRouterTrieFromUrlpatterns(router);
|
|
391
|
+
}
|
|
392
|
+
const manifestCacheDur = performance.now() - manifestCacheStart;
|
|
258
393
|
|
|
259
394
|
// Create unified request context with all methods
|
|
260
395
|
// Includes: stub response, handle store, loader memoization, use(), cookies, headers, cache store
|
|
@@ -266,9 +401,27 @@ export function createRSCHandler<
|
|
|
266
401
|
url,
|
|
267
402
|
variables,
|
|
268
403
|
cacheStore,
|
|
269
|
-
|
|
404
|
+
cacheProfiles: router.cacheProfiles,
|
|
405
|
+
executionContext: executionCtx,
|
|
270
406
|
themeConfig: router.themeConfig,
|
|
271
407
|
});
|
|
408
|
+
if (earlyMetricsStore) {
|
|
409
|
+
requestContext._debugPerformance = true;
|
|
410
|
+
requestContext._metricsStore = earlyMetricsStore;
|
|
411
|
+
}
|
|
412
|
+
// Wire background error reporting so "use cache" and other subsystems
|
|
413
|
+
// can surface non-fatal errors through the router's onError callback.
|
|
414
|
+
requestContext._reportBackgroundError = (
|
|
415
|
+
error: unknown,
|
|
416
|
+
category: string,
|
|
417
|
+
) => {
|
|
418
|
+
callOnError(error, "cache", {
|
|
419
|
+
request,
|
|
420
|
+
url,
|
|
421
|
+
metadata: { category },
|
|
422
|
+
});
|
|
423
|
+
};
|
|
424
|
+
|
|
272
425
|
const ctxCreateDur = performance.now() - ctxCreateStart;
|
|
273
426
|
|
|
274
427
|
// Accumulate handler-level timing for Server-Timing header
|
|
@@ -297,17 +450,71 @@ export function createRSCHandler<
|
|
|
297
450
|
};
|
|
298
451
|
|
|
299
452
|
// Execute middleware chain if any, otherwise call core handler directly
|
|
453
|
+
let response: Response;
|
|
300
454
|
if (matchedMiddleware.length > 0) {
|
|
301
|
-
|
|
455
|
+
const mwResponse = await executeMiddleware(
|
|
302
456
|
matchedMiddleware,
|
|
303
457
|
request,
|
|
304
458
|
env,
|
|
305
459
|
variables,
|
|
306
460
|
coreHandler,
|
|
461
|
+
createReverseFunction(getRequiredRouteMap()),
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
if (
|
|
465
|
+
url.searchParams.has("_rsc_partial") ||
|
|
466
|
+
url.searchParams.has("_rsc_action")
|
|
467
|
+
) {
|
|
468
|
+
const intercepted = interceptRedirectForPartial(
|
|
469
|
+
mwResponse,
|
|
470
|
+
createRedirectFlightResponse,
|
|
471
|
+
);
|
|
472
|
+
response = intercepted ?? finalizeResponse(mwResponse);
|
|
473
|
+
} else {
|
|
474
|
+
response = finalizeResponse(mwResponse);
|
|
475
|
+
}
|
|
476
|
+
} else {
|
|
477
|
+
response = await coreHandler();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Finalize metrics after all middleware (including post-next work)
|
|
481
|
+
// has completed so :post spans are captured in the timeline.
|
|
482
|
+
// Handler timing parts are always emitted (even without debug metrics)
|
|
483
|
+
// so non-debug requests still get bootstrap Server-Timing entries.
|
|
484
|
+
const handlerTimingArr: string[] = variables.__handlerTiming || [];
|
|
485
|
+
// Preserve any existing Server-Timing set by response routes or middleware
|
|
486
|
+
const existingTiming = response.headers.get("Server-Timing");
|
|
487
|
+
const timingParts = existingTiming
|
|
488
|
+
? [existingTiming, ...handlerTimingArr]
|
|
489
|
+
: [...handlerTimingArr];
|
|
490
|
+
|
|
491
|
+
const metricsStore = requestContext._metricsStore;
|
|
492
|
+
if (metricsStore) {
|
|
493
|
+
// When the store was created at handler start (earlyMetricsStore),
|
|
494
|
+
// handler:total covers the full request. When ctx.debugPerformance()
|
|
495
|
+
// created the store mid-request, use its requestStart to avoid a
|
|
496
|
+
// negative startTime offset.
|
|
497
|
+
const totalStart = earlyMetricsStore
|
|
498
|
+
? handlerStart
|
|
499
|
+
: metricsStore.requestStart;
|
|
500
|
+
appendMetric(
|
|
501
|
+
metricsStore,
|
|
502
|
+
"handler:total",
|
|
503
|
+
totalStart,
|
|
504
|
+
performance.now() - totalStart,
|
|
307
505
|
);
|
|
506
|
+
const metricsTiming = buildMetricsTiming(
|
|
507
|
+
request.method,
|
|
508
|
+
url.pathname,
|
|
509
|
+
metricsStore,
|
|
510
|
+
);
|
|
511
|
+
if (metricsTiming) timingParts.push(metricsTiming);
|
|
308
512
|
}
|
|
309
513
|
|
|
310
|
-
|
|
514
|
+
const fullTiming = timingParts.join(", ");
|
|
515
|
+
if (fullTiming) response.headers.set("Server-Timing", fullTiming);
|
|
516
|
+
|
|
517
|
+
return response;
|
|
311
518
|
});
|
|
312
519
|
};
|
|
313
520
|
|
|
@@ -319,224 +526,314 @@ export function createRSCHandler<
|
|
|
319
526
|
variables: Record<string, any>,
|
|
320
527
|
nonce: string | undefined,
|
|
321
528
|
): Promise<Response> {
|
|
322
|
-
// First, check for route-level middleware
|
|
323
529
|
const previewStart = performance.now();
|
|
324
|
-
const preview = await router.previewMatch(request, env);
|
|
530
|
+
const preview = await router.previewMatch(request, { env });
|
|
325
531
|
const previewDur = performance.now() - previewStart;
|
|
326
532
|
const handlerTiming: string[] = variables.__handlerTiming || [];
|
|
327
533
|
handlerTiming.push(`handler-preview-match;dur=${previewDur.toFixed(2)}`);
|
|
328
534
|
// Response route short-circuit: skip entire RSC pipeline
|
|
329
535
|
if (preview?.responseType && preview.handler) {
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
return
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
536
|
+
const responseOutcome = await withTimeout(
|
|
537
|
+
handleResponseRoute(
|
|
538
|
+
handlerCtx,
|
|
539
|
+
preview as ResponseRouteMatch,
|
|
540
|
+
request,
|
|
541
|
+
env,
|
|
542
|
+
url,
|
|
543
|
+
variables,
|
|
544
|
+
),
|
|
545
|
+
router.timeouts.renderStartMs,
|
|
546
|
+
"render-start",
|
|
547
|
+
);
|
|
548
|
+
if (responseOutcome.timedOut) {
|
|
549
|
+
return handleTimeoutResponse(
|
|
550
|
+
request,
|
|
551
|
+
env,
|
|
552
|
+
url,
|
|
553
|
+
"render-start",
|
|
554
|
+
responseOutcome.durationMs,
|
|
555
|
+
preview?.routeKey,
|
|
556
|
+
);
|
|
350
557
|
}
|
|
558
|
+
return responseOutcome.result;
|
|
559
|
+
}
|
|
351
560
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
561
|
+
// Kick off SSR module loading + stream mode resolution in parallel with
|
|
562
|
+
// segment resolution. Placed after the response-route short-circuit so
|
|
563
|
+
// response/mime routes never pay for SSR work.
|
|
564
|
+
if (mayNeedSSR(request, url)) {
|
|
565
|
+
variables[SSR_SETUP_VAR] = startSSRSetup(
|
|
566
|
+
handlerCtx,
|
|
356
567
|
request,
|
|
357
|
-
|
|
358
|
-
env: bindings,
|
|
359
|
-
searchParams: url.searchParams,
|
|
568
|
+
env,
|
|
360
569
|
url,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const value = hrefParams[key];
|
|
367
|
-
if (value === undefined) throw new Error(`Missing param "${key}" for path "${name}"`);
|
|
368
|
-
return encodeURIComponent(value);
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
return name;
|
|
372
|
-
},
|
|
373
|
-
get: (key: string) => variables[key],
|
|
374
|
-
header: (name: string, value: string) => reqCtx.header(name, value),
|
|
375
|
-
setCookie: (name: string, value: string, options?: any) => reqCtx.setCookie(name, value, options),
|
|
376
|
-
};
|
|
570
|
+
router.debugPerformance
|
|
571
|
+
? () => requireRequestContext()._metricsStore
|
|
572
|
+
: undefined,
|
|
573
|
+
);
|
|
574
|
+
}
|
|
377
575
|
|
|
378
|
-
|
|
379
|
-
const callHandler = async () => {
|
|
380
|
-
// JSON response routes: wrap in { data } / { error } envelope
|
|
381
|
-
if (preview.responseType === "json") {
|
|
382
|
-
const errorCtx = { request, url, env };
|
|
383
|
-
try {
|
|
384
|
-
const result = await (preview.handler as Function)(responseHandlerCtx);
|
|
385
|
-
if (result instanceof Response) {
|
|
386
|
-
const mergedHeaders: Record<string, string> = {};
|
|
387
|
-
result.headers.forEach((value, key) => {
|
|
388
|
-
mergedHeaders[key] = value;
|
|
389
|
-
});
|
|
390
|
-
return createResponseWithMergedHeaders(result.body, {
|
|
391
|
-
status: result.status,
|
|
392
|
-
headers: mergedHeaders,
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
return createResponseWithMergedHeaders(
|
|
396
|
-
JSON.stringify({ data: result }),
|
|
397
|
-
{ status: 200, headers: { "content-type": "application/json;charset=utf-8" } },
|
|
398
|
-
);
|
|
399
|
-
} catch (error) {
|
|
400
|
-
callOnError(error, "handler", errorCtx);
|
|
401
|
-
const isDev = process.env.NODE_ENV !== "production";
|
|
402
|
-
const status = error instanceof RouterError ? error.status : 500;
|
|
403
|
-
return createResponseWithMergedHeaders(
|
|
404
|
-
JSON.stringify({ error: createResponseErrorPayload(error, isDev) }),
|
|
405
|
-
{ status, headers: { "content-type": "application/json;charset=utf-8" } },
|
|
406
|
-
);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
576
|
+
const routeReverse = createReverseFunction(getRequiredRouteMap());
|
|
409
577
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
578
|
+
const isAction =
|
|
579
|
+
request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
|
|
580
|
+
const isLoaderFetch = url.searchParams.has("_rsc_loader");
|
|
581
|
+
const actionId =
|
|
582
|
+
request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
|
|
414
583
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
584
|
+
// Origin guard: reject cross-origin actions, loader fetches, and
|
|
585
|
+
// PE form submissions before any execution. Regular page navigations
|
|
586
|
+
// (GET without _rsc_loader/_rsc_action) are not affected.
|
|
587
|
+
const originPhase: OriginCheckPhase | null = isAction
|
|
588
|
+
? "action"
|
|
589
|
+
: isLoaderFetch
|
|
590
|
+
? "loader"
|
|
591
|
+
: request.method === "POST"
|
|
592
|
+
? "pe-form"
|
|
593
|
+
: null;
|
|
594
|
+
if (originPhase) {
|
|
595
|
+
const originResult = await checkRequestOrigin(
|
|
596
|
+
request,
|
|
597
|
+
url,
|
|
598
|
+
router.originCheck,
|
|
599
|
+
env,
|
|
600
|
+
router.id,
|
|
601
|
+
originPhase,
|
|
602
|
+
);
|
|
603
|
+
if (originResult) {
|
|
604
|
+
const originError = new Error(
|
|
605
|
+
`Origin check rejected: ${request.headers.get("origin") ?? "none"} vs ${request.headers.get("host") ?? "none"}`,
|
|
606
|
+
);
|
|
607
|
+
originError.name = "OriginCheckError";
|
|
608
|
+
|
|
609
|
+
callOnError(originError, "origin", {
|
|
610
|
+
request,
|
|
611
|
+
url,
|
|
612
|
+
env,
|
|
613
|
+
handledByBoundary: false,
|
|
614
|
+
metadata: {
|
|
615
|
+
phase: originPhase,
|
|
616
|
+
origin: request.headers.get("origin"),
|
|
617
|
+
host: request.headers.get("host"),
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
try {
|
|
622
|
+
const routerCtx = getRouterContext();
|
|
623
|
+
if (routerCtx?.telemetry) {
|
|
624
|
+
safeEmit(resolveSink(routerCtx.telemetry), {
|
|
625
|
+
type: "request.origin-rejected" as const,
|
|
626
|
+
timestamp: performance.now(),
|
|
627
|
+
requestId: routerCtx.requestId,
|
|
628
|
+
method: request.method,
|
|
629
|
+
pathname: url.pathname,
|
|
630
|
+
phase: originPhase,
|
|
631
|
+
origin: request.headers.get("origin"),
|
|
632
|
+
host: request.headers.get("host"),
|
|
424
633
|
});
|
|
425
634
|
}
|
|
635
|
+
} catch {
|
|
636
|
+
// Router context may not be available
|
|
637
|
+
}
|
|
426
638
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
const message = error instanceof RouterError
|
|
460
|
-
? error.message
|
|
461
|
-
: isDev && error instanceof Error
|
|
462
|
-
? error.message
|
|
463
|
-
: "Internal Server Error";
|
|
464
|
-
return createResponseWithMergedHeaders(message, {
|
|
465
|
-
status,
|
|
466
|
-
headers: { "content-type": "text/plain;charset=utf-8" },
|
|
639
|
+
return originResult;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// Get handle store from request context
|
|
644
|
+
const handleStore = requireRequestContext()._handleStore;
|
|
645
|
+
|
|
646
|
+
// Wire up error reporting for late streaming-handle failures
|
|
647
|
+
// (LateHandlePushError: handle pushed after stream completion).
|
|
648
|
+
// Without this, these errors are only caught by React's error boundary
|
|
649
|
+
// and never reach the router's onError callback or telemetry.
|
|
650
|
+
handleStore.onError = (error: Error) => {
|
|
651
|
+
const reqCtx = requireRequestContext();
|
|
652
|
+
callOnError(error, "handler", {
|
|
653
|
+
request,
|
|
654
|
+
url,
|
|
655
|
+
routeKey: reqCtx._routeName,
|
|
656
|
+
params: reqCtx.params as Record<string, string>,
|
|
657
|
+
handledByBoundary: true,
|
|
658
|
+
});
|
|
659
|
+
try {
|
|
660
|
+
const routerCtx = getRouterContext();
|
|
661
|
+
if (routerCtx?.telemetry) {
|
|
662
|
+
safeEmit(resolveSink(routerCtx.telemetry), {
|
|
663
|
+
type: "handler.error" as const,
|
|
664
|
+
timestamp: performance.now(),
|
|
665
|
+
requestId: routerCtx.requestId,
|
|
666
|
+
error,
|
|
667
|
+
handledByBoundary: true,
|
|
668
|
+
pathname: url.pathname,
|
|
669
|
+
routeKey: reqCtx._routeName,
|
|
670
|
+
params: reqCtx.params as Record<string, string>,
|
|
467
671
|
});
|
|
468
672
|
}
|
|
469
|
-
}
|
|
673
|
+
} catch {
|
|
674
|
+
// Router context may not be available (e.g. prerender path)
|
|
675
|
+
}
|
|
676
|
+
};
|
|
470
677
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
response.headers.append("Vary", "Accept");
|
|
476
|
-
}
|
|
477
|
-
return response;
|
|
478
|
-
};
|
|
678
|
+
// Set route params early so all execution paths can access ctx.params.
|
|
679
|
+
if (preview?.params) {
|
|
680
|
+
setRequestContextParams(preview.params, preview.routeKey);
|
|
681
|
+
}
|
|
479
682
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
683
|
+
// Progressive enhancement runs before the normal action/render paths.
|
|
684
|
+
// Route middleware wraps the PE re-render so handlers see the same
|
|
685
|
+
// context variables regardless of JS/no-JS transport.
|
|
686
|
+
const progressiveResult = await handleProgressiveEnhancement(
|
|
687
|
+
handlerCtx,
|
|
688
|
+
request,
|
|
689
|
+
env,
|
|
690
|
+
url,
|
|
691
|
+
isAction,
|
|
692
|
+
handleStore,
|
|
693
|
+
nonce,
|
|
694
|
+
{
|
|
695
|
+
routeMiddleware: preview?.routeMiddleware,
|
|
696
|
+
variables,
|
|
697
|
+
routeReverse,
|
|
698
|
+
},
|
|
699
|
+
);
|
|
700
|
+
if (progressiveResult) {
|
|
701
|
+
return progressiveResult;
|
|
702
|
+
}
|
|
493
703
|
|
|
494
|
-
|
|
704
|
+
// --- Action execution: runs BEFORE route middleware ---
|
|
705
|
+
// Route middleware wraps rendering only. For actions, the action runs
|
|
706
|
+
// first in the global middleware context, then route middleware wraps
|
|
707
|
+
// the revalidation pass (identical to a normal render).
|
|
708
|
+
let actionContinuation: ActionContinuation | undefined;
|
|
709
|
+
if (isAction && actionId) {
|
|
710
|
+
try {
|
|
711
|
+
const actionOutcome = await withTimeout(
|
|
712
|
+
executeServerAction(
|
|
713
|
+
handlerCtx,
|
|
714
|
+
request,
|
|
715
|
+
env,
|
|
716
|
+
url,
|
|
717
|
+
actionId,
|
|
718
|
+
handleStore,
|
|
719
|
+
),
|
|
720
|
+
router.timeouts.actionMs,
|
|
721
|
+
"action",
|
|
722
|
+
);
|
|
723
|
+
if (actionOutcome.timedOut) {
|
|
724
|
+
return handleTimeoutResponse(
|
|
725
|
+
request,
|
|
726
|
+
env,
|
|
727
|
+
url,
|
|
728
|
+
"action",
|
|
729
|
+
actionOutcome.durationMs,
|
|
730
|
+
preview?.routeKey,
|
|
731
|
+
actionId,
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
const result = actionOutcome.result;
|
|
735
|
+
// Response means redirect or error boundary — done.
|
|
736
|
+
if (result instanceof Response) return result;
|
|
737
|
+
actionContinuation = result;
|
|
738
|
+
} catch (error) {
|
|
739
|
+
callOnError(error, "action", {
|
|
740
|
+
request,
|
|
741
|
+
url,
|
|
742
|
+
env,
|
|
743
|
+
actionId,
|
|
744
|
+
handledByBoundary: false,
|
|
745
|
+
});
|
|
746
|
+
console.error(`[RSC] Action error:`, error);
|
|
747
|
+
throw error;
|
|
748
|
+
}
|
|
495
749
|
}
|
|
496
750
|
|
|
497
|
-
//
|
|
498
|
-
|
|
499
|
-
|
|
751
|
+
// --- Rendering (action revalidation or navigation) ---
|
|
752
|
+
// Route middleware wraps this — same code path for both cases.
|
|
753
|
+
const renderHandler = async () => {
|
|
754
|
+
const response = await coreRequestHandlerInner(
|
|
755
|
+
request,
|
|
756
|
+
env,
|
|
757
|
+
url,
|
|
758
|
+
variables,
|
|
759
|
+
nonce,
|
|
760
|
+
preview?.params,
|
|
761
|
+
preview?.routeKey,
|
|
762
|
+
handleStore,
|
|
763
|
+
actionContinuation,
|
|
764
|
+
);
|
|
500
765
|
if (preview?.negotiated) {
|
|
501
766
|
response.headers.append("Vary", "Accept");
|
|
502
767
|
}
|
|
503
768
|
return response;
|
|
504
769
|
};
|
|
505
770
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
771
|
+
// Wrap the render path (with or without route middleware) in a
|
|
772
|
+
// renderStartMs timeout so slow renders are caught before output.
|
|
773
|
+
const executeRender = async (): Promise<Response> => {
|
|
774
|
+
if (preview?.routeMiddleware && preview.routeMiddleware.length > 0) {
|
|
775
|
+
const mwResponse = await executeMiddleware(
|
|
776
|
+
buildRouteMiddlewareEntries<TEnv>(preview.routeMiddleware),
|
|
777
|
+
request,
|
|
778
|
+
env,
|
|
779
|
+
variables,
|
|
780
|
+
renderHandler,
|
|
781
|
+
routeReverse,
|
|
782
|
+
);
|
|
518
783
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
784
|
+
if (
|
|
785
|
+
url.searchParams.has("_rsc_partial") ||
|
|
786
|
+
url.searchParams.has("_rsc_action")
|
|
787
|
+
) {
|
|
788
|
+
const intercepted = interceptRedirectForPartial(
|
|
789
|
+
mwResponse,
|
|
790
|
+
createRedirectFlightResponse,
|
|
791
|
+
);
|
|
792
|
+
if (intercepted) return intercepted;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
return finalizeResponse(mwResponse);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// No route middleware, proceed directly
|
|
799
|
+
return renderHandler();
|
|
800
|
+
};
|
|
522
801
|
|
|
523
|
-
|
|
524
|
-
|
|
802
|
+
const renderOutcome = await withTimeout(
|
|
803
|
+
executeRender(),
|
|
804
|
+
router.timeouts.renderStartMs,
|
|
805
|
+
"render-start",
|
|
806
|
+
);
|
|
807
|
+
if (renderOutcome.timedOut) {
|
|
808
|
+
return handleTimeoutResponse(
|
|
809
|
+
request,
|
|
810
|
+
env,
|
|
811
|
+
url,
|
|
812
|
+
"render-start",
|
|
813
|
+
renderOutcome.durationMs,
|
|
814
|
+
preview?.routeKey,
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
return renderOutcome.result;
|
|
525
818
|
}
|
|
526
819
|
|
|
527
|
-
// Inner request handler
|
|
820
|
+
// Inner request handler: rendering logic wrapped by route middleware.
|
|
821
|
+
// Handles action revalidation (when actionContinuation is present),
|
|
822
|
+
// loader fetches, and regular RSC rendering.
|
|
528
823
|
async function coreRequestHandlerInner(
|
|
529
824
|
request: Request,
|
|
530
825
|
env: TEnv,
|
|
531
826
|
url: URL,
|
|
532
827
|
variables: Record<string, any>,
|
|
533
828
|
nonce: string | undefined,
|
|
829
|
+
routeParams?: Record<string, string>,
|
|
830
|
+
routeKey?: string,
|
|
831
|
+
handleStore?: ReturnType<typeof requireRequestContext>["_handleStore"],
|
|
832
|
+
actionContinuation?: ActionContinuation,
|
|
534
833
|
): Promise<Response> {
|
|
535
834
|
const isPartial = url.searchParams.has("_rsc_partial");
|
|
536
835
|
const isAction =
|
|
537
836
|
request.headers.has("rsc-action") || url.searchParams.has("_rsc_action");
|
|
538
|
-
const actionId =
|
|
539
|
-
request.headers.get("rsc-action") || url.searchParams.get("_rsc_action");
|
|
540
837
|
|
|
541
838
|
// Version mismatch detection - client may have stale code after HMR/deployment
|
|
542
839
|
// If versions don't match, tell the client to reload
|
|
@@ -546,20 +843,23 @@ export function createRSCHandler<
|
|
|
546
843
|
`[RSC] Version mismatch: client=${clientVersion}, server=${version}. Forcing reload.`,
|
|
547
844
|
);
|
|
548
845
|
|
|
549
|
-
//
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
846
|
+
// For actions, reload current page (referer) if same origin.
|
|
847
|
+
// For navigation, load the target URL.
|
|
848
|
+
// Validate referer origin to prevent open redirect via crafted header.
|
|
849
|
+
let reloadUrl = stripInternalParams(url).toString();
|
|
850
|
+
if (isAction) {
|
|
851
|
+
const referer = request.headers.get("referer");
|
|
852
|
+
if (referer) {
|
|
853
|
+
try {
|
|
854
|
+
const refererUrl = new URL(referer);
|
|
855
|
+
if (refererUrl.origin === url.origin) {
|
|
856
|
+
reloadUrl = referer;
|
|
857
|
+
}
|
|
858
|
+
} catch {
|
|
859
|
+
// Malformed referer, fall back to cleanUrl
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
}
|
|
563
863
|
|
|
564
864
|
// Return special response that tells client to reload
|
|
565
865
|
return createResponseWithMergedHeaders(null, {
|
|
@@ -577,12 +877,15 @@ export function createRSCHandler<
|
|
|
577
877
|
url.searchParams.has("__debug_manifest") &&
|
|
578
878
|
(isDev || router.allowDebugManifest)
|
|
579
879
|
) {
|
|
580
|
-
const trie = getRouteTrie();
|
|
581
|
-
const
|
|
880
|
+
const trie = getRouterTrie(router.id) ?? getRouteTrie();
|
|
881
|
+
const routeManifest = getRequiredRouteMap();
|
|
882
|
+
const { extractAncestryFromTrie } =
|
|
883
|
+
await import("../build/route-trie.js");
|
|
582
884
|
return new Response(
|
|
583
885
|
JSON.stringify(
|
|
584
886
|
{
|
|
585
|
-
|
|
887
|
+
routerId: router.id,
|
|
888
|
+
routeManifest,
|
|
586
889
|
routeAncestry: trie ? extractAncestryFromTrie(trie) : {},
|
|
587
890
|
routeTrie: trie,
|
|
588
891
|
precomputedEntries: getPrecomputedEntries(),
|
|
@@ -596,30 +899,27 @@ export function createRSCHandler<
|
|
|
596
899
|
);
|
|
597
900
|
}
|
|
598
901
|
|
|
599
|
-
|
|
600
|
-
const handleStore = requireRequestContext()._handleStore;
|
|
902
|
+
const store = handleStore ?? requireRequestContext()._handleStore;
|
|
601
903
|
|
|
602
904
|
try {
|
|
603
|
-
//
|
|
604
|
-
//
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
request,
|
|
608
|
-
env,
|
|
609
|
-
url,
|
|
610
|
-
isAction,
|
|
611
|
-
handleStore,
|
|
612
|
-
nonce,
|
|
613
|
-
);
|
|
614
|
-
if (progressiveResult) {
|
|
615
|
-
return progressiveResult;
|
|
905
|
+
// Route params were already set in coreRequestHandler, but set again
|
|
906
|
+
// for callers that enter coreRequestHandlerInner directly.
|
|
907
|
+
if (routeParams) {
|
|
908
|
+
setRequestContextParams(routeParams, routeKey);
|
|
616
909
|
}
|
|
617
910
|
|
|
618
911
|
// ============================================================================
|
|
619
|
-
//
|
|
912
|
+
// ACTION REVALIDATION (action already executed, revalidate segments)
|
|
620
913
|
// ============================================================================
|
|
621
|
-
if (
|
|
622
|
-
return
|
|
914
|
+
if (actionContinuation) {
|
|
915
|
+
return await revalidateAfterAction(
|
|
916
|
+
handlerCtx,
|
|
917
|
+
request,
|
|
918
|
+
env,
|
|
919
|
+
url,
|
|
920
|
+
store,
|
|
921
|
+
actionContinuation,
|
|
922
|
+
);
|
|
623
923
|
}
|
|
624
924
|
|
|
625
925
|
// ============================================================================
|
|
@@ -627,7 +927,14 @@ export function createRSCHandler<
|
|
|
627
927
|
// ============================================================================
|
|
628
928
|
const isLoaderRequest = url.searchParams.has("_rsc_loader");
|
|
629
929
|
if (isLoaderRequest) {
|
|
630
|
-
return handleLoaderFetch(
|
|
930
|
+
return handleLoaderFetch(
|
|
931
|
+
handlerCtx,
|
|
932
|
+
request,
|
|
933
|
+
env,
|
|
934
|
+
url,
|
|
935
|
+
variables,
|
|
936
|
+
routeParams,
|
|
937
|
+
);
|
|
631
938
|
}
|
|
632
939
|
|
|
633
940
|
// ============================================================================
|
|
@@ -635,11 +942,12 @@ export function createRSCHandler<
|
|
|
635
942
|
// ============================================================================
|
|
636
943
|
// Note: Must use "return await" for try/catch to catch async rejections
|
|
637
944
|
return await handleRscRendering(
|
|
945
|
+
handlerCtx,
|
|
638
946
|
request,
|
|
639
947
|
env,
|
|
640
948
|
url,
|
|
641
949
|
isPartial,
|
|
642
|
-
|
|
950
|
+
store,
|
|
643
951
|
nonce,
|
|
644
952
|
);
|
|
645
953
|
} catch (error) {
|
|
@@ -653,23 +961,25 @@ export function createRSCHandler<
|
|
|
653
961
|
if (isPartial && error.status === 200) {
|
|
654
962
|
console.warn(
|
|
655
963
|
`[RSC] Route handler at ${url.pathname} returned a Response during client-side navigation. ` +
|
|
656
|
-
|
|
964
|
+
`Falling back to hard navigation. Use data-external on the <Link> to avoid the extra round-trip.`,
|
|
657
965
|
);
|
|
658
|
-
const cleanUrl = new URL(url);
|
|
659
|
-
cleanUrl.searchParams.delete("_rsc_partial");
|
|
660
|
-
cleanUrl.searchParams.delete("_rsc_segments");
|
|
661
|
-
cleanUrl.searchParams.delete("_rsc_v");
|
|
662
|
-
cleanUrl.searchParams.delete("_rsc_stale");
|
|
663
|
-
cleanUrl.searchParams.delete("_rsc_action");
|
|
664
|
-
cleanUrl.searchParams.delete("_rsc_prev");
|
|
665
966
|
return createResponseWithMergedHeaders(null, {
|
|
666
967
|
status: 200,
|
|
667
968
|
headers: {
|
|
668
|
-
"X-RSC-Reload":
|
|
969
|
+
"X-RSC-Reload": stripInternalParams(url).toString(),
|
|
669
970
|
"content-type": "text/x-component;charset=utf-8",
|
|
670
971
|
},
|
|
671
972
|
});
|
|
672
973
|
}
|
|
974
|
+
|
|
975
|
+
if (isPartial) {
|
|
976
|
+
const intercepted = interceptRedirectForPartial(
|
|
977
|
+
error,
|
|
978
|
+
createRedirectFlightResponse,
|
|
979
|
+
);
|
|
980
|
+
if (intercepted) return intercepted;
|
|
981
|
+
}
|
|
982
|
+
|
|
673
983
|
return error;
|
|
674
984
|
}
|
|
675
985
|
|
|
@@ -703,21 +1013,15 @@ export function createRSCHandler<
|
|
|
703
1013
|
params: {},
|
|
704
1014
|
};
|
|
705
1015
|
|
|
706
|
-
// Render with rootLayout to maintain app shell
|
|
707
|
-
const root = await renderSegments([notFoundSegment], {
|
|
708
|
-
rootLayout: router.rootLayout,
|
|
709
|
-
// No routeName for not-found routes
|
|
710
|
-
});
|
|
711
|
-
|
|
712
1016
|
const payload: RscPayload = {
|
|
713
|
-
root,
|
|
714
1017
|
metadata: {
|
|
715
1018
|
pathname: url.pathname,
|
|
716
1019
|
segments: [notFoundSegment],
|
|
717
1020
|
matched: [],
|
|
718
1021
|
diff: [],
|
|
719
1022
|
isPartial: false,
|
|
720
|
-
|
|
1023
|
+
rootLayout: router.rootLayout,
|
|
1024
|
+
handles: store.stream(),
|
|
721
1025
|
version,
|
|
722
1026
|
themeConfig: router.themeConfig,
|
|
723
1027
|
warmupEnabled: router.warmupEnabled,
|
|
@@ -728,8 +1032,10 @@ export function createRSCHandler<
|
|
|
728
1032
|
|
|
729
1033
|
const rscStream = renderToReadableStream(payload);
|
|
730
1034
|
|
|
731
|
-
// Determine if this is an RSC request or HTML request
|
|
1035
|
+
// Determine if this is an RSC request or HTML request.
|
|
1036
|
+
// Partial requests are always RSC (see main isRscRequest comment).
|
|
732
1037
|
const isRscRequest =
|
|
1038
|
+
isPartial ||
|
|
733
1039
|
(!request.headers.get("accept")?.includes("text/html") &&
|
|
734
1040
|
!url.searchParams.has("__html")) ||
|
|
735
1041
|
url.searchParams.has("__rsc");
|
|
@@ -741,9 +1047,18 @@ export function createRSCHandler<
|
|
|
741
1047
|
});
|
|
742
1048
|
}
|
|
743
1049
|
|
|
744
|
-
// Delegate to SSR for HTML response
|
|
745
|
-
const ssrModule = await
|
|
746
|
-
|
|
1050
|
+
// Delegate to SSR for HTML response (reuse early setup if available)
|
|
1051
|
+
const [ssrModule, streamMode] = await getSSRSetup(
|
|
1052
|
+
handlerCtx,
|
|
1053
|
+
request,
|
|
1054
|
+
env,
|
|
1055
|
+
url,
|
|
1056
|
+
requireRequestContext()._metricsStore,
|
|
1057
|
+
);
|
|
1058
|
+
const htmlStream = await ssrModule.renderHTML(rscStream, {
|
|
1059
|
+
nonce,
|
|
1060
|
+
streamMode,
|
|
1061
|
+
});
|
|
747
1062
|
|
|
748
1063
|
return createResponseWithMergedHeaders(htmlStream, {
|
|
749
1064
|
status: 404,
|
|
@@ -762,682 +1077,4 @@ export function createRSCHandler<
|
|
|
762
1077
|
throw error;
|
|
763
1078
|
}
|
|
764
1079
|
}
|
|
765
|
-
|
|
766
|
-
// ============================================================================
|
|
767
|
-
// PROGRESSIVE ENHANCEMENT HANDLER
|
|
768
|
-
// When JavaScript is disabled, React renders forms with hidden fields
|
|
769
|
-
// ($ACTION_REF_*, $ACTION_KEY) containing the action reference.
|
|
770
|
-
// We detect these and return HTML instead of RSC stream.
|
|
771
|
-
// ============================================================================
|
|
772
|
-
async function handleProgressiveEnhancement(
|
|
773
|
-
request: Request,
|
|
774
|
-
env: TEnv,
|
|
775
|
-
url: URL,
|
|
776
|
-
isAction: boolean,
|
|
777
|
-
handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
|
|
778
|
-
nonce: string | undefined,
|
|
779
|
-
): Promise<Response | null> {
|
|
780
|
-
const contentType = request.headers.get("content-type") || "";
|
|
781
|
-
const isFormSubmission =
|
|
782
|
-
contentType.includes("multipart/form-data") ||
|
|
783
|
-
contentType.includes("application/x-www-form-urlencoded");
|
|
784
|
-
|
|
785
|
-
if (request.method !== "POST" || isAction || !isFormSubmission) {
|
|
786
|
-
return null;
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
// Clone the request to read FormData without consuming it
|
|
790
|
-
const formData = await request.clone().formData();
|
|
791
|
-
|
|
792
|
-
// Look for React's progressive enhancement hidden fields
|
|
793
|
-
let isDirectAction = false;
|
|
794
|
-
let isUseActionState = false;
|
|
795
|
-
let directActionId: string | null = null;
|
|
796
|
-
|
|
797
|
-
formData.forEach((_value, key) => {
|
|
798
|
-
if (key.startsWith("$ACTION_ID_")) {
|
|
799
|
-
isDirectAction = true;
|
|
800
|
-
directActionId = key.slice("$ACTION_ID_".length);
|
|
801
|
-
} else if (key.startsWith("$ACTION_REF_")) {
|
|
802
|
-
isUseActionState = true;
|
|
803
|
-
}
|
|
804
|
-
});
|
|
805
|
-
|
|
806
|
-
if (!isDirectAction && !isUseActionState) {
|
|
807
|
-
return null;
|
|
808
|
-
}
|
|
809
|
-
|
|
810
|
-
// Execute action and return HTML
|
|
811
|
-
let actionResult: unknown = undefined;
|
|
812
|
-
let reactFormState: ReactFormState | null = null;
|
|
813
|
-
|
|
814
|
-
if (isUseActionState) {
|
|
815
|
-
try {
|
|
816
|
-
const boundAction = await decodeAction(formData);
|
|
817
|
-
actionResult = await boundAction();
|
|
818
|
-
} catch (error) {
|
|
819
|
-
callOnError(error, "action", {
|
|
820
|
-
request,
|
|
821
|
-
url,
|
|
822
|
-
env,
|
|
823
|
-
handledByBoundary: false,
|
|
824
|
-
});
|
|
825
|
-
console.error("[RSC] Progressive enhancement action error:", error);
|
|
826
|
-
}
|
|
827
|
-
} else if (isDirectAction && directActionId) {
|
|
828
|
-
const temporaryReferences = createTemporaryReferenceSet();
|
|
829
|
-
|
|
830
|
-
let args: unknown[] = [];
|
|
831
|
-
try {
|
|
832
|
-
args = await decodeReply(formData, { temporaryReferences });
|
|
833
|
-
} catch {
|
|
834
|
-
args = [formData];
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
try {
|
|
838
|
-
const loadedAction = await loadServerAction(directActionId);
|
|
839
|
-
actionResult = await loadedAction.apply(null, args);
|
|
840
|
-
} catch (error) {
|
|
841
|
-
callOnError(error, "action", {
|
|
842
|
-
request,
|
|
843
|
-
url,
|
|
844
|
-
env,
|
|
845
|
-
actionId: directActionId,
|
|
846
|
-
handledByBoundary: false,
|
|
847
|
-
});
|
|
848
|
-
console.error("[RSC] Progressive enhancement action error:", error);
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
// Decode form state for useActionState progressive enhancement
|
|
853
|
-
try {
|
|
854
|
-
reactFormState = await decodeFormState(actionResult, formData);
|
|
855
|
-
} catch (error) {
|
|
856
|
-
callOnError(error, "action", {
|
|
857
|
-
request,
|
|
858
|
-
url,
|
|
859
|
-
env,
|
|
860
|
-
handledByBoundary: false,
|
|
861
|
-
});
|
|
862
|
-
console.error("[RSC] Failed to decode form state:", error);
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
// Re-render the page and return HTML
|
|
866
|
-
const renderRequest = new Request(url.toString(), {
|
|
867
|
-
method: "GET",
|
|
868
|
-
headers: new Headers({ accept: "text/html" }),
|
|
869
|
-
});
|
|
870
|
-
|
|
871
|
-
const match = await router.match(renderRequest, env);
|
|
872
|
-
|
|
873
|
-
if (match.redirect) {
|
|
874
|
-
return new Response(null, {
|
|
875
|
-
status: 308,
|
|
876
|
-
headers: { Location: match.redirect },
|
|
877
|
-
});
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
const root = renderSegments(match.segments, {
|
|
881
|
-
rootLayout: router.rootLayout,
|
|
882
|
-
});
|
|
883
|
-
|
|
884
|
-
const payload: RscPayload = {
|
|
885
|
-
root,
|
|
886
|
-
metadata: {
|
|
887
|
-
pathname: url.pathname,
|
|
888
|
-
segments: match.segments,
|
|
889
|
-
matched: match.matched,
|
|
890
|
-
diff: match.diff,
|
|
891
|
-
isPartial: false,
|
|
892
|
-
rootLayout: router.rootLayout,
|
|
893
|
-
handles: handleStore.stream(),
|
|
894
|
-
version,
|
|
895
|
-
themeConfig: router.themeConfig,
|
|
896
|
-
warmupEnabled: router.warmupEnabled,
|
|
897
|
-
initialTheme: requireRequestContext().theme,
|
|
898
|
-
},
|
|
899
|
-
formState: actionResult,
|
|
900
|
-
};
|
|
901
|
-
|
|
902
|
-
const rscStream = renderToReadableStream<RscPayload>(payload);
|
|
903
|
-
const ssrModule = await loadSSRModule();
|
|
904
|
-
const htmlStream = await ssrModule.renderHTML(rscStream, {
|
|
905
|
-
formState: reactFormState,
|
|
906
|
-
nonce,
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
return new Response(htmlStream, {
|
|
910
|
-
headers: { "content-type": "text/html;charset=utf-8" },
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// ============================================================================
|
|
915
|
-
// SERVER ACTION HANDLER
|
|
916
|
-
// ============================================================================
|
|
917
|
-
async function handleServerAction(
|
|
918
|
-
request: Request,
|
|
919
|
-
env: TEnv,
|
|
920
|
-
url: URL,
|
|
921
|
-
actionId: string,
|
|
922
|
-
handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
|
|
923
|
-
): Promise<Response> {
|
|
924
|
-
const temporaryReferences = createTemporaryReferenceSet();
|
|
925
|
-
|
|
926
|
-
// Decode action arguments from request body
|
|
927
|
-
const contentType = request.headers.get("content-type") || "";
|
|
928
|
-
let args: unknown[] = [];
|
|
929
|
-
let actionFormData: FormData | undefined;
|
|
930
|
-
|
|
931
|
-
try {
|
|
932
|
-
const body = contentType.includes("multipart/form-data")
|
|
933
|
-
? await request.formData()
|
|
934
|
-
: await request.text();
|
|
935
|
-
|
|
936
|
-
if (body instanceof FormData) {
|
|
937
|
-
actionFormData = body;
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
if (hasBodyContent(body)) {
|
|
941
|
-
args = await decodeReply(body, { temporaryReferences });
|
|
942
|
-
}
|
|
943
|
-
} catch (error) {
|
|
944
|
-
callOnError(error, "action", {
|
|
945
|
-
request,
|
|
946
|
-
url,
|
|
947
|
-
env,
|
|
948
|
-
actionId,
|
|
949
|
-
handledByBoundary: false,
|
|
950
|
-
});
|
|
951
|
-
throw new Error(`Failed to decode action arguments: ${error}`, {
|
|
952
|
-
cause: error,
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
// Execute the server action
|
|
957
|
-
let returnValue: { ok: boolean; data: unknown };
|
|
958
|
-
let actionStatus = 200;
|
|
959
|
-
let loadedAction: Function | undefined;
|
|
960
|
-
|
|
961
|
-
try {
|
|
962
|
-
loadedAction = await loadServerAction(actionId);
|
|
963
|
-
const data = await loadedAction!.apply(null, args);
|
|
964
|
-
returnValue = { ok: true, data };
|
|
965
|
-
} catch (error) {
|
|
966
|
-
returnValue = { ok: false, data: error };
|
|
967
|
-
actionStatus = 500;
|
|
968
|
-
|
|
969
|
-
// Try to render error boundary
|
|
970
|
-
const errorResult = await router.matchError(request, env, error, "route");
|
|
971
|
-
|
|
972
|
-
// Report the action error (handledByBoundary indicates if error boundary will render)
|
|
973
|
-
callOnError(error, "action", {
|
|
974
|
-
request,
|
|
975
|
-
url,
|
|
976
|
-
env,
|
|
977
|
-
actionId,
|
|
978
|
-
handledByBoundary: !!errorResult,
|
|
979
|
-
});
|
|
980
|
-
|
|
981
|
-
if (errorResult) {
|
|
982
|
-
setRequestContextParams(errorResult.params);
|
|
983
|
-
|
|
984
|
-
const payload: RscPayload = {
|
|
985
|
-
root: null,
|
|
986
|
-
metadata: {
|
|
987
|
-
pathname: url.pathname,
|
|
988
|
-
segments: errorResult.segments,
|
|
989
|
-
isPartial: true,
|
|
990
|
-
matched: errorResult.matched,
|
|
991
|
-
diff: errorResult.diff,
|
|
992
|
-
isError: true,
|
|
993
|
-
handles: handleStore.stream(),
|
|
994
|
-
version,
|
|
995
|
-
},
|
|
996
|
-
returnValue,
|
|
997
|
-
};
|
|
998
|
-
|
|
999
|
-
const rscStream = renderToReadableStream<RscPayload>(payload, {
|
|
1000
|
-
temporaryReferences,
|
|
1001
|
-
});
|
|
1002
|
-
|
|
1003
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1004
|
-
status: actionStatus,
|
|
1005
|
-
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
1006
|
-
});
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
|
|
1010
|
-
// Revalidate after action
|
|
1011
|
-
const resolvedActionId =
|
|
1012
|
-
(loadedAction as { $id?: string; $$id?: string } | undefined)?.$id ??
|
|
1013
|
-
(loadedAction as { $$id?: string } | undefined)?.$$id ??
|
|
1014
|
-
actionId;
|
|
1015
|
-
const actionContext = {
|
|
1016
|
-
actionId: resolvedActionId,
|
|
1017
|
-
actionUrl: new URL(request.url),
|
|
1018
|
-
actionResult: returnValue.data,
|
|
1019
|
-
formData: actionFormData,
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
const matchResult = await router.matchPartial(request, env, actionContext);
|
|
1023
|
-
|
|
1024
|
-
if (!matchResult) {
|
|
1025
|
-
// Fall back to full render
|
|
1026
|
-
const fullMatch = await router.match(request, env);
|
|
1027
|
-
setRequestContextParams(fullMatch.params);
|
|
1028
|
-
|
|
1029
|
-
if (fullMatch.redirect) {
|
|
1030
|
-
return createResponseWithMergedHeaders(null, {
|
|
1031
|
-
status: 308,
|
|
1032
|
-
headers: { Location: fullMatch.redirect },
|
|
1033
|
-
});
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
const renderStart = performance.now();
|
|
1037
|
-
const root = renderSegments(fullMatch.segments, {
|
|
1038
|
-
rootLayout: router.rootLayout,
|
|
1039
|
-
isAction: true,
|
|
1040
|
-
});
|
|
1041
|
-
const renderDuration = performance.now() - renderStart;
|
|
1042
|
-
const serverTiming = fullMatch.serverTiming
|
|
1043
|
-
? `${fullMatch.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
|
|
1044
|
-
: `rendering;dur=${renderDuration.toFixed(2)}`;
|
|
1045
|
-
|
|
1046
|
-
const payload: RscPayload = {
|
|
1047
|
-
root,
|
|
1048
|
-
metadata: {
|
|
1049
|
-
pathname: url.pathname,
|
|
1050
|
-
segments: fullMatch.segments,
|
|
1051
|
-
matched: fullMatch.matched,
|
|
1052
|
-
diff: fullMatch.diff,
|
|
1053
|
-
handles: handleStore.stream(),
|
|
1054
|
-
version,
|
|
1055
|
-
},
|
|
1056
|
-
returnValue,
|
|
1057
|
-
};
|
|
1058
|
-
|
|
1059
|
-
const rscStream = renderToReadableStream<RscPayload>(payload, {
|
|
1060
|
-
temporaryReferences,
|
|
1061
|
-
});
|
|
1062
|
-
|
|
1063
|
-
const headers: Record<string, string> = {
|
|
1064
|
-
"content-type": "text/x-component;charset=utf-8",
|
|
1065
|
-
};
|
|
1066
|
-
if (serverTiming) {
|
|
1067
|
-
headers["Server-Timing"] = serverTiming;
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1071
|
-
status: actionStatus,
|
|
1072
|
-
headers,
|
|
1073
|
-
});
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
// Return updated segments
|
|
1077
|
-
setRequestContextParams(matchResult.params);
|
|
1078
|
-
|
|
1079
|
-
const renderStart = performance.now();
|
|
1080
|
-
|
|
1081
|
-
const renderDuration = performance.now() - renderStart;
|
|
1082
|
-
const serverTiming = matchResult.serverTiming
|
|
1083
|
-
? `${matchResult.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
|
|
1084
|
-
: `rendering;dur=${renderDuration.toFixed(2)}`;
|
|
1085
|
-
|
|
1086
|
-
const payload: RscPayload = {
|
|
1087
|
-
root: null,
|
|
1088
|
-
metadata: {
|
|
1089
|
-
pathname: url.pathname,
|
|
1090
|
-
segments: matchResult.segments,
|
|
1091
|
-
isPartial: true,
|
|
1092
|
-
matched: matchResult.matched,
|
|
1093
|
-
diff: matchResult.diff,
|
|
1094
|
-
slots: matchResult.slots,
|
|
1095
|
-
handles: handleStore.stream(),
|
|
1096
|
-
version,
|
|
1097
|
-
},
|
|
1098
|
-
returnValue,
|
|
1099
|
-
};
|
|
1100
|
-
|
|
1101
|
-
const rscStream = renderToReadableStream<RscPayload>(payload, {
|
|
1102
|
-
temporaryReferences,
|
|
1103
|
-
});
|
|
1104
|
-
|
|
1105
|
-
const actionHeaders: Record<string, string> = {
|
|
1106
|
-
"content-type": "text/x-component;charset=utf-8",
|
|
1107
|
-
};
|
|
1108
|
-
if (serverTiming) {
|
|
1109
|
-
actionHeaders["Server-Timing"] = serverTiming;
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1113
|
-
status: actionStatus,
|
|
1114
|
-
headers: actionHeaders,
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
// ============================================================================
|
|
1119
|
-
// LOADER FETCH HANDLER
|
|
1120
|
-
// Supports GET (params in query string) and POST/PUT/PATCH/DELETE (JSON body)
|
|
1121
|
-
// ============================================================================
|
|
1122
|
-
async function handleLoaderFetch(
|
|
1123
|
-
request: Request,
|
|
1124
|
-
env: TEnv,
|
|
1125
|
-
url: URL,
|
|
1126
|
-
variables: Record<string, any>,
|
|
1127
|
-
): Promise<Response> {
|
|
1128
|
-
const loaderId = url.searchParams.get("_rsc_loader");
|
|
1129
|
-
|
|
1130
|
-
if (!loaderId) {
|
|
1131
|
-
return createResponseWithMergedHeaders("Missing _rsc_loader parameter", {
|
|
1132
|
-
status: 400,
|
|
1133
|
-
});
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
// Look up loader lazily
|
|
1137
|
-
const registeredLoader = await getLoaderLazy(loaderId);
|
|
1138
|
-
if (!registeredLoader) {
|
|
1139
|
-
return createResponseWithMergedHeaders(
|
|
1140
|
-
`Loader "${loaderId}" not found in registry`,
|
|
1141
|
-
{ status: 404 },
|
|
1142
|
-
);
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
// Parse params and body based on request method
|
|
1146
|
-
let loaderParams: Record<string, string> = {};
|
|
1147
|
-
let loaderBody: unknown = undefined;
|
|
1148
|
-
const isBodyMethod = request.method !== "GET" && request.method !== "HEAD";
|
|
1149
|
-
|
|
1150
|
-
if (isBodyMethod) {
|
|
1151
|
-
try {
|
|
1152
|
-
const contentType = request.headers.get("content-type") || "";
|
|
1153
|
-
if (contentType.includes("application/json")) {
|
|
1154
|
-
const jsonBody = (await request.json()) as {
|
|
1155
|
-
params?: Record<string, string>;
|
|
1156
|
-
body?: unknown;
|
|
1157
|
-
};
|
|
1158
|
-
loaderParams = jsonBody.params ?? {};
|
|
1159
|
-
loaderBody = jsonBody.body;
|
|
1160
|
-
}
|
|
1161
|
-
} catch {
|
|
1162
|
-
return createResponseWithMergedHeaders("Invalid JSON body", {
|
|
1163
|
-
status: 400,
|
|
1164
|
-
});
|
|
1165
|
-
}
|
|
1166
|
-
} else {
|
|
1167
|
-
const loaderParamsJson = url.searchParams.get("_rsc_loader_params");
|
|
1168
|
-
if (loaderParamsJson) {
|
|
1169
|
-
try {
|
|
1170
|
-
loaderParams = JSON.parse(loaderParamsJson);
|
|
1171
|
-
} catch {
|
|
1172
|
-
return createResponseWithMergedHeaders(
|
|
1173
|
-
"Invalid _rsc_loader_params JSON",
|
|
1174
|
-
{ status: 400 },
|
|
1175
|
-
);
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
|
-
// Execute the loader with middleware
|
|
1181
|
-
try {
|
|
1182
|
-
const { fn, middleware } = registeredLoader;
|
|
1183
|
-
|
|
1184
|
-
return await executeLoaderMiddleware(
|
|
1185
|
-
middleware,
|
|
1186
|
-
request,
|
|
1187
|
-
env,
|
|
1188
|
-
loaderParams,
|
|
1189
|
-
variables,
|
|
1190
|
-
async () => {
|
|
1191
|
-
const ctx = requireRequestContext();
|
|
1192
|
-
const loaderCtx: any = {
|
|
1193
|
-
...ctx,
|
|
1194
|
-
params: loaderParams,
|
|
1195
|
-
body: loaderBody,
|
|
1196
|
-
};
|
|
1197
|
-
|
|
1198
|
-
const result = await fn(loaderCtx);
|
|
1199
|
-
|
|
1200
|
-
interface LoaderPayload {
|
|
1201
|
-
loaderResult: unknown;
|
|
1202
|
-
}
|
|
1203
|
-
const loaderPayload: LoaderPayload = { loaderResult: result };
|
|
1204
|
-
const rscStream =
|
|
1205
|
-
renderToReadableStream<LoaderPayload>(loaderPayload);
|
|
1206
|
-
|
|
1207
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1208
|
-
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
1209
|
-
});
|
|
1210
|
-
},
|
|
1211
|
-
);
|
|
1212
|
-
} catch (error) {
|
|
1213
|
-
const err = error instanceof Error ? error : new Error(String(error));
|
|
1214
|
-
const isDev = process.env.NODE_ENV !== "production";
|
|
1215
|
-
|
|
1216
|
-
console.error("[RSC] Loader error:", error);
|
|
1217
|
-
|
|
1218
|
-
callOnError(error, "loader", {
|
|
1219
|
-
request,
|
|
1220
|
-
url,
|
|
1221
|
-
env,
|
|
1222
|
-
loaderName: loaderId,
|
|
1223
|
-
handledByBoundary: false,
|
|
1224
|
-
});
|
|
1225
|
-
|
|
1226
|
-
const errorPayload = {
|
|
1227
|
-
loaderResult: null,
|
|
1228
|
-
loaderError: {
|
|
1229
|
-
message: isDev ? err.message : "An error occurred",
|
|
1230
|
-
name: err.name,
|
|
1231
|
-
},
|
|
1232
|
-
};
|
|
1233
|
-
const rscStream = renderToReadableStream(errorPayload);
|
|
1234
|
-
|
|
1235
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1236
|
-
status: 500,
|
|
1237
|
-
headers: { "content-type": "text/x-component;charset=utf-8" },
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
// ============================================================================
|
|
1243
|
-
// RSC RENDERING HANDLER (Navigation)
|
|
1244
|
-
// ============================================================================
|
|
1245
|
-
async function handleRscRendering(
|
|
1246
|
-
request: Request,
|
|
1247
|
-
env: TEnv,
|
|
1248
|
-
url: URL,
|
|
1249
|
-
isPartial: boolean,
|
|
1250
|
-
handleStore: ReturnType<typeof requireRequestContext>["_handleStore"],
|
|
1251
|
-
nonce: string | undefined,
|
|
1252
|
-
): Promise<Response> {
|
|
1253
|
-
// Retrieve handler-level timing from variables
|
|
1254
|
-
const reqCtx = requireRequestContext();
|
|
1255
|
-
const handlerTimingArr: string[] = reqCtx.var.__handlerTiming || [];
|
|
1256
|
-
const handlerStart: number = reqCtx.var.__handlerStart || 0;
|
|
1257
|
-
|
|
1258
|
-
let payload: RscPayload;
|
|
1259
|
-
let serverTiming: string | undefined;
|
|
1260
|
-
|
|
1261
|
-
if (isPartial) {
|
|
1262
|
-
// Partial render (navigation)
|
|
1263
|
-
const result = await router.matchPartial(request, env);
|
|
1264
|
-
|
|
1265
|
-
if (!result) {
|
|
1266
|
-
// Fall back to full render
|
|
1267
|
-
const match = await router.match(request, env);
|
|
1268
|
-
setRequestContextParams(match.params);
|
|
1269
|
-
|
|
1270
|
-
if (match.redirect) {
|
|
1271
|
-
return createResponseWithMergedHeaders(null, {
|
|
1272
|
-
status: 308,
|
|
1273
|
-
headers: { Location: match.redirect },
|
|
1274
|
-
});
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
const renderStart = performance.now();
|
|
1278
|
-
const root = renderSegments(match.segments, {
|
|
1279
|
-
rootLayout: router.rootLayout,
|
|
1280
|
-
});
|
|
1281
|
-
const renderDuration = performance.now() - renderStart;
|
|
1282
|
-
serverTiming = match.serverTiming
|
|
1283
|
-
? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
|
|
1284
|
-
: `rendering;dur=${renderDuration.toFixed(2)}`;
|
|
1285
|
-
|
|
1286
|
-
payload = {
|
|
1287
|
-
root,
|
|
1288
|
-
metadata: {
|
|
1289
|
-
pathname: url.pathname,
|
|
1290
|
-
segments: match.segments,
|
|
1291
|
-
matched: match.matched,
|
|
1292
|
-
diff: match.diff,
|
|
1293
|
-
isPartial: false,
|
|
1294
|
-
handles: handleStore.stream(),
|
|
1295
|
-
version,
|
|
1296
|
-
themeConfig: router.themeConfig,
|
|
1297
|
-
initialTheme: reqCtx.theme,
|
|
1298
|
-
},
|
|
1299
|
-
};
|
|
1300
|
-
} else {
|
|
1301
|
-
setRequestContextParams(result.params);
|
|
1302
|
-
serverTiming = result.serverTiming;
|
|
1303
|
-
|
|
1304
|
-
payload = {
|
|
1305
|
-
root: null,
|
|
1306
|
-
metadata: {
|
|
1307
|
-
pathname: url.pathname,
|
|
1308
|
-
segments: result.segments,
|
|
1309
|
-
matched: result.matched,
|
|
1310
|
-
diff: result.diff,
|
|
1311
|
-
isPartial: true,
|
|
1312
|
-
slots: result.slots,
|
|
1313
|
-
handles: handleStore.stream(),
|
|
1314
|
-
version,
|
|
1315
|
-
},
|
|
1316
|
-
};
|
|
1317
|
-
}
|
|
1318
|
-
} else {
|
|
1319
|
-
// Full render (initial page load)
|
|
1320
|
-
const match = await router.match(request, env);
|
|
1321
|
-
setRequestContextParams(match.params);
|
|
1322
|
-
|
|
1323
|
-
if (match.redirect) {
|
|
1324
|
-
return createResponseWithMergedHeaders(null, {
|
|
1325
|
-
status: 308,
|
|
1326
|
-
headers: { Location: match.redirect },
|
|
1327
|
-
});
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
// Caching is now handled in router.match() via cache provider in request context
|
|
1331
|
-
// match.segments already contains cached or fresh segments as appropriate
|
|
1332
|
-
|
|
1333
|
-
if (url.searchParams.has("__prerender_collect")) {
|
|
1334
|
-
// Build-time prerender collection: serialize segments and handle data
|
|
1335
|
-
// to JSON for storage as build artifacts. At runtime the worker
|
|
1336
|
-
// deserializes these and feeds them through the normal segment pipeline.
|
|
1337
|
-
const nonLoaderSegments = match.segments.filter((s) => s.type !== "loader");
|
|
1338
|
-
await handleStore.settled;
|
|
1339
|
-
const { serializeSegments } = await import("../cache/cache-scope.js");
|
|
1340
|
-
const serializedSegments = await serializeSegments(nonLoaderSegments);
|
|
1341
|
-
const handles: Record<string, Record<string, unknown[]>> = {};
|
|
1342
|
-
for (const seg of nonLoaderSegments) {
|
|
1343
|
-
handles[seg.id] = handleStore.getDataForSegment(seg.id);
|
|
1344
|
-
}
|
|
1345
|
-
return new Response(
|
|
1346
|
-
JSON.stringify({
|
|
1347
|
-
segments: serializedSegments,
|
|
1348
|
-
handles,
|
|
1349
|
-
routeName: match.routeName,
|
|
1350
|
-
params: match.params,
|
|
1351
|
-
}),
|
|
1352
|
-
{ headers: { "Content-Type": "application/json" } },
|
|
1353
|
-
);
|
|
1354
|
-
} else {
|
|
1355
|
-
const renderStart = performance.now();
|
|
1356
|
-
const root = renderSegments(match.segments, {
|
|
1357
|
-
rootLayout: router.rootLayout,
|
|
1358
|
-
});
|
|
1359
|
-
const renderDuration = performance.now() - renderStart;
|
|
1360
|
-
serverTiming = match.serverTiming
|
|
1361
|
-
? `${match.serverTiming}, rendering;dur=${renderDuration.toFixed(2)}`
|
|
1362
|
-
: `rendering;dur=${renderDuration.toFixed(2)}`;
|
|
1363
|
-
|
|
1364
|
-
payload = {
|
|
1365
|
-
root,
|
|
1366
|
-
metadata: {
|
|
1367
|
-
pathname: url.pathname,
|
|
1368
|
-
segments: match.segments,
|
|
1369
|
-
matched: match.matched,
|
|
1370
|
-
diff: match.diff,
|
|
1371
|
-
isPartial: false,
|
|
1372
|
-
rootLayout: router.rootLayout,
|
|
1373
|
-
handles: handleStore.stream(),
|
|
1374
|
-
version,
|
|
1375
|
-
themeConfig: router.themeConfig,
|
|
1376
|
-
initialTheme: reqCtx.theme,
|
|
1377
|
-
},
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
// Serialize to RSC stream
|
|
1383
|
-
const rscSerializeStart = performance.now();
|
|
1384
|
-
const rscStream = renderToReadableStream<RscPayload>(payload);
|
|
1385
|
-
const rscSerializeDur = performance.now() - rscSerializeStart;
|
|
1386
|
-
|
|
1387
|
-
// Determine if this is an RSC request or HTML request
|
|
1388
|
-
const isRscRequest =
|
|
1389
|
-
(!request.headers.get("accept")?.includes("text/html") &&
|
|
1390
|
-
!url.searchParams.has("__html")) ||
|
|
1391
|
-
url.searchParams.has("__rsc");
|
|
1392
|
-
|
|
1393
|
-
// Build complete Server-Timing: handler phases + match/manifest + rendering + RSC serialize
|
|
1394
|
-
const timingParts: string[] = [...handlerTimingArr];
|
|
1395
|
-
if (serverTiming) {
|
|
1396
|
-
timingParts.push(serverTiming);
|
|
1397
|
-
}
|
|
1398
|
-
timingParts.push(`rsc-serialize;dur=${rscSerializeDur.toFixed(2)}`);
|
|
1399
|
-
|
|
1400
|
-
if (isRscRequest) {
|
|
1401
|
-
const fullTiming = timingParts.join(", ");
|
|
1402
|
-
const rscHeaders: Record<string, string> = {
|
|
1403
|
-
"content-type": "text/x-component;charset=utf-8",
|
|
1404
|
-
vary: "accept",
|
|
1405
|
-
};
|
|
1406
|
-
if (fullTiming) {
|
|
1407
|
-
rscHeaders["Server-Timing"] = fullTiming;
|
|
1408
|
-
}
|
|
1409
|
-
return createResponseWithMergedHeaders(rscStream, {
|
|
1410
|
-
headers: rscHeaders,
|
|
1411
|
-
});
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
// Delegate to SSR for HTML response
|
|
1415
|
-
const ssrModuleStart = performance.now();
|
|
1416
|
-
const ssrModule = await loadSSRModule();
|
|
1417
|
-
const ssrModuleDur = performance.now() - ssrModuleStart;
|
|
1418
|
-
timingParts.push(`ssr-module-load;dur=${ssrModuleDur.toFixed(2)}`);
|
|
1419
|
-
|
|
1420
|
-
const ssrRenderStart = performance.now();
|
|
1421
|
-
const htmlStream = await ssrModule.renderHTML(rscStream, { nonce });
|
|
1422
|
-
const ssrRenderDur = performance.now() - ssrRenderStart;
|
|
1423
|
-
timingParts.push(`ssr-render-html;dur=${ssrRenderDur.toFixed(2)}`);
|
|
1424
|
-
|
|
1425
|
-
// Add total handler duration
|
|
1426
|
-
if (handlerStart) {
|
|
1427
|
-
const totalHandler = performance.now() - handlerStart;
|
|
1428
|
-
timingParts.push(`handler-total;dur=${totalHandler.toFixed(2)}`);
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
const fullTiming = timingParts.join(", ");
|
|
1432
|
-
const htmlHeaders: Record<string, string> = {
|
|
1433
|
-
"content-type": "text/html;charset=utf-8",
|
|
1434
|
-
};
|
|
1435
|
-
if (fullTiming) {
|
|
1436
|
-
htmlHeaders["Server-Timing"] = fullTiming;
|
|
1437
|
-
}
|
|
1438
|
-
|
|
1439
|
-
return createResponseWithMergedHeaders(htmlStream, {
|
|
1440
|
-
headers: htmlHeaders,
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
1080
|
}
|