@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1fa245e2
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/{CLAUDE.md → AGENTS.md} +4 -0
- package/README.md +122 -30
- package/dist/bin/rango.js +245 -63
- package/dist/vite/index.js +859 -418
- package/package.json +3 -3
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +49 -8
- package/skills/document-cache/SKILL.md +2 -2
- package/skills/hooks/SKILL.md +33 -31
- package/skills/host-router/SKILL.md +218 -0
- package/skills/links/SKILL.md +3 -1
- package/skills/loader/SKILL.md +72 -22
- package/skills/middleware/SKILL.md +2 -0
- package/skills/parallel/SKILL.md +126 -0
- package/skills/prerender/SKILL.md +112 -70
- package/skills/rango/SKILL.md +0 -1
- package/skills/route/SKILL.md +34 -4
- package/skills/router-setup/SKILL.md +95 -5
- package/skills/typesafety/SKILL.md +35 -23
- package/src/__internal.ts +92 -0
- package/src/bin/rango.ts +18 -0
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +114 -18
- package/src/browser/navigation-client.ts +126 -44
- package/src/browser/navigation-store.ts +43 -8
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +80 -15
- package/src/browser/prefetch/cache.ts +166 -27
- package/src/browser/prefetch/fetch.ts +52 -39
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/prefetch/queue.ts +92 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/react/Link.tsx +70 -14
- package/src/browser/react/NavigationProvider.tsx +40 -4
- package/src/browser/react/context.ts +7 -2
- package/src/browser/react/use-handle.ts +9 -58
- package/src/browser/react/use-router.ts +21 -8
- package/src/browser/rsc-router.tsx +143 -59
- package/src/browser/scroll-restoration.ts +41 -42
- package/src/browser/segment-reconciler.ts +6 -1
- package/src/browser/server-action-bridge.ts +454 -436
- package/src/browser/types.ts +60 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +5 -0
- package/src/build/route-trie.ts +19 -3
- package/src/build/route-types/include-resolution.ts +8 -1
- package/src/build/route-types/router-processing.ts +346 -87
- package/src/build/route-types/scan-filter.ts +8 -1
- package/src/cache/cache-runtime.ts +15 -11
- package/src/cache/cache-scope.ts +48 -7
- package/src/cache/cf/cf-cache-store.ts +453 -11
- package/src/cache/cf/index.ts +5 -1
- package/src/cache/document-cache.ts +17 -7
- package/src/cache/index.ts +1 -0
- package/src/cache/taint.ts +55 -0
- package/src/client.rsc.tsx +2 -1
- package/src/client.tsx +3 -102
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/handle.ts +40 -0
- package/src/handles/breadcrumbs.ts +66 -0
- package/src/handles/index.ts +1 -0
- package/src/host/index.ts +0 -3
- package/src/index.rsc.ts +8 -37
- package/src/index.ts +40 -66
- package/src/prerender/store.ts +57 -15
- package/src/prerender.ts +138 -77
- package/src/reverse.ts +22 -1
- package/src/route-definition/dsl-helpers.ts +73 -25
- package/src/route-definition/helpers-types.ts +10 -6
- package/src/route-definition/index.ts +3 -3
- package/src/route-definition/redirect.ts +11 -3
- package/src/route-definition/resolve-handler-use.ts +149 -0
- package/src/route-map-builder.ts +7 -1
- package/src/route-types.ts +11 -0
- package/src/router/content-negotiation.ts +100 -1
- package/src/router/find-match.ts +4 -2
- package/src/router/handler-context.ts +108 -25
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/loader-resolution.ts +123 -11
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +9 -3
- package/src/router/match-api.ts +125 -190
- package/src/router/match-middleware/background-revalidation.ts +30 -2
- package/src/router/match-middleware/cache-lookup.ts +88 -16
- package/src/router/match-middleware/cache-store.ts +53 -10
- package/src/router/match-middleware/intercept-resolution.ts +9 -7
- package/src/router/match-middleware/segment-resolution.ts +61 -5
- package/src/router/match-result.ts +22 -15
- package/src/router/metrics.ts +238 -13
- package/src/router/middleware-types.ts +53 -12
- package/src/router/middleware.ts +172 -85
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/pattern-matching.ts +20 -5
- package/src/router/prerender-match.ts +114 -10
- package/src/router/preview-match.ts +30 -102
- package/src/router/request-classification.ts +310 -0
- package/src/router/revalidation.ts +27 -7
- package/src/router/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +50 -5
- package/src/router/router-options.ts +50 -19
- package/src/router/segment-resolution/fresh.ts +200 -19
- package/src/router/segment-resolution/helpers.ts +30 -25
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +429 -301
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/trie-matching.ts +20 -2
- package/src/router/types.ts +1 -0
- package/src/router.ts +88 -15
- package/src/rsc/handler.ts +546 -359
- package/src/rsc/index.ts +0 -20
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +25 -8
- package/src/rsc/rsc-rendering.ts +35 -43
- package/src/rsc/server-action.ts +16 -10
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +10 -1
- package/src/search-params.ts +16 -13
- package/src/segment-system.tsx +140 -4
- package/src/server/context.ts +148 -16
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +182 -34
- package/src/server.ts +6 -0
- package/src/ssr/index.tsx +4 -0
- package/src/static-handler.ts +18 -6
- package/src/theme/index.ts +4 -13
- package/src/types/cache-types.ts +4 -4
- package/src/types/handler-context.ts +149 -49
- package/src/types/loader-types.ts +36 -9
- package/src/types/route-config.ts +17 -8
- package/src/types/route-entry.ts +8 -1
- package/src/types/segments.ts +2 -5
- package/src/urls/path-helper-types.ts +9 -2
- package/src/urls/path-helper.ts +48 -13
- package/src/urls/pattern-types.ts +12 -0
- package/src/urls/response-types.ts +16 -6
- package/src/use-loader.tsx +73 -4
- package/src/vite/discovery/bundle-postprocess.ts +61 -89
- package/src/vite/discovery/discover-routers.ts +23 -5
- package/src/vite/discovery/prerender-collection.ts +48 -15
- package/src/vite/discovery/state.ts +17 -13
- package/src/vite/index.ts +8 -3
- package/src/vite/plugin-types.ts +51 -79
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/performance-tracks.ts +88 -0
- package/src/vite/plugins/refresh-cmd.ts +127 -0
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +174 -211
- package/src/vite/router-discovery.ts +169 -42
- package/src/vite/utils/banner.ts +3 -3
- package/src/vite/utils/prerender-utils.ts +78 -0
- package/src/vite/utils/shared-utils.ts +3 -2
- package/skills/testing/SKILL.md +0 -226
- package/src/route-definition/route-function.ts +0 -119
|
@@ -204,6 +204,7 @@ export function createSegmentWrappers<TEnv = any>(
|
|
|
204
204
|
interceptResult: { intercept: InterceptEntry; entry: EntryData } | null,
|
|
205
205
|
localRouteName: string,
|
|
206
206
|
pathname: string,
|
|
207
|
+
stale?: boolean,
|
|
207
208
|
): ReturnType<typeof _resolveAllSegmentsWithRevalidation> {
|
|
208
209
|
return _resolveAllSegmentsWithRevalidation(
|
|
209
210
|
entries,
|
|
@@ -221,6 +222,7 @@ export function createSegmentWrappers<TEnv = any>(
|
|
|
221
222
|
localRouteName,
|
|
222
223
|
pathname,
|
|
223
224
|
segmentDeps,
|
|
225
|
+
stale,
|
|
224
226
|
);
|
|
225
227
|
}
|
|
226
228
|
|
|
@@ -114,7 +114,25 @@ function walkTrie(
|
|
|
114
114
|
if (result) return result;
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
// Priority 2:
|
|
117
|
+
// Priority 2: Suffix-param match (e.g., :productId.html)
|
|
118
|
+
if (node.xp) {
|
|
119
|
+
for (const suffix in node.xp) {
|
|
120
|
+
if (segment.endsWith(suffix) && segment.length > suffix.length) {
|
|
121
|
+
const paramValue = segment.slice(0, -suffix.length);
|
|
122
|
+
paramValues.push(paramValue);
|
|
123
|
+
const result = walkTrie(
|
|
124
|
+
node.xp[suffix].c,
|
|
125
|
+
segments,
|
|
126
|
+
index + 1,
|
|
127
|
+
paramValues,
|
|
128
|
+
);
|
|
129
|
+
paramValues.pop();
|
|
130
|
+
if (result) return result;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Priority 3: Param match
|
|
118
136
|
if (node.p) {
|
|
119
137
|
paramValues.push(segment);
|
|
120
138
|
const result = walkTrie(node.p.c, segments, index + 1, paramValues);
|
|
@@ -122,7 +140,7 @@ function walkTrie(
|
|
|
122
140
|
if (result) return result;
|
|
123
141
|
}
|
|
124
142
|
|
|
125
|
-
// Priority
|
|
143
|
+
// Priority 4: Wildcard match (consumes rest)
|
|
126
144
|
if (node.w) {
|
|
127
145
|
const rest = joinRemainingSegments(segments, index);
|
|
128
146
|
return {
|
package/src/router/types.ts
CHANGED
|
@@ -96,6 +96,7 @@ export interface SegmentResolutionDeps<TEnv = any> {
|
|
|
96
96
|
findNearestNotFoundBoundary: (
|
|
97
97
|
entry: EntryData | null,
|
|
98
98
|
) => ReactNode | NotFoundBoundaryHandler | null;
|
|
99
|
+
notFoundComponent?: ReactNode | ((props: { pathname: string }) => ReactNode);
|
|
99
100
|
callOnError: (error: unknown, phase: ErrorPhase, context: any) => void;
|
|
100
101
|
}
|
|
101
102
|
|
package/src/router.ts
CHANGED
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
import MapRootLayout from "./server/root-layout.js";
|
|
20
20
|
import type { AllUseItems } from "./route-types.js";
|
|
21
21
|
import type { UrlPatterns } from "./urls.js";
|
|
22
|
+
import type { UrlBuilder } from "./urls/pattern-types.js";
|
|
23
|
+
import { urls } from "./urls.js";
|
|
22
24
|
import {
|
|
23
25
|
EntryData,
|
|
24
26
|
InterceptSelectorContext,
|
|
@@ -133,6 +135,7 @@ export function createRouter<TEnv = any>(
|
|
|
133
135
|
const {
|
|
134
136
|
id: userProvidedId,
|
|
135
137
|
$$id: injectedId,
|
|
138
|
+
basename: basenameOption,
|
|
136
139
|
debugPerformance = false,
|
|
137
140
|
document: documentOption,
|
|
138
141
|
defaultErrorBoundary,
|
|
@@ -147,7 +150,7 @@ export function createRouter<TEnv = any>(
|
|
|
147
150
|
$$sourceFile: injectedSourceFile,
|
|
148
151
|
nonce,
|
|
149
152
|
version,
|
|
150
|
-
|
|
153
|
+
prefetchCacheTTL: prefetchCacheTTLOption,
|
|
151
154
|
warmup: warmupOption,
|
|
152
155
|
allowDebugManifest: allowDebugManifestOption = false,
|
|
153
156
|
telemetry: telemetrySink,
|
|
@@ -158,6 +161,13 @@ export function createRouter<TEnv = any>(
|
|
|
158
161
|
originCheck: originCheckOption,
|
|
159
162
|
} = options;
|
|
160
163
|
|
|
164
|
+
// Normalize basename: ensure leading slash, strip trailing slash.
|
|
165
|
+
// A bare "/" is equivalent to no basename.
|
|
166
|
+
const basename =
|
|
167
|
+
basenameOption && basenameOption.replace(/^\/+|\/+$/g, "")
|
|
168
|
+
? "/" + basenameOption.replace(/^\/+|\/+$/g, "")
|
|
169
|
+
: undefined;
|
|
170
|
+
|
|
161
171
|
// Resolve telemetry sink (no-op when not configured)
|
|
162
172
|
const telemetry = resolveSink(telemetrySink);
|
|
163
173
|
|
|
@@ -200,11 +210,17 @@ export function createRouter<TEnv = any>(
|
|
|
200
210
|
const routerId =
|
|
201
211
|
userProvidedId ?? injectedId ?? `router_${nextRouterAutoId()}`;
|
|
202
212
|
|
|
203
|
-
// Resolve prefetch cache
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
213
|
+
// Resolve prefetch cache TTL (default: 300 seconds / 5 minutes)
|
|
214
|
+
// Clamp to a non-negative integer for valid Cache-Control max-age.
|
|
215
|
+
const rawTTL =
|
|
216
|
+
prefetchCacheTTLOption !== undefined ? prefetchCacheTTLOption : 300;
|
|
217
|
+
const prefetchCacheTTLSeconds =
|
|
218
|
+
rawTTL === false ? 0 : Math.max(0, Math.floor(rawTTL));
|
|
219
|
+
const prefetchCacheTTL = prefetchCacheTTLSeconds * 1000;
|
|
220
|
+
const prefetchCacheControl: string | false =
|
|
221
|
+
prefetchCacheTTLSeconds === 0
|
|
222
|
+
? false
|
|
223
|
+
: `private, max-age=${prefetchCacheTTLSeconds}`;
|
|
208
224
|
|
|
209
225
|
// Resolve warmup enabled flag (default: true)
|
|
210
226
|
const warmupEnabled = warmupOption !== false;
|
|
@@ -357,8 +373,18 @@ export function createRouter<TEnv = any>(
|
|
|
357
373
|
return precomputedByPrefix;
|
|
358
374
|
}
|
|
359
375
|
|
|
360
|
-
// Wrapper to pass debugPerformance to external createMetricsStore
|
|
361
|
-
|
|
376
|
+
// Wrapper to pass debugPerformance to external createMetricsStore.
|
|
377
|
+
// Also checks per-request flag set by ctx.debugPerformance() in middleware.
|
|
378
|
+
const getMetricsStore = () => {
|
|
379
|
+
const reqCtx = _getRequestContext();
|
|
380
|
+
const enabled = debugPerformance || !!reqCtx?._debugPerformance;
|
|
381
|
+
if (!enabled) return undefined;
|
|
382
|
+
if (!reqCtx) {
|
|
383
|
+
return createMetricsStore(true);
|
|
384
|
+
}
|
|
385
|
+
reqCtx._metricsStore ??= createMetricsStore(true);
|
|
386
|
+
return reqCtx._metricsStore;
|
|
387
|
+
};
|
|
362
388
|
|
|
363
389
|
// Wrapper to pass defaults to error/notFound boundary finders
|
|
364
390
|
const findNearestErrorBoundary = (entry: EntryData | null) =>
|
|
@@ -510,6 +536,7 @@ export function createRouter<TEnv = any>(
|
|
|
510
536
|
trackHandler,
|
|
511
537
|
findNearestErrorBoundary,
|
|
512
538
|
findNearestNotFoundBoundary,
|
|
539
|
+
notFoundComponent: notFound,
|
|
513
540
|
callOnError,
|
|
514
541
|
};
|
|
515
542
|
|
|
@@ -544,6 +571,7 @@ export function createRouter<TEnv = any>(
|
|
|
544
571
|
mergedRouteMap,
|
|
545
572
|
nextMountIndex: () => mountIndex++,
|
|
546
573
|
getPrecomputedByPrefix,
|
|
574
|
+
routerId,
|
|
547
575
|
};
|
|
548
576
|
|
|
549
577
|
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void {
|
|
@@ -597,6 +625,8 @@ export function createRouter<TEnv = any>(
|
|
|
597
625
|
params: Record<string, string>,
|
|
598
626
|
buildVars?: Record<string, any>,
|
|
599
627
|
isPassthroughRoute?: boolean,
|
|
628
|
+
buildEnv?: TEnv,
|
|
629
|
+
devMode?: boolean,
|
|
600
630
|
) {
|
|
601
631
|
return _matchForPrerender(
|
|
602
632
|
pathname,
|
|
@@ -604,6 +634,8 @@ export function createRouter<TEnv = any>(
|
|
|
604
634
|
prerenderDeps,
|
|
605
635
|
buildVars,
|
|
606
636
|
isPassthroughRoute,
|
|
637
|
+
buildEnv,
|
|
638
|
+
devMode,
|
|
607
639
|
);
|
|
608
640
|
}
|
|
609
641
|
|
|
@@ -611,12 +643,16 @@ export function createRouter<TEnv = any>(
|
|
|
611
643
|
handler: Function,
|
|
612
644
|
handlerId: string,
|
|
613
645
|
routeName?: string,
|
|
646
|
+
buildEnv?: TEnv,
|
|
647
|
+
devMode?: boolean,
|
|
614
648
|
) {
|
|
615
649
|
return _renderStaticSegment<TEnv>(
|
|
616
650
|
handler,
|
|
617
651
|
handlerId,
|
|
618
652
|
mergedRouteMap,
|
|
619
653
|
routeName,
|
|
654
|
+
buildEnv,
|
|
655
|
+
devMode,
|
|
620
656
|
);
|
|
621
657
|
}
|
|
622
658
|
|
|
@@ -641,8 +677,15 @@ export function createRouter<TEnv = any>(
|
|
|
641
677
|
const router: RSCRouterInternal<TEnv, {}> = {
|
|
642
678
|
__brand: RSC_ROUTER_BRAND,
|
|
643
679
|
id: routerId,
|
|
680
|
+
basename,
|
|
681
|
+
|
|
682
|
+
routes(patternsOrBuilder: UrlPatterns<TEnv> | UrlBuilder<TEnv>): any {
|
|
683
|
+
// Wrap builder functions in urls() automatically
|
|
684
|
+
const urlPatterns: UrlPatterns<TEnv> =
|
|
685
|
+
typeof patternsOrBuilder === "function"
|
|
686
|
+
? (urls(patternsOrBuilder) as UrlPatterns<TEnv>)
|
|
687
|
+
: patternsOrBuilder;
|
|
644
688
|
|
|
645
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
646
689
|
// Store reference for runtime manifest generation
|
|
647
690
|
storedUrlPatterns = urlPatterns;
|
|
648
691
|
const currentMountIndex = mountIndex++;
|
|
@@ -673,7 +716,7 @@ export function createRouter<TEnv = any>(
|
|
|
673
716
|
errorBoundary: [],
|
|
674
717
|
notFoundBoundary: [],
|
|
675
718
|
layout: [],
|
|
676
|
-
parallel:
|
|
719
|
+
parallel: {},
|
|
677
720
|
intercept: [],
|
|
678
721
|
loader: [],
|
|
679
722
|
};
|
|
@@ -690,6 +733,10 @@ export function createRouter<TEnv = any>(
|
|
|
690
733
|
counters: {},
|
|
691
734
|
mountIndex: currentMountIndex,
|
|
692
735
|
cacheProfiles: resolvedCacheProfiles,
|
|
736
|
+
// basename sets the initial URL prefix so all path() patterns
|
|
737
|
+
// are registered with the prefix (e.g. "/admin" + "/users" = "/admin/users").
|
|
738
|
+
// No namePrefix — route names stay unprefixed.
|
|
739
|
+
...(basename ? { urlPrefix: basename } : {}),
|
|
693
740
|
},
|
|
694
741
|
() => {
|
|
695
742
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -709,7 +756,7 @@ export function createRouter<TEnv = any>(
|
|
|
709
756
|
if (entry.type === "route" && entry.isPrerender) {
|
|
710
757
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
711
758
|
prerenderRouteKeys.add(name);
|
|
712
|
-
if (entry.
|
|
759
|
+
if (entry.isPassthrough === true) {
|
|
713
760
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
714
761
|
passthroughRouteKeys.add(name);
|
|
715
762
|
}
|
|
@@ -735,6 +782,7 @@ export function createRouter<TEnv = any>(
|
|
|
735
782
|
trailingSlash: trailingSlashConfig,
|
|
736
783
|
handler: urlPatterns.handler,
|
|
737
784
|
mountIndex: currentMountIndex,
|
|
785
|
+
routerId,
|
|
738
786
|
cacheProfiles: resolvedCacheProfiles,
|
|
739
787
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
740
788
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -754,6 +802,7 @@ export function createRouter<TEnv = any>(
|
|
|
754
802
|
trailingSlash: trailingSlashConfig,
|
|
755
803
|
handler: urlPatterns.handler,
|
|
756
804
|
mountIndex: currentMountIndex,
|
|
805
|
+
routerId,
|
|
757
806
|
cacheProfiles: resolvedCacheProfiles,
|
|
758
807
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
759
808
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -797,6 +846,7 @@ export function createRouter<TEnv = any>(
|
|
|
797
846
|
trailingSlash: trailingSlashConfig,
|
|
798
847
|
handler: urlPatterns.handler,
|
|
799
848
|
mountIndex: mountIndex++,
|
|
849
|
+
routerId,
|
|
800
850
|
// Lazy evaluation fields
|
|
801
851
|
lazy: true,
|
|
802
852
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -835,8 +885,18 @@ export function createRouter<TEnv = any>(
|
|
|
835
885
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
836
886
|
middleware?: MiddlewareFn<TEnv>,
|
|
837
887
|
): any {
|
|
838
|
-
//
|
|
839
|
-
|
|
888
|
+
// Auto-prefix pattern with basename so router-level middleware
|
|
889
|
+
// patterns are router-relative (e.g. "/users/*" matches "/app/users/*").
|
|
890
|
+
if (basename && typeof patternOrMiddleware === "string") {
|
|
891
|
+
const pattern = patternOrMiddleware;
|
|
892
|
+
const prefixed =
|
|
893
|
+
pattern === "/*" || pattern === "*"
|
|
894
|
+
? `${basename}/*`
|
|
895
|
+
: `${basename}${pattern}`;
|
|
896
|
+
addMiddleware(prefixed, middleware, null);
|
|
897
|
+
} else {
|
|
898
|
+
addMiddleware(patternOrMiddleware, middleware, null);
|
|
899
|
+
}
|
|
840
900
|
return router;
|
|
841
901
|
},
|
|
842
902
|
|
|
@@ -869,12 +929,16 @@ export function createRouter<TEnv = any>(
|
|
|
869
929
|
// Expose resolved cache profiles for per-request resolution
|
|
870
930
|
cacheProfiles: resolvedCacheProfiles,
|
|
871
931
|
|
|
872
|
-
// Expose prefetch cache
|
|
932
|
+
// Expose prefetch cache settings
|
|
873
933
|
prefetchCacheControl,
|
|
934
|
+
prefetchCacheTTL,
|
|
874
935
|
|
|
875
936
|
// Expose warmup enabled flag for handler and client
|
|
876
937
|
warmupEnabled,
|
|
877
938
|
|
|
939
|
+
// Expose router-wide performance debugging for request-level metrics setup
|
|
940
|
+
debugPerformance,
|
|
941
|
+
|
|
878
942
|
// Expose debug manifest flag for handler
|
|
879
943
|
allowDebugManifest: allowDebugManifestOption,
|
|
880
944
|
|
|
@@ -933,6 +997,9 @@ export function createRouter<TEnv = any>(
|
|
|
933
997
|
// Expose source file for per-router type generation
|
|
934
998
|
__sourceFile,
|
|
935
999
|
|
|
1000
|
+
// Expose basename for runtime manifest generation
|
|
1001
|
+
__basename: basename,
|
|
1002
|
+
|
|
936
1003
|
// RSC request handler (lazily created on first call)
|
|
937
1004
|
fetch: (() => {
|
|
938
1005
|
// Handler is created on first call and reused
|
|
@@ -966,6 +1033,10 @@ export function createRouter<TEnv = any>(
|
|
|
966
1033
|
};
|
|
967
1034
|
})(),
|
|
968
1035
|
|
|
1036
|
+
// Low-level route matching for request classification
|
|
1037
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1038
|
+
findMatch(pathname, metricsStore),
|
|
1039
|
+
|
|
969
1040
|
// Debug utility for manifest inspection
|
|
970
1041
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
971
1042
|
};
|
|
@@ -974,7 +1045,9 @@ export function createRouter<TEnv = any>(
|
|
|
974
1045
|
RouterRegistry.set(routerId, router);
|
|
975
1046
|
|
|
976
1047
|
// If urls option was provided, auto-register them
|
|
977
|
-
if (urlsOption) {
|
|
1048
|
+
if (typeof urlsOption === "function") {
|
|
1049
|
+
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
1050
|
+
} else if (urlsOption) {
|
|
978
1051
|
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
979
1052
|
}
|
|
980
1053
|
|