@rangojs/router 0.32.0 → 0.33.0
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 +3 -2
- package/dist/bin/browser-7KIJ5HSV.js +15 -0
- package/dist/bin/chunk-3B7CKBRO.js +463 -0
- package/dist/bin/chunk-524VACCG.js +71 -0
- package/dist/bin/chunk-LD7UBHT4.js +196 -0
- package/dist/bin/chunk-TO6CRWLN.js +1429 -0
- package/dist/bin/chunk-TTXC2U3G.js +2477 -0
- package/dist/bin/client-urls-projection-DQLWPDAT.js +28 -0
- package/dist/bin/forward-user-plugins-URBZKJP4.js +62 -0
- package/dist/bin/rango.js +42 -10173
- package/dist/bin/runtime-EPUDEHO4.js +596 -0
- package/dist/bin/runtime-discovery-CZ2QHT4Q.js +352 -0
- package/dist/bin/state-ACD2MGKJ.js +16 -0
- package/dist/bin/temp-rsc-server-QRR6HD6T.js +3190 -0
- package/dist/types/bin/rango.d.ts +1 -0
- package/dist/types/browser/action-fence.d.ts +20 -0
- package/dist/types/browser/cookie-name.d.ts +51 -10
- package/dist/types/browser/invalidate-client-cache.d.ts +8 -6
- package/dist/types/browser/navigation-bridge.d.ts +36 -1
- package/dist/types/browser/navigation-client.d.ts +19 -0
- package/dist/types/browser/navigation-store-handle.d.ts +37 -4
- package/dist/types/browser/navigation-store.d.ts +2 -2
- package/dist/types/browser/navigation-transaction.d.ts +0 -1
- package/dist/types/browser/partial-update.d.ts +13 -0
- package/dist/types/browser/prefetch/cache.d.ts +96 -8
- package/dist/types/browser/prefetch/fetch.d.ts +26 -2
- package/dist/types/browser/prefetch/queue.d.ts +3 -2
- package/dist/types/browser/rango-state.d.ts +34 -5
- package/dist/types/browser/react/Link.d.ts +15 -6
- package/dist/types/browser/types.d.ts +25 -0
- package/dist/types/build/generate-route-types.d.ts +1 -1
- package/dist/types/build/route-types/include-resolution.d.ts +9 -1
- package/dist/types/build/route-types/router-processing.d.ts +3 -1
- package/dist/types/cache/cache-key-utils.d.ts +12 -8
- package/dist/types/cache/cache-scope.d.ts +4 -2
- package/dist/types/cache/cf/cf-cache-types.d.ts +9 -5
- package/dist/types/cache/document-cache-policy.d.ts +9 -1
- package/dist/types/cache/memory-segment-store.d.ts +3 -2
- package/dist/types/cache/segment-codec.d.ts +2 -2
- package/dist/types/cache/shell-snapshot.d.ts +1 -1
- package/dist/types/cache/types.d.ts +12 -7
- package/dist/types/cache/vercel/vercel-cache-store.d.ts +2 -1
- package/dist/types/client-urls/types.d.ts +7 -5
- package/dist/types/prefetch-markers.d.ts +9 -0
- package/dist/types/prefetch-source-scope.d.ts +66 -0
- package/dist/types/route-definition/helpers-types.d.ts +8 -5
- package/dist/types/router/intercept-resolution.d.ts +25 -11
- package/dist/types/router/match-context.d.ts +1 -0
- package/dist/types/router/match-handlers.d.ts +1 -1
- package/dist/types/router/prefetch-cache-ttl.d.ts +11 -3
- package/dist/types/router/router-context.d.ts +1 -1
- package/dist/types/router/router-options.d.ts +6 -3
- package/dist/types/router/segment-resolution/loader-cache.d.ts +8 -0
- package/dist/types/router/segment-resolution/prefetch-deferral.d.ts +23 -7
- package/dist/types/router/segment-resolution/revalidation.d.ts +19 -0
- package/dist/types/router/source-reads.d.ts +53 -0
- package/dist/types/router/types.d.ts +1 -1
- package/dist/types/rsc/helpers.d.ts +5 -2
- package/dist/types/rsc/prefetch-render-error.d.ts +7 -2
- package/dist/types/rsc/request-stages.d.ts +2 -0
- package/dist/types/rsc/shell-serve.d.ts +6 -1
- package/dist/types/server/context.d.ts +23 -6
- package/dist/types/server/cookie-store.d.ts +15 -1
- package/dist/types/server/document-location-state.d.ts +5 -2
- package/dist/types/server/handle-store.d.ts +2 -0
- package/dist/types/server/request-context.d.ts +43 -7
- package/dist/types/testing/e2e/server.d.ts +16 -1
- package/dist/types/testing/render-route.d.ts +66 -2
- package/dist/types/testing/serve-shell-request.d.ts +6 -3
- package/dist/types/types/handler-context.d.ts +7 -5
- package/dist/types/types/loader-types.d.ts +7 -4
- package/dist/types/types/segments.d.ts +15 -4
- package/dist/types/urls/path-helper-types.d.ts +7 -5
- package/dist/types/vite/temp-rsc-server.d.ts +2 -2
- package/dist/vite/index.js +449 -189
- package/package.json +2 -2
- package/skills/app-structure/SKILL.md +74 -0
- package/skills/app-structure/e-commerce.md +10 -9
- package/skills/app-structure/large-app.md +15 -2
- package/skills/caching/SKILL.md +10 -5
- package/skills/client-urls/SKILL.md +18 -11
- package/skills/comparison/references/framework-comparison.md +13 -8
- package/skills/document-cache/SKILL.md +8 -0
- package/skills/hooks/navigation.md +8 -8
- package/skills/hooks/state.md +24 -8
- package/skills/intercept/SKILL.md +33 -12
- package/skills/layout/SKILL.md +11 -0
- package/skills/links/SKILL.md +101 -4
- package/skills/loader/SKILL.md +49 -22
- package/skills/migrate-nextjs/SKILL.md +8 -2
- package/skills/migrate-react-router/data-and-actions.md +5 -0
- package/skills/ppr/SKILL.md +26 -5
- package/skills/prerender/SKILL.md +4 -1
- package/skills/route/SKILL.md +6 -6
- package/skills/router-setup/SKILL.md +2 -1
- package/skills/server-actions/SKILL.md +41 -8
- package/skills/testing/client-components.md +29 -13
- package/skills/testing/serve-shell-request.md +7 -7
- package/skills/testing/server-actions.md +8 -0
- package/skills/ux-architecture/SKILL.md +67 -18
- package/src/bin/rango.ts +39 -13
- package/src/browser/action-fence.ts +72 -0
- package/src/browser/cookie-name.ts +82 -14
- package/src/browser/invalidate-client-cache.ts +9 -7
- package/src/browser/navigation-bridge.ts +164 -32
- package/src/browser/navigation-client.ts +95 -20
- package/src/browser/navigation-store-handle.ts +67 -5
- package/src/browser/navigation-store.ts +86 -17
- package/src/browser/navigation-transaction.ts +0 -6
- package/src/browser/partial-update.ts +31 -12
- package/src/browser/prefetch/cache.ts +188 -11
- package/src/browser/prefetch/fetch.ts +211 -51
- package/src/browser/prefetch/queue.ts +3 -2
- package/src/browser/rango-state.ts +50 -8
- package/src/browser/react/Link.tsx +20 -9
- package/src/browser/react/use-navigation.ts +1 -1
- package/src/browser/rsc-router.tsx +8 -1
- package/src/browser/server-action-bridge.ts +3 -3
- package/src/browser/types.ts +25 -0
- package/src/build/generate-route-types.ts +1 -0
- package/src/build/route-types/include-resolution.ts +40 -3
- package/src/build/route-types/router-processing.ts +170 -25
- package/src/build/route-types/scan-filter.ts +1 -0
- package/src/cache/cache-key-utils.ts +12 -8
- package/src/cache/cache-runtime.ts +5 -1
- package/src/cache/cache-scope.ts +28 -7
- package/src/cache/cf/cf-cache-types.ts +9 -5
- package/src/cache/document-cache-policy.ts +27 -0
- package/src/cache/document-cache.ts +5 -0
- package/src/cache/memory-segment-store.ts +3 -2
- package/src/cache/segment-codec.ts +2 -2
- package/src/cache/shell-snapshot.ts +1 -1
- package/src/cache/types.ts +12 -7
- package/src/cache/vercel/vercel-cache-store.ts +2 -1
- package/src/client-urls/types.ts +7 -5
- package/src/prefetch-markers.ts +10 -0
- package/src/prefetch-source-scope.ts +137 -0
- package/src/route-definition/helpers-types.ts +8 -5
- package/src/router/intercept-resolution.ts +94 -50
- package/src/router/loader-resolution.ts +8 -6
- package/src/router/match-api.ts +33 -29
- package/src/router/match-context.ts +5 -0
- package/src/router/match-handlers.ts +2 -1
- package/src/router/match-middleware/cache-lookup.ts +21 -13
- package/src/router/match-result.ts +39 -87
- package/src/router/navigation-snapshot.ts +18 -3
- package/src/router/prefetch-cache-ttl.ts +15 -3
- package/src/router/revalidation.ts +53 -23
- package/src/router/router-context.ts +2 -1
- package/src/router/router-options.ts +6 -3
- package/src/router/segment-resolution/loader-cache.ts +21 -3
- package/src/router/segment-resolution/prefetch-deferral.ts +38 -31
- package/src/router/segment-resolution/revalidation.ts +40 -12
- package/src/router/source-reads.ts +122 -0
- package/src/router/types.ts +2 -1
- package/src/router.ts +11 -12
- package/src/rsc/helpers.ts +8 -3
- package/src/rsc/prefetch-render-error.ts +7 -2
- package/src/rsc/progressive-enhancement.ts +3 -2
- package/src/rsc/request-stages.ts +59 -0
- package/src/rsc/rsc-rendering.ts +49 -33
- package/src/rsc/server-action.ts +2 -1
- package/src/rsc/shell-capture.ts +4 -5
- package/src/rsc/shell-serve.ts +12 -1
- package/src/segment-system.tsx +1 -1
- package/src/server/context.ts +37 -6
- package/src/server/cookie-store.ts +22 -1
- package/src/server/document-location-state.ts +23 -2
- package/src/server/handle-store.ts +2 -0
- package/src/server/request-context.ts +113 -28
- package/src/testing/dispatch.ts +3 -0
- package/src/testing/e2e/fixture.ts +4 -12
- package/src/testing/e2e/server.ts +91 -4
- package/src/testing/render-route.tsx +269 -4
- package/src/testing/serve-shell-request.ts +6 -3
- package/src/types/handler-context.ts +7 -5
- package/src/types/loader-types.ts +7 -4
- package/src/types/segments.ts +15 -4
- package/src/urls/path-helper-types.ts +7 -5
- package/src/vite/temp-rsc-server.ts +2 -2
package/dist/vite/index.js
CHANGED
|
@@ -138,11 +138,11 @@ var init_logging = __esm({
|
|
|
138
138
|
// src/browser/notify-listeners.ts
|
|
139
139
|
function notifyListeners(entries, notify, isActive, shouldContinue) {
|
|
140
140
|
const errors = [];
|
|
141
|
-
for (const
|
|
141
|
+
for (const entry2 of entries) {
|
|
142
142
|
if (shouldContinue && !shouldContinue()) break;
|
|
143
|
-
if (isActive && !isActive(
|
|
143
|
+
if (isActive && !isActive(entry2)) continue;
|
|
144
144
|
try {
|
|
145
|
-
notify(
|
|
145
|
+
notify(entry2);
|
|
146
146
|
} catch (error) {
|
|
147
147
|
errors.push(error);
|
|
148
148
|
}
|
|
@@ -179,21 +179,36 @@ function getRawCookieValue(cookieString, name) {
|
|
|
179
179
|
}
|
|
180
180
|
return null;
|
|
181
181
|
}
|
|
182
|
-
function encodeStateValue(version, timestamp) {
|
|
183
|
-
|
|
182
|
+
function encodeStateValue(version, timestamp, write = 0) {
|
|
183
|
+
const base = `${encodeURIComponent(version)}:${timestamp}`;
|
|
184
|
+
return write === 0 ? base : `${base}:${write}`;
|
|
184
185
|
}
|
|
185
186
|
function decodeStateValue(raw) {
|
|
186
187
|
const colon = raw.indexOf(":");
|
|
187
188
|
if (colon <= 0) return null;
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
189
|
+
const parts = raw.slice(colon + 1).split(":");
|
|
190
|
+
if (parts.length > 2) return null;
|
|
191
|
+
const timestamp = parseStatePart(parts[0]);
|
|
192
|
+
const write = parts.length === 2 ? parseStatePart(parts[1]) : 0;
|
|
193
|
+
if (timestamp === null || write === null) return null;
|
|
190
194
|
let version;
|
|
191
195
|
try {
|
|
192
196
|
version = decodeURIComponent(raw.slice(0, colon));
|
|
193
197
|
} catch {
|
|
194
198
|
return null;
|
|
195
199
|
}
|
|
196
|
-
return { version, timestamp };
|
|
200
|
+
return { version, timestamp, write };
|
|
201
|
+
}
|
|
202
|
+
function parseStatePart(part) {
|
|
203
|
+
if (part === "") return null;
|
|
204
|
+
const value = Number(part);
|
|
205
|
+
return Number.isFinite(value) ? value : null;
|
|
206
|
+
}
|
|
207
|
+
function stateEpoch(raw) {
|
|
208
|
+
const first = raw.indexOf(":");
|
|
209
|
+
if (first < 0) return raw;
|
|
210
|
+
const second = raw.indexOf(":", first + 1);
|
|
211
|
+
return second < 0 ? raw : raw.slice(0, second);
|
|
197
212
|
}
|
|
198
213
|
function mintStateValue(version, prevRaw) {
|
|
199
214
|
const prevTs = prevRaw ? decodeStateValue(prevRaw)?.timestamp ?? 0 : 0;
|
|
@@ -246,9 +261,11 @@ function getRangoState() {
|
|
|
246
261
|
}
|
|
247
262
|
if (read.value !== null) {
|
|
248
263
|
if (read.value !== mirror) {
|
|
264
|
+
const rotated = mirror === null || stateEpoch(mirror) !== stateEpoch(read.value);
|
|
249
265
|
mirror = read.value;
|
|
250
266
|
cookieBacked = true;
|
|
251
|
-
notifyExternalRotation(read.value);
|
|
267
|
+
if (rotated) notifyExternalRotation(read.value);
|
|
268
|
+
else externalWriteObserver?.();
|
|
252
269
|
} else {
|
|
253
270
|
cookieBacked = true;
|
|
254
271
|
}
|
|
@@ -265,7 +282,7 @@ function getRangoState() {
|
|
|
265
282
|
}
|
|
266
283
|
return mirror;
|
|
267
284
|
}
|
|
268
|
-
var cookieName, currentVersion, mirror, cookieBacked, externalRotationObserver;
|
|
285
|
+
var cookieName, currentVersion, mirror, cookieBacked, externalRotationObserver, externalWriteObserver;
|
|
269
286
|
var init_rango_state = __esm({
|
|
270
287
|
"src/browser/rango-state.ts"() {
|
|
271
288
|
"use strict";
|
|
@@ -275,6 +292,7 @@ var init_rango_state = __esm({
|
|
|
275
292
|
mirror = null;
|
|
276
293
|
cookieBacked = false;
|
|
277
294
|
externalRotationObserver = null;
|
|
295
|
+
externalWriteObserver = null;
|
|
278
296
|
}
|
|
279
297
|
});
|
|
280
298
|
|
|
@@ -318,6 +336,52 @@ var init_wire_params = __esm({
|
|
|
318
336
|
}
|
|
319
337
|
});
|
|
320
338
|
|
|
339
|
+
// src/prefetch-source-scope.ts
|
|
340
|
+
function formatSourceLabel(shape, page) {
|
|
341
|
+
const parts = [];
|
|
342
|
+
if (shape.keys) {
|
|
343
|
+
parts.push(
|
|
344
|
+
"$k=" + Object.keys(page.params).sort().map(encodeURIComponent).join(",")
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (shape.route) parts.push(entry("$r", page.routeName));
|
|
348
|
+
for (const name of shape.names) {
|
|
349
|
+
parts.push(entry(encodeURIComponent(name), page.params[name]));
|
|
350
|
+
}
|
|
351
|
+
return parts.join("&");
|
|
352
|
+
}
|
|
353
|
+
function entry(name, value) {
|
|
354
|
+
return value === void 0 ? name : name + "=" + encodeURIComponent(value);
|
|
355
|
+
}
|
|
356
|
+
function paramsScopeLabel(header) {
|
|
357
|
+
if (!header?.startsWith(PARAMS_SCOPE_PREFIX)) return void 0;
|
|
358
|
+
return header.slice(PARAMS_SCOPE_PREFIX.length);
|
|
359
|
+
}
|
|
360
|
+
function parseSourceShape(label) {
|
|
361
|
+
let keys = false;
|
|
362
|
+
let route2 = false;
|
|
363
|
+
const names = [];
|
|
364
|
+
for (const part of label.split("&")) {
|
|
365
|
+
if (part === "") continue;
|
|
366
|
+
const eq = part.indexOf("=");
|
|
367
|
+
const name = eq === -1 ? part : part.slice(0, eq);
|
|
368
|
+
if (name === "$k") keys = true;
|
|
369
|
+
else if (name === "$r") route2 = true;
|
|
370
|
+
else names.push(decodeURIComponent(name));
|
|
371
|
+
}
|
|
372
|
+
return { keys, route: route2, names: names.sort() };
|
|
373
|
+
}
|
|
374
|
+
function sourceShapeId(shape) {
|
|
375
|
+
return (shape.keys ? "k" : "") + (shape.route ? "r" : "") + ":" + shape.names.map(encodeURIComponent).join(",");
|
|
376
|
+
}
|
|
377
|
+
var PARAMS_SCOPE_PREFIX;
|
|
378
|
+
var init_prefetch_source_scope = __esm({
|
|
379
|
+
"src/prefetch-source-scope.ts"() {
|
|
380
|
+
"use strict";
|
|
381
|
+
PARAMS_SCOPE_PREFIX = "params; ";
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
|
|
321
385
|
// src/browser/prefetch/cache.ts
|
|
322
386
|
function isPrefetchCacheDisabled() {
|
|
323
387
|
return cacheTTL <= 0;
|
|
@@ -330,6 +394,31 @@ function buildPrefetchKey(prefix, targetUrl) {
|
|
|
330
394
|
function buildSourceKey(rangoState, sourceHref, targetUrl) {
|
|
331
395
|
return rangoState + "\0" + sourceHref + "\0" + targetUrl.pathname + targetUrl.search;
|
|
332
396
|
}
|
|
397
|
+
function buildParamsKey(rangoState, label, targetUrl) {
|
|
398
|
+
return buildPrefetchKey(rangoState + "\0p:" + label, targetUrl);
|
|
399
|
+
}
|
|
400
|
+
function rememberParamsShape(targetUrl, label) {
|
|
401
|
+
const target = buildPrefetchKey("", targetUrl);
|
|
402
|
+
const shape = parseSourceShape(label);
|
|
403
|
+
let shapes = paramsShapes.get(target);
|
|
404
|
+
if (!shapes) {
|
|
405
|
+
if (paramsShapes.size >= maxPrefetchCacheSize) {
|
|
406
|
+
const oldest = paramsShapes.keys().next().value;
|
|
407
|
+
if (oldest !== void 0) paramsShapes.delete(oldest);
|
|
408
|
+
}
|
|
409
|
+
shapes = /* @__PURE__ */ new Map();
|
|
410
|
+
paramsShapes.set(target, shapes);
|
|
411
|
+
}
|
|
412
|
+
shapes.set(sourceShapeId(shape), shape);
|
|
413
|
+
}
|
|
414
|
+
function paramsCandidateKeys(rangoState, targetUrl, page) {
|
|
415
|
+
if (!page) return [];
|
|
416
|
+
const shapes = paramsShapes.get(buildPrefetchKey("", targetUrl));
|
|
417
|
+
if (!shapes) return [];
|
|
418
|
+
return [...shapes.values()].sort((a, b) => weightOf(b) - weightOf(a)).map(
|
|
419
|
+
(shape) => buildParamsKey(rangoState, formatSourceLabel(shape, page), targetUrl)
|
|
420
|
+
);
|
|
421
|
+
}
|
|
333
422
|
function forEachAlias(key, fn) {
|
|
334
423
|
const aliases = inflightAliases.get(key);
|
|
335
424
|
if (aliases) {
|
|
@@ -341,20 +430,20 @@ function forEachAlias(key, fn) {
|
|
|
341
430
|
function hasPrefetch(key) {
|
|
342
431
|
if (inflight.has(key)) return true;
|
|
343
432
|
if (cacheTTL <= 0) return false;
|
|
344
|
-
const
|
|
345
|
-
if (!
|
|
346
|
-
if (Date.now() -
|
|
347
|
-
|
|
433
|
+
const entry2 = cache.get(key);
|
|
434
|
+
if (!entry2) return false;
|
|
435
|
+
if (Date.now() - entry2.timestamp > cacheTTL || isPrefetchStale(entry2.entry)) {
|
|
436
|
+
entry2.entry.dispose?.();
|
|
348
437
|
cache.delete(key);
|
|
349
438
|
return false;
|
|
350
439
|
}
|
|
351
440
|
return true;
|
|
352
441
|
}
|
|
353
|
-
function storePrefetch(key,
|
|
442
|
+
function storePrefetch(key, entry2, fetchGeneration, inflightKey = key) {
|
|
354
443
|
if (cacheTTL <= 0) return;
|
|
355
444
|
if (fetchGeneration !== generation) return;
|
|
356
|
-
if (adoptedKeys.has(
|
|
357
|
-
forEachAlias(
|
|
445
|
+
if (adoptedKeys.has(inflightKey)) {
|
|
446
|
+
forEachAlias(inflightKey, (k) => adoptedKeys.delete(k));
|
|
358
447
|
return;
|
|
359
448
|
}
|
|
360
449
|
const now = Date.now();
|
|
@@ -377,18 +466,24 @@ function storePrefetch(key, entry, fetchGeneration) {
|
|
|
377
466
|
cache.delete(oldest);
|
|
378
467
|
}
|
|
379
468
|
}
|
|
380
|
-
cache.set(key, { entry, timestamp: now });
|
|
469
|
+
cache.set(key, { entry: entry2, timestamp: now });
|
|
381
470
|
if (now < earliestTimestamp) earliestTimestamp = now;
|
|
382
471
|
}
|
|
383
|
-
function removePrefetch(key,
|
|
384
|
-
if (cache.get(key)?.entry ===
|
|
385
|
-
|
|
472
|
+
function removePrefetch(key, entry2) {
|
|
473
|
+
if (cache.get(key)?.entry === entry2) {
|
|
474
|
+
entry2.dispose?.();
|
|
386
475
|
cache.delete(key);
|
|
387
476
|
}
|
|
388
477
|
}
|
|
389
478
|
function currentGeneration() {
|
|
390
479
|
return generation;
|
|
391
480
|
}
|
|
481
|
+
function currentPrefetchEpoch() {
|
|
482
|
+
return staleEpoch;
|
|
483
|
+
}
|
|
484
|
+
function isPrefetchStale(entry2) {
|
|
485
|
+
return entry2.epoch < staleEpoch;
|
|
486
|
+
}
|
|
392
487
|
function markPrefetchInflight(key) {
|
|
393
488
|
inflight.add(key);
|
|
394
489
|
}
|
|
@@ -409,7 +504,7 @@ function clearPrefetchInflight(key) {
|
|
|
409
504
|
function isFragmentPassthroughEnabled() {
|
|
410
505
|
return fragmentPassthroughEnabled;
|
|
411
506
|
}
|
|
412
|
-
var cacheTTL, fragmentPassthroughEnabled, maxPrefetchCacheSize, cache, inflight, earliestTimestamp, inflightPromises, inflightAliases, adoptedKeys, generation;
|
|
507
|
+
var cacheTTL, fragmentPassthroughEnabled, maxPrefetchCacheSize, cache, inflight, earliestTimestamp, inflightPromises, inflightAliases, adoptedKeys, paramsShapes, generation, staleEpoch, weightOf;
|
|
413
508
|
var init_cache = __esm({
|
|
414
509
|
"src/browser/prefetch/cache.ts"() {
|
|
415
510
|
"use strict";
|
|
@@ -417,6 +512,7 @@ var init_cache = __esm({
|
|
|
417
512
|
init_invalidation();
|
|
418
513
|
init_rango_state();
|
|
419
514
|
init_wire_params();
|
|
515
|
+
init_prefetch_source_scope();
|
|
420
516
|
cacheTTL = 3e5;
|
|
421
517
|
fragmentPassthroughEnabled = true;
|
|
422
518
|
maxPrefetchCacheSize = 100;
|
|
@@ -426,7 +522,10 @@ var init_cache = __esm({
|
|
|
426
522
|
inflightPromises = /* @__PURE__ */ new Map();
|
|
427
523
|
inflightAliases = /* @__PURE__ */ new Map();
|
|
428
524
|
adoptedKeys = /* @__PURE__ */ new Set();
|
|
525
|
+
paramsShapes = /* @__PURE__ */ new Map();
|
|
429
526
|
generation = 0;
|
|
527
|
+
staleEpoch = 0;
|
|
528
|
+
weightOf = (shape) => shape.names.length + (shape.route ? 1 : 0) + (shape.keys ? 1 : 0);
|
|
430
529
|
}
|
|
431
530
|
});
|
|
432
531
|
|
|
@@ -627,11 +726,12 @@ var init_validate_redirect_origin = __esm({
|
|
|
627
726
|
});
|
|
628
727
|
|
|
629
728
|
// src/prefetch-markers.ts
|
|
630
|
-
var PREFETCH_HEADER, PREFETCH_FAILED_ROW;
|
|
729
|
+
var PREFETCH_HEADER, PREFETCH_INTENT, PREFETCH_FAILED_ROW;
|
|
631
730
|
var init_prefetch_markers = __esm({
|
|
632
731
|
"src/prefetch-markers.ts"() {
|
|
633
732
|
"use strict";
|
|
634
733
|
PREFETCH_HEADER = "X-Rango-Prefetch";
|
|
734
|
+
PREFETCH_INTENT = "intent";
|
|
635
735
|
PREFETCH_FAILED_ROW = ":H_0\n";
|
|
636
736
|
}
|
|
637
737
|
});
|
|
@@ -710,12 +810,17 @@ var init_segment_fragments = __esm({
|
|
|
710
810
|
function getRegisteredStore() {
|
|
711
811
|
return registeredStore;
|
|
712
812
|
}
|
|
713
|
-
|
|
813
|
+
function getCommittedPage() {
|
|
814
|
+
return readCommittedPage ? readCommittedPage() : null;
|
|
815
|
+
}
|
|
816
|
+
var registeredStore, readCommittedPage;
|
|
714
817
|
var init_navigation_store_handle = __esm({
|
|
715
818
|
"src/browser/navigation-store-handle.ts"() {
|
|
716
819
|
"use strict";
|
|
820
|
+
init_action_fence();
|
|
717
821
|
init_rango_state();
|
|
718
822
|
registeredStore = null;
|
|
823
|
+
readCommittedPage = null;
|
|
719
824
|
}
|
|
720
825
|
});
|
|
721
826
|
|
|
@@ -746,31 +851,42 @@ var init_wire_protocol = __esm({
|
|
|
746
851
|
function setPrefetchDecoder(fn) {
|
|
747
852
|
decoder = fn;
|
|
748
853
|
}
|
|
749
|
-
function makeRespawn(storageKey, reserve,
|
|
854
|
+
function makeRespawn(storageKey, reserve, slot, epoch) {
|
|
750
855
|
return () => {
|
|
751
856
|
const [body, nextReserve] = reserve.tee();
|
|
752
857
|
const payload = decoder(Promise.resolve(new Response(body)));
|
|
753
858
|
payload.catch(() => {
|
|
754
859
|
});
|
|
755
|
-
const
|
|
860
|
+
const entry2 = {
|
|
756
861
|
payload,
|
|
757
862
|
streamComplete: Promise.resolve(),
|
|
758
|
-
scope,
|
|
863
|
+
scope: slot.scope,
|
|
864
|
+
paramsLabel: slot.paramsLabel,
|
|
865
|
+
epoch,
|
|
759
866
|
complete: true,
|
|
760
867
|
dispose: () => {
|
|
761
868
|
nextReserve.cancel().catch(() => {
|
|
762
869
|
});
|
|
763
870
|
}
|
|
764
871
|
};
|
|
765
|
-
|
|
766
|
-
payload.catch(() => removePrefetch(storageKey,
|
|
767
|
-
return
|
|
872
|
+
entry2.respawn = makeRespawn(storageKey, nextReserve, slot, epoch);
|
|
873
|
+
payload.catch(() => removePrefetch(storageKey, entry2));
|
|
874
|
+
return entry2;
|
|
768
875
|
};
|
|
769
876
|
}
|
|
770
|
-
function
|
|
877
|
+
function committedHref() {
|
|
878
|
+
const committed = getRegisteredStore()?.getSegmentState().currentUrl;
|
|
879
|
+
return committed ? new URL(committed, window.location.origin).href : window.location.href;
|
|
880
|
+
}
|
|
881
|
+
function withoutHash(href2) {
|
|
882
|
+
const hash = href2.indexOf("#");
|
|
883
|
+
return hash === -1 ? href2 : href2.slice(0, hash);
|
|
884
|
+
}
|
|
885
|
+
function isSamePage(url, sourceHref) {
|
|
771
886
|
try {
|
|
772
887
|
const target = new URL(url, window.location.origin);
|
|
773
|
-
|
|
888
|
+
const source = new URL(sourceHref, window.location.origin);
|
|
889
|
+
return target.pathname + target.search === source.pathname + source.search;
|
|
774
890
|
} catch {
|
|
775
891
|
return false;
|
|
776
892
|
}
|
|
@@ -793,8 +909,21 @@ function buildPrefetchUrl(url, segmentIds, version, routerId2) {
|
|
|
793
909
|
rewriteTarget: getRegisteredStore()?.getHistoryEntryMemory()?.rewriteTarget
|
|
794
910
|
});
|
|
795
911
|
}
|
|
796
|
-
function
|
|
912
|
+
function prefetchStorageSlot(forceSourceScope, scopeHeader, sourceKey, wildcardKey, stateKey, targetUrl) {
|
|
913
|
+
if (forceSourceScope || scopeHeader === "source") {
|
|
914
|
+
return { scope: "source", key: sourceKey };
|
|
915
|
+
}
|
|
916
|
+
const label = paramsScopeLabel(scopeHeader);
|
|
917
|
+
if (label === void 0) return { scope: "wildcard", key: wildcardKey };
|
|
918
|
+
return {
|
|
919
|
+
scope: "params",
|
|
920
|
+
key: buildParamsKey(stateKey, label, targetUrl),
|
|
921
|
+
paramsLabel: label
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
function executePrefetchFetch(wildcardKey, sourceKey, sourceHref, targetUrl, forceSourceScope, rangoState, intent, expectedRouterId, signal) {
|
|
797
925
|
const gen = currentGeneration();
|
|
926
|
+
const epoch = currentPrefetchEpoch();
|
|
798
927
|
const inflightKeys = forceSourceScope ? [sourceKey] : [wildcardKey, sourceKey];
|
|
799
928
|
for (const k of inflightKeys) markPrefetchInflight(k);
|
|
800
929
|
let publishedKey;
|
|
@@ -819,7 +948,7 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
819
948
|
once: true
|
|
820
949
|
});
|
|
821
950
|
}
|
|
822
|
-
const promise = fetch(
|
|
951
|
+
const promise = fetch(targetUrl.toString(), {
|
|
823
952
|
priority: "low",
|
|
824
953
|
// During an action's flight the state is not rotated, so the old
|
|
825
954
|
// X-Rango-State still matches the Vary-keyed HTTP-cache entry; bypass it so
|
|
@@ -830,8 +959,8 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
830
959
|
signal: effectiveSignal,
|
|
831
960
|
headers: {
|
|
832
961
|
"X-Rango-State": rangoState,
|
|
833
|
-
"X-RSC-Router-Client-Path":
|
|
834
|
-
[PREFETCH_HEADER]: "1",
|
|
962
|
+
"X-RSC-Router-Client-Path": sourceHref,
|
|
963
|
+
[PREFETCH_HEADER]: intent ? PREFETCH_INTENT : "1",
|
|
835
964
|
...isFragmentPassthroughEnabled() && {
|
|
836
965
|
[SEGMENT_FRAGMENT_CAPABILITY_HEADER]: "1"
|
|
837
966
|
}
|
|
@@ -844,8 +973,15 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
844
973
|
if (isForeignRouterId(response, expectedRouterId)) {
|
|
845
974
|
return null;
|
|
846
975
|
}
|
|
847
|
-
const
|
|
848
|
-
|
|
976
|
+
const slot = prefetchStorageSlot(
|
|
977
|
+
forceSourceScope,
|
|
978
|
+
response.headers.get("x-rsc-prefetch-scope"),
|
|
979
|
+
sourceKey,
|
|
980
|
+
wildcardKey,
|
|
981
|
+
stateEpoch(rangoState),
|
|
982
|
+
targetUrl
|
|
983
|
+
);
|
|
984
|
+
const storageKey = slot.key;
|
|
849
985
|
let resolveStreamComplete;
|
|
850
986
|
let endedCleanly = false;
|
|
851
987
|
const streamComplete = new Promise((resolve16) => {
|
|
@@ -871,10 +1007,12 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
871
1007
|
const payload = decoder(Promise.resolve(decodeSource));
|
|
872
1008
|
payload.catch(() => {
|
|
873
1009
|
});
|
|
874
|
-
const
|
|
1010
|
+
const entry2 = {
|
|
875
1011
|
payload,
|
|
876
1012
|
streamComplete,
|
|
877
|
-
scope,
|
|
1013
|
+
scope: slot.scope,
|
|
1014
|
+
paramsLabel: slot.paramsLabel,
|
|
1015
|
+
epoch,
|
|
878
1016
|
complete: false,
|
|
879
1017
|
stallTimer: timeoutId,
|
|
880
1018
|
...reserve && {
|
|
@@ -884,26 +1022,29 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
884
1022
|
}
|
|
885
1023
|
}
|
|
886
1024
|
};
|
|
887
|
-
storePrefetch(storageKey,
|
|
1025
|
+
storePrefetch(storageKey, entry2, gen, inflightKeys[0]);
|
|
1026
|
+
if (slot.paramsLabel !== void 0) {
|
|
1027
|
+
rememberParamsShape(targetUrl, slot.paramsLabel);
|
|
1028
|
+
}
|
|
888
1029
|
publishedKey = storageKey;
|
|
889
|
-
publishedEntry =
|
|
890
|
-
payload.catch(() => removePrefetch(storageKey,
|
|
1030
|
+
publishedEntry = entry2;
|
|
1031
|
+
payload.catch(() => removePrefetch(storageKey, entry2));
|
|
891
1032
|
streamComplete.then(() => {
|
|
892
|
-
if (!endedCleanly) removePrefetch(storageKey,
|
|
1033
|
+
if (!endedCleanly) removePrefetch(storageKey, entry2);
|
|
893
1034
|
});
|
|
894
1035
|
Promise.allSettled([payload, streamComplete]).then(([decode]) => {
|
|
895
1036
|
clearTimeout(timeoutId);
|
|
896
1037
|
if (decode.status === "fulfilled" && endedCleanly) {
|
|
897
|
-
|
|
1038
|
+
entry2.complete = true;
|
|
898
1039
|
if (reserve) {
|
|
899
|
-
|
|
900
|
-
if (!hasPrefetch(storageKey)) {
|
|
901
|
-
storePrefetch(storageKey,
|
|
1040
|
+
entry2.respawn = makeRespawn(storageKey, reserve, slot, epoch);
|
|
1041
|
+
if (!isPrefetchStale(entry2) && !hasPrefetch(storageKey)) {
|
|
1042
|
+
storePrefetch(storageKey, entry2.respawn(), gen);
|
|
902
1043
|
}
|
|
903
1044
|
}
|
|
904
1045
|
}
|
|
905
1046
|
});
|
|
906
|
-
return
|
|
1047
|
+
return entry2;
|
|
907
1048
|
}).catch(() => null).finally(() => {
|
|
908
1049
|
clearPrefetchInflight(inflightKeys[0]);
|
|
909
1050
|
if (publishedKey === void 0) clearTimeout(timeoutId);
|
|
@@ -911,22 +1052,32 @@ function executePrefetchFetch(wildcardKey, sourceKey, fetchUrl, forceSourceScope
|
|
|
911
1052
|
setInflightPromiseWithAliases(inflightKeys, promise);
|
|
912
1053
|
return promise;
|
|
913
1054
|
}
|
|
914
|
-
function hasPrefetchHit(forceSourceScope, wildcardKey, sourceKey) {
|
|
915
|
-
|
|
1055
|
+
function hasPrefetchHit(forceSourceScope, wildcardKey, sourceKey, stateKey, targetUrl) {
|
|
1056
|
+
if (forceSourceScope) return hasPrefetch(sourceKey);
|
|
1057
|
+
return hasPrefetch(wildcardKey) || hasPrefetch(sourceKey) || paramsCandidateKeys(stateKey, targetUrl, getCommittedPage()).some(
|
|
1058
|
+
hasPrefetch
|
|
1059
|
+
);
|
|
916
1060
|
}
|
|
917
1061
|
function prefetchDirect(url, segmentIds, version, routerId2, prefetchKey) {
|
|
918
1062
|
if (!shouldPrefetch()) return;
|
|
919
1063
|
const targetUrl = buildPrefetchUrl(url, segmentIds, version, routerId2);
|
|
920
1064
|
if (!targetUrl) return;
|
|
921
1065
|
const forceSourceScope = prefetchKey === ":source";
|
|
922
|
-
|
|
1066
|
+
const sourceHref = committedHref();
|
|
1067
|
+
if (!forceSourceScope && isSamePage(url, sourceHref)) {
|
|
923
1068
|
return;
|
|
924
1069
|
}
|
|
925
|
-
const sourceHref = window.location.href;
|
|
926
1070
|
const rangoState = getRangoState();
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
|
|
1071
|
+
const stateKey = stateEpoch(rangoState);
|
|
1072
|
+
const wildcardKey = buildPrefetchKey(stateKey, targetUrl);
|
|
1073
|
+
const sourceKey = buildSourceKey(stateKey, sourceHref, targetUrl);
|
|
1074
|
+
if (hasPrefetchHit(
|
|
1075
|
+
forceSourceScope,
|
|
1076
|
+
wildcardKey,
|
|
1077
|
+
sourceKey,
|
|
1078
|
+
stateKey,
|
|
1079
|
+
targetUrl
|
|
1080
|
+
)) {
|
|
930
1081
|
if (IS_BROWSER_DEBUG) {
|
|
931
1082
|
debugLog("[prefetch] direct dedup (key already exists)", {
|
|
932
1083
|
url,
|
|
@@ -949,9 +1100,11 @@ function prefetchDirect(url, segmentIds, version, routerId2, prefetchKey) {
|
|
|
949
1100
|
executePrefetchFetch(
|
|
950
1101
|
wildcardKey,
|
|
951
1102
|
sourceKey,
|
|
952
|
-
|
|
1103
|
+
sourceHref,
|
|
1104
|
+
targetUrl,
|
|
953
1105
|
forceSourceScope,
|
|
954
1106
|
rangoState,
|
|
1107
|
+
true,
|
|
955
1108
|
routerId2
|
|
956
1109
|
);
|
|
957
1110
|
}
|
|
@@ -960,15 +1113,22 @@ function prefetchQueued(url, segmentIds, version, routerId2, prefetchKey) {
|
|
|
960
1113
|
const targetUrl = buildPrefetchUrl(url, segmentIds, version, routerId2);
|
|
961
1114
|
if (!targetUrl) return "";
|
|
962
1115
|
const forceSourceScope = prefetchKey === ":source";
|
|
963
|
-
|
|
1116
|
+
const sourceHref = committedHref();
|
|
1117
|
+
if (!forceSourceScope && isSamePage(url, sourceHref)) {
|
|
964
1118
|
return "";
|
|
965
1119
|
}
|
|
966
|
-
const sourceHref = window.location.href;
|
|
967
1120
|
const rangoState = getRangoState();
|
|
968
|
-
const
|
|
969
|
-
const
|
|
1121
|
+
const stateKey = stateEpoch(rangoState);
|
|
1122
|
+
const wildcardKey = buildPrefetchKey(stateKey, targetUrl);
|
|
1123
|
+
const sourceKey = buildSourceKey(stateKey, sourceHref, targetUrl);
|
|
970
1124
|
const queueKey = forceSourceScope ? sourceKey : wildcardKey;
|
|
971
|
-
if (hasPrefetchHit(
|
|
1125
|
+
if (hasPrefetchHit(
|
|
1126
|
+
forceSourceScope,
|
|
1127
|
+
wildcardKey,
|
|
1128
|
+
sourceKey,
|
|
1129
|
+
stateKey,
|
|
1130
|
+
targetUrl
|
|
1131
|
+
)) {
|
|
972
1132
|
if (IS_BROWSER_DEBUG) {
|
|
973
1133
|
debugLog("[prefetch] queued dedup (key already exists)", {
|
|
974
1134
|
url,
|
|
@@ -979,20 +1139,30 @@ function prefetchQueued(url, segmentIds, version, routerId2, prefetchKey) {
|
|
|
979
1139
|
}
|
|
980
1140
|
return queueKey;
|
|
981
1141
|
}
|
|
982
|
-
const fetchUrlStr = targetUrl.toString();
|
|
983
1142
|
enqueuePrefetch(queueKey, (signal) => {
|
|
984
|
-
|
|
1143
|
+
const liveState = getRangoState();
|
|
1144
|
+
if (stateEpoch(liveState) !== stateKey) return Promise.resolve();
|
|
1145
|
+
if (hasPrefetchHit(
|
|
1146
|
+
forceSourceScope,
|
|
1147
|
+
wildcardKey,
|
|
1148
|
+
sourceKey,
|
|
1149
|
+
stateKey,
|
|
1150
|
+
targetUrl
|
|
1151
|
+
)) {
|
|
985
1152
|
return Promise.resolve();
|
|
986
1153
|
}
|
|
987
|
-
|
|
1154
|
+
const committed = committedHref();
|
|
1155
|
+
if (withoutHash(committed) !== withoutHash(sourceHref) || !forceSourceScope && isSamePage(url, committed)) {
|
|
988
1156
|
return Promise.resolve();
|
|
989
1157
|
}
|
|
990
1158
|
return executePrefetchFetch(
|
|
991
1159
|
wildcardKey,
|
|
992
1160
|
sourceKey,
|
|
993
|
-
|
|
1161
|
+
sourceHref,
|
|
1162
|
+
targetUrl,
|
|
994
1163
|
forceSourceScope,
|
|
995
|
-
|
|
1164
|
+
liveState,
|
|
1165
|
+
false,
|
|
996
1166
|
routerId2,
|
|
997
1167
|
signal
|
|
998
1168
|
).then(() => {
|
|
@@ -1005,7 +1175,9 @@ var init_fetch = __esm({
|
|
|
1005
1175
|
"src/browser/prefetch/fetch.ts"() {
|
|
1006
1176
|
"use strict";
|
|
1007
1177
|
init_cache();
|
|
1178
|
+
init_prefetch_source_scope();
|
|
1008
1179
|
init_rango_state();
|
|
1180
|
+
init_cookie_name();
|
|
1009
1181
|
init_action_fence();
|
|
1010
1182
|
init_queue();
|
|
1011
1183
|
init_policy();
|
|
@@ -1994,6 +2166,7 @@ var DEFAULT_EXCLUDE_PATTERNS = [
|
|
|
1994
2166
|
"**/dist/**",
|
|
1995
2167
|
"**/coverage/**",
|
|
1996
2168
|
"**/*.test.{ts,tsx,js,jsx}",
|
|
2169
|
+
"**/*.rsc-test.{ts,tsx,js,jsx}",
|
|
1997
2170
|
"**/*.spec.{ts,tsx,js,jsx}"
|
|
1998
2171
|
];
|
|
1999
2172
|
function createScanFilter(root, opts) {
|
|
@@ -2035,12 +2208,12 @@ function findTsFiles(dir, filter) {
|
|
|
2035
2208
|
);
|
|
2036
2209
|
return results;
|
|
2037
2210
|
}
|
|
2038
|
-
for (const
|
|
2039
|
-
const fullPath = join(dir,
|
|
2040
|
-
if (
|
|
2041
|
-
if (isSkippedSourceScanDir(
|
|
2211
|
+
for (const entry2 of entries) {
|
|
2212
|
+
const fullPath = join(dir, entry2.name);
|
|
2213
|
+
if (entry2.isDirectory()) {
|
|
2214
|
+
if (isSkippedSourceScanDir(entry2.name)) continue;
|
|
2042
2215
|
results.push(...findTsFiles(fullPath, filter));
|
|
2043
|
-
} else if ((
|
|
2216
|
+
} else if ((entry2.name.endsWith(".ts") || entry2.name.endsWith(".tsx") || entry2.name.endsWith(".js") || entry2.name.endsWith(".jsx")) && !entry2.name.includes(".gen.")) {
|
|
2044
2217
|
if (filter && !filter(fullPath)) continue;
|
|
2045
2218
|
results.push(fullPath);
|
|
2046
2219
|
}
|
|
@@ -2883,20 +3056,20 @@ ${lazyImports.join(",\n")}
|
|
|
2883
3056
|
return "\0" + id;
|
|
2884
3057
|
}
|
|
2885
3058
|
if (importer?.startsWith("\0" + VIRTUAL_HANDLER_PREFIX)) {
|
|
2886
|
-
const
|
|
2887
|
-
if (
|
|
2888
|
-
return this.resolve(id,
|
|
3059
|
+
const entry2 = virtualHandlers.get(importer);
|
|
3060
|
+
if (entry2) {
|
|
3061
|
+
return this.resolve(id, entry2.originalModuleId, { skipSelf: true });
|
|
2889
3062
|
}
|
|
2890
3063
|
}
|
|
2891
3064
|
},
|
|
2892
3065
|
load(id) {
|
|
2893
3066
|
if (id.startsWith("\0" + VIRTUAL_HANDLER_PREFIX)) {
|
|
2894
|
-
const
|
|
2895
|
-
if (!
|
|
3067
|
+
const entry2 = virtualHandlers.get(id);
|
|
3068
|
+
if (!entry2) return null;
|
|
2896
3069
|
return [
|
|
2897
|
-
...
|
|
2898
|
-
...
|
|
2899
|
-
`export const ${
|
|
3070
|
+
...entry2.imports,
|
|
3071
|
+
...entry2.declarations,
|
|
3072
|
+
`export const ${entry2.exportName} = ${entry2.handlerCode};`
|
|
2900
3073
|
].join("\n") + "\n";
|
|
2901
3074
|
}
|
|
2902
3075
|
if (id !== RESOLVED_VIRTUAL_LOADER_MANIFEST) return;
|
|
@@ -2911,13 +3084,13 @@ ${lazyImports.join(",\n")}
|
|
|
2911
3084
|
const results = [];
|
|
2912
3085
|
try {
|
|
2913
3086
|
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
2914
|
-
for (const
|
|
2915
|
-
const fullPath = path4.join(dir,
|
|
2916
|
-
if (
|
|
2917
|
-
if (!isSkippedSourceScanDir(
|
|
3087
|
+
for (const entry2 of entries) {
|
|
3088
|
+
const fullPath = path4.join(dir, entry2.name);
|
|
3089
|
+
if (entry2.isDirectory()) {
|
|
3090
|
+
if (!isSkippedSourceScanDir(entry2.name)) {
|
|
2918
3091
|
results.push(...await scanDir(fullPath));
|
|
2919
3092
|
}
|
|
2920
|
-
} else if (/\.(ts|tsx|js|jsx)$/.test(
|
|
3093
|
+
} else if (/\.(ts|tsx|js|jsx)$/.test(entry2.name)) {
|
|
2921
3094
|
results.push(fullPath);
|
|
2922
3095
|
}
|
|
2923
3096
|
}
|
|
@@ -4181,8 +4354,8 @@ async function recordEmitted(emitted, file, value) {
|
|
|
4181
4354
|
emitted.set(file, { disk: await readSource(file), value });
|
|
4182
4355
|
}
|
|
4183
4356
|
async function loadEmittedOrDisk(emitted, hoistedFile, disk, rehoist) {
|
|
4184
|
-
const
|
|
4185
|
-
if (
|
|
4357
|
+
const entry2 = emitted.get(normalizePath2(hoistedFile));
|
|
4358
|
+
if (entry2 && (disk === null || entry2.disk === disk)) return entry2.value;
|
|
4186
4359
|
return disk === null ? void 0 : rehoist(disk);
|
|
4187
4360
|
}
|
|
4188
4361
|
|
|
@@ -4476,6 +4649,7 @@ function getLoaderBodyTags() {
|
|
|
4476
4649
|
function getCurrentLoaderBodyId() {
|
|
4477
4650
|
return loaderBodyScopeALS.getStore()?.loaderId;
|
|
4478
4651
|
}
|
|
4652
|
+
var segmentPinALS = globalThis[/* @__PURE__ */ Symbol.for("rangojs-router:segment-pin")] ??= new AsyncLocalStorage2();
|
|
4479
4653
|
var PUSH_CALLBACK_SCOPE_KEY = /* @__PURE__ */ Symbol.for(
|
|
4480
4654
|
"rangojs-router:push-callback-scope"
|
|
4481
4655
|
);
|
|
@@ -5315,6 +5489,7 @@ init_logging();
|
|
|
5315
5489
|
|
|
5316
5490
|
// src/browser/navigation-store.ts
|
|
5317
5491
|
init_cache();
|
|
5492
|
+
init_action_fence();
|
|
5318
5493
|
init_rango_state();
|
|
5319
5494
|
|
|
5320
5495
|
// src/browser/react/NavigationProvider.tsx
|
|
@@ -5373,12 +5548,12 @@ function getObserver() {
|
|
|
5373
5548
|
observer = new IntersectionObserver(
|
|
5374
5549
|
(entries, currentObserver) => {
|
|
5375
5550
|
function* intersectingCallbacks() {
|
|
5376
|
-
for (const
|
|
5377
|
-
if (
|
|
5378
|
-
const subscriptions = callbacks.get(
|
|
5551
|
+
for (const entry2 of entries) {
|
|
5552
|
+
if (entry2.isIntersecting) {
|
|
5553
|
+
const subscriptions = callbacks.get(entry2.target);
|
|
5379
5554
|
if (subscriptions) {
|
|
5380
|
-
currentObserver.unobserve(
|
|
5381
|
-
callbacks.delete(
|
|
5555
|
+
currentObserver.unobserve(entry2.target);
|
|
5556
|
+
callbacks.delete(entry2.target);
|
|
5382
5557
|
for (const [subscription, callback] of subscriptions) {
|
|
5383
5558
|
yield [subscriptions, subscription, callback];
|
|
5384
5559
|
}
|
|
@@ -5937,6 +6112,12 @@ var DERIVED_RENDER_BARRIER_DESCRIPTOR = {
|
|
|
5937
6112
|
};
|
|
5938
6113
|
var backgroundWork = new AsyncLocalStorage6();
|
|
5939
6114
|
|
|
6115
|
+
// src/router/revalidation.ts
|
|
6116
|
+
init_prefetch_source_scope();
|
|
6117
|
+
|
|
6118
|
+
// src/router/source-reads.ts
|
|
6119
|
+
init_prefetch_source_scope();
|
|
6120
|
+
|
|
5940
6121
|
// src/route-definition/redirect.ts
|
|
5941
6122
|
init_redirect_origin();
|
|
5942
6123
|
|
|
@@ -6119,9 +6300,9 @@ function serializeRoute(route2, options, ordinals) {
|
|
|
6119
6300
|
}
|
|
6120
6301
|
function serializeLoaderOptions(loaders, owner, options) {
|
|
6121
6302
|
const loaderRevalidate = loaders.map(
|
|
6122
|
-
({ loader: loader3, revalidate: revalidate3 }) => revalidate3.flatMap((
|
|
6123
|
-
if (isHoistedRevalidateRef(
|
|
6124
|
-
if (typeof
|
|
6303
|
+
({ loader: loader3, revalidate: revalidate3 }) => revalidate3.flatMap((entry2) => {
|
|
6304
|
+
if (isHoistedRevalidateRef(entry2)) return [entry2.$$rangoRevalidate];
|
|
6305
|
+
if (typeof entry2 === "boolean") return [entry2];
|
|
6125
6306
|
if (options.hoisted) {
|
|
6126
6307
|
throw new Error(
|
|
6127
6308
|
`clientUrls() revalidate() on loader "${loader3.$$id}" of ${owner} was not hoisted to the server: call revalidate() (the builder's helper, or the one "@rangojs/router/client" exports for a component's .use) with an inline function, an imported predicate or a boolean.`
|
|
@@ -6562,25 +6743,25 @@ function fingerprint(node) {
|
|
|
6562
6743
|
out.push(JSON.stringify(typeof value === "bigint" ? `${value}n` : value));
|
|
6563
6744
|
return;
|
|
6564
6745
|
}
|
|
6565
|
-
let
|
|
6566
|
-
if (typeof
|
|
6567
|
-
|
|
6568
|
-
if (
|
|
6569
|
-
visit(
|
|
6746
|
+
let entry2 = value;
|
|
6747
|
+
if (typeof entry2.type === "string") {
|
|
6748
|
+
entry2 = unwrapExpression(entry2);
|
|
6749
|
+
if (entry2.type.startsWith("TS")) {
|
|
6750
|
+
visit(entry2.expression);
|
|
6570
6751
|
return;
|
|
6571
6752
|
}
|
|
6572
|
-
out.push(
|
|
6573
|
-
if (
|
|
6574
|
-
out.push(JSON.stringify(
|
|
6753
|
+
out.push(entry2.type, "(");
|
|
6754
|
+
if (entry2.type === "TemplateElement") {
|
|
6755
|
+
out.push(JSON.stringify(entry2.value.raw));
|
|
6575
6756
|
}
|
|
6576
6757
|
}
|
|
6577
|
-
for (const key of Object.keys(
|
|
6758
|
+
for (const key of Object.keys(entry2)) {
|
|
6578
6759
|
if (FINGERPRINT_SKIP.has(key)) continue;
|
|
6579
|
-
if (key === "optional" &&
|
|
6760
|
+
if (key === "optional" && entry2.type === "Identifier") continue;
|
|
6580
6761
|
out.push(key);
|
|
6581
|
-
visit(
|
|
6762
|
+
visit(entry2[key]);
|
|
6582
6763
|
}
|
|
6583
|
-
if (typeof
|
|
6764
|
+
if (typeof entry2.type === "string") out.push(")");
|
|
6584
6765
|
};
|
|
6585
6766
|
visit(node);
|
|
6586
6767
|
return out.join(" ");
|
|
@@ -7146,7 +7327,7 @@ function resolveVersionsFrom(table, routerId2) {
|
|
|
7146
7327
|
// package.json
|
|
7147
7328
|
var package_default = {
|
|
7148
7329
|
name: "@rangojs/router",
|
|
7149
|
-
version: "0.
|
|
7330
|
+
version: "0.33.0",
|
|
7150
7331
|
description: "Django-inspired RSC router with composable URL patterns",
|
|
7151
7332
|
keywords: [
|
|
7152
7333
|
"react",
|
|
@@ -7339,7 +7520,7 @@ var package_default = {
|
|
|
7339
7520
|
tag: "latest"
|
|
7340
7521
|
},
|
|
7341
7522
|
scripts: {
|
|
7342
|
-
build: "pnpm run build:types && pnpm exec esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm exec esbuild src/testing/vitest.ts --bundle --format=esm --outfile=dist/testing/vitest.js --platform=node --packages=external && pnpm exec esbuild src/bin/rango.ts --bundle --format=esm --
|
|
7523
|
+
build: "pnpm run build:types && pnpm exec esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external && mkdir -p dist/vite/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/vite/plugins/cloudflare-protocol-loader-hook.mjs && pnpm exec esbuild src/testing/vitest.ts --bundle --format=esm --outfile=dist/testing/vitest.js --platform=node --packages=external && rm -rf dist/bin && pnpm exec esbuild src/bin/rango.ts --bundle --format=esm --splitting --outdir=dist/bin --platform=node --packages=external && chmod +x dist/bin/rango.js && mkdir -p dist/bin/plugins && cp src/vite/plugins/cloudflare-protocol-loader-hook.mjs dist/bin/plugins/cloudflare-protocol-loader-hook.mjs",
|
|
7343
7524
|
"build:types": "rm -rf dist/types && pnpm exec tsc -p tsconfig.types.json",
|
|
7344
7525
|
prepublishOnly: "pnpm build",
|
|
7345
7526
|
typecheck: "tsc --noEmit && tsc -p tsconfig.strict-check.json --noEmit && tsc -p tsconfig.augment-check.json --noEmit",
|
|
@@ -8243,10 +8424,10 @@ function serverCssRecords(server, projectRoot, serverResources) {
|
|
|
8243
8424
|
const key = portableModuleId(id, projectRoot).match(SERVER_CSS_MODULE)?.[1];
|
|
8244
8425
|
if (key !== void 0) moduleOf.set(key, id);
|
|
8245
8426
|
}
|
|
8246
|
-
return [...serverResources].map(([key,
|
|
8427
|
+
return [...serverResources].map(([key, entry2]) => ({
|
|
8247
8428
|
kind: "server-css",
|
|
8248
8429
|
key,
|
|
8249
|
-
digest: sha256(
|
|
8430
|
+
digest: sha256(entry2),
|
|
8250
8431
|
moduleId: moduleOf.get(key)
|
|
8251
8432
|
}));
|
|
8252
8433
|
}
|
|
@@ -8485,8 +8666,8 @@ function isWorkspaceDevelopment() {
|
|
|
8485
8666
|
return !isInstalledFromNpm();
|
|
8486
8667
|
}
|
|
8487
8668
|
var SOURCE_EXPORT_SUBPATHS = Object.keys(package_default.exports).filter((key) => {
|
|
8488
|
-
const
|
|
8489
|
-
return Object.entries(
|
|
8669
|
+
const entry2 = package_default.exports[key];
|
|
8670
|
+
return Object.entries(entry2).some(
|
|
8490
8671
|
([condition, path6]) => condition !== "types" && typeof path6 === "string" && /\.tsx?$/.test(path6)
|
|
8491
8672
|
);
|
|
8492
8673
|
}).map((key) => key.replace(/^\./, ""));
|
|
@@ -8690,9 +8871,26 @@ function readSourceMemoized(memo, realPath) {
|
|
|
8690
8871
|
if (memo) memo.files.set(realPath, source);
|
|
8691
8872
|
return source;
|
|
8692
8873
|
}
|
|
8693
|
-
function isUrlsDefinitionCall(node) {
|
|
8874
|
+
function isUrlsDefinitionCall(node, aliases) {
|
|
8694
8875
|
const callee = node.expression;
|
|
8695
|
-
return ts3.isIdentifier(callee) && (callee.text === "urls" || callee.text === "clientUrls");
|
|
8876
|
+
return ts3.isIdentifier(callee) && (callee.text === "urls" || callee.text === "clientUrls" || aliases?.has(callee.text) === true);
|
|
8877
|
+
}
|
|
8878
|
+
function collectUrlsImportAliases(sourceFile) {
|
|
8879
|
+
const aliases = /* @__PURE__ */ new Set();
|
|
8880
|
+
for (const stmt of sourceFile.statements) {
|
|
8881
|
+
if (!ts3.isImportDeclaration(stmt) || !ts3.isStringLiteral(stmt.moduleSpecifier) || stmt.moduleSpecifier.text !== "@rangojs/router" && stmt.moduleSpecifier.text !== "@rangojs/router/client") {
|
|
8882
|
+
continue;
|
|
8883
|
+
}
|
|
8884
|
+
const bindings = stmt.importClause?.namedBindings;
|
|
8885
|
+
if (!bindings || !ts3.isNamedImports(bindings)) continue;
|
|
8886
|
+
for (const el of bindings.elements) {
|
|
8887
|
+
const imported = (el.propertyName ?? el.name).text;
|
|
8888
|
+
if (imported === "urls" || imported === "clientUrls") {
|
|
8889
|
+
aliases.add(el.name.text);
|
|
8890
|
+
}
|
|
8891
|
+
}
|
|
8892
|
+
}
|
|
8893
|
+
return aliases;
|
|
8696
8894
|
}
|
|
8697
8895
|
function extractNamePrefixFromInclude(node) {
|
|
8698
8896
|
if (node.arguments.length >= 3) {
|
|
@@ -8939,8 +9137,8 @@ function buildRouteMapFromBlock(block, fullSource, filePath, visited, searchSche
|
|
|
8939
9137
|
blockSourceFile
|
|
8940
9138
|
);
|
|
8941
9139
|
if (diagnosticsOut) {
|
|
8942
|
-
for (const
|
|
8943
|
-
diagnosticsOut.push({ ...
|
|
9140
|
+
for (const entry2 of unresolvable) {
|
|
9141
|
+
diagnosticsOut.push({ ...entry2, sourceFile: filePath });
|
|
8944
9142
|
}
|
|
8945
9143
|
}
|
|
8946
9144
|
for (const inc of includes) {
|
|
@@ -9227,7 +9425,7 @@ function countPublicRouteEntries(source) {
|
|
|
9227
9425
|
var ROUTER_CALL_PATTERN = /\bcreateRouter\s*[<(]/;
|
|
9228
9426
|
var ROUTER_CALL_PATTERN_G = /\bcreateRouter\s*[<(]/g;
|
|
9229
9427
|
function isRoutableSourceFile(name) {
|
|
9230
|
-
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".spec.");
|
|
9428
|
+
return (name.endsWith(".ts") || name.endsWith(".tsx") || name.endsWith(".js") || name.endsWith(".jsx")) && !name.includes(".gen.") && !name.includes(".test.") && !name.includes(".rsc-test.") && !name.includes(".spec.");
|
|
9231
9429
|
}
|
|
9232
9430
|
function isExcludedScanDir(name) {
|
|
9233
9431
|
return isUniversallySkippedScanDir(name) || name === "__tests__" || name === "__mocks__";
|
|
@@ -9244,13 +9442,13 @@ function findCallSiteFilesRecursive(dir, pattern, patternG, stopAtMatchDir, filt
|
|
|
9244
9442
|
}
|
|
9245
9443
|
const childDirs = [];
|
|
9246
9444
|
const matchesInDir = [];
|
|
9247
|
-
for (const
|
|
9248
|
-
const fullPath = join3(dir,
|
|
9249
|
-
if (
|
|
9250
|
-
if (!isExcludedScanDir(
|
|
9445
|
+
for (const entry2 of entries) {
|
|
9446
|
+
const fullPath = join3(dir, entry2.name);
|
|
9447
|
+
if (entry2.isDirectory()) {
|
|
9448
|
+
if (!isExcludedScanDir(entry2.name)) childDirs.push(fullPath);
|
|
9251
9449
|
continue;
|
|
9252
9450
|
}
|
|
9253
|
-
if (!isRoutableSourceFile(
|
|
9451
|
+
if (!isRoutableSourceFile(entry2.name)) continue;
|
|
9254
9452
|
if (filter && !filter(fullPath)) continue;
|
|
9255
9453
|
try {
|
|
9256
9454
|
const source = readFileSync4(fullPath, "utf-8");
|
|
@@ -9309,11 +9507,12 @@ function isCreateRouterCall(node) {
|
|
|
9309
9507
|
const callee = node.expression;
|
|
9310
9508
|
return ts5.isIdentifier(callee) && callee.text === "createRouter";
|
|
9311
9509
|
}
|
|
9312
|
-
function extractUrlsArgument(
|
|
9510
|
+
function extractUrlsArgument(arg, sourceFile, urlsAliases) {
|
|
9511
|
+
const node = unwrapTypeOperators(arg);
|
|
9313
9512
|
if (ts5.isIdentifier(node)) {
|
|
9314
9513
|
return { kind: "variable", name: node.text };
|
|
9315
9514
|
}
|
|
9316
|
-
if (ts5.isArrowFunction(node) || ts5.isFunctionExpression(node)) {
|
|
9515
|
+
if (ts5.isArrowFunction(node) || ts5.isFunctionExpression(node) || ts5.isCallExpression(node) && isUrlsDefinitionCall(node, urlsAliases)) {
|
|
9317
9516
|
return { kind: "inline", block: node.getText(sourceFile) };
|
|
9318
9517
|
}
|
|
9319
9518
|
return null;
|
|
@@ -9330,23 +9529,77 @@ function collectCreateRouterCallChain(endpoint) {
|
|
|
9330
9529
|
current = receiver;
|
|
9331
9530
|
}
|
|
9332
9531
|
}
|
|
9532
|
+
function collectExportedLocalNames(sourceFile) {
|
|
9533
|
+
const names = /* @__PURE__ */ new Set();
|
|
9534
|
+
const addIdentifier = (expr) => {
|
|
9535
|
+
const node = expr && unwrapTypeOperators(expr);
|
|
9536
|
+
if (node && ts5.isIdentifier(node)) names.add(node.text);
|
|
9537
|
+
};
|
|
9538
|
+
for (const statement of sourceFile.statements) {
|
|
9539
|
+
if (ts5.isExportAssignment(statement)) {
|
|
9540
|
+
addIdentifier(statement.expression);
|
|
9541
|
+
} else if (ts5.isExportDeclaration(statement) && !statement.moduleSpecifier && !statement.isTypeOnly && statement.exportClause && ts5.isNamedExports(statement.exportClause)) {
|
|
9542
|
+
for (const element of statement.exportClause.elements) {
|
|
9543
|
+
if (!element.isTypeOnly) {
|
|
9544
|
+
names.add((element.propertyName ?? element.name).text);
|
|
9545
|
+
}
|
|
9546
|
+
}
|
|
9547
|
+
} else if (ts5.isVariableStatement(statement) && hasModifier(statement, ts5.SyntaxKind.ExportKeyword)) {
|
|
9548
|
+
for (const decl of statement.declarationList.declarations) {
|
|
9549
|
+
addIdentifier(decl.initializer);
|
|
9550
|
+
}
|
|
9551
|
+
}
|
|
9552
|
+
}
|
|
9553
|
+
return names;
|
|
9554
|
+
}
|
|
9555
|
+
function isExportedChain(chainEnd, exportedNames) {
|
|
9556
|
+
let current = chainEnd;
|
|
9557
|
+
while (current.parent && (ts5.isAsExpression(current.parent) || ts5.isSatisfiesExpression(current.parent) || ts5.isParenthesizedExpression(current.parent))) {
|
|
9558
|
+
current = current.parent;
|
|
9559
|
+
}
|
|
9560
|
+
const parent = current.parent;
|
|
9561
|
+
if (!parent) return false;
|
|
9562
|
+
if (ts5.isExportAssignment(parent))
|
|
9563
|
+
return parent.parent === current.getSourceFile();
|
|
9564
|
+
if (!ts5.isVariableDeclaration(parent) || parent.initializer !== current || !ts5.isIdentifier(parent.name)) {
|
|
9565
|
+
return false;
|
|
9566
|
+
}
|
|
9567
|
+
const statement = parent.parent.parent;
|
|
9568
|
+
if (!ts5.isVariableStatement(statement) || !ts5.isSourceFile(statement.parent)) {
|
|
9569
|
+
return false;
|
|
9570
|
+
}
|
|
9571
|
+
return hasModifier(statement, ts5.SyntaxKind.ExportKeyword) || exportedNames.has(parent.name.text);
|
|
9572
|
+
}
|
|
9333
9573
|
function findRouterUrls(sourceFile) {
|
|
9334
|
-
|
|
9574
|
+
const exported = [];
|
|
9575
|
+
const local = [];
|
|
9576
|
+
let anyExported = false;
|
|
9577
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9578
|
+
const urlsAliases = collectUrlsImportAliases(sourceFile);
|
|
9579
|
+
const exportedNames = collectExportedLocalNames(sourceFile);
|
|
9335
9580
|
function visit(node) {
|
|
9336
|
-
if (result) return;
|
|
9337
9581
|
if (ts5.isCallExpression(node)) {
|
|
9338
9582
|
const chain = collectCreateRouterCallChain(node);
|
|
9339
|
-
if (chain) {
|
|
9583
|
+
if (chain && !seen.has(chain[0])) {
|
|
9340
9584
|
const extracted = [];
|
|
9585
|
+
const unreadable = [];
|
|
9341
9586
|
const createRouterCall = chain[0];
|
|
9587
|
+
seen.add(createRouterCall);
|
|
9588
|
+
const addMount = (arg, mount) => {
|
|
9589
|
+
const urls2 = extractUrlsArgument(arg, sourceFile, urlsAliases);
|
|
9590
|
+
if (urls2) extracted.push(urls2);
|
|
9591
|
+
else
|
|
9592
|
+
unreadable.push(
|
|
9593
|
+
mount(arg.getText(sourceFile).replace(/\s+/g, " "))
|
|
9594
|
+
);
|
|
9595
|
+
};
|
|
9342
9596
|
for (const callArg of createRouterCall.arguments) {
|
|
9343
9597
|
if (!ts5.isObjectLiteralExpression(callArg)) continue;
|
|
9344
9598
|
for (const prop of callArg.properties) {
|
|
9345
9599
|
if (!ts5.isPropertyAssignment(prop) || !ts5.isIdentifier(prop.name) || prop.name.text !== "urls") {
|
|
9346
9600
|
continue;
|
|
9347
9601
|
}
|
|
9348
|
-
|
|
9349
|
-
if (urls2) extracted.push(urls2);
|
|
9602
|
+
addMount(prop.initializer, (text) => `urls: ${text}`);
|
|
9350
9603
|
break;
|
|
9351
9604
|
}
|
|
9352
9605
|
}
|
|
@@ -9354,36 +9607,43 @@ function findRouterUrls(sourceFile) {
|
|
|
9354
9607
|
if (!ts5.isPropertyAccessExpression(call.expression) || call.expression.name.text !== "routes" || call.arguments.length === 0) {
|
|
9355
9608
|
continue;
|
|
9356
9609
|
}
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
if (
|
|
9361
|
-
|
|
9362
|
-
|
|
9610
|
+
addMount(call.arguments[0], (text) => `.routes(${text})`);
|
|
9611
|
+
}
|
|
9612
|
+
const isExported = isExportedChain(node, exportedNames);
|
|
9613
|
+
if (isExported) anyExported = true;
|
|
9614
|
+
if (extracted.length > 0 || unreadable.length > 0) {
|
|
9615
|
+
(isExported ? exported : local).push({
|
|
9616
|
+
createRouterCall,
|
|
9617
|
+
extractions: extracted,
|
|
9618
|
+
unreadable
|
|
9619
|
+
});
|
|
9363
9620
|
}
|
|
9364
9621
|
}
|
|
9365
9622
|
}
|
|
9366
9623
|
ts5.forEachChild(node, visit);
|
|
9367
9624
|
}
|
|
9368
9625
|
visit(sourceFile);
|
|
9369
|
-
|
|
9626
|
+
const candidates = anyExported ? exported : local;
|
|
9627
|
+
return candidates.find((c) => c.extractions.length > 0) ?? candidates[0] ?? null;
|
|
9370
9628
|
}
|
|
9371
|
-
function
|
|
9372
|
-
|
|
9629
|
+
function parseRouterSource(code) {
|
|
9630
|
+
return ts5.createSourceFile(
|
|
9373
9631
|
"router.tsx",
|
|
9374
9632
|
code,
|
|
9375
9633
|
ts5.ScriptTarget.Latest,
|
|
9376
9634
|
true,
|
|
9377
9635
|
ts5.ScriptKind.TSX
|
|
9378
9636
|
);
|
|
9379
|
-
|
|
9637
|
+
}
|
|
9638
|
+
function extractAllUrlsFromRouter(code) {
|
|
9639
|
+
return findRouterUrls(parseRouterSource(code))?.extractions ?? [];
|
|
9380
9640
|
}
|
|
9381
9641
|
function extractUrlsFromRouter(code) {
|
|
9382
9642
|
const extractions = extractAllUrlsFromRouter(code);
|
|
9383
9643
|
return extractions[extractions.length - 1] ?? null;
|
|
9384
9644
|
}
|
|
9385
9645
|
function unwrapTypeOperators(expr) {
|
|
9386
|
-
while (ts5.isAsExpression(expr) || ts5.isSatisfiesExpression(expr)) {
|
|
9646
|
+
while (ts5.isAsExpression(expr) || ts5.isSatisfiesExpression(expr) || ts5.isParenthesizedExpression(expr)) {
|
|
9387
9647
|
expr = expr.expression;
|
|
9388
9648
|
}
|
|
9389
9649
|
return expr;
|
|
@@ -10701,10 +10961,10 @@ function generateRoutesManifestModule(state) {
|
|
|
10701
10961
|
const genFileImports = [];
|
|
10702
10962
|
const genFileVarByEntry = [];
|
|
10703
10963
|
let varIdx = 0;
|
|
10704
|
-
for (const
|
|
10705
|
-
if (
|
|
10706
|
-
const routerDir = dirname4(
|
|
10707
|
-
const routerBasename = basename(
|
|
10964
|
+
for (const entry2 of state.perRouterManifests) {
|
|
10965
|
+
if (entry2.sourceFile) {
|
|
10966
|
+
const routerDir = dirname4(entry2.sourceFile);
|
|
10967
|
+
const routerBasename = basename(entry2.sourceFile).replace(
|
|
10708
10968
|
/\.(tsx?|jsx?)$/,
|
|
10709
10969
|
""
|
|
10710
10970
|
);
|
|
@@ -10747,10 +11007,10 @@ function generateRoutesManifestModule(state) {
|
|
|
10747
11007
|
);
|
|
10748
11008
|
}
|
|
10749
11009
|
const routerMapVars = [];
|
|
10750
|
-
for (const [i,
|
|
11010
|
+
for (const [i, entry2] of state.perRouterManifests.entries()) {
|
|
10751
11011
|
const mapVar = `__m${i}`;
|
|
10752
11012
|
const genVar = genFileVarByEntry[i];
|
|
10753
|
-
const init = genVar ? `__flat(${genVar})` : jsonParseExpression(
|
|
11013
|
+
const init = genVar ? `__flat(${genVar})` : jsonParseExpression(entry2.routeManifest);
|
|
10754
11014
|
lines2.push(`const ${mapVar} = ${init};`);
|
|
10755
11015
|
routerMapVars.push(mapVar);
|
|
10756
11016
|
}
|
|
@@ -10761,9 +11021,9 @@ function generateRoutesManifestModule(state) {
|
|
|
10761
11021
|
`setCachedManifest({ ${routerMapVars.map((v) => `...${v}`).join(", ")} });`
|
|
10762
11022
|
);
|
|
10763
11023
|
}
|
|
10764
|
-
for (const [i,
|
|
11024
|
+
for (const [i, entry2] of state.perRouterManifests.entries()) {
|
|
10765
11025
|
lines2.push(
|
|
10766
|
-
`setRouterManifest(${JSON.stringify(
|
|
11026
|
+
`setRouterManifest(${JSON.stringify(entry2.id)}, ${routerMapVars[i]});`
|
|
10767
11027
|
);
|
|
10768
11028
|
}
|
|
10769
11029
|
if (state.isBuildMode) {
|
|
@@ -11041,14 +11301,14 @@ async function runWithConcurrency(items, concurrency2, fn) {
|
|
|
11041
11301
|
}
|
|
11042
11302
|
function groupByConcurrency(entries) {
|
|
11043
11303
|
const map2 = /* @__PURE__ */ new Map();
|
|
11044
|
-
for (const
|
|
11045
|
-
const key =
|
|
11304
|
+
for (const entry2 of entries) {
|
|
11305
|
+
const key = entry2.concurrency;
|
|
11046
11306
|
let group = map2.get(key);
|
|
11047
11307
|
if (!group) {
|
|
11048
11308
|
group = [];
|
|
11049
11309
|
map2.set(key, group);
|
|
11050
11310
|
}
|
|
11051
|
-
group.push(
|
|
11311
|
+
group.push(entry2);
|
|
11052
11312
|
}
|
|
11053
11313
|
return Array.from(map2.entries(), ([concurrency2, items]) => ({
|
|
11054
11314
|
concurrency: concurrency2,
|
|
@@ -11726,23 +11986,23 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
11726
11986
|
await runWithConcurrency(
|
|
11727
11987
|
group.entries,
|
|
11728
11988
|
group.concurrency,
|
|
11729
|
-
async (
|
|
11989
|
+
async (entry2) => {
|
|
11730
11990
|
const startUrl = performance.now();
|
|
11731
11991
|
for (const [routerId2, routerInstance] of registry) {
|
|
11732
11992
|
if (!routerInstance.matchForPrerender) continue;
|
|
11733
11993
|
try {
|
|
11734
11994
|
const result = await routerInstance.matchForPrerender(
|
|
11735
|
-
|
|
11995
|
+
entry2.urlPath,
|
|
11736
11996
|
{},
|
|
11737
|
-
|
|
11738
|
-
|
|
11997
|
+
entry2.buildVars,
|
|
11998
|
+
entry2.isPassthroughRoute,
|
|
11739
11999
|
state.resolvedBuildEnv
|
|
11740
12000
|
);
|
|
11741
12001
|
if (!result) continue;
|
|
11742
12002
|
if (result.passthrough) {
|
|
11743
12003
|
const elapsed2 = (performance.now() - startUrl).toFixed(0);
|
|
11744
12004
|
console.log(
|
|
11745
|
-
`[rango] PASS ${
|
|
12005
|
+
`[rango] PASS ${entry2.urlPath.padEnd(40)} (${elapsed2}ms) - live fallback`
|
|
11746
12006
|
);
|
|
11747
12007
|
doneCount++;
|
|
11748
12008
|
break;
|
|
@@ -11763,7 +12023,7 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
11763
12023
|
stage(main);
|
|
11764
12024
|
if (result.ppr !== void 0 && result.ppr !== false) {
|
|
11765
12025
|
(state.shellCandidates ??= []).push({
|
|
11766
|
-
urlPath:
|
|
12026
|
+
urlPath: entry2.urlPath,
|
|
11767
12027
|
routeName: result.routeName,
|
|
11768
12028
|
paramHash,
|
|
11769
12029
|
ppr: result.ppr === true ? true : result.ppr
|
|
@@ -11773,13 +12033,13 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
11773
12033
|
if (intercept2) stage(intercept2);
|
|
11774
12034
|
const elapsed = (performance.now() - startUrl).toFixed(0);
|
|
11775
12035
|
console.log(
|
|
11776
|
-
`[rango] OK ${
|
|
12036
|
+
`[rango] OK ${entry2.urlPath.padEnd(40)} (${elapsed}ms)`
|
|
11777
12037
|
);
|
|
11778
12038
|
warnLiveIntercepts(
|
|
11779
12039
|
warnedLiveIntercepts,
|
|
11780
12040
|
routerId2,
|
|
11781
12041
|
result.routeName,
|
|
11782
|
-
|
|
12042
|
+
entry2.urlPath,
|
|
11783
12043
|
result.liveIntercepts
|
|
11784
12044
|
);
|
|
11785
12045
|
doneCount++;
|
|
@@ -11790,11 +12050,11 @@ async function expandPrerenderRoutes(state, rscEnv, registry, allManifests) {
|
|
|
11790
12050
|
registry,
|
|
11791
12051
|
err,
|
|
11792
12052
|
prerenderOnError,
|
|
11793
|
-
|
|
12053
|
+
entry2.urlPath.padEnd(40),
|
|
11794
12054
|
elapsed,
|
|
11795
12055
|
"prerender",
|
|
11796
|
-
|
|
11797
|
-
|
|
12056
|
+
entry2.routeName,
|
|
12057
|
+
entry2.urlPath
|
|
11798
12058
|
);
|
|
11799
12059
|
skipCount++;
|
|
11800
12060
|
break;
|
|
@@ -11942,8 +12202,8 @@ function isLazyMount(route2) {
|
|
|
11942
12202
|
}
|
|
11943
12203
|
async function resolveHostRouterHandlers(hostRegistry) {
|
|
11944
12204
|
const errors = [];
|
|
11945
|
-
for (const [hostId,
|
|
11946
|
-
for (const route2 of
|
|
12205
|
+
for (const [hostId, entry2] of hostRegistry) {
|
|
12206
|
+
for (const route2 of entry2.routes) {
|
|
11947
12207
|
if (isLazyMount(route2)) {
|
|
11948
12208
|
await invokeLazyMount(
|
|
11949
12209
|
route2.handler,
|
|
@@ -11952,9 +12212,9 @@ async function resolveHostRouterHandlers(hostRegistry) {
|
|
|
11952
12212
|
);
|
|
11953
12213
|
}
|
|
11954
12214
|
}
|
|
11955
|
-
if (isLazyMount(
|
|
12215
|
+
if (isLazyMount(entry2.fallback)) {
|
|
11956
12216
|
await invokeLazyMount(
|
|
11957
|
-
|
|
12217
|
+
entry2.fallback.handler,
|
|
11958
12218
|
`host "${hostId}" fallback handler`,
|
|
11959
12219
|
errors
|
|
11960
12220
|
);
|
|
@@ -12001,17 +12261,17 @@ var DiscoveryError = class _DiscoveryError extends Error {
|
|
|
12001
12261
|
};
|
|
12002
12262
|
function describeDiscoveryFailure(err, opts = {}) {
|
|
12003
12263
|
if (err instanceof DiscoveryError && err.caught.length === 0) {
|
|
12004
|
-
const
|
|
12264
|
+
const entry2 = err.entryPath ?? "the router entry";
|
|
12005
12265
|
if (opts.reoptimizeObserved) {
|
|
12006
12266
|
return {
|
|
12007
12267
|
level: "warn",
|
|
12008
|
-
message: `[rango] No routers found while Vite was re-optimizing dependencies on dev boot. This is transient: routes are served per-request and discovery re-runs automatically, so it clears on the next boot. If routes still 404, confirm ${
|
|
12268
|
+
message: `[rango] No routers found while Vite was re-optimizing dependencies on dev boot. This is transient: routes are served per-request and discovery re-runs automatically, so it clears on the next boot. If routes still 404, confirm ${entry2} calls createRouter().`
|
|
12009
12269
|
};
|
|
12010
12270
|
}
|
|
12011
12271
|
return {
|
|
12012
12272
|
level: "error",
|
|
12013
12273
|
message: `${err.message}
|
|
12014
|
-
Ensure ${
|
|
12274
|
+
Ensure ${entry2} calls createRouter() at module top level and that the configured router entry path is correct.`
|
|
12015
12275
|
};
|
|
12016
12276
|
}
|
|
12017
12277
|
const e = err;
|
|
@@ -13809,9 +14069,9 @@ function devServerPhase(s, server) {
|
|
|
13809
14069
|
if (s.resolvedEntryPath) {
|
|
13810
14070
|
routerSourceFiles.add(resolve12(s.resolvedEntryPath));
|
|
13811
14071
|
}
|
|
13812
|
-
for (const
|
|
13813
|
-
if (
|
|
13814
|
-
routerSourceFiles.add(resolve12(
|
|
14072
|
+
for (const entry2 of s.perRouterManifests) {
|
|
14073
|
+
if (entry2.sourceFile) {
|
|
14074
|
+
routerSourceFiles.add(resolve12(entry2.sourceFile));
|
|
13815
14075
|
}
|
|
13816
14076
|
}
|
|
13817
14077
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13916,11 +14176,11 @@ function digestDirectory(dir) {
|
|
|
13916
14176
|
const entries = readdirSync3(current, { withFileTypes: true }).sort(
|
|
13917
14177
|
(a, b) => compareStrings(a.name, b.name)
|
|
13918
14178
|
);
|
|
13919
|
-
for (const
|
|
13920
|
-
if (
|
|
13921
|
-
const path6 = join8(current,
|
|
13922
|
-
const name = `${prefix}${
|
|
13923
|
-
const kind =
|
|
14179
|
+
for (const entry2 of entries) {
|
|
14180
|
+
if (entry2.name === "node_modules" || entry2.name === ".git") continue;
|
|
14181
|
+
const path6 = join8(current, entry2.name);
|
|
14182
|
+
const name = `${prefix}${entry2.name}`;
|
|
14183
|
+
const kind = entry2.isSymbolicLink() ? linkTarget(path6) : entry2;
|
|
13924
14184
|
if (kind?.isDirectory()) {
|
|
13925
14185
|
visit(path6, `${name}/`);
|
|
13926
14186
|
} else if (kind?.isFile()) {
|
|
@@ -14027,9 +14287,9 @@ function readServerResources(manifest) {
|
|
|
14027
14287
|
);
|
|
14028
14288
|
}
|
|
14029
14289
|
return new Map(
|
|
14030
|
-
entries.map((
|
|
14031
|
-
|
|
14032
|
-
manifest.slice(
|
|
14290
|
+
entries.map((entry2) => [
|
|
14291
|
+
entry2.key,
|
|
14292
|
+
manifest.slice(entry2.value.start, entry2.value.end)
|
|
14033
14293
|
])
|
|
14034
14294
|
);
|
|
14035
14295
|
}
|
|
@@ -14118,9 +14378,9 @@ function runRouterVersionsPhase(s, builder) {
|
|
|
14118
14378
|
{ fileName: ASSETS_MANIFEST_FILE, name: ASSETS_MANIFEST_FILE }
|
|
14119
14379
|
]
|
|
14120
14380
|
},
|
|
14121
|
-
routers: s.perRouterManifests.map((
|
|
14122
|
-
id:
|
|
14123
|
-
moduleId:
|
|
14381
|
+
routers: s.perRouterManifests.map((entry2) => ({
|
|
14382
|
+
id: entry2.id,
|
|
14383
|
+
moduleId: entry2.sourceFile
|
|
14124
14384
|
})),
|
|
14125
14385
|
buildData: [...s.buildData, ...clientUrlRecords(s)],
|
|
14126
14386
|
readServerFile: (fileName) => readIfPresent(join9(rscOutDir, fileName)),
|
|
@@ -14159,9 +14419,9 @@ function runRouterVersionsPhase(s, builder) {
|
|
|
14159
14419
|
}
|
|
14160
14420
|
const elapsed = (performance.now() - start).toFixed(1);
|
|
14161
14421
|
const sourceOf = new Map(
|
|
14162
|
-
s.perRouterManifests.map((
|
|
14163
|
-
|
|
14164
|
-
|
|
14422
|
+
s.perRouterManifests.map((entry2) => [
|
|
14423
|
+
entry2.id,
|
|
14424
|
+
entry2.sourceFile ? portableModuleId(entry2.sourceFile, s.projectRoot) : ""
|
|
14165
14425
|
])
|
|
14166
14426
|
);
|
|
14167
14427
|
const detailOf = new Map(details.map((detail) => [detail.routerId, detail]));
|
|
@@ -14759,8 +15019,8 @@ function createRouterDiscoveryPlugin(entryPath, opts) {
|
|
|
14759
15019
|
s.resolvedEntryPath = opts.routerPathRef.path;
|
|
14760
15020
|
}
|
|
14761
15021
|
if (!s.resolvedEntryPath) {
|
|
14762
|
-
const
|
|
14763
|
-
if (
|
|
15022
|
+
const entry2 = resolveRscEntryFromConfig(config);
|
|
15023
|
+
if (entry2) s.resolvedEntryPath = entry2;
|
|
14764
15024
|
}
|
|
14765
15025
|
if (opts?.staticRouteTypesGeneration !== false) {
|
|
14766
15026
|
s.cachedRouterFiles = findRouterFiles(s.projectRoot, s.scanFilter);
|