@rangojs/router 0.0.0-experimental.9c9afef3 → 0.0.0-experimental.a014d2b7
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 -0
- package/README.md +245 -49
- package/dist/bin/rango.js +440 -133
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3373 -1176
- package/dist/vite/index.js.bak +5448 -0
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +68 -14
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +64 -2
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +224 -32
- package/skills/caching/SKILL.md +279 -17
- package/skills/composability/SKILL.md +27 -3
- package/skills/css/SKILL.md +76 -0
- package/skills/debug-manifest/SKILL.md +4 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +250 -30
- package/skills/host-router/SKILL.md +83 -23
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +87 -18
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +235 -9
- package/skills/middleware/SKILL.md +52 -13
- package/skills/migrate-nextjs/SKILL.md +584 -0
- package/skills/migrate-react-router/SKILL.md +771 -0
- package/skills/mime-routes/SKILL.md +28 -1
- package/skills/observability/SKILL.md +172 -0
- package/skills/parallel/SKILL.md +77 -7
- package/skills/prerender/SKILL.md +172 -125
- package/skills/rango/SKILL.md +251 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +70 -5
- package/skills/router-setup/SKILL.md +65 -8
- package/skills/scripts/SKILL.md +179 -0
- package/skills/server-actions/SKILL.md +775 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +130 -0
- 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 +129 -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 +84 -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/typesafety/SKILL.md +322 -29
- package/skills/use-cache/SKILL.md +57 -14
- package/skills/view-transitions/SKILL.md +337 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +1 -66
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +39 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/connection-warmup.ts +134 -0
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +192 -150
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/invalidate-client-cache.ts +52 -0
- package/src/browser/navigation-bridge.ts +131 -30
- package/src/browser/navigation-client.ts +186 -100
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +157 -74
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +165 -112
- package/src/browser/prefetch/cache.ts +205 -62
- package/src/browser/prefetch/fetch.ts +347 -39
- package/src/browser/prefetch/queue.ts +42 -8
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +102 -15
- package/src/browser/react/NavigationProvider.tsx +295 -119
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/deferred-handle-resolution.ts +75 -0
- package/src/browser/react/filter-segment-order.ts +66 -7
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +178 -8
- package/src/browser/react/location-state.ts +39 -14
- package/src/browser/react/use-action.ts +6 -15
- package/src/browser/react/use-handle.ts +23 -69
- 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 +32 -7
- package/src/browser/react/use-params.ts +20 -10
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +46 -11
- package/src/browser/react/use-search-params.ts +0 -5
- package/src/browser/react/use-segments.ts +11 -21
- package/src/browser/response-adapter.ts +99 -8
- package/src/browser/rsc-router.tsx +114 -24
- package/src/browser/scroll-restoration.ts +37 -22
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +222 -72
- package/src/browser/types.ts +102 -12
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +65 -40
- package/src/build/generate-route-types.ts +5 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +165 -36
- package/src/build/route-types/ast-route-extraction.ts +15 -8
- package/src/build/route-types/codegen.ts +16 -5
- package/src/build/route-types/include-resolution.ts +125 -24
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +22 -6
- package/src/build/route-types/router-processing.ts +260 -94
- package/src/build/route-types/scan-filter.ts +9 -2
- package/src/build/route-types/source-scan.ts +216 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-key-utils.ts +29 -13
- package/src/cache/cache-policy.ts +108 -34
- package/src/cache/cache-runtime.ts +224 -41
- package/src/cache/cache-scope.ts +188 -82
- package/src/cache/cache-tag.ts +103 -0
- package/src/cache/cf/cf-base64.ts +33 -0
- package/src/cache/cf/cf-cache-constants.ts +127 -0
- package/src/cache/cf/cf-cache-store.ts +1989 -378
- 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 +89 -21
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +10 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +46 -31
- package/src/cache/read-through-swr.ts +56 -12
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +44 -21
- package/src/client.tsx +119 -290
- package/src/cloudflare/index.ts +11 -0
- package/src/cloudflare/tracing.ts +109 -0
- package/src/component-utils.ts +19 -0
- package/src/components/DefaultDocument.tsx +8 -2
- package/src/context-var.ts +18 -6
- package/src/decode-loader-results.ts +52 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/encode-kv.ts +49 -0
- package/src/errors.ts +30 -4
- package/src/escape-script.ts +52 -0
- package/src/handle.ts +70 -22
- package/src/handles/MetaTags.tsx +62 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +37 -8
- package/src/handles/is-thenable.ts +19 -0
- package/src/handles/meta.ts +51 -40
- package/src/handles/script.ts +244 -0
- package/src/host/cookie-handler.ts +9 -60
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +23 -52
- package/src/host/router.ts +107 -99
- package/src/host/testing.ts +40 -27
- package/src/host/types.ts +37 -4
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +137 -22
- package/src/index.rsc.ts +99 -13
- package/src/index.ts +139 -19
- package/src/internal-debug.ts +11 -10
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +20 -13
- package/src/loader.ts +12 -11
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +16 -16
- package/src/prerender/store.ts +37 -41
- package/src/prerender.ts +198 -82
- package/src/redirect-origin.ts +100 -0
- package/src/regex-escape.ts +8 -0
- package/src/render-error-thrower.tsx +20 -0
- package/src/response-utils.ts +62 -0
- package/src/reverse.ts +65 -15
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +19 -77
- package/src/route-definition/dsl-helpers.ts +461 -304
- package/src/route-definition/helper-factories.ts +28 -140
- package/src/route-definition/helpers-types.ts +143 -69
- package/src/route-definition/index.ts +4 -2
- package/src/route-definition/redirect.ts +51 -10
- package/src/route-definition/resolve-handler-use.ts +160 -0
- package/src/route-definition/use-item-types.ts +29 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +37 -46
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +164 -17
- package/src/router/error-handling.ts +45 -18
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +52 -31
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +48 -24
- package/src/router/lazy-includes.ts +15 -52
- package/src/router/loader-resolution.ts +268 -56
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +40 -42
- package/src/router/match-api.ts +124 -204
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +40 -24
- package/src/router/match-middleware/cache-lookup.ts +170 -276
- package/src/router/match-middleware/cache-store.ts +64 -52
- package/src/router/match-middleware/intercept-resolution.ts +0 -22
- package/src/router/match-middleware/segment-resolution.ts +45 -14
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +87 -39
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +7 -140
- package/src/router/middleware.ts +266 -169
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +132 -90
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +195 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +123 -73
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +3 -28
- package/src/router/router-interfaces.ts +115 -35
- package/src/router/router-options.ts +172 -15
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +162 -84
- package/src/router/segment-resolution/helpers.ts +86 -6
- package/src/router/segment-resolution/loader-cache.ts +76 -39
- package/src/router/segment-resolution/revalidation.ts +351 -321
- 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 +56 -0
- 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 +56 -0
- package/src/router/telemetry-otel.ts +161 -199
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/tracing.ts +206 -0
- package/src/router/trie-matching.ts +163 -59
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +157 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +655 -529
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -5
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +122 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +131 -14
- package/src/rsc/redirect-guard.ts +99 -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 +99 -189
- package/src/rsc/rsc-rendering.ts +109 -74
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +287 -115
- package/src/rsc/ssr-setup.ts +18 -2
- package/src/rsc/transition-gate.ts +89 -0
- package/src/rsc/types.ts +29 -9
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +35 -30
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +236 -202
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +224 -52
- package/src/server/cookie-parse.ts +32 -0
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +40 -38
- package/src/server/loader-registry.ts +38 -46
- package/src/server/request-context.ts +401 -173
- package/src/ssr/index.tsx +24 -16
- package/src/static-handler.ts +27 -18
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +701 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +188 -0
- package/src/testing/e2e/index.ts +128 -0
- package/src/testing/e2e/matchers.ts +35 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +387 -0
- package/src/testing/e2e/server.ts +195 -0
- package/src/testing/flight-matchers.ts +97 -0
- package/src/testing/flight-normalize.ts +11 -0
- package/src/testing/flight-runtime.d.ts +57 -0
- package/src/testing/flight-tree.ts +682 -0
- package/src/testing/flight.entry.ts +52 -0
- package/src/testing/flight.ts +257 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +371 -0
- package/src/testing/internal/flight-client-globals.ts +30 -0
- package/src/testing/internal/seed-vars.ts +54 -0
- package/src/testing/render-handler.ts +357 -0
- package/src/testing/render-route.tsx +581 -0
- package/src/testing/run-loader.ts +385 -0
- package/src/testing/run-middleware.ts +205 -0
- package/src/testing/run-transition-when.ts +164 -0
- package/src/testing/vitest-stubs/cloudflare-email.ts +9 -0
- package/src/testing/vitest-stubs/cloudflare-workers.ts +21 -0
- package/src/testing/vitest-stubs/plugin-rsc.ts +16 -0
- package/src/testing/vitest-stubs/version.ts +5 -0
- package/src/testing/vitest.ts +305 -0
- package/src/theme/ThemeProvider.tsx +20 -58
- 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 +17 -8
- package/src/types/error-types.ts +30 -90
- package/src/types/global-namespace.ts +54 -41
- package/src/types/handler-context.ts +125 -71
- package/src/types/index.ts +3 -10
- package/src/types/loader-types.ts +40 -11
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +12 -7
- package/src/types/segments.ts +136 -15
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +68 -18
- package/src/urls/path-helper.ts +57 -111
- package/src/urls/pattern-types.ts +48 -19
- package/src/urls/response-types.ts +25 -22
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -19
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +36 -38
- package/src/vite/discovery/discover-routers.ts +130 -85
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/gate-state.ts +171 -0
- package/src/vite/discovery/prerender-collection.ts +214 -132
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/self-gen-tracking.ts +27 -1
- package/src/vite/discovery/state.ts +57 -4
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +6 -0
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +178 -5
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +16 -11
- package/src/vite/plugins/client-ref-hashing.ts +28 -15
- package/src/vite/plugins/cloudflare-protocol-loader-hook.d.mts +23 -0
- package/src/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/src/vite/plugins/cloudflare-protocol-stub.ts +194 -0
- package/src/vite/plugins/expose-action-id.ts +48 -95
- package/src/vite/plugins/expose-id-utils.ts +96 -51
- package/src/vite/plugins/expose-ids/export-analysis.ts +101 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +15 -64
- package/src/vite/plugins/expose-ids/loader-transform.ts +14 -24
- package/src/vite/plugins/expose-ids/router-transform.ts +118 -29
- package/src/vite/plugins/expose-internal-ids.ts +553 -317
- package/src/vite/plugins/performance-tracks.ts +64 -170
- package/src/vite/plugins/refresh-cmd.ts +89 -27
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +40 -29
- package/src/vite/plugins/version-plugin.ts +37 -40
- package/src/vite/plugins/virtual-entries.ts +39 -25
- package/src/vite/rango.ts +118 -114
- package/src/vite/router-discovery.ts +941 -142
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -0
- package/src/vite/utils/directive-prologue.ts +40 -0
- package/src/vite/utils/forward-user-plugins.ts +171 -0
- package/src/vite/utils/manifest-utils.ts +4 -59
- package/src/vite/utils/package-resolution.ts +20 -52
- package/src/vite/utils/prerender-utils.ts +81 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/debug-channel.ts +0 -93
- 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
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL param encode/decode at the route boundary.
|
|
3
|
+
*
|
|
4
|
+
* Extraction (decode): regex/trie matchers keep param values URL-encoded;
|
|
5
|
+
* `safeDecodeURIComponent` turns them back into raw strings so `ctx.params`
|
|
6
|
+
* matches the contract apps expect (Express/React Router/Fastify/Koa) and
|
|
7
|
+
* round-trips through reverse stay stable. Malformed %-encoding is
|
|
8
|
+
* preserved as-is so a broken URL doesn't crash matching.
|
|
9
|
+
*
|
|
10
|
+
* Reversal (encode): `encodePathSegment` escapes only what RFC 3986
|
|
11
|
+
* requires for a path segment — `/`, `?`, `#`, space, control chars,
|
|
12
|
+
* non-ASCII — and leaves pchar sub-delims (`@ : $ & + , ; =` and friends)
|
|
13
|
+
* readable. `encodeURIComponent` over-encodes for path segments, which
|
|
14
|
+
* makes generated URLs harder for humans to read in the address bar
|
|
15
|
+
* (e.g. mailbox IDs like `ivo@example.com` would become
|
|
16
|
+
* `ivo%40example.com` even though `@` is path-legal).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export function safeDecodeURIComponent(raw: string): string {
|
|
20
|
+
if (raw === "" || raw.indexOf("%") === -1) return raw;
|
|
21
|
+
try {
|
|
22
|
+
return decodeURIComponent(raw);
|
|
23
|
+
} catch {
|
|
24
|
+
return raw;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const PATH_SAFE_ESCAPES: Record<string, string> = {
|
|
29
|
+
"%3A": ":",
|
|
30
|
+
"%40": "@",
|
|
31
|
+
"%24": "$",
|
|
32
|
+
"%26": "&",
|
|
33
|
+
"%2B": "+",
|
|
34
|
+
"%2C": ",",
|
|
35
|
+
"%3B": ";",
|
|
36
|
+
"%3D": "=",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export function encodePathSegment(value: string): string {
|
|
40
|
+
return encodeURIComponent(value).replace(
|
|
41
|
+
/%(?:3A|40|24|26|2B|2C|3B|3D)/gi,
|
|
42
|
+
(match) => PATH_SAFE_ESCAPES[match.toUpperCase()] ?? match,
|
|
43
|
+
);
|
|
44
|
+
}
|
package/src/router.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { createCacheScope } from "./cache/cache-scope.js";
|
|
3
|
-
import {
|
|
4
|
-
setCacheProfiles,
|
|
5
|
-
resolveCacheProfiles,
|
|
6
|
-
} from "./cache/profile-registry.js";
|
|
3
|
+
import { resolveCacheProfiles } from "./cache/profile-registry.js";
|
|
7
4
|
import { isCachedFunction } from "./cache/taint.js";
|
|
8
5
|
import { assertClientComponent } from "./component-utils.js";
|
|
9
6
|
import { DefaultDocument } from "./components/DefaultDocument.js";
|
|
@@ -19,11 +16,13 @@ import {
|
|
|
19
16
|
import MapRootLayout from "./server/root-layout.js";
|
|
20
17
|
import type { AllUseItems } from "./route-types.js";
|
|
21
18
|
import type { UrlPatterns } from "./urls.js";
|
|
19
|
+
import type { UrlBuilder } from "./urls/pattern-types.js";
|
|
20
|
+
import { urls } from "./urls.js";
|
|
21
|
+
import { buildPrecomputedByPrefix } from "./build/prefix-tree-utils.js";
|
|
22
22
|
import {
|
|
23
|
-
EntryData,
|
|
24
|
-
InterceptSelectorContext,
|
|
23
|
+
type EntryData,
|
|
25
24
|
getContext,
|
|
26
|
-
|
|
25
|
+
RangoContext,
|
|
27
26
|
type MetricsStore,
|
|
28
27
|
} from "./server/context";
|
|
29
28
|
import { createHandleStore, type HandleStore } from "./server/handle-store.js";
|
|
@@ -55,6 +54,7 @@ import { buildDebugManifest } from "./router/debug-manifest.js";
|
|
|
55
54
|
|
|
56
55
|
import type { SegmentResolutionDeps, MatchApiDeps } from "./router/types.js";
|
|
57
56
|
import { createHandlerContext } from "./router/handler-context.js";
|
|
57
|
+
import { normalizeBasename } from "./router/basename.js";
|
|
58
58
|
import {
|
|
59
59
|
setupLoaderAccess,
|
|
60
60
|
setupLoaderAccessSilent,
|
|
@@ -63,15 +63,17 @@ import {
|
|
|
63
63
|
import { loadManifest } from "./router/manifest.js";
|
|
64
64
|
import { createMetricsStore } from "./router/metrics.js";
|
|
65
65
|
import {
|
|
66
|
-
|
|
66
|
+
compileMiddlewarePattern,
|
|
67
67
|
type MiddlewareEntry,
|
|
68
68
|
type MiddlewareFn,
|
|
69
69
|
} from "./router/middleware.js";
|
|
70
70
|
import {
|
|
71
71
|
extractStaticPrefix,
|
|
72
|
+
joinPrefix,
|
|
72
73
|
traverseBack,
|
|
73
74
|
} from "./router/pattern-matching.js";
|
|
74
75
|
import { resolveSink, safeEmit, getRequestId } from "./router/telemetry.js";
|
|
76
|
+
import { resolveTracing } from "./router/tracing.js";
|
|
75
77
|
import { evaluateRevalidation } from "./router/revalidation.js";
|
|
76
78
|
import {
|
|
77
79
|
type RouterContext,
|
|
@@ -89,13 +91,10 @@ import {
|
|
|
89
91
|
RouterRegistry,
|
|
90
92
|
nextRouterAutoId,
|
|
91
93
|
} from "./router/router-registry.js";
|
|
94
|
+
import type { RangoOptions, RootLayoutProps } from "./router/router-options.js";
|
|
92
95
|
import type {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
} from "./router/router-options.js";
|
|
96
|
-
import type {
|
|
97
|
-
RSCRouter,
|
|
98
|
-
RSCRouterInternal,
|
|
96
|
+
Rango,
|
|
97
|
+
RangoInternal,
|
|
99
98
|
RouterRequestInput,
|
|
100
99
|
} from "./router/router-interfaces.js";
|
|
101
100
|
|
|
@@ -110,29 +109,32 @@ import {
|
|
|
110
109
|
matchForPrerender as _matchForPrerender,
|
|
111
110
|
renderStaticSegment as _renderStaticSegment,
|
|
112
111
|
} from "./router/prerender-match.js";
|
|
112
|
+
import { resolveStateCookieName } from "./router/state-cookie-name.js";
|
|
113
|
+
import { resolvePrefetchCacheTTL } from "./router/prefetch-cache-ttl.js";
|
|
113
114
|
|
|
114
115
|
// Re-export public types and values from extracted modules
|
|
115
116
|
export { RSC_ROUTER_BRAND, RouterRegistry } from "./router/router-registry.js";
|
|
116
117
|
export type {
|
|
117
|
-
|
|
118
|
+
RangoOptions,
|
|
118
119
|
RootLayoutProps,
|
|
119
120
|
SSRStreamMode,
|
|
120
121
|
SSROptions,
|
|
121
122
|
ResolveStreamingContext,
|
|
122
123
|
} from "./router/router-options.js";
|
|
123
124
|
export type {
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
Rango,
|
|
126
|
+
RangoInternal,
|
|
126
127
|
RouterRequestInput,
|
|
127
128
|
} from "./router/router-interfaces.js";
|
|
128
129
|
export { toInternal } from "./router/router-interfaces.js";
|
|
129
130
|
|
|
130
131
|
export function createRouter<TEnv = any>(
|
|
131
|
-
options:
|
|
132
|
-
):
|
|
132
|
+
options: RangoOptions<TEnv> = {},
|
|
133
|
+
): Rango<TEnv, {}> {
|
|
133
134
|
const {
|
|
134
135
|
id: userProvidedId,
|
|
135
136
|
$$id: injectedId,
|
|
137
|
+
basename: basenameOption,
|
|
136
138
|
debugPerformance = false,
|
|
137
139
|
document: documentOption,
|
|
138
140
|
defaultErrorBoundary,
|
|
@@ -148,24 +150,46 @@ export function createRouter<TEnv = any>(
|
|
|
148
150
|
nonce,
|
|
149
151
|
version,
|
|
150
152
|
prefetchCacheTTL: prefetchCacheTTLOption,
|
|
153
|
+
stateCookiePrefix: stateCookiePrefixOption,
|
|
151
154
|
warmup: warmupOption,
|
|
152
155
|
allowDebugManifest: allowDebugManifestOption = false,
|
|
153
156
|
telemetry: telemetrySink,
|
|
157
|
+
tracing: tracingOption,
|
|
154
158
|
ssr: ssrOption,
|
|
155
159
|
timeout: timeoutShorthand,
|
|
156
160
|
timeouts: timeoutsOption,
|
|
157
161
|
onTimeout,
|
|
158
162
|
originCheck: originCheckOption,
|
|
163
|
+
viewTransition: viewTransitionOption = "auto",
|
|
164
|
+
debugCacheSignal: debugCacheSignalOption = false,
|
|
165
|
+
strictMode: strictModeOption = true,
|
|
159
166
|
} = options;
|
|
160
167
|
|
|
168
|
+
// Debug cache signal gate (DEVELOPMENT/TEST ONLY). Enabled by the
|
|
169
|
+
// debugCacheSignal option OR the RANGO_TEST_SIGNALS=1 env flag. When off,
|
|
170
|
+
// no X-Rango-Cache header is emitted and output is byte-identical.
|
|
171
|
+
const cacheSignalEnabled =
|
|
172
|
+
debugCacheSignalOption ||
|
|
173
|
+
(typeof process !== "undefined" &&
|
|
174
|
+
(process as { env?: Record<string, string | undefined> }).env
|
|
175
|
+
?.RANGO_TEST_SIGNALS === "1");
|
|
176
|
+
|
|
177
|
+
// Normalize basename: ensure leading slash, strip trailing slash.
|
|
178
|
+
// A bare "/" is equivalent to no basename. Shared with the testing
|
|
179
|
+
// primitives via normalizeBasename so they can never drift.
|
|
180
|
+
const basename = normalizeBasename(basenameOption);
|
|
181
|
+
|
|
161
182
|
// Resolve telemetry sink (no-op when not configured)
|
|
162
183
|
const telemetry = resolveSink(telemetrySink);
|
|
163
184
|
|
|
164
|
-
// Resolve
|
|
165
|
-
//
|
|
166
|
-
|
|
185
|
+
// Resolve span tracing (undefined when not configured; every traceSpan() call
|
|
186
|
+
// is then a direct pass-through with zero behavior change).
|
|
187
|
+
const resolvedTracing = resolveTracing(tracingOption);
|
|
188
|
+
|
|
189
|
+
// Resolve cache profiles: merge user config with the guaranteed default
|
|
190
|
+
// profile. This resolved map is threaded onto each request context; the
|
|
191
|
+
// "use cache: <profile>" runtime path reads it request-scoped.
|
|
167
192
|
const resolvedCacheProfiles = resolveCacheProfiles(cacheProfilesOption);
|
|
168
|
-
setCacheProfiles(resolvedCacheProfiles);
|
|
169
193
|
|
|
170
194
|
// Source file: prefer Vite-injected path (zero cost), fall back to
|
|
171
195
|
// stack trace parsing for non-Vite environments (e.g. tests).
|
|
@@ -200,21 +224,32 @@ export function createRouter<TEnv = any>(
|
|
|
200
224
|
const routerId =
|
|
201
225
|
userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
|
|
202
226
|
|
|
203
|
-
// Resolve
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
227
|
+
// Resolve the rango state cookie name once, here, so the two cookie writers
|
|
228
|
+
// (the client document.cookie writer and the server Set-Cookie writer)
|
|
229
|
+
// consume one pre-composed name and cannot drift.
|
|
230
|
+
const resolvedStateCookieName = resolveStateCookieName(
|
|
231
|
+
stateCookiePrefixOption,
|
|
232
|
+
routerId,
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
// Resolve prefetch cache TTL (default: 300 seconds / 5 minutes). Clamps to a
|
|
236
|
+
// non-negative integer and guards non-finite (NaN/Infinity) inputs so a
|
|
237
|
+
// malformed `Cache-Control: max-age=NaN` can never reach the wire.
|
|
238
|
+
const resolvedPrefetchCacheTTL = resolvePrefetchCacheTTL(
|
|
239
|
+
prefetchCacheTTLOption,
|
|
240
|
+
);
|
|
241
|
+
const prefetchCacheTTL = resolvedPrefetchCacheTTL.ms;
|
|
210
242
|
const prefetchCacheControl: string | false =
|
|
211
|
-
|
|
212
|
-
? false
|
|
213
|
-
: `private, max-age=${prefetchCacheTTLSeconds}`;
|
|
243
|
+
resolvedPrefetchCacheTTL.cacheControl;
|
|
214
244
|
|
|
215
245
|
// Resolve warmup enabled flag (default: true)
|
|
216
246
|
const warmupEnabled = warmupOption !== false;
|
|
217
247
|
|
|
248
|
+
// Resolve StrictMode flag (default: true). Shipped to the client in payload
|
|
249
|
+
// metadata; the browser entry reads it once to decide whether to wrap the
|
|
250
|
+
// hydrated tree in React.StrictMode.
|
|
251
|
+
const strictMode = strictModeOption !== false;
|
|
252
|
+
|
|
218
253
|
// Resolve theme config (null if theme not enabled)
|
|
219
254
|
const resolvedThemeConfig = themeOption
|
|
220
255
|
? resolveThemeConfig(themeOption)
|
|
@@ -246,9 +281,14 @@ export function createRouter<TEnv = any>(
|
|
|
246
281
|
invokeOnError(onError, error, phase, context, "Router");
|
|
247
282
|
}
|
|
248
283
|
|
|
249
|
-
// Validate document is a client component
|
|
284
|
+
// Validate document is a client component. Under a test runner the "use
|
|
285
|
+
// client" transform has not run, so a real exported document has no marker;
|
|
286
|
+
// allowServerInTest lets the router construct in a bare unit test (for
|
|
287
|
+
// dispatch / assertGeneratedRoutesMatch) while a real build still throws.
|
|
250
288
|
if (documentOption !== undefined) {
|
|
251
|
-
assertClientComponent(documentOption, "document"
|
|
289
|
+
assertClientComponent(documentOption, "document", {
|
|
290
|
+
allowServerInTest: true,
|
|
291
|
+
});
|
|
252
292
|
}
|
|
253
293
|
|
|
254
294
|
// Use default document if none provided (keeps internal name as rootLayout)
|
|
@@ -312,7 +352,7 @@ export function createRouter<TEnv = any>(
|
|
|
312
352
|
let regex: RegExp | null = null;
|
|
313
353
|
let paramNames: string[] = [];
|
|
314
354
|
if (fullPattern) {
|
|
315
|
-
const parsed =
|
|
355
|
+
const parsed = compileMiddlewarePattern(fullPattern);
|
|
316
356
|
regex = parsed.regex;
|
|
317
357
|
paramNames = parsed.paramNames;
|
|
318
358
|
}
|
|
@@ -322,7 +362,6 @@ export function createRouter<TEnv = any>(
|
|
|
322
362
|
regex,
|
|
323
363
|
paramNames,
|
|
324
364
|
handler,
|
|
325
|
-
mountPrefix,
|
|
326
365
|
});
|
|
327
366
|
}
|
|
328
367
|
|
|
@@ -356,9 +395,11 @@ export function createRouter<TEnv = any>(
|
|
|
356
395
|
getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
357
396
|
if (current !== precomputedSource) {
|
|
358
397
|
precomputedSource = current;
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
398
|
+
// buildPrecomputedByPrefix drops any staticPrefix owned by more than one
|
|
399
|
+
// leaf include instead of collapsing it last-wins (which would mis-assign
|
|
400
|
+
// one include's routes to another's entry and 500 a valid sibling route).
|
|
401
|
+
// Such shared-prefix includes resolve via the handler path instead.
|
|
402
|
+
precomputedByPrefix = current ? buildPrecomputedByPrefix(current) : null;
|
|
362
403
|
}
|
|
363
404
|
return precomputedByPrefix;
|
|
364
405
|
}
|
|
@@ -528,6 +569,7 @@ export function createRouter<TEnv = any>(
|
|
|
528
569
|
findNearestNotFoundBoundary,
|
|
529
570
|
notFoundComponent: notFound,
|
|
530
571
|
callOnError,
|
|
572
|
+
viewTransitionDefault: viewTransitionOption,
|
|
531
573
|
};
|
|
532
574
|
|
|
533
575
|
// Match API dependencies
|
|
@@ -615,6 +657,8 @@ export function createRouter<TEnv = any>(
|
|
|
615
657
|
params: Record<string, string>,
|
|
616
658
|
buildVars?: Record<string, any>,
|
|
617
659
|
isPassthroughRoute?: boolean,
|
|
660
|
+
buildEnv?: TEnv,
|
|
661
|
+
devMode?: boolean,
|
|
618
662
|
) {
|
|
619
663
|
return _matchForPrerender(
|
|
620
664
|
pathname,
|
|
@@ -622,6 +666,8 @@ export function createRouter<TEnv = any>(
|
|
|
622
666
|
prerenderDeps,
|
|
623
667
|
buildVars,
|
|
624
668
|
isPassthroughRoute,
|
|
669
|
+
buildEnv,
|
|
670
|
+
devMode,
|
|
625
671
|
);
|
|
626
672
|
}
|
|
627
673
|
|
|
@@ -629,12 +675,16 @@ export function createRouter<TEnv = any>(
|
|
|
629
675
|
handler: Function,
|
|
630
676
|
handlerId: string,
|
|
631
677
|
routeName?: string,
|
|
678
|
+
buildEnv?: TEnv,
|
|
679
|
+
devMode?: boolean,
|
|
632
680
|
) {
|
|
633
681
|
return _renderStaticSegment<TEnv>(
|
|
634
682
|
handler,
|
|
635
683
|
handlerId,
|
|
636
684
|
mergedRouteMap,
|
|
637
685
|
routeName,
|
|
686
|
+
buildEnv,
|
|
687
|
+
devMode,
|
|
638
688
|
);
|
|
639
689
|
}
|
|
640
690
|
|
|
@@ -647,6 +697,7 @@ export function createRouter<TEnv = any>(
|
|
|
647
697
|
findMatch,
|
|
648
698
|
findInterceptForRoute,
|
|
649
699
|
telemetry: telemetrySink,
|
|
700
|
+
cacheSignalEnabled,
|
|
650
701
|
});
|
|
651
702
|
|
|
652
703
|
const { match, matchPartial, matchError, previewMatch } = matchHandlers;
|
|
@@ -656,11 +707,18 @@ export function createRouter<TEnv = any>(
|
|
|
656
707
|
* The type system tracks accumulated routes through the builder chain
|
|
657
708
|
* Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
|
|
658
709
|
*/
|
|
659
|
-
const router:
|
|
710
|
+
const router: RangoInternal<TEnv, {}> = {
|
|
660
711
|
__brand: RSC_ROUTER_BRAND,
|
|
661
712
|
id: routerId,
|
|
713
|
+
basename,
|
|
714
|
+
|
|
715
|
+
routes(patternsOrBuilder: UrlPatterns<TEnv> | UrlBuilder<TEnv>): any {
|
|
716
|
+
// Wrap builder functions in urls() automatically
|
|
717
|
+
const urlPatterns: UrlPatterns<TEnv> =
|
|
718
|
+
typeof patternsOrBuilder === "function"
|
|
719
|
+
? (urls(patternsOrBuilder) as UrlPatterns<TEnv>)
|
|
720
|
+
: patternsOrBuilder;
|
|
662
721
|
|
|
663
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
664
722
|
// Store reference for runtime manifest generation
|
|
665
723
|
storedUrlPatterns = urlPatterns;
|
|
666
724
|
const currentMountIndex = mountIndex++;
|
|
@@ -697,7 +755,7 @@ export function createRouter<TEnv = any>(
|
|
|
697
755
|
};
|
|
698
756
|
|
|
699
757
|
let handlerResult: AllUseItems[] = [];
|
|
700
|
-
|
|
758
|
+
RangoContext.run(
|
|
701
759
|
{
|
|
702
760
|
manifest,
|
|
703
761
|
patterns: routePatterns,
|
|
@@ -708,6 +766,10 @@ export function createRouter<TEnv = any>(
|
|
|
708
766
|
counters: {},
|
|
709
767
|
mountIndex: currentMountIndex,
|
|
710
768
|
cacheProfiles: resolvedCacheProfiles,
|
|
769
|
+
// basename sets the initial URL prefix so all path() patterns
|
|
770
|
+
// are registered with the prefix (e.g. "/admin" + "/users" = "/admin/users").
|
|
771
|
+
// No namePrefix — route names stay unprefixed.
|
|
772
|
+
...(basename ? { urlPrefix: basename } : {}),
|
|
711
773
|
},
|
|
712
774
|
() => {
|
|
713
775
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -727,7 +789,7 @@ export function createRouter<TEnv = any>(
|
|
|
727
789
|
if (entry.type === "route" && entry.isPrerender) {
|
|
728
790
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
729
791
|
prerenderRouteKeys.add(name);
|
|
730
|
-
if (entry.
|
|
792
|
+
if (entry.isPassthrough === true) {
|
|
731
793
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
732
794
|
passthroughRouteKeys.add(name);
|
|
733
795
|
}
|
|
@@ -805,10 +867,13 @@ export function createRouter<TEnv = any>(
|
|
|
805
867
|
|
|
806
868
|
// Create placeholder RouteEntry for each lazy include
|
|
807
869
|
for (const lazyInclude of lazyIncludes) {
|
|
808
|
-
// Compute the full URL prefix (combining parent prefix if any)
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
870
|
+
// Compute the full URL prefix (combining parent prefix if any). Use the
|
|
871
|
+
// slash-collapsing join so a trailing-slash parent prefix does not
|
|
872
|
+
// produce a double-slash staticPrefix the trie's sp can never match.
|
|
873
|
+
const fullPrefix = joinPrefix(
|
|
874
|
+
lazyInclude.context.urlPrefix,
|
|
875
|
+
lazyInclude.prefix,
|
|
876
|
+
);
|
|
812
877
|
|
|
813
878
|
const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
814
879
|
prefix: "",
|
|
@@ -856,8 +921,18 @@ export function createRouter<TEnv = any>(
|
|
|
856
921
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
857
922
|
middleware?: MiddlewareFn<TEnv>,
|
|
858
923
|
): any {
|
|
859
|
-
//
|
|
860
|
-
|
|
924
|
+
// Auto-prefix pattern with basename so router-level middleware
|
|
925
|
+
// patterns are router-relative (e.g. "/users/*" matches "/app/users/*").
|
|
926
|
+
if (basename && typeof patternOrMiddleware === "string") {
|
|
927
|
+
const pattern = patternOrMiddleware;
|
|
928
|
+
const prefixed =
|
|
929
|
+
pattern === "/*" || pattern === "*"
|
|
930
|
+
? `${basename}/*`
|
|
931
|
+
: `${basename}${pattern}`;
|
|
932
|
+
addMiddleware(prefixed, middleware, null);
|
|
933
|
+
} else {
|
|
934
|
+
addMiddleware(patternOrMiddleware, middleware, null);
|
|
935
|
+
}
|
|
861
936
|
return router;
|
|
862
937
|
},
|
|
863
938
|
|
|
@@ -894,12 +969,22 @@ export function createRouter<TEnv = any>(
|
|
|
894
969
|
prefetchCacheControl,
|
|
895
970
|
prefetchCacheTTL,
|
|
896
971
|
|
|
972
|
+
// Expose the resolved rango state cookie name for the server-side writer
|
|
973
|
+
// (invalidateClientCache) and for shipping to the client in metadata.
|
|
974
|
+
resolvedStateCookieName,
|
|
975
|
+
|
|
897
976
|
// Expose warmup enabled flag for handler and client
|
|
898
977
|
warmupEnabled,
|
|
899
978
|
|
|
979
|
+
// Expose StrictMode flag for the initial-render payload metadata
|
|
980
|
+
strictMode,
|
|
981
|
+
|
|
900
982
|
// Expose router-wide performance debugging for request-level metrics setup
|
|
901
983
|
debugPerformance,
|
|
902
984
|
|
|
985
|
+
// Expose resolved span tracing for the handler (Cloudflare custom spans)
|
|
986
|
+
tracing: resolvedTracing,
|
|
987
|
+
|
|
903
988
|
// Expose debug manifest flag for handler
|
|
904
989
|
allowDebugManifest: allowDebugManifestOption,
|
|
905
990
|
|
|
@@ -958,6 +1043,16 @@ export function createRouter<TEnv = any>(
|
|
|
958
1043
|
// Expose source file for per-router type generation
|
|
959
1044
|
__sourceFile,
|
|
960
1045
|
|
|
1046
|
+
// Expose basename for runtime manifest generation
|
|
1047
|
+
__basename: basename,
|
|
1048
|
+
|
|
1049
|
+
// Expose router-level boundary defaults for build-time clientChunks
|
|
1050
|
+
// discovery (so a "use client" default boundary lands in app-fallback).
|
|
1051
|
+
// These are createRouter options, never pushed onto EntryData.
|
|
1052
|
+
__defaultErrorBoundary: defaultErrorBoundary,
|
|
1053
|
+
__defaultNotFoundBoundary: defaultNotFoundBoundary,
|
|
1054
|
+
__notFound: notFound,
|
|
1055
|
+
|
|
961
1056
|
// RSC request handler (lazily created on first call)
|
|
962
1057
|
fetch: (() => {
|
|
963
1058
|
// Handler is created on first call and reused
|
|
@@ -975,8 +1070,10 @@ export function createRouter<TEnv = any>(
|
|
|
975
1070
|
if (!handler) {
|
|
976
1071
|
// Lazy import deferred to first request to avoid dev mode issues
|
|
977
1072
|
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
978
|
-
// Cast:
|
|
979
|
-
//
|
|
1073
|
+
// Cast: createRSCHandler receives `router as any`, which erases TEnv
|
|
1074
|
+
// and infers its handler as RouterRequestInput<unknown>. Re-narrow the
|
|
1075
|
+
// returned handler to RouterRequestInput<TEnv> so the call below stays
|
|
1076
|
+
// typed. (The handler already accepts (request, RouterRequestInput).)
|
|
980
1077
|
handler = createRSCHandler({
|
|
981
1078
|
router: router as any,
|
|
982
1079
|
cache,
|
|
@@ -991,6 +1088,10 @@ export function createRouter<TEnv = any>(
|
|
|
991
1088
|
};
|
|
992
1089
|
})(),
|
|
993
1090
|
|
|
1091
|
+
// Low-level route matching for request classification
|
|
1092
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1093
|
+
findMatch(pathname, metricsStore),
|
|
1094
|
+
|
|
994
1095
|
// Debug utility for manifest inspection
|
|
995
1096
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
996
1097
|
};
|
|
@@ -999,8 +1100,10 @@ export function createRouter<TEnv = any>(
|
|
|
999
1100
|
RouterRegistry.set(routerId, router);
|
|
1000
1101
|
|
|
1001
1102
|
// If urls option was provided, auto-register them
|
|
1002
|
-
if (urlsOption) {
|
|
1003
|
-
return router.routes(urlsOption) as
|
|
1103
|
+
if (typeof urlsOption === "function") {
|
|
1104
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
1105
|
+
} else if (urlsOption) {
|
|
1106
|
+
return router.routes(urlsOption) as Rango<TEnv, {}>;
|
|
1004
1107
|
}
|
|
1005
1108
|
|
|
1006
1109
|
return router;
|
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
* RSC rendering) so they can be standalone modules without closure coupling.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import type {
|
|
9
|
+
import type { RangoInternal } from "../router/router-interfaces.js";
|
|
10
10
|
import type { ErrorPhase } from "../types.js";
|
|
11
11
|
import type { InvokeOnErrorContext } from "../router/error-handling.js";
|
|
12
12
|
import type { RSCDependencies, LoadSSRModule } from "./types.js";
|
|
13
13
|
import type { SSRStreamMode } from "../router/router-options.js";
|
|
14
14
|
|
|
15
15
|
export interface HandlerContext<TEnv = unknown> {
|
|
16
|
-
router:
|
|
16
|
+
router: RangoInternal<TEnv, any>;
|
|
17
17
|
version: string;
|
|
18
18
|
renderToReadableStream: RSCDependencies["renderToReadableStream"];
|
|
19
19
|
decodeReply: RSCDependencies["decodeReply"];
|
|
@@ -31,6 +31,7 @@ export interface HandlerContext<TEnv = unknown> {
|
|
|
31
31
|
createRedirectFlightResponse: (
|
|
32
32
|
redirectUrl: string,
|
|
33
33
|
locationState?: Record<string, unknown>,
|
|
34
|
+
external?: boolean,
|
|
34
35
|
) => Response;
|
|
35
36
|
|
|
36
37
|
/**
|