@tanstack/react-router 1.39.8 → 1.41.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/dist/cjs/CatchBoundary.d.cts +2 -2
- package/dist/cjs/Match.cjs +238 -0
- package/dist/cjs/Match.cjs.map +1 -0
- package/dist/cjs/Match.d.cts +5 -0
- package/dist/cjs/Matches.cjs +8 -253
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +2 -11
- package/dist/cjs/RouterProvider.cjs.map +1 -1
- package/dist/cjs/RouterProvider.d.cts +3 -2
- package/dist/cjs/SafeFragment.cjs +8 -0
- package/dist/cjs/SafeFragment.cjs.map +1 -0
- package/dist/cjs/SafeFragment.d.cts +1 -0
- package/dist/cjs/ScriptOnce.cjs +28 -0
- package/dist/cjs/ScriptOnce.cjs.map +1 -0
- package/dist/cjs/ScriptOnce.d.cts +5 -0
- package/dist/cjs/Transitioner.cjs +2 -1
- package/dist/cjs/Transitioner.cjs.map +1 -1
- package/dist/cjs/awaited.cjs +14 -71
- package/dist/cjs/awaited.cjs.map +1 -1
- package/dist/cjs/awaited.d.cts +3 -6
- package/dist/cjs/defer.cjs +7 -13
- package/dist/cjs/defer.cjs.map +1 -1
- package/dist/cjs/defer.d.cts +2 -6
- package/dist/cjs/index.cjs +11 -7
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +8 -3
- package/dist/cjs/isServerSideError.cjs +22 -0
- package/dist/cjs/isServerSideError.cjs.map +1 -0
- package/dist/cjs/isServerSideError.d.cts +5 -0
- package/dist/cjs/link.cjs +8 -9
- package/dist/cjs/link.cjs.map +1 -1
- package/dist/cjs/link.d.cts +1 -0
- package/dist/cjs/matchContext.cjs +23 -0
- package/dist/cjs/matchContext.cjs.map +1 -0
- package/dist/cjs/matchContext.d.cts +2 -0
- package/dist/cjs/not-found.cjs +1 -2
- package/dist/cjs/not-found.cjs.map +1 -1
- package/dist/cjs/not-found.d.cts +2 -2
- package/dist/cjs/path.cjs +3 -6
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/qss.cjs +3 -6
- package/dist/cjs/qss.cjs.map +1 -1
- package/dist/cjs/qss.d.cts +1 -1
- package/dist/cjs/redirects.cjs.map +1 -1
- package/dist/cjs/renderRouteNotFound.cjs +22 -0
- package/dist/cjs/renderRouteNotFound.cjs.map +1 -0
- package/dist/cjs/renderRouteNotFound.d.cts +4 -0
- package/dist/cjs/root.cjs.map +1 -1
- package/dist/cjs/root.d.cts +1 -1
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/router.cjs +33 -26
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +16 -11
- package/dist/cjs/scroll-restoration.cjs +1 -2
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/useMatch.cjs +2 -2
- package/dist/cjs/useMatch.cjs.map +1 -1
- package/dist/cjs/utils.cjs +4 -3
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +3 -2
- package/dist/esm/CatchBoundary.d.ts +2 -2
- package/dist/esm/Match.d.ts +5 -0
- package/dist/esm/Match.js +221 -0
- package/dist/esm/Match.js.map +1 -0
- package/dist/esm/Matches.d.ts +2 -11
- package/dist/esm/Matches.js +5 -250
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/RouterProvider.d.ts +3 -2
- package/dist/esm/RouterProvider.js.map +1 -1
- package/dist/esm/SafeFragment.d.ts +1 -0
- package/dist/esm/SafeFragment.js +8 -0
- package/dist/esm/SafeFragment.js.map +1 -0
- package/dist/esm/ScriptOnce.d.ts +5 -0
- package/dist/esm/ScriptOnce.js +28 -0
- package/dist/esm/ScriptOnce.js.map +1 -0
- package/dist/esm/Transitioner.js +2 -1
- package/dist/esm/Transitioner.js.map +1 -1
- package/dist/esm/awaited.d.ts +3 -6
- package/dist/esm/awaited.js +16 -73
- package/dist/esm/awaited.js.map +1 -1
- package/dist/esm/defer.d.ts +2 -6
- package/dist/esm/defer.js +8 -14
- package/dist/esm/defer.js.map +1 -1
- package/dist/esm/index.d.ts +8 -3
- package/dist/esm/index.js +9 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/isServerSideError.d.ts +5 -0
- package/dist/esm/isServerSideError.js +22 -0
- package/dist/esm/isServerSideError.js.map +1 -0
- package/dist/esm/link.d.ts +1 -0
- package/dist/esm/link.js +8 -9
- package/dist/esm/link.js.map +1 -1
- package/dist/esm/matchContext.d.ts +2 -0
- package/dist/esm/matchContext.js +6 -0
- package/dist/esm/matchContext.js.map +1 -0
- package/dist/esm/not-found.d.ts +2 -2
- package/dist/esm/not-found.js +1 -2
- package/dist/esm/not-found.js.map +1 -1
- package/dist/esm/path.js +3 -6
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/qss.d.ts +1 -1
- package/dist/esm/qss.js +3 -6
- package/dist/esm/qss.js.map +1 -1
- package/dist/esm/redirects.js.map +1 -1
- package/dist/esm/renderRouteNotFound.d.ts +4 -0
- package/dist/esm/renderRouteNotFound.js +22 -0
- package/dist/esm/renderRouteNotFound.js.map +1 -0
- package/dist/esm/root.d.ts +1 -1
- package/dist/esm/root.js.map +1 -1
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +16 -11
- package/dist/esm/router.js +33 -26
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.js +1 -2
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/useMatch.js +1 -1
- package/dist/esm/useMatch.js.map +1 -1
- package/dist/esm/utils.d.ts +3 -2
- package/dist/esm/utils.js +4 -3
- package/dist/esm/utils.js.map +1 -1
- package/package.json +6 -5
- package/src/Match.tsx +296 -0
- package/src/Matches.tsx +4 -333
- package/src/RouterProvider.tsx +2 -1
- package/src/SafeFragment.tsx +5 -0
- package/src/ScriptOnce.tsx +27 -0
- package/src/Transitioner.tsx +1 -1
- package/src/awaited.tsx +17 -89
- package/src/defer.ts +9 -26
- package/src/index.tsx +7 -13
- package/src/isServerSideError.tsx +23 -0
- package/src/link.tsx +5 -0
- package/src/matchContext.tsx +3 -0
- package/src/not-found.tsx +1 -1
- package/src/qss.ts +5 -6
- package/src/redirects.ts +0 -1
- package/src/renderRouteNotFound.tsx +28 -0
- package/src/root.ts +1 -1
- package/src/route.ts +1 -1
- package/src/router.ts +54 -39
- package/src/useMatch.tsx +1 -1
- package/src/utils.ts +11 -9
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function isServerSideError(error: unknown): error is {
|
|
2
|
+
__isServerError: true
|
|
3
|
+
data: Record<string, any>
|
|
4
|
+
} {
|
|
5
|
+
if (!(typeof error === 'object' && error && 'data' in error)) return false
|
|
6
|
+
if (!('__isServerError' in error && error.__isServerError)) return false
|
|
7
|
+
if (!(typeof error.data === 'object' && error.data)) return false
|
|
8
|
+
|
|
9
|
+
return error.__isServerError === true
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function defaultDeserializeError(serializedData: Record<string, any>) {
|
|
13
|
+
if ('name' in serializedData && 'message' in serializedData) {
|
|
14
|
+
const error = new Error(serializedData.message)
|
|
15
|
+
error.name = serializedData.name
|
|
16
|
+
if (process.env.NODE_ENV === 'development') {
|
|
17
|
+
error.stack = serializedData.stack
|
|
18
|
+
}
|
|
19
|
+
return error
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return serializedData.data
|
|
23
|
+
}
|
package/src/link.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
1
3
|
import * as React from 'react'
|
|
2
4
|
import { flushSync } from 'react-dom'
|
|
3
5
|
import { useMatch } from './useMatch'
|
|
@@ -183,6 +185,7 @@ export interface NavigateOptionProps {
|
|
|
183
185
|
startTransition?: boolean
|
|
184
186
|
// if set to `true`, the router will wrap the resulting navigation in a document.startViewTransition() call.
|
|
185
187
|
viewTransition?: boolean
|
|
188
|
+
ignoreBlocker?: boolean
|
|
186
189
|
}
|
|
187
190
|
|
|
188
191
|
export type ToOptions<
|
|
@@ -572,6 +575,7 @@ export function useLinkProps<
|
|
|
572
575
|
onMouseEnter,
|
|
573
576
|
onMouseLeave,
|
|
574
577
|
onTouchStart,
|
|
578
|
+
ignoreBlocker,
|
|
575
579
|
...rest
|
|
576
580
|
} = options
|
|
577
581
|
|
|
@@ -669,6 +673,7 @@ export function useLinkProps<
|
|
|
669
673
|
resetScroll,
|
|
670
674
|
startTransition,
|
|
671
675
|
viewTransition,
|
|
676
|
+
ignoreBlocker,
|
|
672
677
|
})
|
|
673
678
|
}
|
|
674
679
|
}
|
package/src/not-found.tsx
CHANGED
package/src/qss.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
|
|
3
1
|
// qss has been slightly modified and inlined here for our use cases (and compression's sake). We've included it as a hard dependency for MIT license attribution.
|
|
4
2
|
|
|
5
3
|
/**
|
|
@@ -13,7 +11,7 @@
|
|
|
13
11
|
* // Expected output: "token=foo&key=value"
|
|
14
12
|
* ```
|
|
15
13
|
*/
|
|
16
|
-
export function encode(obj, pfx?: string) {
|
|
14
|
+
export function encode(obj: any, pfx?: string) {
|
|
17
15
|
let k,
|
|
18
16
|
i,
|
|
19
17
|
tmp,
|
|
@@ -44,7 +42,7 @@ export function encode(obj, pfx?: string) {
|
|
|
44
42
|
* // Example input: toValue("123")
|
|
45
43
|
* // Expected output: 123
|
|
46
44
|
*/
|
|
47
|
-
function toValue(mix) {
|
|
45
|
+
function toValue(mix: any) {
|
|
48
46
|
if (!mix) return ''
|
|
49
47
|
const str = decodeURIComponent(mix)
|
|
50
48
|
if (str === 'false') return false
|
|
@@ -61,9 +59,9 @@ function toValue(mix) {
|
|
|
61
59
|
* // Example input: decode("token=foo&key=value")
|
|
62
60
|
* // Expected output: { "token": "foo", "key": "value" }
|
|
63
61
|
*/
|
|
64
|
-
export function decode(str, pfx?: string) {
|
|
62
|
+
export function decode(str: any, pfx?: string) {
|
|
65
63
|
let tmp, k
|
|
66
|
-
const out = {},
|
|
64
|
+
const out: any = {},
|
|
67
65
|
arr = (pfx ? str.substr(pfx.length) : str).split('&')
|
|
68
66
|
|
|
69
67
|
while ((tmp = arr.shift())) {
|
|
@@ -72,6 +70,7 @@ export function decode(str, pfx?: string) {
|
|
|
72
70
|
k = tmp.slice(0, equalIndex)
|
|
73
71
|
const value = tmp.slice(equalIndex + 1)
|
|
74
72
|
if (out[k] !== void 0) {
|
|
73
|
+
// @ts-expect-error
|
|
75
74
|
out[k] = [].concat(out[k], toValue(value))
|
|
76
75
|
} else {
|
|
77
76
|
out[k] = toValue(value)
|
package/src/redirects.ts
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import warning from 'tiny-warning'
|
|
3
|
+
import { DefaultGlobalNotFound } from './not-found'
|
|
4
|
+
import { type AnyRouter } from './router'
|
|
5
|
+
import { type AnyRoute } from './route'
|
|
6
|
+
|
|
7
|
+
export function renderRouteNotFound(
|
|
8
|
+
router: AnyRouter,
|
|
9
|
+
route: AnyRoute,
|
|
10
|
+
data: any,
|
|
11
|
+
) {
|
|
12
|
+
if (!route.options.notFoundComponent) {
|
|
13
|
+
if (router.options.defaultNotFoundComponent) {
|
|
14
|
+
return <router.options.defaultNotFoundComponent data={data} />
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (process.env.NODE_ENV === 'development') {
|
|
18
|
+
warning(
|
|
19
|
+
route.options.notFoundComponent,
|
|
20
|
+
`A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<div>Not Found<div>)`,
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return <DefaultGlobalNotFound />
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return <route.options.notFoundComponent data={data} />
|
|
28
|
+
}
|
package/src/root.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const rootRouteId = '__root__'
|
|
1
|
+
export const rootRouteId = '__root__'
|
|
2
2
|
export type RootRouteId = typeof rootRouteId
|
package/src/route.ts
CHANGED
|
@@ -706,7 +706,7 @@ export class Route<
|
|
|
706
706
|
|
|
707
707
|
const isRoot = !options?.path && !options?.id
|
|
708
708
|
|
|
709
|
-
// eslint-disable-next-line
|
|
709
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
710
710
|
this.parentRoute = this.options?.getParentRoute?.()
|
|
711
711
|
|
|
712
712
|
if (isRoot) {
|
package/src/router.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { createBrowserHistory, createMemoryHistory } from '@tanstack/history'
|
|
2
2
|
import { Store } from '@tanstack/react-store'
|
|
3
3
|
import invariant from 'tiny-invariant'
|
|
4
|
-
import warning from 'tiny-warning'
|
|
5
4
|
import { rootRouteId } from './root'
|
|
6
5
|
import { defaultParseSearch, defaultStringifySearch } from './searchParams'
|
|
7
6
|
import {
|
|
@@ -44,6 +43,7 @@ import type {
|
|
|
44
43
|
LoaderFnContext,
|
|
45
44
|
NotFoundRouteComponent,
|
|
46
45
|
RootRoute,
|
|
46
|
+
RouteComponent,
|
|
47
47
|
RouteMask,
|
|
48
48
|
} from './route'
|
|
49
49
|
import type {
|
|
@@ -57,22 +57,18 @@ import type {
|
|
|
57
57
|
ControlledPromise,
|
|
58
58
|
NonNullableUpdater,
|
|
59
59
|
PickAsRequired,
|
|
60
|
-
Timeout,
|
|
61
60
|
Updater,
|
|
62
61
|
} from './utils'
|
|
63
|
-
import type { RouteComponent } from './route'
|
|
64
62
|
import type {
|
|
65
63
|
AnyRouteMatch,
|
|
66
64
|
MakeRouteMatch,
|
|
67
65
|
MatchRouteOptions,
|
|
68
|
-
RouteMatch,
|
|
69
66
|
} from './Matches'
|
|
70
67
|
import type { ParsedLocation } from './location'
|
|
71
68
|
import type { SearchParser, SearchSerializer } from './searchParams'
|
|
72
69
|
import type {
|
|
73
70
|
BuildLocationFn,
|
|
74
71
|
CommitLocationOptions,
|
|
75
|
-
InjectedHtmlEntry,
|
|
76
72
|
NavigateFn,
|
|
77
73
|
} from './RouterProvider'
|
|
78
74
|
|
|
@@ -82,13 +78,16 @@ import type { NotFoundError } from './not-found'
|
|
|
82
78
|
import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
|
|
83
79
|
import type { NoInfer } from '@tanstack/react-store'
|
|
84
80
|
import type { DeferredPromiseState } from './defer'
|
|
85
|
-
import type { ErrorInfo } from 'react'
|
|
86
81
|
|
|
87
82
|
//
|
|
88
83
|
|
|
89
84
|
declare global {
|
|
90
85
|
interface Window {
|
|
91
|
-
|
|
86
|
+
__TSR__?: {
|
|
87
|
+
matches: Array<any>
|
|
88
|
+
cleanScripts: () => void
|
|
89
|
+
dehydrated?: any
|
|
90
|
+
}
|
|
92
91
|
__TSR_ROUTER_CONTEXT__?: React.Context<Router<any, any>>
|
|
93
92
|
}
|
|
94
93
|
}
|
|
@@ -237,7 +236,7 @@ export interface RouterOptions<
|
|
|
237
236
|
* @link [API Docs](https://tanstack.com/router/latest/docs/framework/react/api/router/RouterOptionsType#defaultoncatch-property)
|
|
238
237
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#handling-errors-with-routeoptionsoncatch)
|
|
239
238
|
*/
|
|
240
|
-
defaultOnCatch?: (error: Error, errorInfo: ErrorInfo) => void
|
|
239
|
+
defaultOnCatch?: (error: Error, errorInfo: React.ErrorInfo) => void
|
|
241
240
|
defaultViewTransition?: boolean
|
|
242
241
|
/**
|
|
243
242
|
* @link [Guide](https://tanstack.com/router/latest/docs/framework/react/guide/not-found-errors#the-notfoundmode-option)
|
|
@@ -508,6 +507,20 @@ export class Router<
|
|
|
508
507
|
dehydratedData?: TDehydrated
|
|
509
508
|
viewTransitionPromise?: ControlledPromise<true>
|
|
510
509
|
manifest?: Manifest
|
|
510
|
+
AfterEachMatch?: (props: {
|
|
511
|
+
match: Pick<
|
|
512
|
+
AnyRouteMatch,
|
|
513
|
+
'id' | 'status' | 'error' | 'loadPromise' | 'minPendingPromise'
|
|
514
|
+
>
|
|
515
|
+
matchIndex: number
|
|
516
|
+
}) => any
|
|
517
|
+
serializeLoaderData?: (
|
|
518
|
+
data: any,
|
|
519
|
+
ctx: {
|
|
520
|
+
router: AnyRouter
|
|
521
|
+
match: AnyRouteMatch
|
|
522
|
+
},
|
|
523
|
+
) => any
|
|
511
524
|
|
|
512
525
|
// Must build in constructor
|
|
513
526
|
__store!: Store<RouterState<TRouteTree>>
|
|
@@ -603,7 +616,7 @@ export class Router<
|
|
|
603
616
|
}
|
|
604
617
|
|
|
605
618
|
if (
|
|
606
|
-
// eslint-disable-next-line
|
|
619
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
607
620
|
!this.history ||
|
|
608
621
|
(this.options.history && this.options.history !== this.history)
|
|
609
622
|
) {
|
|
@@ -622,7 +635,7 @@ export class Router<
|
|
|
622
635
|
this.buildRouteTree()
|
|
623
636
|
}
|
|
624
637
|
|
|
625
|
-
// eslint-disable-next-line
|
|
638
|
+
// eslint-disable-next-line ts/no-unnecessary-condition
|
|
626
639
|
if (!this.__store) {
|
|
627
640
|
this.__store = new Store(getInitialRouterState(this.latestLocation), {
|
|
628
641
|
onUpdate: () => {
|
|
@@ -1042,6 +1055,7 @@ export class Router<
|
|
|
1042
1055
|
|
|
1043
1056
|
match = {
|
|
1044
1057
|
id: matchId,
|
|
1058
|
+
index,
|
|
1045
1059
|
routeId: route.id,
|
|
1046
1060
|
params: routeParams,
|
|
1047
1061
|
pathname: joinPaths([this.basepath, interpolatedPath]),
|
|
@@ -1332,6 +1346,7 @@ export class Router<
|
|
|
1332
1346
|
commitLocation = async ({
|
|
1333
1347
|
startTransition,
|
|
1334
1348
|
viewTransition,
|
|
1349
|
+
ignoreBlocker,
|
|
1335
1350
|
...next
|
|
1336
1351
|
}: ParsedLocation & CommitLocationOptions) => {
|
|
1337
1352
|
const isSameState = () => {
|
|
@@ -1387,6 +1402,7 @@ export class Router<
|
|
|
1387
1402
|
this.history[next.replace ? 'replace' : 'push'](
|
|
1388
1403
|
nextHistory.href,
|
|
1389
1404
|
nextHistory.state,
|
|
1405
|
+
{ ignoreBlocker },
|
|
1390
1406
|
)
|
|
1391
1407
|
}
|
|
1392
1408
|
|
|
@@ -1400,6 +1416,7 @@ export class Router<
|
|
|
1400
1416
|
resetScroll,
|
|
1401
1417
|
startTransition,
|
|
1402
1418
|
viewTransition,
|
|
1419
|
+
ignoreBlocker,
|
|
1403
1420
|
...rest
|
|
1404
1421
|
}: BuildNextOptions & CommitLocationOptions = {}) => {
|
|
1405
1422
|
const location = this.buildLocation(rest as any)
|
|
@@ -1409,6 +1426,7 @@ export class Router<
|
|
|
1409
1426
|
viewTransition,
|
|
1410
1427
|
replace,
|
|
1411
1428
|
resetScroll,
|
|
1429
|
+
ignoreBlocker,
|
|
1412
1430
|
})
|
|
1413
1431
|
}
|
|
1414
1432
|
|
|
@@ -1954,7 +1972,13 @@ export class Router<
|
|
|
1954
1972
|
)
|
|
1955
1973
|
}
|
|
1956
1974
|
|
|
1957
|
-
|
|
1975
|
+
let loaderData = await loaderPromise
|
|
1976
|
+
if (this.serializeLoaderData) {
|
|
1977
|
+
loaderData = this.serializeLoaderData(loaderData, {
|
|
1978
|
+
router: this,
|
|
1979
|
+
match,
|
|
1980
|
+
})
|
|
1981
|
+
}
|
|
1958
1982
|
checkLatest()
|
|
1959
1983
|
|
|
1960
1984
|
handleRedirectAndNotFound(match, loaderData)
|
|
@@ -2284,38 +2308,29 @@ export class Router<
|
|
|
2284
2308
|
return match
|
|
2285
2309
|
}
|
|
2286
2310
|
|
|
2287
|
-
// We use a token -> weak map to keep track of deferred promises
|
|
2288
|
-
// that are registered on the server and need to be resolved
|
|
2289
|
-
registeredDeferredsIds = new Map<string, {}>()
|
|
2290
|
-
registeredDeferreds = new WeakMap<{}, DeferredPromiseState<any>>()
|
|
2291
|
-
|
|
2292
|
-
getDeferred = (uid: string) => {
|
|
2293
|
-
const token = this.registeredDeferredsIds.get(uid)
|
|
2294
|
-
|
|
2295
|
-
if (!token) {
|
|
2296
|
-
return undefined
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
return this.registeredDeferreds.get(token)
|
|
2300
|
-
}
|
|
2301
|
-
|
|
2302
2311
|
dehydrate = (): DehydratedRouter => {
|
|
2303
2312
|
const pickError =
|
|
2304
2313
|
this.options.errorSerializer?.serialize ?? defaultSerializeError
|
|
2305
2314
|
|
|
2306
2315
|
return {
|
|
2307
2316
|
state: {
|
|
2308
|
-
dehydratedMatches: this.state.matches.map((d) =>
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2317
|
+
dehydratedMatches: this.state.matches.map((d) => {
|
|
2318
|
+
return {
|
|
2319
|
+
...pick(d, ['id', 'status', 'updatedAt']),
|
|
2320
|
+
// If an error occurs server-side during SSRing,
|
|
2321
|
+
// send a small subset of the error to the client
|
|
2322
|
+
error: d.error
|
|
2323
|
+
? {
|
|
2324
|
+
data: pickError(d.error),
|
|
2325
|
+
__isServerError: true,
|
|
2326
|
+
}
|
|
2327
|
+
: undefined,
|
|
2328
|
+
// NOTE: We don't send the loader data here, because
|
|
2329
|
+
// there is a potential that it needs to be streamed.
|
|
2330
|
+
// Instead, we render it next to the route match in the HTML
|
|
2331
|
+
// which gives us the potential to stream it via suspense.
|
|
2332
|
+
}
|
|
2333
|
+
}),
|
|
2319
2334
|
},
|
|
2320
2335
|
manifest: this.manifest,
|
|
2321
2336
|
}
|
|
@@ -2325,12 +2340,12 @@ export class Router<
|
|
|
2325
2340
|
let _ctx = __do_not_use_server_ctx
|
|
2326
2341
|
// Client hydrates from window
|
|
2327
2342
|
if (typeof document !== 'undefined') {
|
|
2328
|
-
_ctx = window.
|
|
2343
|
+
_ctx = window.__TSR__?.dehydrated
|
|
2329
2344
|
}
|
|
2330
2345
|
|
|
2331
2346
|
invariant(
|
|
2332
2347
|
_ctx,
|
|
2333
|
-
'Expected to find a
|
|
2348
|
+
'Expected to find a dehydrated data on window.__TSR__.dehydrated... but we did not. Please file an issue!',
|
|
2334
2349
|
)
|
|
2335
2350
|
|
|
2336
2351
|
const ctx = this.options.transformer.parse(_ctx) as HydrationCtx
|
package/src/useMatch.tsx
CHANGED
|
@@ -3,7 +3,7 @@ import invariant from 'tiny-invariant'
|
|
|
3
3
|
import { useRouterState } from './useRouterState'
|
|
4
4
|
import { type RegisteredRouter } from './router'
|
|
5
5
|
import { type AnyRoute } from './route'
|
|
6
|
-
import { matchContext } from './
|
|
6
|
+
import { matchContext } from './matchContext'
|
|
7
7
|
import type { MakeRouteMatch } from './Matches'
|
|
8
8
|
import type { RouteIds } from './routeInfo'
|
|
9
9
|
import type { StrictOrFrom } from './utils'
|
package/src/utils.ts
CHANGED
|
@@ -40,7 +40,7 @@ export type MakeDifferenceOptional<TLeft, TRight> = Omit<
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// from https://stackoverflow.com/a/53955431
|
|
43
|
-
// eslint-disable-next-line
|
|
43
|
+
// eslint-disable-next-line ts/naming-convention
|
|
44
44
|
export type IsUnion<T, U extends T = T> = (
|
|
45
45
|
T extends any ? (U extends T ? false : true) : never
|
|
46
46
|
) extends false
|
|
@@ -152,7 +152,7 @@ export function replaceEqualDeep<T>(prev: any, _next: T): T {
|
|
|
152
152
|
let equalItems = 0
|
|
153
153
|
|
|
154
154
|
for (let i = 0; i < nextSize; i++) {
|
|
155
|
-
const key = array ? i : nextItems[i]
|
|
155
|
+
const key = array ? i : (nextItems[i] as any)
|
|
156
156
|
if (
|
|
157
157
|
((!array && prevItems.includes(key)) || array) &&
|
|
158
158
|
prev[key] === undefined &&
|
|
@@ -205,7 +205,7 @@ function hasObjectPrototype(o: any) {
|
|
|
205
205
|
return Object.prototype.toString.call(o) === '[object Object]'
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
export function isPlainArray(value: unknown) {
|
|
208
|
+
export function isPlainArray(value: unknown): value is Array<unknown> {
|
|
209
209
|
return Array.isArray(value) && value.length === Object.keys(value).length
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -315,23 +315,25 @@ export type ControlledPromise<T> = Promise<T> & {
|
|
|
315
315
|
resolve: (value: T) => void
|
|
316
316
|
reject: (value: any) => void
|
|
317
317
|
status: 'pending' | 'resolved' | 'rejected'
|
|
318
|
+
value?: T
|
|
318
319
|
}
|
|
319
320
|
|
|
320
|
-
export function createControlledPromise<T>(onResolve?: () => void) {
|
|
321
|
-
let resolveLoadPromise!: () => void
|
|
321
|
+
export function createControlledPromise<T>(onResolve?: (value: T) => void) {
|
|
322
|
+
let resolveLoadPromise!: (value: T) => void
|
|
322
323
|
let rejectLoadPromise!: (value: any) => void
|
|
323
324
|
|
|
324
|
-
const controlledPromise = new Promise<
|
|
325
|
+
const controlledPromise = new Promise<T>((resolve, reject) => {
|
|
325
326
|
resolveLoadPromise = resolve
|
|
326
327
|
rejectLoadPromise = reject
|
|
327
328
|
}) as ControlledPromise<T>
|
|
328
329
|
|
|
329
330
|
controlledPromise.status = 'pending'
|
|
330
331
|
|
|
331
|
-
controlledPromise.resolve = () => {
|
|
332
|
+
controlledPromise.resolve = (value: T) => {
|
|
332
333
|
controlledPromise.status = 'resolved'
|
|
333
|
-
|
|
334
|
-
|
|
334
|
+
controlledPromise.value = value
|
|
335
|
+
resolveLoadPromise(value)
|
|
336
|
+
onResolve?.(value)
|
|
335
337
|
}
|
|
336
338
|
|
|
337
339
|
controlledPromise.reject = (e) => {
|