@tanstack/router-core 1.168.9 → 1.168.11
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/dist/cjs/hash-scroll.cjs +1 -1
- package/dist/cjs/hash-scroll.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/load-matches.cjs +6 -6
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/router.cjs +57 -58
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -1
- package/dist/cjs/scroll-restoration.cjs +1 -1
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/ssr/createRequestHandler.cjs +2 -2
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.cjs +41 -32
- package/dist/cjs/ssr/serializer/RawStream.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/RawStream.d.cts +12 -4
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/ShallowErrorPlugin.d.cts +2 -2
- package/dist/cjs/ssr/serializer/seroval-plugins.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/seroval-plugins.d.cts +2 -1
- package/dist/cjs/ssr/serializer/transformer.cjs +16 -14
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.d.cts +24 -23
- package/dist/cjs/ssr/ssr-client.cjs +9 -9
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +31 -9
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +3 -2
- package/dist/cjs/ssr/transformStreamWithRouter.cjs +4 -1
- package/dist/cjs/ssr/transformStreamWithRouter.cjs.map +1 -1
- package/dist/cjs/stores.cjs +57 -57
- package/dist/cjs/stores.cjs.map +1 -1
- package/dist/cjs/stores.d.cts +16 -16
- package/dist/esm/hash-scroll.js +1 -1
- package/dist/esm/hash-scroll.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/load-matches.js +6 -6
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/router.d.ts +3 -1
- package/dist/esm/router.js +57 -58
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +1 -1
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +2 -2
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/serializer/RawStream.d.ts +12 -4
- package/dist/esm/ssr/serializer/RawStream.js +41 -32
- package/dist/esm/ssr/serializer/RawStream.js.map +1 -1
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.d.ts +2 -2
- package/dist/esm/ssr/serializer/ShallowErrorPlugin.js.map +1 -1
- package/dist/esm/ssr/serializer/seroval-plugins.d.ts +2 -1
- package/dist/esm/ssr/serializer/seroval-plugins.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.d.ts +24 -23
- package/dist/esm/ssr/serializer/transformer.js +16 -14
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/ssr-client.js +9 -9
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +3 -2
- package/dist/esm/ssr/ssr-server.js +31 -9
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/ssr/transformStreamWithRouter.js +4 -1
- package/dist/esm/ssr/transformStreamWithRouter.js.map +1 -1
- package/dist/esm/stores.d.ts +16 -16
- package/dist/esm/stores.js +58 -58
- package/dist/esm/stores.js.map +1 -1
- package/package.json +3 -3
- package/src/hash-scroll.ts +1 -1
- package/src/index.ts +1 -1
- package/src/load-matches.ts +8 -11
- package/src/router.ts +74 -85
- package/src/scroll-restoration.ts +1 -1
- package/src/ssr/createRequestHandler.ts +4 -5
- package/src/ssr/serializer/RawStream.ts +65 -56
- package/src/ssr/serializer/ShallowErrorPlugin.ts +2 -2
- package/src/ssr/serializer/seroval-plugins.ts +2 -1
- package/src/ssr/serializer/transformer.ts +71 -76
- package/src/ssr/ssr-client.ts +8 -12
- package/src/ssr/ssr-server.ts +39 -7
- package/src/ssr/transformStreamWithRouter.ts +3 -0
- package/src/stores.ts +86 -86
package/src/router.ts
CHANGED
|
@@ -799,7 +799,9 @@ export interface ServerSsr {
|
|
|
799
799
|
setRenderFinished: () => void
|
|
800
800
|
cleanup: () => void
|
|
801
801
|
onSerializationFinished: (listener: () => void) => void
|
|
802
|
-
dehydrate: (
|
|
802
|
+
dehydrate: (opts?: {
|
|
803
|
+
requestAssets?: Array<RouterManagedTag>
|
|
804
|
+
}) => Promise<void>
|
|
803
805
|
takeBufferedScripts: () => RouterManagedTag | undefined
|
|
804
806
|
/**
|
|
805
807
|
* Takes any buffered HTML that was injected.
|
|
@@ -1167,7 +1169,7 @@ export class RouterCore<
|
|
|
1167
1169
|
}
|
|
1168
1170
|
|
|
1169
1171
|
if (needsLocationUpdate && this.stores) {
|
|
1170
|
-
this.stores.location.
|
|
1172
|
+
this.stores.location.set(this.latestLocation)
|
|
1171
1173
|
}
|
|
1172
1174
|
|
|
1173
1175
|
if (
|
|
@@ -1182,7 +1184,7 @@ export class RouterCore<
|
|
|
1182
1184
|
}
|
|
1183
1185
|
|
|
1184
1186
|
get state(): RouterState<TRouteTree> {
|
|
1185
|
-
return this.stores.__store.
|
|
1187
|
+
return this.stores.__store.get()
|
|
1186
1188
|
}
|
|
1187
1189
|
|
|
1188
1190
|
updateLatestLocation = () => {
|
|
@@ -1418,9 +1420,9 @@ export class RouterCore<
|
|
|
1418
1420
|
// Snapshot of active match state keyed by routeId, used to stabilise
|
|
1419
1421
|
// params/search across navigations.
|
|
1420
1422
|
const previousActiveMatchesByRouteId = new Map<string, AnyRouteMatch>()
|
|
1421
|
-
for (const store of this.stores.
|
|
1423
|
+
for (const store of this.stores.matchStores.values()) {
|
|
1422
1424
|
if (store.routeId) {
|
|
1423
|
-
previousActiveMatchesByRouteId.set(store.routeId, store.
|
|
1425
|
+
previousActiveMatchesByRouteId.set(store.routeId, store.get())
|
|
1424
1426
|
}
|
|
1425
1427
|
}
|
|
1426
1428
|
|
|
@@ -1713,10 +1715,9 @@ export class RouterCore<
|
|
|
1713
1715
|
}
|
|
1714
1716
|
|
|
1715
1717
|
// Determine params: reuse from state if possible, otherwise parse
|
|
1716
|
-
const lastStateMatchId = last(this.stores.matchesId.
|
|
1718
|
+
const lastStateMatchId = last(this.stores.matchesId.get())
|
|
1717
1719
|
const lastStateMatch =
|
|
1718
|
-
lastStateMatchId &&
|
|
1719
|
-
this.stores.activeMatchStoresById.get(lastStateMatchId)?.state
|
|
1720
|
+
lastStateMatchId && this.stores.matchStores.get(lastStateMatchId)?.get()
|
|
1720
1721
|
const canReuseParams =
|
|
1721
1722
|
lastStateMatch &&
|
|
1722
1723
|
lastStateMatch.routeId === lastRoute.id &&
|
|
@@ -1765,16 +1766,16 @@ export class RouterCore<
|
|
|
1765
1766
|
}
|
|
1766
1767
|
|
|
1767
1768
|
cancelMatches = () => {
|
|
1768
|
-
this.stores.
|
|
1769
|
+
this.stores.pendingIds.get().forEach((matchId) => {
|
|
1769
1770
|
this.cancelMatch(matchId)
|
|
1770
1771
|
})
|
|
1771
1772
|
|
|
1772
|
-
this.stores.matchesId.
|
|
1773
|
-
if (this.stores.
|
|
1773
|
+
this.stores.matchesId.get().forEach((matchId) => {
|
|
1774
|
+
if (this.stores.pendingMatchStores.has(matchId)) {
|
|
1774
1775
|
return
|
|
1775
1776
|
}
|
|
1776
1777
|
|
|
1777
|
-
const match = this.stores.
|
|
1778
|
+
const match = this.stores.matchStores.get(matchId)?.get()
|
|
1778
1779
|
if (!match) {
|
|
1779
1780
|
return
|
|
1780
1781
|
}
|
|
@@ -2354,19 +2355,19 @@ export class RouterCore<
|
|
|
2354
2355
|
// Match the routes
|
|
2355
2356
|
const pendingMatches = this.matchRoutes(this.latestLocation)
|
|
2356
2357
|
|
|
2357
|
-
const nextCachedMatches = this.stores.
|
|
2358
|
-
|
|
2359
|
-
|
|
2358
|
+
const nextCachedMatches = this.stores.cachedMatches
|
|
2359
|
+
.get()
|
|
2360
|
+
.filter((d) => !pendingMatches.some((e) => e.id === d.id))
|
|
2360
2361
|
|
|
2361
2362
|
// Ingest the new matches
|
|
2362
2363
|
this.batch(() => {
|
|
2363
|
-
this.stores.status.
|
|
2364
|
-
this.stores.statusCode.
|
|
2365
|
-
this.stores.isLoading.
|
|
2366
|
-
this.stores.location.
|
|
2367
|
-
this.stores.
|
|
2364
|
+
this.stores.status.set('pending')
|
|
2365
|
+
this.stores.statusCode.set(200)
|
|
2366
|
+
this.stores.isLoading.set(true)
|
|
2367
|
+
this.stores.location.set(this.latestLocation)
|
|
2368
|
+
this.stores.setPending(pendingMatches)
|
|
2368
2369
|
// If a cached match moved to pending matches, remove it from cached matches
|
|
2369
|
-
this.stores.
|
|
2370
|
+
this.stores.setCached(nextCachedMatches)
|
|
2370
2371
|
})
|
|
2371
2372
|
}
|
|
2372
2373
|
|
|
@@ -2375,7 +2376,7 @@ export class RouterCore<
|
|
|
2375
2376
|
let notFound: NotFoundError | undefined
|
|
2376
2377
|
let loadPromise: Promise<void>
|
|
2377
2378
|
const previousLocation =
|
|
2378
|
-
this.stores.resolvedLocation.
|
|
2379
|
+
this.stores.resolvedLocation.get() ?? this.stores.location.get()
|
|
2379
2380
|
|
|
2380
2381
|
// eslint-disable-next-line prefer-const
|
|
2381
2382
|
loadPromise = new Promise<void>((resolve) => {
|
|
@@ -2383,10 +2384,10 @@ export class RouterCore<
|
|
|
2383
2384
|
try {
|
|
2384
2385
|
this.beforeLoad()
|
|
2385
2386
|
const next = this.latestLocation
|
|
2386
|
-
const prevLocation = this.stores.resolvedLocation.
|
|
2387
|
+
const prevLocation = this.stores.resolvedLocation.get()
|
|
2387
2388
|
const locationChangeInfo = getLocationChangeInfo(next, prevLocation)
|
|
2388
2389
|
|
|
2389
|
-
if (!this.stores.redirect.
|
|
2390
|
+
if (!this.stores.redirect.get()) {
|
|
2390
2391
|
this.emit({
|
|
2391
2392
|
type: 'onBeforeNavigate',
|
|
2392
2393
|
...locationChangeInfo,
|
|
@@ -2402,7 +2403,7 @@ export class RouterCore<
|
|
|
2402
2403
|
router: this,
|
|
2403
2404
|
sync: opts?.sync,
|
|
2404
2405
|
forceStaleReload: previousLocation.href === next.href,
|
|
2405
|
-
matches: this.stores.
|
|
2406
|
+
matches: this.stores.pendingMatches.get(),
|
|
2406
2407
|
location: next,
|
|
2407
2408
|
updateMatch: this.updateMatch,
|
|
2408
2409
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
@@ -2426,27 +2427,25 @@ export class RouterCore<
|
|
|
2426
2427
|
let hookStayingMatches: Array<AnyRouteMatch> | null = null
|
|
2427
2428
|
|
|
2428
2429
|
this.batch(() => {
|
|
2429
|
-
const pendingMatches =
|
|
2430
|
-
this.stores.pendingMatchesSnapshot.state
|
|
2430
|
+
const pendingMatches = this.stores.pendingMatches.get()
|
|
2431
2431
|
const mountPending = pendingMatches.length
|
|
2432
|
-
const currentMatches =
|
|
2433
|
-
this.stores.activeMatchesSnapshot.state
|
|
2432
|
+
const currentMatches = this.stores.matches.get()
|
|
2434
2433
|
|
|
2435
2434
|
exitingMatches = mountPending
|
|
2436
2435
|
? currentMatches.filter(
|
|
2437
2436
|
(match) =>
|
|
2438
|
-
!this.stores.
|
|
2437
|
+
!this.stores.pendingMatchStores.has(match.id),
|
|
2439
2438
|
)
|
|
2440
2439
|
: null
|
|
2441
2440
|
|
|
2442
2441
|
// Lifecycle-hook identity: routeId only (route presence in tree)
|
|
2443
2442
|
// Build routeId sets from pools to avoid derived stores.
|
|
2444
2443
|
const pendingRouteIds = new Set<string>()
|
|
2445
|
-
for (const s of this.stores.
|
|
2444
|
+
for (const s of this.stores.pendingMatchStores.values()) {
|
|
2446
2445
|
if (s.routeId) pendingRouteIds.add(s.routeId)
|
|
2447
2446
|
}
|
|
2448
2447
|
const activeRouteIds = new Set<string>()
|
|
2449
|
-
for (const s of this.stores.
|
|
2448
|
+
for (const s of this.stores.matchStores.values()) {
|
|
2450
2449
|
if (s.routeId) activeRouteIds.add(s.routeId)
|
|
2451
2450
|
}
|
|
2452
2451
|
|
|
@@ -2466,8 +2465,8 @@ export class RouterCore<
|
|
|
2466
2465
|
)
|
|
2467
2466
|
: currentMatches
|
|
2468
2467
|
|
|
2469
|
-
this.stores.isLoading.
|
|
2470
|
-
this.stores.loadedAt.
|
|
2468
|
+
this.stores.isLoading.set(false)
|
|
2469
|
+
this.stores.loadedAt.set(Date.now())
|
|
2471
2470
|
/**
|
|
2472
2471
|
* When committing new matches, cache any exiting matches that are still usable.
|
|
2473
2472
|
* Routes that resolved with `status: 'error'` or `status: 'notFound'` are
|
|
@@ -2475,10 +2474,10 @@ export class RouterCore<
|
|
|
2475
2474
|
* or reloads re-run their loaders instead of reusing the failed/not-found data.
|
|
2476
2475
|
*/
|
|
2477
2476
|
if (mountPending) {
|
|
2478
|
-
this.stores.
|
|
2479
|
-
this.stores.
|
|
2480
|
-
this.stores.
|
|
2481
|
-
...this.stores.
|
|
2477
|
+
this.stores.setMatches(pendingMatches)
|
|
2478
|
+
this.stores.setPending([])
|
|
2479
|
+
this.stores.setCached([
|
|
2480
|
+
...this.stores.cachedMatches.get(),
|
|
2482
2481
|
...exitingMatches!.filter(
|
|
2483
2482
|
(d) =>
|
|
2484
2483
|
d.status !== 'error' &&
|
|
@@ -2525,15 +2524,13 @@ export class RouterCore<
|
|
|
2525
2524
|
? redirect.status
|
|
2526
2525
|
: notFound
|
|
2527
2526
|
? 404
|
|
2528
|
-
: this.stores.
|
|
2529
|
-
(d) => d.status === 'error',
|
|
2530
|
-
)
|
|
2527
|
+
: this.stores.matches.get().some((d) => d.status === 'error')
|
|
2531
2528
|
? 500
|
|
2532
2529
|
: 200
|
|
2533
2530
|
|
|
2534
2531
|
this.batch(() => {
|
|
2535
|
-
this.stores.statusCode.
|
|
2536
|
-
this.stores.redirect.
|
|
2532
|
+
this.stores.statusCode.set(nextStatusCode)
|
|
2533
|
+
this.stores.redirect.set(redirect)
|
|
2537
2534
|
})
|
|
2538
2535
|
}
|
|
2539
2536
|
|
|
@@ -2561,13 +2558,11 @@ export class RouterCore<
|
|
|
2561
2558
|
let newStatusCode: number | undefined = undefined
|
|
2562
2559
|
if (this.hasNotFoundMatch()) {
|
|
2563
2560
|
newStatusCode = 404
|
|
2564
|
-
} else if (
|
|
2565
|
-
this.stores.activeMatchesSnapshot.state.some((d) => d.status === 'error')
|
|
2566
|
-
) {
|
|
2561
|
+
} else if (this.stores.matches.get().some((d) => d.status === 'error')) {
|
|
2567
2562
|
newStatusCode = 500
|
|
2568
2563
|
}
|
|
2569
2564
|
if (newStatusCode !== undefined) {
|
|
2570
|
-
this.stores.statusCode.
|
|
2565
|
+
this.stores.statusCode.set(newStatusCode)
|
|
2571
2566
|
}
|
|
2572
2567
|
}
|
|
2573
2568
|
|
|
@@ -2596,7 +2591,7 @@ export class RouterCore<
|
|
|
2596
2591
|
this.isViewTransitionTypesSupported
|
|
2597
2592
|
) {
|
|
2598
2593
|
const next = this.latestLocation
|
|
2599
|
-
const prevLocation = this.stores.resolvedLocation.
|
|
2594
|
+
const prevLocation = this.stores.resolvedLocation.get()
|
|
2600
2595
|
|
|
2601
2596
|
const resolvedViewTransitionTypes =
|
|
2602
2597
|
typeof shouldViewTransition.types === 'function'
|
|
@@ -2626,30 +2621,30 @@ export class RouterCore<
|
|
|
2626
2621
|
|
|
2627
2622
|
updateMatch: UpdateMatchFn = (id, updater) => {
|
|
2628
2623
|
this.startTransition(() => {
|
|
2629
|
-
const pendingMatch = this.stores.
|
|
2624
|
+
const pendingMatch = this.stores.pendingMatchStores.get(id)
|
|
2630
2625
|
if (pendingMatch) {
|
|
2631
|
-
pendingMatch.
|
|
2626
|
+
pendingMatch.set(updater)
|
|
2632
2627
|
return
|
|
2633
2628
|
}
|
|
2634
2629
|
|
|
2635
|
-
const activeMatch = this.stores.
|
|
2630
|
+
const activeMatch = this.stores.matchStores.get(id)
|
|
2636
2631
|
if (activeMatch) {
|
|
2637
|
-
activeMatch.
|
|
2632
|
+
activeMatch.set(updater)
|
|
2638
2633
|
return
|
|
2639
2634
|
}
|
|
2640
2635
|
|
|
2641
|
-
const cachedMatch = this.stores.
|
|
2636
|
+
const cachedMatch = this.stores.cachedMatchStores.get(id)
|
|
2642
2637
|
if (cachedMatch) {
|
|
2643
|
-
const next = updater(cachedMatch.
|
|
2638
|
+
const next = updater(cachedMatch.get())
|
|
2644
2639
|
if (next.status === 'redirected') {
|
|
2645
|
-
const deleted = this.stores.
|
|
2640
|
+
const deleted = this.stores.cachedMatchStores.delete(id)
|
|
2646
2641
|
if (deleted) {
|
|
2647
|
-
this.stores.
|
|
2642
|
+
this.stores.cachedIds.set((prev) =>
|
|
2648
2643
|
prev.filter((matchId) => matchId !== id),
|
|
2649
2644
|
)
|
|
2650
2645
|
}
|
|
2651
2646
|
} else {
|
|
2652
|
-
cachedMatch.
|
|
2647
|
+
cachedMatch.set(next)
|
|
2653
2648
|
}
|
|
2654
2649
|
}
|
|
2655
2650
|
})
|
|
@@ -2657,9 +2652,9 @@ export class RouterCore<
|
|
|
2657
2652
|
|
|
2658
2653
|
getMatch: GetMatchFn = (matchId: string): AnyRouteMatch | undefined => {
|
|
2659
2654
|
return (
|
|
2660
|
-
this.stores.
|
|
2661
|
-
this.stores.
|
|
2662
|
-
this.stores.
|
|
2655
|
+
this.stores.cachedMatchStores.get(matchId)?.get() ??
|
|
2656
|
+
this.stores.pendingMatchStores.get(matchId)?.get() ??
|
|
2657
|
+
this.stores.matchStores.get(matchId)?.get()
|
|
2663
2658
|
)
|
|
2664
2659
|
}
|
|
2665
2660
|
|
|
@@ -2696,15 +2691,9 @@ export class RouterCore<
|
|
|
2696
2691
|
}
|
|
2697
2692
|
|
|
2698
2693
|
this.batch(() => {
|
|
2699
|
-
this.stores.
|
|
2700
|
-
|
|
2701
|
-
)
|
|
2702
|
-
this.stores.setCachedMatches(
|
|
2703
|
-
this.stores.cachedMatchesSnapshot.state.map(invalidate),
|
|
2704
|
-
)
|
|
2705
|
-
this.stores.setPendingMatches(
|
|
2706
|
-
this.stores.pendingMatchesSnapshot.state.map(invalidate),
|
|
2707
|
-
)
|
|
2694
|
+
this.stores.setMatches(this.stores.matches.get().map(invalidate))
|
|
2695
|
+
this.stores.setCached(this.stores.cachedMatches.get().map(invalidate))
|
|
2696
|
+
this.stores.setPending(this.stores.pendingMatches.get().map(invalidate))
|
|
2708
2697
|
})
|
|
2709
2698
|
|
|
2710
2699
|
this.shouldViewTransition = false
|
|
@@ -2762,13 +2751,13 @@ export class RouterCore<
|
|
|
2762
2751
|
clearCache: ClearCacheFn<this> = (opts) => {
|
|
2763
2752
|
const filter = opts?.filter
|
|
2764
2753
|
if (filter !== undefined) {
|
|
2765
|
-
this.stores.
|
|
2766
|
-
this.stores.
|
|
2767
|
-
(
|
|
2768
|
-
|
|
2754
|
+
this.stores.setCached(
|
|
2755
|
+
this.stores.cachedMatches
|
|
2756
|
+
.get()
|
|
2757
|
+
.filter((m) => !filter(m as MakeRouteMatchUnion<this>)),
|
|
2769
2758
|
)
|
|
2770
2759
|
} else {
|
|
2771
|
-
this.stores.
|
|
2760
|
+
this.stores.setCached([])
|
|
2772
2761
|
}
|
|
2773
2762
|
}
|
|
2774
2763
|
|
|
@@ -2816,13 +2805,13 @@ export class RouterCore<
|
|
|
2816
2805
|
})
|
|
2817
2806
|
|
|
2818
2807
|
const activeMatchIds = new Set([
|
|
2819
|
-
...this.stores.matchesId.
|
|
2820
|
-
...this.stores.
|
|
2808
|
+
...this.stores.matchesId.get(),
|
|
2809
|
+
...this.stores.pendingIds.get(),
|
|
2821
2810
|
])
|
|
2822
2811
|
|
|
2823
2812
|
const loadedMatchIds = new Set([
|
|
2824
2813
|
...activeMatchIds,
|
|
2825
|
-
...this.stores.
|
|
2814
|
+
...this.stores.cachedIds.get(),
|
|
2826
2815
|
])
|
|
2827
2816
|
|
|
2828
2817
|
// If the matches are already loaded, we need to add them to the cached matches.
|
|
@@ -2830,8 +2819,8 @@ export class RouterCore<
|
|
|
2830
2819
|
(match) => !loadedMatchIds.has(match.id),
|
|
2831
2820
|
)
|
|
2832
2821
|
if (matchesToCache.length) {
|
|
2833
|
-
const cachedMatches = this.stores.
|
|
2834
|
-
this.stores.
|
|
2822
|
+
const cachedMatches = this.stores.cachedMatches.get()
|
|
2823
|
+
this.stores.setCached([...cachedMatches, ...matchesToCache])
|
|
2835
2824
|
}
|
|
2836
2825
|
|
|
2837
2826
|
try {
|
|
@@ -2886,16 +2875,16 @@ export class RouterCore<
|
|
|
2886
2875
|
}
|
|
2887
2876
|
const next = this.buildLocation(matchLocation as any)
|
|
2888
2877
|
|
|
2889
|
-
if (opts?.pending && this.stores.status.
|
|
2878
|
+
if (opts?.pending && this.stores.status.get() !== 'pending') {
|
|
2890
2879
|
return false
|
|
2891
2880
|
}
|
|
2892
2881
|
|
|
2893
2882
|
const pending =
|
|
2894
|
-
opts?.pending === undefined ? !this.stores.isLoading.
|
|
2883
|
+
opts?.pending === undefined ? !this.stores.isLoading.get() : opts.pending
|
|
2895
2884
|
|
|
2896
2885
|
const baseLocation = pending
|
|
2897
2886
|
? this.latestLocation
|
|
2898
|
-
: this.stores.resolvedLocation.
|
|
2887
|
+
: this.stores.resolvedLocation.get() || this.stores.location.get()
|
|
2899
2888
|
|
|
2900
2889
|
const match = findSingleMatch(
|
|
2901
2890
|
next.pathname,
|
|
@@ -2931,9 +2920,9 @@ export class RouterCore<
|
|
|
2931
2920
|
serverSsr?: ServerSsr
|
|
2932
2921
|
|
|
2933
2922
|
hasNotFoundMatch = () => {
|
|
2934
|
-
return this.stores.
|
|
2935
|
-
(
|
|
2936
|
-
|
|
2923
|
+
return this.stores.matches
|
|
2924
|
+
.get()
|
|
2925
|
+
.some((d) => d.status === 'notFound' || d.globalNotFound)
|
|
2937
2926
|
}
|
|
2938
2927
|
}
|
|
2939
2928
|
|
|
@@ -233,7 +233,7 @@ export function setupScrollRestoration(router: AnyRouter, force?: boolean) {
|
|
|
233
233
|
window.addEventListener('pagehide', () => {
|
|
234
234
|
snapshotCurrentScrollTargets(
|
|
235
235
|
getKey(
|
|
236
|
-
router.stores.resolvedLocation.
|
|
236
|
+
router.stores.resolvedLocation.get() ?? router.stores.location.get(),
|
|
237
237
|
),
|
|
238
238
|
)
|
|
239
239
|
cache.persist()
|
|
@@ -78,13 +78,12 @@ export function createRequestHandler<TRouter extends AnyRouter>({
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function getRequestHeaders(opts: { router: AnyRouter }): Headers {
|
|
81
|
-
const matchHeaders =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
81
|
+
const matchHeaders = opts.router.stores.matches
|
|
82
|
+
.get()
|
|
83
|
+
.map<AnyHeaders>((match) => match.headers)
|
|
85
84
|
|
|
86
85
|
// Handle Redirects
|
|
87
|
-
const redirect = opts.router.stores.redirect.
|
|
86
|
+
const redirect = opts.router.stores.redirect.get()
|
|
88
87
|
if (redirect) {
|
|
89
88
|
matchHeaders.push(redirect.headers)
|
|
90
89
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createPlugin, createStream } from 'seroval'
|
|
2
|
-
import type {
|
|
2
|
+
import type { PluginData, PluginInfo, SerovalNode } from 'seroval'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Hint for RawStream encoding strategy during SSR serialization.
|
|
@@ -240,61 +240,71 @@ function toTextStream(readable: ReadableStream<Uint8Array>) {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
// Factory plugin for binary mode
|
|
243
|
-
const RawStreamFactoryBinaryPlugin = createPlugin<
|
|
243
|
+
const RawStreamFactoryBinaryPlugin = /* @__PURE__ */ createPlugin<
|
|
244
244
|
Record<string, never>,
|
|
245
|
-
|
|
245
|
+
PluginInfo
|
|
246
246
|
>({
|
|
247
247
|
tag: 'tss/RawStreamFactory',
|
|
248
248
|
test(value) {
|
|
249
249
|
return value === RAW_STREAM_FACTORY_BINARY
|
|
250
250
|
},
|
|
251
251
|
parse: {
|
|
252
|
-
sync() {
|
|
253
|
-
return
|
|
252
|
+
sync(_value, _ctx, _data) {
|
|
253
|
+
return {}
|
|
254
254
|
},
|
|
255
|
-
async() {
|
|
256
|
-
return
|
|
255
|
+
async async(_value, _ctx, _data) {
|
|
256
|
+
return {}
|
|
257
257
|
},
|
|
258
|
-
stream() {
|
|
259
|
-
return
|
|
258
|
+
stream(_value, _ctx, _data) {
|
|
259
|
+
return {}
|
|
260
260
|
},
|
|
261
261
|
},
|
|
262
|
-
serialize() {
|
|
262
|
+
serialize(_node, _ctx, _data) {
|
|
263
263
|
return FACTORY_BINARY
|
|
264
264
|
},
|
|
265
|
-
deserialize() {
|
|
265
|
+
deserialize(_node, _ctx, _data) {
|
|
266
266
|
return RAW_STREAM_FACTORY_BINARY
|
|
267
267
|
},
|
|
268
268
|
})
|
|
269
269
|
|
|
270
270
|
// Factory plugin for text mode
|
|
271
|
-
const RawStreamFactoryTextPlugin = createPlugin<
|
|
271
|
+
const RawStreamFactoryTextPlugin = /* @__PURE__ */ createPlugin<
|
|
272
272
|
Record<string, never>,
|
|
273
|
-
|
|
273
|
+
PluginInfo
|
|
274
274
|
>({
|
|
275
275
|
tag: 'tss/RawStreamFactoryText',
|
|
276
276
|
test(value) {
|
|
277
277
|
return value === RAW_STREAM_FACTORY_TEXT
|
|
278
278
|
},
|
|
279
279
|
parse: {
|
|
280
|
-
sync() {
|
|
281
|
-
return
|
|
280
|
+
sync(_value, _ctx, _data) {
|
|
281
|
+
return {}
|
|
282
282
|
},
|
|
283
|
-
async() {
|
|
284
|
-
return
|
|
283
|
+
async async(_value, _ctx, _data) {
|
|
284
|
+
return {}
|
|
285
285
|
},
|
|
286
|
-
stream() {
|
|
287
|
-
return
|
|
286
|
+
stream(_value, _ctx, _data) {
|
|
287
|
+
return {}
|
|
288
288
|
},
|
|
289
289
|
},
|
|
290
|
-
serialize() {
|
|
290
|
+
serialize(_node, _ctx, _data) {
|
|
291
291
|
return FACTORY_TEXT
|
|
292
292
|
},
|
|
293
|
-
deserialize() {
|
|
293
|
+
deserialize(_node, _ctx, _data) {
|
|
294
294
|
return RAW_STREAM_FACTORY_TEXT
|
|
295
295
|
},
|
|
296
296
|
})
|
|
297
297
|
|
|
298
|
+
export interface RawStreamSSRNode extends PluginInfo {
|
|
299
|
+
hint: SerovalNode
|
|
300
|
+
factory: SerovalNode
|
|
301
|
+
stream: SerovalNode
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface RawStreamRPCNode extends PluginInfo {
|
|
305
|
+
streamId: SerovalNode
|
|
306
|
+
}
|
|
307
|
+
|
|
298
308
|
/**
|
|
299
309
|
* SSR Plugin - uses base64 or UTF-8+base64 encoding for chunks, delegates to seroval's stream mechanism.
|
|
300
310
|
* Used during SSR when serializing to JavaScript code for HTML injection.
|
|
@@ -303,7 +313,10 @@ const RawStreamFactoryTextPlugin = createPlugin<
|
|
|
303
313
|
* - 'binary': Always base64 encode (default)
|
|
304
314
|
* - 'text': Try UTF-8 first, fallback to base64 for invalid UTF-8
|
|
305
315
|
*/
|
|
306
|
-
export const RawStreamSSRPlugin
|
|
316
|
+
export const RawStreamSSRPlugin = /* @__PURE__ */ createPlugin<
|
|
317
|
+
RawStream,
|
|
318
|
+
RawStreamSSRNode
|
|
319
|
+
>({
|
|
307
320
|
tag: 'tss/RawStream',
|
|
308
321
|
extends: [RawStreamFactoryBinaryPlugin, RawStreamFactoryTextPlugin],
|
|
309
322
|
|
|
@@ -312,19 +325,19 @@ export const RawStreamSSRPlugin: Plugin<any, any> = createPlugin({
|
|
|
312
325
|
},
|
|
313
326
|
|
|
314
327
|
parse: {
|
|
315
|
-
sync(value: RawStream, ctx) {
|
|
328
|
+
sync(value: RawStream, ctx, _data) {
|
|
316
329
|
// Sync parse not really supported for streams, return empty stream
|
|
317
330
|
const factory =
|
|
318
331
|
value.hint === 'text'
|
|
319
332
|
? RAW_STREAM_FACTORY_TEXT
|
|
320
333
|
: RAW_STREAM_FACTORY_BINARY
|
|
321
334
|
return {
|
|
322
|
-
hint: value.hint,
|
|
335
|
+
hint: ctx.parse(value.hint),
|
|
323
336
|
factory: ctx.parse(factory),
|
|
324
337
|
stream: ctx.parse(createStream()),
|
|
325
338
|
}
|
|
326
339
|
},
|
|
327
|
-
async async(value: RawStream, ctx) {
|
|
340
|
+
async async(value: RawStream, ctx, _data) {
|
|
328
341
|
const factory =
|
|
329
342
|
value.hint === 'text'
|
|
330
343
|
? RAW_STREAM_FACTORY_TEXT
|
|
@@ -334,12 +347,12 @@ export const RawStreamSSRPlugin: Plugin<any, any> = createPlugin({
|
|
|
334
347
|
? toTextStream(value.stream)
|
|
335
348
|
: toBinaryStream(value.stream)
|
|
336
349
|
return {
|
|
337
|
-
hint: value.hint,
|
|
350
|
+
hint: await ctx.parse(value.hint),
|
|
338
351
|
factory: await ctx.parse(factory),
|
|
339
352
|
stream: await ctx.parse(encodedStream),
|
|
340
353
|
}
|
|
341
354
|
},
|
|
342
|
-
stream(value: RawStream, ctx) {
|
|
355
|
+
stream(value: RawStream, ctx, _data) {
|
|
343
356
|
const factory =
|
|
344
357
|
value.hint === 'text'
|
|
345
358
|
? RAW_STREAM_FACTORY_TEXT
|
|
@@ -349,14 +362,14 @@ export const RawStreamSSRPlugin: Plugin<any, any> = createPlugin({
|
|
|
349
362
|
? toTextStream(value.stream)
|
|
350
363
|
: toBinaryStream(value.stream)
|
|
351
364
|
return {
|
|
352
|
-
hint: value.hint,
|
|
365
|
+
hint: ctx.parse(value.hint),
|
|
353
366
|
factory: ctx.parse(factory),
|
|
354
367
|
stream: ctx.parse(encodedStream),
|
|
355
368
|
}
|
|
356
369
|
},
|
|
357
370
|
},
|
|
358
371
|
|
|
359
|
-
serialize(node:
|
|
372
|
+
serialize(node: RawStreamSSRNode, ctx, _data) {
|
|
360
373
|
return (
|
|
361
374
|
'(' +
|
|
362
375
|
ctx.serialize(node.factory) +
|
|
@@ -366,23 +379,14 @@ export const RawStreamSSRPlugin: Plugin<any, any> = createPlugin({
|
|
|
366
379
|
)
|
|
367
380
|
},
|
|
368
381
|
|
|
369
|
-
deserialize(
|
|
370
|
-
node: { hint: RawStreamHint; factory: any; stream: any },
|
|
371
|
-
ctx,
|
|
372
|
-
): any {
|
|
382
|
+
deserialize(node: RawStreamSSRNode, ctx, _data): any {
|
|
373
383
|
const stream: ReturnType<typeof createStream> = ctx.deserialize(node.stream)
|
|
374
|
-
|
|
384
|
+
const hint = ctx.deserialize(node.hint)
|
|
385
|
+
return hint === 'text'
|
|
375
386
|
? RAW_STREAM_FACTORY_CONSTRUCTOR_TEXT(stream)
|
|
376
387
|
: RAW_STREAM_FACTORY_CONSTRUCTOR_BINARY(stream)
|
|
377
388
|
},
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Node type for RPC plugin serialization
|
|
382
|
-
*/
|
|
383
|
-
interface RawStreamRPCNode {
|
|
384
|
-
streamId: number
|
|
385
|
-
}
|
|
389
|
+
})
|
|
386
390
|
|
|
387
391
|
/**
|
|
388
392
|
* Creates an RPC plugin instance that registers raw streams with a multiplexer.
|
|
@@ -391,13 +395,12 @@ interface RawStreamRPCNode {
|
|
|
391
395
|
*
|
|
392
396
|
* @param onRawStream Callback invoked when a RawStream is encountered during serialization
|
|
393
397
|
*/
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
): Plugin<any, any> {
|
|
398
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
399
|
+
export function createRawStreamRPCPlugin(onRawStream: OnRawStreamCallback) {
|
|
397
400
|
// Own stream counter - sequential IDs starting at 1, independent of seroval internals
|
|
398
401
|
let nextStreamId = 1
|
|
399
402
|
|
|
400
|
-
return createPlugin({
|
|
403
|
+
return /* @__PURE__ */ createPlugin<RawStream, RawStreamRPCNode>({
|
|
401
404
|
tag: 'tss/RawStream',
|
|
402
405
|
|
|
403
406
|
test(value: unknown) {
|
|
@@ -405,15 +408,15 @@ export function createRawStreamRPCPlugin(
|
|
|
405
408
|
},
|
|
406
409
|
|
|
407
410
|
parse: {
|
|
408
|
-
async(value: RawStream) {
|
|
411
|
+
async async(value: RawStream, ctx, _data: PluginData) {
|
|
409
412
|
const streamId = nextStreamId++
|
|
410
413
|
onRawStream(streamId, value.stream)
|
|
411
|
-
return
|
|
414
|
+
return { streamId: await ctx.parse(streamId) }
|
|
412
415
|
},
|
|
413
|
-
stream(value: RawStream) {
|
|
416
|
+
stream(value: RawStream, ctx, _data: PluginData) {
|
|
414
417
|
const streamId = nextStreamId++
|
|
415
418
|
onRawStream(streamId, value.stream)
|
|
416
|
-
return { streamId }
|
|
419
|
+
return { streamId: ctx.parse(streamId) }
|
|
417
420
|
},
|
|
418
421
|
},
|
|
419
422
|
|
|
@@ -431,7 +434,7 @@ export function createRawStreamRPCPlugin(
|
|
|
431
434
|
'RawStreamRPCPlugin.deserialize should not be called. Use createRawStreamDeserializePlugin on client.',
|
|
432
435
|
)
|
|
433
436
|
},
|
|
434
|
-
})
|
|
437
|
+
})
|
|
435
438
|
}
|
|
436
439
|
|
|
437
440
|
/**
|
|
@@ -442,8 +445,8 @@ export function createRawStreamRPCPlugin(
|
|
|
442
445
|
*/
|
|
443
446
|
export function createRawStreamDeserializePlugin(
|
|
444
447
|
getOrCreateStream: (id: number) => ReadableStream<Uint8Array>,
|
|
445
|
-
)
|
|
446
|
-
return createPlugin({
|
|
448
|
+
) {
|
|
449
|
+
return /* @__PURE__ */ createPlugin<any, RawStreamRPCNode>({
|
|
447
450
|
tag: 'tss/RawStream',
|
|
448
451
|
|
|
449
452
|
test: () => false, // Client never serializes RawStream
|
|
@@ -457,8 +460,14 @@ export function createRawStreamDeserializePlugin(
|
|
|
457
460
|
)
|
|
458
461
|
},
|
|
459
462
|
|
|
460
|
-
deserialize(node
|
|
461
|
-
|
|
463
|
+
deserialize(node, ctx, _data) {
|
|
464
|
+
// In normal seroval usage, ctx.deserialize exists.
|
|
465
|
+
// Some unit tests call plugin.deserialize directly with a minimal ctx.
|
|
466
|
+
const id =
|
|
467
|
+
typeof (ctx as any)?.deserialize === 'function'
|
|
468
|
+
? (ctx as any).deserialize(node.streamId)
|
|
469
|
+
: (node as any).streamId
|
|
470
|
+
return getOrCreateStream(id as number)
|
|
462
471
|
},
|
|
463
|
-
})
|
|
472
|
+
})
|
|
464
473
|
}
|