@rangojs/router 0.0.0-experimental.13 → 0.0.0-experimental.15
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 +589 -4
- package/dist/bin/rango.js +425 -204
- package/dist/vite/index.js +116 -326
- package/package.json +1 -1
- package/skills/rango/SKILL.md +63 -0
- package/skills/testing/SKILL.md +226 -0
- package/skills/typesafety/SKILL.md +49 -31
- package/src/bin/rango.ts +63 -12
- package/src/build/generate-route-types.ts +260 -450
- package/src/index.rsc.ts +13 -1
- package/src/index.ts +7 -0
- package/src/route-definition.ts +31 -0
- package/src/router/match-middleware/cache-store.ts +1 -1
- package/src/router.ts +13 -6
- package/src/server.ts +13 -158
- package/src/urls.ts +29 -0
- package/src/vite/index.ts +9 -17
package/src/index.rsc.ts
CHANGED
|
@@ -67,13 +67,22 @@ export type {
|
|
|
67
67
|
NotFoundInfo,
|
|
68
68
|
NotFoundBoundaryFallbackProps,
|
|
69
69
|
NotFoundBoundaryHandler,
|
|
70
|
+
// Error handling callback types
|
|
71
|
+
ErrorPhase,
|
|
72
|
+
OnErrorContext,
|
|
73
|
+
OnErrorCallback,
|
|
70
74
|
} from "./types.js";
|
|
71
75
|
|
|
72
76
|
// Router options type (server-only, so import directly)
|
|
73
77
|
export type { RSCRouterOptions } from "./router.js";
|
|
74
78
|
|
|
75
79
|
// Server-side createLoader and redirect
|
|
76
|
-
export {
|
|
80
|
+
export {
|
|
81
|
+
createLoader,
|
|
82
|
+
redirect,
|
|
83
|
+
type RouteHelpers,
|
|
84
|
+
type RouteHandlers,
|
|
85
|
+
} from "./route-definition.js";
|
|
77
86
|
|
|
78
87
|
// Handle API
|
|
79
88
|
export { createHandle, isHandle, type Handle } from "./handle.js";
|
|
@@ -167,3 +176,6 @@ export {
|
|
|
167
176
|
type LocationStateDefinition,
|
|
168
177
|
type LocationStateEntry,
|
|
169
178
|
} from "./browser/react/location-state-shared.js";
|
|
179
|
+
|
|
180
|
+
// Path-based response type lookup from RegisteredRoutes
|
|
181
|
+
export type { PathResponse } from "./href-client.js";
|
package/src/index.ts
CHANGED
|
@@ -68,6 +68,10 @@ export type {
|
|
|
68
68
|
NotFoundInfo,
|
|
69
69
|
NotFoundBoundaryFallbackProps,
|
|
70
70
|
NotFoundBoundaryHandler,
|
|
71
|
+
// Error handling callback types
|
|
72
|
+
ErrorPhase,
|
|
73
|
+
OnErrorContext,
|
|
74
|
+
OnErrorCallback,
|
|
71
75
|
} from "./types.js";
|
|
72
76
|
|
|
73
77
|
// Search params schema types
|
|
@@ -77,6 +81,9 @@ export type { SearchSchema, SearchSchemaValue, ResolveSearchSchema, RouteSearchP
|
|
|
77
81
|
// Use this when defining loaders that will be imported by client components
|
|
78
82
|
export { createLoader } from "./loader.js";
|
|
79
83
|
|
|
84
|
+
// Route definition types (safe to import anywhere)
|
|
85
|
+
export type { RouteHelpers, RouteHandlers } from "./route-definition.js";
|
|
86
|
+
|
|
80
87
|
// Response route types (usable in both server and client contexts)
|
|
81
88
|
export type {
|
|
82
89
|
ResponseHandler,
|
package/src/route-definition.ts
CHANGED
|
@@ -517,6 +517,10 @@ export type RouteHelpers<T extends RouteDefinition, TEnv> = {
|
|
|
517
517
|
*/
|
|
518
518
|
const hasRoutesInItem = (item: AllUseItems): boolean => {
|
|
519
519
|
if (item.type === "route") return true;
|
|
520
|
+
// Lazy includes contain deferred routes — treat them as having routes
|
|
521
|
+
// to prevent the parent layout from being misclassified as orphan,
|
|
522
|
+
// which would clear its parent pointer and break the middleware chain.
|
|
523
|
+
if (item.type === "include") return true;
|
|
520
524
|
if (item.type === "cache" && item.uses) {
|
|
521
525
|
return item.uses.some((child) => hasRoutesInItem(child));
|
|
522
526
|
}
|
|
@@ -823,6 +827,11 @@ const parallel: RouteHelpers<any, any>["parallel"] = (slots, use) => {
|
|
|
823
827
|
invariant(false, "No parent entry available for parallel()");
|
|
824
828
|
}
|
|
825
829
|
|
|
830
|
+
invariant(
|
|
831
|
+
ctx.parent.type !== "parallel",
|
|
832
|
+
"parallel() cannot be nested inside another parallel()"
|
|
833
|
+
);
|
|
834
|
+
|
|
826
835
|
const namespace = `${ctx.namespace}.$${store.getNextIndex("parallel")}`;
|
|
827
836
|
|
|
828
837
|
// Unwrap any static handler definitions in parallel slots
|
|
@@ -888,6 +897,11 @@ const intercept: RouteHelpers<any, any>["intercept"] = (
|
|
|
888
897
|
invariant(false, "No parent entry available for intercept()");
|
|
889
898
|
}
|
|
890
899
|
|
|
900
|
+
invariant(
|
|
901
|
+
ctx.parent.type !== "parallel",
|
|
902
|
+
"intercept() cannot be used inside parallel()"
|
|
903
|
+
);
|
|
904
|
+
|
|
891
905
|
const namespace = `${ctx.namespace}.$${store.getNextIndex("intercept")}.${slotName}`;
|
|
892
906
|
|
|
893
907
|
// Apply name prefix to routeName (from include())
|
|
@@ -1080,6 +1094,12 @@ const layout: RouteHelpers<any, any>["layout"] = (handler, use) => {
|
|
|
1080
1094
|
const store = getContext();
|
|
1081
1095
|
const ctx = store.getStore();
|
|
1082
1096
|
if (!ctx) throw new Error("layout() must be called inside map()");
|
|
1097
|
+
|
|
1098
|
+
invariant(
|
|
1099
|
+
!ctx.parent || ctx.parent.type !== "parallel",
|
|
1100
|
+
"layout() cannot be used inside parallel()"
|
|
1101
|
+
);
|
|
1102
|
+
|
|
1083
1103
|
const isRoot = !ctx.parent || ctx.parent === null;
|
|
1084
1104
|
const nextIndex = isRoot ? "$root" : store.getNextIndex("layout");
|
|
1085
1105
|
const namespace = `${ctx.namespace}.${nextIndex}`;
|
|
@@ -1127,6 +1147,17 @@ const layout: RouteHelpers<any, any>["layout"] = (handler, use) => {
|
|
|
1127
1147
|
result.some((item) => hasRoutesInItem(item));
|
|
1128
1148
|
|
|
1129
1149
|
if (!hasRoutes) {
|
|
1150
|
+
// Orphan layouts must not contain other layouts as children.
|
|
1151
|
+
// If we're here, all child layouts are also orphan (if any had routes,
|
|
1152
|
+
// hasRoutesInItem would have returned true). Nested orphan chains are
|
|
1153
|
+
// confusing — use sibling orphan layouts instead.
|
|
1154
|
+
if (result) {
|
|
1155
|
+
invariant(
|
|
1156
|
+
!result.some((item) => item?.type === "layout"),
|
|
1157
|
+
`orphan layout cannot contain other layouts as children [${namespace}]`
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1130
1161
|
const parent = ctx.parent;
|
|
1131
1162
|
|
|
1132
1163
|
// Allow orphan layouts at root level if they're part of map() builder result
|
|
@@ -104,8 +104,8 @@ import type { ResolvedSegment } from "../../types.js";
|
|
|
104
104
|
import { getRequestContext } from "../../server/request-context.js";
|
|
105
105
|
import type { MatchContext, MatchPipelineState } from "../match-context.js";
|
|
106
106
|
import { getRouterContext } from "../router-context.js";
|
|
107
|
-
import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
108
107
|
import { debugLog, debugWarn } from "../logging.js";
|
|
108
|
+
import type { GeneratorMiddleware } from "./cache-lookup.js";
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
111
|
* Creates cache store middleware
|
package/src/router.ts
CHANGED
|
@@ -98,7 +98,7 @@ import {
|
|
|
98
98
|
} from "./router/match-api.js";
|
|
99
99
|
|
|
100
100
|
import type { SegmentResolutionDeps, MatchApiDeps } from "./router/types.js";
|
|
101
|
-
import { createHandlerContext
|
|
101
|
+
import { createHandlerContext } from "./router/handler-context.js";
|
|
102
102
|
import {
|
|
103
103
|
setupLoaderAccess,
|
|
104
104
|
setupLoaderAccessSilent,
|
|
@@ -1655,7 +1655,7 @@ export function createRouter<TEnv = any>(
|
|
|
1655
1655
|
routes: {} as ResolvedRouteMap<any>, // Empty until first match
|
|
1656
1656
|
trailingSlash: entry.trailingSlash,
|
|
1657
1657
|
handler: (lazyInclude.patterns as UrlPatterns<TEnv>).handler,
|
|
1658
|
-
mountIndex:
|
|
1658
|
+
mountIndex: mountIndex++,
|
|
1659
1659
|
// Lazy evaluation fields
|
|
1660
1660
|
lazy: true,
|
|
1661
1661
|
lazyPatterns: lazyInclude.patterns,
|
|
@@ -1911,11 +1911,18 @@ export function createRouter<TEnv = any>(
|
|
|
1911
1911
|
};
|
|
1912
1912
|
|
|
1913
1913
|
return runWithRequestContext(minimalRequestContext, async () => {
|
|
1914
|
-
// 6. Create
|
|
1915
|
-
|
|
1914
|
+
// 6. Create handler context with synthetic request for pre-rendering.
|
|
1915
|
+
// The synthetic request and route map are available at build time,
|
|
1916
|
+
// so reverse() and other context properties work normally.
|
|
1917
|
+
const buildCtx = createHandlerContext<TEnv>(
|
|
1916
1918
|
matchedParams,
|
|
1919
|
+
minimalRequestContext.request,
|
|
1920
|
+
minimalRequestContext.url.searchParams,
|
|
1917
1921
|
pathname,
|
|
1918
|
-
|
|
1922
|
+
minimalRequestContext.url,
|
|
1923
|
+
{},
|
|
1924
|
+
mergedRouteMap,
|
|
1925
|
+
matched.routeKey,
|
|
1919
1926
|
);
|
|
1920
1927
|
|
|
1921
1928
|
// 7. Wire use() for handles only (loaders throw)
|
|
@@ -2527,7 +2534,7 @@ export function createRouter<TEnv = any>(
|
|
|
2527
2534
|
routes: {} as ResolvedRouteMap<any>, // Empty until first match
|
|
2528
2535
|
trailingSlash: trailingSlashConfig,
|
|
2529
2536
|
handler: urlPatterns.handler,
|
|
2530
|
-
mountIndex:
|
|
2537
|
+
mountIndex: mountIndex++,
|
|
2531
2538
|
// Lazy evaluation fields
|
|
2532
2539
|
lazy: true,
|
|
2533
2540
|
lazyPatterns: lazyInclude.patterns,
|
package/src/server.ts
CHANGED
|
@@ -1,95 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* @rangojs/router/server — Internal subpath
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* This module is NOT user-facing. Import from "@rangojs/router" instead.
|
|
5
|
+
*
|
|
6
|
+
* Exports here are consumed by the Vite plugin (discovery, manifest injection,
|
|
7
|
+
* virtual modules) and the RSC handler internals. They are not part of the
|
|
8
|
+
* public API and may change without notice.
|
|
6
9
|
*/
|
|
7
10
|
|
|
8
|
-
//
|
|
9
|
-
export {
|
|
10
|
-
createLoader,
|
|
11
|
-
redirect,
|
|
12
|
-
type RouteHelpers,
|
|
13
|
-
type RouteHandlers,
|
|
14
|
-
} from "./route-definition.js";
|
|
15
|
-
|
|
16
|
-
// Django-style URL patterns (server-only)
|
|
11
|
+
// Router registry (used by Vite plugin for build-time discovery)
|
|
17
12
|
export {
|
|
18
|
-
urls,
|
|
19
|
-
RESPONSE_TYPE,
|
|
20
|
-
type PathHelpers,
|
|
21
|
-
type PathOptions,
|
|
22
|
-
type UrlPatterns,
|
|
23
|
-
type IncludeOptions,
|
|
24
|
-
type ResponseHandler,
|
|
25
|
-
type ResponseHandlerContext,
|
|
26
|
-
type JsonResponseHandler,
|
|
27
|
-
type TextResponseHandler,
|
|
28
|
-
type JsonValue,
|
|
29
|
-
type ResponsePathFn,
|
|
30
|
-
type JsonResponsePathFn,
|
|
31
|
-
type TextResponsePathFn,
|
|
32
|
-
type RouteResponse,
|
|
33
|
-
type ResponseError,
|
|
34
|
-
type ResponseEnvelope,
|
|
35
|
-
} from "./urls.js";
|
|
36
|
-
|
|
37
|
-
// Re-export IncludeItem from route-types
|
|
38
|
-
export type { IncludeItem } from "./route-types.js";
|
|
39
|
-
|
|
40
|
-
// Core router (server-only)
|
|
41
|
-
export {
|
|
42
|
-
createRouter,
|
|
43
13
|
RSC_ROUTER_BRAND,
|
|
44
14
|
RouterRegistry,
|
|
45
|
-
type RSCRouter,
|
|
46
|
-
type RSCRouterOptions,
|
|
47
|
-
type RootLayoutProps,
|
|
48
15
|
} from "./router.js";
|
|
49
16
|
|
|
50
|
-
//
|
|
51
|
-
export {
|
|
52
|
-
createReverse,
|
|
53
|
-
type ReverseFunction,
|
|
54
|
-
type PrefixedRoutes,
|
|
55
|
-
type PrefixRoutePatterns,
|
|
56
|
-
type ParamsFor,
|
|
57
|
-
type SanitizePrefix,
|
|
58
|
-
type MergeRoutes,
|
|
59
|
-
} from "./reverse.js";
|
|
60
|
-
|
|
61
|
-
// Segment system (server-only)
|
|
62
|
-
export { renderSegments } from "./segment-system.js";
|
|
63
|
-
|
|
64
|
-
// Performance tracking (server-only)
|
|
65
|
-
export { track } from "./server/context.js";
|
|
66
|
-
|
|
67
|
-
// Handle API (works in both server and client contexts)
|
|
68
|
-
export { createHandle, isHandle, type Handle } from "./handle.js";
|
|
69
|
-
|
|
70
|
-
// Pre-render handler API
|
|
71
|
-
export {
|
|
72
|
-
Prerender,
|
|
73
|
-
isPrerenderHandler,
|
|
74
|
-
type PrerenderHandlerDefinition,
|
|
75
|
-
type PrerenderOptions,
|
|
76
|
-
type BuildContext,
|
|
77
|
-
} from "./prerender.js";
|
|
78
|
-
|
|
79
|
-
// Static handler API
|
|
80
|
-
export {
|
|
81
|
-
Static,
|
|
82
|
-
isStaticHandler,
|
|
83
|
-
type StaticHandlerDefinition,
|
|
84
|
-
} from "./static-handler.js";
|
|
85
|
-
|
|
86
|
-
// Built-in handles
|
|
87
|
-
export { Meta } from "./handles/meta.js";
|
|
88
|
-
|
|
89
|
-
// Loader registry (for GET-based loader fetching)
|
|
90
|
-
export { registerLoaderById, setLoaderImports } from "./server/loader-registry.js";
|
|
91
|
-
|
|
92
|
-
// Route map builder (for build-time manifest registration)
|
|
17
|
+
// Route map builder (Vite plugin injects these via virtual modules)
|
|
93
18
|
export {
|
|
94
19
|
registerRouteMap,
|
|
95
20
|
setCachedManifest,
|
|
@@ -103,87 +28,17 @@ export {
|
|
|
103
28
|
ensureRouterManifest,
|
|
104
29
|
} from "./route-map-builder.js";
|
|
105
30
|
|
|
106
|
-
//
|
|
31
|
+
// Loader registry (Vite plugin registers lazy loader imports)
|
|
32
|
+
export { registerLoaderById, setLoaderImports } from "./server/loader-registry.js";
|
|
33
|
+
|
|
34
|
+
// Request context creation (used by RSC handler, not user-facing)
|
|
107
35
|
export {
|
|
108
|
-
getRequestContext,
|
|
109
|
-
requireRequestContext,
|
|
110
36
|
createRequestContext,
|
|
111
|
-
type RequestContext,
|
|
112
37
|
type CreateRequestContextOptions,
|
|
113
38
|
} from "./server/request-context.js";
|
|
114
39
|
|
|
115
|
-
//
|
|
116
|
-
export type { MetaDescriptor, MetaDescriptorBase } from "./router/types.js";
|
|
117
|
-
|
|
118
|
-
// Middleware context types (Middleware type is exported from types.ts)
|
|
119
|
-
export type {
|
|
120
|
-
MiddlewareContext,
|
|
121
|
-
CookieOptions,
|
|
122
|
-
} from "./router/middleware.js";
|
|
123
|
-
|
|
124
|
-
// Error classes and utilities
|
|
125
|
-
export {
|
|
126
|
-
RouteNotFoundError,
|
|
127
|
-
DataNotFoundError,
|
|
128
|
-
notFound,
|
|
129
|
-
MiddlewareError,
|
|
130
|
-
HandlerError,
|
|
131
|
-
BuildError,
|
|
132
|
-
InvalidHandlerError,
|
|
133
|
-
sanitizeError,
|
|
134
|
-
RouterError,
|
|
135
|
-
} from "./errors.js";
|
|
136
|
-
|
|
137
|
-
// Component utilities
|
|
40
|
+
// Component utilities (used internally for server/client boundary checks)
|
|
138
41
|
export {
|
|
139
42
|
isClientComponent,
|
|
140
43
|
assertClientComponent,
|
|
141
44
|
} from "./component-utils.js";
|
|
142
|
-
|
|
143
|
-
// Debug utilities for route matching (development only)
|
|
144
|
-
export {
|
|
145
|
-
enableMatchDebug,
|
|
146
|
-
getMatchDebugStats,
|
|
147
|
-
} from "./router/pattern-matching.js";
|
|
148
|
-
|
|
149
|
-
// Types (re-exported for convenience - user-facing only)
|
|
150
|
-
export type {
|
|
151
|
-
// Configuration types
|
|
152
|
-
RouterEnv,
|
|
153
|
-
DefaultEnv,
|
|
154
|
-
RouteDefinition,
|
|
155
|
-
RouteConfig,
|
|
156
|
-
RouteDefinitionOptions,
|
|
157
|
-
TrailingSlashMode,
|
|
158
|
-
// Handler types
|
|
159
|
-
Handler, // Supports params object, path pattern, or route name
|
|
160
|
-
HandlerContext,
|
|
161
|
-
ExtractParams,
|
|
162
|
-
GenericParams,
|
|
163
|
-
// Middleware types (also exported from router/middleware.js above)
|
|
164
|
-
Middleware, // Supports env type and optional route name for params
|
|
165
|
-
// Revalidation types
|
|
166
|
-
RevalidateParams,
|
|
167
|
-
Revalidate,
|
|
168
|
-
RouteKeys,
|
|
169
|
-
// Loader types
|
|
170
|
-
LoaderDefinition,
|
|
171
|
-
LoaderFn,
|
|
172
|
-
LoaderContext,
|
|
173
|
-
// Error boundary types
|
|
174
|
-
ErrorInfo,
|
|
175
|
-
ErrorBoundaryFallbackProps,
|
|
176
|
-
ErrorBoundaryHandler,
|
|
177
|
-
ClientErrorBoundaryFallbackProps,
|
|
178
|
-
// NotFound boundary types
|
|
179
|
-
NotFoundInfo,
|
|
180
|
-
NotFoundBoundaryFallbackProps,
|
|
181
|
-
NotFoundBoundaryHandler,
|
|
182
|
-
// Error handling callback types
|
|
183
|
-
ErrorPhase,
|
|
184
|
-
OnErrorContext,
|
|
185
|
-
OnErrorCallback,
|
|
186
|
-
} from "./types.js";
|
|
187
|
-
|
|
188
|
-
// Path-based response type lookup from RegisteredRoutes
|
|
189
|
-
export type { PathResponse } from "./href-client.js";
|
package/src/urls.ts
CHANGED
|
@@ -813,6 +813,24 @@ function createPathHelper<TEnv>(): PathFn<TEnv> {
|
|
|
813
813
|
const ctx = store.getStore();
|
|
814
814
|
if (!ctx) throw new Error("path() must be called inside urls()");
|
|
815
815
|
|
|
816
|
+
invariant(
|
|
817
|
+
!ctx.parent || ctx.parent.type !== "parallel",
|
|
818
|
+
"path() cannot be used inside parallel()"
|
|
819
|
+
);
|
|
820
|
+
|
|
821
|
+
// Walk the parent chain to prevent path() nested under another path(),
|
|
822
|
+
// even when separated by intermediate layouts (e.g. path(layout(path())))
|
|
823
|
+
{
|
|
824
|
+
let ancestor = ctx.parent;
|
|
825
|
+
while (ancestor) {
|
|
826
|
+
invariant(
|
|
827
|
+
ancestor.type !== "route",
|
|
828
|
+
"path() cannot be nested inside another path()"
|
|
829
|
+
);
|
|
830
|
+
ancestor = ancestor.parent;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
816
834
|
// Determine options and use based on argument types
|
|
817
835
|
let options: PathOptions | undefined;
|
|
818
836
|
let use: (() => RouteUseItem[]) | undefined;
|
|
@@ -1113,6 +1131,17 @@ function createIncludeHelper<TEnv>(): IncludeFn<TEnv> {
|
|
|
1113
1131
|
// sibling entries (e.g., BlogLayout and ArticlesLayout under NavLayout).
|
|
1114
1132
|
const capturedCounters = { ...ctx.counters };
|
|
1115
1133
|
|
|
1134
|
+
// Reserve a layout slot in the parent's counter so sibling lazy includes
|
|
1135
|
+
// produce different shortCode indices for their root layout.
|
|
1136
|
+
// Without this, consecutive include() calls capture identical counters
|
|
1137
|
+
// and their first child layouts get the same shortCode (e.g., both M0L0L0),
|
|
1138
|
+
// causing the client partial-update diff to see no changes on navigation.
|
|
1139
|
+
if (capturedParent?.shortCode) {
|
|
1140
|
+
const layoutCounterKey = `${capturedParent.shortCode}_layout`;
|
|
1141
|
+
ctx.counters[layoutCounterKey] ??= 0;
|
|
1142
|
+
ctx.counters[layoutCounterKey]++;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1116
1145
|
// All includes are lazy - patterns are evaluated on first matching request
|
|
1117
1146
|
// This improves cold start time significantly for large route sets
|
|
1118
1147
|
return {
|
package/src/vite/index.ts
CHANGED
|
@@ -7,8 +7,6 @@ import { createRequire } from "node:module";
|
|
|
7
7
|
import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync } from "node:fs";
|
|
8
8
|
import {
|
|
9
9
|
generateRouteTypesSource,
|
|
10
|
-
writePerModuleRouteTypes,
|
|
11
|
-
writePerModuleRouteTypesForFile,
|
|
12
10
|
writeCombinedRouteTypes,
|
|
13
11
|
findRouterFiles,
|
|
14
12
|
createScanFilter,
|
|
@@ -111,9 +109,8 @@ interface RangoBaseOptions {
|
|
|
111
109
|
banner?: boolean;
|
|
112
110
|
|
|
113
111
|
/**
|
|
114
|
-
* Generate
|
|
115
|
-
*
|
|
116
|
-
* Handler<"name", routes> and href() without executing router code.
|
|
112
|
+
* Generate named-routes.gen.ts by parsing url modules at startup.
|
|
113
|
+
* Provides type-safe Handler<"name"> and href() without executing router code.
|
|
117
114
|
* Set to `false` to disable (run `npx rango extract-names` manually instead).
|
|
118
115
|
* @default true
|
|
119
116
|
*/
|
|
@@ -964,15 +961,13 @@ function createRouterDiscoveryPlugin(
|
|
|
964
961
|
exclude: opts.exclude,
|
|
965
962
|
});
|
|
966
963
|
}
|
|
967
|
-
// Generate
|
|
968
|
-
// Runs before the dev server starts so
|
|
964
|
+
// Generate combined named-routes.gen.ts from static source parsing.
|
|
965
|
+
// Runs before the dev server starts so the gen file exists immediately for IDE.
|
|
969
966
|
// In build mode, the runtime discovery in buildStart produces the definitive
|
|
970
|
-
// named-routes.gen.ts (including dynamically generated routes).
|
|
971
|
-
//
|
|
972
|
-
//
|
|
973
|
-
// previously generated complete file with a partial one.
|
|
967
|
+
// named-routes.gen.ts (including dynamically generated routes).
|
|
968
|
+
// preserveIfLarger prevents overwriting a previously generated complete
|
|
969
|
+
// file with a partial one.
|
|
974
970
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
975
|
-
writePerModuleRouteTypes(projectRoot, scanFilter);
|
|
976
971
|
cachedRouterFiles = findRouterFiles(projectRoot, scanFilter);
|
|
977
972
|
writeCombinedRouteTypes(projectRoot, cachedRouterFiles, { preserveIfLarger: true });
|
|
978
973
|
}
|
|
@@ -1173,8 +1168,8 @@ function createRouterDiscoveryPlugin(
|
|
|
1173
1168
|
res.end("No prerender match");
|
|
1174
1169
|
});
|
|
1175
1170
|
|
|
1176
|
-
// Watch url module and router files for changes and regenerate
|
|
1177
|
-
// Process files containing urls(
|
|
1171
|
+
// Watch url module and router files for changes and regenerate named-routes.gen.ts.
|
|
1172
|
+
// Process files containing urls( or createRouter( to update the combined route map.
|
|
1178
1173
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
1179
1174
|
server.watcher.on("change", (filePath) => {
|
|
1180
1175
|
if (filePath.endsWith(".gen.ts")) return;
|
|
@@ -1188,9 +1183,6 @@ function createRouterDiscoveryPlugin(
|
|
|
1188
1183
|
const hasUrls = source.includes("urls(");
|
|
1189
1184
|
const hasCreateRouter = /\bcreateRouter\s*[<(]/.test(source);
|
|
1190
1185
|
if (!hasUrls && !hasCreateRouter) return;
|
|
1191
|
-
if (hasUrls) {
|
|
1192
|
-
writePerModuleRouteTypesForFile(filePath);
|
|
1193
|
-
}
|
|
1194
1186
|
// Invalidate cache when a router file changes (new router added/removed)
|
|
1195
1187
|
if (hasCreateRouter) {
|
|
1196
1188
|
cachedRouterFiles = undefined;
|