@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1c0bdfad
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +17 -0
- package/README.md +291 -61
- package/dist/bin/rango.js +544 -143
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +3744 -1329
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +67 -13
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +312 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +247 -23
- package/skills/caching/SKILL.md +322 -19
- package/skills/composability/SKILL.md +27 -2
- 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 +282 -60
- package/skills/host-router/SKILL.md +278 -0
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +50 -6
- package/skills/layout/SKILL.md +35 -9
- package/skills/links/SKILL.md +249 -17
- package/skills/loader/SKILL.md +297 -31
- 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 +203 -7
- package/skills/prerender/SKILL.md +155 -111
- package/skills/rango/SKILL.md +251 -23
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +123 -48
- package/skills/route/SKILL.md +104 -9
- package/skills/router-setup/SKILL.md +124 -11
- 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 +125 -222
- package/skills/testing/bindings.md +103 -0
- package/skills/testing/cache-prerender.md +127 -0
- package/skills/testing/client-components.md +124 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +91 -0
- package/skills/testing/handles.md +129 -0
- package/skills/testing/loader.md +128 -0
- package/skills/testing/middleware.md +99 -0
- package/skills/testing/render-handler.md +121 -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 +357 -52
- package/skills/use-cache/SKILL.md +46 -14
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +116 -0
- package/src/__internal.ts +67 -40
- package/src/bin/rango.ts +18 -0
- 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 +197 -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/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +200 -30
- package/src/browser/navigation-client.ts +217 -58
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +76 -67
- package/src/browser/navigation-transaction.ts +18 -66
- package/src/browser/network-error-handler.ts +34 -7
- package/src/browser/partial-update.ts +187 -112
- package/src/browser/prefetch/cache.ts +312 -30
- package/src/browser/prefetch/fetch.ts +344 -47
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +126 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/rango-state.ts +158 -76
- package/src/browser/react/Link.tsx +125 -18
- package/src/browser/react/NavigationProvider.tsx +135 -120
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/context.ts +7 -2
- 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 +80 -5
- package/src/browser/rsc-router.tsx +226 -75
- package/src/browser/scroll-restoration.ts +54 -42
- package/src/browser/segment-reconciler.ts +36 -9
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +619 -442
- package/src/browser/types.ts +115 -11
- 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 +7 -1
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +182 -37
- 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 +392 -106
- 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 +214 -48
- package/src/cache/cache-scope.ts +236 -89
- 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 +2224 -171
- 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 +11 -17
- package/src/cache/document-cache.ts +89 -27
- package/src/cache/handle-snapshot.ts +70 -0
- package/src/cache/index.ts +11 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +31 -31
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +9 -17
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/taint.ts +55 -0
- package/src/cache/types.ts +37 -100
- package/src/client.rsc.tsx +45 -21
- package/src/client.tsx +120 -336
- 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 +84 -2
- package/src/debug.ts +2 -2
- 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 +56 -19
- package/src/handles/Scripts.tsx +183 -0
- package/src/handles/breadcrumbs.ts +95 -0
- 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 -5
- 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 +79 -29
- package/src/index.ts +149 -65
- 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 +63 -26
- 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 +7 -72
- package/src/route-definition/dsl-helpers.ts +469 -276
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +113 -37
- package/src/route-definition/index.ts +3 -3
- package/src/route-definition/redirect.ts +53 -12
- package/src/route-definition/resolve-handler-use.ts +161 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +7 -17
- package/src/route-types.ts +37 -41
- 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 +45 -22
- package/src/router/handler-context.ts +110 -39
- package/src/router/instrument.ts +350 -0
- package/src/router/intercept-resolution.ts +50 -24
- package/src/router/lazy-includes.ts +19 -53
- package/src/router/loader-resolution.ts +274 -56
- package/src/router/logging.ts +5 -8
- package/src/router/manifest.ts +49 -45
- package/src/router/match-api.ts +121 -205
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +58 -58
- package/src/router/match-middleware/background-revalidation.ts +33 -6
- package/src/router/match-middleware/cache-lookup.ts +214 -263
- package/src/router/match-middleware/cache-store.ts +73 -33
- package/src/router/match-middleware/intercept-resolution.ts +8 -28
- package/src/router/match-middleware/segment-resolution.ts +52 -18
- package/src/router/match-pipelines.ts +1 -42
- package/src/router/match-result.ts +104 -49
- package/src/router/metrics.ts +217 -26
- package/src/router/middleware-types.ts +24 -110
- package/src/router/middleware.ts +384 -197
- package/src/router/navigation-snapshot.ts +131 -0
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +148 -91
- package/src/router/prefetch-cache-ttl.ts +51 -0
- package/src/router/prerender-match.ts +199 -56
- package/src/router/preview-match.ts +32 -102
- package/src/router/request-classification.ts +276 -0
- package/src/router/revalidation.ts +144 -74
- package/src/router/route-snapshot.ts +244 -0
- package/src/router/router-context.ts +8 -28
- package/src/router/router-interfaces.ts +129 -36
- package/src/router/router-options.ts +185 -23
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +281 -76
- package/src/router/segment-resolution/helpers.ts +116 -31
- package/src/router/segment-resolution/loader-cache.ts +63 -37
- package/src/router/segment-resolution/revalidation.ts +493 -391
- 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 +36 -0
- package/src/router/segment-resolution.ts +5 -1
- package/src/router/segment-wrappers.ts +8 -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 +180 -58
- package/src/router/types.ts +10 -63
- package/src/router/url-params.ts +44 -0
- package/src/router.ts +182 -54
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +702 -460
- package/src/rsc/helpers.ts +168 -46
- package/src/rsc/index.ts +2 -25
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/loader-fetch.ts +127 -31
- package/src/rsc/manifest-init.ts +33 -42
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +98 -19
- 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 +126 -106
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +269 -114
- package/src/rsc/ssr-setup.ts +144 -0
- package/src/rsc/types.ts +34 -6
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +49 -41
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +149 -0
- package/src/segment-system.tsx +281 -129
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +317 -63
- 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 +26 -46
- package/src/server/request-context.ts +425 -177
- package/src/server.ts +6 -0
- package/src/ssr/index.tsx +25 -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 +99 -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 +343 -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/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 +3 -19
- 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 +236 -88
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +44 -15
- package/src/types/request-scope.ts +112 -0
- package/src/types/route-config.ts +10 -45
- package/src/types/route-entry.ts +19 -7
- package/src/types/segments.ts +37 -19
- package/src/urls/include-helper.ts +33 -70
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +58 -11
- 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 -18
- package/src/use-loader.tsx +346 -89
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +64 -91
- package/src/vite/discovery/discover-routers.ts +147 -88
- 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 +247 -145
- 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 +61 -13
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +10 -3
- package/src/vite/inject-client-debug.ts +36 -0
- package/src/vite/plugin-types.ts +155 -65
- package/src/vite/plugins/cjs-to-esm.ts +16 -19
- package/src/vite/plugins/client-ref-dedup.ts +120 -0
- 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 +49 -98
- 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 +89 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/use-cache-transform.ts +73 -83
- package/src/vite/plugins/version-injector.ts +21 -25
- package/src/vite/plugins/version-plugin.ts +46 -37
- package/src/vite/plugins/virtual-entries.ts +13 -18
- package/src/vite/rango.ts +241 -287
- package/src/vite/router-discovery.ts +956 -149
- package/src/vite/utils/ast-handler-extract.ts +26 -35
- package/src/vite/utils/banner.ts +4 -4
- 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 +141 -34
- package/src/vite/utils/shared-utils.ts +92 -42
- package/CLAUDE.md +0 -5
- package/src/browser/action-response-classifier.ts +0 -99
- package/src/browser/react/use-client-cache.ts +0 -58
- package/src/browser/shallow.ts +0 -40
- package/src/handles/index.ts +0 -6
- package/src/network-error-thrower.tsx +0 -23
- package/src/route-definition/route-function.ts +0 -119
- 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,
|
|
@@ -147,25 +149,47 @@ export function createRouter<TEnv = any>(
|
|
|
147
149
|
$$sourceFile: injectedSourceFile,
|
|
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,15 +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
|
-
|
|
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;
|
|
242
|
+
const prefetchCacheControl: string | false =
|
|
243
|
+
resolvedPrefetchCacheTTL.cacheControl;
|
|
208
244
|
|
|
209
245
|
// Resolve warmup enabled flag (default: true)
|
|
210
246
|
const warmupEnabled = warmupOption !== false;
|
|
211
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
|
+
|
|
212
253
|
// Resolve theme config (null if theme not enabled)
|
|
213
254
|
const resolvedThemeConfig = themeOption
|
|
214
255
|
? resolveThemeConfig(themeOption)
|
|
@@ -240,9 +281,14 @@ export function createRouter<TEnv = any>(
|
|
|
240
281
|
invokeOnError(onError, error, phase, context, "Router");
|
|
241
282
|
}
|
|
242
283
|
|
|
243
|
-
// 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.
|
|
244
288
|
if (documentOption !== undefined) {
|
|
245
|
-
assertClientComponent(documentOption, "document"
|
|
289
|
+
assertClientComponent(documentOption, "document", {
|
|
290
|
+
allowServerInTest: true,
|
|
291
|
+
});
|
|
246
292
|
}
|
|
247
293
|
|
|
248
294
|
// Use default document if none provided (keeps internal name as rootLayout)
|
|
@@ -306,7 +352,7 @@ export function createRouter<TEnv = any>(
|
|
|
306
352
|
let regex: RegExp | null = null;
|
|
307
353
|
let paramNames: string[] = [];
|
|
308
354
|
if (fullPattern) {
|
|
309
|
-
const parsed =
|
|
355
|
+
const parsed = compileMiddlewarePattern(fullPattern);
|
|
310
356
|
regex = parsed.regex;
|
|
311
357
|
paramNames = parsed.paramNames;
|
|
312
358
|
}
|
|
@@ -316,7 +362,6 @@ export function createRouter<TEnv = any>(
|
|
|
316
362
|
regex,
|
|
317
363
|
paramNames,
|
|
318
364
|
handler,
|
|
319
|
-
mountPrefix,
|
|
320
365
|
});
|
|
321
366
|
}
|
|
322
367
|
|
|
@@ -350,15 +395,27 @@ export function createRouter<TEnv = any>(
|
|
|
350
395
|
getRouterPrecomputedEntries(routerId) ?? getPrecomputedEntries();
|
|
351
396
|
if (current !== precomputedSource) {
|
|
352
397
|
precomputedSource = current;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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;
|
|
356
403
|
}
|
|
357
404
|
return precomputedByPrefix;
|
|
358
405
|
}
|
|
359
406
|
|
|
360
|
-
// Wrapper to pass debugPerformance to external createMetricsStore
|
|
361
|
-
|
|
407
|
+
// Wrapper to pass debugPerformance to external createMetricsStore.
|
|
408
|
+
// Also checks per-request flag set by ctx.debugPerformance() in middleware.
|
|
409
|
+
const getMetricsStore = () => {
|
|
410
|
+
const reqCtx = _getRequestContext();
|
|
411
|
+
const enabled = debugPerformance || !!reqCtx?._debugPerformance;
|
|
412
|
+
if (!enabled) return undefined;
|
|
413
|
+
if (!reqCtx) {
|
|
414
|
+
return createMetricsStore(true);
|
|
415
|
+
}
|
|
416
|
+
reqCtx._metricsStore ??= createMetricsStore(true);
|
|
417
|
+
return reqCtx._metricsStore;
|
|
418
|
+
};
|
|
362
419
|
|
|
363
420
|
// Wrapper to pass defaults to error/notFound boundary finders
|
|
364
421
|
const findNearestErrorBoundary = (entry: EntryData | null) =>
|
|
@@ -510,7 +567,9 @@ export function createRouter<TEnv = any>(
|
|
|
510
567
|
trackHandler,
|
|
511
568
|
findNearestErrorBoundary,
|
|
512
569
|
findNearestNotFoundBoundary,
|
|
570
|
+
notFoundComponent: notFound,
|
|
513
571
|
callOnError,
|
|
572
|
+
viewTransitionDefault: viewTransitionOption,
|
|
514
573
|
};
|
|
515
574
|
|
|
516
575
|
// Match API dependencies
|
|
@@ -544,6 +603,7 @@ export function createRouter<TEnv = any>(
|
|
|
544
603
|
mergedRouteMap,
|
|
545
604
|
nextMountIndex: () => mountIndex++,
|
|
546
605
|
getPrecomputedByPrefix,
|
|
606
|
+
routerId,
|
|
547
607
|
};
|
|
548
608
|
|
|
549
609
|
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void {
|
|
@@ -597,6 +657,8 @@ export function createRouter<TEnv = any>(
|
|
|
597
657
|
params: Record<string, string>,
|
|
598
658
|
buildVars?: Record<string, any>,
|
|
599
659
|
isPassthroughRoute?: boolean,
|
|
660
|
+
buildEnv?: TEnv,
|
|
661
|
+
devMode?: boolean,
|
|
600
662
|
) {
|
|
601
663
|
return _matchForPrerender(
|
|
602
664
|
pathname,
|
|
@@ -604,6 +666,8 @@ export function createRouter<TEnv = any>(
|
|
|
604
666
|
prerenderDeps,
|
|
605
667
|
buildVars,
|
|
606
668
|
isPassthroughRoute,
|
|
669
|
+
buildEnv,
|
|
670
|
+
devMode,
|
|
607
671
|
);
|
|
608
672
|
}
|
|
609
673
|
|
|
@@ -611,12 +675,16 @@ export function createRouter<TEnv = any>(
|
|
|
611
675
|
handler: Function,
|
|
612
676
|
handlerId: string,
|
|
613
677
|
routeName?: string,
|
|
678
|
+
buildEnv?: TEnv,
|
|
679
|
+
devMode?: boolean,
|
|
614
680
|
) {
|
|
615
681
|
return _renderStaticSegment<TEnv>(
|
|
616
682
|
handler,
|
|
617
683
|
handlerId,
|
|
618
684
|
mergedRouteMap,
|
|
619
685
|
routeName,
|
|
686
|
+
buildEnv,
|
|
687
|
+
devMode,
|
|
620
688
|
);
|
|
621
689
|
}
|
|
622
690
|
|
|
@@ -629,6 +697,7 @@ export function createRouter<TEnv = any>(
|
|
|
629
697
|
findMatch,
|
|
630
698
|
findInterceptForRoute,
|
|
631
699
|
telemetry: telemetrySink,
|
|
700
|
+
cacheSignalEnabled,
|
|
632
701
|
});
|
|
633
702
|
|
|
634
703
|
const { match, matchPartial, matchError, previewMatch } = matchHandlers;
|
|
@@ -638,11 +707,18 @@ export function createRouter<TEnv = any>(
|
|
|
638
707
|
* The type system tracks accumulated routes through the builder chain
|
|
639
708
|
* Initial TRoutes is {} (empty) to avoid poisoning accumulated types with Record<string, string>
|
|
640
709
|
*/
|
|
641
|
-
const router:
|
|
710
|
+
const router: RangoInternal<TEnv, {}> = {
|
|
642
711
|
__brand: RSC_ROUTER_BRAND,
|
|
643
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;
|
|
644
721
|
|
|
645
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
646
722
|
// Store reference for runtime manifest generation
|
|
647
723
|
storedUrlPatterns = urlPatterns;
|
|
648
724
|
const currentMountIndex = mountIndex++;
|
|
@@ -673,13 +749,13 @@ export function createRouter<TEnv = any>(
|
|
|
673
749
|
errorBoundary: [],
|
|
674
750
|
notFoundBoundary: [],
|
|
675
751
|
layout: [],
|
|
676
|
-
parallel:
|
|
752
|
+
parallel: {},
|
|
677
753
|
intercept: [],
|
|
678
754
|
loader: [],
|
|
679
755
|
};
|
|
680
756
|
|
|
681
757
|
let handlerResult: AllUseItems[] = [];
|
|
682
|
-
|
|
758
|
+
RangoContext.run(
|
|
683
759
|
{
|
|
684
760
|
manifest,
|
|
685
761
|
patterns: routePatterns,
|
|
@@ -690,6 +766,10 @@ export function createRouter<TEnv = any>(
|
|
|
690
766
|
counters: {},
|
|
691
767
|
mountIndex: currentMountIndex,
|
|
692
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 } : {}),
|
|
693
773
|
},
|
|
694
774
|
() => {
|
|
695
775
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -709,7 +789,7 @@ export function createRouter<TEnv = any>(
|
|
|
709
789
|
if (entry.type === "route" && entry.isPrerender) {
|
|
710
790
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
711
791
|
prerenderRouteKeys.add(name);
|
|
712
|
-
if (entry.
|
|
792
|
+
if (entry.isPassthrough === true) {
|
|
713
793
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
714
794
|
passthroughRouteKeys.add(name);
|
|
715
795
|
}
|
|
@@ -735,6 +815,7 @@ export function createRouter<TEnv = any>(
|
|
|
735
815
|
trailingSlash: trailingSlashConfig,
|
|
736
816
|
handler: urlPatterns.handler,
|
|
737
817
|
mountIndex: currentMountIndex,
|
|
818
|
+
routerId,
|
|
738
819
|
cacheProfiles: resolvedCacheProfiles,
|
|
739
820
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
740
821
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -754,6 +835,7 @@ export function createRouter<TEnv = any>(
|
|
|
754
835
|
trailingSlash: trailingSlashConfig,
|
|
755
836
|
handler: urlPatterns.handler,
|
|
756
837
|
mountIndex: currentMountIndex,
|
|
838
|
+
routerId,
|
|
757
839
|
cacheProfiles: resolvedCacheProfiles,
|
|
758
840
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
759
841
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -785,10 +867,13 @@ export function createRouter<TEnv = any>(
|
|
|
785
867
|
|
|
786
868
|
// Create placeholder RouteEntry for each lazy include
|
|
787
869
|
for (const lazyInclude of lazyIncludes) {
|
|
788
|
-
// Compute the full URL prefix (combining parent prefix if any)
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
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
|
+
);
|
|
792
877
|
|
|
793
878
|
const lazyEntry: RouteEntry<TEnv> & { _lazyPrefix?: string } = {
|
|
794
879
|
prefix: "",
|
|
@@ -797,6 +882,7 @@ export function createRouter<TEnv = any>(
|
|
|
797
882
|
trailingSlash: trailingSlashConfig,
|
|
798
883
|
handler: urlPatterns.handler,
|
|
799
884
|
mountIndex: mountIndex++,
|
|
885
|
+
routerId,
|
|
800
886
|
// Lazy evaluation fields
|
|
801
887
|
lazy: true,
|
|
802
888
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -835,8 +921,18 @@ export function createRouter<TEnv = any>(
|
|
|
835
921
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
836
922
|
middleware?: MiddlewareFn<TEnv>,
|
|
837
923
|
): any {
|
|
838
|
-
//
|
|
839
|
-
|
|
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
|
+
}
|
|
840
936
|
return router;
|
|
841
937
|
},
|
|
842
938
|
|
|
@@ -869,12 +965,26 @@ export function createRouter<TEnv = any>(
|
|
|
869
965
|
// Expose resolved cache profiles for per-request resolution
|
|
870
966
|
cacheProfiles: resolvedCacheProfiles,
|
|
871
967
|
|
|
872
|
-
// Expose prefetch cache
|
|
968
|
+
// Expose prefetch cache settings
|
|
873
969
|
prefetchCacheControl,
|
|
970
|
+
prefetchCacheTTL,
|
|
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,
|
|
874
975
|
|
|
875
976
|
// Expose warmup enabled flag for handler and client
|
|
876
977
|
warmupEnabled,
|
|
877
978
|
|
|
979
|
+
// Expose StrictMode flag for the initial-render payload metadata
|
|
980
|
+
strictMode,
|
|
981
|
+
|
|
982
|
+
// Expose router-wide performance debugging for request-level metrics setup
|
|
983
|
+
debugPerformance,
|
|
984
|
+
|
|
985
|
+
// Expose resolved span tracing for the handler (Cloudflare custom spans)
|
|
986
|
+
tracing: resolvedTracing,
|
|
987
|
+
|
|
878
988
|
// Expose debug manifest flag for handler
|
|
879
989
|
allowDebugManifest: allowDebugManifestOption,
|
|
880
990
|
|
|
@@ -933,6 +1043,16 @@ export function createRouter<TEnv = any>(
|
|
|
933
1043
|
// Expose source file for per-router type generation
|
|
934
1044
|
__sourceFile,
|
|
935
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
|
+
|
|
936
1056
|
// RSC request handler (lazily created on first call)
|
|
937
1057
|
fetch: (() => {
|
|
938
1058
|
// Handler is created on first call and reused
|
|
@@ -950,8 +1070,10 @@ export function createRouter<TEnv = any>(
|
|
|
950
1070
|
if (!handler) {
|
|
951
1071
|
// Lazy import deferred to first request to avoid dev mode issues
|
|
952
1072
|
const { createRSCHandler } = await import("./rsc/handler.js");
|
|
953
|
-
// Cast:
|
|
954
|
-
//
|
|
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).)
|
|
955
1077
|
handler = createRSCHandler({
|
|
956
1078
|
router: router as any,
|
|
957
1079
|
cache,
|
|
@@ -966,6 +1088,10 @@ export function createRouter<TEnv = any>(
|
|
|
966
1088
|
};
|
|
967
1089
|
})(),
|
|
968
1090
|
|
|
1091
|
+
// Low-level route matching for request classification
|
|
1092
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1093
|
+
findMatch(pathname, metricsStore),
|
|
1094
|
+
|
|
969
1095
|
// Debug utility for manifest inspection
|
|
970
1096
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
971
1097
|
};
|
|
@@ -974,8 +1100,10 @@ export function createRouter<TEnv = any>(
|
|
|
974
1100
|
RouterRegistry.set(routerId, router);
|
|
975
1101
|
|
|
976
1102
|
// If urls option was provided, auto-register them
|
|
977
|
-
if (urlsOption) {
|
|
978
|
-
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, {}>;
|
|
979
1107
|
}
|
|
980
1108
|
|
|
981
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
|
/**
|