@rangojs/router 0.0.0-experimental.19 → 0.0.0-experimental.1b930379
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 +46 -12
- package/dist/bin/rango.js +109 -15
- package/dist/vite/index.js +323 -121
- package/package.json +15 -16
- package/skills/breadcrumbs/SKILL.md +250 -0
- package/skills/caching/SKILL.md +4 -4
- 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/loader/SKILL.md +55 -15
- package/skills/prerender/SKILL.md +2 -2
- package/skills/rango/SKILL.md +0 -1
- package/skills/route/SKILL.md +3 -4
- package/skills/router-setup/SKILL.md +8 -3
- package/skills/typesafety/SKILL.md +25 -23
- package/src/__internal.ts +92 -0
- package/src/bin/rango.ts +18 -0
- package/src/browser/link-interceptor.ts +4 -0
- package/src/browser/navigation-bridge.ts +95 -5
- package/src/browser/navigation-client.ts +97 -72
- package/src/browser/prefetch/cache.ts +112 -25
- package/src/browser/prefetch/fetch.ts +28 -30
- package/src/browser/prefetch/policy.ts +6 -0
- package/src/browser/react/Link.tsx +19 -7
- package/src/browser/rsc-router.tsx +11 -2
- package/src/browser/server-action-bridge.ts +448 -432
- package/src/browser/types.ts +24 -0
- package/src/build/generate-route-types.ts +2 -0
- package/src/build/route-trie.ts +19 -3
- package/src/build/route-types/router-processing.ts +125 -15
- package/src/client.rsc.tsx +2 -1
- package/src/client.tsx +1 -46
- 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 +5 -36
- package/src/index.ts +32 -66
- package/src/prerender/store.ts +56 -15
- package/src/route-definition/index.ts +0 -3
- package/src/router/handler-context.ts +30 -3
- package/src/router/loader-resolution.ts +1 -1
- package/src/router/match-api.ts +1 -1
- package/src/router/match-result.ts +0 -9
- package/src/router/metrics.ts +233 -13
- package/src/router/middleware-types.ts +53 -10
- package/src/router/middleware.ts +170 -81
- package/src/router/pattern-matching.ts +20 -5
- package/src/router/prerender-match.ts +4 -0
- package/src/router/revalidation.ts +27 -7
- package/src/router/router-interfaces.ts +14 -1
- package/src/router/router-options.ts +13 -8
- package/src/router/segment-resolution/fresh.ts +18 -0
- package/src/router/segment-resolution/helpers.ts +1 -1
- package/src/router/segment-resolution/revalidation.ts +22 -9
- package/src/router/trie-matching.ts +20 -2
- package/src/router.ts +29 -9
- package/src/rsc/handler.ts +106 -11
- package/src/rsc/index.ts +0 -20
- package/src/rsc/progressive-enhancement.ts +21 -8
- package/src/rsc/rsc-rendering.ts +30 -43
- package/src/rsc/server-action.ts +14 -10
- package/src/rsc/ssr-setup.ts +128 -0
- package/src/rsc/types.ts +2 -0
- package/src/search-params.ts +16 -13
- package/src/server/context.ts +8 -2
- package/src/server/request-context.ts +38 -16
- package/src/server.ts +6 -0
- package/src/theme/index.ts +4 -13
- package/src/types/handler-context.ts +12 -16
- package/src/types/route-config.ts +17 -8
- package/src/types/segments.ts +0 -5
- package/src/vite/discovery/bundle-postprocess.ts +31 -56
- package/src/vite/discovery/discover-routers.ts +18 -4
- package/src/vite/discovery/prerender-collection.ts +34 -14
- package/src/vite/discovery/state.ts +4 -7
- package/src/vite/index.ts +4 -3
- package/src/vite/plugins/client-ref-dedup.ts +115 -0
- package/src/vite/plugins/refresh-cmd.ts +65 -0
- package/src/vite/rango.ts +11 -0
- package/src/vite/router-discovery.ts +16 -0
- package/src/vite/utils/prerender-utils.ts +60 -0
- package/skills/testing/SKILL.md +0 -226
- package/src/route-definition/route-function.ts +0 -119
- /package/{CLAUDE.md → AGENTS.md} +0 -0
package/src/index.ts
CHANGED
|
@@ -10,9 +10,6 @@
|
|
|
10
10
|
* import from "@rangojs/router/client"
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
// Universal rendering utilities (work on both server and client)
|
|
14
|
-
export { renderSegments } from "./segment-system.js";
|
|
15
|
-
|
|
16
13
|
// Error classes (can be used on both server and client)
|
|
17
14
|
export {
|
|
18
15
|
RouteNotFoundError,
|
|
@@ -22,9 +19,6 @@ export {
|
|
|
22
19
|
HandlerError,
|
|
23
20
|
BuildError,
|
|
24
21
|
InvalidHandlerError,
|
|
25
|
-
NetworkError,
|
|
26
|
-
isNetworkError,
|
|
27
|
-
sanitizeError,
|
|
28
22
|
RouterError,
|
|
29
23
|
Skip,
|
|
30
24
|
isSkip,
|
|
@@ -41,7 +35,6 @@ export type {
|
|
|
41
35
|
TrailingSlashMode,
|
|
42
36
|
// Handler types
|
|
43
37
|
Handler, // Supports params object, path pattern, or route name
|
|
44
|
-
ScopedRouteMap, // Scoped view of GeneratedRouteMap for Handler<"localName", ScopedRouteMap<"prefix">>
|
|
45
38
|
HandlerContext,
|
|
46
39
|
ExtractParams,
|
|
47
40
|
GenericParams,
|
|
@@ -115,25 +108,32 @@ export type {
|
|
|
115
108
|
// Middleware context types
|
|
116
109
|
export type { MiddlewareContext, CookieOptions } from "./router/middleware.js";
|
|
117
110
|
|
|
111
|
+
function serverOnlyStubError(name: string): Error {
|
|
112
|
+
return new Error(
|
|
113
|
+
`${name}() is only available from "@rangojs/router" in a react-server/RSC environment. ` +
|
|
114
|
+
`For client hooks and components, import from "@rangojs/router/client".`,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
118
|
/**
|
|
119
119
|
* Error-throwing stub for server-only `urls` function.
|
|
120
120
|
*/
|
|
121
121
|
export function urls(): never {
|
|
122
|
-
throw
|
|
122
|
+
throw serverOnlyStubError("urls");
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
/**
|
|
126
126
|
* Error-throwing stub for server-only `createRouter` function.
|
|
127
127
|
*/
|
|
128
128
|
export function createRouter(): never {
|
|
129
|
-
throw
|
|
129
|
+
throw serverOnlyStubError("createRouter");
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/**
|
|
133
133
|
* Error-throwing stub for server-only `redirect` function.
|
|
134
134
|
*/
|
|
135
135
|
export function redirect(): never {
|
|
136
|
-
throw
|
|
136
|
+
throw serverOnlyStubError("redirect");
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// Handle API (universal - works on both server and client)
|
|
@@ -149,102 +149,80 @@ export { nonce } from "./rsc/nonce.js";
|
|
|
149
149
|
* Error-throwing stub for server-only `Prerender` function.
|
|
150
150
|
*/
|
|
151
151
|
export function Prerender(): never {
|
|
152
|
-
throw
|
|
152
|
+
throw serverOnlyStubError("Prerender");
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
156
|
* Error-throwing stub for server-only `Static` function.
|
|
157
157
|
*/
|
|
158
158
|
export function Static(): never {
|
|
159
|
-
throw
|
|
159
|
+
throw serverOnlyStubError("Static");
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
/**
|
|
163
163
|
* Error-throwing stub for server-only `getRequestContext` function.
|
|
164
164
|
*/
|
|
165
165
|
export function getRequestContext(): never {
|
|
166
|
-
throw
|
|
167
|
-
"getRequestContext() is server-only and requires RSC context.",
|
|
168
|
-
);
|
|
166
|
+
throw serverOnlyStubError("getRequestContext");
|
|
169
167
|
}
|
|
170
168
|
|
|
171
169
|
/**
|
|
172
170
|
* Error-throwing stub for server-only `cookies` function.
|
|
173
171
|
*/
|
|
174
172
|
export function cookies(): never {
|
|
175
|
-
throw
|
|
173
|
+
throw serverOnlyStubError("cookies");
|
|
176
174
|
}
|
|
177
175
|
|
|
178
176
|
/**
|
|
179
177
|
* Error-throwing stub for server-only `headers` function.
|
|
180
178
|
*/
|
|
181
179
|
export function headers(): never {
|
|
182
|
-
throw
|
|
180
|
+
throw serverOnlyStubError("headers");
|
|
183
181
|
}
|
|
184
182
|
|
|
185
183
|
/**
|
|
186
184
|
* Error-throwing stub for server-only `createReverse` function.
|
|
187
185
|
*/
|
|
188
186
|
export function createReverse(): never {
|
|
189
|
-
throw
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Error-throwing stub for server-only `enableMatchDebug` function.
|
|
194
|
-
*/
|
|
195
|
-
export function enableMatchDebug(): never {
|
|
196
|
-
throw new Error(
|
|
197
|
-
"enableMatchDebug() is server-only and requires RSC context.",
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Error-throwing stub for server-only `getMatchDebugStats` function.
|
|
203
|
-
*/
|
|
204
|
-
export function getMatchDebugStats(): never {
|
|
205
|
-
throw new Error(
|
|
206
|
-
"getMatchDebugStats() is server-only and requires RSC context.",
|
|
207
|
-
);
|
|
187
|
+
throw serverOnlyStubError("createReverse");
|
|
208
188
|
}
|
|
209
189
|
|
|
210
190
|
// Error-throwing stubs for server-only route helpers
|
|
211
191
|
export function layout(): never {
|
|
212
|
-
throw
|
|
192
|
+
throw serverOnlyStubError("layout");
|
|
213
193
|
}
|
|
214
194
|
export function cache(): never {
|
|
215
|
-
throw
|
|
195
|
+
throw serverOnlyStubError("cache");
|
|
216
196
|
}
|
|
217
197
|
export function middleware(): never {
|
|
218
|
-
throw
|
|
198
|
+
throw serverOnlyStubError("middleware");
|
|
219
199
|
}
|
|
220
200
|
export function revalidate(): never {
|
|
221
|
-
throw
|
|
201
|
+
throw serverOnlyStubError("revalidate");
|
|
222
202
|
}
|
|
223
203
|
export function loader(): never {
|
|
224
|
-
throw
|
|
204
|
+
throw serverOnlyStubError("loader");
|
|
225
205
|
}
|
|
226
206
|
export function loading(): never {
|
|
227
|
-
throw
|
|
207
|
+
throw serverOnlyStubError("loading");
|
|
228
208
|
}
|
|
229
209
|
export function parallel(): never {
|
|
230
|
-
throw
|
|
210
|
+
throw serverOnlyStubError("parallel");
|
|
231
211
|
}
|
|
232
212
|
export function intercept(): never {
|
|
233
|
-
throw
|
|
213
|
+
throw serverOnlyStubError("intercept");
|
|
234
214
|
}
|
|
235
215
|
export function when(): never {
|
|
236
|
-
throw
|
|
216
|
+
throw serverOnlyStubError("when");
|
|
237
217
|
}
|
|
238
218
|
export function errorBoundary(): never {
|
|
239
|
-
throw
|
|
219
|
+
throw serverOnlyStubError("errorBoundary");
|
|
240
220
|
}
|
|
241
221
|
export function notFoundBoundary(): never {
|
|
242
|
-
throw
|
|
243
|
-
"notFoundBoundary() is server-only and requires RSC context.",
|
|
244
|
-
);
|
|
222
|
+
throw serverOnlyStubError("notFoundBoundary");
|
|
245
223
|
}
|
|
246
224
|
export function transition(): never {
|
|
247
|
-
throw
|
|
225
|
+
throw serverOnlyStubError("transition");
|
|
248
226
|
}
|
|
249
227
|
|
|
250
228
|
// Request context type (safe for client)
|
|
@@ -260,14 +238,15 @@ export type {
|
|
|
260
238
|
// Meta types
|
|
261
239
|
export type { MetaDescriptor, MetaDescriptorBase } from "./router/types.js";
|
|
262
240
|
|
|
241
|
+
// Breadcrumb types
|
|
242
|
+
export type { BreadcrumbItem } from "./handles/breadcrumbs.js";
|
|
243
|
+
|
|
263
244
|
// Reverse type utilities for type-safe URL generation (Django-style URL reversal)
|
|
264
245
|
export type {
|
|
265
246
|
ScopedReverseFunction,
|
|
266
247
|
ReverseFunction,
|
|
267
248
|
ExtractLocalRoutes,
|
|
268
249
|
ParamsFor,
|
|
269
|
-
SanitizePrefix,
|
|
270
|
-
MergeRoutes,
|
|
271
250
|
} from "./reverse.js";
|
|
272
251
|
// scopedReverse() helper for handlers to get locally-typed reverse
|
|
273
252
|
export { scopedReverse } from "./reverse.js";
|
|
@@ -287,20 +266,7 @@ export type { PathResponse } from "./href-client.js";
|
|
|
287
266
|
export { createConsoleSink } from "./router/telemetry.js";
|
|
288
267
|
export { createOTelSink } from "./router/telemetry-otel.js";
|
|
289
268
|
export type { OTelTracer, OTelSpan } from "./router/telemetry-otel.js";
|
|
290
|
-
export type {
|
|
291
|
-
TelemetrySink,
|
|
292
|
-
TelemetryEvent,
|
|
293
|
-
RequestStartEvent,
|
|
294
|
-
RequestEndEvent,
|
|
295
|
-
RequestErrorEvent,
|
|
296
|
-
RequestTimeoutEvent,
|
|
297
|
-
LoaderStartEvent,
|
|
298
|
-
LoaderEndEvent,
|
|
299
|
-
LoaderErrorEvent,
|
|
300
|
-
HandlerErrorEvent,
|
|
301
|
-
CacheDecisionEvent,
|
|
302
|
-
RevalidationDecisionEvent,
|
|
303
|
-
} from "./router/telemetry.js";
|
|
269
|
+
export type { TelemetrySink, TelemetryEvent } from "./router/telemetry.js";
|
|
304
270
|
|
|
305
271
|
// Timeout types and error class
|
|
306
272
|
export { RouterTimeoutError } from "./router/timeout.js";
|
package/src/prerender/store.ts
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
* Prerender Store
|
|
3
3
|
*
|
|
4
4
|
* Reads pre-rendered segment data from the worker bundle at build time.
|
|
5
|
-
* The
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The manifest module is lazily loaded via globalThis.__loadPrerenderManifestModule,
|
|
6
|
+
* a function injected into the RSC entry that returns the manifest module
|
|
7
|
+
* containing a key-to-specifier map and a `loadPrerenderAsset` function
|
|
8
|
+
* that anchors import() resolution relative to the manifest file.
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
import type {
|
|
@@ -34,11 +35,20 @@ export interface StaticStore {
|
|
|
34
35
|
get(handlerId: string): Promise<StaticEntry | null>;
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
interface PrerenderManifestModule {
|
|
39
|
+
default: Record<string, string>;
|
|
40
|
+
loadPrerenderAsset: (
|
|
41
|
+
specifier: string,
|
|
42
|
+
) => Promise<{ default: PrerenderEntry }>;
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
declare global {
|
|
38
|
-
// Injected by closeBundle post-processing:
|
|
46
|
+
// Injected by closeBundle post-processing: lazy loader for the prerender
|
|
47
|
+
// manifest module. The module exports a key→specifier map and a
|
|
48
|
+
// loadPrerenderAsset function that anchors import() relative to the manifest.
|
|
39
49
|
// eslint-disable-next-line no-var
|
|
40
|
-
var
|
|
41
|
-
|
|
|
50
|
+
var __loadPrerenderManifestModule:
|
|
51
|
+
| (() => Promise<PrerenderManifestModule>)
|
|
42
52
|
| undefined;
|
|
43
53
|
// Injected by closeBundle post-processing: map of handlerId -> () => import("./assets/__st-*.js")
|
|
44
54
|
// Asset default export is either a string (no handles) or { encoded, handles } object.
|
|
@@ -78,17 +88,28 @@ export function createDevPrerenderStore(devUrl: string): PrerenderStore {
|
|
|
78
88
|
/**
|
|
79
89
|
* Create a prerender store.
|
|
80
90
|
* Dev mode: on-demand fetch from Vite dev server (node:fs works there).
|
|
81
|
-
* Production: backed by globalThis.
|
|
91
|
+
* Production: backed by globalThis.__loadPrerenderManifestModule which lazily
|
|
92
|
+
* loads the manifest module on first access.
|
|
82
93
|
* Returns null if no prerender data is available.
|
|
83
94
|
*/
|
|
84
95
|
export function createPrerenderStore(): PrerenderStore | null {
|
|
85
96
|
if (globalThis.__PRERENDER_DEV_URL) {
|
|
86
97
|
return createDevPrerenderStore(globalThis.__PRERENDER_DEV_URL);
|
|
87
98
|
}
|
|
88
|
-
|
|
89
|
-
if (!manifest || Object.keys(manifest).length === 0) return null;
|
|
99
|
+
if (!globalThis.__loadPrerenderManifestModule) return null;
|
|
90
100
|
|
|
91
101
|
const cache = new Map<string, Promise<PrerenderEntry | null>>();
|
|
102
|
+
let manifestModulePromise: Promise<PrerenderManifestModule | null> | null =
|
|
103
|
+
null;
|
|
104
|
+
|
|
105
|
+
function loadManifestModule(): Promise<PrerenderManifestModule | null> {
|
|
106
|
+
if (!manifestModulePromise) {
|
|
107
|
+
manifestModulePromise = globalThis.__loadPrerenderManifestModule!().catch(
|
|
108
|
+
() => null,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
return manifestModulePromise;
|
|
112
|
+
}
|
|
92
113
|
|
|
93
114
|
return {
|
|
94
115
|
get(routeName: string, paramHash: string): Promise<PrerenderEntry | null> {
|
|
@@ -96,18 +117,38 @@ export function createPrerenderStore(): PrerenderStore | null {
|
|
|
96
117
|
const cached = cache.get(key);
|
|
97
118
|
if (cached) return cached;
|
|
98
119
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
120
|
+
const promise = loadManifestModule().then((mod) => {
|
|
121
|
+
if (!mod) return null;
|
|
122
|
+
const specifier = mod.default[key];
|
|
123
|
+
if (!specifier) return null;
|
|
124
|
+
return mod
|
|
125
|
+
.loadPrerenderAsset(specifier)
|
|
126
|
+
.then((asset) => asset.default)
|
|
127
|
+
.catch(() => null);
|
|
128
|
+
});
|
|
105
129
|
cache.set(key, promise);
|
|
106
130
|
return promise;
|
|
107
131
|
},
|
|
108
132
|
};
|
|
109
133
|
}
|
|
110
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Load the prerender manifest index for test introspection.
|
|
137
|
+
* Returns the key→specifier map or null if unavailable.
|
|
138
|
+
*/
|
|
139
|
+
export async function loadPrerenderManifestIndex(): Promise<Record<
|
|
140
|
+
string,
|
|
141
|
+
string
|
|
142
|
+
> | null> {
|
|
143
|
+
if (!globalThis.__loadPrerenderManifestModule) return null;
|
|
144
|
+
try {
|
|
145
|
+
const mod = await globalThis.__loadPrerenderManifestModule();
|
|
146
|
+
return mod.default;
|
|
147
|
+
} catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
111
152
|
/**
|
|
112
153
|
* Create a static segment store.
|
|
113
154
|
* Production only: backed by globalThis.__STATIC_MANIFEST injected at build time.
|
|
@@ -9,7 +9,7 @@ import { _getRequestContext } from "../server/request-context.js";
|
|
|
9
9
|
import { getSearchSchema, isRouteRootScoped } from "../route-map-builder.js";
|
|
10
10
|
import { parseSearchParams, serializeSearchParams } from "../search-params.js";
|
|
11
11
|
import { contextGet, contextSet } from "../context-var.js";
|
|
12
|
-
import { NOCACHE_SYMBOL } from "../cache/taint.js";
|
|
12
|
+
import { NOCACHE_SYMBOL, assertNotInsideCacheExec } from "../cache/taint.js";
|
|
13
13
|
import { isAutoGeneratedRouteName } from "../route-name.js";
|
|
14
14
|
import { PRERENDER_PASSTHROUGH } from "../prerender.js";
|
|
15
15
|
|
|
@@ -213,7 +213,28 @@ export function createHandlerContext<TEnv>(
|
|
|
213
213
|
const stubResponse =
|
|
214
214
|
requestContext?.res ?? new Response(null, { status: 200 });
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
// Guard mutating Headers methods so they throw inside "use cache" functions.
|
|
217
|
+
// Uses lazy `ctx` reference (assigned below) — only the specific handler ctx
|
|
218
|
+
// is stamped by cache-runtime, not the shared request context.
|
|
219
|
+
const MUTATING_HEADERS_METHODS = new Set(["set", "append", "delete"]);
|
|
220
|
+
let ctx: InternalHandlerContext<any, TEnv>;
|
|
221
|
+
const guardedHeaders = new Proxy(stubResponse.headers, {
|
|
222
|
+
get(target, prop, receiver) {
|
|
223
|
+
const value = Reflect.get(target, prop, receiver);
|
|
224
|
+
if (typeof value === "function") {
|
|
225
|
+
if (MUTATING_HEADERS_METHODS.has(prop as string)) {
|
|
226
|
+
return (...args: any[]) => {
|
|
227
|
+
assertNotInsideCacheExec(ctx, "headers");
|
|
228
|
+
return value.apply(target, args);
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return value.bind(target);
|
|
232
|
+
}
|
|
233
|
+
return value;
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
ctx = {
|
|
217
238
|
params,
|
|
218
239
|
build: false,
|
|
219
240
|
request,
|
|
@@ -221,6 +242,7 @@ export function createHandlerContext<TEnv>(
|
|
|
221
242
|
search: searchSchema ? resolvedSearchParams : {},
|
|
222
243
|
pathname,
|
|
223
244
|
url,
|
|
245
|
+
originalUrl: new URL(request.url),
|
|
224
246
|
env: bindings,
|
|
225
247
|
var: variables,
|
|
226
248
|
get: ((keyOrVar: any) => contextGet(variables, keyOrVar)) as HandlerContext<
|
|
@@ -228,10 +250,11 @@ export function createHandlerContext<TEnv>(
|
|
|
228
250
|
TEnv
|
|
229
251
|
>["get"],
|
|
230
252
|
set: ((keyOrVar: any, value: any) => {
|
|
253
|
+
assertNotInsideCacheExec(ctx, "set");
|
|
231
254
|
contextSet(variables, keyOrVar, value);
|
|
232
255
|
}) as HandlerContext<any, TEnv>["set"],
|
|
233
256
|
res: stubResponse, // Stub response for setting headers
|
|
234
|
-
headers:
|
|
257
|
+
headers: guardedHeaders, // Guarded shorthand for res.headers
|
|
235
258
|
// Placeholder use() - will be replaced with actual implementation during request
|
|
236
259
|
use: () => {
|
|
237
260
|
throw new Error("ctx.use() called before loaders were initialized");
|
|
@@ -304,6 +327,7 @@ export function createPrerenderContext<TEnv>(
|
|
|
304
327
|
search: {},
|
|
305
328
|
pathname,
|
|
306
329
|
url: syntheticUrl,
|
|
330
|
+
originalUrl: syntheticUrl,
|
|
307
331
|
get env(): TEnv {
|
|
308
332
|
return throwUnavailable("env");
|
|
309
333
|
},
|
|
@@ -385,6 +409,9 @@ export function createStaticContext<TEnv>(
|
|
|
385
409
|
get url(): URL {
|
|
386
410
|
return throwUnavailable("url");
|
|
387
411
|
},
|
|
412
|
+
get originalUrl(): URL {
|
|
413
|
+
return throwUnavailable("originalUrl");
|
|
414
|
+
},
|
|
388
415
|
get env(): TEnv {
|
|
389
416
|
return throwUnavailable("env");
|
|
390
417
|
},
|
|
@@ -262,7 +262,7 @@ function createLoaderExecutor<TEnv>(
|
|
|
262
262
|
reverse: ctx.reverse as LoaderContext["reverse"],
|
|
263
263
|
};
|
|
264
264
|
|
|
265
|
-
const doneLoader = track(`loader:${loader.$$id}
|
|
265
|
+
const doneLoader = track(`loader:${loader.$$id}`, 2);
|
|
266
266
|
const promise = Promise.resolve(
|
|
267
267
|
loaderFn(loaderCtx as LoaderContext<any, TEnv>),
|
|
268
268
|
).finally(() => {
|
package/src/router/match-api.ts
CHANGED
|
@@ -108,7 +108,6 @@
|
|
|
108
108
|
*/
|
|
109
109
|
import type { MatchResult, ResolvedSegment } from "../types.js";
|
|
110
110
|
import type { MatchContext, MatchPipelineState } from "./match-context.js";
|
|
111
|
-
import { generateServerTiming, logMetrics } from "./metrics.js";
|
|
112
111
|
import { debugLog } from "./logging.js";
|
|
113
112
|
|
|
114
113
|
/**
|
|
@@ -186,20 +185,12 @@ export function buildMatchResult<TEnv>(
|
|
|
186
185
|
segmentIds: segmentsToRender.map((s) => s.id),
|
|
187
186
|
});
|
|
188
187
|
|
|
189
|
-
// Output metrics if enabled
|
|
190
|
-
let serverTiming: string | undefined;
|
|
191
|
-
if (ctx.metricsStore) {
|
|
192
|
-
logMetrics(ctx.request.method, ctx.pathname, ctx.metricsStore);
|
|
193
|
-
serverTiming = generateServerTiming(ctx.metricsStore);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
188
|
return {
|
|
197
189
|
segments: segmentsToRender,
|
|
198
190
|
matched: allIds,
|
|
199
191
|
diff: segmentsToRender.map((s) => s.id),
|
|
200
192
|
params: ctx.matched.params,
|
|
201
193
|
routeName: ctx.routeKey,
|
|
202
|
-
serverTiming,
|
|
203
194
|
slots: Object.keys(state.slots).length > 0 ? state.slots : undefined,
|
|
204
195
|
routeMiddleware:
|
|
205
196
|
ctx.routeMiddleware.length > 0 ? ctx.routeMiddleware : undefined,
|