@rangojs/router 0.0.0-experimental.bd6e11bc → 0.0.0-experimental.bdaf10aa
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 +8 -4
- package/README.md +296 -887
- package/dist/bin/rango.js +459 -91
- package/dist/testing/vitest.js +36 -2
- package/dist/vite/index.js +1708 -414
- package/package.json +35 -10
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +82 -5
- package/skills/bundle-analysis/SKILL.md +2 -2
- package/skills/cache-guide/SKILL.md +14 -9
- package/skills/caching/SKILL.md +221 -12
- package/skills/catalog.json +271 -0
- 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 +83 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +5 -3
- package/skills/defer-hydration/SKILL.md +235 -0
- package/skills/document-cache/SKILL.md +11 -3
- package/skills/fonts/SKILL.md +1 -1
- package/skills/handler-use/SKILL.md +9 -9
- package/skills/hooks/SKILL.md +73 -900
- package/skills/hooks/data.md +273 -0
- package/skills/hooks/handle-and-actions.md +103 -0
- package/skills/hooks/navigation.md +110 -0
- package/skills/hooks/outlets.md +41 -0
- package/skills/hooks/state.md +228 -0
- package/skills/hooks/urls.md +135 -0
- package/skills/host-router/SKILL.md +84 -7
- package/skills/i18n/SKILL.md +1 -1
- package/skills/intercept/SKILL.md +51 -17
- package/skills/layout/SKILL.md +38 -16
- package/skills/links/SKILL.md +1 -1
- package/skills/loader/SKILL.md +48 -20
- package/skills/middleware/SKILL.md +11 -5
- package/skills/migrate-nextjs/SKILL.md +203 -20
- package/skills/migrate-react-router/SKILL.md +59 -675
- package/skills/migrate-react-router/cloudflare-workers.md +129 -0
- package/skills/migrate-react-router/component-migration.md +196 -0
- package/skills/migrate-react-router/data-and-actions.md +225 -0
- package/skills/migrate-react-router/route-mapping.md +271 -0
- package/skills/mime-routes/SKILL.md +3 -3
- package/skills/observability/SKILL.md +70 -5
- package/skills/parallel/SKILL.md +32 -8
- package/skills/ppr/SKILL.md +622 -0
- package/skills/prerender/SKILL.md +59 -28
- package/skills/rango/SKILL.md +124 -50
- package/skills/response-routes/SKILL.md +78 -46
- package/skills/route/SKILL.md +85 -6
- package/skills/router-setup/SKILL.md +41 -6
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +28 -3
- package/skills/shell-manifest/SKILL.md +185 -0
- package/skills/streams-and-websockets/SKILL.md +1 -1
- package/skills/tailwind/SKILL.md +28 -4
- package/skills/testing/SKILL.md +68 -654
- 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 +1 -1
- package/skills/typesafety/SKILL.md +45 -918
- package/skills/typesafety/env-and-bindings.md +254 -0
- package/skills/typesafety/generated-files-and-cli.md +335 -0
- package/skills/typesafety/params-and-search.md +153 -0
- package/skills/typesafety/route-types.md +209 -0
- package/skills/use-cache/SKILL.md +47 -17
- package/skills/vercel/SKILL.md +128 -0
- package/skills/view-transitions/SKILL.md +44 -1
- package/src/__augment-tests__/augmented.check.ts +2 -3
- package/src/__internal.ts +0 -65
- package/src/browser/action-coordinator.ts +1 -1
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +178 -100
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/logging.ts +28 -0
- package/src/browser/merge-segment-loaders.ts +6 -4
- package/src/browser/navigation-bridge.ts +81 -68
- package/src/browser/navigation-client.ts +115 -70
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +153 -88
- package/src/browser/navigation-transaction.ts +0 -32
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +157 -144
- package/src/browser/prefetch/cache.ts +148 -81
- package/src/browser/prefetch/fetch.ts +231 -51
- package/src/browser/prefetch/queue.ts +25 -7
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +40 -7
- package/src/browser/react/NavigationProvider.tsx +140 -99
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +17 -2
- package/src/browser/react/index.ts +0 -51
- package/src/browser/react/location-state-shared.ts +14 -15
- package/src/browser/react/location-state.ts +0 -1
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +0 -5
- package/src/browser/react/use-href.tsx +8 -1
- package/src/browser/react/use-link-status.ts +33 -8
- package/src/browser/react/use-navigation.ts +10 -5
- package/src/browser/react/use-params.ts +0 -2
- package/src/browser/react/use-router.ts +6 -4
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +0 -13
- package/src/browser/response-adapter.ts +74 -8
- package/src/browser/rsc-router.tsx +97 -22
- package/src/browser/scroll-restoration.ts +15 -8
- package/src/browser/segment-reconciler.ts +31 -21
- package/src/browser/server-action-bridge.ts +216 -38
- package/src/browser/types.ts +94 -22
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/generate-manifest.ts +155 -131
- package/src/build/generate-route-types.ts +1 -1
- package/src/build/index.ts +11 -5
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +152 -22
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +12 -1
- package/src/build/route-types/include-resolution.ts +455 -61
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +15 -2
- package/src/build/route-types/router-processing.ts +77 -41
- package/src/build/route-types/source-scan.ts +105 -7
- package/src/build/runtime-discovery.ts +4 -1
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +58 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +454 -101
- package/src/cache/cache-scope.ts +159 -54
- package/src/cache/cache-tag.ts +149 -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 +2170 -377
- 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 +6 -16
- package/src/cache/document-cache.ts +126 -41
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +23 -20
- package/src/cache/memory-segment-store.ts +243 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +13 -21
- package/src/cache/shell-snapshot.ts +417 -0
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +194 -99
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +1132 -0
- package/src/client.rsc.tsx +39 -22
- package/src/client.tsx +28 -58
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +108 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +13 -1
- package/src/decode-loader-results.ts +18 -2
- package/src/defer.ts +185 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +0 -3
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +57 -40
- package/src/handles/MetaTags.tsx +24 -53
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +35 -8
- package/src/handles/deferred-resolution.ts +127 -0
- package/src/handles/is-thenable.ts +18 -0
- package/src/handles/meta.ts +14 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +13 -22
- package/src/host/index.ts +7 -0
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +1 -65
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +6 -2
- package/src/href-client.ts +7 -12
- package/src/index.rsc.ts +88 -8
- package/src/index.ts +90 -16
- package/src/internal-debug.ts +11 -10
- package/src/loader.rsc.ts +19 -9
- package/src/loader.ts +12 -4
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +75 -7
- package/src/redirect-origin.ts +114 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +25 -0
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +13 -49
- package/src/route-definition/dsl-helpers.ts +60 -53
- package/src/route-definition/helper-factories.ts +0 -2
- package/src/route-definition/helpers-types.ts +46 -46
- package/src/route-definition/index.ts +1 -2
- package/src/route-definition/redirect.ts +44 -11
- package/src/route-definition/resolve-handler-use.ts +6 -1
- package/src/route-definition/use-item-types.ts +3 -6
- package/src/route-map-builder.ts +41 -20
- package/src/route-types.ts +0 -5
- package/src/router/content-negotiation.ts +58 -23
- package/src/router/error-handling.ts +44 -17
- package/src/router/find-match.ts +129 -30
- package/src/router/handler-context.ts +6 -1
- package/src/router/instrument.ts +355 -0
- package/src/router/intercept-resolution.ts +35 -2
- package/src/router/lazy-includes.ts +79 -56
- package/src/router/loader-resolution.ts +151 -73
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +74 -40
- package/src/router/match-api.ts +76 -52
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +181 -178
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +115 -194
- package/src/router/match-middleware/cache-store.ts +61 -50
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +0 -22
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +36 -67
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +0 -116
- package/src/router/middleware.ts +231 -120
- package/src/router/navigation-snapshot.ts +7 -56
- package/src/router/params-util.ts +23 -0
- package/src/router/parse-pattern.ts +115 -0
- package/src/router/pattern-matching.ts +99 -152
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prefetch-limits.ts +37 -0
- package/src/router/prerender-match.ts +111 -66
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +47 -42
- package/src/router/revalidation.ts +75 -81
- package/src/router/route-snapshot.ts +14 -3
- package/src/router/router-context.ts +6 -29
- package/src/router/router-interfaces.ts +70 -8
- package/src/router/router-options.ts +126 -4
- package/src/router/segment-resolution/fresh.ts +104 -80
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +155 -39
- package/src/router/segment-resolution/loader-mask.ts +60 -0
- package/src/router/segment-resolution/loader-snapshot.ts +259 -0
- package/src/router/segment-resolution/mask-nested.ts +83 -0
- package/src/router/segment-resolution/revalidation.ts +215 -304
- package/src/router/segment-resolution/static-store.ts +19 -5
- package/src/router/segment-resolution/streamed-handler-telemetry.ts +52 -0
- package/src/router/segment-resolution/view-transition-default.ts +35 -15
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +6 -5
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +54 -35
- package/src/router/telemetry-otel.ts +160 -200
- package/src/router/telemetry.ts +9 -23
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +215 -0
- package/src/router/trie-matching.ts +171 -64
- package/src/router/types.ts +1 -63
- package/src/router/url-params.ts +13 -5
- package/src/router.ts +119 -48
- package/src/rsc/full-payload.ts +70 -0
- package/src/rsc/handler-context.ts +1 -0
- package/src/rsc/handler.ts +267 -152
- package/src/rsc/helpers.ts +78 -4
- package/src/rsc/index.ts +1 -4
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +114 -38
- package/src/rsc/manifest-init.ts +29 -42
- package/src/rsc/nonce.ts +10 -1
- package/src/rsc/origin-guard.ts +11 -15
- package/src/rsc/progressive-enhancement.ts +120 -13
- package/src/rsc/redirect-guard.ts +100 -0
- package/src/rsc/response-cache-serve.ts +238 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +58 -141
- package/src/rsc/rsc-rendering.ts +492 -49
- package/src/rsc/runtime-warnings.ts +14 -0
- package/src/rsc/server-action.ts +268 -82
- package/src/rsc/shell-capture.ts +1190 -0
- package/src/rsc/shell-serve.ts +181 -0
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +45 -3
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +31 -26
- package/src/segment-loader-promise.ts +49 -4
- package/src/segment-system.tsx +260 -95
- package/src/server/context.ts +99 -9
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +125 -2
- package/src/server/handle-store.ts +21 -38
- package/src/server/loader-registry.ts +33 -42
- package/src/server/request-context.ts +379 -138
- package/src/ssr/index.tsx +491 -182
- package/src/ssr/inject-rsc-eager.ts +167 -0
- package/src/ssr/ssr-root.tsx +228 -0
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +44 -48
- package/src/testing/collect-handle.ts +14 -31
- package/src/testing/dispatch.ts +533 -160
- package/src/testing/e2e/fixture.ts +45 -11
- package/src/testing/e2e/index.ts +1 -22
- package/src/testing/e2e/matchers.ts +0 -16
- package/src/testing/e2e/parity.ts +85 -4
- package/src/testing/e2e/server.ts +12 -0
- package/src/testing/flight-matchers.ts +7 -14
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +36 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +30 -0
- package/src/testing/flight.ts +145 -70
- package/src/testing/generated-routes.ts +26 -50
- package/src/testing/index.ts +18 -19
- package/src/testing/internal/context.ts +184 -68
- 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 +134 -115
- package/src/testing/run-loader.ts +140 -51
- package/src/testing/run-middleware.ts +59 -33
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +1 -1
- package/src/testing/vitest-stubs/cloudflare-workers.ts +1 -1
- package/src/testing/vitest.ts +138 -16
- package/src/theme/ThemeProvider.tsx +56 -84
- package/src/theme/ThemeScript.tsx +7 -9
- package/src/theme/constants.ts +52 -13
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +22 -21
- package/src/theme/use-theme.ts +0 -3
- package/src/types/boundaries.ts +0 -35
- package/src/types/cache-types.ts +13 -4
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +15 -15
- package/src/types/handler-context.ts +45 -15
- package/src/types/index.ts +2 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +8 -22
- package/src/types/route-config.ts +20 -52
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +100 -13
- package/src/urls/include-helper.ts +10 -12
- package/src/urls/include-provider.ts +71 -0
- package/src/urls/index.ts +2 -8
- package/src/urls/path-helper-types.ts +52 -14
- package/src/urls/path-helper.ts +5 -54
- package/src/urls/pattern-types.ts +36 -0
- package/src/urls/type-extraction.ts +76 -42
- package/src/urls/urls-function.ts +0 -14
- package/src/use-loader.tsx +0 -186
- package/src/vercel/index.ts +11 -0
- package/src/vercel/tracing.ts +88 -0
- package/src/vite/discovery/bundle-postprocess.ts +2 -1
- package/src/vite/discovery/dev-prerender-cache.ts +117 -0
- package/src/vite/discovery/discover-routers.ts +34 -43
- package/src/vite/discovery/discovery-errors.ts +61 -0
- package/src/vite/discovery/prerender-collection.ts +33 -46
- package/src/vite/discovery/state.ts +12 -1
- package/src/vite/discovery/virtual-module-codegen.ts +1 -11
- package/src/vite/index.ts +9 -0
- package/src/vite/inject-client-debug.ts +88 -0
- package/src/vite/plugin-types.ts +143 -10
- package/src/vite/plugins/cjs-to-esm.ts +8 -12
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +0 -10
- package/src/vite/plugins/cloudflare-protocol-stub.ts +0 -20
- package/src/vite/plugins/expose-action-id.ts +2 -73
- package/src/vite/plugins/expose-id-utils.ts +85 -56
- package/src/vite/plugins/expose-ids/export-analysis.ts +30 -43
- package/src/vite/plugins/expose-ids/handler-transform.ts +5 -31
- package/src/vite/plugins/expose-ids/loader-transform.ts +12 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +98 -26
- package/src/vite/plugins/expose-internal-ids.ts +10 -1
- package/src/vite/plugins/performance-tracks.ts +0 -3
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +21 -46
- package/src/vite/plugins/vercel-output.ts +384 -0
- package/src/vite/plugins/version-injector.ts +22 -27
- package/src/vite/plugins/version-plugin.ts +6 -66
- package/src/vite/plugins/virtual-entries.ts +137 -26
- package/src/vite/rango.ts +146 -135
- package/src/vite/router-discovery.ts +189 -48
- package/src/vite/utils/ast-handler-extract.ts +11 -20
- package/src/vite/utils/bundle-analysis.ts +6 -13
- package/src/vite/utils/client-chunks.ts +0 -6
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +0 -22
- package/src/vite/utils/manifest-utils.ts +4 -75
- package/src/vite/utils/package-resolution.ts +1 -73
- package/src/vite/utils/prerender-utils.ts +71 -44
- package/src/vite/utils/shared-utils.ts +55 -37
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -7
- package/src/network-error-thrower.tsx +0 -23
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -1,82 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Navigation Snapshot
|
|
3
|
-
*
|
|
4
|
-
* Pure data type representing the navigation-specific state for partial requests.
|
|
5
|
-
* Consolidates the header parsing, previous-route matching, intercept-context
|
|
6
|
-
* detection, and segment ID filtering that previously lived inline in
|
|
7
|
-
* createMatchContextForPartial (match-api.ts).
|
|
8
|
-
*
|
|
9
|
-
* resolveNavigation() is the factory: given a request + URL + current route key,
|
|
10
|
-
* it returns a NavigationSnapshot (or null if no previous URL).
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
1
|
import type { RouteMatchResult } from "./pattern-matching.js";
|
|
14
2
|
|
|
15
|
-
/**
|
|
16
|
-
* Snapshot of navigation state for a partial (navigation/action) request.
|
|
17
|
-
*
|
|
18
|
-
* Contains the "where are we coming from?" data: previous route, intercept
|
|
19
|
-
* source, client segment state, and derived flags.
|
|
20
|
-
*/
|
|
21
3
|
export interface NavigationSnapshot {
|
|
22
|
-
/** Previous page URL (from X-RSC-Router-Client-Path or Referer) */
|
|
23
4
|
prevUrl: URL;
|
|
24
|
-
/** Params from the previous route match */
|
|
25
5
|
prevParams: Record<string, string>;
|
|
26
|
-
/** Previous route match result (null if prev URL doesn't match any route) */
|
|
27
6
|
prevMatch: RouteMatchResult | null;
|
|
28
7
|
|
|
29
|
-
/** URL used as intercept context source */
|
|
30
8
|
interceptContextUrl: URL;
|
|
31
|
-
/** Route match for the intercept context URL */
|
|
32
9
|
interceptContextMatch: RouteMatchResult | null;
|
|
33
10
|
|
|
34
|
-
/** Raw segment IDs the client currently has */
|
|
35
11
|
clientSegmentIds: string[];
|
|
36
|
-
/** Set version for O(1) lookup */
|
|
37
12
|
clientSegmentSet: Set<string>;
|
|
38
|
-
/** Segment IDs filtered to remove parallel (.@) and loader (D\d+.) entries */
|
|
39
13
|
filteredSegmentIds: string[];
|
|
40
14
|
|
|
41
|
-
/** Whether client considers its cache stale */
|
|
42
15
|
stale: boolean;
|
|
43
16
|
|
|
44
|
-
/** Whether the intercept context route is the same as the current route */
|
|
45
17
|
isSameRouteNavigation: boolean;
|
|
46
18
|
|
|
47
|
-
/** Effective "from" URL (intercept source URL when present, else prevUrl) */
|
|
48
19
|
effectiveFromUrl: URL;
|
|
49
|
-
/** Effective "from" match (intercept source match when present, else prevMatch) */
|
|
50
20
|
effectiveFromMatch: RouteMatchResult | null;
|
|
51
21
|
|
|
52
|
-
/** Whether an intercept source header was present */
|
|
53
22
|
hasInterceptSource: boolean;
|
|
54
23
|
|
|
55
|
-
/** Whether an HMR request header was present */
|
|
56
24
|
isHmr: boolean;
|
|
57
25
|
}
|
|
58
26
|
|
|
59
27
|
export interface ResolveNavigationDeps {
|
|
60
|
-
findMatch: (
|
|
28
|
+
findMatch: (
|
|
29
|
+
pathname: string,
|
|
30
|
+
) => RouteMatchResult | null | Promise<RouteMatchResult | null>;
|
|
61
31
|
}
|
|
62
32
|
|
|
63
|
-
|
|
64
|
-
* Resolve navigation state from a partial request.
|
|
65
|
-
*
|
|
66
|
-
* Returns null if no previous URL is available (required for partial navigation).
|
|
67
|
-
*
|
|
68
|
-
* @param request - The incoming HTTP request
|
|
69
|
-
* @param url - Parsed URL of the request
|
|
70
|
-
* @param currentRouteKey - Route key of the current (target) route match
|
|
71
|
-
* @param deps - Dependencies (findMatch)
|
|
72
|
-
*/
|
|
73
|
-
export function resolveNavigation(
|
|
33
|
+
export async function resolveNavigation(
|
|
74
34
|
request: Request,
|
|
75
35
|
url: URL,
|
|
76
36
|
currentRouteKey: string,
|
|
77
37
|
deps: ResolveNavigationDeps,
|
|
78
|
-
): NavigationSnapshot | null {
|
|
79
|
-
// Parse client state from RSC request params/headers
|
|
38
|
+
): Promise<NavigationSnapshot | null> {
|
|
80
39
|
const clientSegmentIds =
|
|
81
40
|
url.searchParams.get("_rsc_segments")?.split(",").filter(Boolean) || [];
|
|
82
41
|
const stale = url.searchParams.get("_rsc_stale") === "true";
|
|
@@ -92,7 +51,6 @@ export function resolveNavigation(
|
|
|
92
51
|
return null;
|
|
93
52
|
}
|
|
94
53
|
|
|
95
|
-
// Parse previous URL
|
|
96
54
|
let prevUrl: URL;
|
|
97
55
|
try {
|
|
98
56
|
prevUrl = new URL(previousUrl, url.origin);
|
|
@@ -100,7 +58,6 @@ export function resolveNavigation(
|
|
|
100
58
|
return null;
|
|
101
59
|
}
|
|
102
60
|
|
|
103
|
-
// Parse intercept context URL
|
|
104
61
|
let interceptContextUrl: URL;
|
|
105
62
|
try {
|
|
106
63
|
interceptContextUrl = interceptSourceUrl
|
|
@@ -110,14 +67,12 @@ export function resolveNavigation(
|
|
|
110
67
|
interceptContextUrl = prevUrl;
|
|
111
68
|
}
|
|
112
69
|
|
|
113
|
-
|
|
114
|
-
const prevMatch = deps.findMatch(prevUrl.pathname);
|
|
70
|
+
const prevMatch = await deps.findMatch(prevUrl.pathname);
|
|
115
71
|
const prevParams = prevMatch?.params || {};
|
|
116
72
|
const interceptContextMatch = interceptSourceUrl
|
|
117
|
-
? deps.findMatch(interceptContextUrl.pathname)
|
|
73
|
+
? await deps.findMatch(interceptContextUrl.pathname)
|
|
118
74
|
: prevMatch;
|
|
119
75
|
|
|
120
|
-
// Derived state
|
|
121
76
|
const isSameRouteNavigation = !!(
|
|
122
77
|
interceptContextMatch && interceptContextMatch.routeKey === currentRouteKey
|
|
123
78
|
);
|
|
@@ -128,7 +83,6 @@ export function resolveNavigation(
|
|
|
128
83
|
? interceptContextMatch
|
|
129
84
|
: prevMatch;
|
|
130
85
|
|
|
131
|
-
// Filter segment IDs: remove parallel (.@) and loader (D\d+.) entries
|
|
132
86
|
const filteredSegmentIds = clientSegmentIds.filter((id) => {
|
|
133
87
|
if (id.includes(".@")) return false;
|
|
134
88
|
if (/D\d+\./.test(id)) return false;
|
|
@@ -155,9 +109,6 @@ export function resolveNavigation(
|
|
|
155
109
|
};
|
|
156
110
|
}
|
|
157
111
|
|
|
158
|
-
/**
|
|
159
|
-
* Test helper: create a NavigationSnapshot with sensible defaults and overrides.
|
|
160
|
-
*/
|
|
161
112
|
export function createNavigationSnapshot(
|
|
162
113
|
overrides?: Partial<NavigationSnapshot>,
|
|
163
114
|
): NavigationSnapshot {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared route-param comparison helpers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shallow equality for two route-param records. Same-reference is a fast path;
|
|
7
|
+
* otherwise compares key count then each value.
|
|
8
|
+
*/
|
|
9
|
+
export function paramsEqual(
|
|
10
|
+
a: Record<string, string>,
|
|
11
|
+
b: Record<string, string>,
|
|
12
|
+
): boolean {
|
|
13
|
+
if (a === b) return true;
|
|
14
|
+
|
|
15
|
+
const keysA = Object.keys(a);
|
|
16
|
+
if (keysA.length !== Object.keys(b).length) return false;
|
|
17
|
+
|
|
18
|
+
for (const key of keysA) {
|
|
19
|
+
if (a[key] !== b[key]) return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route pattern parsing (grammar only).
|
|
3
|
+
*
|
|
4
|
+
* Deliberately dependency-free so it is safe to bundle into the CLIENT — the
|
|
5
|
+
* reverse helper (`substitute-pattern-params.ts` -> `use-reverse`) needs it, and
|
|
6
|
+
* pulling it from `pattern-matching.ts` would drag that module's server-only
|
|
7
|
+
* transitive imports (`node:async_hooks` via `logging.ts`) into the browser.
|
|
8
|
+
* `pattern-matching.ts` re-exports these so existing importers are unaffected.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Parsed segment info
|
|
13
|
+
*/
|
|
14
|
+
export interface ParsedSegment {
|
|
15
|
+
type: "static" | "param" | "wildcard";
|
|
16
|
+
value: string; // static text, param name, or "*"
|
|
17
|
+
optional: boolean;
|
|
18
|
+
constraint?: string[]; // enum values like ["en", "gb"]
|
|
19
|
+
suffix?: string; // literal text after param in same segment (e.g., ".html")
|
|
20
|
+
/**
|
|
21
|
+
* Named catch-all repeat modifier. On a `wildcard` segment whose `value` is a
|
|
22
|
+
* param name (`:name+` / `:name*`), `true` marks one-or-more (`+`, rejects the
|
|
23
|
+
* zero-segment case); absent/false marks zero-or-more (`*`, and the bare `/*`).
|
|
24
|
+
*/
|
|
25
|
+
oneOrMore?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Parse a route pattern into segments
|
|
30
|
+
*
|
|
31
|
+
* Supports:
|
|
32
|
+
* - Static: /blog, /about
|
|
33
|
+
* - Params: /:slug, /:id
|
|
34
|
+
* - Optional: /:locale?, /:page?
|
|
35
|
+
* - Constrained: /:locale(en|gb), /:type(post|page)
|
|
36
|
+
* - Optional + Constrained: /:locale(en|gb)?
|
|
37
|
+
* - Wildcard: /*
|
|
38
|
+
* - Named catch-all: /:slug* (zero-or-more), /:path+ (one-or-more)
|
|
39
|
+
*/
|
|
40
|
+
export function parsePattern(pattern: string): ParsedSegment[] {
|
|
41
|
+
const segments: ParsedSegment[] = [];
|
|
42
|
+
// The `([+*])?` group peels a trailing `+`/`*` off a `:name` BEFORE the
|
|
43
|
+
// literal-suffix group `([^/]*)` so it can be inspected. Whether it is a
|
|
44
|
+
// catch-all MODIFIER or a literal suffix character is decided below — a bare
|
|
45
|
+
// trailing `+`/`*` is the named catch-all of issue #634; any other combination
|
|
46
|
+
// is folded back into the literal suffix so previously-valid patterns are
|
|
47
|
+
// unaffected. It sits after `(\?)?` so `:name?*` is seen as `?` + suffix `*`.
|
|
48
|
+
const segmentRegex =
|
|
49
|
+
/\/(:([a-zA-Z_][a-zA-Z0-9_]*)(\(([^)]+)\))?(\?)?([+*])?([^/]*)|(\*)|([^/]+))/g;
|
|
50
|
+
|
|
51
|
+
let match;
|
|
52
|
+
while ((match = segmentRegex.exec(pattern)) !== null) {
|
|
53
|
+
const [
|
|
54
|
+
,
|
|
55
|
+
,
|
|
56
|
+
paramName,
|
|
57
|
+
,
|
|
58
|
+
constraint,
|
|
59
|
+
optional,
|
|
60
|
+
repeat,
|
|
61
|
+
suffix,
|
|
62
|
+
wildcard,
|
|
63
|
+
staticText,
|
|
64
|
+
] = match;
|
|
65
|
+
|
|
66
|
+
if (wildcard) {
|
|
67
|
+
// Bare `/*`: zero-or-more, captured under "*".
|
|
68
|
+
segments.push({ type: "wildcard", value: "*", optional: false });
|
|
69
|
+
} else if (paramName) {
|
|
70
|
+
// A trailing `+`/`*` is a named catch-all ONLY when it stands alone on the
|
|
71
|
+
// param — no `?`, no constraint, no literal suffix after it. In any other
|
|
72
|
+
// combination it is the start of a literal suffix, exactly as before this
|
|
73
|
+
// feature existed, so `:version+build` still matches `/…/v1+build` and
|
|
74
|
+
// never throws at registration.
|
|
75
|
+
if (repeat && !suffix && optional !== "?" && !constraint) {
|
|
76
|
+
segments.push({
|
|
77
|
+
type: "wildcard",
|
|
78
|
+
value: paramName,
|
|
79
|
+
optional: false,
|
|
80
|
+
oneOrMore: repeat === "+",
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
segments.push({
|
|
84
|
+
type: "param",
|
|
85
|
+
value: paramName,
|
|
86
|
+
optional: optional === "?",
|
|
87
|
+
constraint: constraint ? constraint.split("|") : undefined,
|
|
88
|
+
// Fold a non-modifier `+`/`*` back into the literal suffix.
|
|
89
|
+
suffix: (repeat ?? "") + (suffix ?? "") || undefined,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
} else if (staticText) {
|
|
93
|
+
segments.push({ type: "static", value: staticText, optional: false });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// A named catch-all consumes the remainder, so it only makes sense as the final
|
|
98
|
+
// segment. If it isn't last, it isn't really a catch-all: restore the literal
|
|
99
|
+
// parse (`:name` + literal `+`/`*` suffix) rather than error, so a pattern like
|
|
100
|
+
// `/docs/:slug+/edit` keeps its pre-feature behavior (matches `/docs/x+/edit`).
|
|
101
|
+
// Bare `/*` keeps its historical mid-pattern leniency and is left untouched.
|
|
102
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
103
|
+
const s = segments[i];
|
|
104
|
+
if (s.type === "wildcard" && s.value !== "*") {
|
|
105
|
+
segments[i] = {
|
|
106
|
+
type: "param",
|
|
107
|
+
value: s.value,
|
|
108
|
+
optional: false,
|
|
109
|
+
suffix: s.oneOrMore ? "+" : "*",
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return segments;
|
|
115
|
+
}
|