@rangojs/router 0.0.0-experimental.d7eeaa75 → 0.0.0-experimental.dc2bd2b4
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 +120 -25
- package/dist/bin/rango.js +147 -57
- package/dist/testing/vitest.js +48 -0
- package/dist/vite/index.js +2151 -846
- package/dist/vite/plugins/cloudflare-protocol-loader-hook.mjs +76 -0
- package/package.json +57 -11
- package/skills/breadcrumbs/SKILL.md +3 -1
- package/skills/bundle-analysis/SKILL.md +159 -0
- package/skills/cache-guide/SKILL.md +220 -30
- package/skills/caching/SKILL.md +116 -8
- package/skills/composability/SKILL.md +27 -2
- package/skills/document-cache/SKILL.md +78 -55
- package/skills/handler-use/SKILL.md +364 -0
- package/skills/hooks/SKILL.md +229 -20
- package/skills/host-router/SKILL.md +45 -20
- package/skills/i18n/SKILL.md +276 -0
- package/skills/intercept/SKILL.md +46 -4
- package/skills/layout/SKILL.md +28 -7
- package/skills/links/SKILL.md +247 -17
- package/skills/loader/SKILL.md +219 -9
- package/skills/middleware/SKILL.md +47 -12
- package/skills/migrate-nextjs/SKILL.md +562 -0
- package/skills/migrate-react-router/SKILL.md +769 -0
- package/skills/mime-routes/SKILL.md +27 -0
- package/skills/observability/SKILL.md +137 -0
- package/skills/parallel/SKILL.md +71 -6
- package/skills/prerender/SKILL.md +14 -33
- package/skills/rango/SKILL.md +242 -22
- package/skills/react-compiler/SKILL.md +168 -0
- package/skills/response-routes/SKILL.md +66 -9
- package/skills/route/SKILL.md +57 -4
- package/skills/router-setup/SKILL.md +3 -3
- package/skills/server-actions/SKILL.md +751 -0
- package/skills/streams-and-websockets/SKILL.md +283 -0
- package/skills/testing/SKILL.md +647 -0
- package/skills/typesafety/SKILL.md +319 -27
- package/skills/use-cache/SKILL.md +34 -5
- package/skills/view-transitions/SKILL.md +294 -0
- package/src/__augment-tests__/augment.ts +81 -0
- package/src/__augment-tests__/augmented.check.ts +117 -0
- package/src/browser/action-coordinator.ts +53 -36
- package/src/browser/app-shell.ts +52 -0
- package/src/browser/event-controller.ts +86 -70
- package/src/browser/history-state.ts +21 -0
- package/src/browser/index.ts +3 -3
- package/src/browser/navigation-bridge.ts +84 -11
- package/src/browser/navigation-client.ts +76 -28
- package/src/browser/navigation-store.ts +32 -9
- package/src/browser/navigation-transaction.ts +10 -28
- package/src/browser/partial-update.ts +64 -26
- package/src/browser/prefetch/cache.ts +129 -21
- package/src/browser/prefetch/fetch.ts +148 -16
- package/src/browser/prefetch/queue.ts +36 -5
- package/src/browser/rango-state.ts +53 -13
- package/src/browser/react/Link.tsx +30 -2
- package/src/browser/react/NavigationProvider.tsx +72 -31
- package/src/browser/react/filter-segment-order.ts +51 -7
- package/src/browser/react/index.ts +3 -0
- package/src/browser/react/location-state-shared.ts +175 -4
- package/src/browser/react/location-state.ts +39 -13
- package/src/browser/react/use-handle.ts +17 -9
- package/src/browser/react/use-navigation.ts +22 -2
- package/src/browser/react/use-params.ts +20 -8
- package/src/browser/react/use-reverse.ts +106 -0
- package/src/browser/react/use-router.ts +22 -2
- package/src/browser/react/use-segments.ts +11 -8
- package/src/browser/response-adapter.ts +25 -0
- package/src/browser/rsc-router.tsx +64 -22
- package/src/browser/scroll-restoration.ts +22 -14
- package/src/browser/segment-reconciler.ts +36 -14
- package/src/browser/segment-structure-assert.ts +2 -2
- package/src/browser/server-action-bridge.ts +23 -30
- package/src/browser/types.ts +21 -0
- package/src/build/collect-fallback-refs.ts +107 -0
- package/src/build/generate-manifest.ts +60 -35
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/index.ts +2 -0
- package/src/build/route-trie.ts +52 -25
- package/src/build/route-types/codegen.ts +4 -4
- package/src/build/route-types/include-resolution.ts +1 -1
- package/src/build/route-types/per-module-writer.ts +7 -4
- package/src/build/route-types/router-processing.ts +55 -14
- 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-scope.ts +28 -42
- package/src/cache/cf/cf-cache-store.ts +54 -13
- package/src/client.rsc.tsx +3 -0
- package/src/client.tsx +92 -182
- package/src/context-var.ts +5 -5
- package/src/decode-loader-results.ts +36 -0
- package/src/errors.ts +30 -1
- package/src/handle.ts +26 -13
- package/src/host/index.ts +2 -2
- package/src/host/router.ts +129 -57
- package/src/host/types.ts +31 -2
- package/src/host/utils.ts +1 -1
- package/src/href-client.ts +140 -20
- package/src/index.rsc.ts +9 -4
- package/src/index.ts +53 -15
- package/src/loader-store.ts +500 -0
- package/src/loader.rsc.ts +2 -5
- package/src/loader.ts +3 -10
- package/src/missing-id-error.ts +68 -0
- package/src/outlet-context.ts +1 -1
- package/src/prerender.ts +4 -4
- package/src/response-utils.ts +37 -0
- package/src/reverse.ts +65 -36
- package/src/route-content-wrapper.tsx +6 -28
- package/src/route-definition/dsl-helpers.ts +384 -257
- package/src/route-definition/helper-factories.ts +29 -139
- package/src/route-definition/helpers-types.ts +100 -28
- package/src/route-definition/resolve-handler-use.ts +6 -0
- package/src/route-definition/use-item-types.ts +32 -0
- package/src/route-types.ts +26 -41
- package/src/router/basename.ts +14 -0
- package/src/router/content-negotiation.ts +15 -2
- package/src/router/error-handling.ts +1 -1
- package/src/router/handler-context.ts +21 -38
- package/src/router/intercept-resolution.ts +4 -18
- package/src/router/lazy-includes.ts +8 -8
- package/src/router/loader-resolution.ts +19 -2
- package/src/router/manifest.ts +22 -13
- package/src/router/match-api.ts +4 -3
- package/src/router/match-handlers.ts +63 -20
- package/src/router/match-middleware/cache-lookup.ts +44 -91
- package/src/router/match-middleware/cache-store.ts +3 -2
- package/src/router/match-result.ts +53 -32
- package/src/router/metrics.ts +1 -1
- package/src/router/middleware-types.ts +15 -26
- package/src/router/middleware.ts +99 -84
- package/src/router/pattern-matching.ts +101 -17
- package/src/router/prerender-match.ts +1 -1
- package/src/router/preview-match.ts +3 -1
- package/src/router/request-classification.ts +4 -28
- package/src/router/revalidation.ts +58 -2
- package/src/router/router-interfaces.ts +45 -28
- package/src/router/router-options.ts +40 -1
- package/src/router/router-registry.ts +2 -5
- package/src/router/segment-resolution/fresh.ts +27 -6
- package/src/router/segment-resolution/revalidation.ts +147 -106
- package/src/router/segment-resolution/view-transition-default.ts +36 -0
- package/src/router/substitute-pattern-params.ts +56 -0
- package/src/router/telemetry.ts +99 -0
- package/src/router/trie-matching.ts +18 -13
- package/src/router/types.ts +8 -0
- package/src/router/url-params.ts +49 -0
- package/src/router.ts +38 -23
- package/src/rsc/handler-context.ts +2 -2
- package/src/rsc/handler.ts +28 -69
- package/src/rsc/helpers.ts +91 -43
- package/src/rsc/index.ts +1 -1
- package/src/rsc/origin-guard.ts +28 -10
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/response-route-handler.ts +46 -53
- package/src/rsc/rsc-rendering.ts +35 -51
- package/src/rsc/runtime-warnings.ts +9 -10
- package/src/rsc/server-action.ts +17 -37
- package/src/rsc/ssr-setup.ts +16 -0
- package/src/rsc/types.ts +8 -2
- package/src/search-params.ts +4 -4
- package/src/segment-content-promise.ts +67 -0
- package/src/segment-loader-promise.ts +122 -0
- package/src/segment-system.tsx +132 -116
- package/src/serialize.ts +243 -0
- package/src/server/context.ts +143 -53
- package/src/server/cookie-store.ts +28 -4
- package/src/server/request-context.ts +20 -42
- package/src/ssr/index.tsx +5 -1
- package/src/static-handler.ts +1 -1
- package/src/testing/cache-status.ts +166 -0
- package/src/testing/collect-handle.ts +63 -0
- package/src/testing/dispatch.ts +440 -0
- package/src/testing/dom.entry.ts +22 -0
- package/src/testing/e2e/fixture.ts +154 -0
- package/src/testing/e2e/index.ts +149 -0
- package/src/testing/e2e/matchers.ts +51 -0
- package/src/testing/e2e/page-helpers.ts +272 -0
- package/src/testing/e2e/parity.ts +306 -0
- package/src/testing/e2e/server.ts +183 -0
- package/src/testing/flight-matchers.ts +104 -0
- package/src/testing/flight-runtime.d.ts +21 -0
- package/src/testing/flight.entry.ts +22 -0
- package/src/testing/flight.ts +182 -0
- package/src/testing/generated-routes.ts +223 -0
- package/src/testing/index.ts +105 -0
- package/src/testing/internal/context.ts +193 -0
- package/src/testing/render-route.tsx +536 -0
- package/src/testing/run-loader.ts +296 -0
- package/src/testing/run-middleware.ts +170 -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 +183 -0
- package/src/types/global-namespace.ts +39 -26
- package/src/types/handler-context.ts +68 -50
- package/src/types/index.ts +1 -0
- package/src/types/loader-types.ts +5 -6
- package/src/types/request-scope.ts +126 -0
- package/src/types/route-entry.ts +11 -0
- package/src/types/segments.ts +35 -2
- package/src/urls/include-helper.ts +34 -67
- package/src/urls/index.ts +0 -3
- package/src/urls/path-helper-types.ts +41 -7
- package/src/urls/path-helper.ts +17 -52
- package/src/urls/pattern-types.ts +36 -19
- package/src/urls/response-types.ts +22 -29
- package/src/urls/type-extraction.ts +26 -116
- package/src/urls/urls-function.ts +1 -5
- package/src/use-loader.tsx +413 -42
- package/src/vite/debug.ts +185 -0
- package/src/vite/discovery/bundle-postprocess.ts +6 -6
- package/src/vite/discovery/discover-routers.ts +101 -51
- 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 +67 -26
- 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 +33 -0
- package/src/vite/discovery/virtual-module-codegen.ts +13 -23
- package/src/vite/index.ts +2 -0
- package/src/vite/plugin-types.ts +67 -0
- package/src/vite/plugins/cjs-to-esm.ts +8 -7
- package/src/vite/plugins/client-ref-dedup.ts +16 -0
- package/src/vite/plugins/client-ref-hashing.ts +28 -5
- 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 +214 -0
- package/src/vite/plugins/expose-action-id.ts +54 -30
- package/src/vite/plugins/expose-id-utils.ts +12 -8
- package/src/vite/plugins/expose-ids/export-analysis.ts +100 -20
- package/src/vite/plugins/expose-ids/handler-transform.ts +8 -61
- package/src/vite/plugins/expose-ids/loader-transform.ts +3 -5
- package/src/vite/plugins/expose-ids/router-transform.ts +20 -3
- package/src/vite/plugins/expose-internal-ids.ts +496 -486
- package/src/vite/plugins/performance-tracks.ts +29 -25
- package/src/vite/plugins/use-cache-transform.ts +65 -50
- package/src/vite/plugins/version-injector.ts +39 -23
- package/src/vite/plugins/version-plugin.ts +59 -2
- package/src/vite/plugins/virtual-entries.ts +2 -2
- package/src/vite/rango.ts +116 -29
- package/src/vite/router-discovery.ts +750 -100
- package/src/vite/utils/ast-handler-extract.ts +15 -15
- package/src/vite/utils/banner.ts +1 -1
- package/src/vite/utils/bundle-analysis.ts +4 -2
- package/src/vite/utils/client-chunks.ts +190 -0
- package/src/vite/utils/forward-user-plugins.ts +193 -0
- package/src/vite/utils/manifest-utils.ts +21 -5
- package/src/vite/utils/package-resolution.ts +41 -1
- package/src/vite/utils/prerender-utils.ts +21 -6
- package/src/vite/utils/shared-utils.ts +107 -26
- package/src/browser/action-response-classifier.ts +0 -99
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import type { RouteEntry, TrailingSlashMode } from "../types";
|
|
8
8
|
import type { EntryData } from "../server/context";
|
|
9
9
|
import { debugLog, isRouterDebugEnabled } from "./logging.js";
|
|
10
|
+
import { safeDecodeURIComponent } from "./url-params.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Parsed segment info
|
|
@@ -82,6 +83,13 @@ export interface CompiledPattern {
|
|
|
82
83
|
paramNames: string[];
|
|
83
84
|
optionalParams: Set<string>;
|
|
84
85
|
hasTrailingSlash: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Param-name → allowed values for constrained params (e.g. `:lang(en|gb)`).
|
|
88
|
+
* Validated against the **decoded** param value after regex extraction so
|
|
89
|
+
* a URL like `/en%20GB` still matches `:lang(en GB)` — matching the trie
|
|
90
|
+
* path's behavior (trie-matching.ts:validateAndBuild).
|
|
91
|
+
*/
|
|
92
|
+
constraints?: Record<string, string[]>;
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
// Module-level cache for compiled patterns. Route patterns are a finite set
|
|
@@ -142,6 +150,7 @@ export function compilePattern(pattern: string): CompiledPattern {
|
|
|
142
150
|
const segments = parsePattern(normalizedPattern);
|
|
143
151
|
const paramNames: string[] = [];
|
|
144
152
|
const optionalParams = new Set<string>();
|
|
153
|
+
let constraints: Record<string, string[]> | undefined;
|
|
145
154
|
|
|
146
155
|
let regexPattern = "";
|
|
147
156
|
|
|
@@ -152,11 +161,14 @@ export function compilePattern(pattern: string): CompiledPattern {
|
|
|
152
161
|
} else if (segment.type === "param") {
|
|
153
162
|
paramNames.push(segment.value);
|
|
154
163
|
const suffixPattern = segment.suffix ? escapeRegex(segment.suffix) : "";
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
164
|
+
// Constrained params capture anything here; the allowed values are
|
|
165
|
+
// checked post-decode in findMatch so URL-encoded constraint values
|
|
166
|
+
// (e.g. `:lang(en GB)` via `/en%20GB`) still match.
|
|
167
|
+
const valuePattern = segment.suffix ? "([^/]+?)" : "([^/]+)";
|
|
168
|
+
|
|
169
|
+
if (segment.constraint) {
|
|
170
|
+
(constraints ??= {})[segment.value] = segment.constraint;
|
|
171
|
+
}
|
|
160
172
|
|
|
161
173
|
if (segment.optional) {
|
|
162
174
|
optionalParams.add(segment.value);
|
|
@@ -176,6 +188,20 @@ export function compilePattern(pattern: string): CompiledPattern {
|
|
|
176
188
|
regexPattern = "/";
|
|
177
189
|
}
|
|
178
190
|
|
|
191
|
+
// Patterns of only optional segments (e.g. `/:locale?`, `/:a?/:b?`) need
|
|
192
|
+
// an explicit `/` alternative so a bare `/` matches the absent form. The
|
|
193
|
+
// optional template `(?:/X)?` matches `/X` or empty string, but pathnames
|
|
194
|
+
// are never empty. Arises from `include("/:locale?", routes)` + inner
|
|
195
|
+
// `path("/")`. Skip when an explicit trailing slash already anchors the
|
|
196
|
+
// match.
|
|
197
|
+
const hasOnlyOptionalSegments =
|
|
198
|
+
!hasTrailingSlash &&
|
|
199
|
+
segments.length > 0 &&
|
|
200
|
+
segments.every((segment) => segment.type === "param" && segment.optional);
|
|
201
|
+
if (hasOnlyOptionalSegments) {
|
|
202
|
+
regexPattern = `(?:/|${regexPattern})`;
|
|
203
|
+
}
|
|
204
|
+
|
|
179
205
|
// Add trailing slash to regex if pattern has one
|
|
180
206
|
if (hasTrailingSlash) {
|
|
181
207
|
regexPattern += "/";
|
|
@@ -186,9 +212,35 @@ export function compilePattern(pattern: string): CompiledPattern {
|
|
|
186
212
|
paramNames,
|
|
187
213
|
optionalParams,
|
|
188
214
|
hasTrailingSlash,
|
|
215
|
+
...(constraints ? { constraints } : {}),
|
|
189
216
|
};
|
|
190
217
|
}
|
|
191
218
|
|
|
219
|
+
/**
|
|
220
|
+
* Validate decoded params against a compiled pattern's constraints.
|
|
221
|
+
* Returns false if any constrained param has a non-empty value not in the
|
|
222
|
+
* allowed list. Absent optionals (key missing or `undefined`) are allowed;
|
|
223
|
+
* `""` is also tolerated as "absent" so user-provided params or fixtures
|
|
224
|
+
* that pass empty strings explicitly behave the same way.
|
|
225
|
+
*/
|
|
226
|
+
function satisfiesConstraints(
|
|
227
|
+
params: Record<string, string>,
|
|
228
|
+
constraints: Record<string, string[]> | undefined,
|
|
229
|
+
): boolean {
|
|
230
|
+
if (!constraints) return true;
|
|
231
|
+
for (const name in constraints) {
|
|
232
|
+
const value = params[name];
|
|
233
|
+
if (
|
|
234
|
+
value !== undefined &&
|
|
235
|
+
value !== "" &&
|
|
236
|
+
!constraints[name].includes(value)
|
|
237
|
+
) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
|
|
192
244
|
/**
|
|
193
245
|
* Escape special regex characters in a string
|
|
194
246
|
*/
|
|
@@ -196,6 +248,27 @@ function escapeRegex(str: string): string {
|
|
|
196
248
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
197
249
|
}
|
|
198
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Build the named-params record from a regex match. Optional segments that
|
|
253
|
+
* didn't capture leave the corresponding group `undefined`; we skip those
|
|
254
|
+
* keys so `ctx.params.<name>` reads as `undefined` rather than `""`. This
|
|
255
|
+
* keeps the runtime aligned with the `ExtractParams` type and matches the
|
|
256
|
+
* trie matcher's contract (see `trie-matching.ts:validateAndBuild`).
|
|
257
|
+
*/
|
|
258
|
+
function buildParamsFromMatch(
|
|
259
|
+
match: RegExpExecArray,
|
|
260
|
+
paramNames: string[],
|
|
261
|
+
): Record<string, string> {
|
|
262
|
+
const params: Record<string, string> = {};
|
|
263
|
+
paramNames.forEach((name, index) => {
|
|
264
|
+
const captured = match[index + 1];
|
|
265
|
+
if (captured !== undefined) {
|
|
266
|
+
params[name] = safeDecodeURIComponent(captured);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
return params;
|
|
270
|
+
}
|
|
271
|
+
|
|
199
272
|
/**
|
|
200
273
|
* Extract the static prefix from a route pattern.
|
|
201
274
|
* Returns everything before the first param/wildcard.
|
|
@@ -247,8 +320,10 @@ export function extractStaticPrefix(pattern: string): string {
|
|
|
247
320
|
/**
|
|
248
321
|
* Match a pathname against registered routes
|
|
249
322
|
*
|
|
250
|
-
* Note: Optional params that are absent in the path
|
|
251
|
-
*
|
|
323
|
+
* Note: Optional params that are absent in the path are omitted from the
|
|
324
|
+
* returned `params` (read as `undefined`), matching the trie matcher and
|
|
325
|
+
* the `ExtractParams<"/:locale?/...">` type. Use the pattern definition or
|
|
326
|
+
* `optionalParams` to determine which keys are optional.
|
|
252
327
|
*
|
|
253
328
|
* Trailing slash handling (priority order):
|
|
254
329
|
* 1. Per-route `trailingSlash` config from route()
|
|
@@ -392,8 +467,13 @@ export function findMatch<TEnv>(
|
|
|
392
467
|
fullPattern = entry.prefix + pattern;
|
|
393
468
|
}
|
|
394
469
|
|
|
395
|
-
const {
|
|
396
|
-
|
|
470
|
+
const {
|
|
471
|
+
regex,
|
|
472
|
+
paramNames,
|
|
473
|
+
optionalParams,
|
|
474
|
+
hasTrailingSlash,
|
|
475
|
+
constraints,
|
|
476
|
+
} = getCompiledPattern(fullPattern);
|
|
397
477
|
|
|
398
478
|
// Get trailing slash mode for this route (per-route config or pattern-based)
|
|
399
479
|
const trailingSlashMode: TrailingSlashMode | undefined =
|
|
@@ -410,10 +490,13 @@ export function findMatch<TEnv>(
|
|
|
410
490
|
// Try exact match first
|
|
411
491
|
const match = regex.exec(pathname);
|
|
412
492
|
if (match) {
|
|
413
|
-
const params
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
493
|
+
const params = buildParamsFromMatch(match, paramNames);
|
|
494
|
+
|
|
495
|
+
// Validate constraints against decoded values; a failure falls
|
|
496
|
+
// through to the next route so other patterns can still match.
|
|
497
|
+
if (!satisfiesConstraints(params, constraints)) {
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
417
500
|
|
|
418
501
|
if (effectiveDebug) {
|
|
419
502
|
debugLog("findMatch", "matched route", {
|
|
@@ -465,10 +548,11 @@ export function findMatch<TEnv>(
|
|
|
465
548
|
// Try alternate pathname (opposite trailing slash)
|
|
466
549
|
const altMatch = regex.exec(alternatePathname);
|
|
467
550
|
if (altMatch) {
|
|
468
|
-
const params
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
551
|
+
const params = buildParamsFromMatch(altMatch, paramNames);
|
|
552
|
+
|
|
553
|
+
if (!satisfiesConstraints(params, constraints)) {
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
472
556
|
|
|
473
557
|
// Determine redirect behavior based on mode
|
|
474
558
|
if (trailingSlashMode === "ignore") {
|
|
@@ -126,7 +126,7 @@ export async function matchForPrerender<TEnv = any>(
|
|
|
126
126
|
get env() {
|
|
127
127
|
if (buildEnv !== undefined) return buildEnv;
|
|
128
128
|
throw new Error(
|
|
129
|
-
"[
|
|
129
|
+
"[rango] ctx.env is not available during dev-mode getParams(). " +
|
|
130
130
|
"Configure buildEnv in your rango() plugin options to enable build-time env access.",
|
|
131
131
|
);
|
|
132
132
|
},
|
|
@@ -67,9 +67,11 @@ export async function previewMatch<TEnv = any>(
|
|
|
67
67
|
responseType: negotiation.responseType,
|
|
68
68
|
handler: negotiation.handler,
|
|
69
69
|
params: matched.params,
|
|
70
|
-
negotiated: true,
|
|
71
70
|
manifestEntry: negotiation.manifestEntry,
|
|
72
71
|
routeKey: matched.routeKey,
|
|
72
|
+
// omitted unless a variant negotiated, preserving the prior public
|
|
73
|
+
// shape (absent for plain response routes, not negotiated:false)
|
|
74
|
+
...(negotiation.negotiated ? { negotiated: true } : {}),
|
|
73
75
|
};
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -278,33 +278,9 @@ async function classifyResponseRoute<TEnv>(
|
|
|
278
278
|
pathname: string,
|
|
279
279
|
snapshot: RouteSnapshot<TEnv>,
|
|
280
280
|
): Promise<ResponseRoutePlan<TEnv> | null> {
|
|
281
|
-
|
|
282
|
-
|
|
281
|
+
// negotiateRoute returns the response plan (variant or plain) or null for RSC.
|
|
283
282
|
const negotiation = await negotiateRoute(request, pathname, snapshot);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
route: snapshot,
|
|
288
|
-
...negotiation,
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Non-negotiated response route (no variants, or RSC won negotiation)
|
|
293
|
-
if (responseType) {
|
|
294
|
-
const handler =
|
|
295
|
-
manifestEntry.type === "route" ? manifestEntry.handler : undefined;
|
|
296
|
-
if (handler) {
|
|
297
|
-
return {
|
|
298
|
-
mode: "response",
|
|
299
|
-
route: snapshot,
|
|
300
|
-
handler,
|
|
301
|
-
responseType,
|
|
302
|
-
negotiated: false,
|
|
303
|
-
manifestEntry,
|
|
304
|
-
routeMiddleware: snapshot.routeMiddleware,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return null;
|
|
283
|
+
return negotiation
|
|
284
|
+
? { mode: "response", route: snapshot, ...negotiation }
|
|
285
|
+
: null;
|
|
310
286
|
}
|
|
@@ -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,
|
|
@@ -15,6 +15,47 @@ import type { RevalidationTraceEntry } from "./logging.js";
|
|
|
15
15
|
import { _getRequestContext } from "../server/request-context.js";
|
|
16
16
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a server-action reference's stable id, mirroring how the action
|
|
20
|
+
* boundary derives `actionContext.actionId` in `rsc/server-action.ts`
|
|
21
|
+
* (`$id ?? $$id`): the file-path `$id` set by the expose-action-id plugin in a
|
|
22
|
+
* production RSC build when present, otherwise React's `$$id`. Resolving both
|
|
23
|
+
* the incoming `actionId` and the reference with the same precedence makes
|
|
24
|
+
* `isAction()` form-agnostic across dev and production.
|
|
25
|
+
*/
|
|
26
|
+
function resolveActionRefId(ref: unknown): string | undefined {
|
|
27
|
+
if (ref == null) return undefined;
|
|
28
|
+
const r = ref as { $id?: unknown; $$id?: unknown };
|
|
29
|
+
if (typeof r.$id === "string") return r.$id;
|
|
30
|
+
if (typeof r.$$id === "string") return r.$$id;
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build the `isAction()` helper bound to the current action's id. Matches a
|
|
36
|
+
* single imported action reference, several (variadic), or any export of a
|
|
37
|
+
* namespace import (`import * as Mod`). Returns `false` when there is no action
|
|
38
|
+
* (plain navigation) or nothing matches.
|
|
39
|
+
*/
|
|
40
|
+
function makeIsAction(
|
|
41
|
+
currentActionId: string | undefined,
|
|
42
|
+
): (...actions: ActionRef[]) => boolean {
|
|
43
|
+
return (...actions: ActionRef[]): boolean => {
|
|
44
|
+
if (!currentActionId) return false;
|
|
45
|
+
for (const action of actions) {
|
|
46
|
+
if (typeof action === "function") {
|
|
47
|
+
if (resolveActionRefId(action) === currentActionId) return true;
|
|
48
|
+
} else if (action && typeof action === "object") {
|
|
49
|
+
// Namespace import: match any export of the module.
|
|
50
|
+
for (const value of Object.values(action)) {
|
|
51
|
+
if (resolveActionRefId(value) === currentActionId) return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
18
59
|
function paramsEqual(
|
|
19
60
|
a: Record<string, string>,
|
|
20
61
|
b: Record<string, string>,
|
|
@@ -59,6 +100,14 @@ interface EvaluateRevalidationOptions<TEnv> {
|
|
|
59
100
|
stale?: boolean;
|
|
60
101
|
/** Trace source hint for the revalidation trace */
|
|
61
102
|
traceSource?: RevalidationTraceEntry["source"];
|
|
103
|
+
/**
|
|
104
|
+
* Override the segment-type-derived default. When set, the value is used as
|
|
105
|
+
* the seed `defaultShouldRevalidate` passed to user revalidate fns and the
|
|
106
|
+
* reason flows into the trace. Callers use this when client-knowledge
|
|
107
|
+
* (e.g. parallel slot not in clientSegmentIds) should dictate the seed
|
|
108
|
+
* instead of the params/method-based heuristic.
|
|
109
|
+
*/
|
|
110
|
+
defaultOverride?: { value: boolean; reason: string };
|
|
62
111
|
}
|
|
63
112
|
|
|
64
113
|
/**
|
|
@@ -81,6 +130,7 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
81
130
|
actionContext,
|
|
82
131
|
stale,
|
|
83
132
|
traceSource,
|
|
133
|
+
defaultOverride,
|
|
84
134
|
} = options;
|
|
85
135
|
const nextParams = segment.params || {};
|
|
86
136
|
const paramsChanged = !paramsEqual(nextParams, prevParams);
|
|
@@ -110,7 +160,12 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
110
160
|
let defaultShouldRevalidate: boolean;
|
|
111
161
|
let defaultReason: string;
|
|
112
162
|
|
|
113
|
-
if (
|
|
163
|
+
if (defaultOverride) {
|
|
164
|
+
// Caller injected the seed (e.g. parallel slot not in clientSegmentIds).
|
|
165
|
+
// Skip the type-derived heuristic — caller knows better in this context.
|
|
166
|
+
defaultShouldRevalidate = defaultOverride.value;
|
|
167
|
+
defaultReason = defaultOverride.reason;
|
|
168
|
+
} else if (request.method === "POST") {
|
|
114
169
|
// Actions: revalidate segments that belong to the route, skip parent chain
|
|
115
170
|
if (segment.type === "route") {
|
|
116
171
|
// Route segment always revalidates on actions
|
|
@@ -226,6 +281,7 @@ export async function evaluateRevalidation<TEnv>(
|
|
|
226
281
|
slotName: segment.slot,
|
|
227
282
|
// Action context (only populated when triggered by server action)
|
|
228
283
|
actionId: actionContext?.actionId,
|
|
284
|
+
isAction: makeIsAction(actionContext?.actionId),
|
|
229
285
|
actionUrl: actionContext?.actionUrl,
|
|
230
286
|
actionResult: actionContext?.actionResult,
|
|
231
287
|
formData: actionContext?.formData,
|
|
@@ -2,7 +2,7 @@ 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";
|
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
} from "../cache/types.js";
|
|
14
14
|
import type { MiddlewareEntry, MiddlewareFn } from "./middleware.js";
|
|
15
15
|
import { RSC_ROUTER_BRAND } from "./router-registry.js";
|
|
16
|
-
import type {
|
|
16
|
+
import type { RangoOptions, RootLayoutProps } from "./router-options.js";
|
|
17
17
|
import type { DefaultVars } from "../types/global-namespace.js";
|
|
18
18
|
import type { ResolvedTimeouts, OnTimeoutCallback } from "./timeout.js";
|
|
19
19
|
|
|
@@ -49,16 +49,16 @@ type MergeRoutesWithResponses<
|
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
* Public
|
|
52
|
+
* Public Rango router interface — the user-facing API surface.
|
|
53
53
|
*
|
|
54
54
|
* Users interact with this type when building and using routers.
|
|
55
|
-
* Internal framework code uses
|
|
55
|
+
* Internal framework code uses RangoInternal (via toInternal()) to access
|
|
56
56
|
* matching, build-time, and configuration members that are not part of the
|
|
57
57
|
* public contract.
|
|
58
58
|
*
|
|
59
59
|
* TRoutes accumulates all registered route types through the builder chain.
|
|
60
60
|
*/
|
|
61
|
-
export interface
|
|
61
|
+
export interface Rango<
|
|
62
62
|
TEnv = any,
|
|
63
63
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
64
64
|
> {
|
|
@@ -89,16 +89,16 @@ export interface RSCRouter<
|
|
|
89
89
|
* ])
|
|
90
90
|
* ```
|
|
91
91
|
*/
|
|
92
|
-
routes<T extends UrlPatterns<
|
|
93
|
-
patterns: T,
|
|
94
|
-
):
|
|
92
|
+
routes<T extends UrlPatterns<any, any, any>>(
|
|
93
|
+
patterns: T & EnvCompatible<T, TEnv>,
|
|
94
|
+
): Rango<
|
|
95
95
|
TEnv,
|
|
96
96
|
TRoutes &
|
|
97
97
|
(NonNullable<T["_routes"]> extends Record<string, unknown>
|
|
98
98
|
? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
|
|
99
99
|
: Record<string, string>)
|
|
100
100
|
>;
|
|
101
|
-
routes(builder: UrlBuilder<TEnv>):
|
|
101
|
+
routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
104
|
* Add global middleware that runs on all routes
|
|
@@ -114,7 +114,7 @@ export interface RSCRouter<
|
|
|
114
114
|
use(
|
|
115
115
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
116
116
|
middleware?: MiddlewareFn<TEnv>,
|
|
117
|
-
):
|
|
117
|
+
): Rango<TEnv, TRoutes>;
|
|
118
118
|
|
|
119
119
|
/**
|
|
120
120
|
* Type-safe URL builder for registered routes
|
|
@@ -141,7 +141,7 @@ export interface RSCRouter<
|
|
|
141
141
|
* type AppRoutes = typeof _router.routeMap;
|
|
142
142
|
*
|
|
143
143
|
* declare global {
|
|
144
|
-
* namespace
|
|
144
|
+
* namespace Rango {
|
|
145
145
|
* interface RegisteredRoutes extends AppRoutes {}
|
|
146
146
|
* }
|
|
147
147
|
* }
|
|
@@ -177,16 +177,16 @@ export interface RSCRouter<
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/**
|
|
180
|
-
* Internal
|
|
180
|
+
* Internal Rango router interface — the full framework-facing API.
|
|
181
181
|
*
|
|
182
182
|
* This type includes all members used by the Vite plugin, RSC handler,
|
|
183
183
|
* pre-rendering pipeline, and other framework internals. It is NOT exported
|
|
184
184
|
* from the public package API.
|
|
185
185
|
*
|
|
186
|
-
* Use toInternal(router) to assert a public
|
|
186
|
+
* Use toInternal(router) to assert a public Rango into this type
|
|
187
187
|
* at the boundary where framework code receives a user-provided router.
|
|
188
188
|
*/
|
|
189
|
-
export interface
|
|
189
|
+
export interface RangoInternal<
|
|
190
190
|
TEnv = any,
|
|
191
191
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
192
192
|
> {
|
|
@@ -206,18 +206,24 @@ export interface RSCRouterInternal<
|
|
|
206
206
|
readonly basename: string | undefined;
|
|
207
207
|
|
|
208
208
|
/**
|
|
209
|
-
* Register routes using URL patterns from urls() or a builder function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
209
|
+
* Register routes using URL patterns from urls() or a builder function.
|
|
210
|
+
*
|
|
211
|
+
* Env compatibility is checked by EnvCompatible: an env-agnostic urls() block
|
|
212
|
+
* (its env is `unknown` — e.g. a shared module, or an app that does not augment
|
|
213
|
+
* `Rango.Env`) attaches to any router, while a urls<TEnv>() block carrying a
|
|
214
|
+
* concrete env is accepted only when this router's `TEnv` satisfies it. So a
|
|
215
|
+
* `urls<{ DB }>()` cannot be mounted on a `createRouter<{}>()`.
|
|
216
|
+
*/
|
|
217
|
+
routes<T extends UrlPatterns<any, any, any>>(
|
|
218
|
+
patterns: T & EnvCompatible<T, TEnv>,
|
|
219
|
+
): Rango<
|
|
214
220
|
TEnv,
|
|
215
221
|
TRoutes &
|
|
216
222
|
(NonNullable<T["_routes"]> extends Record<string, unknown>
|
|
217
223
|
? MergeRoutesWithResponses<NonNullable<T["_routes"]>, T["_responses"]>
|
|
218
224
|
: Record<string, string>)
|
|
219
225
|
>;
|
|
220
|
-
routes(builder: UrlBuilder<TEnv>):
|
|
226
|
+
routes(builder: UrlBuilder<TEnv>): Rango<TEnv, TRoutes>;
|
|
221
227
|
|
|
222
228
|
/**
|
|
223
229
|
* Add global middleware that runs on all routes
|
|
@@ -225,7 +231,7 @@ export interface RSCRouterInternal<
|
|
|
225
231
|
use(
|
|
226
232
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
227
233
|
middleware?: MiddlewareFn<TEnv>,
|
|
228
|
-
):
|
|
234
|
+
): Rango<TEnv, TRoutes>;
|
|
229
235
|
|
|
230
236
|
/**
|
|
231
237
|
* Type-safe URL builder for registered routes
|
|
@@ -247,17 +253,17 @@ export interface RSCRouterInternal<
|
|
|
247
253
|
* Error callback for monitoring/alerting
|
|
248
254
|
* Called when errors occur in loaders, actions, or routes
|
|
249
255
|
*/
|
|
250
|
-
readonly onError?:
|
|
256
|
+
readonly onError?: RangoOptions<TEnv>["onError"];
|
|
251
257
|
|
|
252
258
|
/**
|
|
253
259
|
* Cache configuration
|
|
254
260
|
*/
|
|
255
|
-
readonly cache?:
|
|
261
|
+
readonly cache?: RangoOptions<TEnv>["cache"];
|
|
256
262
|
|
|
257
263
|
/**
|
|
258
264
|
* Not found component to render when no route matches
|
|
259
265
|
*/
|
|
260
|
-
readonly notFound?:
|
|
266
|
+
readonly notFound?: RangoOptions<TEnv>["notFound"];
|
|
261
267
|
|
|
262
268
|
/**
|
|
263
269
|
* Resolved theme configuration (null if theme not enabled)
|
|
@@ -359,6 +365,17 @@ export interface RSCRouterInternal<
|
|
|
359
365
|
/** @internal basename for runtime manifest generation */
|
|
360
366
|
readonly __basename?: string;
|
|
361
367
|
|
|
368
|
+
/**
|
|
369
|
+
* @internal Router-level error/notFound fallbacks (`createRouter` options),
|
|
370
|
+
* exposed for the build-time clientChunks discovery so a `"use client"`
|
|
371
|
+
* default boundary is routed into the dedicated `app-fallback` chunk. Unlike
|
|
372
|
+
* the route-tree `errorBoundary()`/`notFoundBoundary()` helpers these never
|
|
373
|
+
* land in `EntryData`, so they are read directly off the router instance.
|
|
374
|
+
*/
|
|
375
|
+
readonly __defaultErrorBoundary?: RangoOptions<TEnv>["defaultErrorBoundary"];
|
|
376
|
+
readonly __defaultNotFoundBoundary?: RangoOptions<TEnv>["defaultNotFoundBoundary"];
|
|
377
|
+
readonly __notFound?: RangoOptions<TEnv>["notFound"];
|
|
378
|
+
|
|
362
379
|
match(
|
|
363
380
|
request: Request,
|
|
364
381
|
input?: RouterRequestInput<TEnv>,
|
|
@@ -469,16 +486,16 @@ export interface RSCRouterInternal<
|
|
|
469
486
|
}
|
|
470
487
|
|
|
471
488
|
/**
|
|
472
|
-
* Assert a public
|
|
489
|
+
* Assert a public Rango into the internal type.
|
|
473
490
|
*
|
|
474
491
|
* Use this at the boundary where framework code receives a user-provided
|
|
475
492
|
* router and needs access to internal members (match, config, build-time).
|
|
476
493
|
* The cast is safe because createRouter() always produces an object that
|
|
477
|
-
* satisfies
|
|
494
|
+
* satisfies RangoInternal; the public type is just a narrower view.
|
|
478
495
|
*/
|
|
479
496
|
export function toInternal<
|
|
480
497
|
TEnv = any,
|
|
481
498
|
TRoutes extends Record<string, unknown> = Record<string, string>,
|
|
482
|
-
>(router:
|
|
483
|
-
return router as
|
|
499
|
+
>(router: Rango<TEnv, TRoutes>): RangoInternal<TEnv, TRoutes> {
|
|
500
|
+
return router as RangoInternal<TEnv, TRoutes>;
|
|
484
501
|
}
|
|
@@ -73,7 +73,7 @@ export interface RootLayoutProps {
|
|
|
73
73
|
/**
|
|
74
74
|
* Router configuration options
|
|
75
75
|
*/
|
|
76
|
-
export interface
|
|
76
|
+
export interface RangoOptions<TEnv = any> {
|
|
77
77
|
/**
|
|
78
78
|
* Unique identifier for this router instance.
|
|
79
79
|
* Used to namespace static output files and route maps.
|
|
@@ -132,6 +132,21 @@ export interface RSCRouterOptions<TEnv = any> {
|
|
|
132
132
|
*/
|
|
133
133
|
allowDebugManifest?: boolean;
|
|
134
134
|
|
|
135
|
+
/**
|
|
136
|
+
* DEVELOPMENT/TEST ONLY. Emit an `X-Rango-Cache` response header describing
|
|
137
|
+
* the cache status of the matched route, for use by testing primitives such
|
|
138
|
+
* as `assertCacheStatus`.
|
|
139
|
+
*
|
|
140
|
+
* Defaults to `false`. When neither this option nor the
|
|
141
|
+
* `RANGO_TEST_SIGNALS=1` environment flag is set, NO header is emitted and
|
|
142
|
+
* router output is byte-identical to the default.
|
|
143
|
+
*
|
|
144
|
+
* The header encodes per-segment (v1: coarse route-level) status keyed by the
|
|
145
|
+
* route NAME, e.g. `X-Rango-Cache: product.detail=hit`. Do NOT enable in
|
|
146
|
+
* production — it exposes internal cache decisions.
|
|
147
|
+
*/
|
|
148
|
+
debugCacheSignal?: boolean;
|
|
149
|
+
|
|
135
150
|
/**
|
|
136
151
|
* Document component that wraps the entire application.
|
|
137
152
|
*
|
|
@@ -357,6 +372,30 @@ export interface RSCRouterOptions<TEnv = any> {
|
|
|
357
372
|
*/
|
|
358
373
|
theme?: import("../theme/types.js").ThemeConfig | true;
|
|
359
374
|
|
|
375
|
+
/**
|
|
376
|
+
* Default for whether the router wraps `transition()` segments in its own
|
|
377
|
+
* React `<ViewTransition>` boundary (experimental React only).
|
|
378
|
+
*
|
|
379
|
+
* - "auto" (default): every route/layout that opts in via `transition()`
|
|
380
|
+
* gets a router-owned cross-fade.
|
|
381
|
+
* - false: the router never places its own boundary. Routes that use
|
|
382
|
+
* `transition()` still drive navigation through startTransition (so loaders
|
|
383
|
+
* hold instead of flashing a skeleton) and still let consumer-placed
|
|
384
|
+
* `<ViewTransition>` elements animate — the router just contributes no
|
|
385
|
+
* cross-fade of its own. This is the "router triggers, you place the
|
|
386
|
+
* transitions" model.
|
|
387
|
+
*
|
|
388
|
+
* A per-segment `transition({ viewTransition })` overrides this default.
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```typescript
|
|
392
|
+
* // App-wide: drive + hold, but never auto-wrap. Place <ViewTransition>
|
|
393
|
+
* // yourself in components where you want a morph.
|
|
394
|
+
* const router = createRouter<AppEnv>({ viewTransition: false });
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
viewTransition?: "auto" | false;
|
|
398
|
+
|
|
360
399
|
/**
|
|
361
400
|
* URL patterns to register with the router.
|
|
362
401
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RangoInternal } from "./router-interfaces.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Brand marker for identifying router instances at build time.
|
|
@@ -12,10 +12,7 @@ export const RSC_ROUTER_BRAND = "__rsc_router__" as const;
|
|
|
12
12
|
* Used by the Vite plugin at build time to discover routers and extract
|
|
13
13
|
* manifests, prefix trees, and pre-render candidates.
|
|
14
14
|
*/
|
|
15
|
-
export const RouterRegistry: Map<
|
|
16
|
-
string,
|
|
17
|
-
RSCRouterInternal<any, any>
|
|
18
|
-
> = new Map();
|
|
15
|
+
export const RouterRegistry: Map<string, RangoInternal<any, any>> = new Map();
|
|
19
16
|
|
|
20
17
|
export let routerAutoId = 0;
|
|
21
18
|
|