@tanstack/router-core 1.171.16-pre.0 → 1.171.17
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/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +5 -3
- package/dist/cjs/load-client.cjs +169 -246
- package/dist/cjs/load-client.cjs.map +1 -1
- package/dist/cjs/load-client.d.cts +10 -39
- package/dist/cjs/router.cjs +42 -22
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +14 -10
- package/dist/esm/link.d.ts +5 -3
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/load-client.d.ts +10 -39
- package/dist/esm/load-client.js +171 -247
- package/dist/esm/load-client.js.map +1 -1
- package/dist/esm/router.d.ts +14 -10
- package/dist/esm/router.js +44 -23
- package/dist/esm/router.js.map +1 -1
- package/package.json +3 -3
- package/skills/router-core/SKILL.md +23 -4
- package/skills/router-core/auth-and-guards/SKILL.md +10 -10
- package/skills/router-core/code-splitting/SKILL.md +5 -4
- package/skills/router-core/data-loading/SKILL.md +30 -18
- package/skills/router-core/navigation/SKILL.md +5 -4
- package/skills/router-core/not-found-and-errors/SKILL.md +5 -4
- package/skills/router-core/path-params/SKILL.md +5 -4
- package/skills/router-core/search-params/SKILL.md +5 -4
- package/skills/router-core/ssr/SKILL.md +5 -4
- package/skills/router-core/type-safety/SKILL.md +11 -4
- package/src/link.ts +5 -3
- package/src/load-client.ts +582 -632
- package/src/router.ts +87 -44
package/src/router.ts
CHANGED
|
@@ -41,7 +41,6 @@ import {
|
|
|
41
41
|
preloadClientRoute,
|
|
42
42
|
refreshClientRoute,
|
|
43
43
|
replaceRouteChunk,
|
|
44
|
-
transferMatchResources,
|
|
45
44
|
} from './load-client'
|
|
46
45
|
import {
|
|
47
46
|
composeRewrites,
|
|
@@ -58,7 +57,6 @@ import type {
|
|
|
58
57
|
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
59
58
|
import type { AnyRedirect, ResolvedRedirect } from './redirect'
|
|
60
59
|
import type {
|
|
61
|
-
ActivePreload,
|
|
62
60
|
LoadTransaction,
|
|
63
61
|
LoaderFlight,
|
|
64
62
|
PendingSession,
|
|
@@ -766,7 +764,6 @@ export type LoadFn = (opts?: {
|
|
|
766
764
|
sync?: boolean
|
|
767
765
|
action?: { type: HistoryAction }
|
|
768
766
|
_signal?: AbortSignal
|
|
769
|
-
_dedupe?: boolean
|
|
770
767
|
}) => Promise<void>
|
|
771
768
|
|
|
772
769
|
export type CommitLocationFn = ({
|
|
@@ -778,7 +775,6 @@ export type CommitLocationFn = ({
|
|
|
778
775
|
export type StartTransitionFn = (
|
|
779
776
|
fn: () => void,
|
|
780
777
|
expected: Array<AnyRouteMatch>,
|
|
781
|
-
urgent?: boolean,
|
|
782
778
|
) => Promise<boolean>
|
|
783
779
|
|
|
784
780
|
export interface MatchRoutesFn {
|
|
@@ -1027,8 +1023,8 @@ export interface RouterCore<
|
|
|
1027
1023
|
_tx?: LoadTransaction
|
|
1028
1024
|
/** Joinable in-flight loader generations keyed by match ID. */
|
|
1029
1025
|
_flights?: Map<string, LoaderFlight>
|
|
1030
|
-
/**
|
|
1031
|
-
_preloads?: Map<
|
|
1026
|
+
/** Active speculative lanes retained for cancellation, invalidation, and cache clearing. */
|
|
1027
|
+
_preloads?: Map<AbortController, Array<AnyRouteMatch>>
|
|
1032
1028
|
/** Owns cancellable work before a client transaction publishes. */
|
|
1033
1029
|
_preflight?: AbortController
|
|
1034
1030
|
/** Transfers one reconstructed SSR prefix into its initial client load. */
|
|
@@ -1037,8 +1033,11 @@ export interface RouterCore<
|
|
|
1037
1033
|
_pending?: PendingSession
|
|
1038
1034
|
/** Result of the latest server load, used to render or redirect. */
|
|
1039
1035
|
_serverResult?: ServerLoadResult
|
|
1040
|
-
/** Framework
|
|
1041
|
-
_rendered?:
|
|
1036
|
+
/** Framework publication waiting for an exact render acknowledgement. */
|
|
1037
|
+
_rendered?: [
|
|
1038
|
+
offered?: Array<AnyRouteMatch>,
|
|
1039
|
+
settle?: (rendered: boolean) => void,
|
|
1040
|
+
]
|
|
1042
1041
|
/** Development-only HMR reload for a route and its descendants. */
|
|
1043
1042
|
_refreshRoute: (() => Promise<void>) | undefined
|
|
1044
1043
|
/** Development-only replacement for a route's lazy chunk owner. */
|
|
@@ -1769,8 +1768,8 @@ export class RouterCore<
|
|
|
1769
1768
|
: undefined
|
|
1770
1769
|
const lastStateMatchId = lastStateMatch?.id
|
|
1771
1770
|
const cached = this.lightweightCache.get(location)
|
|
1772
|
-
if (cached && cached[0] === lastStateMatchId) {
|
|
1773
|
-
return cached[1]
|
|
1771
|
+
if (cached && cached[0 /* lastMatchId */] === lastStateMatchId) {
|
|
1772
|
+
return cached[1 /* result */]
|
|
1774
1773
|
}
|
|
1775
1774
|
|
|
1776
1775
|
const { matchedRoutes, routeParams } = this.getMatchedRoutes(
|
|
@@ -2169,7 +2168,7 @@ export class RouterCore<
|
|
|
2169
2168
|
|
|
2170
2169
|
// Don't commit to history if nothing changed
|
|
2171
2170
|
if (isSameLocation) {
|
|
2172
|
-
this.load(
|
|
2171
|
+
this.load()
|
|
2173
2172
|
} else {
|
|
2174
2173
|
let {
|
|
2175
2174
|
// eslint-disable-next-line prefer-const
|
|
@@ -2451,9 +2450,11 @@ export class RouterCore<
|
|
|
2451
2450
|
}
|
|
2452
2451
|
|
|
2453
2452
|
/**
|
|
2454
|
-
* Invalidate
|
|
2453
|
+
* Invalidate selected match generations and optionally force current matches
|
|
2454
|
+
* back into a pending state.
|
|
2455
2455
|
*
|
|
2456
|
-
* - Marks
|
|
2456
|
+
* - Marks committed and cached matches whose IDs are selected as invalid.
|
|
2457
|
+
* - Retires selected active preloads so older work cannot publish fresh data.
|
|
2457
2458
|
*
|
|
2458
2459
|
* The next load decides when to publish pending UI, so invalidation does not
|
|
2459
2460
|
* mutate the currently rendered status.
|
|
@@ -2469,15 +2470,28 @@ export class RouterCore<
|
|
|
2469
2470
|
> = (opts) => {
|
|
2470
2471
|
const committedMatches = this._committed
|
|
2471
2472
|
const filter = opts?.filter
|
|
2472
|
-
const
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2473
|
+
const preloads = this._preloads
|
|
2474
|
+
const invalidIds = new Set(
|
|
2475
|
+
[
|
|
2476
|
+
...committedMatches,
|
|
2477
|
+
...this._cache.values(),
|
|
2478
|
+
...[...(preloads?.values() ?? [])].flat(),
|
|
2479
|
+
...(this._tx?.[3 /* matches */] ?? []),
|
|
2480
|
+
]
|
|
2481
|
+
.filter(
|
|
2482
|
+
(match) => !filter || filter(match as MakeRouteMatchUnion<this>),
|
|
2477
2483
|
)
|
|
2478
|
-
|
|
2484
|
+
.map((match) => match.id),
|
|
2485
|
+
)
|
|
2486
|
+
const discardedPreloads: Array<AbortController> = []
|
|
2487
|
+
for (const [controller, matches] of preloads ?? []) {
|
|
2488
|
+
if (matches.some((match) => invalidIds.has(match.id))) {
|
|
2489
|
+
preloads!.delete(controller)
|
|
2490
|
+
discardedPreloads.push(controller)
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2479
2493
|
const invalidate = (d: MakeRouteMatch<TRouteTree>) => {
|
|
2480
|
-
if (
|
|
2494
|
+
if (invalidIds.has(d.id)) {
|
|
2481
2495
|
const route = this.routesById[d.routeId] as AnyRoute
|
|
2482
2496
|
const next = {
|
|
2483
2497
|
...d,
|
|
@@ -2496,13 +2510,25 @@ export class RouterCore<
|
|
|
2496
2510
|
return d
|
|
2497
2511
|
}
|
|
2498
2512
|
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2513
|
+
this._committed = committedMatches.map(invalidate)
|
|
2514
|
+
// Cache entries are settled successes. Retiring matching active preload
|
|
2515
|
+
// owners makes an in-place stale mark sufficient while preserving data.
|
|
2502
2516
|
for (const [id, match] of this._cache) {
|
|
2503
|
-
|
|
2517
|
+
if (invalidIds.has(id)) {
|
|
2518
|
+
match.invalid = true
|
|
2519
|
+
if (opts?.forcePending) {
|
|
2520
|
+
match.status = 'pending'
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
// The superseding load must not discover any same-ID generation selected
|
|
2525
|
+
// for replacement. Existing owners release it in their normal order.
|
|
2526
|
+
for (const id of invalidIds) {
|
|
2527
|
+
this._flights?.delete(id)
|
|
2528
|
+
}
|
|
2529
|
+
for (const controller of discardedPreloads) {
|
|
2530
|
+
controller.abort()
|
|
2504
2531
|
}
|
|
2505
|
-
this._cache = cache
|
|
2506
2532
|
|
|
2507
2533
|
this.shouldViewTransition = false
|
|
2508
2534
|
return this.load({ sync: opts?.sync })
|
|
@@ -2554,37 +2580,54 @@ export class RouterCore<
|
|
|
2554
2580
|
const cached = this._cache
|
|
2555
2581
|
const preloads = this._preloads
|
|
2556
2582
|
const filter = opts?.filter
|
|
2557
|
-
const retained = new Map<string, AnyRouteMatch>()
|
|
2558
2583
|
const discarded: Array<AnyRouteMatch> = []
|
|
2584
|
+
const discardedIds: Array<string> = []
|
|
2559
2585
|
for (const [id, match] of cached) {
|
|
2560
|
-
if (filter
|
|
2561
|
-
|
|
2562
|
-
} else {
|
|
2586
|
+
if (!filter || filter(match as MakeRouteMatchUnion<this>)) {
|
|
2587
|
+
discardedIds.push(id)
|
|
2563
2588
|
discarded.push(match)
|
|
2564
2589
|
}
|
|
2565
2590
|
}
|
|
2566
|
-
const
|
|
2567
|
-
const
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
discarded.push(...preload[0])
|
|
2572
|
-
} else {
|
|
2573
|
-
retainedPreloads.set(href, preload)
|
|
2591
|
+
const abort: Array<AbortController> = []
|
|
2592
|
+
for (const [controller, matches] of preloads ?? []) {
|
|
2593
|
+
if (!filter || matches.some(filter as any)) {
|
|
2594
|
+
abort.push(controller)
|
|
2595
|
+
discarded.push(...matches)
|
|
2574
2596
|
}
|
|
2575
2597
|
}
|
|
2576
2598
|
|
|
2577
|
-
//
|
|
2599
|
+
// Run every public filter before changing authority, then prune both maps
|
|
2600
|
+
// before releasing a public loader
|
|
2578
2601
|
// signal, whose abort listeners can synchronously reenter the router.
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
for (const
|
|
2583
|
-
|
|
2602
|
+
for (const id of discardedIds) {
|
|
2603
|
+
cached.delete(id)
|
|
2604
|
+
}
|
|
2605
|
+
for (const controller of abort) {
|
|
2606
|
+
preloads!.delete(controller)
|
|
2607
|
+
}
|
|
2608
|
+
// clearCache is a force-retirement boundary, so a final discarded lease
|
|
2609
|
+
// must not use the normal zero-owner handoff window.
|
|
2610
|
+
for (const match of discarded as Array<
|
|
2611
|
+
AnyRouteMatch & { _flight?: LoaderFlight }
|
|
2612
|
+
>) {
|
|
2613
|
+
const flight = match._flight
|
|
2614
|
+
match._flight = undefined
|
|
2615
|
+
if (flight && !--flight[2 /* leases */]) {
|
|
2616
|
+
if (this._flights?.get(match.id) === flight) {
|
|
2617
|
+
this._flights.delete(match.id)
|
|
2618
|
+
}
|
|
2619
|
+
abort.push(flight[1 /* controller */])
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
for (const controller of abort) {
|
|
2623
|
+
controller.abort()
|
|
2584
2624
|
}
|
|
2585
2625
|
}
|
|
2586
2626
|
|
|
2587
|
-
loadRouteChunk
|
|
2627
|
+
loadRouteChunk: (
|
|
2628
|
+
route: AnyRoute,
|
|
2629
|
+
componentType?: 'errorComponent' | 'notFoundComponent' | false,
|
|
2630
|
+
) => Promise<void> | undefined = loadRouteChunk
|
|
2588
2631
|
|
|
2589
2632
|
preloadRoute: PreloadRouteFn<
|
|
2590
2633
|
TRouteTree,
|