@rangojs/router 0.5.1 → 0.6.0
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/README.md +5 -1
- package/dist/bin/rango.js +343 -125
- package/dist/types/browser/event-controller.d.ts +6 -0
- package/dist/types/browser/react/use-router.d.ts +10 -3
- package/dist/types/browser/react/use-search-params.d.ts +57 -10
- package/dist/types/browser/types.d.ts +22 -0
- package/dist/types/build/merge-full-manifests.d.ts +3 -0
- package/dist/types/build/route-trie.d.ts +4 -73
- package/dist/types/build/route-types/per-module-writer.d.ts +6 -4
- package/dist/types/build/route-types/router-processing.d.ts +2 -3
- package/dist/types/cache/cache-exec-scope.d.ts +31 -0
- package/dist/types/cache/cf/cf-cache-constants.d.ts +8 -1
- package/dist/types/cache/cf/cf-cache-store.d.ts +15 -1
- package/dist/types/cache/cf/cf-cache-types.d.ts +1 -1
- package/dist/types/cache/cf/cf-kv-utils.d.ts +21 -0
- package/dist/types/cache/taint.d.ts +12 -6
- package/dist/types/client-urls/client-root.d.ts +38 -0
- package/dist/types/client-urls/client-urls.d.ts +5 -0
- package/dist/types/client-urls/navigation.d.ts +38 -0
- package/dist/types/client-urls/revalidation-protocol.d.ts +25 -0
- package/dist/types/client-urls/server-projection.d.ts +62 -0
- package/dist/types/client-urls/types.d.ts +144 -0
- package/dist/types/client.d.ts +12 -4
- package/dist/types/client.rsc.d.ts +4 -1
- package/dist/types/decode-loader-results.d.ts +37 -0
- package/dist/types/errors.d.ts +1 -0
- package/dist/types/handles/is-thenable.d.ts +2 -4
- package/dist/types/index.d.ts +1 -1
- package/dist/types/loader-redirect.d.ts +27 -0
- package/dist/types/outlet-context.d.ts +12 -0
- package/dist/types/outlet-provider.d.ts +3 -1
- package/dist/types/redirect-origin.d.ts +4 -0
- package/dist/types/route-content-wrapper.d.ts +42 -1
- package/dist/types/route-definition/helpers-types.d.ts +13 -2
- package/dist/types/router/error-handling.d.ts +35 -1
- package/dist/types/router/intercept-resolution.d.ts +12 -0
- package/dist/types/router/loader-resolution.d.ts +24 -2
- package/dist/types/router/revalidation.d.ts +7 -0
- package/dist/{types.backup/build/route-trie.d.ts → types/router/route-trie-builder.d.ts} +4 -16
- package/dist/types/router/router-interfaces.d.ts +20 -0
- package/dist/types/router/segment-resolution/helpers.d.ts +1 -1
- package/dist/types/router/trie-matching.d.ts +1 -1
- package/dist/types/rsc/helpers.d.ts +3 -0
- package/dist/types/rsc/manifest-init.d.ts +5 -5
- package/dist/types/rsc/render-pipeline.d.ts +9 -0
- package/dist/types/rsc/routine-plan.d.ts +124 -0
- package/dist/types/rsc/shell-capture-constants.d.ts +17 -0
- package/dist/types/rsc/shell-capture.d.ts +9 -0
- package/dist/types/rsc/shell-serve.d.ts +11 -0
- package/dist/types/rsc/types.d.ts +30 -0
- package/dist/types/segment-system.d.ts +2 -0
- package/dist/types/server/context.d.ts +10 -0
- package/dist/types/server/handle-store.d.ts +34 -3
- package/dist/types/server/request-context.d.ts +14 -1
- package/dist/types/server.d.ts +1 -0
- package/dist/types/ssr/index.d.ts +22 -0
- package/dist/types/ssr/ssr-root.d.ts +10 -0
- package/dist/types/testing/dom.entry.d.ts +1 -1
- package/dist/types/testing/render-route.d.ts +16 -6
- package/dist/types/testing/run-loader.d.ts +9 -0
- package/dist/types/types/boundaries.d.ts +22 -0
- package/dist/types/types/index.d.ts +1 -1
- package/dist/types/types/loader-types.d.ts +57 -5
- package/dist/types/types/segments.d.ts +7 -0
- package/dist/types/urls/path-helper-types.d.ts +10 -4
- package/dist/types/vite/discovery/client-urls-projection.d.ts +53 -0
- package/dist/types/vite/discovery/discover-routers.d.ts +1 -1
- package/dist/types/vite/discovery/state.d.ts +8 -1
- package/dist/types/vite/encryption-key.d.ts +2 -0
- package/dist/types/vite/plugins/expose-internal-ids.d.ts +10 -0
- package/dist/types/vite/plugins/server-ref-hashing.d.ts +24 -0
- package/dist/types/vite/plugins/server-reference-pattern.d.ts +1 -0
- package/dist/types/vite/utils/shared-utils.d.ts +12 -0
- package/dist/vite/index.js +5101 -2056
- package/package.json +3 -3
- package/skills/breadcrumbs/SKILL.md +39 -9
- package/skills/caching/SKILL.md +1 -1
- package/skills/catalog.json +7 -1
- package/skills/client-urls/SKILL.md +338 -0
- package/skills/comparison/references/framework-comparison.md +23 -9
- package/skills/hooks/SKILL.md +2 -2
- package/skills/hooks/data.md +11 -2
- package/skills/hooks/handle-and-actions.md +7 -0
- package/skills/hooks/outlets.md +26 -5
- package/skills/hooks/urls.md +40 -3
- package/skills/loader/SKILL.md +132 -20
- package/skills/migrate-nextjs/SKILL.md +70 -10
- package/skills/migrate-react-router/SKILL.md +49 -13
- package/skills/migrate-react-router/component-migration.md +18 -13
- package/skills/migrate-react-router/data-and-actions.md +14 -3
- package/skills/migrate-react-router/route-mapping.md +15 -2
- package/skills/mime-routes/SKILL.md +3 -1
- package/skills/parallel/SKILL.md +32 -1
- package/skills/ppr/SKILL.md +16 -6
- package/skills/prerender/SKILL.md +8 -4
- package/skills/rango/SKILL.md +21 -17
- package/skills/react-compiler/SKILL.md +3 -3
- package/skills/response-routes/SKILL.md +4 -2
- package/skills/route/SKILL.md +5 -2
- package/skills/router-setup/SKILL.md +16 -2
- package/skills/scripts/SKILL.md +16 -6
- package/skills/shell-manifest/SKILL.md +16 -7
- package/skills/testing/SKILL.md +2 -2
- package/skills/testing/client-components.md +6 -0
- package/skills/testing/handles.md +30 -8
- package/skills/testing/loader.md +51 -49
- package/skills/testing/middleware.md +1 -1
- package/skills/theme/SKILL.md +8 -5
- package/skills/typesafety/generated-files-and-cli.md +16 -9
- package/skills/typesafety/route-types.md +5 -1
- package/skills/use-cache/SKILL.md +47 -0
- package/src/bin/rango.ts +7 -3
- package/src/browser/event-controller.ts +40 -15
- package/src/browser/navigation-bridge.ts +6 -0
- package/src/browser/navigation-client.ts +5 -0
- package/src/browser/partial-update.ts +77 -10
- package/src/browser/react/NavigationProvider.tsx +7 -0
- package/src/browser/react/use-router.ts +40 -11
- package/src/browser/react/use-search-params.ts +140 -17
- package/src/browser/rsc-router.tsx +59 -0
- package/src/browser/server-action-bridge.ts +26 -0
- package/src/browser/types.ts +22 -0
- package/src/build/merge-full-manifests.ts +161 -0
- package/src/build/route-trie.ts +9 -332
- package/src/build/route-types/include-resolution.ts +66 -11
- package/src/build/route-types/per-module-writer.ts +11 -6
- package/src/build/route-types/router-processing.ts +184 -153
- package/src/build/runtime-discovery.ts +23 -12
- package/src/cache/cache-exec-scope.ts +47 -0
- package/src/cache/cache-runtime.ts +113 -40
- package/src/cache/cf/cf-cache-constants.ts +8 -1
- package/src/cache/cf/cf-cache-store.ts +41 -64
- package/src/cache/cf/cf-cache-types.ts +1 -1
- package/src/cache/cf/cf-kv-utils.ts +38 -0
- package/src/cache/segment-codec.ts +21 -5
- package/src/cache/taint.ts +28 -9
- package/src/client-urls/client-root.tsx +168 -0
- package/src/client-urls/client-urls.ts +698 -0
- package/src/client-urls/navigation.ts +237 -0
- package/src/client-urls/revalidation-protocol.ts +56 -0
- package/src/client-urls/server-projection.ts +579 -0
- package/src/client-urls/types.ts +195 -0
- package/src/client.rsc.tsx +12 -0
- package/src/client.tsx +49 -6
- package/src/decode-loader-results.ts +113 -0
- package/src/errors.ts +14 -0
- package/src/handles/deferred-resolution.ts +14 -7
- package/src/handles/is-thenable.ts +2 -4
- package/src/index.ts +1 -0
- package/src/loader-redirect.tsx +64 -0
- package/src/outlet-context.ts +12 -0
- package/src/outlet-provider.tsx +15 -1
- package/src/redirect-origin.ts +29 -0
- package/src/route-content-wrapper.tsx +96 -3
- package/src/route-definition/dsl-helpers.ts +28 -3
- package/src/route-definition/helpers-types.ts +13 -0
- package/src/route-definition/redirect.ts +17 -18
- package/src/router/error-handling.ts +65 -11
- package/src/router/intercept-resolution.ts +29 -0
- package/src/router/loader-resolution.ts +261 -28
- package/src/router/match-middleware/cache-lookup.ts +24 -15
- package/src/router/match-result.ts +7 -0
- package/src/router/revalidation.ts +24 -11
- package/src/router/route-trie-builder.ts +334 -0
- package/src/router/router-interfaces.ts +38 -0
- package/src/router/segment-resolution/fresh.ts +47 -0
- package/src/router/segment-resolution/helpers.ts +9 -11
- package/src/router/segment-resolution/loader-cache.ts +14 -24
- package/src/router/segment-resolution/revalidation.ts +20 -1
- package/src/router/trie-matching.ts +3 -3
- package/src/router.ts +46 -1
- package/src/rsc/full-payload.ts +6 -0
- package/src/rsc/handler.ts +36 -12
- package/src/rsc/helpers.ts +13 -0
- package/src/rsc/loader-fetch.ts +2 -2
- package/src/rsc/manifest-init.ts +28 -9
- package/src/rsc/progressive-enhancement.ts +247 -70
- package/src/rsc/render-pipeline.ts +68 -24
- package/src/rsc/routine-plan.ts +359 -0
- package/src/rsc/rsc-rendering.ts +569 -302
- package/src/rsc/server-action.ts +180 -71
- package/src/rsc/shell-capture-constants.ts +18 -0
- package/src/rsc/shell-capture.ts +104 -21
- package/src/rsc/shell-serve.ts +15 -2
- package/src/rsc/ssr-setup.ts +10 -1
- package/src/rsc/types.ts +31 -2
- package/src/segment-system.tsx +83 -26
- package/src/server/context.ts +10 -0
- package/src/server/cookie-store.ts +19 -19
- package/src/server/handle-store.ts +185 -48
- package/src/server/request-context.ts +36 -6
- package/src/server.ts +7 -0
- package/src/ssr/index.tsx +37 -2
- package/src/ssr/ssr-root.tsx +30 -2
- package/src/testing/dom.entry.ts +1 -1
- package/src/testing/render-route.tsx +22 -8
- package/src/testing/run-loader.ts +51 -13
- package/src/types/boundaries.ts +19 -0
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +60 -5
- package/src/types/segments.ts +7 -0
- package/src/urls/include-helper.ts +22 -4
- package/src/urls/path-helper-types.ts +14 -1
- package/src/use-loader.tsx +67 -6
- package/src/vite/discovery/client-urls-projection.ts +322 -0
- package/src/vite/discovery/discover-routers.ts +43 -17
- package/src/vite/discovery/state.ts +11 -1
- package/src/vite/discovery/virtual-module-codegen.ts +20 -0
- package/src/vite/encryption-key.ts +29 -0
- package/src/vite/plugins/expose-action-id.ts +2 -2
- package/src/vite/plugins/expose-internal-ids.ts +46 -0
- package/src/vite/plugins/server-ref-hashing.ts +74 -0
- package/src/vite/plugins/server-reference-pattern.ts +10 -0
- package/src/vite/plugins/virtual-entries.ts +12 -3
- package/src/vite/rango.ts +9 -0
- package/src/vite/router-discovery.ts +184 -14
- package/src/vite/utils/shared-utils.ts +12 -7
- package/dist/types.backup/__internal.d.ts +0 -127
- package/dist/types.backup/bin/rango.d.ts +0 -1
- package/dist/types.backup/browser/action-coordinator.d.ts +0 -57
- package/dist/types.backup/browser/action-fence.d.ts +0 -33
- package/dist/types.backup/browser/app-shell.d.ts +0 -34
- package/dist/types.backup/browser/app-version.d.ts +0 -6
- package/dist/types.backup/browser/connection-warmup.d.ts +0 -31
- package/dist/types.backup/browser/cookie-name.d.ts +0 -66
- package/dist/types.backup/browser/event-controller.d.ts +0 -221
- package/dist/types.backup/browser/history-state.d.ts +0 -26
- package/dist/types.backup/browser/index.d.ts +0 -1
- package/dist/types.backup/browser/intercept-utils.d.ts +0 -30
- package/dist/types.backup/browser/invalidate-client-cache.d.ts +0 -17
- package/dist/types.backup/browser/link-interceptor.d.ts +0 -43
- package/dist/types.backup/browser/logging.d.ts +0 -33
- package/dist/types.backup/browser/merge-segment-loaders.d.ts +0 -38
- package/dist/types.backup/browser/navigation-bridge.d.ts +0 -27
- package/dist/types.backup/browser/navigation-client.d.ts +0 -17
- package/dist/types.backup/browser/navigation-store-handle.d.ts +0 -25
- package/dist/types.backup/browser/navigation-store.d.ts +0 -95
- package/dist/types.backup/browser/navigation-transaction.d.ts +0 -75
- package/dist/types.backup/browser/network-error-handler.d.ts +0 -35
- package/dist/types.backup/browser/partial-update.d.ts +0 -61
- package/dist/types.backup/browser/prefetch/cache.d.ts +0 -183
- package/dist/types.backup/browser/prefetch/fetch.d.ts +0 -52
- package/dist/types.backup/browser/prefetch/observer.d.ts +0 -27
- package/dist/types.backup/browser/prefetch/policy.d.ts +0 -13
- package/dist/types.backup/browser/prefetch/queue.d.ts +0 -48
- package/dist/types.backup/browser/prefetch/resource-ready.d.ts +0 -28
- package/dist/types.backup/browser/rango-state.d.ts +0 -52
- package/dist/types.backup/browser/react/Link.d.ts +0 -140
- package/dist/types.backup/browser/react/NavigationProvider.d.ts +0 -88
- package/dist/types.backup/browser/react/ScrollRestoration.d.ts +0 -78
- package/dist/types.backup/browser/react/context.d.ts +0 -54
- package/dist/types.backup/browser/react/filter-segment-order.d.ts +0 -35
- package/dist/types.backup/browser/react/index.d.ts +0 -1
- package/dist/types.backup/browser/react/location-state-shared.d.ts +0 -162
- package/dist/types.backup/browser/react/location-state.d.ts +0 -29
- package/dist/types.backup/browser/react/mount-context.d.ts +0 -23
- package/dist/types.backup/browser/react/nonce-context.d.ts +0 -14
- package/dist/types.backup/browser/react/shallow-equal.d.ts +0 -5
- package/dist/types.backup/browser/react/use-action.d.ts +0 -61
- package/dist/types.backup/browser/react/use-handle.d.ts +0 -21
- package/dist/types.backup/browser/react/use-href.d.ts +0 -32
- package/dist/types.backup/browser/react/use-link-status.d.ts +0 -36
- package/dist/types.backup/browser/react/use-mount.d.ts +0 -24
- package/dist/types.backup/browser/react/use-navigation.d.ts +0 -15
- package/dist/types.backup/browser/react/use-params.d.ts +0 -21
- package/dist/types.backup/browser/react/use-pathname.d.ts +0 -13
- package/dist/types.backup/browser/react/use-reverse.d.ts +0 -40
- package/dist/types.backup/browser/react/use-router.d.ts +0 -23
- package/dist/types.backup/browser/react/use-search-params.d.ts +0 -19
- package/dist/types.backup/browser/react/use-segments.d.ts +0 -29
- package/dist/types.backup/browser/response-adapter.d.ts +0 -58
- package/dist/types.backup/browser/rsc-router.d.ts +0 -141
- package/dist/types.backup/browser/scroll-restoration.d.ts +0 -103
- package/dist/types.backup/browser/segment-reconciler.d.ts +0 -74
- package/dist/types.backup/browser/segment-structure-assert.d.ts +0 -16
- package/dist/types.backup/browser/server-action-bridge.d.ts +0 -29
- package/dist/types.backup/browser/types.d.ts +0 -530
- package/dist/types.backup/browser/validate-redirect-origin.d.ts +0 -28
- package/dist/types.backup/build/collect-fallback-refs.d.ts +0 -5
- package/dist/types.backup/build/generate-manifest.d.ts +0 -100
- package/dist/types.backup/build/generate-route-types.d.ts +0 -8
- package/dist/types.backup/build/index.d.ts +0 -21
- package/dist/types.backup/build/prefix-tree-utils.d.ts +0 -56
- package/dist/types.backup/build/route-types/ast-helpers.d.ts +0 -3
- package/dist/types.backup/build/route-types/ast-route-extraction.d.ts +0 -13
- package/dist/types.backup/build/route-types/codegen.d.ts +0 -16
- package/dist/types.backup/build/route-types/include-resolution.d.ts +0 -74
- package/dist/types.backup/build/route-types/param-extraction.d.ts +0 -13
- package/dist/types.backup/build/route-types/per-module-writer.d.ts +0 -18
- package/dist/types.backup/build/route-types/router-processing.d.ts +0 -82
- package/dist/types.backup/build/route-types/scan-filter.d.ts +0 -17
- package/dist/types.backup/build/route-types/source-scan.d.ts +0 -13
- package/dist/types.backup/build/runtime-discovery.d.ts +0 -24
- package/dist/types.backup/cache/background-task.d.ts +0 -21
- package/dist/types.backup/cache/cache-error.d.ts +0 -71
- package/dist/types.backup/cache/cache-key-utils.d.ts +0 -35
- package/dist/types.backup/cache/cache-policy.d.ts +0 -59
- package/dist/types.backup/cache/cache-runtime.d.ts +0 -51
- package/dist/types.backup/cache/cache-scope.d.ts +0 -134
- package/dist/types.backup/cache/cache-tag.d.ts +0 -79
- package/dist/types.backup/cache/cf/cf-base64.d.ts +0 -4
- package/dist/types.backup/cache/cf/cf-cache-constants.d.ts +0 -105
- package/dist/types.backup/cache/cf/cf-cache-store.d.ts +0 -481
- package/dist/types.backup/cache/cf/cf-cache-types.d.ts +0 -300
- package/dist/types.backup/cache/cf/cf-kv-utils.d.ts +0 -22
- package/dist/types.backup/cache/cf/cf-tag-marker-memo.d.ts +0 -15
- package/dist/types.backup/cache/cf/index.d.ts +0 -3
- package/dist/types.backup/cache/document-cache.d.ts +0 -69
- package/dist/types.backup/cache/handle-capture.d.ts +0 -23
- package/dist/types.backup/cache/handle-snapshot.d.ts +0 -39
- package/dist/types.backup/cache/index.d.ts +0 -7
- package/dist/types.backup/cache/memory-segment-store.d.ts +0 -163
- package/dist/types.backup/cache/profile-registry.d.ts +0 -40
- package/dist/types.backup/cache/read-through-swr.d.ts +0 -60
- package/dist/types.backup/cache/segment-codec.d.ts +0 -78
- package/dist/types.backup/cache/shell-snapshot.d.ts +0 -162
- package/dist/types.backup/cache/tag-invalidation.d.ts +0 -74
- package/dist/types.backup/cache/taint.d.ts +0 -71
- package/dist/types.backup/cache/types.d.ts +0 -407
- package/dist/types.backup/cache/vercel/index.d.ts +0 -1
- package/dist/types.backup/cache/vercel/vercel-cache-store.d.ts +0 -267
- package/dist/types.backup/client.d.ts +0 -184
- package/dist/types.backup/client.rsc.d.ts +0 -39
- package/dist/types.backup/cloudflare/index.d.ts +0 -7
- package/dist/types.backup/cloudflare/tracing.d.ts +0 -53
- package/dist/types.backup/component-utils.d.ts +0 -46
- package/dist/types.backup/components/DefaultDocument.d.ts +0 -13
- package/dist/types.backup/context-var.d.ts +0 -84
- package/dist/types.backup/debug.d.ts +0 -57
- package/dist/types.backup/decode-loader-results.d.ts +0 -5
- package/dist/types.backup/default-error-boundary.d.ts +0 -10
- package/dist/types.backup/defer.d.ts +0 -89
- package/dist/types.backup/deps/browser.d.ts +0 -1
- package/dist/types.backup/deps/html-stream-client.d.ts +0 -1
- package/dist/types.backup/deps/html-stream-server.d.ts +0 -1
- package/dist/types.backup/deps/rsc.d.ts +0 -1
- package/dist/types.backup/deps/ssr.d.ts +0 -1
- package/dist/types.backup/encode-kv.d.ts +0 -35
- package/dist/types.backup/errors.d.ts +0 -226
- package/dist/types.backup/escape-script.d.ts +0 -44
- package/dist/types.backup/handle.d.ts +0 -93
- package/dist/types.backup/handles/MetaTags.d.ts +0 -17
- package/dist/types.backup/handles/Scripts.d.ts +0 -38
- package/dist/types.backup/handles/breadcrumbs.d.ts +0 -43
- package/dist/types.backup/handles/deferred-resolution.d.ts +0 -53
- package/dist/types.backup/handles/is-thenable.d.ts +0 -12
- package/dist/types.backup/handles/meta.d.ts +0 -43
- package/dist/types.backup/handles/script.d.ts +0 -139
- package/dist/types.backup/host/cookie-handler.d.ts +0 -8
- package/dist/types.backup/host/errors.d.ts +0 -40
- package/dist/types.backup/host/index.d.ts +0 -33
- package/dist/types.backup/host/pattern-matcher.d.ts +0 -30
- package/dist/types.backup/host/router.d.ts +0 -12
- package/dist/types.backup/host/testing.d.ts +0 -41
- package/dist/types.backup/host/types.d.ts +0 -148
- package/dist/types.backup/host/utils.d.ts +0 -20
- package/dist/types.backup/href-client.d.ts +0 -214
- package/dist/types.backup/index.d.ts +0 -112
- package/dist/types.backup/index.rsc.d.ts +0 -51
- package/dist/types.backup/internal-debug.d.ts +0 -1
- package/dist/types.backup/loader-store.d.ts +0 -193
- package/dist/types.backup/loader.d.ts +0 -18
- package/dist/types.backup/loader.rsc.d.ts +0 -18
- package/dist/types.backup/missing-id-error.d.ts +0 -1
- package/dist/types.backup/outlet-context.d.ts +0 -12
- package/dist/types.backup/outlet-provider.d.ts +0 -12
- package/dist/types.backup/prerender/build-shell-capture.d.ts +0 -104
- package/dist/types.backup/prerender/param-hash.d.ts +0 -6
- package/dist/types.backup/prerender/shell-manifest-key.d.ts +0 -18
- package/dist/types.backup/prerender/store.d.ts +0 -62
- package/dist/types.backup/prerender.d.ts +0 -292
- package/dist/types.backup/redirect-origin.d.ts +0 -55
- package/dist/types.backup/regex-escape.d.ts +0 -6
- package/dist/types.backup/render-error-thrower.d.ts +0 -13
- package/dist/types.backup/response-utils.d.ts +0 -35
- package/dist/types.backup/reverse.d.ts +0 -206
- package/dist/types.backup/root-error-boundary.d.ts +0 -32
- package/dist/types.backup/route-content-wrapper.d.ts +0 -40
- package/dist/types.backup/route-definition/dsl-helpers.d.ts +0 -130
- package/dist/types.backup/route-definition/helper-factories.d.ts +0 -22
- package/dist/types.backup/route-definition/helpers-types.d.ts +0 -392
- package/dist/types.backup/route-definition/index.d.ts +0 -7
- package/dist/types.backup/route-definition/redirect.d.ts +0 -48
- package/dist/types.backup/route-definition/resolve-handler-use.d.ts +0 -19
- package/dist/types.backup/route-definition/use-item-types.d.ts +0 -1
- package/dist/types.backup/route-definition.d.ts +0 -1
- package/dist/types.backup/route-map-builder.d.ts +0 -127
- package/dist/types.backup/route-name.d.ts +0 -27
- package/dist/types.backup/route-types.d.ts +0 -172
- package/dist/types.backup/router/basename.d.ts +0 -10
- package/dist/types.backup/router/content-negotiation.d.ts +0 -91
- package/dist/types.backup/router/debug-manifest.d.ts +0 -7
- package/dist/types.backup/router/error-handling.d.ts +0 -76
- package/dist/types.backup/router/find-match.d.ts +0 -19
- package/dist/types.backup/router/handler-context.d.ts +0 -41
- package/dist/types.backup/router/instrument.d.ts +0 -161
- package/dist/types.backup/router/intercept-resolution.d.ts +0 -79
- package/dist/types.backup/router/lazy-includes.d.ts +0 -26
- package/dist/types.backup/router/loader-resolution.d.ts +0 -63
- package/dist/types.backup/router/logging.d.ts +0 -41
- package/dist/types.backup/router/manifest.d.ts +0 -8
- package/dist/types.backup/router/match-api.d.ts +0 -19
- package/dist/types.backup/router/match-context.d.ts +0 -184
- package/dist/types.backup/router/match-handlers.d.ts +0 -49
- package/dist/types.backup/router/match-middleware/background-revalidation.d.ts +0 -113
- package/dist/types.backup/router/match-middleware/cache-lookup.d.ts +0 -113
- package/dist/types.backup/router/match-middleware/cache-store.d.ts +0 -112
- package/dist/types.backup/router/match-middleware/index.d.ts +0 -80
- package/dist/types.backup/router/match-middleware/intercept-resolution.d.ts +0 -116
- package/dist/types.backup/router/match-middleware/segment-resolution.d.ts +0 -94
- package/dist/types.backup/router/match-pipelines.d.ts +0 -103
- package/dist/types.backup/router/match-result.d.ts +0 -114
- package/dist/types.backup/router/metrics.d.ts +0 -6
- package/dist/types.backup/router/middleware-types.d.ts +0 -74
- package/dist/types.backup/router/middleware.d.ts +0 -116
- package/dist/types.backup/router/navigation-snapshot.d.ts +0 -22
- package/dist/types.backup/router/params-util.d.ts +0 -8
- package/dist/types.backup/router/parse-pattern.d.ts +0 -38
- package/dist/types.backup/router/pattern-matching.d.ts +0 -169
- package/dist/types.backup/router/prefetch-cache-ttl.d.ts +0 -27
- package/dist/types.backup/router/prefetch-limits.d.ts +0 -20
- package/dist/types.backup/router/prerender-match.d.ts +0 -50
- package/dist/types.backup/router/preview-match.d.ts +0 -22
- package/dist/types.backup/router/request-classification.d.ts +0 -104
- package/dist/types.backup/router/revalidation.d.ts +0 -57
- package/dist/types.backup/router/route-snapshot.d.ts +0 -112
- package/dist/types.backup/router/router-context.d.ts +0 -137
- package/dist/types.backup/router/router-interfaces.d.ts +0 -432
- package/dist/types.backup/router/router-options.d.ts +0 -738
- package/dist/types.backup/router/router-registry.d.ts +0 -15
- package/dist/types.backup/router/segment-resolution/fresh.d.ts +0 -55
- package/dist/types.backup/router/segment-resolution/helpers.d.ts +0 -93
- package/dist/types.backup/router/segment-resolution/loader-cache.d.ts +0 -33
- package/dist/types.backup/router/segment-resolution/loader-mask.d.ts +0 -44
- package/dist/types.backup/router/segment-resolution/loader-snapshot.d.ts +0 -90
- package/dist/types.backup/router/segment-resolution/mask-nested.d.ts +0 -53
- package/dist/types.backup/router/segment-resolution/revalidation.d.ts +0 -85
- package/dist/types.backup/router/segment-resolution/static-store.d.ts +0 -17
- package/dist/types.backup/router/segment-resolution/streamed-handler-telemetry.d.ts +0 -16
- package/dist/types.backup/router/segment-resolution/view-transition-default.d.ts +0 -28
- package/dist/types.backup/router/segment-resolution.d.ts +0 -3
- package/dist/types.backup/router/segment-wrappers.d.ts +0 -53
- package/dist/types.backup/router/state-cookie-name.d.ts +0 -1
- package/dist/types.backup/router/substitute-pattern-params.d.ts +0 -23
- package/dist/types.backup/router/telemetry-otel.d.ts +0 -113
- package/dist/types.backup/router/telemetry.d.ts +0 -215
- package/dist/types.backup/router/timeout.d.ts +0 -68
- package/dist/types.backup/router/tracing.d.ts +0 -125
- package/dist/types.backup/router/trie-matching.d.ts +0 -32
- package/dist/types.backup/router/types.d.ts +0 -98
- package/dist/types.backup/router/url-params.d.ts +0 -26
- package/dist/types.backup/router.d.ts +0 -7
- package/dist/types.backup/rsc/capture-queue.d.ts +0 -6
- package/dist/types.backup/rsc/full-payload.d.ts +0 -22
- package/dist/types.backup/rsc/handler-context.d.ts +0 -31
- package/dist/types.backup/rsc/handler.d.ts +0 -9
- package/dist/types.backup/rsc/helpers.d.ts +0 -213
- package/dist/types.backup/rsc/index.d.ts +0 -17
- package/dist/types.backup/rsc/json-route-result.d.ts +0 -20
- package/dist/types.backup/rsc/loader-fetch.d.ts +0 -14
- package/dist/types.backup/rsc/manifest-init.d.ts +0 -18
- package/dist/types.backup/rsc/nonce.d.ts +0 -28
- package/dist/types.backup/rsc/origin-guard.d.ts +0 -50
- package/dist/types.backup/rsc/progressive-enhancement.d.ts +0 -19
- package/dist/types.backup/rsc/redirect-guard.d.ts +0 -35
- package/dist/types.backup/rsc/response-cache-serve.d.ts +0 -46
- package/dist/types.backup/rsc/response-error.d.ts +0 -19
- package/dist/types.backup/rsc/response-route-handler.d.ts +0 -29
- package/dist/types.backup/rsc/rsc-rendering.d.ts +0 -23
- package/dist/types.backup/rsc/runtime-warnings.d.ts +0 -22
- package/dist/types.backup/rsc/server-action.d.ts +0 -68
- package/dist/types.backup/rsc/shell-build-manifest.d.ts +0 -84
- package/dist/types.backup/rsc/shell-capture-constants.d.ts +0 -27
- package/dist/types.backup/rsc/shell-capture.d.ts +0 -374
- package/dist/types.backup/rsc/shell-serve.d.ts +0 -136
- package/dist/types.backup/rsc/ssr-setup.d.ts +0 -48
- package/dist/types.backup/rsc/transition-gate.d.ts +0 -27
- package/dist/types.backup/rsc/types.d.ts +0 -290
- package/dist/types.backup/runtime-env.d.ts +0 -1
- package/dist/types.backup/search-params.d.ts +0 -125
- package/dist/types.backup/segment-content-promise.d.ts +0 -13
- package/dist/types.backup/segment-fragments.d.ts +0 -56
- package/dist/types.backup/segment-loader-promise.d.ts +0 -22
- package/dist/types.backup/segment-system.d.ts +0 -84
- package/dist/types.backup/serialize.d.ts +0 -164
- package/dist/types.backup/server/context.d.ts +0 -494
- package/dist/types.backup/server/cookie-parse.d.ts +0 -10
- package/dist/types.backup/server/cookie-store.d.ts +0 -107
- package/dist/types.backup/server/fetchable-loader-store.d.ts +0 -20
- package/dist/types.backup/server/handle-store.d.ts +0 -100
- package/dist/types.backup/server/loader-registry.d.ts +0 -32
- package/dist/types.backup/server/request-context.d.ts +0 -596
- package/dist/types.backup/server/root-layout.d.ts +0 -3
- package/dist/types.backup/server.d.ts +0 -15
- package/dist/types.backup/ssr/index.d.ts +0 -233
- package/dist/types.backup/ssr/inject-rsc-eager.d.ts +0 -3
- package/dist/types.backup/ssr/preinit-client-references.d.ts +0 -71
- package/dist/types.backup/ssr/ssr-root.d.ts +0 -69
- package/dist/types.backup/static-handler.d.ts +0 -57
- package/dist/types.backup/testing/cache-status.d.ts +0 -63
- package/dist/types.backup/testing/collect-handle.d.ts +0 -20
- package/dist/types.backup/testing/dispatch.d.ts +0 -123
- package/dist/types.backup/testing/dom.entry.d.ts +0 -15
- package/dist/types.backup/testing/e2e/fixture.d.ts +0 -37
- package/dist/types.backup/testing/e2e/index.d.ts +0 -30
- package/dist/types.backup/testing/e2e/matchers.d.ts +0 -17
- package/dist/types.backup/testing/e2e/page-helpers.d.ts +0 -62
- package/dist/types.backup/testing/e2e/parity.d.ts +0 -111
- package/dist/types.backup/testing/e2e/server.d.ts +0 -35
- package/dist/types.backup/testing/flight-matchers.d.ts +0 -55
- package/dist/types.backup/testing/flight-normalize.d.ts +0 -1
- package/dist/types.backup/testing/flight-tree.d.ts +0 -192
- package/dist/types.backup/testing/flight.d.ts +0 -115
- package/dist/types.backup/testing/flight.entry.d.ts +0 -27
- package/dist/types.backup/testing/generated-routes.d.ts +0 -66
- package/dist/types.backup/testing/index.d.ts +0 -52
- package/dist/types.backup/testing/internal/context.d.ts +0 -225
- package/dist/types.backup/testing/internal/flight-client-globals.d.ts +0 -1
- package/dist/types.backup/testing/internal/seed-vars.d.ts +0 -30
- package/dist/types.backup/testing/render-handler.d.ts +0 -160
- package/dist/types.backup/testing/render-route.d.ts +0 -246
- package/dist/types.backup/testing/run-loader.d.ts +0 -186
- package/dist/types.backup/testing/run-middleware.d.ts +0 -132
- package/dist/types.backup/testing/run-transition-when.d.ts +0 -77
- package/dist/types.backup/testing/vitest-stubs/cloudflare-email.d.ts +0 -6
- package/dist/types.backup/testing/vitest-stubs/cloudflare-workers.d.ts +0 -13
- package/dist/types.backup/testing/vitest-stubs/plugin-rsc.d.ts +0 -7
- package/dist/types.backup/testing/vitest-stubs/version.d.ts +0 -1
- package/dist/types.backup/testing/vitest.d.ts +0 -205
- package/dist/types.backup/theme/ThemeProvider.d.ts +0 -13
- package/dist/types.backup/theme/ThemeScript.d.ts +0 -45
- package/dist/types.backup/theme/constants.d.ts +0 -39
- package/dist/types.backup/theme/index.d.ts +0 -29
- package/dist/types.backup/theme/theme-context.d.ts +0 -21
- package/dist/types.backup/theme/theme-script.d.ts +0 -26
- package/dist/types.backup/theme/types.d.ts +0 -162
- package/dist/types.backup/theme/use-theme.d.ts +0 -8
- package/dist/types.backup/types/boundaries.d.ts +0 -93
- package/dist/types.backup/types/cache-types.d.ts +0 -191
- package/dist/types.backup/types/error-types.d.ts +0 -114
- package/dist/types.backup/types/global-namespace.d.ts +0 -90
- package/dist/types.backup/types/handler-context.d.ts +0 -658
- package/dist/types.backup/types/index.d.ts +0 -11
- package/dist/types.backup/types/loader-types.d.ts +0 -182
- package/dist/types.backup/types/request-scope.d.ts +0 -93
- package/dist/types.backup/types/route-config.d.ts +0 -105
- package/dist/types.backup/types/route-entry.d.ts +0 -95
- package/dist/types.backup/types/segments.d.ts +0 -234
- package/dist/types.backup/types.d.ts +0 -1
- package/dist/types.backup/urls/include-helper.d.ts +0 -17
- package/dist/types.backup/urls/include-provider.d.ts +0 -27
- package/dist/types.backup/urls/index.d.ts +0 -6
- package/dist/types.backup/urls/path-helper-types.d.ts +0 -197
- package/dist/types.backup/urls/path-helper.d.ts +0 -12
- package/dist/types.backup/urls/pattern-types.d.ts +0 -166
- package/dist/types.backup/urls/response-types.d.ts +0 -67
- package/dist/types.backup/urls/type-extraction.d.ts +0 -157
- package/dist/types.backup/urls/urls-function.d.ts +0 -24
- package/dist/types.backup/urls.d.ts +0 -1
- package/dist/types.backup/use-loader.d.ts +0 -150
- package/dist/types.backup/vercel/index.d.ts +0 -10
- package/dist/types.backup/vercel/tracing.d.ts +0 -70
- package/dist/types.backup/vite/debug.d.ts +0 -80
- package/dist/types.backup/vite/discovery/bundle-postprocess.d.ts +0 -12
- package/dist/types.backup/vite/discovery/dev-prerender-cache.d.ts +0 -65
- package/dist/types.backup/vite/discovery/discover-routers.d.ts +0 -17
- package/dist/types.backup/vite/discovery/discovery-errors.d.ts +0 -113
- package/dist/types.backup/vite/discovery/gate-state.d.ts +0 -79
- package/dist/types.backup/vite/discovery/prerender-collection.d.ts +0 -24
- package/dist/types.backup/vite/discovery/route-types-writer.d.ts +0 -32
- package/dist/types.backup/vite/discovery/self-gen-tracking.d.ts +0 -22
- package/dist/types.backup/vite/discovery/shell-prerender-phase.d.ts +0 -40
- package/dist/types.backup/vite/discovery/state.d.ts +0 -162
- package/dist/types.backup/vite/discovery/virtual-module-codegen.d.ts +0 -15
- package/dist/types.backup/vite/index.d.ts +0 -11
- package/dist/types.backup/vite/inject-client-debug.d.ts +0 -56
- package/dist/types.backup/vite/plugin-types.d.ts +0 -298
- package/dist/types.backup/vite/plugins/cjs-to-esm.d.ts +0 -6
- package/dist/types.backup/vite/plugins/client-ref-dedup.d.ts +0 -40
- package/dist/types.backup/vite/plugins/client-ref-hashing.d.ts +0 -35
- package/dist/types.backup/vite/plugins/cloudflare-protocol-stub.d.ts +0 -64
- package/dist/types.backup/vite/plugins/expose-action-id.d.ts +0 -18
- package/dist/types.backup/vite/plugins/expose-id-utils.d.ts +0 -37
- package/dist/types.backup/vite/plugins/expose-ids/export-analysis.d.ts +0 -19
- package/dist/types.backup/vite/plugins/expose-ids/handler-transform.d.ts +0 -10
- package/dist/types.backup/vite/plugins/expose-ids/loader-transform.d.ts +0 -8
- package/dist/types.backup/vite/plugins/expose-ids/router-transform.d.ts +0 -13
- package/dist/types.backup/vite/plugins/expose-ids/types.d.ts +0 -29
- package/dist/types.backup/vite/plugins/expose-internal-ids.d.ts +0 -6
- package/dist/types.backup/vite/plugins/performance-tracks.d.ts +0 -25
- package/dist/types.backup/vite/plugins/refresh-cmd.d.ts +0 -20
- package/dist/types.backup/vite/plugins/use-cache-transform.d.ts +0 -20
- package/dist/types.backup/vite/plugins/vercel-output.d.ts +0 -85
- package/dist/types.backup/vite/plugins/version-injector.d.ts +0 -21
- package/dist/types.backup/vite/plugins/version-plugin.d.ts +0 -19
- package/dist/types.backup/vite/plugins/virtual-entries.d.ts +0 -36
- package/dist/types.backup/vite/plugins/virtual-stub-plugin.d.ts +0 -7
- package/dist/types.backup/vite/rango.d.ts +0 -29
- package/dist/types.backup/vite/router-discovery.d.ts +0 -23
- package/dist/types.backup/vite/utils/ast-handler-extract.d.ts +0 -64
- package/dist/types.backup/vite/utils/banner.d.ts +0 -2
- package/dist/types.backup/vite/utils/bundle-analysis.d.ts +0 -28
- package/dist/types.backup/vite/utils/client-chunks.d.ts +0 -55
- package/dist/types.backup/vite/utils/directive-prologue.d.ts +0 -16
- package/dist/types.backup/vite/utils/forward-user-plugins.d.ts +0 -37
- package/dist/types.backup/vite/utils/manifest-utils.d.ts +0 -7
- package/dist/types.backup/vite/utils/package-resolution.d.ts +0 -6
- package/dist/types.backup/vite/utils/prerender-utils.d.ts +0 -32
- package/dist/types.backup/vite/utils/shared-utils.d.ts +0 -55
|
@@ -86,7 +86,7 @@ Pass an array to run several in order. Cookies set inside middleware via the sta
|
|
|
86
86
|
|
|
87
87
|
## Caveats
|
|
88
88
|
|
|
89
|
-
- No `handles`/`rendered` option by design: middleware
|
|
89
|
+
- No `handles`/`rendered` option by design: the middleware context has no handle APIs in production — no push (`ctx.use(Handle)` is a handler/loader API) and no post-barrier read (`ctx.get(handle)` is loader-only, and middleware runs BEFORE the render barrier anyway). Read handle data in a loader and test it with `runLoader`; assert loader pushes via `runLoaderResult(...).handlePushes` (see `./handles.md`).
|
|
90
90
|
- A COMPONENT route's guard stack cannot be exercised through `dispatch` (it throws on component routes), and `renderToFlightString`/`renderRoute` don't run route middleware. Extract the middleware fn and unit-test it here, or assert the guard stack at e2e.
|
|
91
91
|
- Middleware-phase `ctx.reverse` is map-only (no auto-fill from current params), matching production — enable it with `routeMap`. `routeName` only feeds `ctx.routeName`; it does NOT scope `.name` reverse (the chain reverse stays map-only by design).
|
|
92
92
|
- `ctx.theme` is `undefined` unless `theme` is passed; `redirect()` does no basename prefixing unless `basename` is seeded.
|
package/skills/theme/SKILL.md
CHANGED
|
@@ -33,16 +33,15 @@ const router = createRouter<Env>({
|
|
|
33
33
|
});
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
## Server (in
|
|
36
|
+
## Server (in handlers/middleware)
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
|
-
import { createLoader } from "@rangojs/router";
|
|
40
39
|
import type { Middleware } from "@rangojs/router";
|
|
41
40
|
|
|
42
|
-
// In a
|
|
43
|
-
|
|
41
|
+
// In a handler
|
|
42
|
+
path("/settings", (ctx) => {
|
|
44
43
|
const currentTheme = ctx.theme; // read from cookie
|
|
45
|
-
return
|
|
44
|
+
return <SettingsPage theme={currentTheme} />;
|
|
46
45
|
});
|
|
47
46
|
|
|
48
47
|
// In middleware
|
|
@@ -53,6 +52,10 @@ export const themeMiddleware: Middleware = async (ctx, next) => {
|
|
|
53
52
|
};
|
|
54
53
|
```
|
|
55
54
|
|
|
55
|
+
Theme accessors are handler/middleware-only — the loader context has no
|
|
56
|
+
`ctx.theme`/`ctx.setTheme`. A loader that needs the theme reads the cookie
|
|
57
|
+
directly via `cookies()` (loaders always run fresh, so the read is safe).
|
|
58
|
+
|
|
56
59
|
## Client
|
|
57
60
|
|
|
58
61
|
```tsx
|
|
@@ -38,11 +38,11 @@ available globally.
|
|
|
38
38
|
There are three distinct typing surfaces. They are **not** interchangeable —
|
|
39
39
|
pick the one that matches what you need to type:
|
|
40
40
|
|
|
41
|
-
| Surface | Source
|
|
42
|
-
| ------------------- |
|
|
43
|
-
| `GeneratedRouteMap` | `router.named-routes.gen.ts` (auto)
|
|
44
|
-
| `routes` | per-module `*.gen.ts` (`rango generate`)
|
|
45
|
-
| `RegisteredRoutes` | manual `extends typeof router.routeMap`
|
|
41
|
+
| Surface | Source | Scope | Gives | Does not give |
|
|
42
|
+
| ------------------- | ---------------------------------------------------- | ------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
43
|
+
| `GeneratedRouteMap` | `router.named-routes.gen.ts` (auto) | global | route names, path params, search schemas | response/MIME payloads |
|
|
44
|
+
| `routes` | per-module `*.gen.ts` (`rango generate`) | local | local names, params, search | the global app map |
|
|
45
|
+
| `RegisteredRoutes` | manual `extends` of a `typeof router.routeMap` alias | global | paths, params, **response payloads** | the `Handler`/`Prerender` default (those read `GeneratedRouteMap` to avoid a `router.tsx` cycle) |
|
|
46
46
|
|
|
47
47
|
Key consequence: `href()` and the ambient `Rango.Path` type are typed from
|
|
48
48
|
whichever map is present — they prefer `RegisteredRoutes` when you wire it, otherwise fall back to
|
|
@@ -63,11 +63,15 @@ import type { AppBindings, AppVars } from "./env";
|
|
|
63
63
|
|
|
64
64
|
export const router = createRouter<AppBindings>({}).routes(urlpatterns);
|
|
65
65
|
|
|
66
|
+
// The alias is required: an interface heritage clause cannot take a `typeof`
|
|
67
|
+
// type query directly (TS1109).
|
|
68
|
+
type AppRoutes = typeof router.routeMap;
|
|
69
|
+
|
|
66
70
|
declare global {
|
|
67
71
|
namespace Rango {
|
|
68
72
|
interface Env extends AppBindings {}
|
|
69
73
|
interface Vars extends AppVars {}
|
|
70
|
-
interface RegisteredRoutes extends
|
|
74
|
+
interface RegisteredRoutes extends AppRoutes {}
|
|
71
75
|
}
|
|
72
76
|
}
|
|
73
77
|
```
|
|
@@ -257,10 +261,12 @@ export const router = createRouter<ShopEnv>({ document: Document }).routes(
|
|
|
257
261
|
urlpatterns,
|
|
258
262
|
);
|
|
259
263
|
|
|
264
|
+
type ShopRoutes = typeof router.routeMap;
|
|
265
|
+
|
|
260
266
|
declare global {
|
|
261
267
|
namespace Rango {
|
|
262
268
|
interface Env extends ShopEnv {}
|
|
263
|
-
interface RegisteredRoutes extends
|
|
269
|
+
interface RegisteredRoutes extends ShopRoutes {}
|
|
264
270
|
}
|
|
265
271
|
}
|
|
266
272
|
```
|
|
@@ -312,8 +318,9 @@ export default router;
|
|
|
312
318
|
// router.named-routes.gen.ts (auto-registers GeneratedRouteMap globally).
|
|
313
319
|
// No manual RegisteredRoutes declaration is needed for named-route handlers,
|
|
314
320
|
// ctx.reverse, prerender, href(), or Rango.Path. Add `RegisteredRoutes
|
|
315
|
-
// extends typeof router.routeMap
|
|
316
|
-
// as Rango.PathResponse need the richer
|
|
321
|
+
// extends AppRoutes` (an alias of typeof router.routeMap) when global
|
|
322
|
+
// response payload helpers such as Rango.PathResponse need the richer
|
|
323
|
+
// router.routeMap metadata.
|
|
317
324
|
|
|
318
325
|
// 5. loaders/*.ts - Type-safe loaders
|
|
319
326
|
export const ProductLoader = createLoader(async (ctx) => {
|
|
@@ -76,9 +76,13 @@ below is only needed for **`Rango.PathResponse`** (response-payload inference),
|
|
|
76
76
|
`GeneratedRouteMap` cannot provide:
|
|
77
77
|
|
|
78
78
|
```typescript
|
|
79
|
+
// The alias is required: an interface heritage clause cannot take a `typeof`
|
|
80
|
+
// type query directly (TS1109).
|
|
81
|
+
type AppRoutes = typeof router.routeMap;
|
|
82
|
+
|
|
79
83
|
declare global {
|
|
80
84
|
namespace Rango {
|
|
81
|
-
interface RegisteredRoutes extends
|
|
85
|
+
interface RegisteredRoutes extends AppRoutes {}
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
88
|
```
|
|
@@ -307,6 +307,53 @@ intercept("@modal", ".product", async (ctx) => {
|
|
|
307
307
|
}),
|
|
308
308
|
```
|
|
309
309
|
|
|
310
|
+
## Embedding server actions in cached components
|
|
311
|
+
|
|
312
|
+
A cached function may return a component that creates an inline `"use server"`
|
|
313
|
+
action. The canonical case is a cached list whose items each carry an action --
|
|
314
|
+
e.g. a cached article list where every row has a like button:
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
export async function ArticleList() {
|
|
318
|
+
"use cache: articles";
|
|
319
|
+
const articles = await db.query("SELECT id, title FROM articles");
|
|
320
|
+
return (
|
|
321
|
+
<ul>
|
|
322
|
+
{articles.map((a) => {
|
|
323
|
+
const articleId = a.id; // captured -> frozen with the cache entry
|
|
324
|
+
async function like() {
|
|
325
|
+
"use server";
|
|
326
|
+
// runs live on click, in the CURRENT request scope
|
|
327
|
+
const user = cookies().get("session")?.value;
|
|
328
|
+
if (user) await db.like(articleId, user);
|
|
329
|
+
}
|
|
330
|
+
return <LikeButton key={a.id} title={a.title} action={like} />;
|
|
331
|
+
})}
|
|
332
|
+
</ul>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Three behaviors, locked by `use-cache-inline-action.test.ts` (dev + prod):
|
|
338
|
+
|
|
339
|
+
| What | Behavior | Why |
|
|
340
|
+
| ----------------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
341
|
+
| Values the action **closes over** (`articleId`) | **Frozen** at cache-write | The closure compiles to encrypted bound args, snapshotted when the entry is written and replayed verbatim on a hit. Correct for stable identities; wrong for volatile values. |
|
|
342
|
+
| The action **body** | **Runs live** every call | Once invoked it is an ordinary server function: fresh computation and live request context. `cookies()` / `headers()` work here (the body executes in the live request). |
|
|
343
|
+
| Invocability on a **cache hit** | **Works** | The action survives serialize -> cache -> deserialize and stays callable. |
|
|
344
|
+
|
|
345
|
+
Rule of thumb: **capture stable identities, read volatile/request-scoped values
|
|
346
|
+
live in the body.** Do not close over a per-request token, the current user, or
|
|
347
|
+
the current time and expect freshness -- those are frozen at cache-write. The
|
|
348
|
+
`cookies()`/`headers()` read guard applies to the cached function body, NOT to an
|
|
349
|
+
inline action's body.
|
|
350
|
+
|
|
351
|
+
Deploy note: captured values are encrypted with a per-build key by default. If
|
|
352
|
+
cache entries can outlive a deploy (a persistent store such as the Cloudflare
|
|
353
|
+
cache store), set `RANGO_ENCRYPTION_KEY` (base64-encoded 32 bytes) in the build
|
|
354
|
+
environment so actions embedded in entries written by a previous deploy still
|
|
355
|
+
decrypt; without it they fail until the entry expires or revalidates.
|
|
356
|
+
|
|
310
357
|
## Vite Transform
|
|
311
358
|
|
|
312
359
|
The `rango:use-cache` Vite plugin detects the directive and wraps exports with
|
package/src/bin/rango.ts
CHANGED
|
@@ -144,7 +144,10 @@ function runStaticGeneration(args: string[], mode: "default" | "static") {
|
|
|
144
144
|
if (/\bcreateRouter\s*[<(]/.test(source)) {
|
|
145
145
|
routerFiles.push(filePath);
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
// Both spellings, matching the writer's own gate: "clientUrls(" does
|
|
148
|
+
// NOT contain the lowercase "urls(" token (capital U), so a
|
|
149
|
+
// clientUrls-only module fails the server-token sniff alone.
|
|
150
|
+
if (source.includes("urls(") || source.includes("clientUrls(")) {
|
|
148
151
|
urlsFiles.push(filePath);
|
|
149
152
|
}
|
|
150
153
|
} catch (err) {
|
|
@@ -255,8 +258,9 @@ async function runRuntimeDiscovery(args: string[], configFile?: string) {
|
|
|
255
258
|
if (/\bcreateRouter\s*[<(]/.test(source)) {
|
|
256
259
|
routerEntries.push(filePath);
|
|
257
260
|
}
|
|
258
|
-
// Also generate per-module types for urls files
|
|
259
|
-
|
|
261
|
+
// Also generate per-module types for urls files. Both spellings — a
|
|
262
|
+
// clientUrls-only module has no lowercase "urls(" token (capital U).
|
|
263
|
+
if (source.includes("urls(") || source.includes("clientUrls(")) {
|
|
260
264
|
writePerModuleRouteTypesForFile(filePath);
|
|
261
265
|
}
|
|
262
266
|
} catch {
|
|
@@ -234,6 +234,12 @@ export interface EventController {
|
|
|
234
234
|
listener: ActionStateListener,
|
|
235
235
|
): () => void;
|
|
236
236
|
subscribeToHandles(listener: HandleListener): () => void;
|
|
237
|
+
/**
|
|
238
|
+
* Deliver queued location, params, navigation, and handle notifications now.
|
|
239
|
+
* NavigationProvider calls this inside the payload update so React assigns
|
|
240
|
+
* every route-state hook update to the same normal or transition lane.
|
|
241
|
+
*/
|
|
242
|
+
flushRouteState(): void;
|
|
237
243
|
|
|
238
244
|
// Handle operations
|
|
239
245
|
setHandleData(
|
|
@@ -367,19 +373,32 @@ function matchesActionId(
|
|
|
367
373
|
return entryActionId.endsWith(`#${subscriptionId}`);
|
|
368
374
|
}
|
|
369
375
|
|
|
370
|
-
|
|
371
|
-
|
|
376
|
+
interface DebouncedNotifier {
|
|
377
|
+
schedule(): void;
|
|
378
|
+
flush(): void;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Batch rapid notifications into one task to prevent render storms. The
|
|
382
|
+
// explicit flush lets a React update owner preserve its scheduling lane.
|
|
383
|
+
function makeDebouncedNotifier(listeners: Set<() => void>): DebouncedNotifier {
|
|
372
384
|
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
373
|
-
|
|
374
|
-
if (timeout
|
|
375
|
-
timeout
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
385
|
+
const flush = () => {
|
|
386
|
+
if (timeout === null) return;
|
|
387
|
+
clearTimeout(timeout);
|
|
388
|
+
timeout = null;
|
|
389
|
+
notifyListeners(
|
|
390
|
+
[...listeners],
|
|
391
|
+
(listener) => listener(),
|
|
392
|
+
(listener) => listeners.has(listener),
|
|
393
|
+
);
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
schedule() {
|
|
398
|
+
if (timeout !== null) clearTimeout(timeout);
|
|
399
|
+
timeout = setTimeout(flush, 0);
|
|
400
|
+
},
|
|
401
|
+
flush,
|
|
383
402
|
};
|
|
384
403
|
}
|
|
385
404
|
|
|
@@ -459,7 +478,7 @@ export function createEventController(
|
|
|
459
478
|
|
|
460
479
|
function notify(): void {
|
|
461
480
|
cachedDerivedState = null;
|
|
462
|
-
notifyStateListeners();
|
|
481
|
+
notifyStateListeners.schedule();
|
|
463
482
|
}
|
|
464
483
|
|
|
465
484
|
const actionNotifyTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
|
@@ -517,6 +536,11 @@ export function createEventController(
|
|
|
517
536
|
|
|
518
537
|
const notifyHandles = makeDebouncedNotifier(handleListeners);
|
|
519
538
|
|
|
539
|
+
function flushRouteState(): void {
|
|
540
|
+
notifyStateListeners.flush();
|
|
541
|
+
notifyHandles.flush();
|
|
542
|
+
}
|
|
543
|
+
|
|
520
544
|
function getState(): DerivedNavigationState {
|
|
521
545
|
if (cachedDerivedState) return cachedDerivedState;
|
|
522
546
|
|
|
@@ -1001,7 +1025,7 @@ export function createEventController(
|
|
|
1001
1025
|
handleSegmentOrder = newSegmentOrder;
|
|
1002
1026
|
routeSegmentIds = newRouteSegmentIds;
|
|
1003
1027
|
|
|
1004
|
-
notifyHandles();
|
|
1028
|
+
notifyHandles.schedule();
|
|
1005
1029
|
}
|
|
1006
1030
|
|
|
1007
1031
|
function getHandleState(): HandleState {
|
|
@@ -1021,7 +1045,7 @@ export function createEventController(
|
|
|
1021
1045
|
return;
|
|
1022
1046
|
}
|
|
1023
1047
|
routeSegmentIds = next;
|
|
1024
|
-
notifyHandles();
|
|
1048
|
+
notifyHandles.schedule();
|
|
1025
1049
|
}
|
|
1026
1050
|
|
|
1027
1051
|
// ========================================================================
|
|
@@ -1102,6 +1126,7 @@ export function createEventController(
|
|
|
1102
1126
|
subscribe,
|
|
1103
1127
|
subscribeToAction,
|
|
1104
1128
|
subscribeToHandles,
|
|
1129
|
+
flushRouteState,
|
|
1105
1130
|
|
|
1106
1131
|
// Direct access
|
|
1107
1132
|
getCurrentNavigation: () => currentNavigation,
|
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
schedulePrefetchWhenRouterIdle,
|
|
49
49
|
} from "./prefetch/loader.js";
|
|
50
50
|
import type { PrefetchStrategy } from "../router/prefetch-default.js";
|
|
51
|
+
import { beginClientUrlNavigation } from "../client-urls/navigation.js";
|
|
51
52
|
|
|
52
53
|
// Polyfill Symbol.dispose for Safari and older browsers
|
|
53
54
|
if (typeof Symbol.dispose === "undefined") {
|
|
@@ -342,6 +343,10 @@ export function createNavigationBridge(
|
|
|
342
343
|
state: resolvedState,
|
|
343
344
|
skipLoadingState: false,
|
|
344
345
|
});
|
|
346
|
+
const clientUrlPresentation = beginClientUrlNavigation(
|
|
347
|
+
targetUrl,
|
|
348
|
+
tx.handle.signal,
|
|
349
|
+
);
|
|
345
350
|
|
|
346
351
|
// REVALIDATE: Fetch fresh data from server
|
|
347
352
|
try {
|
|
@@ -422,6 +427,7 @@ export function createNavigationBridge(
|
|
|
422
427
|
console.error("[Browser] Unprocessable navigation response:", error);
|
|
423
428
|
emitNavigationError(onUpdate, error, url);
|
|
424
429
|
} finally {
|
|
430
|
+
clientUrlPresentation?.clear();
|
|
425
431
|
tx[Symbol.dispose]();
|
|
426
432
|
}
|
|
427
433
|
},
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./logging.js";
|
|
15
15
|
import { getRangoState } from "./rango-state.js";
|
|
16
16
|
import { isActionFenceActive } from "./action-fence.js";
|
|
17
|
+
import { CLIENT_REVALIDATION_HEADER } from "../client-urls/revalidation-protocol.js";
|
|
17
18
|
import {
|
|
18
19
|
expandPayloadFragments,
|
|
19
20
|
SEGMENT_FRAGMENT_CAPABILITY_HEADER,
|
|
@@ -79,6 +80,7 @@ export function createNavigationClient(
|
|
|
79
80
|
previousUrl,
|
|
80
81
|
signal,
|
|
81
82
|
staleRevalidation,
|
|
83
|
+
clientRevalidation,
|
|
82
84
|
interceptSourceUrl,
|
|
83
85
|
version,
|
|
84
86
|
routerId,
|
|
@@ -261,6 +263,9 @@ export function createNavigationClient(
|
|
|
261
263
|
...(fragmentRecovery && {
|
|
262
264
|
[SEGMENT_FRAGMENT_RECOVERY_HEADER]: "1",
|
|
263
265
|
}),
|
|
266
|
+
...(clientRevalidation && {
|
|
267
|
+
[CLIENT_REVALIDATION_HEADER]: clientRevalidation,
|
|
268
|
+
}),
|
|
264
269
|
...(tx && { "X-RSC-Router-Request-Id": tx.requestId }),
|
|
265
270
|
...(interceptSourceUrl && {
|
|
266
271
|
"X-RSC-Router-Intercept-Source": interceptSourceUrl,
|
|
@@ -30,6 +30,10 @@ import {
|
|
|
30
30
|
validateExternalRedirect,
|
|
31
31
|
} from "./validate-redirect-origin.js";
|
|
32
32
|
import type { NavigationUpdate } from "./types.js";
|
|
33
|
+
import {
|
|
34
|
+
collectClientRevalidationDecisions,
|
|
35
|
+
setActiveInterceptTargets,
|
|
36
|
+
} from "../client-urls/navigation.js";
|
|
33
37
|
|
|
34
38
|
function toScrollPayload(
|
|
35
39
|
scroll: boolean | undefined,
|
|
@@ -187,6 +191,22 @@ export function createPartialUpdater(
|
|
|
187
191
|
);
|
|
188
192
|
}
|
|
189
193
|
|
|
194
|
+
// Client-run per-loader revalidation: execute the held clientUrls route's
|
|
195
|
+
// revalidate() predicates now and ship their decisions with the request.
|
|
196
|
+
// Fails soft to null (locked server defaults) when no group is active or
|
|
197
|
+
// URLs do not parse.
|
|
198
|
+
let clientRevalidation: string | null = null;
|
|
199
|
+
try {
|
|
200
|
+
clientRevalidation = collectClientRevalidationDecisions({
|
|
201
|
+
currentUrl: new URL(previousUrl, window.location.origin),
|
|
202
|
+
nextUrl: new URL(url, window.location.origin),
|
|
203
|
+
isAction: false,
|
|
204
|
+
stale: mode.type === "stale-revalidation",
|
|
205
|
+
});
|
|
206
|
+
} catch {
|
|
207
|
+
clientRevalidation = null;
|
|
208
|
+
}
|
|
209
|
+
|
|
190
210
|
let fetchResult: Awaited<ReturnType<NavigationClient["fetchPartial"]>>;
|
|
191
211
|
fetchResult = await client.fetchPartial({
|
|
192
212
|
targetUrl: url,
|
|
@@ -194,6 +214,7 @@ export function createPartialUpdater(
|
|
|
194
214
|
previousUrl,
|
|
195
215
|
staleRevalidation:
|
|
196
216
|
mode.type === "stale-revalidation" || segments.length === 0,
|
|
217
|
+
clientRevalidation,
|
|
197
218
|
version: getVersion(),
|
|
198
219
|
routerId: store.getRouterId?.(),
|
|
199
220
|
});
|
|
@@ -421,10 +442,8 @@ export function createPartialUpdater(
|
|
|
421
442
|
// forceAwait unwraps the ROUTER loader promises during render so they
|
|
422
443
|
// land without a loading()/fallback frame. A fully-prefetched nav has
|
|
423
444
|
// its router data already resolved (the prefetch stream drained), so
|
|
424
|
-
// awaiting it here is free
|
|
425
|
-
//
|
|
426
|
-
// CLIENT component that suspends on mount, which a transition would
|
|
427
|
-
// wrongly suppress by holding the old UI until that suspense settles.
|
|
445
|
+
// awaiting it here is free; the commit below then runs in a transition
|
|
446
|
+
// (fullyPrefetched branch) so nothing router-owned can flash.
|
|
428
447
|
forceAwait: mode.type === "stale-revalidation" || fullyPrefetched,
|
|
429
448
|
interceptSegments:
|
|
430
449
|
reconciled.interceptSegments.length > 0
|
|
@@ -469,6 +488,23 @@ export function createPartialUpdater(
|
|
|
469
488
|
payload.metadata?.slots,
|
|
470
489
|
);
|
|
471
490
|
|
|
491
|
+
// Same-structure revalidation: every segment this commit will render
|
|
492
|
+
// already exists on screen (by id) — the navigation mounts nothing new,
|
|
493
|
+
// it only refreshes what the user is looking at. The hold this enables
|
|
494
|
+
// manifests on SEARCH-only navs (filters, tabs — search is never in the
|
|
495
|
+
// segment key, so the subtree reconciles); a PARAM nav outside a
|
|
496
|
+
// transition() scope still remounts via its param-bearing key
|
|
497
|
+
// (segment-system.tsx) and reveals its fresh skeleton inside the
|
|
498
|
+
// transition, unchanged. Compared against the CURRENT page's cache, not
|
|
499
|
+
// cachedSegs: for a popstate restore cachedSegs is the TARGET's history
|
|
500
|
+
// cache, which says nothing about what is visible now. Restricted to
|
|
501
|
+
// plain navigations — leave-intercept must close its modal urgently,
|
|
502
|
+
// and action/stale modes have their own transition branch.
|
|
503
|
+
const onScreenIds = new Set(getCurrentCachedSegments().map((s) => s.id));
|
|
504
|
+
const isSameStructureNav =
|
|
505
|
+
mode.type === "navigate" &&
|
|
506
|
+
reconciled.segments.every((s) => onScreenIds.has(s.id));
|
|
507
|
+
|
|
472
508
|
const effectiveInterceptSource =
|
|
473
509
|
interceptSourceUrl || segmentState.currentUrl;
|
|
474
510
|
if (mode.type !== "action" && mode.type !== "stale-revalidation") {
|
|
@@ -525,6 +561,13 @@ export function createPartialUpdater(
|
|
|
525
561
|
all: reconciled.segments.map((s) => s.id),
|
|
526
562
|
});
|
|
527
563
|
}
|
|
564
|
+
// Refresh the browser-local intercept-target set for the location being
|
|
565
|
+
// committed — the clientUrls matcher declines optimistic presentation
|
|
566
|
+
// for targets an intercept would claim from here. Back/forward commits
|
|
567
|
+
// served purely from the history cache keep the previous set (no fresh
|
|
568
|
+
// metadata); popstate navigations get no optimistic presentation anyway.
|
|
569
|
+
setActiveInterceptTargets(payload.metadata?.interceptTargets);
|
|
570
|
+
|
|
528
571
|
const scrollPayload = toScrollPayload(navScroll);
|
|
529
572
|
|
|
530
573
|
if (mode.type === "action" || mode.type === "stale-revalidation") {
|
|
@@ -549,13 +592,37 @@ export function createPartialUpdater(
|
|
|
549
592
|
scroll: scrollPayload,
|
|
550
593
|
});
|
|
551
594
|
});
|
|
595
|
+
} else if (fullyPrefetched || isSameStructureNav) {
|
|
596
|
+
// Content-hold commit, two triggers. Fully-prefetched nav: the payload
|
|
597
|
+
// is fully resolved (forceAwait above), so the transition commits
|
|
598
|
+
// synchronously — no fallback flash. Same-structure nav: the re-run
|
|
599
|
+
// loaders are still streaming, and an urgent commit would re-suspend
|
|
600
|
+
// the ALREADY-REVEALED boundaries — replacing visible content with its
|
|
601
|
+
// own fallback for the loader's full duration (the PLP filter-change
|
|
602
|
+
// flash). Inside a transition React holds the current UI until the
|
|
603
|
+
// suspended data lands, the action treatment; nothing new mounts (by
|
|
604
|
+
// the isSameStructureNav definition), so no fallback is being withheld
|
|
605
|
+
// from a first paint. No addTransitionType: this is the React
|
|
606
|
+
// content-hold, not a view transition. Deliberate trade-off (#622
|
|
607
|
+
// introduced, #624 reverted, then reinstated): a client component that
|
|
608
|
+
// suspends during its FIRST render (use() of a promise created at
|
|
609
|
+
// mount — see ClientMountSuspense in the e2e test-app) under an
|
|
610
|
+
// ALREADY-REVEALED boundary holds the old content until it resolves
|
|
611
|
+
// instead of revealing that boundary's fallback; its render happens
|
|
612
|
+
// pre-commit inside the transition, so userland effects cannot run
|
|
613
|
+
// first. Boundaries newly mounted by this nav still reveal their
|
|
614
|
+
// fallbacks (React shows new boundaries inside transitions).
|
|
615
|
+
startTransition(() => {
|
|
616
|
+
onUpdate({
|
|
617
|
+
root: newTree,
|
|
618
|
+
metadata: payload.metadata!,
|
|
619
|
+
scroll: scrollPayload,
|
|
620
|
+
});
|
|
621
|
+
});
|
|
552
622
|
} else {
|
|
553
|
-
//
|
|
554
|
-
//
|
|
555
|
-
//
|
|
556
|
-
// every suspense in the new tree settles — including a client
|
|
557
|
-
// component that only starts fetching post-mount, retaining the
|
|
558
|
-
// previous page indefinitely. Explicit transition() routes keep the
|
|
623
|
+
// Cold/partially-prefetched nav that mounts NEW segments: normal
|
|
624
|
+
// commit so fallbacks stream like a first load and the click has
|
|
625
|
+
// visible feedback. Explicit transition() routes keep the
|
|
559
626
|
// content-hold via the hasTransition branch above (the opt-in).
|
|
560
627
|
onUpdate({
|
|
561
628
|
root: newTree,
|
|
@@ -456,6 +456,13 @@ export function NavigationProvider({
|
|
|
456
456
|
cached === undefined ? update.metadata.resolvedIds : undefined,
|
|
457
457
|
);
|
|
458
458
|
}
|
|
459
|
+
|
|
460
|
+
// tx.commit() and the metadata updates above mutate the controller
|
|
461
|
+
// synchronously, but its ordinary notifications are task-debounced. Flush
|
|
462
|
+
// them here so hook setState calls inherit this payload update's lane. In
|
|
463
|
+
// a transition that suspends, the source tree therefore keeps its source
|
|
464
|
+
// pathname/params until the destination payload commits with them.
|
|
465
|
+
eventController.flushRouteState();
|
|
459
466
|
});
|
|
460
467
|
|
|
461
468
|
return unsubscribe;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useContext, useMemo } from "react";
|
|
4
4
|
import { NavigationStoreContext } from "./context.js";
|
|
5
|
+
import { useMount } from "./use-mount.js";
|
|
5
6
|
import { prefetchDirect } from "../prefetch/loader.js";
|
|
6
7
|
import { getAppVersion } from "../app-version.js";
|
|
7
8
|
import type { RouterInstance, RouterNavigateOptions } from "../types.js";
|
|
@@ -9,8 +10,8 @@ import type { RouterInstance, RouterNavigateOptions } from "../types.js";
|
|
|
9
10
|
/**
|
|
10
11
|
* Hook to access router actions (push, replace, refresh, prefetch, back, forward).
|
|
11
12
|
*
|
|
12
|
-
* Returns a STABLE reference
|
|
13
|
-
*
|
|
13
|
+
* Returns a STABLE reference per component, so components using useRouter()
|
|
14
|
+
* do not re-render on navigation state changes.
|
|
14
15
|
* For reactive navigation state, use useNavigation() instead.
|
|
15
16
|
*
|
|
16
17
|
* Methods read `basename` from the context on each call. It is set once from
|
|
@@ -18,10 +19,17 @@ import type { RouterInstance, RouterNavigateOptions } from "../types.js";
|
|
|
18
19
|
* is a full document load (X-RSC-Reload), so the target app mounts fresh with
|
|
19
20
|
* its own basename.
|
|
20
21
|
*
|
|
22
|
+
* RELATIVE paths (no leading `/`, no scheme/query/hash) resolve against the
|
|
23
|
+
* current include() mount: `router.push("cart")` inside `include("/shop")`
|
|
24
|
+
* navigates to `/shop/cart`. Absolute paths stay APP-absolute — unlike
|
|
25
|
+
* basename, the mount is scoped, and absolute pushes legitimately target
|
|
26
|
+
* outside it, so they are never auto-prefixed.
|
|
27
|
+
*
|
|
21
28
|
* @example
|
|
22
29
|
* ```tsx
|
|
23
30
|
* const router = useRouter();
|
|
24
|
-
* router.push("/products");
|
|
31
|
+
* router.push("/products"); // app-absolute
|
|
32
|
+
* router.push("cart"); // mount-relative
|
|
25
33
|
* router.replace("/login", { scroll: false });
|
|
26
34
|
* router.prefetch("/dashboard");
|
|
27
35
|
* router.back();
|
|
@@ -29,15 +37,17 @@ import type { RouterInstance, RouterNavigateOptions } from "../types.js";
|
|
|
29
37
|
*/
|
|
30
38
|
export function useRouter(): RouterInstance {
|
|
31
39
|
const ctx = useContext(NavigationStoreContext);
|
|
40
|
+
const mount = useMount();
|
|
32
41
|
|
|
33
42
|
if (!ctx) {
|
|
34
43
|
throw new Error("useRouter must be used within NavigationProvider");
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
// Stable reference: ctx
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
46
|
+
// Stable reference per component: ctx is stable and mount is a static
|
|
47
|
+
// property of the component's position in the tree; reads on each method
|
|
48
|
+
// call pick up live basename values from the context (backed by a live
|
|
49
|
+
// ref in NavigationProvider), so app-switch transitions are reflected
|
|
50
|
+
// without recreating this object.
|
|
41
51
|
return useMemo<RouterInstance>(() => {
|
|
42
52
|
/** Prefix a root-relative path with basename if not already prefixed. */
|
|
43
53
|
function withBasename(url: string): string {
|
|
@@ -47,13 +57,32 @@ export function useRouter(): RouterInstance {
|
|
|
47
57
|
return url === "/" ? bn : bn + url;
|
|
48
58
|
}
|
|
49
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a navigation/prefetch target. RELATIVE paths — a leading word
|
|
62
|
+
* character or `./`, never a scheme (`http:`, `mailto:`), query, or
|
|
63
|
+
* hash form — join onto the include mount and then take the basename
|
|
64
|
+
* pass like any root-relative path. Everything else passes through
|
|
65
|
+
* unchanged.
|
|
66
|
+
*/
|
|
67
|
+
function resolveTarget(url: string): string {
|
|
68
|
+
const relative = url.startsWith("./") ? url.slice(2) : url;
|
|
69
|
+
if (
|
|
70
|
+
!/^[A-Za-z0-9]/.test(relative) ||
|
|
71
|
+
/^[a-z][a-z0-9+.-]*:/i.test(relative)
|
|
72
|
+
) {
|
|
73
|
+
return withBasename(url);
|
|
74
|
+
}
|
|
75
|
+
const base = mount === "/" ? "" : mount.replace(/\/$/, "");
|
|
76
|
+
return withBasename(`${base}/${relative}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
50
79
|
return {
|
|
51
80
|
push(url: string, options?: RouterNavigateOptions): Promise<void> {
|
|
52
|
-
return ctx.navigate(
|
|
81
|
+
return ctx.navigate(resolveTarget(url), { ...options, replace: false });
|
|
53
82
|
},
|
|
54
83
|
|
|
55
84
|
replace(url: string, options?: RouterNavigateOptions): Promise<void> {
|
|
56
|
-
return ctx.navigate(
|
|
85
|
+
return ctx.navigate(resolveTarget(url), { ...options, replace: true });
|
|
57
86
|
},
|
|
58
87
|
|
|
59
88
|
refresh(): Promise<void> {
|
|
@@ -64,7 +93,7 @@ export function useRouter(): RouterInstance {
|
|
|
64
93
|
const segmentState = ctx.store?.getSegmentState();
|
|
65
94
|
if (segmentState) {
|
|
66
95
|
prefetchDirect(
|
|
67
|
-
|
|
96
|
+
resolveTarget(url),
|
|
68
97
|
segmentState.currentSegmentIds,
|
|
69
98
|
getAppVersion(),
|
|
70
99
|
ctx.store?.getRouterId?.(),
|
|
@@ -94,5 +123,5 @@ export function useRouter(): RouterInstance {
|
|
|
94
123
|
window.history.forward();
|
|
95
124
|
},
|
|
96
125
|
};
|
|
97
|
-
}, []);
|
|
126
|
+
}, [mount]);
|
|
98
127
|
}
|