@rangojs/router 0.0.0-experimental.1b930379 → 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/AGENTS.md +4 -0
- package/README.md +76 -18
- package/dist/bin/rango.js +138 -50
- package/dist/vite/index.js +558 -319
- package/package.json +16 -15
- package/skills/cache-guide/SKILL.md +32 -0
- package/skills/caching/SKILL.md +45 -4
- package/skills/links/SKILL.md +3 -1
- package/skills/loader/SKILL.md +53 -43
- package/skills/middleware/SKILL.md +2 -0
- package/skills/parallel/SKILL.md +126 -0
- package/skills/prerender/SKILL.md +110 -68
- package/skills/route/SKILL.md +31 -0
- package/skills/router-setup/SKILL.md +87 -2
- package/skills/typesafety/SKILL.md +10 -0
- package/src/__internal.ts +1 -1
- package/src/browser/app-version.ts +14 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/navigation-bridge.ts +19 -13
- package/src/browser/navigation-client.ts +115 -58
- 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 +57 -5
- package/src/browser/prefetch/fetch.ts +38 -23
- package/src/browser/prefetch/queue.ts +92 -20
- package/src/browser/prefetch/resource-ready.ts +77 -0
- package/src/browser/react/Link.tsx +53 -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 +134 -59
- package/src/browser/scroll-restoration.ts +41 -42
- package/src/browser/segment-reconciler.ts +6 -1
- package/src/browser/server-action-bridge.ts +8 -6
- package/src/browser/types.ts +36 -5
- package/src/build/generate-manifest.ts +6 -6
- package/src/build/generate-route-types.ts +3 -0
- 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.tsx +2 -56
- package/src/context-var.ts +72 -2
- package/src/debug.ts +2 -2
- package/src/handle.ts +40 -0
- package/src/index.rsc.ts +3 -1
- package/src/index.ts +8 -0
- package/src/prerender/store.ts +5 -4
- 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 -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 +79 -23
- package/src/router/intercept-resolution.ts +11 -4
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/loader-resolution.ts +122 -10
- package/src/router/logging.ts +5 -2
- package/src/router/manifest.ts +9 -3
- package/src/router/match-api.ts +124 -189
- 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 -6
- package/src/router/metrics.ts +6 -1
- package/src/router/middleware-types.ts +6 -8
- package/src/router/middleware.ts +4 -6
- package/src/router/navigation-snapshot.ts +182 -0
- package/src/router/prerender-match.ts +110 -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 +36 -4
- package/src/router/router-options.ts +37 -11
- package/src/router/segment-resolution/fresh.ts +183 -20
- package/src/router/segment-resolution/helpers.ts +29 -24
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +412 -297
- package/src/router/segment-wrappers.ts +2 -0
- package/src/router/types.ts +1 -0
- package/src/router.ts +59 -6
- package/src/rsc/handler.ts +460 -368
- package/src/rsc/manifest-init.ts +5 -1
- package/src/rsc/progressive-enhancement.ts +4 -0
- package/src/rsc/rsc-rendering.ts +5 -0
- package/src/rsc/server-action.ts +2 -0
- package/src/rsc/ssr-setup.ts +2 -2
- package/src/rsc/types.ts +8 -1
- package/src/segment-system.tsx +140 -4
- package/src/server/context.ts +140 -14
- package/src/server/loader-registry.ts +9 -8
- package/src/server/request-context.ts +144 -18
- 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 +137 -33
- package/src/types/loader-types.ts +36 -9
- package/src/types/route-entry.ts +8 -1
- package/src/types/segments.ts +2 -0
- 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 +30 -33
- package/src/vite/discovery/discover-routers.ts +5 -1
- package/src/vite/discovery/prerender-collection.ts +14 -1
- 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/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 +153 -42
- package/src/vite/utils/banner.ts +3 -3
- package/src/vite/utils/prerender-utils.ts +18 -0
- 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,
|
|
@@ -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
|
|
|
@@ -526,6 +536,7 @@ export function createRouter<TEnv = any>(
|
|
|
526
536
|
trackHandler,
|
|
527
537
|
findNearestErrorBoundary,
|
|
528
538
|
findNearestNotFoundBoundary,
|
|
539
|
+
notFoundComponent: notFound,
|
|
529
540
|
callOnError,
|
|
530
541
|
};
|
|
531
542
|
|
|
@@ -560,6 +571,7 @@ export function createRouter<TEnv = any>(
|
|
|
560
571
|
mergedRouteMap,
|
|
561
572
|
nextMountIndex: () => mountIndex++,
|
|
562
573
|
getPrecomputedByPrefix,
|
|
574
|
+
routerId,
|
|
563
575
|
};
|
|
564
576
|
|
|
565
577
|
function evaluateLazyEntry(entry: RouteEntry<TEnv>): void {
|
|
@@ -613,6 +625,8 @@ export function createRouter<TEnv = any>(
|
|
|
613
625
|
params: Record<string, string>,
|
|
614
626
|
buildVars?: Record<string, any>,
|
|
615
627
|
isPassthroughRoute?: boolean,
|
|
628
|
+
buildEnv?: TEnv,
|
|
629
|
+
devMode?: boolean,
|
|
616
630
|
) {
|
|
617
631
|
return _matchForPrerender(
|
|
618
632
|
pathname,
|
|
@@ -620,6 +634,8 @@ export function createRouter<TEnv = any>(
|
|
|
620
634
|
prerenderDeps,
|
|
621
635
|
buildVars,
|
|
622
636
|
isPassthroughRoute,
|
|
637
|
+
buildEnv,
|
|
638
|
+
devMode,
|
|
623
639
|
);
|
|
624
640
|
}
|
|
625
641
|
|
|
@@ -627,12 +643,16 @@ export function createRouter<TEnv = any>(
|
|
|
627
643
|
handler: Function,
|
|
628
644
|
handlerId: string,
|
|
629
645
|
routeName?: string,
|
|
646
|
+
buildEnv?: TEnv,
|
|
647
|
+
devMode?: boolean,
|
|
630
648
|
) {
|
|
631
649
|
return _renderStaticSegment<TEnv>(
|
|
632
650
|
handler,
|
|
633
651
|
handlerId,
|
|
634
652
|
mergedRouteMap,
|
|
635
653
|
routeName,
|
|
654
|
+
buildEnv,
|
|
655
|
+
devMode,
|
|
636
656
|
);
|
|
637
657
|
}
|
|
638
658
|
|
|
@@ -657,8 +677,15 @@ export function createRouter<TEnv = any>(
|
|
|
657
677
|
const router: RSCRouterInternal<TEnv, {}> = {
|
|
658
678
|
__brand: RSC_ROUTER_BRAND,
|
|
659
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;
|
|
660
688
|
|
|
661
|
-
routes(urlPatterns: UrlPatterns<TEnv>): any {
|
|
662
689
|
// Store reference for runtime manifest generation
|
|
663
690
|
storedUrlPatterns = urlPatterns;
|
|
664
691
|
const currentMountIndex = mountIndex++;
|
|
@@ -689,7 +716,7 @@ export function createRouter<TEnv = any>(
|
|
|
689
716
|
errorBoundary: [],
|
|
690
717
|
notFoundBoundary: [],
|
|
691
718
|
layout: [],
|
|
692
|
-
parallel:
|
|
719
|
+
parallel: {},
|
|
693
720
|
intercept: [],
|
|
694
721
|
loader: [],
|
|
695
722
|
};
|
|
@@ -706,6 +733,10 @@ export function createRouter<TEnv = any>(
|
|
|
706
733
|
counters: {},
|
|
707
734
|
mountIndex: currentMountIndex,
|
|
708
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 } : {}),
|
|
709
740
|
},
|
|
710
741
|
() => {
|
|
711
742
|
handlerResult = urlPatterns.handler() as AllUseItems[];
|
|
@@ -725,7 +756,7 @@ export function createRouter<TEnv = any>(
|
|
|
725
756
|
if (entry.type === "route" && entry.isPrerender) {
|
|
726
757
|
if (!prerenderRouteKeys) prerenderRouteKeys = new Set();
|
|
727
758
|
prerenderRouteKeys.add(name);
|
|
728
|
-
if (entry.
|
|
759
|
+
if (entry.isPassthrough === true) {
|
|
729
760
|
if (!passthroughRouteKeys) passthroughRouteKeys = new Set();
|
|
730
761
|
passthroughRouteKeys.add(name);
|
|
731
762
|
}
|
|
@@ -751,6 +782,7 @@ export function createRouter<TEnv = any>(
|
|
|
751
782
|
trailingSlash: trailingSlashConfig,
|
|
752
783
|
handler: urlPatterns.handler,
|
|
753
784
|
mountIndex: currentMountIndex,
|
|
785
|
+
routerId,
|
|
754
786
|
cacheProfiles: resolvedCacheProfiles,
|
|
755
787
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
756
788
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -770,6 +802,7 @@ export function createRouter<TEnv = any>(
|
|
|
770
802
|
trailingSlash: trailingSlashConfig,
|
|
771
803
|
handler: urlPatterns.handler,
|
|
772
804
|
mountIndex: currentMountIndex,
|
|
805
|
+
routerId,
|
|
773
806
|
cacheProfiles: resolvedCacheProfiles,
|
|
774
807
|
...(prerenderRouteKeys ? { prerenderRouteKeys } : {}),
|
|
775
808
|
...(passthroughRouteKeys ? { passthroughRouteKeys } : {}),
|
|
@@ -813,6 +846,7 @@ export function createRouter<TEnv = any>(
|
|
|
813
846
|
trailingSlash: trailingSlashConfig,
|
|
814
847
|
handler: urlPatterns.handler,
|
|
815
848
|
mountIndex: mountIndex++,
|
|
849
|
+
routerId,
|
|
816
850
|
// Lazy evaluation fields
|
|
817
851
|
lazy: true,
|
|
818
852
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -851,8 +885,18 @@ export function createRouter<TEnv = any>(
|
|
|
851
885
|
patternOrMiddleware: string | MiddlewareFn<TEnv>,
|
|
852
886
|
middleware?: MiddlewareFn<TEnv>,
|
|
853
887
|
): any {
|
|
854
|
-
//
|
|
855
|
-
|
|
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
|
+
}
|
|
856
900
|
return router;
|
|
857
901
|
},
|
|
858
902
|
|
|
@@ -953,6 +997,9 @@ export function createRouter<TEnv = any>(
|
|
|
953
997
|
// Expose source file for per-router type generation
|
|
954
998
|
__sourceFile,
|
|
955
999
|
|
|
1000
|
+
// Expose basename for runtime manifest generation
|
|
1001
|
+
__basename: basename,
|
|
1002
|
+
|
|
956
1003
|
// RSC request handler (lazily created on first call)
|
|
957
1004
|
fetch: (() => {
|
|
958
1005
|
// Handler is created on first call and reused
|
|
@@ -986,6 +1033,10 @@ export function createRouter<TEnv = any>(
|
|
|
986
1033
|
};
|
|
987
1034
|
})(),
|
|
988
1035
|
|
|
1036
|
+
// Low-level route matching for request classification
|
|
1037
|
+
findMatch: (pathname: string, metricsStore?: any) =>
|
|
1038
|
+
findMatch(pathname, metricsStore),
|
|
1039
|
+
|
|
989
1040
|
// Debug utility for manifest inspection
|
|
990
1041
|
debugManifest: () => buildDebugManifest<TEnv>(routesEntries),
|
|
991
1042
|
};
|
|
@@ -994,7 +1045,9 @@ export function createRouter<TEnv = any>(
|
|
|
994
1045
|
RouterRegistry.set(routerId, router);
|
|
995
1046
|
|
|
996
1047
|
// If urls option was provided, auto-register them
|
|
997
|
-
if (urlsOption) {
|
|
1048
|
+
if (typeof urlsOption === "function") {
|
|
1049
|
+
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
1050
|
+
} else if (urlsOption) {
|
|
998
1051
|
return router.routes(urlsOption) as RSCRouter<TEnv, {}>;
|
|
999
1052
|
}
|
|
1000
1053
|
|