@tanstack/router-core 1.141.0 → 1.141.2
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/load-matches.cjs +22 -28
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/location.d.cts +3 -3
- package/dist/cjs/router.cjs +25 -23
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +1 -0
- package/dist/esm/load-matches.js +22 -28
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/location.d.ts +3 -3
- package/dist/esm/router.d.ts +1 -0
- package/dist/esm/router.js +25 -23
- package/dist/esm/router.js.map +1 -1
- package/package.json +1 -1
- package/src/load-matches.ts +32 -30
- package/src/location.ts +3 -3
- package/src/router.ts +27 -29
package/src/load-matches.ts
CHANGED
|
@@ -50,6 +50,29 @@ const resolvePreload = (inner: InnerLoadContext, matchId: string): boolean => {
|
|
|
50
50
|
)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Builds the accumulated context from router options and all matches up to (and optionally including) the given index.
|
|
55
|
+
* Merges __routeContext and __beforeLoadContext from each match.
|
|
56
|
+
*/
|
|
57
|
+
const buildMatchContext = (
|
|
58
|
+
inner: InnerLoadContext,
|
|
59
|
+
index: number,
|
|
60
|
+
includeCurrentMatch: boolean = true,
|
|
61
|
+
): Record<string, unknown> => {
|
|
62
|
+
const context: Record<string, unknown> = {
|
|
63
|
+
...(inner.router.options.context ?? {}),
|
|
64
|
+
}
|
|
65
|
+
const end = includeCurrentMatch ? index : index - 1
|
|
66
|
+
for (let i = 0; i <= end; i++) {
|
|
67
|
+
const innerMatch = inner.matches[i]
|
|
68
|
+
if (!innerMatch) continue
|
|
69
|
+
const m = inner.router.getMatch(innerMatch.id)
|
|
70
|
+
if (!m) continue
|
|
71
|
+
Object.assign(context, m.__routeContext, m.__beforeLoadContext)
|
|
72
|
+
}
|
|
73
|
+
return context
|
|
74
|
+
}
|
|
75
|
+
|
|
53
76
|
const _handleNotFound = (inner: InnerLoadContext, err: NotFoundError) => {
|
|
54
77
|
// Find the route that should handle the not found error
|
|
55
78
|
// First check if a specific route is requested to show the error
|
|
@@ -407,6 +430,12 @@ const executeBeforeLoad = (
|
|
|
407
430
|
|
|
408
431
|
match._nonReactive.beforeLoadPromise = createControlledPromise<void>()
|
|
409
432
|
|
|
433
|
+
// Build context from all parent matches, excluding current match's __beforeLoadContext
|
|
434
|
+
// (since we're about to execute beforeLoad for this match)
|
|
435
|
+
const context = {
|
|
436
|
+
...buildMatchContext(inner, index, false),
|
|
437
|
+
...match.__routeContext,
|
|
438
|
+
}
|
|
410
439
|
const { search, params, cause } = match
|
|
411
440
|
const preload = resolvePreload(inner, matchId)
|
|
412
441
|
const beforeLoadFnContext: BeforeLoadContextOptions<
|
|
@@ -423,12 +452,7 @@ const executeBeforeLoad = (
|
|
|
423
452
|
abortController,
|
|
424
453
|
params,
|
|
425
454
|
preload,
|
|
426
|
-
|
|
427
|
-
context: {
|
|
428
|
-
...parentMatchContext,
|
|
429
|
-
...parentMatch?.__beforeLoadContext,
|
|
430
|
-
...match.__routeContext,
|
|
431
|
-
},
|
|
455
|
+
context,
|
|
432
456
|
location: inner.location,
|
|
433
457
|
navigate: (opts: any) =>
|
|
434
458
|
inner.router.navigate({
|
|
@@ -569,19 +593,7 @@ const getLoaderContext = (
|
|
|
569
593
|
const { params, loaderDeps, abortController, cause } =
|
|
570
594
|
inner.router.getMatch(matchId)!
|
|
571
595
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
for (let i = 0; i <= index; i++) {
|
|
575
|
-
const innerMatch = inner.matches[i]
|
|
576
|
-
if (!innerMatch) continue
|
|
577
|
-
const m = inner.router.getMatch(innerMatch.id)
|
|
578
|
-
if (!m) continue
|
|
579
|
-
context = {
|
|
580
|
-
...context,
|
|
581
|
-
...(m.__routeContext ?? {}),
|
|
582
|
-
...(m.__beforeLoadContext ?? {}),
|
|
583
|
-
}
|
|
584
|
-
}
|
|
596
|
+
const context = buildMatchContext(inner, index)
|
|
585
597
|
|
|
586
598
|
const preload = resolvePreload(inner, matchId)
|
|
587
599
|
|
|
@@ -747,19 +759,9 @@ const loadRouteMatch = async (
|
|
|
747
759
|
const route = inner.router.looseRoutesById[routeId]!
|
|
748
760
|
|
|
749
761
|
const commitContext = () => {
|
|
750
|
-
const context = { ...inner.router.options.context }
|
|
751
|
-
|
|
752
|
-
for (let i = 0; i <= index; i++) {
|
|
753
|
-
const innerMatch = inner.matches[i]
|
|
754
|
-
if (!innerMatch) continue
|
|
755
|
-
const m = inner.router.getMatch(innerMatch.id)
|
|
756
|
-
if (!m) continue
|
|
757
|
-
Object.assign(context, m.__routeContext, m.__beforeLoadContext)
|
|
758
|
-
}
|
|
759
|
-
|
|
760
762
|
inner.updateMatch(matchId, (prev) => ({
|
|
761
763
|
...prev,
|
|
762
|
-
context,
|
|
764
|
+
context: buildMatchContext(inner, index),
|
|
763
765
|
}))
|
|
764
766
|
}
|
|
765
767
|
|
package/src/location.ts
CHANGED
|
@@ -38,14 +38,14 @@ export interface ParsedLocation<TSearchObj extends AnySchema = {}> {
|
|
|
38
38
|
unmaskOnReload?: boolean
|
|
39
39
|
/**
|
|
40
40
|
* @private
|
|
41
|
-
* @description The public href of the location
|
|
41
|
+
* @description The public href of the location.
|
|
42
42
|
* If a rewrite is applied, the `href` property will be the rewritten URL.
|
|
43
43
|
*/
|
|
44
44
|
publicHref: string
|
|
45
45
|
/**
|
|
46
46
|
* @private
|
|
47
|
-
* @description The full URL of the location
|
|
47
|
+
* @description The full URL of the location.
|
|
48
48
|
* @private
|
|
49
49
|
*/
|
|
50
|
-
url:
|
|
50
|
+
url: URL
|
|
51
51
|
}
|
package/src/router.ts
CHANGED
|
@@ -1176,16 +1176,14 @@ export class RouterCore<
|
|
|
1176
1176
|
|
|
1177
1177
|
const fullPath = url.href.replace(url.origin, '')
|
|
1178
1178
|
|
|
1179
|
-
const { pathname, hash } = url
|
|
1180
|
-
|
|
1181
1179
|
return {
|
|
1182
1180
|
href: fullPath,
|
|
1183
1181
|
publicHref: href,
|
|
1184
|
-
url: url
|
|
1185
|
-
pathname: decodePath(pathname),
|
|
1182
|
+
url: url,
|
|
1183
|
+
pathname: decodePath(url.pathname),
|
|
1186
1184
|
searchStr,
|
|
1187
1185
|
search: replaceEqualDeep(previousLocation?.search, parsedSearch) as any,
|
|
1188
|
-
hash: hash.split('#').reverse()[0] ?? '',
|
|
1186
|
+
hash: url.hash.split('#').reverse()[0] ?? '',
|
|
1189
1187
|
state: replaceEqualDeep(previousLocation?.state, state),
|
|
1190
1188
|
}
|
|
1191
1189
|
}
|
|
@@ -1765,7 +1763,7 @@ export class RouterCore<
|
|
|
1765
1763
|
publicHref:
|
|
1766
1764
|
rewrittenUrl.pathname + rewrittenUrl.search + rewrittenUrl.hash,
|
|
1767
1765
|
href: fullPath,
|
|
1768
|
-
url: rewrittenUrl
|
|
1766
|
+
url: rewrittenUrl,
|
|
1769
1767
|
pathname: nextPathname,
|
|
1770
1768
|
search: nextSearch,
|
|
1771
1769
|
searchStr,
|
|
@@ -1878,8 +1876,16 @@ export class RouterCore<
|
|
|
1878
1876
|
if (isSameUrl && isSameState()) {
|
|
1879
1877
|
this.load()
|
|
1880
1878
|
} else {
|
|
1881
|
-
|
|
1882
|
-
|
|
1879
|
+
let {
|
|
1880
|
+
// eslint-disable-next-line prefer-const
|
|
1881
|
+
maskedLocation,
|
|
1882
|
+
// eslint-disable-next-line prefer-const
|
|
1883
|
+
hashScrollIntoView,
|
|
1884
|
+
// don't pass url into history since it is a URL instance that cannot be serialized
|
|
1885
|
+
// eslint-disable-next-line prefer-const
|
|
1886
|
+
url: _url,
|
|
1887
|
+
...nextHistory
|
|
1888
|
+
} = next
|
|
1883
1889
|
|
|
1884
1890
|
if (maskedLocation) {
|
|
1885
1891
|
nextHistory = {
|
|
@@ -2000,7 +2006,7 @@ export class RouterCore<
|
|
|
2000
2006
|
if (reloadDocument) {
|
|
2001
2007
|
if (!href) {
|
|
2002
2008
|
const location = this.buildLocation({ to, ...rest } as any)
|
|
2003
|
-
href = location.url
|
|
2009
|
+
href = location.url.href
|
|
2004
2010
|
}
|
|
2005
2011
|
|
|
2006
2012
|
// Check blockers for external URLs unless ignoreBlocker is true
|
|
@@ -2056,24 +2062,11 @@ export class RouterCore<
|
|
|
2056
2062
|
_includeValidateSearch: true,
|
|
2057
2063
|
})
|
|
2058
2064
|
|
|
2059
|
-
// Normalize URLs for comparison to handle encoding differences
|
|
2060
|
-
// Browser history always stores encoded URLs while buildLocation may produce decoded URLs
|
|
2061
|
-
const normalizeUrl = (url: string) => {
|
|
2062
|
-
try {
|
|
2063
|
-
return encodeURI(decodeURI(url))
|
|
2064
|
-
} catch {
|
|
2065
|
-
return url
|
|
2066
|
-
}
|
|
2067
|
-
}
|
|
2068
|
-
|
|
2069
2065
|
if (
|
|
2070
|
-
|
|
2071
|
-
|
|
2066
|
+
this.latestLocation.publicHref !== nextLocation.publicHref ||
|
|
2067
|
+
nextLocation.url.origin !== this.origin
|
|
2072
2068
|
) {
|
|
2073
|
-
|
|
2074
|
-
if (this.origin && href.startsWith(this.origin)) {
|
|
2075
|
-
href = href.replace(this.origin, '') || '/'
|
|
2076
|
-
}
|
|
2069
|
+
const href = this.getParsedLocationHref(nextLocation)
|
|
2077
2070
|
|
|
2078
2071
|
throw redirect({ href })
|
|
2079
2072
|
}
|
|
@@ -2395,13 +2388,18 @@ export class RouterCore<
|
|
|
2395
2388
|
return this.load({ sync: opts?.sync })
|
|
2396
2389
|
}
|
|
2397
2390
|
|
|
2391
|
+
getParsedLocationHref = (location: ParsedLocation) => {
|
|
2392
|
+
let href = location.url.href
|
|
2393
|
+
if (this.origin && location.url.origin === this.origin) {
|
|
2394
|
+
href = href.replace(this.origin, '') || '/'
|
|
2395
|
+
}
|
|
2396
|
+
return href
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2398
2399
|
resolveRedirect = (redirect: AnyRedirect): AnyRedirect => {
|
|
2399
2400
|
if (!redirect.options.href) {
|
|
2400
2401
|
const location = this.buildLocation(redirect.options)
|
|
2401
|
-
|
|
2402
|
-
if (this.origin && href.startsWith(this.origin)) {
|
|
2403
|
-
href = href.replace(this.origin, '') || '/'
|
|
2404
|
-
}
|
|
2402
|
+
const href = this.getParsedLocationHref(location)
|
|
2405
2403
|
redirect.options.href = location.href
|
|
2406
2404
|
redirect.headers.set('Location', href)
|
|
2407
2405
|
}
|