@rangojs/router 0.0.0-experimental.97 → 0.0.0-experimental.98914650
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -9
- package/dist/bin/rango.js +157 -63
- package/dist/testing/vitest.js +82 -0
- package/dist/vite/index.js +1584 -639
- package/package.json +71 -21
- package/skills/api-client/SKILL.md +211 -0
- package/skills/breadcrumbs/SKILL.md +60 -0
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +222 -30
- package/skills/caching/SKILL.md +263 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/css/SKILL.md +76 -0
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +3 -1
- package/skills/hooks/SKILL.md +235 -28
- package/skills/host-router/SKILL.md +122 -22
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +29 -5
- package/skills/layout/SKILL.md +13 -9
- package/skills/links/SKILL.md +173 -17
- package/skills/loader/SKILL.md +170 -23
- package/skills/middleware/SKILL.md +16 -10
- package/skills/migrate-nextjs/SKILL.md +38 -16
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +11 -7
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +250 -25
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +114 -47
- package/skills/route/SKILL.md +42 -5
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +78 -42
- package/skills/tailwind/SKILL.md +27 -3
- package/skills/testing/SKILL.md +129 -0
- package/skills/testing/bindings.md +89 -0
- package/skills/testing/cache-prerender.md +124 -0
- package/skills/testing/client-components.md +122 -0
- package/skills/testing/e2e-parity.md +125 -0
- package/skills/testing/flight.md +92 -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 +120 -0
- package/skills/typesafety/SKILL.md +316 -26
- package/skills/use-cache/SKILL.md +36 -5
- package/skills/vercel/SKILL.md +107 -0
- 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 +0 -65
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/action-fence.ts +47 -0
- package/src/browser/app-shell.ts +14 -27
- package/src/browser/cookie-name.ts +140 -0
- package/src/browser/event-controller.ts +37 -143
- 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 +30 -59
- package/src/browser/navigation-client.ts +96 -84
- package/src/browser/navigation-store-handle.ts +38 -0
- package/src/browser/navigation-store.ts +32 -82
- package/src/browser/navigation-transaction.ts +9 -59
- package/src/browser/partial-update.ts +60 -127
- package/src/browser/prefetch/cache.ts +82 -72
- package/src/browser/prefetch/fetch.ts +108 -33
- package/src/browser/prefetch/queue.ts +6 -3
- package/src/browser/rango-state.ts +157 -115
- package/src/browser/react/Link.tsx +0 -2
- package/src/browser/react/NavigationProvider.tsx +41 -48
- package/src/browser/react/ScrollRestoration.tsx +10 -6
- package/src/browser/react/filter-segment-order.ts +0 -2
- package/src/browser/react/index.ts +0 -48
- package/src/browser/react/location-state-shared.ts +166 -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 +17 -14
- package/src/browser/react/use-link-status.ts +0 -4
- package/src/browser/react/use-navigation.ts +0 -3
- package/src/browser/react/use-params.ts +11 -11
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +20 -5
- 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 +52 -1
- package/src/browser/rsc-router.tsx +70 -34
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +168 -44
- package/src/browser/types.ts +36 -21
- package/src/browser/validate-redirect-origin.ts +43 -16
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/index.ts +8 -2
- package/src/build/prefix-tree-utils.ts +123 -0
- package/src/build/route-trie.ts +89 -10
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/param-extraction.ts +6 -3
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +122 -22
- package/src/build/route-types/scan-filter.ts +1 -1
- package/src/build/route-types/source-scan.ts +118 -0
- package/src/build/runtime-discovery.ts +9 -20
- package/src/cache/cache-error.ts +104 -0
- package/src/cache/cache-policy.ts +68 -28
- package/src/cache/cache-runtime.ts +134 -32
- package/src/cache/cache-scope.ts +100 -74
- package/src/cache/cache-tag.ts +98 -0
- package/src/cache/cf/cf-cache-store.ts +2255 -238
- package/src/cache/cf/index.ts +6 -16
- package/src/cache/document-cache.ts +61 -20
- package/src/cache/handle-snapshot.ts +63 -0
- package/src/cache/index.ts +22 -20
- package/src/cache/memory-segment-store.ts +136 -37
- package/src/cache/profile-registry.ts +6 -30
- package/src/cache/read-through-swr.ts +41 -11
- package/src/cache/segment-codec.ts +0 -16
- package/src/cache/tag-invalidation.ts +230 -0
- package/src/cache/types.ts +33 -100
- package/src/cache/vercel/index.ts +11 -0
- package/src/cache/vercel/vercel-cache-store.ts +799 -0
- package/src/client.rsc.tsx +6 -21
- package/src/client.tsx +25 -61
- package/src/component-utils.ts +19 -0
- package/src/context-var.ts +17 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/defer.ts +196 -0
- package/src/deps/ssr.ts +0 -1
- package/src/errors.ts +30 -4
- package/src/handle.ts +31 -23
- package/src/handles/MetaTags.tsx +0 -14
- package/src/handles/breadcrumbs.ts +16 -5
- package/src/handles/meta.ts +0 -39
- package/src/host/cookie-handler.ts +0 -36
- package/src/host/errors.ts +0 -24
- package/src/host/index.ts +8 -2
- package/src/host/pattern-matcher.ts +7 -50
- 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 +63 -9
- package/src/index.ts +64 -9
- package/src/internal-debug.ts +2 -4
- 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/network-error-thrower.tsx +1 -6
- package/src/outlet-provider.tsx +1 -5
- package/src/prerender/param-hash.ts +10 -11
- package/src/prerender/store.ts +32 -37
- package/src/prerender.ts +61 -6
- package/src/redirect-origin.ts +100 -0
- package/src/response-utils.ts +9 -0
- package/src/reverse.ts +65 -40
- package/src/root-error-boundary.tsx +1 -19
- package/src/route-content-wrapper.tsx +7 -72
- package/src/route-definition/dsl-helpers.ts +244 -281
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +40 -17
- package/src/route-definition/redirect.ts +43 -9
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-map-builder.ts +0 -16
- package/src/route-types.ts +19 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -15
- package/src/router/error-handling.ts +13 -17
- package/src/router/find-match.ts +44 -23
- package/src/router/handler-context.ts +4 -41
- package/src/router/intercept-resolution.ts +14 -19
- package/src/router/lazy-includes.ts +9 -46
- package/src/router/loader-resolution.ts +91 -46
- package/src/router/logging.ts +0 -6
- package/src/router/manifest.ts +18 -29
- package/src/router/match-api.ts +0 -20
- package/src/router/match-context.ts +0 -22
- package/src/router/match-handlers.ts +57 -58
- package/src/router/match-middleware/background-revalidation.ts +0 -7
- package/src/router/match-middleware/cache-lookup.ts +150 -271
- package/src/router/match-middleware/cache-store.ts +3 -33
- 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 +31 -80
- package/src/router/metrics.ts +0 -34
- package/src/router/middleware-types.ts +5 -112
- package/src/router/middleware.ts +118 -133
- package/src/router/navigation-snapshot.ts +0 -51
- package/src/router/params-util.ts +23 -0
- package/src/router/pattern-matching.ts +62 -67
- package/src/router/prerender-match.ts +99 -63
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +28 -62
- package/src/router/revalidation.ts +50 -56
- package/src/router/route-snapshot.ts +0 -1
- package/src/router/router-context.ts +0 -27
- package/src/router/router-interfaces.ts +68 -35
- package/src/router/router-options.ts +55 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +44 -63
- package/src/router/segment-resolution/helpers.ts +34 -0
- package/src/router/segment-resolution/loader-cache.ts +40 -37
- package/src/router/segment-resolution/revalidation.ts +203 -285
- 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 +4 -1
- package/src/router/segment-wrappers.ts +0 -3
- package/src/router/state-cookie-name.ts +33 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry-otel.ts +0 -20
- package/src/router/telemetry.ts +96 -19
- package/src/router/timeout.ts +0 -20
- package/src/router/trie-matching.ts +87 -48
- package/src/router/types.ts +9 -63
- package/src/router/url-params.ts +0 -5
- package/src/router.ts +80 -41
- package/src/rsc/handler-context.ts +3 -2
- package/src/rsc/handler.ts +83 -78
- package/src/rsc/helpers.ts +93 -5
- package/src/rsc/index.ts +1 -1
- package/src/rsc/json-route-result.ts +38 -0
- package/src/rsc/manifest-init.ts +28 -41
- package/src/rsc/origin-guard.ts +39 -25
- package/src/rsc/progressive-enhancement.ts +12 -1
- package/src/rsc/redirect-guard.ts +99 -0
- package/src/rsc/response-error.ts +79 -12
- package/src/rsc/response-route-handler.ts +76 -62
- package/src/rsc/rsc-rendering.ts +41 -60
- package/src/rsc/runtime-warnings.ts +23 -10
- package/src/rsc/server-action.ts +62 -67
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +10 -5
- package/src/runtime-env.ts +18 -0
- package/src/search-params.ts +4 -20
- package/src/segment-loader-promise.ts +14 -2
- package/src/segment-system.tsx +199 -142
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +150 -51
- package/src/server/cookie-store.ts +80 -5
- package/src/server/handle-store.ts +7 -24
- package/src/server/loader-registry.ts +5 -24
- package/src/server/request-context.ts +165 -87
- package/src/ssr/index.tsx +14 -14
- package/src/static-handler.ts +10 -13
- package/src/testing/cache-status.ts +162 -0
- package/src/testing/collect-handle.ts +40 -0
- package/src/testing/dispatch.ts +618 -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 +232 -0
- package/src/testing/generated-routes.ts +183 -0
- package/src/testing/index.ts +99 -0
- package/src/testing/internal/context.ts +348 -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 +330 -0
- package/src/testing/render-route.tsx +566 -0
- package/src/testing/run-loader.ts +378 -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 +0 -52
- package/src/theme/ThemeScript.tsx +0 -6
- package/src/theme/constants.ts +0 -12
- package/src/theme/index.ts +0 -7
- package/src/theme/theme-context.ts +1 -5
- package/src/theme/theme-script.ts +0 -14
- 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 +54 -41
- package/src/types/handler-context.ts +97 -22
- package/src/types/index.ts +1 -10
- package/src/types/loader-types.ts +6 -3
- package/src/types/request-scope.ts +0 -19
- package/src/types/route-config.ts +6 -50
- package/src/types/route-entry.ts +0 -6
- package/src/types/segments.ts +18 -14
- package/src/urls/include-helper.ts +9 -56
- package/src/urls/index.ts +1 -11
- package/src/urls/path-helper-types.ts +19 -5
- package/src/urls/path-helper.ts +17 -106
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +20 -19
- package/src/urls/type-extraction.ts +58 -139
- package/src/urls/urls-function.ts +1 -18
- package/src/use-loader.tsx +292 -107
- package/src/vite/debug.ts +1 -0
- package/src/vite/discovery/bundle-postprocess.ts +8 -7
- package/src/vite/discovery/discover-routers.ts +95 -82
- package/src/vite/discovery/discovery-errors.ts +194 -0
- package/src/vite/discovery/prerender-collection.ts +26 -34
- package/src/vite/discovery/route-types-writer.ts +40 -84
- package/src/vite/discovery/state.ts +39 -1
- package/src/vite/discovery/virtual-module-codegen.ts +14 -34
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +185 -10
- package/src/vite/plugins/cjs-to-esm.ts +3 -18
- package/src/vite/plugins/client-ref-dedup.ts +0 -11
- package/src/vite/plugins/client-ref-hashing.ts +12 -11
- package/src/vite/plugins/cloudflare-protocol-stub.ts +1 -21
- package/src/vite/plugins/expose-action-id.ts +4 -75
- package/src/vite/plugins/expose-id-utils.ts +3 -54
- package/src/vite/plugins/expose-ids/export-analysis.ts +76 -34
- package/src/vite/plugins/expose-ids/handler-transform.ts +6 -74
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -20
- package/src/vite/plugins/expose-ids/router-transform.ts +0 -13
- package/src/vite/plugins/expose-internal-ids.ts +57 -67
- package/src/vite/plugins/performance-tracks.ts +9 -16
- package/src/vite/plugins/refresh-cmd.ts +1 -1
- package/src/vite/plugins/use-cache-transform.ts +26 -49
- package/src/vite/plugins/vercel-output.ts +258 -0
- package/src/vite/plugins/version-injector.ts +2 -32
- package/src/vite/plugins/version-plugin.ts +32 -23
- package/src/vite/plugins/virtual-entries.ts +35 -17
- package/src/vite/rango.ts +148 -115
- package/src/vite/router-discovery.ts +220 -68
- package/src/vite/utils/ast-handler-extract.ts +15 -31
- package/src/vite/utils/bundle-analysis.ts +10 -15
- package/src/vite/utils/client-chunks.ts +184 -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 +1 -73
- package/src/vite/utils/prerender-utils.ts +0 -34
- package/src/vite/utils/shared-utils.ts +95 -43
- 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 -7
- package/src/router/middleware-cookies.ts +0 -55
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Evaluates whether segments should revalidate based on params, actions, and custom functions.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type { ResolvedSegment, HandlerContext } from "../types";
|
|
7
|
+
import type { ResolvedSegment, HandlerContext, ActionRef } from "../types";
|
|
8
8
|
import type { ActionContext } from "./types";
|
|
9
9
|
import {
|
|
10
10
|
debugLog,
|
|
@@ -14,21 +14,52 @@ import {
|
|
|
14
14
|
import type { RevalidationTraceEntry } from "./logging.js";
|
|
15
15
|
import { _getRequestContext } from "../server/request-context.js";
|
|
16
16
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
17
|
+
import { paramsEqual } from "./params-util.js";
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
):
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a server-action reference's stable id, mirroring how the action
|
|
21
|
+
* boundary derives `actionContext.actionId` in `rsc/server-action.ts`
|
|
22
|
+
* (`$id ?? $$id`): the file-path `$id` set by the expose-action-id plugin in a
|
|
23
|
+
* production RSC build when present, otherwise React's `$$id`. Resolving both
|
|
24
|
+
* the incoming `actionId` and the reference with the same precedence makes
|
|
25
|
+
* `isAction()` form-agnostic across dev and production.
|
|
26
|
+
*/
|
|
27
|
+
function resolveActionRefId(ref: unknown): string | undefined {
|
|
28
|
+
if (ref == null) return undefined;
|
|
29
|
+
const r = ref as { $id?: unknown; $$id?: unknown };
|
|
30
|
+
if (typeof r.$id === "string") return r.$id;
|
|
31
|
+
if (typeof r.$$id === "string") return r.$$id;
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Build the `isAction()` helper bound to the current action's id. Called with no
|
|
37
|
+
* arguments it answers "is this request an action at all?" (any action) — `true`
|
|
38
|
+
* during action handling, `false` on plain navigation. Called with one or more
|
|
39
|
+
* action references it narrows to those: a single imported action, several
|
|
40
|
+
* (variadic), or any export of a namespace import (`import * as Mod`). Returns
|
|
41
|
+
* `false` when there is no action (plain navigation) or nothing matches.
|
|
42
|
+
*/
|
|
43
|
+
function makeIsAction(
|
|
44
|
+
currentActionId: string | undefined,
|
|
45
|
+
): (...actions: ActionRef[]) => boolean {
|
|
46
|
+
return (...actions: ActionRef[]): boolean => {
|
|
47
|
+
if (!currentActionId) return false;
|
|
48
|
+
// Bare isAction(): an action is in flight (currentActionId is set) and the
|
|
49
|
+
// caller did not narrow to a specific action, so this is "any action".
|
|
50
|
+
if (actions.length === 0) return true;
|
|
51
|
+
for (const action of actions) {
|
|
52
|
+
if (typeof action === "function") {
|
|
53
|
+
if (resolveActionRefId(action) === currentActionId) return true;
|
|
54
|
+
} else if (action && typeof action === "object") {
|
|
55
|
+
// Namespace import: match any export of the module.
|
|
56
|
+
for (const value of Object.values(action)) {
|
|
57
|
+
if (resolveActionRefId(value) === currentActionId) return true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
};
|
|
32
63
|
}
|
|
33
64
|
|
|
34
65
|
/**
|
|
@@ -95,8 +126,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
95
126
|
const paramsChanged = !paramsEqual(nextParams, prevParams);
|
|
96
127
|
const searchChanged = prevUrl.search !== nextUrl.search;
|
|
97
128
|
|
|
98
|
-
// Trace helper: push a structured entry to the request-scoped trace buffer.
|
|
99
|
-
// Guarded by isTraceActive() so object construction is skipped in production.
|
|
100
129
|
function pushTrace(
|
|
101
130
|
defaultVal: boolean,
|
|
102
131
|
finalVal: boolean,
|
|
@@ -115,43 +144,28 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
115
144
|
});
|
|
116
145
|
}
|
|
117
146
|
|
|
118
|
-
// Calculate default revalidation based on segment type and request method
|
|
119
147
|
let defaultShouldRevalidate: boolean;
|
|
120
148
|
let defaultReason: string;
|
|
121
149
|
|
|
122
150
|
if (defaultOverride) {
|
|
123
|
-
// Caller injected the seed (e.g. parallel slot not in clientSegmentIds).
|
|
124
|
-
// Skip the type-derived heuristic — caller knows better in this context.
|
|
125
151
|
defaultShouldRevalidate = defaultOverride.value;
|
|
126
152
|
defaultReason = defaultOverride.reason;
|
|
127
153
|
} else if (request.method === "POST") {
|
|
128
|
-
// Actions: revalidate segments that belong to the route, skip parent chain
|
|
129
154
|
if (segment.type === "route") {
|
|
130
|
-
// Route segment always revalidates on actions
|
|
131
155
|
defaultShouldRevalidate = true;
|
|
132
156
|
defaultReason = "action:route-segment";
|
|
133
157
|
} else if (segment.type === "loader") {
|
|
134
|
-
// Loaders always revalidate on actions - they often contain action-sensitive data
|
|
135
|
-
// (e.g., cart count after add-to-cart action)
|
|
136
158
|
defaultShouldRevalidate = true;
|
|
137
159
|
defaultReason = "action:loader-segment";
|
|
138
160
|
} else if (segment.belongsToRoute) {
|
|
139
|
-
// Segment belongs to route (orphan layouts/parallels) - revalidate
|
|
140
161
|
defaultShouldRevalidate = true;
|
|
141
162
|
defaultReason = "action:belongs-to-route";
|
|
142
163
|
} else {
|
|
143
|
-
// Parent chain segment (shared layouts/parallels) - don't revalidate
|
|
144
164
|
defaultShouldRevalidate = false;
|
|
145
165
|
defaultReason = "action:parent-chain-skip";
|
|
146
166
|
}
|
|
147
167
|
} else {
|
|
148
|
-
// Navigation (GET): Conservative defaults to minimize unnecessary revalidations
|
|
149
|
-
// Only the route segment revalidates by default - all others require explicit opt-in
|
|
150
|
-
|
|
151
168
|
if (segment.type === "route") {
|
|
152
|
-
// Route segments revalidate when path params OR search params change.
|
|
153
|
-
// Search params (e.g., ?page=2&sort=price) are server-parsed via ctx.search,
|
|
154
|
-
// so the handler must re-execute to produce updated content.
|
|
155
169
|
const routeChanged = paramsChanged || searchChanged;
|
|
156
170
|
defaultShouldRevalidate = routeChanged;
|
|
157
171
|
defaultReason = paramsChanged
|
|
@@ -167,8 +181,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
167
181
|
});
|
|
168
182
|
}
|
|
169
183
|
} else if (segment.belongsToRoute && (paramsChanged || searchChanged)) {
|
|
170
|
-
// Children of the route path (loaders, orphan layouts/parallels)
|
|
171
|
-
// revalidate when path params or search params change
|
|
172
184
|
defaultShouldRevalidate = true;
|
|
173
185
|
defaultReason = paramsChanged
|
|
174
186
|
? "nav:route-child-params-changed"
|
|
@@ -180,9 +192,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
180
192
|
searchChanged,
|
|
181
193
|
});
|
|
182
194
|
} else {
|
|
183
|
-
// Parent layouts and parallels default to no revalidation
|
|
184
|
-
// Cannot assume these segments depend on params without explicit declaration
|
|
185
|
-
// Use custom revalidation functions to opt-in when needed
|
|
186
195
|
defaultShouldRevalidate = false;
|
|
187
196
|
defaultReason = "nav:non-route-skip";
|
|
188
197
|
debugLog("revalidation", "non-route segment skipped by default", {
|
|
@@ -192,7 +201,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
192
201
|
}
|
|
193
202
|
}
|
|
194
203
|
|
|
195
|
-
// No custom revalidations defined - return default behavior without prev segment
|
|
196
204
|
if (revalidations.length === 0) {
|
|
197
205
|
if (defaultShouldRevalidate) {
|
|
198
206
|
debugLog("revalidation", "default revalidate=true", {
|
|
@@ -209,14 +217,10 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
209
217
|
return defaultShouldRevalidate;
|
|
210
218
|
}
|
|
211
219
|
|
|
212
|
-
// Custom revalidations exist - may need full prev segment
|
|
213
|
-
// Lazy load prev segment only if getPrevSegment provided
|
|
214
220
|
const prevSegment = getPrevSegment ? await getPrevSegment() : null;
|
|
215
221
|
|
|
216
|
-
// Execute revalidation functions with soft/hard decision pattern
|
|
217
222
|
let currentSuggestion = defaultShouldRevalidate;
|
|
218
223
|
|
|
219
|
-
// Compute public route names (filtered: undefined for auto-generated routes)
|
|
220
224
|
const toRouteName =
|
|
221
225
|
routeKey && !isAutoGeneratedRouteName(routeKey) ? routeKey : undefined;
|
|
222
226
|
const reqCtx = _getRequestContext();
|
|
@@ -240,23 +244,18 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
240
244
|
slotName: segment.slot,
|
|
241
245
|
// Action context (only populated when triggered by server action)
|
|
242
246
|
actionId: actionContext?.actionId,
|
|
247
|
+
isAction: makeIsAction(actionContext?.actionId),
|
|
243
248
|
actionUrl: actionContext?.actionUrl,
|
|
244
249
|
actionResult: actionContext?.actionResult,
|
|
245
250
|
formData: actionContext?.formData,
|
|
246
|
-
method: request.method,
|
|
247
|
-
routeName: toRouteName,
|
|
248
|
-
fromRouteName,
|
|
249
|
-
toRouteName,
|
|
250
|
-
// Stale cache context (only true for background revalidation after stale cache render)
|
|
251
|
+
method: request.method,
|
|
252
|
+
routeName: toRouteName,
|
|
253
|
+
fromRouteName,
|
|
254
|
+
toRouteName,
|
|
251
255
|
stale,
|
|
252
256
|
});
|
|
253
257
|
|
|
254
|
-
// Check return type:
|
|
255
|
-
// - boolean: hard decision, short-circuit immediately
|
|
256
|
-
// - { defaultShouldRevalidate: boolean }: soft decision, update suggestion and continue
|
|
257
|
-
// - null/undefined: use default behavior (equivalent to returning { defaultShouldRevalidate })
|
|
258
258
|
if (typeof result === "boolean") {
|
|
259
|
-
// Hard decision - short-circuit
|
|
260
259
|
debugLog("revalidation", "hard decision", {
|
|
261
260
|
segmentId: segment.id,
|
|
262
261
|
revalidator: name,
|
|
@@ -269,7 +268,6 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
269
268
|
typeof result === "object" &&
|
|
270
269
|
"defaultShouldRevalidate" in result
|
|
271
270
|
) {
|
|
272
|
-
// Soft decision - update suggestion and continue
|
|
273
271
|
currentSuggestion = result.defaultShouldRevalidate;
|
|
274
272
|
debugLog("revalidation", "soft decision", {
|
|
275
273
|
segmentId: segment.id,
|
|
@@ -277,18 +275,14 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
277
275
|
revalidate: currentSuggestion,
|
|
278
276
|
});
|
|
279
277
|
} else if (result === null || result === undefined) {
|
|
280
|
-
// Defer to default - equivalent to { defaultShouldRevalidate: currentSuggestion }
|
|
281
|
-
// This means "I don't care, use whatever the default is"
|
|
282
278
|
debugLog("revalidation", "deferred to current default", {
|
|
283
279
|
segmentId: segment.id,
|
|
284
280
|
revalidator: name,
|
|
285
281
|
revalidate: currentSuggestion,
|
|
286
282
|
});
|
|
287
|
-
// currentSuggestion stays the same, continue to next function
|
|
288
283
|
}
|
|
289
284
|
}
|
|
290
285
|
|
|
291
|
-
// All revalidators completed - use final suggestion
|
|
292
286
|
debugLog("revalidation", "final decision", {
|
|
293
287
|
segmentId: segment.id,
|
|
294
288
|
revalidate: currentSuggestion,
|
|
@@ -230,7 +230,6 @@ export function createRouteSnapshot<TEnv = any>(
|
|
|
230
230
|
entry: {} as any,
|
|
231
231
|
routeKey: "test",
|
|
232
232
|
params: {},
|
|
233
|
-
optionalParams: new Set(),
|
|
234
233
|
} as RouteMatchResult<TEnv>,
|
|
235
234
|
manifestEntry: { type: "route", shortCode: "R0", parent: null } as any,
|
|
236
235
|
entries: [],
|
|
@@ -54,10 +54,8 @@ export interface InterceptResult {
|
|
|
54
54
|
* Instead of passing 20+ parameters, middleware calls getRouterContext() to access them.
|
|
55
55
|
*/
|
|
56
56
|
export interface RouterContext<TEnv = any> {
|
|
57
|
-
// Route matching
|
|
58
57
|
findMatch: (pathname: string) => RouteMatchResult | null;
|
|
59
58
|
|
|
60
|
-
// Manifest loading
|
|
61
59
|
loadManifest: (
|
|
62
60
|
entry: any,
|
|
63
61
|
routeKey: string,
|
|
@@ -66,10 +64,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
66
64
|
isSSR?: boolean,
|
|
67
65
|
) => Promise<EntryData>;
|
|
68
66
|
|
|
69
|
-
// Entry traversal
|
|
70
67
|
traverseBack: (entry: EntryData) => Generator<EntryData>;
|
|
71
68
|
|
|
72
|
-
// Handler context creation
|
|
73
69
|
createHandlerContext: (
|
|
74
70
|
params: Record<string, string>,
|
|
75
71
|
request: Request,
|
|
@@ -83,7 +79,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
83
79
|
isPassthroughRoute?: boolean,
|
|
84
80
|
) => HandlerContext<any, TEnv>;
|
|
85
81
|
|
|
86
|
-
// Loader setup
|
|
87
82
|
setupLoaderAccess: (
|
|
88
83
|
ctx: HandlerContext<any, TEnv>,
|
|
89
84
|
loaderPromises: Map<string, Promise<any>>,
|
|
@@ -94,7 +89,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
94
89
|
loaderPromises: Map<string, Promise<any>>,
|
|
95
90
|
) => void;
|
|
96
91
|
|
|
97
|
-
// Context access
|
|
98
92
|
getContext: () => {
|
|
99
93
|
getOrCreateStore: (key: string) => any;
|
|
100
94
|
runWithStore: <T>(
|
|
@@ -105,16 +99,13 @@ export interface RouterContext<TEnv = any> {
|
|
|
105
99
|
) => T;
|
|
106
100
|
};
|
|
107
101
|
|
|
108
|
-
// Metrics
|
|
109
102
|
getMetricsStore: () => MetricsStore | undefined;
|
|
110
103
|
|
|
111
|
-
// Cache
|
|
112
104
|
createCacheScope: (
|
|
113
105
|
cacheConfig: any,
|
|
114
106
|
parent: CacheScope | null,
|
|
115
107
|
) => CacheScope | null;
|
|
116
108
|
|
|
117
|
-
// Intercept detection
|
|
118
109
|
findInterceptForRoute: (
|
|
119
110
|
routeKey: string,
|
|
120
111
|
parentEntry: EntryData | null,
|
|
@@ -122,7 +113,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
122
113
|
isAction: boolean,
|
|
123
114
|
) => InterceptResult | null;
|
|
124
115
|
|
|
125
|
-
// Segment resolution (with revalidation)
|
|
126
116
|
resolveAllSegmentsWithRevalidation: (
|
|
127
117
|
entries: EntryData[],
|
|
128
118
|
routeKey: string,
|
|
@@ -133,7 +123,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
133
123
|
request: Request,
|
|
134
124
|
prevUrl: URL,
|
|
135
125
|
nextUrl: URL,
|
|
136
|
-
loaderPromises: Map<string, Promise<any>>,
|
|
137
126
|
actionContext: any | undefined,
|
|
138
127
|
interceptResult: InterceptResult | null,
|
|
139
128
|
localRouteName: string,
|
|
@@ -166,12 +155,10 @@ export interface RouterContext<TEnv = any> {
|
|
|
166
155
|
revalidationContext?: RevalidationContext,
|
|
167
156
|
) => Promise<ResolvedSegment[]>;
|
|
168
157
|
|
|
169
|
-
// Collect with markers
|
|
170
158
|
collectWithMarkers?: <T>(
|
|
171
159
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
172
160
|
) => Promise<{ items: T[]; matchedIds: string[] }>;
|
|
173
161
|
|
|
174
|
-
// Revalidation evaluation
|
|
175
162
|
evaluateRevalidation: (params: {
|
|
176
163
|
segment: ResolvedSegment;
|
|
177
164
|
prevParams: Record<string, string>;
|
|
@@ -195,7 +182,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
195
182
|
| "intercept-loader";
|
|
196
183
|
}) => Promise<boolean>;
|
|
197
184
|
|
|
198
|
-
// Request context
|
|
199
185
|
getRequestContext: () =>
|
|
200
186
|
| {
|
|
201
187
|
waitUntil: (fn: () => Promise<void>) => void;
|
|
@@ -203,7 +189,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
203
189
|
}
|
|
204
190
|
| undefined;
|
|
205
191
|
|
|
206
|
-
// Simple segment resolution (without revalidation - for full match)
|
|
207
192
|
resolveAllSegments: (
|
|
208
193
|
entries: EntryData[],
|
|
209
194
|
routeKey: string,
|
|
@@ -213,7 +198,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
213
198
|
options?: { skipLoaders?: boolean },
|
|
214
199
|
) => Promise<ResolvedSegment[]>;
|
|
215
200
|
|
|
216
|
-
// Generator-based simple resolution
|
|
217
201
|
resolveAllSegmentsGenerator?: (
|
|
218
202
|
entries: EntryData[],
|
|
219
203
|
routeKey: string,
|
|
@@ -222,21 +206,17 @@ export interface RouterContext<TEnv = any> {
|
|
|
222
206
|
loaderPromises: Map<string, Promise<any>>,
|
|
223
207
|
) => AsyncGenerator<ResolvedSegment | { __type: "id"; id: string }>;
|
|
224
208
|
|
|
225
|
-
// Collect segments from generator
|
|
226
209
|
collectSegmentsFromGenerator?: <T>(
|
|
227
210
|
gen: AsyncGenerator<T | { __type: "id"; id: string }>,
|
|
228
211
|
) => Promise<T[]>;
|
|
229
212
|
|
|
230
|
-
// Handle store
|
|
231
213
|
createHandleStore: () => any;
|
|
232
214
|
|
|
233
|
-
// Loaders-only resolution (for full match cache hit - no revalidation)
|
|
234
215
|
resolveLoadersOnly?: (
|
|
235
216
|
entries: EntryData[],
|
|
236
217
|
handlerContext: HandlerContext<any, TEnv>,
|
|
237
218
|
) => Promise<ResolvedSegment[]>;
|
|
238
219
|
|
|
239
|
-
// Loaders-only resolution (for cache hit scenarios)
|
|
240
220
|
resolveLoadersOnlyWithRevalidation?: (
|
|
241
221
|
entries: EntryData[],
|
|
242
222
|
handlerContext: HandlerContext<any, TEnv>,
|
|
@@ -258,10 +238,8 @@ export interface RouterContext<TEnv = any> {
|
|
|
258
238
|
// Telemetry sink (optional, no-op when undefined)
|
|
259
239
|
telemetry?: TelemetrySink;
|
|
260
240
|
|
|
261
|
-
// Request ID for telemetry span correlation (set per-request in match handlers)
|
|
262
241
|
requestId?: string;
|
|
263
242
|
|
|
264
|
-
// Intercept loaders only (for cache hit + intercept scenarios)
|
|
265
243
|
resolveInterceptLoadersOnly?: (
|
|
266
244
|
intercept: InterceptEntry,
|
|
267
245
|
entry: EntryData,
|
|
@@ -284,7 +262,6 @@ export interface RouterContext<TEnv = any> {
|
|
|
284
262
|
} | null>;
|
|
285
263
|
}
|
|
286
264
|
|
|
287
|
-
// AsyncLocalStorage instance for router context
|
|
288
265
|
const routerContext = new AsyncLocalStorage<RouterContext<any>>();
|
|
289
266
|
|
|
290
267
|
/**
|
|
@@ -308,10 +285,6 @@ export function getRouterContext<TEnv = any>(): RouterContext<TEnv> {
|
|
|
308
285
|
*
|
|
309
286
|
* All async code within fn() can call getRouterContext() to access router closures.
|
|
310
287
|
* This works across async boundaries thanks to AsyncLocalStorage.
|
|
311
|
-
*
|
|
312
|
-
* @param deps Router dependencies to make available
|
|
313
|
-
* @param fn Function to run with dependencies available
|
|
314
|
-
* @returns Result of fn()
|
|
315
288
|
*/
|
|
316
289
|
export function runWithRouterContext<T, TEnv = any>(
|
|
317
290
|
deps: RouterContext<TEnv>,
|
|
@@ -2,18 +2,16 @@ import type { ComponentType, ReactNode } from "react";
|
|
|
2
2
|
import type { SerializedManifest } from "../debug.js";
|
|
3
3
|
import type { ReverseFunction } from "../reverse.js";
|
|
4
4
|
import type { UrlPatterns } from "../urls.js";
|
|
5
|
-
import type { UrlBuilder } from "../urls/pattern-types.js";
|
|
5
|
+
import type { UrlBuilder, EnvCompatible } from "../urls/pattern-types.js";
|
|
6
6
|
import type { EntryData } from "../server/context";
|
|
7
7
|
import type { ErrorInfo, MatchResult } from "../types";
|
|
8
8
|
import type { NonceProvider } from "../rsc/types.js";
|
|
9
9
|
import type { ExecutionContext } from "../server/request-context.js";
|
|
10
|
-
import type {
|
|
11
|
-
SerializedSegmentData,
|
|
12
|
-
SegmentHandleData,
|
|
13
|
-
} from "../cache/types.js";
|
|
10
|
+
import type { SerializedSegmentData } from "../cache/types.js";
|
|
14
11
|
import type { MiddlewareEntry, MiddlewareFn } from "./middleware.js";
|
|
12
|
+
import type { ExtractParams } from "../types/route-config.js";
|
|
15
13
|
import { RSC_ROUTER_BRAND } from "./router-registry.js";
|
|
16
|
-
import type {
|
|
14
|
+
import type { RangoOptions, RootLayoutProps } from "./router-options.js";
|
|
17
15
|
import type { DefaultVars } from "../types/global-namespace.js";
|
|
18
16
|
import type { ResolvedTimeouts, OnTimeoutCallback } from "./timeout.js";
|
|
19
17
|
|
|
@@ -49,16 +47,16 @@ type MergeRoutesWithResponses<
|
|
|
49
47
|
};
|
|
50
48
|
|
|
51
49
|
/**
|
|
52
|
-
* Public
|
|
50
|
+
* Public Rango router interface — the user-facing API surface.
|
|
53
51
|
*
|
|
54
52
|
* Users interact with this type when building and using routers.
|
|
55
|
-
* Internal framework code uses
|
|
53
|
+
* Internal framework code uses RangoInternal (via toInternal()) to access
|
|
56
54
|
* matching, build-time, and configuration members that are not part of the
|
|
57
55
|
* public contract.
|
|
58
56
|
*
|
|
59
57
|
* TRoutes accumulates all registered route types through the builder chain.
|
|
60
58
|
*/
|
|
61
|
-
export interface
|
|
59
|
+
export interface Rango<
|
|
62
60
|
TEnv = any,
|
|
63
61
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
64
62
|
> {
|
|
@@ -89,16 +87,16 @@ export interface RSCRouter<
|
|
|
89
87
|
* ])
|
|
90
88
|
* ```
|
|
91
89
|
*/
|
|
92
|
-
routes<T extends UrlPatterns<
|
|
93
|
-
patterns: T,
|
|
94
|
-
):
|
|
90
|
+
routes<T extends UrlPatterns<any, any, any>>(
|
|
91
|
+
patterns: T & EnvCompatible<T, TEnv>,
|
|
92
|
+
): Rango<
|
|
95
93
|
TEnv,
|
|
96
94
|
TRoutes &
|
|
97
95
|
(NonNullable<T["_routes"]> extends Record<string, unknown>
|
|
98
96
|
? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
|
|
99
97
|
: Record<string, string>)
|
|
100
98
|
>;
|
|
101
|
-
routes(builder: UrlBuilder<TEnv>):
|
|
99
|
+
routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
|
|
102
100
|
|
|
103
101
|
/**
|
|
104
102
|
* Add global middleware that runs on all routes
|
|
@@ -108,13 +106,18 @@ export interface RSCRouter<
|
|
|
108
106
|
* createRouter({ document: RootLayout })
|
|
109
107
|
* .use(loggerMiddleware) // All routes
|
|
110
108
|
* .use("/api/*", rateLimiter) // Pattern match
|
|
109
|
+
* .use("/users/:id", (ctx) => {}) // ctx.params.id is typed
|
|
111
110
|
* .routes(urlpatterns)
|
|
112
111
|
* ```
|
|
113
112
|
*/
|
|
113
|
+
use<Pattern extends string>(
|
|
114
|
+
pattern: Pattern,
|
|
115
|
+
middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
|
|
116
|
+
): Rango<TEnv, TRoutes>;
|
|
114
117
|
use(
|
|
115
118
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
116
119
|
middleware?: MiddlewareFn<TEnv>,
|
|
117
|
-
):
|
|
120
|
+
): Rango<TEnv, TRoutes>;
|
|
118
121
|
|
|
119
122
|
/**
|
|
120
123
|
* Type-safe URL builder for registered routes
|
|
@@ -141,7 +144,7 @@ export interface RSCRouter<
|
|
|
141
144
|
* type AppRoutes = typeof _router.routeMap;
|
|
142
145
|
*
|
|
143
146
|
* declare global {
|
|
144
|
-
* namespace
|
|
147
|
+
* namespace Rango {
|
|
145
148
|
* interface RegisteredRoutes extends AppRoutes {}
|
|
146
149
|
* }
|
|
147
150
|
* }
|
|
@@ -177,16 +180,16 @@ export interface RSCRouter<
|
|
|
177
180
|
}
|
|
178
181
|
|
|
179
182
|
/**
|
|
180
|
-
* Internal
|
|
183
|
+
* Internal Rango router interface — the full framework-facing API.
|
|
181
184
|
*
|
|
182
185
|
* This type includes all members used by the Vite plugin, RSC handler,
|
|
183
186
|
* pre-rendering pipeline, and other framework internals. It is NOT exported
|
|
184
187
|
* from the public package API.
|
|
185
188
|
*
|
|
186
|
-
* Use toInternal(router) to assert a public
|
|
189
|
+
* Use toInternal(router) to assert a public Rango into this type
|
|
187
190
|
* at the boundary where framework code receives a user-provided router.
|
|
188
191
|
*/
|
|
189
|
-
export interface
|
|
192
|
+
export interface RangoInternal<
|
|
190
193
|
TEnv = any,
|
|
191
194
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
192
195
|
> {
|
|
@@ -206,26 +209,36 @@ export interface RSCRouterInternal<
|
|
|
206
209
|
readonly basename: string | undefined;
|
|
207
210
|
|
|
208
211
|
/**
|
|
209
|
-
* Register routes using URL patterns from urls() or a builder function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
* Register routes using URL patterns from urls() or a builder function.
|
|
213
|
+
*
|
|
214
|
+
* Env compatibility is checked by EnvCompatible: an env-agnostic urls() block
|
|
215
|
+
* (its env is `unknown` — e.g. a shared module, or an app that does not augment
|
|
216
|
+
* `Rango.Env`) attaches to any router, while a urls<TEnv>() block carrying a
|
|
217
|
+
* concrete env is accepted only when this router's `TEnv` satisfies it. So a
|
|
218
|
+
* `urls<{ DB }>()` cannot be mounted on a `createRouter<{}>()`.
|
|
219
|
+
*/
|
|
220
|
+
routes<T extends UrlPatterns<any, any, any>>(
|
|
221
|
+
patterns: T & EnvCompatible<T, TEnv>,
|
|
222
|
+
): Rango<
|
|
214
223
|
TEnv,
|
|
215
224
|
TRoutes &
|
|
216
225
|
(NonNullable<T["_routes"]> extends Record<string, unknown>
|
|
217
226
|
? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
|
|
218
227
|
: Record<string, string>)
|
|
219
228
|
>;
|
|
220
|
-
routes(builder: UrlBuilder<TEnv>):
|
|
229
|
+
routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
|
|
221
230
|
|
|
222
231
|
/**
|
|
223
232
|
* Add global middleware that runs on all routes
|
|
224
233
|
*/
|
|
234
|
+
use<Pattern extends string>(
|
|
235
|
+
pattern: Pattern,
|
|
236
|
+
middleware: MiddlewareFn<TEnv, ExtractParams<Pattern>>,
|
|
237
|
+
): Rango<TEnv, TRoutes>;
|
|
225
238
|
use(
|
|
226
239
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
227
240
|
middleware?: MiddlewareFn<TEnv>,
|
|
228
|
-
):
|
|
241
|
+
): Rango<TEnv, TRoutes>;
|
|
229
242
|
|
|
230
243
|
/**
|
|
231
244
|
* Type-safe URL builder for registered routes
|
|
@@ -247,17 +260,17 @@ export interface RSCRouterInternal<
|
|
|
247
260
|
* Error callback for monitoring/alerting
|
|
248
261
|
* Called when errors occur in loaders, actions, or routes
|
|
249
262
|
*/
|
|
250
|
-
readonly onError?:
|
|
263
|
+
readonly onError?: RangoOptions<TEnv>["onError"];
|
|
251
264
|
|
|
252
265
|
/**
|
|
253
266
|
* Cache configuration
|
|
254
267
|
*/
|
|
255
|
-
readonly cache?:
|
|
268
|
+
readonly cache?: RangoOptions<TEnv>["cache"];
|
|
256
269
|
|
|
257
270
|
/**
|
|
258
271
|
* Not found component to render when no route matches
|
|
259
272
|
*/
|
|
260
|
-
readonly notFound?:
|
|
273
|
+
readonly notFound?: RangoOptions<TEnv>["notFound"];
|
|
261
274
|
|
|
262
275
|
/**
|
|
263
276
|
* Resolved theme configuration (null if theme not enabled)
|
|
@@ -287,6 +300,13 @@ export interface RSCRouterInternal<
|
|
|
287
300
|
*/
|
|
288
301
|
readonly prefetchCacheTTL: number;
|
|
289
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Resolved rango state cookie name (`{prefix}_{routerId}`), composed once at
|
|
305
|
+
* router init and shipped to the client in payload metadata. The server-side
|
|
306
|
+
* cookie writer reads it from here; the client reads it from metadata.
|
|
307
|
+
*/
|
|
308
|
+
readonly resolvedStateCookieName: string;
|
|
309
|
+
|
|
290
310
|
/**
|
|
291
311
|
* Whether connection warmup is enabled.
|
|
292
312
|
* When true, the client sends HEAD /?_rsc_warmup after idle periods
|
|
@@ -359,6 +379,17 @@ export interface RSCRouterInternal<
|
|
|
359
379
|
/** @internal basename for runtime manifest generation */
|
|
360
380
|
readonly __basename?: string;
|
|
361
381
|
|
|
382
|
+
/**
|
|
383
|
+
* @internal Router-level error/notFound fallbacks (`createRouter` options),
|
|
384
|
+
* exposed for the build-time clientChunks discovery so a `"use client"`
|
|
385
|
+
* default boundary is routed into the dedicated `app-fallback` chunk. Unlike
|
|
386
|
+
* the route-tree `errorBoundary()`/`notFoundBoundary()` helpers these never
|
|
387
|
+
* land in `EntryData`, so they are read directly off the router instance.
|
|
388
|
+
*/
|
|
389
|
+
readonly __defaultErrorBoundary?: RangoOptions<TEnv>["defaultErrorBoundary"];
|
|
390
|
+
readonly __defaultNotFoundBoundary?: RangoOptions<TEnv>["defaultNotFoundBoundary"];
|
|
391
|
+
readonly __notFound?: RangoOptions<TEnv>["notFound"];
|
|
392
|
+
|
|
362
393
|
match(
|
|
363
394
|
request: Request,
|
|
364
395
|
input?: RouterRequestInput<TEnv>,
|
|
@@ -378,11 +409,13 @@ export interface RSCRouterInternal<
|
|
|
378
409
|
devMode?: boolean,
|
|
379
410
|
): Promise<{
|
|
380
411
|
segments: SerializedSegmentData[];
|
|
381
|
-
|
|
412
|
+
/** RSC-encoded handle map ("" when none) — see handle-snapshot.ts. */
|
|
413
|
+
handles: string;
|
|
382
414
|
routeName: string;
|
|
383
415
|
params: Record<string, string>;
|
|
384
416
|
interceptSegments?: SerializedSegmentData[];
|
|
385
|
-
|
|
417
|
+
/** RSC-encoded MERGED (main + intercept) handle map for the intercept artifact. */
|
|
418
|
+
interceptHandles?: string;
|
|
386
419
|
passthrough?: true;
|
|
387
420
|
} | null>;
|
|
388
421
|
|
|
@@ -396,7 +429,7 @@ export interface RSCRouterInternal<
|
|
|
396
429
|
routeName?: string,
|
|
397
430
|
buildEnv?: any,
|
|
398
431
|
devMode?: boolean,
|
|
399
|
-
): Promise<{ encoded: string; handles:
|
|
432
|
+
): Promise<{ encoded: string; handles: string } | null>;
|
|
400
433
|
|
|
401
434
|
/**
|
|
402
435
|
* Preview match - returns route middleware without segment resolution.
|
|
@@ -469,16 +502,16 @@ export interface RSCRouterInternal<
|
|
|
469
502
|
}
|
|
470
503
|
|
|
471
504
|
/**
|
|
472
|
-
* Assert a public
|
|
505
|
+
* Assert a public Rango into the internal type.
|
|
473
506
|
*
|
|
474
507
|
* Use this at the boundary where framework code receives a user-provided
|
|
475
508
|
* router and needs access to internal members (match, config, build-time).
|
|
476
509
|
* The cast is safe because createRouter() always produces an object that
|
|
477
|
-
* satisfies
|
|
510
|
+
* satisfies RangoInternal; the public type is just a narrower view.
|
|
478
511
|
*/
|
|
479
512
|
export function toInternal<
|
|
480
513
|
TEnv = any,
|
|
481
514
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
482
|
-
>(router:
|
|
483
|
-
return router as
|
|
515
|
+
>(router: Rango<TEnv, TRoutes>): RangoInternal<TEnv, TRoutes> {
|
|
516
|
+
return router as RangoInternal<TEnv, TRoutes>;
|
|
484
517
|
}
|