@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
|
@@ -1,67 +1,93 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import React, {
|
|
3
|
+
import React, {
|
|
4
|
+
forwardRef,
|
|
5
|
+
useCallback,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useRef,
|
|
10
|
+
type ForwardRefExoticComponent,
|
|
11
|
+
type RefAttributes,
|
|
12
|
+
} from "react";
|
|
4
13
|
import { NavigationStoreContext } from "./context.js";
|
|
5
14
|
import { LinkContext } from "./use-link-status.js";
|
|
6
15
|
import type { NavigateOptions } from "../types.js";
|
|
16
|
+
import { isHashOnlyNavigation } from "../link-interceptor.js";
|
|
7
17
|
import {
|
|
8
|
-
type LocationStateEntry,
|
|
9
18
|
isLocationStateEntry,
|
|
19
|
+
type LocationStateEntry,
|
|
10
20
|
resolveLocationStateEntries,
|
|
11
21
|
} from "./location-state.js";
|
|
12
22
|
|
|
13
23
|
/**
|
|
14
|
-
* State
|
|
24
|
+
* State prop type for Link component.
|
|
25
|
+
* - LocationStateEntry[]: Type-safe state entries via createLocationState()
|
|
26
|
+
* - StateOrGetter: Plain state object or click-time getter function
|
|
27
|
+
* - Record<string, unknown>: Plain state object passed to history.pushState
|
|
15
28
|
*/
|
|
16
29
|
export type StateOrGetter<T = unknown> = T | (() => T);
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* - StateOrGetter: Legacy format for backwards compatibility
|
|
22
|
-
*/
|
|
23
|
-
export type LinkState = LocationStateEntry[] | StateOrGetter;
|
|
31
|
+
export type LinkState =
|
|
32
|
+
| LocationStateEntry[]
|
|
33
|
+
| StateOrGetter<Record<string, unknown>>;
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
import { prefetchDirect, prefetchQueued } from "../prefetch/fetch.js";
|
|
36
|
+
import { getAppVersion } from "../app-version.js";
|
|
37
|
+
import {
|
|
38
|
+
observeForPrefetch,
|
|
39
|
+
unobserveForPrefetch,
|
|
40
|
+
} from "../prefetch/observer.js";
|
|
27
41
|
|
|
28
42
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
43
|
+
* Read current touch/no-hover capability. Evaluated at the point of use (per
|
|
44
|
+
* render) rather than once at module load, so `prefetch="adaptive"` reacts to
|
|
45
|
+
* input-capability changes on hybrid devices (touch laptops, tablets gaining or
|
|
46
|
+
* losing a pointer) and after SSR -> hydrate. The SSR guard returns a stable
|
|
47
|
+
* `false` (pointer/hover default) so the resolved strategy doesn't drift on the
|
|
48
|
+
* server vs the first client render.
|
|
31
49
|
*/
|
|
32
|
-
function
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// Build RSC partial URL with segment IDs
|
|
37
|
-
const targetUrl = new URL(url, window.location.origin);
|
|
38
|
-
targetUrl.searchParams.set("_rsc_partial", "true");
|
|
39
|
-
if (segmentIds.length > 0) {
|
|
40
|
-
targetUrl.searchParams.set("_rsc_segments", segmentIds.join(","));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Inject <link rel="prefetch"> into head
|
|
44
|
-
const link = document.createElement("link");
|
|
45
|
-
link.rel = "prefetch";
|
|
46
|
-
link.href = targetUrl.toString();
|
|
47
|
-
link.as = "fetch";
|
|
48
|
-
document.head.appendChild(link);
|
|
50
|
+
function isTouchDevice(): boolean {
|
|
51
|
+
if (typeof window === "undefined") return false;
|
|
52
|
+
return window.matchMedia("(hover: none)").matches;
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
/**
|
|
52
56
|
* Prefetch strategy for the Link component
|
|
53
|
-
* - "hover": Prefetch on mouse enter (
|
|
54
|
-
* - "viewport": Prefetch when link enters viewport (
|
|
55
|
-
* - "
|
|
57
|
+
* - "hover": Prefetch on mouse enter (direct, no queue)
|
|
58
|
+
* - "viewport": Prefetch when link enters viewport (queued, waits for idle)
|
|
59
|
+
* - "render": Prefetch on component mount regardless of visibility (queued, waits for idle)
|
|
60
|
+
* - "adaptive": Hover on pointer devices, viewport on touch devices
|
|
56
61
|
* - "none": No prefetching (default)
|
|
57
62
|
*/
|
|
58
|
-
export type PrefetchStrategy =
|
|
63
|
+
export type PrefetchStrategy =
|
|
64
|
+
| "hover"
|
|
65
|
+
| "viewport"
|
|
66
|
+
| "render"
|
|
67
|
+
| "adaptive"
|
|
68
|
+
| "none";
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve a prefetch strategy, expanding "adaptive" to the concrete strategy
|
|
72
|
+
* for the CURRENT input capability: "viewport" on touch (no-hover) devices,
|
|
73
|
+
* "hover" on pointer devices. Non-adaptive strategies pass through unchanged.
|
|
74
|
+
* Reads touch capability live (not a module-load snapshot) so the result
|
|
75
|
+
* tracks input-capability changes.
|
|
76
|
+
*/
|
|
77
|
+
export function resolveAdaptiveStrategy(
|
|
78
|
+
prefetch: PrefetchStrategy,
|
|
79
|
+
): PrefetchStrategy {
|
|
80
|
+
if (prefetch !== "adaptive") return prefetch;
|
|
81
|
+
return isTouchDevice() ? "viewport" : "hover";
|
|
82
|
+
}
|
|
59
83
|
|
|
60
84
|
/**
|
|
61
85
|
* Link component props
|
|
62
86
|
*/
|
|
63
|
-
export interface LinkProps
|
|
64
|
-
|
|
87
|
+
export interface LinkProps extends Omit<
|
|
88
|
+
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
89
|
+
"href"
|
|
90
|
+
> {
|
|
65
91
|
/**
|
|
66
92
|
* The URL to navigate to (typically from router.reverse())
|
|
67
93
|
*/
|
|
@@ -78,11 +104,46 @@ export interface LinkProps
|
|
|
78
104
|
* Force full document navigation instead of SPA
|
|
79
105
|
*/
|
|
80
106
|
reloadDocument?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Whether to revalidate server data on navigation.
|
|
109
|
+
* Set to `false` to skip the RSC server fetch and only update the URL.
|
|
110
|
+
*
|
|
111
|
+
* Only takes effect when the pathname stays the same (search param / hash changes).
|
|
112
|
+
* If the pathname changes, this option is ignored and a full navigation occurs.
|
|
113
|
+
*
|
|
114
|
+
* @default true
|
|
115
|
+
*/
|
|
116
|
+
revalidate?: boolean;
|
|
81
117
|
/**
|
|
82
118
|
* Prefetch strategy for the link destination
|
|
83
119
|
* @default "none"
|
|
84
120
|
*/
|
|
85
121
|
prefetch?: PrefetchStrategy;
|
|
122
|
+
/**
|
|
123
|
+
* Opt-in override for the prefetch cache scope.
|
|
124
|
+
*
|
|
125
|
+
* The default cache is source-agnostic: one shared entry per target,
|
|
126
|
+
* keyed on Rango state + target URL. This is correct for routes whose
|
|
127
|
+
* response shape doesn't depend on where the user navigates from.
|
|
128
|
+
*
|
|
129
|
+
* Set `":source"` when this Link's response would legitimately differ
|
|
130
|
+
* based on the source page — typically when the target route (or one
|
|
131
|
+
* of its layouts) uses a custom `revalidate()` handler that reads
|
|
132
|
+
* `currentUrl` / `currentParams`, and the wildcard entry would
|
|
133
|
+
* therefore serve the wrong diff to a navigation from a different
|
|
134
|
+
* source.
|
|
135
|
+
*
|
|
136
|
+
* Intercept responses are auto-scoped to the source via a server-side
|
|
137
|
+
* tag, so `":source"` is only needed for custom revalidation logic.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```tsx
|
|
141
|
+
* // Route uses a `revalidate()` that branches on currentUrl — opt in
|
|
142
|
+
* // so prefetches don't bleed across source pages.
|
|
143
|
+
* <Link to="/dashboard" prefetch="hover" prefetchKey=":source" />
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
prefetchKey?: ":source";
|
|
86
147
|
/**
|
|
87
148
|
* State to pass to history.pushState/replaceState.
|
|
88
149
|
* Accessible via useLocationState() hook.
|
|
@@ -90,16 +151,29 @@ export interface LinkProps
|
|
|
90
151
|
* @example
|
|
91
152
|
* ```tsx
|
|
92
153
|
* // Type-safe state with createLocationState (recommended)
|
|
93
|
-
* const ProductState = createLocationState
|
|
94
|
-
* <Link to="/product" state={[ProductState(product)]}>
|
|
154
|
+
* const ProductState = createLocationState<{ name: string; price: number }>();
|
|
155
|
+
* <Link to="/product" state={[ProductState({ name: product.name, price: product.price })]}>
|
|
156
|
+
* View
|
|
157
|
+
* </Link>
|
|
158
|
+
*
|
|
159
|
+
* // Type-safe just-in-time state (getter called at click time, not render time).
|
|
160
|
+
* // Must be in a client component -- getter can't cross the RSC boundary.
|
|
161
|
+
* <Link
|
|
162
|
+
* to="/product"
|
|
163
|
+
* state={[ProductState(() => ({ name: product.name, price: product.price }))]}
|
|
164
|
+
* >
|
|
165
|
+
* View
|
|
166
|
+
* </Link>
|
|
95
167
|
*
|
|
96
168
|
* // Multiple typed states
|
|
97
|
-
* <Link to="/checkout" state={[ProductState(p), CartState(c)]}>
|
|
169
|
+
* <Link to="/checkout" state={[ProductState({ name: p.name, price: p.price }), CartState(c)]}>
|
|
170
|
+
* Checkout
|
|
171
|
+
* </Link>
|
|
98
172
|
*
|
|
99
|
-
* //
|
|
173
|
+
* // Plain static state
|
|
100
174
|
* <Link to="/product" state={{ from: "list" }}>View</Link>
|
|
101
175
|
*
|
|
102
|
-
* //
|
|
176
|
+
* // Plain just-in-time state (called at click time, requires client component)
|
|
103
177
|
* <Link to="/product" state={() => ({ scrollY: window.scrollY })}>View</Link>
|
|
104
178
|
* ```
|
|
105
179
|
*/
|
|
@@ -147,23 +221,57 @@ function isExternalUrl(href: string): boolean {
|
|
|
147
221
|
* <Link to="https://example.com">External</Link>
|
|
148
222
|
* ```
|
|
149
223
|
*/
|
|
150
|
-
export const Link: ForwardRefExoticComponent<
|
|
224
|
+
export const Link: ForwardRefExoticComponent<
|
|
225
|
+
LinkProps & RefAttributes<HTMLAnchorElement>
|
|
226
|
+
> = forwardRef<HTMLAnchorElement, LinkProps>(function Link(
|
|
151
227
|
{
|
|
152
228
|
to,
|
|
153
229
|
replace = false,
|
|
154
230
|
scroll = true,
|
|
155
231
|
reloadDocument = false,
|
|
232
|
+
revalidate,
|
|
156
233
|
prefetch = "none",
|
|
234
|
+
prefetchKey,
|
|
157
235
|
state,
|
|
158
236
|
children,
|
|
159
237
|
onClick,
|
|
160
238
|
...props
|
|
161
239
|
},
|
|
162
|
-
ref
|
|
240
|
+
ref,
|
|
163
241
|
) {
|
|
164
242
|
const ctx = useContext(NavigationStoreContext);
|
|
165
243
|
const isExternal = isExternalUrl(to);
|
|
166
244
|
|
|
245
|
+
// Auto-prefix with basename for app-local paths.
|
|
246
|
+
// Skip if external, already prefixed, or not a root-relative path.
|
|
247
|
+
const resolvedTo = useMemo(() => {
|
|
248
|
+
if (isExternal) return to;
|
|
249
|
+
const bn = ctx?.basename;
|
|
250
|
+
if (!bn || !to.startsWith("/") || to.startsWith(bn + "/") || to === bn)
|
|
251
|
+
return to;
|
|
252
|
+
return to === "/" ? bn : bn + to;
|
|
253
|
+
}, [to, isExternal, ctx?.basename]);
|
|
254
|
+
|
|
255
|
+
// Resolve adaptive: viewport on touch devices, hover on pointer devices.
|
|
256
|
+
// isTouchDevice() is read here (per render), not from a module-load snapshot,
|
|
257
|
+
// so a device whose input capability changes resolves to the current value.
|
|
258
|
+
const resolvedStrategy = resolveAdaptiveStrategy(prefetch);
|
|
259
|
+
|
|
260
|
+
// Internal ref for viewport observation; merge with forwarded ref
|
|
261
|
+
const internalRef = useRef<HTMLAnchorElement | null>(null);
|
|
262
|
+
const setRef = useCallback(
|
|
263
|
+
(node: HTMLAnchorElement | null) => {
|
|
264
|
+
internalRef.current = node;
|
|
265
|
+
if (typeof ref === "function") {
|
|
266
|
+
ref(node);
|
|
267
|
+
} else if (ref) {
|
|
268
|
+
(ref as React.MutableRefObject<HTMLAnchorElement | null>).current =
|
|
269
|
+
node;
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
[ref],
|
|
273
|
+
);
|
|
274
|
+
|
|
167
275
|
// Use ref to always get the latest state/getter without adding to useCallback deps
|
|
168
276
|
// This enables just-in-time state resolution without causing re-renders
|
|
169
277
|
const stateRef = useRef(state);
|
|
@@ -194,55 +302,154 @@ export const Link: ForwardRefExoticComponent<LinkProps & RefAttributes<HTMLAncho
|
|
|
194
302
|
const target = (e.currentTarget as HTMLAnchorElement).target;
|
|
195
303
|
if (target && target !== "_self") return;
|
|
196
304
|
|
|
305
|
+
// Hash-only navigation: let the browser handle anchor scrolling natively.
|
|
306
|
+
if (isHashOnlyNavigation(e.currentTarget as HTMLAnchorElement)) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// No navigation context (outside provider): fall back to native navigation.
|
|
311
|
+
if (!ctx?.navigate) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
197
315
|
// Prevent default and use SPA navigation
|
|
198
316
|
e.preventDefault();
|
|
199
317
|
// Stop propagation to prevent link-interceptor from also handling this
|
|
200
318
|
e.stopPropagation();
|
|
201
319
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
let resolvedState: unknown;
|
|
205
|
-
const currentState = stateRef.current;
|
|
206
|
-
|
|
207
|
-
if (Array.isArray(currentState) && currentState.length > 0 && isLocationStateEntry(currentState[0])) {
|
|
208
|
-
// Type-safe LocationStateEntry[] - resolve each entry into keyed object
|
|
209
|
-
resolvedState = resolveLocationStateEntries(currentState as LocationStateEntry[]);
|
|
210
|
-
} else if (typeof currentState === "function") {
|
|
211
|
-
// Legacy getter function
|
|
212
|
-
resolvedState = currentState();
|
|
213
|
-
} else {
|
|
214
|
-
// Legacy static value
|
|
215
|
-
resolvedState = currentState;
|
|
216
|
-
}
|
|
320
|
+
const currentState = stateRef.current;
|
|
321
|
+
let resolvedState: unknown;
|
|
217
322
|
|
|
218
|
-
|
|
323
|
+
if (
|
|
324
|
+
Array.isArray(currentState) &&
|
|
325
|
+
currentState.length > 0 &&
|
|
326
|
+
isLocationStateEntry(currentState[0])
|
|
327
|
+
) {
|
|
328
|
+
resolvedState = resolveLocationStateEntries(
|
|
329
|
+
currentState as LocationStateEntry[],
|
|
330
|
+
);
|
|
331
|
+
} else if (typeof currentState === "function") {
|
|
332
|
+
resolvedState = currentState();
|
|
333
|
+
} else if (currentState != null) {
|
|
334
|
+
resolvedState = currentState;
|
|
219
335
|
}
|
|
336
|
+
|
|
337
|
+
ctx.navigate(resolvedTo, {
|
|
338
|
+
replace,
|
|
339
|
+
scroll,
|
|
340
|
+
state: resolvedState,
|
|
341
|
+
revalidate,
|
|
342
|
+
});
|
|
220
343
|
},
|
|
221
|
-
[
|
|
344
|
+
[
|
|
345
|
+
resolvedTo,
|
|
346
|
+
isExternal,
|
|
347
|
+
reloadDocument,
|
|
348
|
+
replace,
|
|
349
|
+
scroll,
|
|
350
|
+
revalidate,
|
|
351
|
+
ctx,
|
|
352
|
+
onClick,
|
|
353
|
+
],
|
|
222
354
|
);
|
|
223
355
|
|
|
224
356
|
const handleMouseEnter = useCallback(() => {
|
|
225
|
-
if (
|
|
357
|
+
if (
|
|
358
|
+
(resolvedStrategy === "hover" || resolvedStrategy === "viewport") &&
|
|
359
|
+
!isExternal &&
|
|
360
|
+
ctx?.store
|
|
361
|
+
) {
|
|
362
|
+
// For "hover", this is the primary prefetch trigger.
|
|
363
|
+
// For "viewport", this upgrades/prioritizes a potentially queued
|
|
364
|
+
// prefetch — prefetchDirect bypasses the queue, and hasPrefetch
|
|
365
|
+
// deduplicates if the viewport prefetch already completed.
|
|
226
366
|
const segmentState = ctx.store.getSegmentState();
|
|
227
|
-
|
|
367
|
+
prefetchDirect(
|
|
368
|
+
resolvedTo,
|
|
369
|
+
segmentState.currentSegmentIds,
|
|
370
|
+
getAppVersion(),
|
|
371
|
+
ctx.store.getRouterId?.(),
|
|
372
|
+
prefetchKey,
|
|
373
|
+
);
|
|
228
374
|
}
|
|
229
|
-
}, [
|
|
375
|
+
}, [resolvedStrategy, resolvedTo, isExternal, ctx, prefetchKey]);
|
|
376
|
+
|
|
377
|
+
// Viewport/render prefetch: waits for idle before starting,
|
|
378
|
+
// uses concurrency-limited queue to avoid flooding.
|
|
379
|
+
useEffect(() => {
|
|
380
|
+
if (isExternal || !ctx?.store) return;
|
|
381
|
+
const isViewport = resolvedStrategy === "viewport";
|
|
382
|
+
const isRender = resolvedStrategy === "render";
|
|
383
|
+
if (!isViewport && !isRender) return;
|
|
384
|
+
|
|
385
|
+
let cancelled = false;
|
|
386
|
+
let unsubIdle: (() => void) | undefined;
|
|
387
|
+
let observedElement: Element | null = null;
|
|
388
|
+
|
|
389
|
+
const triggerPrefetch = () => {
|
|
390
|
+
if (cancelled) return;
|
|
391
|
+
const segmentState = ctx.store.getSegmentState();
|
|
392
|
+
prefetchQueued(
|
|
393
|
+
resolvedTo,
|
|
394
|
+
segmentState.currentSegmentIds,
|
|
395
|
+
getAppVersion(),
|
|
396
|
+
ctx.store.getRouterId?.(),
|
|
397
|
+
prefetchKey,
|
|
398
|
+
);
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// Schedule prefetch only when the app is idle (no navigation/streaming).
|
|
402
|
+
// This avoids competing with hydration and active navigation fetches.
|
|
403
|
+
const scheduleWhenIdle = (callback: () => void) => {
|
|
404
|
+
const state = ctx.eventController.getState();
|
|
405
|
+
if (state.state === "idle" && !state.isStreaming) {
|
|
406
|
+
callback();
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const unsub = ctx.eventController.subscribe(() => {
|
|
410
|
+
const s = ctx.eventController.getState();
|
|
411
|
+
if (s.state === "idle" && !s.isStreaming) {
|
|
412
|
+
unsub();
|
|
413
|
+
callback();
|
|
414
|
+
}
|
|
415
|
+
});
|
|
416
|
+
unsubIdle = unsub;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
if (isRender) {
|
|
420
|
+
scheduleWhenIdle(triggerPrefetch);
|
|
421
|
+
} else if (isViewport) {
|
|
422
|
+
const element = internalRef.current;
|
|
423
|
+
if (!element) return;
|
|
424
|
+
observedElement = element;
|
|
425
|
+
observeForPrefetch(element, () => {
|
|
426
|
+
scheduleWhenIdle(triggerPrefetch);
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
return () => {
|
|
431
|
+
cancelled = true;
|
|
432
|
+
unsubIdle?.();
|
|
433
|
+
if (isViewport && observedElement) {
|
|
434
|
+
unobserveForPrefetch(observedElement);
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
}, [resolvedStrategy, resolvedTo, isExternal, ctx, prefetchKey]);
|
|
230
438
|
|
|
231
439
|
return (
|
|
232
440
|
<a
|
|
233
|
-
ref={
|
|
234
|
-
href={
|
|
441
|
+
ref={setRef}
|
|
442
|
+
href={resolvedTo}
|
|
235
443
|
onClick={handleClick}
|
|
236
444
|
onMouseEnter={handleMouseEnter}
|
|
237
445
|
data-link-component
|
|
238
446
|
data-external={isExternal ? "" : undefined}
|
|
239
447
|
data-scroll={scroll === false ? "false" : undefined}
|
|
240
448
|
data-replace={replace ? "true" : undefined}
|
|
449
|
+
data-revalidate={revalidate === false ? "false" : undefined}
|
|
241
450
|
{...props}
|
|
242
451
|
>
|
|
243
|
-
<LinkContext.Provider value={
|
|
244
|
-
{children}
|
|
245
|
-
</LinkContext.Provider>
|
|
452
|
+
<LinkContext.Provider value={resolvedTo}>{children}</LinkContext.Provider>
|
|
246
453
|
</a>
|
|
247
454
|
);
|
|
248
455
|
});
|