@rangojs/router 0.0.0-experimental.14 → 0.0.0-experimental.140
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 +17 -0
- package/README.md +432 -7
- package/dist/bin/rango.js +2073 -213
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +7258 -2714
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +140 -67
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +329 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +487 -0
- package/skills/caching/SKILL.md +357 -25
- package/skills/comparison/SKILL.md +50 -0
- package/skills/comparison/agents/openai.yaml +4 -0
- package/skills/comparison/references/framework-comparison.md +837 -0
- package/skills/composability/SKILL.md +246 -0
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +16 -10
- package/skills/document-cache/SKILL.md +87 -62
- package/skills/fonts/SKILL.md +6 -4
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +557 -79
- package/skills/host-router/SKILL.md +320 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +207 -15
- package/skills/layout/SKILL.md +146 -6
- package/skills/links/SKILL.md +304 -25
- package/skills/loader/SKILL.md +616 -54
- package/skills/middleware/SKILL.md +217 -37
- package/skills/migrate-nextjs/SKILL.md +611 -0
- package/skills/migrate-react-router/SKILL.md +927 -0
- package/skills/mime-routes/SKILL.md +42 -11
- package/skills/observability/SKILL.md +194 -0
- package/skills/parallel/SKILL.md +284 -3
- package/skills/ppr/SKILL.md +426 -0
- package/skills/prerender/SKILL.md +437 -52
- package/skills/rango/SKILL.md +369 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +263 -121
- package/skills/route/SKILL.md +350 -21
- package/skills/router-setup/SKILL.md +246 -33
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +126 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +131 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +122 -0
- package/skills/testing/response-routes.md +95 -0
- package/skills/testing/reverse-and-types.md +85 -0
- package/skills/testing/server-actions.md +107 -0
- package/skills/testing/server-tree.md +128 -0
- package/skills/testing/setup.md +123 -0
- package/skills/theme/SKILL.md +9 -8
- package/skills/typesafety/SKILL.md +532 -103
- package/skills/use-cache/SKILL.md +367 -0
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +77 -44
- package/src/bin/rango.ts +312 -15
- package/src/browser/action-coordinator.ts +114 -0
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +293 -202
- package/src/browser/history-state.ts +101 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/intercept-utils.ts +52 -0
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/link-interceptor.ts +24 -4
- package/src/browser/logging.ts +11 -0
- package/src/browser/merge-segment-loaders.ts +20 -12
- package/src/browser/navigation-bridge.ts +385 -576
- package/src/browser/navigation-client.ts +245 -75
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +184 -118
- package/src/browser/navigation-transaction.ts +247 -0
- package/src/browser/network-error-handler.ts +88 -0
- package/src/browser/partial-update.ts +412 -364
- package/src/browser/prefetch/cache.ts +359 -0
- package/src/browser/prefetch/fetch.ts +452 -0
- package/src/browser/prefetch/observer.ts +65 -0
- package/src/browser/prefetch/policy.ts +48 -0
- package/src/browser/prefetch/queue.ts +209 -0
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +194 -0
- package/src/browser/react/Link.tsx +275 -68
- package/src/browser/react/NavigationProvider.tsx +265 -109
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +11 -0
- package/src/browser/react/filter-segment-order.ts +70 -0
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +272 -60
- package/src/browser/react/location-state.ts +90 -20
- 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 +35 -66
- package/src/browser/react/use-handle.ts +39 -126
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +39 -13
- package/src/browser/react/use-navigation.ts +53 -69
- package/src/browser/react/use-params.ts +75 -0
- package/src/browser/react/use-pathname.ts +47 -0
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +98 -0
- package/src/browser/react/use-search-params.ts +51 -0
- package/src/browser/react/use-segments.ts +72 -99
- package/src/browser/response-adapter.ts +164 -0
- package/src/browser/rsc-router.tsx +300 -72
- package/src/browser/scroll-restoration.ts +138 -50
- package/src/browser/segment-reconciler.ts +243 -0
- package/src/browser/segment-structure-assert.ts +17 -1
- package/src/browser/server-action-bridge.ts +668 -613
- package/src/browser/types.ts +223 -51
- package/src/browser/validate-redirect-origin.ts +56 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +252 -161
- package/src/build/generate-route-types.ts +41 -1038
- package/src/build/index.ts +12 -7
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +225 -42
- package/src/build/route-types/ast-helpers.ts +25 -0
- package/src/build/route-types/ast-route-extraction.ts +105 -0
- package/src/build/route-types/codegen.ts +113 -0
- package/src/build/route-types/include-resolution.ts +812 -0
- package/src/build/route-types/param-extraction.ts +51 -0
- package/src/build/route-types/per-module-writer.ts +144 -0
- package/src/build/route-types/router-processing.ts +695 -0
- package/src/build/route-types/scan-filter.ts +85 -0
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +223 -0
- package/src/cache/background-task.ts +34 -0
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +60 -0
- package/src/cache/cache-policy.ts +199 -0
- package/src/cache/cache-runtime.ts +525 -0
- package/src/cache/cache-scope.ts +298 -332
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +2500 -158
- package/src/cache/cf/cf-cache-types.ts +349 -0
- package/src/cache/cf/cf-kv-utils.ts +46 -0
- package/src/cache/cf/cf-tag-marker-memo.ts +105 -0
- package/src/cache/cf/index.ts +17 -17
- package/src/cache/document-cache.ts +199 -92
- package/src/cache/handle-capture.ts +81 -0
- package/src/cache/handle-snapshot.ts +111 -0
- package/src/cache/index.ts +29 -35
- package/src/cache/memory-segment-store.ts +363 -30
- package/src/cache/profile-registry.ts +88 -0
- package/src/cache/read-through-swr.ts +178 -0
- package/src/cache/segment-codec.ts +248 -0
- package/src/cache/shell-cache.ts +386 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +153 -0
- package/src/cache/types.ts +156 -211
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1102 -0
- package/src/client.rsc.tsx +43 -21
- package/src/client.tsx +131 -347
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +23 -4
- package/src/components/DefaultDocument.tsx +13 -3
- package/src/context-var.ts +168 -0
- package/src/debug.ts +19 -9
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +106 -10
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +110 -35
- package/src/handles/MetaTags.tsx +83 -59
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +93 -0
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +44 -53
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +20 -65
- package/src/host/errors.ts +21 -30
- package/src/host/index.ts +13 -9
- package/src/host/pattern-matcher.ts +50 -79
- package/src/host/router.ts +151 -121
- package/src/host/testing.ts +45 -32
- package/src/host/types.ts +52 -11
- package/src/host/utils.ts +2 -2
- package/src/href-client.ts +192 -57
- package/src/index.rsc.ts +177 -35
- package/src/index.ts +255 -71
- package/src/internal-debug.ts +9 -2
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +31 -99
- package/src/loader.ts +30 -12
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +41 -0
- package/src/prerender/param-hash.ts +16 -14
- package/src/prerender/store.ts +121 -21
- package/src/prerender.ts +460 -26
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +198 -128
- package/src/root-error-boundary.tsx +42 -48
- package/src/route-content-wrapper.tsx +22 -77
- package/src/route-definition/dsl-helpers.ts +1116 -0
- package/src/route-definition/helper-factories.ts +88 -0
- package/src/route-definition/helpers-types.ts +505 -0
- package/src/route-definition/index.ts +54 -0
- package/src/route-definition/redirect.ts +134 -0
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-definition.ts +1 -1481
- package/src/route-map-builder.ts +82 -144
- package/src/route-name.ts +53 -0
- package/src/route-types.ts +71 -45
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +263 -0
- package/src/router/debug-manifest.ts +72 -0
- package/src/router/error-handling.ts +54 -27
- package/src/router/find-match.ts +245 -0
- package/src/router/handler-context.ts +377 -125
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +59 -28
- package/src/router/lazy-includes.ts +254 -0
- package/src/router/loader-resolution.ts +421 -157
- package/src/router/logging.ts +106 -6
- package/src/router/manifest.ts +131 -57
- package/src/router/match-api.ts +167 -246
- package/src/router/match-context.ts +4 -24
- package/src/router/match-handlers.ts +440 -0
- package/src/router/match-middleware/background-revalidation.ts +117 -93
- package/src/router/match-middleware/cache-lookup.ts +297 -150
- package/src/router/match-middleware/cache-store.ts +123 -51
- package/src/router/match-middleware/intercept-resolution.ts +44 -43
- package/src/router/match-middleware/segment-resolution.ts +64 -22
- package/src/router/match-pipelines.ts +11 -87
- package/src/router/match-result.ts +121 -50
- package/src/router/metrics.ts +219 -28
- package/src/router/middleware-types.ts +93 -0
- package/src/router/middleware.ts +505 -441
- package/src/router/navigation-snapshot.ts +133 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +311 -142
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +547 -0
- package/src/router/preview-match.ts +102 -0
- package/src/router/request-classification.ts +278 -0
- package/src/router/revalidation.ts +203 -62
- package/src/router/route-snapshot.ts +246 -0
- package/src/router/router-context.ts +45 -48
- package/src/router/router-interfaces.ts +554 -0
- package/src/router/router-options.ts +779 -0
- package/src/router/router-registry.ts +21 -0
- package/src/router/segment-resolution/fresh.ts +772 -0
- package/src/router/segment-resolution/helpers.ts +348 -0
- package/src/router/segment-resolution/loader-cache.ts +250 -0
- package/src/router/segment-resolution/loader-mask.ts +44 -0
- package/src/router/segment-resolution/revalidation.ts +1331 -0
- package/src/router/segment-resolution/static-store.ts +81 -0
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +56 -0
- package/src/router/segment-resolution.ts +25 -1354
- package/src/router/segment-wrappers.ts +292 -0
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +75 -0
- package/src/router/telemetry-otel.ts +261 -0
- package/src/router/telemetry.ts +377 -0
- package/src/router/timeout.ts +128 -0
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +240 -61
- package/src/router/types.ts +23 -70
- package/src/router/url-params.ts +57 -0
- package/src/router.ts +781 -2378
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +46 -0
- package/src/rsc/handler.ts +905 -1142
- package/src/rsc/helpers.ts +275 -19
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +305 -0
- package/src/rsc/manifest-init.ts +77 -0
- package/src/rsc/nonce.ts +14 -0
- package/src/rsc/origin-guard.ts +155 -0
- package/src/rsc/progressive-enhancement.ts +502 -0
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +104 -0
- package/src/rsc/response-route-handler.ts +257 -0
- package/src/rsc/rsc-rendering.ts +337 -0
- package/src/rsc/runtime-warnings.ts +55 -0
- package/src/rsc/server-action.ts +522 -0
- package/src/rsc/shell-capture.ts +439 -0
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +95 -12
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +99 -82
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +349 -134
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +452 -85
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +310 -0
- package/src/server/fetchable-loader-store.ts +11 -6
- package/src/server/handle-store.ts +123 -42
- package/src/server/live.ts +130 -0
- package/src/server/loader-registry.ts +51 -100
- package/src/server/request-context.ts +842 -157
- package/src/server.ts +15 -8
- package/src/ssr/index.tsx +412 -136
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +45 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +46 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +199 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +584 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +40 -72
- package/src/theme/ThemeScript.tsx +12 -14
- package/src/theme/constants.ts +57 -15
- package/src/theme/index.ts +3 -20
- package/src/theme/theme-context.ts +5 -35
- package/src/theme/theme-script.ts +43 -39
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +123 -0
- package/src/types/cache-types.ts +207 -0
- package/src/types/error-types.ts +132 -0
- package/src/types/global-namespace.ts +113 -0
- package/src/types/handler-context.ts +839 -0
- package/src/types/index.ts +81 -0
- package/src/types/loader-types.ts +212 -0
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +138 -0
- package/src/types/route-entry.ts +114 -0
- package/src/types/segments.ts +271 -0
- package/src/types.ts +1 -1795
- package/src/urls/include-helper.ts +162 -0
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +43 -0
- package/src/urls/path-helper-types.ts +413 -0
- package/src/urls/path-helper.ts +275 -0
- package/src/urls/pattern-types.ts +124 -0
- package/src/urls/response-types.ts +109 -0
- package/src/urls/type-extraction.ts +316 -0
- package/src/urls/urls-function.ts +80 -0
- package/src/urls.ts +1 -1341
- package/src/use-loader.tsx +406 -141
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +182 -0
- package/src/vite/discovery/discover-routers.ts +389 -0
- package/src/vite/discovery/discovery-errors.ts +255 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +467 -0
- package/src/vite/discovery/route-types-writer.ts +214 -0
- package/src/vite/discovery/self-gen-tracking.ts +73 -0
- package/src/vite/discovery/state.ts +161 -0
- package/src/vite/discovery/virtual-module-codegen.ts +183 -0
- package/src/vite/index.ts +23 -2255
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +303 -0
- package/src/vite/plugins/cjs-to-esm.ts +90 -0
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- package/src/vite/plugins/client-ref-hashing.ts +118 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/{expose-action-id.ts → plugins/expose-action-id.ts} +88 -110
- package/src/vite/{expose-id-utils.ts → plugins/expose-id-utils.ts} +89 -79
- package/src/vite/plugins/expose-ids/export-analysis.ts +363 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +130 -0
- package/src/vite/plugins/expose-ids/loader-transform.ts +64 -0
- package/src/vite/plugins/expose-ids/router-transform.ts +199 -0
- package/src/vite/plugins/expose-ids/types.ts +45 -0
- package/src/vite/plugins/expose-internal-ids.ts +805 -0
- package/src/vite/plugins/performance-tracks.ts +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +313 -0
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +94 -0
- package/src/vite/plugins/version-plugin.ts +263 -0
- package/src/vite/plugins/virtual-entries.ts +234 -0
- package/src/vite/plugins/virtual-stub-plugin.ts +29 -0
- package/src/vite/rango.ts +560 -0
- package/src/vite/router-discovery.ts +1638 -0
- package/src/vite/{ast-handler-extract.ts → utils/ast-handler-extract.ts} +200 -37
- package/src/vite/utils/banner.ts +36 -0
- package/src/vite/utils/bundle-analysis.ts +132 -0
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +15 -0
- package/src/vite/utils/package-resolution.ts +89 -0
- package/src/vite/utils/prerender-utils.ts +249 -0
- package/src/vite/utils/shared-utils.ts +269 -0
- package/CLAUDE.md +0 -43
- package/dist/vite/index.named-routes.gen.ts +0 -103
- package/src/browser/lru-cache.ts +0 -69
- package/src/browser/react/use-client-cache.ts +0 -56
- package/src/browser/request-controller.ts +0 -164
- package/src/browser/shallow.ts +0 -35
- package/src/cache/memory-store.ts +0 -253
- package/src/handles/index.ts +0 -6
- package/src/href-context.ts +0 -33
- package/src/network-error-thrower.tsx +0 -21
- package/src/router.gen.ts +0 -6
- package/src/static-handler.gen.ts +0 -5
- package/src/urls.gen.ts +0 -8
- package/src/vite/expose-internal-ids.ts +0 -1167
- package/src/vite/package-resolution.ts +0 -125
- package/src/vite/virtual-entries.ts +0 -114
- /package/src/vite/{version.d.ts → plugins/version.d.ts} +0 -0
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useContext, useState, useEffect, useRef } from "react";
|
|
4
4
|
import { NavigationStoreContext } from "./context.js";
|
|
5
|
+
import { shallowEqual } from "./shallow-equal.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Segments state returned by useSegments hook
|
|
@@ -15,65 +16,6 @@ export interface SegmentsState {
|
|
|
15
16
|
location: URL;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
/**
|
|
19
|
-
* SSR module-level state.
|
|
20
|
-
* Populated by initSegmentsSync before React renders.
|
|
21
|
-
* Used by useState initializer during SSR.
|
|
22
|
-
*/
|
|
23
|
-
let ssrSegmentOrder: string[] = [];
|
|
24
|
-
let ssrPathname: string = "/";
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Filter segment IDs to only include routes and layouts.
|
|
28
|
-
* Excludes parallels (contain .@) and loaders (contain D followed by digit).
|
|
29
|
-
*/
|
|
30
|
-
function filterSegmentOrder(matched: string[]): string[] {
|
|
31
|
-
return matched.filter((id) => {
|
|
32
|
-
if (id.includes(".@")) return false;
|
|
33
|
-
if (/D\d+\./.test(id)) return false;
|
|
34
|
-
return true;
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Initialize segments data synchronously for SSR.
|
|
40
|
-
* Called before rendering to populate state for useState initializer.
|
|
41
|
-
*
|
|
42
|
-
* @param matched - Segment order from RSC metadata
|
|
43
|
-
* @param pathname - Current pathname
|
|
44
|
-
*/
|
|
45
|
-
export function initSegmentsSync(matched?: string[], pathname?: string): void {
|
|
46
|
-
ssrSegmentOrder = filterSegmentOrder(matched ?? []);
|
|
47
|
-
ssrPathname = pathname ?? "/";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Shallow equality check for selector results
|
|
52
|
-
*/
|
|
53
|
-
function shallowEqual<T>(a: T, b: T): boolean {
|
|
54
|
-
if (Object.is(a, b)) return true;
|
|
55
|
-
if (
|
|
56
|
-
typeof a !== "object" ||
|
|
57
|
-
a === null ||
|
|
58
|
-
typeof b !== "object" ||
|
|
59
|
-
b === null
|
|
60
|
-
) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
const keysA = Object.keys(a);
|
|
64
|
-
const keysB = Object.keys(b);
|
|
65
|
-
if (keysA.length !== keysB.length) return false;
|
|
66
|
-
for (const key of keysA) {
|
|
67
|
-
if (
|
|
68
|
-
!Object.hasOwn(b, key) ||
|
|
69
|
-
!Object.is((a as any)[key], (b as any)[key])
|
|
70
|
-
) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
19
|
/**
|
|
78
20
|
* Parse pathname into path segments
|
|
79
21
|
* /shop/products/123 → ["shop", "products", "123"]
|
|
@@ -83,27 +25,18 @@ function parsePathname(pathname: string): string[] {
|
|
|
83
25
|
}
|
|
84
26
|
|
|
85
27
|
/**
|
|
86
|
-
* Build segments state from event controller
|
|
28
|
+
* Build segments state from event controller. `segmentIds` is the
|
|
29
|
+
* route-only list (parallels and loaders stripped) — distinct from the
|
|
30
|
+
* controller's `segmentOrder` which drives handle collection and includes
|
|
31
|
+
* parallel slot ids.
|
|
87
32
|
*/
|
|
88
33
|
function buildSegmentsState(
|
|
89
34
|
location: URL,
|
|
90
|
-
|
|
35
|
+
routeSegmentIds: string[],
|
|
91
36
|
): SegmentsState {
|
|
92
37
|
return {
|
|
93
38
|
path: parsePathname(location.pathname),
|
|
94
|
-
segmentIds:
|
|
95
|
-
location,
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Build SSR state from module-level variables
|
|
101
|
-
*/
|
|
102
|
-
function buildSsrState(): SegmentsState {
|
|
103
|
-
const location = new URL(ssrPathname, "http://localhost");
|
|
104
|
-
return {
|
|
105
|
-
path: parsePathname(ssrPathname),
|
|
106
|
-
segmentIds: ssrSegmentOrder,
|
|
39
|
+
segmentIds: routeSegmentIds,
|
|
107
40
|
location,
|
|
108
41
|
};
|
|
109
42
|
}
|
|
@@ -127,62 +60,102 @@ function buildSsrState(): SegmentsState {
|
|
|
127
60
|
export function useSegments(): SegmentsState;
|
|
128
61
|
export function useSegments<T>(selector: (state: SegmentsState) => T): T;
|
|
129
62
|
export function useSegments<T>(
|
|
130
|
-
selector?: (state: SegmentsState) => T
|
|
63
|
+
selector?: (state: SegmentsState) => T,
|
|
131
64
|
): T | SegmentsState {
|
|
132
65
|
const ctx = useContext(NavigationStoreContext);
|
|
133
66
|
|
|
134
|
-
// Build initial state from
|
|
67
|
+
// Build initial state from event controller when context exists.
|
|
68
|
+
// Inlined rather than calling recompute() because the segmentsCache ref
|
|
69
|
+
// is not yet initialized during the useState initializer.
|
|
135
70
|
const [state, setState] = useState<T | SegmentsState>(() => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
return selector ? selector(
|
|
71
|
+
if (!ctx) {
|
|
72
|
+
const fallbackLocation = new URL("/", "http://localhost");
|
|
73
|
+
const fallbackState = buildSegmentsState(fallbackLocation, []);
|
|
74
|
+
return selector ? selector(fallbackState) : fallbackState;
|
|
140
75
|
}
|
|
141
|
-
|
|
142
|
-
const navState = ctx.eventController.getState();
|
|
76
|
+
const location = ctx.eventController.getLocation();
|
|
143
77
|
const handleState = ctx.eventController.getHandleState();
|
|
144
78
|
const segmentsState = buildSegmentsState(
|
|
145
|
-
|
|
146
|
-
handleState.
|
|
79
|
+
location as URL,
|
|
80
|
+
handleState.routeSegmentIds,
|
|
147
81
|
);
|
|
148
82
|
return selector ? selector(segmentsState) : segmentsState;
|
|
149
83
|
});
|
|
150
84
|
|
|
151
85
|
const prevState = useRef(state);
|
|
86
|
+
const selectorRef = useRef(selector);
|
|
87
|
+
selectorRef.current = selector;
|
|
88
|
+
|
|
89
|
+
const prevSelectorIdentity = useRef(selector);
|
|
90
|
+
|
|
91
|
+
const segmentsCache = useRef<{
|
|
92
|
+
location: URL;
|
|
93
|
+
routeSegmentIds: string[];
|
|
94
|
+
state: SegmentsState;
|
|
95
|
+
} | null>(null);
|
|
96
|
+
|
|
97
|
+
function recompute(
|
|
98
|
+
sel: ((state: SegmentsState) => T) | undefined,
|
|
99
|
+
): T | SegmentsState {
|
|
100
|
+
const location = ctx!.eventController.getLocation();
|
|
101
|
+
const handleState = ctx!.eventController.getHandleState();
|
|
102
|
+
|
|
103
|
+
const cache = segmentsCache.current;
|
|
104
|
+
let segmentsState: SegmentsState;
|
|
105
|
+
if (
|
|
106
|
+
cache &&
|
|
107
|
+
cache.location === location &&
|
|
108
|
+
cache.routeSegmentIds === handleState.routeSegmentIds
|
|
109
|
+
) {
|
|
110
|
+
segmentsState = cache.state;
|
|
111
|
+
} else {
|
|
112
|
+
segmentsState = buildSegmentsState(
|
|
113
|
+
location as URL,
|
|
114
|
+
handleState.routeSegmentIds,
|
|
115
|
+
);
|
|
116
|
+
segmentsCache.current = {
|
|
117
|
+
location: location as URL,
|
|
118
|
+
routeSegmentIds: handleState.routeSegmentIds,
|
|
119
|
+
state: segmentsState,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return sel ? sel(segmentsState) : segmentsState;
|
|
123
|
+
}
|
|
152
124
|
|
|
153
|
-
|
|
125
|
+
if (ctx && selector !== prevSelectorIdentity.current) {
|
|
126
|
+
prevSelectorIdentity.current = selector;
|
|
127
|
+
const nextSelected = recompute(selector);
|
|
128
|
+
if (!shallowEqual(nextSelected, prevState.current)) {
|
|
129
|
+
prevState.current = nextSelected;
|
|
130
|
+
setState(nextSelected);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Subscribe to store changes. The eager block above handles selector
|
|
135
|
+
// changes and SSR drift, so no initial updateState() call is needed.
|
|
154
136
|
useEffect(() => {
|
|
155
137
|
if (!ctx) {
|
|
156
138
|
return;
|
|
157
139
|
}
|
|
158
140
|
|
|
159
141
|
const updateState = () => {
|
|
160
|
-
const
|
|
161
|
-
const handleState = ctx.eventController.getHandleState();
|
|
162
|
-
const segmentsState = buildSegmentsState(
|
|
163
|
-
navState.location as URL,
|
|
164
|
-
handleState.segmentOrder
|
|
165
|
-
);
|
|
166
|
-
const nextSelected = selector ? selector(segmentsState) : segmentsState;
|
|
167
|
-
|
|
142
|
+
const nextSelected = recompute(selectorRef.current);
|
|
168
143
|
if (!shallowEqual(nextSelected, prevState.current)) {
|
|
169
144
|
prevState.current = nextSelected;
|
|
170
145
|
setState(nextSelected);
|
|
171
146
|
}
|
|
172
147
|
};
|
|
173
148
|
|
|
174
|
-
// Initial update in case SSR state differs from client state
|
|
175
|
-
updateState();
|
|
176
|
-
|
|
177
|
-
// Subscribe to both state sources
|
|
178
149
|
const unsubscribeNav = ctx.eventController.subscribe(updateState);
|
|
179
|
-
const unsubscribeHandles =
|
|
150
|
+
const unsubscribeHandles =
|
|
151
|
+
ctx.eventController.subscribeToHandles(updateState);
|
|
180
152
|
|
|
181
153
|
return () => {
|
|
182
154
|
unsubscribeNav();
|
|
183
155
|
unsubscribeHandles();
|
|
184
156
|
};
|
|
185
|
-
|
|
157
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
158
|
+
}, []);
|
|
186
159
|
|
|
187
160
|
return state as T | SegmentsState;
|
|
188
161
|
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { validateRedirectOrigin } from "./validate-redirect-origin.js";
|
|
2
|
+
|
|
3
|
+
type HeaderResult = { url: string } | "blocked" | null;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Null-body statuses: the Fetch spec forbids pairing these with a body, so
|
|
7
|
+
* `new Response(body, { status })` throws ("Response with null body status
|
|
8
|
+
* cannot have body"). fetch() can still surface one WITH a body straight from
|
|
9
|
+
* the network layer (never the JS constructor): a 304 stale-while-revalidate
|
|
10
|
+
* prefetch revalidated to Not Modified (body from cache), or a 204 soft
|
|
11
|
+
* redirect. teeWithCompletion must not re-run those through `new Response`.
|
|
12
|
+
*/
|
|
13
|
+
const NULL_BODY_STATUS = new Set([101, 204, 205, 304]);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Extract and validate an RSC response header URL (X-RSC-Reload, X-RSC-Redirect).
|
|
17
|
+
* Returns { url } if valid, "blocked" if present but invalid origin, null if absent.
|
|
18
|
+
*/
|
|
19
|
+
export function extractRscHeaderUrl(
|
|
20
|
+
response: Response,
|
|
21
|
+
header: string,
|
|
22
|
+
): HeaderResult {
|
|
23
|
+
const raw = response.headers.get(header);
|
|
24
|
+
if (!raw) return null;
|
|
25
|
+
const url = validateRedirectOrigin(raw, window.location.origin);
|
|
26
|
+
return url ? { url } : "blocked";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Empty 200 response that won't choke Flight parsing.
|
|
31
|
+
* Used when a header URL is blocked by origin validation.
|
|
32
|
+
*/
|
|
33
|
+
export function emptyResponse(): Response {
|
|
34
|
+
return new Response(null, { status: 200 });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Whether an RSC content response carries a server-stamped router identity
|
|
39
|
+
* (`X-RSC-Router-Id`) that DIFFERS from the id this client expects (its own
|
|
40
|
+
* routerId, also sent as `_rsc_rid`). Pre-decode integrity check: lets a caller
|
|
41
|
+
* refuse a foreign app's payload before `createFromFetch` imports its chunks.
|
|
42
|
+
*
|
|
43
|
+
* True ONLY when both the header and the expected id are present and differ. An
|
|
44
|
+
* absent header (control-only reload/redirect responses are not stamped) or an
|
|
45
|
+
* absent expected id (e.g. before the client is seeded) is a pass-through —
|
|
46
|
+
* never a false reject.
|
|
47
|
+
*/
|
|
48
|
+
export function isForeignRouterId(
|
|
49
|
+
response: Response,
|
|
50
|
+
expectedId: string | undefined,
|
|
51
|
+
): boolean {
|
|
52
|
+
const got = response.headers.get("X-RSC-Router-Id");
|
|
53
|
+
if (!got || !expectedId) return false;
|
|
54
|
+
return got !== expectedId;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Handle the X-RSC-Reload control header (server requests a full page reload on
|
|
59
|
+
* a version mismatch). Returns a short-circuit response when the header is
|
|
60
|
+
* present -- emptyResponse() if the URL was blocked by origin validation, or a
|
|
61
|
+
* never-resolving promise while the page reloads -- and null when absent, so
|
|
62
|
+
* the caller continues processing (e.g. the X-RSC-Redirect check). Scoped to
|
|
63
|
+
* X-RSC-Reload only; redirect handling differs between callers.
|
|
64
|
+
*/
|
|
65
|
+
export function handleReloadHeader(
|
|
66
|
+
response: Response,
|
|
67
|
+
opts: { onBlocked: () => void; onReload: (url: string) => void },
|
|
68
|
+
): Response | Promise<Response> | null {
|
|
69
|
+
const reload = extractRscHeaderUrl(response, "X-RSC-Reload");
|
|
70
|
+
if (reload === "blocked") {
|
|
71
|
+
opts.onBlocked();
|
|
72
|
+
return emptyResponse();
|
|
73
|
+
}
|
|
74
|
+
if (reload) {
|
|
75
|
+
opts.onReload(reload.url);
|
|
76
|
+
window.location.href = reload.url;
|
|
77
|
+
return new Promise<Response>(() => {});
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Tee a response body for RSC parsing and stream completion tracking.
|
|
84
|
+
* Returns a new Response with one branch; the other is consumed to detect
|
|
85
|
+
* end-of-stream, calling onComplete when done.
|
|
86
|
+
*
|
|
87
|
+
* `onComplete` receives `endedCleanly`: true only on a normal EOF drain, false
|
|
88
|
+
* on a read error or an abort (the signal cancelled the reader). Callers that
|
|
89
|
+
* gate a "fully complete" fast path (e.g. prefetch's `entry.complete`) must
|
|
90
|
+
* treat a non-clean end as incomplete — a broken stream is not complete data.
|
|
91
|
+
*
|
|
92
|
+
* If the response has no body, onComplete fires synchronously with `true`
|
|
93
|
+
* (an empty body is a clean, complete stream).
|
|
94
|
+
* If signal is provided, an abort cancels the tracking reader.
|
|
95
|
+
*
|
|
96
|
+
* `silent` suppresses the stream-error log. Prefetch passes it: a speculative,
|
|
97
|
+
* low-priority prefetch that is aborted or never consumed can error its stream
|
|
98
|
+
* benignly, which is not worth surfacing. The fresh-navigation path keeps the
|
|
99
|
+
* log (default), where a stream error reflects a real failed navigation.
|
|
100
|
+
*/
|
|
101
|
+
export function teeWithCompletion(
|
|
102
|
+
response: Response,
|
|
103
|
+
onComplete: (endedCleanly: boolean) => void,
|
|
104
|
+
signal?: AbortSignal,
|
|
105
|
+
silent = false,
|
|
106
|
+
): Response {
|
|
107
|
+
// Once-guard: a mid-stream read error runs both the finally block and the
|
|
108
|
+
// rejection's .catch, so onComplete must be settled exactly once across all
|
|
109
|
+
// paths (no-body early return, finally, catch).
|
|
110
|
+
let settled = false;
|
|
111
|
+
const settle = (endedCleanly: boolean) => {
|
|
112
|
+
if (!settled) {
|
|
113
|
+
settled = true;
|
|
114
|
+
onComplete(endedCleanly);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Empty body, or a null-body status fetch() paired with a body: either way the
|
|
119
|
+
// body can't be re-attached via `new Response` below. Settle and pass the
|
|
120
|
+
// original response through; its body (when present) stays readable downstream.
|
|
121
|
+
if (!response.body || NULL_BODY_STATUS.has(response.status)) {
|
|
122
|
+
settle(true);
|
|
123
|
+
return response;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const [rscStream, trackingStream] = response.body.tee();
|
|
127
|
+
|
|
128
|
+
(async () => {
|
|
129
|
+
const reader = trackingStream.getReader();
|
|
130
|
+
const onAbort = signal ? reader.cancel.bind(reader) : undefined;
|
|
131
|
+
if (onAbort) signal!.addEventListener("abort", onAbort, { once: true });
|
|
132
|
+
// Only a loop that reaches `done` is a clean EOF. A read error rejects out
|
|
133
|
+
// of the try and still runs the finally, so the finally must NOT assume
|
|
134
|
+
// clean — it gates on this flag (false on error) AND on signal.aborted
|
|
135
|
+
// (an abort cancels the reader so read() resolves { done: true } and the
|
|
136
|
+
// loop breaks here normally, NOT in the .catch — re-check the signal to
|
|
137
|
+
// catch that case).
|
|
138
|
+
let cleanEof = false;
|
|
139
|
+
try {
|
|
140
|
+
while (true) {
|
|
141
|
+
const { done } = await reader.read();
|
|
142
|
+
if (done) {
|
|
143
|
+
cleanEof = true;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
} finally {
|
|
148
|
+
if (onAbort) signal!.removeEventListener("abort", onAbort);
|
|
149
|
+
reader.releaseLock();
|
|
150
|
+
settle(cleanEof && !signal?.aborted);
|
|
151
|
+
}
|
|
152
|
+
})().catch((error) => {
|
|
153
|
+
if (!silent && !signal?.aborted) {
|
|
154
|
+
console.error("[Browser] Error reading tracking stream:", error);
|
|
155
|
+
}
|
|
156
|
+
settle(false);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
return new Response(rscStream, {
|
|
160
|
+
headers: response.headers,
|
|
161
|
+
status: response.status,
|
|
162
|
+
statusText: response.statusText,
|
|
163
|
+
});
|
|
164
|
+
}
|