@rangojs/router 0.0.0-experimental.29-prefetch-cache.29972e92 → 0.0.0-experimental.2a0dea97
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/README.md +78 -19
- package/dist/bin/rango.js +138 -50
- package/dist/vite/index.js +853 -435
- package/package.json +17 -16
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +45 -4
- package/skills/handler-use/SKILL.md +362 -0
- package/skills/hooks/SKILL.md +22 -4
- package/skills/intercept/SKILL.md +20 -0
- package/skills/layout/SKILL.md +22 -0
- package/skills/links/SKILL.md +3 -1
- package/skills/loader/SKILL.md +71 -21
- package/skills/middleware/SKILL.md +34 -3
- package/skills/migrate-nextjs/SKILL.md +560 -0
- package/skills/migrate-react-router/SKILL.md +764 -0
- package/skills/parallel/SKILL.md +185 -0
- package/skills/prerender/SKILL.md +110 -68
- package/skills/rango/SKILL.md +24 -22
- package/skills/route/SKILL.md +56 -2
- package/skills/router-setup/SKILL.md +92 -2
- package/skills/typesafety/SKILL.md +33 -21
- package/src/__internal.ts +92 -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 +125 -16
- package/src/browser/navigation-client.ts +142 -57
- package/src/browser/navigation-store.ts +43 -8
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +94 -17
- package/src/browser/prefetch/cache.ts +101 -15
- package/src/browser/prefetch/fetch.ts +98 -27
- 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 +88 -9
- 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 -60
- package/src/browser/scroll-restoration.ts +41 -42
- package/src/browser/segment-reconciler.ts +72 -10
- package/src/browser/server-action-bridge.ts +8 -6
- package/src/browser/types.ts +60 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +3 -0
- package/src/build/route-trie.ts +50 -24
- package/src/build/route-types/include-resolution.ts +8 -1
- package/src/build/route-types/router-processing.ts +223 -74
- 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 -0
- package/src/client.tsx +6 -66
- 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/index.rsc.ts +6 -36
- package/src/index.ts +50 -43
- package/src/prerender/store.ts +5 -4
- package/src/prerender.ts +138 -77
- package/src/reverse.ts +25 -1
- package/src/route-definition/dsl-helpers.ts +224 -37
- package/src/route-definition/helpers-types.ts +67 -19
- package/src/route-definition/index.ts +3 -0
- 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 +111 -25
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/loader-resolution.ts +156 -21
- 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 +94 -17
- 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 +104 -10
- package/src/router/metrics.ts +6 -1
- package/src/router/middleware-types.ts +40 -12
- package/src/router/middleware.ts +43 -79
- package/src/router/navigation-snapshot.ts +182 -0
- 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/route-snapshot.ts +245 -0
- package/src/router/router-context.ts +6 -1
- package/src/router/router-interfaces.ts +44 -5
- package/src/router/router-options.ts +49 -18
- package/src/router/segment-resolution/fresh.ts +198 -20
- 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 +438 -300
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/types.ts +1 -0
- package/src/router.ts +73 -13
- package/src/rsc/handler.ts +472 -372
- package/src/rsc/loader-fetch.ts +23 -3
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +14 -2
- package/src/rsc/rsc-rendering.ts +13 -1
- package/src/rsc/server-action.ts +8 -0
- package/src/rsc/ssr-setup.ts +2 -2
- package/src/rsc/types.ts +11 -1
- package/src/segment-content-promise.ts +33 -0
- package/src/segment-system.tsx +164 -23
- package/src/server/context.ts +140 -14
- package/src/server/handle-store.ts +19 -0
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +204 -28
- package/src/ssr/index.tsx +4 -0
- package/src/static-handler.ts +18 -6
- 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-entry.ts +8 -1
- package/src/types/segments.ts +6 -0
- package/src/urls/path-helper-types.ts +39 -6
- 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 +77 -5
- package/src/vite/discovery/bundle-postprocess.ts +30 -33
- package/src/vite/discovery/discover-routers.ts +5 -1
- package/src/vite/discovery/prerender-collection.ts +128 -74
- package/src/vite/discovery/state.ts +13 -6
- package/src/vite/index.ts +4 -0
- package/src/vite/plugin-types.ts +51 -79
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/expose-id-utils.ts +12 -0
- package/src/vite/plugins/expose-ids/handler-transform.ts +30 -0
- package/src/vite/plugins/expose-internal-ids.ts +257 -40
- package/src/vite/plugins/performance-tracks.ts +88 -0
- package/src/vite/plugins/refresh-cmd.ts +88 -26
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +163 -211
- package/src/vite/router-discovery.ts +178 -45
- package/src/vite/utils/banner.ts +3 -3
- package/src/vite/utils/prerender-utils.ts +37 -5
- package/src/vite/utils/shared-utils.ts +3 -2
|
@@ -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
|
|
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;
|
|
@@ -520,6 +536,7 @@ export function createRouter<TEnv = any>(
|
|
|
520
536
|
trackHandler,
|
|
521
537
|
findNearestErrorBoundary,
|
|
522
538
|
findNearestNotFoundBoundary,
|
|
539
|
+
notFoundComponent: notFound,
|
|
523
540
|
callOnError,
|
|
524
541
|
};
|
|
525
542
|
|
|
@@ -554,6 +571,7 @@ export function createRouter<TEnv = any>(
|
|
|
554
571
|
mergedRouteMap,
|
|
555
572
|
nextMountIndex: () => mountIndex++,
|
|
556
573
|
getPrecomputedByPrefix,
|
|
574
|
+
routerId,
|
|
557
575
|
};
|
|
558
576
|
|
|
559
577
|
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void {
|
|
@@ -607,6 +625,8 @@ export function createRouter<TEnv = any>(
|
|
|
607
625
|
params: Record<string, string>,
|
|
608
626
|
buildVars?: Record<string, any>,
|
|
609
627
|
isPassthroughRoute?: boolean,
|
|
628
|
+
buildEnv?: TEnv,
|
|
629
|
+
devMode?: boolean,
|
|
610
630
|
) {
|
|
611
631
|
return _matchForPrerender(
|
|
612
632
|
pathname,
|
|
@@ -614,6 +634,8 @@ export function createRouter<TEnv = any>(
|
|
|
614
634
|
prerenderDeps,
|
|
615
635
|
buildVars,
|
|
616
636
|
isPassthroughRoute,
|
|
637
|
+
buildEnv,
|
|
638
|
+
devMode,
|
|
617
639
|
);
|
|
618
640
|
}
|
|
619
641
|
|
|
@@ -621,12 +643,16 @@ export function createRouter<TEnv = any>(
|
|
|
621
643
|
handler: Function,
|
|
622
644
|
handlerId: string,
|
|
623
645
|
routeName?: string,
|
|
646
|
+
buildEnv?: TEnv,
|
|
647
|
+
devMode?: boolean,
|
|
624
648
|
) {
|
|
625
649
|
return _renderStaticSegment<TEnv>(
|
|
626
650
|
handler,
|
|
627
651
|
handlerId,
|
|
628
652
|
mergedRouteMap,
|
|
629
653
|
routeName,
|
|
654
|
+
buildEnv,
|
|
655
|
+
devMode,
|
|
630
656
|
);
|
|
631
657
|
}
|
|
632
658
|
|
|
@@ -651,8 +677,15 @@ export function createRouter<TEnv = any>(
|
|
|
651
677
|
const router: RSCRouterInternal<TEnv, {}> = {
|
|
652
678
|
__brand: RSC_ROUTER_BRAND,
|
|
653
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;
|
|
654
688
|
|
|
655
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
656
689
|
// Store reference for runtime manifest generation
|
|
657
690
|
storedUrlPatterns = urlPatterns;
|
|
658
691
|
const currentMountIndex = mountIndex++;
|
|
@@ -683,7 +716,7 @@ export function createRouter<TEnv = any>(
|
|
|
683
716
|
errorBoundary: [],
|
|
684
717
|
notFoundBoundary: [],
|
|
685
718
|
layout: [],
|
|
686
|
-
parallel:
|
|
719
|
+
parallel: {},
|
|
687
720
|
intercept: [],
|
|
688
721
|
loader: [],
|
|
689
722
|
};
|
|
@@ -700,6 +733,10 @@ export function createRouter<TEnv = any>(
|
|
|
700
733
|
counters: {},
|
|
701
734
|
mountIndex: currentMountIndex,
|
|
702
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 } : {}),
|
|
703
740
|
},
|
|
704
741
|
() => {
|
|
705
742
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -719,7 +756,7 @@ export function createRouter<TEnv = any>(
|
|
|
719
756
|
if (entry.type === "route" && entry.isPrerender) {
|
|
720
757
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
721
758
|
prerenderRouteKeys.add(name);
|
|
722
|
-
if (entry.
|
|
759
|
+
if (entry.isPassthrough === true) {
|
|
723
760
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
724
761
|
passthroughRouteKeys.add(name);
|
|
725
762
|
}
|
|
@@ -745,6 +782,7 @@ export function createRouter<TEnv = any>(
|
|
|
745
782
|
trailingSlash: trailingSlashConfig,
|
|
746
783
|
handler: urlPatterns.handler,
|
|
747
784
|
mountIndex: currentMountIndex,
|
|
785
|
+
routerId,
|
|
748
786
|
cacheProfiles: resolvedCacheProfiles,
|
|
749
787
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
750
788
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -764,6 +802,7 @@ export function createRouter<TEnv = any>(
|
|
|
764
802
|
trailingSlash: trailingSlashConfig,
|
|
765
803
|
handler: urlPatterns.handler,
|
|
766
804
|
mountIndex: currentMountIndex,
|
|
805
|
+
routerId,
|
|
767
806
|
cacheProfiles: resolvedCacheProfiles,
|
|
768
807
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
769
808
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -807,6 +846,7 @@ export function createRouter<TEnv = any>(
|
|
|
807
846
|
trailingSlash: trailingSlashConfig,
|
|
808
847
|
handler: urlPatterns.handler,
|
|
809
848
|
mountIndex: mountIndex++,
|
|
849
|
+
routerId,
|
|
810
850
|
// Lazy evaluation fields
|
|
811
851
|
lazy: true,
|
|
812
852
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -845,8 +885,18 @@ export function createRouter<TEnv = any>(
|
|
|
845
885
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
846
886
|
middleware?: MiddlewareFn<TEnv>,
|
|
847
887
|
): any {
|
|
848
|
-
//
|
|
849
|
-
|
|
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
|
+
}
|
|
850
900
|
return router;
|
|
851
901
|
},
|
|
852
902
|
|
|
@@ -879,8 +929,9 @@ export function createRouter<TEnv = any>(
|
|
|
879
929
|
// Expose resolved cache profiles for per-request resolution
|
|
880
930
|
cacheProfiles: resolvedCacheProfiles,
|
|
881
931
|
|
|
882
|
-
// Expose prefetch cache
|
|
932
|
+
// Expose prefetch cache settings
|
|
883
933
|
prefetchCacheControl,
|
|
934
|
+
prefetchCacheTTL,
|
|
884
935
|
|
|
885
936
|
// Expose warmup enabled flag for handler and client
|
|
886
937
|
warmupEnabled,
|
|
@@ -946,6 +997,9 @@ export function createRouter<TEnv = any>(
|
|
|
946
997
|
// Expose source file for per-router type generation
|
|
947
998
|
__sourceFile,
|
|
948
999
|
|
|
1000
|
+
// Expose basename for runtime manifest generation
|
|
1001
|
+
__basename: basename,
|
|
1002
|
+
|
|
949
1003
|
// RSC request handler (lazily created on first call)
|
|
950
1004
|
fetch: (() => {
|
|
951
1005
|
// Handler is created on first call and reused
|
|
@@ -979,6 +1033,10 @@ export function createRouter<TEnv = any>(
|
|
|
979
1033
|
};
|
|
980
1034
|
})(),
|
|
981
1035
|
|
|
1036
|
+
// Low-level route matching for request classification
|
|
1037
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1038
|
+
findMatch(pathname, metricsStore),
|
|
1039
|
+
|
|
982
1040
|
// Debug utility for manifest inspection
|
|
983
1041
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
984
1042
|
};
|
|
@@ -987,7 +1045,9 @@ export function createRouter<TEnv = any>(
|
|
|
987
1045
|
RouterRegistry.set(routerId, router);
|
|
988
1046
|
|
|
989
1047
|
// If urls option was provided, auto-register them
|
|
990
|
-
if (urlsOption) {
|
|
1048
|
+
if (typeof urlsOption === "function") {
|
|
1049
|
+
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
1050
|
+
} else if (urlsOption) {
|
|
991
1051
|
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
992
1052
|
}
|
|
993
1053
|
|