@tanstack/react-router 1.81.4 → 1.81.6
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/fileRoute.cjs.map +1 -1
- package/dist/cjs/fileRoute.d.cts +3 -2
- package/dist/cjs/index.d.cts +3 -2
- package/dist/cjs/location.d.cts +2 -2
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +14 -51
- package/dist/cjs/routeInfo.d.cts +6 -6
- package/dist/cjs/router.cjs +26 -5
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +3 -2
- package/dist/cjs/searchParams.cjs.map +1 -1
- package/dist/cjs/searchParams.d.cts +3 -3
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +17 -5
- package/dist/cjs/validators.d.cts +49 -0
- package/dist/esm/fileRoute.d.ts +3 -2
- package/dist/esm/fileRoute.js.map +1 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/location.d.ts +2 -2
- package/dist/esm/route.d.ts +14 -51
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/routeInfo.d.ts +6 -6
- package/dist/esm/router.d.ts +3 -2
- package/dist/esm/router.js +26 -5
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/searchParams.d.ts +3 -3
- package/dist/esm/searchParams.js.map +1 -1
- package/dist/esm/utils.d.ts +17 -5
- package/dist/esm/utils.js.map +1 -1
- package/dist/esm/validators.d.ts +49 -0
- package/package.json +3 -3
- package/src/fileRoute.ts +2 -2
- package/src/index.tsx +18 -15
- package/src/location.ts +2 -2
- package/src/route.ts +32 -79
- package/src/routeInfo.ts +6 -6
- package/src/router.ts +31 -13
- package/src/searchParams.ts +2 -2
- package/src/utils.ts +38 -8
- package/src/validators.ts +106 -0
package/src/router.ts
CHANGED
|
@@ -42,8 +42,6 @@ import type {
|
|
|
42
42
|
AnyContext,
|
|
43
43
|
AnyRoute,
|
|
44
44
|
AnyRouteWithContext,
|
|
45
|
-
AnySearchSchema,
|
|
46
|
-
AnySearchValidator,
|
|
47
45
|
BeforeLoadContextOptions,
|
|
48
46
|
ErrorRouteComponent,
|
|
49
47
|
LoaderFnContext,
|
|
@@ -84,6 +82,7 @@ import type { AnyRedirect, ResolvedRedirect } from './redirects'
|
|
|
84
82
|
import type { NotFoundError } from './not-found'
|
|
85
83
|
import type { NavigateOptions, ResolveRelativePath, ToOptions } from './link'
|
|
86
84
|
import type { RouterTransformer } from './transformer'
|
|
85
|
+
import type { AnySchema, AnyValidator } from './validators'
|
|
87
86
|
|
|
88
87
|
declare global {
|
|
89
88
|
interface Window {
|
|
@@ -579,10 +578,7 @@ function routeNeedsPreload(route: AnyRoute) {
|
|
|
579
578
|
return false
|
|
580
579
|
}
|
|
581
580
|
|
|
582
|
-
function validateSearch(
|
|
583
|
-
validateSearch: AnySearchValidator,
|
|
584
|
-
input: unknown,
|
|
585
|
-
): unknown {
|
|
581
|
+
function validateSearch(validateSearch: AnyValidator, input: unknown): unknown {
|
|
586
582
|
if (validateSearch == null) return {}
|
|
587
583
|
|
|
588
584
|
if ('~standard' in validateSearch) {
|
|
@@ -1075,7 +1071,7 @@ export class Router<
|
|
|
1075
1071
|
*/
|
|
1076
1072
|
public matchRoutes(
|
|
1077
1073
|
pathname: string,
|
|
1078
|
-
locationSearch:
|
|
1074
|
+
locationSearch: AnySchema,
|
|
1079
1075
|
opts?: MatchRoutesOpts,
|
|
1080
1076
|
): Array<AnyRouteMatch>
|
|
1081
1077
|
public matchRoutes(
|
|
@@ -1085,7 +1081,7 @@ export class Router<
|
|
|
1085
1081
|
|
|
1086
1082
|
public matchRoutes(
|
|
1087
1083
|
pathnameOrNext: string | ParsedLocation,
|
|
1088
|
-
locationSearchOrOpts?:
|
|
1084
|
+
locationSearchOrOpts?: AnySchema | MatchRoutesOpts,
|
|
1089
1085
|
opts?: MatchRoutesOpts,
|
|
1090
1086
|
) {
|
|
1091
1087
|
if (typeof pathnameOrNext === 'string') {
|
|
@@ -1514,8 +1510,8 @@ export class Router<
|
|
|
1514
1510
|
})
|
|
1515
1511
|
|
|
1516
1512
|
let search = fromSearch
|
|
1517
|
-
if (opts._includeValidateSearch) {
|
|
1518
|
-
let validatedSearch =
|
|
1513
|
+
if (opts._includeValidateSearch && this.options.search?.strict) {
|
|
1514
|
+
let validatedSearch = {}
|
|
1519
1515
|
matchedRoutesResult?.matchedRoutes.forEach((route) => {
|
|
1520
1516
|
try {
|
|
1521
1517
|
if (route.options.validateSearch) {
|
|
@@ -1538,10 +1534,10 @@ export class Router<
|
|
|
1538
1534
|
const allMiddlewares =
|
|
1539
1535
|
matchedRoutesResult?.matchedRoutes.reduce(
|
|
1540
1536
|
(acc, route) => {
|
|
1541
|
-
|
|
1537
|
+
const middlewares: Array<SearchMiddleware<any>> = []
|
|
1542
1538
|
if ('search' in route.options) {
|
|
1543
1539
|
if (route.options.search?.middlewares) {
|
|
1544
|
-
middlewares
|
|
1540
|
+
middlewares.push(...route.options.search.middlewares)
|
|
1545
1541
|
}
|
|
1546
1542
|
}
|
|
1547
1543
|
// TODO remove preSearchFilters and postSearchFilters in v2
|
|
@@ -1575,7 +1571,25 @@ export class Router<
|
|
|
1575
1571
|
}
|
|
1576
1572
|
return result
|
|
1577
1573
|
}
|
|
1578
|
-
middlewares
|
|
1574
|
+
middlewares.push(legacyMiddleware)
|
|
1575
|
+
}
|
|
1576
|
+
if (opts._includeValidateSearch && route.options.validateSearch) {
|
|
1577
|
+
const validate: SearchMiddleware<any> = ({ search, next }) => {
|
|
1578
|
+
try {
|
|
1579
|
+
const result = next(search)
|
|
1580
|
+
const validatedSearch = {
|
|
1581
|
+
...result,
|
|
1582
|
+
...(validateSearch(
|
|
1583
|
+
route.options.validateSearch,
|
|
1584
|
+
result,
|
|
1585
|
+
) ?? {}),
|
|
1586
|
+
}
|
|
1587
|
+
return validatedSearch
|
|
1588
|
+
} catch (e) {
|
|
1589
|
+
// ignore errors here because they are already handled in matchRoutes
|
|
1590
|
+
}
|
|
1591
|
+
}
|
|
1592
|
+
middlewares.push(validate)
|
|
1579
1593
|
}
|
|
1580
1594
|
return acc.concat(middlewares)
|
|
1581
1595
|
},
|
|
@@ -2542,6 +2556,10 @@ export class Router<
|
|
|
2542
2556
|
// to be preloaded before we resolve the match
|
|
2543
2557
|
await route._componentsPromise
|
|
2544
2558
|
} catch (err) {
|
|
2559
|
+
updateMatch(matchId, (prev) => ({
|
|
2560
|
+
...prev,
|
|
2561
|
+
loaderPromise: undefined,
|
|
2562
|
+
}))
|
|
2545
2563
|
handleRedirectAndNotFound(this.getMatch(matchId)!, err)
|
|
2546
2564
|
}
|
|
2547
2565
|
}
|
package/src/searchParams.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { decode, encode } from './qss'
|
|
2
|
-
import type {
|
|
2
|
+
import type { AnySchema } from './validators'
|
|
3
3
|
|
|
4
4
|
export const defaultParseSearch = parseSearchWith(JSON.parse)
|
|
5
5
|
export const defaultStringifySearch = stringifySearchWith(
|
|
@@ -8,7 +8,7 @@ export const defaultStringifySearch = stringifySearchWith(
|
|
|
8
8
|
)
|
|
9
9
|
|
|
10
10
|
export function parseSearchWith(parser: (str: string) => any) {
|
|
11
|
-
return (searchStr: string):
|
|
11
|
+
return (searchStr: string): AnySchema => {
|
|
12
12
|
if (searchStr.substring(0, 1) === '?') {
|
|
13
13
|
searchStr = searchStr.substring(1)
|
|
14
14
|
}
|
package/src/utils.ts
CHANGED
|
@@ -72,12 +72,12 @@ export type NonNullableUpdater<TPrevious, TResult = TPrevious> =
|
|
|
72
72
|
| TResult
|
|
73
73
|
| ((prev: TPrevious) => TResult)
|
|
74
74
|
|
|
75
|
-
export type
|
|
75
|
+
export type ExtractObjects<TUnion> = TUnion extends MergeAllPrimitive
|
|
76
76
|
? never
|
|
77
77
|
: TUnion
|
|
78
78
|
|
|
79
|
-
export type
|
|
80
|
-
|
|
79
|
+
export type PartialMergeAllObject<TUnion> =
|
|
80
|
+
ExtractObjects<TUnion> extends infer TObj
|
|
81
81
|
? {
|
|
82
82
|
[TKey in TObj extends any ? keyof TObj : never]?: TObj extends any
|
|
83
83
|
? TKey extends keyof TObj
|
|
@@ -87,23 +87,53 @@ export type MergeUnionObject<TUnion> =
|
|
|
87
87
|
}
|
|
88
88
|
: never
|
|
89
89
|
|
|
90
|
-
export type
|
|
90
|
+
export type MergeAllPrimitive =
|
|
91
91
|
| ReadonlyArray<any>
|
|
92
92
|
| number
|
|
93
93
|
| string
|
|
94
94
|
| bigint
|
|
95
95
|
| boolean
|
|
96
96
|
| symbol
|
|
97
|
+
| undefined
|
|
98
|
+
| null
|
|
97
99
|
|
|
98
|
-
export type
|
|
100
|
+
export type ExtractPrimitives<TUnion> = TUnion extends MergeAllPrimitive
|
|
99
101
|
? TUnion
|
|
100
102
|
: TUnion extends object
|
|
101
103
|
? never
|
|
102
104
|
: TUnion
|
|
103
105
|
|
|
104
|
-
export type
|
|
105
|
-
|
|
|
106
|
-
|
|
|
106
|
+
export type PartialMergeAll<TUnion> =
|
|
107
|
+
| ExtractPrimitives<TUnion>
|
|
108
|
+
| PartialMergeAllObject<TUnion>
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* To be added to router types
|
|
112
|
+
*/
|
|
113
|
+
export type UnionToIntersection<T> = (
|
|
114
|
+
T extends any ? (arg: T) => any : never
|
|
115
|
+
) extends (arg: infer T) => any
|
|
116
|
+
? T
|
|
117
|
+
: never
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Merges everything in a union into one object.
|
|
121
|
+
* This mapped type is homomorphic which means it preserves stuff! :)
|
|
122
|
+
*/
|
|
123
|
+
export type MergeAllObjects<
|
|
124
|
+
TUnion,
|
|
125
|
+
TIntersected = UnionToIntersection<ExtractObjects<TUnion>>,
|
|
126
|
+
> = [keyof TIntersected] extends [never]
|
|
127
|
+
? never
|
|
128
|
+
: {
|
|
129
|
+
[TKey in keyof TIntersected]: TUnion extends any
|
|
130
|
+
? TUnion[TKey & keyof TUnion]
|
|
131
|
+
: never
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type MergeAll<TUnion> =
|
|
135
|
+
| MergeAllObjects<TUnion>
|
|
136
|
+
| ExtractPrimitives<TUnion>
|
|
107
137
|
|
|
108
138
|
export type Constrain<T, TConstraint, TDefault = TConstraint> =
|
|
109
139
|
| (T extends TConstraint ? T : never)
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { SearchSchemaInput } from './route'
|
|
2
|
+
|
|
3
|
+
export interface StandardSchemaValidatorProps<TInput, TOutput> {
|
|
4
|
+
readonly types?: StandardSchemaValidatorTypes<TInput, TOutput> | undefined
|
|
5
|
+
readonly validate: AnyStandardSchemaValidate
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface StandardSchemaValidator<TInput, TOutput> {
|
|
9
|
+
readonly '~standard': StandardSchemaValidatorProps<TInput, TOutput>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type AnyStandardSchemaValidator = StandardSchemaValidator<any, any>
|
|
13
|
+
|
|
14
|
+
export interface StandardSchemaValidatorTypes<TInput, TOutput> {
|
|
15
|
+
readonly input: TInput
|
|
16
|
+
readonly output: TOutput
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface AnyStandardSchemaValidateSuccess {
|
|
20
|
+
readonly value: any
|
|
21
|
+
readonly issues?: undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface AnyStandardSchemaValidateFailure {
|
|
25
|
+
readonly issues: ReadonlyArray<AnyStandardSchemaValidateIssue>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AnyStandardSchemaValidateIssue {
|
|
29
|
+
readonly message: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface AnyStandardSchemaValidateInput {
|
|
33
|
+
readonly value: any
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type AnyStandardSchemaValidate = (
|
|
37
|
+
value: unknown,
|
|
38
|
+
) =>
|
|
39
|
+
| (AnyStandardSchemaValidateSuccess | AnyStandardSchemaValidateFailure)
|
|
40
|
+
| Promise<AnyStandardSchemaValidateSuccess | AnyStandardSchemaValidateFailure>
|
|
41
|
+
|
|
42
|
+
export interface ValidatorObj<TInput, TOutput> {
|
|
43
|
+
parse: ValidatorFn<TInput, TOutput>
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type AnyValidatorObj = ValidatorObj<any, any>
|
|
47
|
+
|
|
48
|
+
export interface ValidatorAdapter<TInput, TOutput> {
|
|
49
|
+
types: {
|
|
50
|
+
input: TInput
|
|
51
|
+
output: TOutput
|
|
52
|
+
}
|
|
53
|
+
parse: (input: unknown) => TOutput
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type AnyValidatorAdapter = ValidatorAdapter<any, any>
|
|
57
|
+
|
|
58
|
+
export type AnyValidatorFn = ValidatorFn<any, any>
|
|
59
|
+
|
|
60
|
+
export type ValidatorFn<TInput, TOutput> = (input: TInput) => TOutput
|
|
61
|
+
|
|
62
|
+
export type Validator<TInput, TOutput> =
|
|
63
|
+
| ValidatorObj<TInput, TOutput>
|
|
64
|
+
| ValidatorFn<TInput, TOutput>
|
|
65
|
+
| ValidatorAdapter<TInput, TOutput>
|
|
66
|
+
| StandardSchemaValidator<TInput, TOutput>
|
|
67
|
+
| undefined
|
|
68
|
+
|
|
69
|
+
export type AnyValidator = Validator<any, any>
|
|
70
|
+
|
|
71
|
+
export type AnySchema = {}
|
|
72
|
+
|
|
73
|
+
export type DefaultValidator = Validator<Record<string, unknown>, AnySchema>
|
|
74
|
+
|
|
75
|
+
export type ResolveValidatorInputFn<TValidator> = TValidator extends (
|
|
76
|
+
input: infer TSchemaInput,
|
|
77
|
+
) => any
|
|
78
|
+
? TSchemaInput extends SearchSchemaInput
|
|
79
|
+
? Omit<TSchemaInput, keyof SearchSchemaInput>
|
|
80
|
+
: ResolveValidatorOutputFn<TValidator>
|
|
81
|
+
: AnySchema
|
|
82
|
+
|
|
83
|
+
export type ResolveValidatorInput<TValidator> =
|
|
84
|
+
TValidator extends AnyStandardSchemaValidator
|
|
85
|
+
? NonNullable<TValidator['~standard']['types']>['input']
|
|
86
|
+
: TValidator extends AnyValidatorAdapter
|
|
87
|
+
? TValidator['types']['input']
|
|
88
|
+
: TValidator extends AnyValidatorObj
|
|
89
|
+
? ResolveValidatorInputFn<TValidator['parse']>
|
|
90
|
+
: ResolveValidatorInputFn<TValidator>
|
|
91
|
+
|
|
92
|
+
export type ResolveValidatorOutputFn<TValidator> = TValidator extends (
|
|
93
|
+
...args: any
|
|
94
|
+
) => infer TSchema
|
|
95
|
+
? TSchema
|
|
96
|
+
: AnySchema
|
|
97
|
+
|
|
98
|
+
export type ResolveValidatorOutput<TValidator> = unknown extends TValidator
|
|
99
|
+
? TValidator
|
|
100
|
+
: TValidator extends AnyStandardSchemaValidator
|
|
101
|
+
? NonNullable<TValidator['~standard']['types']>['output']
|
|
102
|
+
: TValidator extends AnyValidatorAdapter
|
|
103
|
+
? TValidator['types']['output']
|
|
104
|
+
: TValidator extends AnyValidatorObj
|
|
105
|
+
? ResolveValidatorOutputFn<TValidator['parse']>
|
|
106
|
+
: ResolveValidatorOutputFn<TValidator>
|