@tanstack/router-core 0.0.1-beta.9 → 1.97.21
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/cjs/Matches.cjs +13 -0
- package/dist/cjs/Matches.cjs.map +1 -0
- package/dist/cjs/Matches.d.cts +28 -0
- package/dist/cjs/RouterProvider.d.cts +18 -0
- package/dist/cjs/defer.cjs +25 -0
- package/dist/cjs/defer.cjs.map +1 -0
- package/dist/cjs/defer.d.cts +20 -0
- package/dist/cjs/index.cjs +50 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +25 -0
- package/dist/cjs/link.cjs +5 -0
- package/dist/cjs/link.cjs.map +1 -0
- package/dist/cjs/link.d.cts +51 -0
- package/dist/cjs/location.d.cts +12 -0
- package/dist/cjs/manifest.d.cts +24 -0
- package/dist/cjs/path.cjs +289 -0
- package/dist/cjs/path.cjs.map +1 -0
- package/dist/cjs/path.d.cts +34 -0
- package/dist/cjs/qss.cjs +51 -0
- package/dist/cjs/qss.cjs.map +1 -0
- package/dist/cjs/qss.d.cts +27 -0
- package/dist/cjs/root.cjs +5 -0
- package/dist/cjs/root.cjs.map +1 -0
- package/dist/cjs/root.d.cts +2 -0
- package/dist/cjs/route.d.cts +148 -0
- package/dist/cjs/router.cjs +19 -0
- package/dist/cjs/router.cjs.map +1 -0
- package/dist/cjs/router.d.cts +31 -0
- package/dist/cjs/searchMiddleware.cjs +42 -0
- package/dist/cjs/searchMiddleware.cjs.map +1 -0
- package/dist/cjs/searchMiddleware.d.cts +5 -0
- package/dist/cjs/searchParams.cjs +61 -0
- package/dist/cjs/searchParams.cjs.map +1 -0
- package/dist/cjs/searchParams.d.cts +7 -0
- package/dist/cjs/serializer.d.cts +15 -0
- package/dist/cjs/structuralSharing.d.cts +4 -0
- package/dist/cjs/utils.cjs +155 -0
- package/dist/cjs/utils.cjs.map +1 -0
- package/dist/cjs/utils.d.cts +81 -0
- package/dist/cjs/validators.d.cts +51 -0
- package/dist/esm/Matches.d.ts +28 -0
- package/dist/esm/Matches.js +13 -0
- package/dist/esm/Matches.js.map +1 -0
- package/dist/esm/RouterProvider.d.ts +18 -0
- package/dist/esm/defer.d.ts +20 -0
- package/dist/esm/defer.js +25 -0
- package/dist/esm/defer.js.map +1 -0
- package/dist/esm/index.d.ts +25 -0
- package/dist/esm/index.js +50 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/link.d.ts +51 -0
- package/dist/esm/link.js +5 -0
- package/dist/esm/link.js.map +1 -0
- package/dist/esm/location.d.ts +12 -0
- package/dist/esm/manifest.d.ts +24 -0
- package/dist/esm/path.d.ts +34 -0
- package/dist/esm/path.js +289 -0
- package/dist/esm/path.js.map +1 -0
- package/dist/esm/qss.d.ts +27 -0
- package/dist/esm/qss.js +51 -0
- package/dist/esm/qss.js.map +1 -0
- package/dist/esm/root.d.ts +2 -0
- package/dist/esm/root.js +5 -0
- package/dist/esm/root.js.map +1 -0
- package/dist/esm/route.d.ts +148 -0
- package/dist/esm/router.d.ts +31 -0
- package/dist/esm/router.js +19 -0
- package/dist/esm/router.js.map +1 -0
- package/dist/esm/searchMiddleware.d.ts +5 -0
- package/dist/esm/searchMiddleware.js +42 -0
- package/dist/esm/searchMiddleware.js.map +1 -0
- package/dist/esm/searchParams.d.ts +7 -0
- package/dist/esm/searchParams.js +61 -0
- package/dist/esm/searchParams.js.map +1 -0
- package/dist/esm/serializer.d.ts +15 -0
- package/dist/esm/structuralSharing.d.ts +4 -0
- package/dist/esm/utils.d.ts +81 -0
- package/dist/esm/utils.js +155 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/validators.d.ts +51 -0
- package/package.json +35 -32
- package/src/Matches.ts +94 -0
- package/src/RouterProvider.ts +20 -0
- package/src/defer.ts +52 -0
- package/src/index.ts +206 -19
- package/src/link.ts +122 -300
- package/src/location.ts +13 -0
- package/src/manifest.ts +32 -0
- package/src/path.ts +238 -47
- package/src/qss.ts +56 -19
- package/src/root.ts +2 -0
- package/src/route.ts +296 -223
- package/src/router.ts +34 -1281
- package/src/searchMiddleware.ts +54 -0
- package/src/searchParams.ts +43 -20
- package/src/serializer.ts +24 -0
- package/src/structuralSharing.ts +7 -0
- package/src/utils.ts +314 -75
- package/src/validators.ts +121 -0
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js +0 -33
- package/build/cjs/_virtual/_rollupPluginBabelHelpers.js.map +0 -1
- package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js +0 -33
- package/build/cjs/node_modules/@babel/runtime/helpers/esm/extends.js.map +0 -1
- package/build/cjs/node_modules/history/index.js +0 -815
- package/build/cjs/node_modules/history/index.js.map +0 -1
- package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js +0 -30
- package/build/cjs/node_modules/tiny-invariant/dist/esm/tiny-invariant.js.map +0 -1
- package/build/cjs/packages/router-core/src/index.js +0 -58
- package/build/cjs/packages/router-core/src/index.js.map +0 -1
- package/build/cjs/packages/router-core/src/path.js +0 -222
- package/build/cjs/packages/router-core/src/path.js.map +0 -1
- package/build/cjs/packages/router-core/src/qss.js +0 -71
- package/build/cjs/packages/router-core/src/qss.js.map +0 -1
- package/build/cjs/packages/router-core/src/route.js +0 -150
- package/build/cjs/packages/router-core/src/route.js.map +0 -1
- package/build/cjs/packages/router-core/src/routeConfig.js +0 -69
- package/build/cjs/packages/router-core/src/routeConfig.js.map +0 -1
- package/build/cjs/packages/router-core/src/routeMatch.js +0 -266
- package/build/cjs/packages/router-core/src/routeMatch.js.map +0 -1
- package/build/cjs/packages/router-core/src/router.js +0 -822
- package/build/cjs/packages/router-core/src/router.js.map +0 -1
- package/build/cjs/packages/router-core/src/searchParams.js +0 -70
- package/build/cjs/packages/router-core/src/searchParams.js.map +0 -1
- package/build/cjs/packages/router-core/src/utils.js +0 -125
- package/build/cjs/packages/router-core/src/utils.js.map +0 -1
- package/build/esm/index.js +0 -2481
- package/build/esm/index.js.map +0 -1
- package/build/stats-html.html +0 -4034
- package/build/stats-react.json +0 -493
- package/build/types/index.d.ts +0 -618
- package/build/umd/index.development.js +0 -2514
- package/build/umd/index.development.js.map +0 -1
- package/build/umd/index.production.js +0 -12
- package/build/umd/index.production.js.map +0 -1
- package/src/frameworks.ts +0 -12
- package/src/routeConfig.ts +0 -495
- package/src/routeInfo.ts +0 -228
- package/src/routeMatch.ts +0 -374
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { deepEqual } from './utils'
|
|
2
|
+
import type { NoInfer, PickOptional } from './utils'
|
|
3
|
+
import type { SearchMiddleware } from './route'
|
|
4
|
+
import type { IsRequiredParams } from './link'
|
|
5
|
+
|
|
6
|
+
export function retainSearchParams<TSearchSchema extends object>(
|
|
7
|
+
keys: Array<keyof TSearchSchema> | true,
|
|
8
|
+
): SearchMiddleware<TSearchSchema> {
|
|
9
|
+
return ({ search, next }) => {
|
|
10
|
+
const result = next(search)
|
|
11
|
+
if (keys === true) {
|
|
12
|
+
return { ...search, ...result }
|
|
13
|
+
}
|
|
14
|
+
// add missing keys from search to result
|
|
15
|
+
keys.forEach((key) => {
|
|
16
|
+
if (!(key in result)) {
|
|
17
|
+
result[key] = search[key]
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
return result
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function stripSearchParams<
|
|
25
|
+
TSearchSchema,
|
|
26
|
+
TOptionalProps = PickOptional<NoInfer<TSearchSchema>>,
|
|
27
|
+
const TValues =
|
|
28
|
+
| Partial<NoInfer<TOptionalProps>>
|
|
29
|
+
| Array<keyof TOptionalProps>,
|
|
30
|
+
const TInput = IsRequiredParams<TSearchSchema> extends never
|
|
31
|
+
? TValues | true
|
|
32
|
+
: TValues,
|
|
33
|
+
>(input: NoInfer<TInput>): SearchMiddleware<TSearchSchema> {
|
|
34
|
+
return ({ search, next }) => {
|
|
35
|
+
if (input === true) {
|
|
36
|
+
return {}
|
|
37
|
+
}
|
|
38
|
+
const result = next(search) as Record<string, unknown>
|
|
39
|
+
if (Array.isArray(input)) {
|
|
40
|
+
input.forEach((key) => {
|
|
41
|
+
delete result[key]
|
|
42
|
+
})
|
|
43
|
+
} else {
|
|
44
|
+
Object.entries(input as Record<string, unknown>).forEach(
|
|
45
|
+
([key, value]) => {
|
|
46
|
+
if (deepEqual(result[key], value)) {
|
|
47
|
+
delete result[key]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
return result as any
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/searchParams.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { decode, encode } from './qss'
|
|
2
|
-
import {
|
|
2
|
+
import type { AnySchema } from './validators'
|
|
3
3
|
|
|
4
4
|
export const defaultParseSearch = parseSearchWith(JSON.parse)
|
|
5
|
-
export const defaultStringifySearch = stringifySearchWith(
|
|
5
|
+
export const defaultStringifySearch = stringifySearchWith(
|
|
6
|
+
JSON.stringify,
|
|
7
|
+
JSON.parse,
|
|
8
|
+
)
|
|
6
9
|
|
|
7
10
|
export function parseSearchWith(parser: (str: string) => any) {
|
|
8
|
-
return (searchStr: string):
|
|
11
|
+
return (searchStr: string): AnySchema => {
|
|
9
12
|
if (searchStr.substring(0, 1) === '?') {
|
|
10
13
|
searchStr = searchStr.substring(1)
|
|
11
14
|
}
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
const query: Record<string, unknown> = decode(searchStr)
|
|
14
17
|
|
|
15
18
|
// Try to parse any query params that might be json
|
|
16
|
-
for (
|
|
19
|
+
for (const key in query) {
|
|
17
20
|
const value = query[key]
|
|
18
21
|
if (typeof value === 'string') {
|
|
19
22
|
try {
|
|
@@ -28,27 +31,47 @@ export function parseSearchWith(parser: (str: string) => any) {
|
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
export function stringifySearchWith(
|
|
34
|
+
export function stringifySearchWith(
|
|
35
|
+
stringify: (search: any) => string,
|
|
36
|
+
parser?: (str: string) => any,
|
|
37
|
+
) {
|
|
38
|
+
function stringifyValue(val: any) {
|
|
39
|
+
if (typeof val === 'object' && val !== null) {
|
|
40
|
+
try {
|
|
41
|
+
return stringify(val)
|
|
42
|
+
} catch (err) {
|
|
43
|
+
// silent
|
|
44
|
+
}
|
|
45
|
+
} else if (typeof val === 'string' && typeof parser === 'function') {
|
|
46
|
+
try {
|
|
47
|
+
// Check if it's a valid parseable string.
|
|
48
|
+
// If it is, then stringify it again.
|
|
49
|
+
parser(val)
|
|
50
|
+
return stringify(val)
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// silent
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return val
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
return (search: Record<string, any>) => {
|
|
33
59
|
search = { ...search }
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
} catch (err) {
|
|
44
|
-
// silent
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
}
|
|
61
|
+
Object.keys(search).forEach((key) => {
|
|
62
|
+
const val = search[key]
|
|
63
|
+
if (typeof val === 'undefined' || val === undefined) {
|
|
64
|
+
delete search[key]
|
|
65
|
+
} else {
|
|
66
|
+
search[key] = stringifyValue(val)
|
|
67
|
+
}
|
|
68
|
+
})
|
|
49
69
|
|
|
50
70
|
const searchStr = encode(search as Record<string, string>).toString()
|
|
51
71
|
|
|
52
72
|
return searchStr ? `?${searchStr}` : ''
|
|
53
73
|
}
|
|
54
74
|
}
|
|
75
|
+
|
|
76
|
+
export type SearchSerializer = (searchObj: Record<string, any>) => string
|
|
77
|
+
export type SearchParser = (searchStr: string) => Record<string, any>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface StartSerializer {
|
|
2
|
+
stringify: (obj: unknown) => string
|
|
3
|
+
parse: (str: string) => unknown
|
|
4
|
+
encode: <T>(value: T) => T
|
|
5
|
+
decode: <T>(value: T) => T
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type SerializerStringifyBy<T, TSerializable> = T extends TSerializable
|
|
9
|
+
? T
|
|
10
|
+
: T extends (...args: Array<any>) => any
|
|
11
|
+
? 'Function is not serializable'
|
|
12
|
+
: { [K in keyof T]: SerializerStringifyBy<T[K], TSerializable> }
|
|
13
|
+
|
|
14
|
+
export type SerializerParseBy<T, TSerializable> = T extends TSerializable
|
|
15
|
+
? T
|
|
16
|
+
: T extends React.JSX.Element
|
|
17
|
+
? ReadableStream
|
|
18
|
+
: { [K in keyof T]: SerializerParseBy<T[K], TSerializable> }
|
|
19
|
+
|
|
20
|
+
export type Serializable = Date | undefined | Error | FormData
|
|
21
|
+
|
|
22
|
+
export type SerializerStringify<T> = SerializerStringifyBy<T, Serializable>
|
|
23
|
+
|
|
24
|
+
export type SerializerParse<T> = SerializerParseBy<T, Serializable>
|
package/src/utils.ts
CHANGED
|
@@ -1,50 +1,81 @@
|
|
|
1
1
|
export type NoInfer<T> = [T][T extends any ? 0 : never]
|
|
2
|
-
export type IsAny<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
? never
|
|
13
|
-
: TKey extends keyof T
|
|
14
|
-
? never
|
|
15
|
-
: TKey]: K[TKey]
|
|
16
|
-
}>
|
|
2
|
+
export type IsAny<TValue, TYesResult, TNoResult = TValue> = 1 extends 0 & TValue
|
|
3
|
+
? TYesResult
|
|
4
|
+
: TNoResult
|
|
5
|
+
|
|
6
|
+
export type PickAsRequired<TValue, TKey extends keyof TValue> = Omit<
|
|
7
|
+
TValue,
|
|
8
|
+
TKey
|
|
9
|
+
> &
|
|
10
|
+
Required<Pick<TValue, TKey>>
|
|
11
|
+
|
|
17
12
|
export type PickRequired<T> = {
|
|
18
13
|
[K in keyof T as undefined extends T[K] ? never : K]: T[K]
|
|
19
14
|
}
|
|
20
15
|
|
|
16
|
+
export type PickOptional<T> = {
|
|
17
|
+
[K in keyof T as undefined extends T[K] ? K : never]: T[K]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// from https://stackoverflow.com/a/76458160
|
|
21
|
+
export type WithoutEmpty<T> = T extends any ? ({} extends T ? never : T) : never
|
|
22
|
+
|
|
21
23
|
export type Expand<T> = T extends object
|
|
22
24
|
? T extends infer O
|
|
23
|
-
?
|
|
25
|
+
? O extends Function
|
|
26
|
+
? O
|
|
27
|
+
: { [K in keyof O]: O[K] }
|
|
24
28
|
: never
|
|
25
29
|
: T
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
export type DeepPartial<T> = T extends object
|
|
32
|
+
? {
|
|
33
|
+
[P in keyof T]?: DeepPartial<T[P]>
|
|
34
|
+
}
|
|
35
|
+
: T
|
|
36
|
+
|
|
37
|
+
export type MakeDifferenceOptional<TLeft, TRight> = Omit<
|
|
38
|
+
TRight,
|
|
39
|
+
keyof TLeft
|
|
40
|
+
> & {
|
|
41
|
+
[K in keyof TLeft & keyof TRight]?: TRight[K]
|
|
42
|
+
}
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
// from https://stackoverflow.com/a/53955431
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
46
|
+
export type IsUnion<T, U extends T = T> = (
|
|
47
|
+
T extends any ? (U extends T ? false : true) : never
|
|
48
|
+
) extends false
|
|
49
|
+
? false
|
|
50
|
+
: true
|
|
35
51
|
|
|
36
|
-
export type
|
|
37
|
-
?
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
:
|
|
52
|
+
export type IsNonEmptyObject<T> = T extends object
|
|
53
|
+
? keyof T extends never
|
|
54
|
+
? false
|
|
55
|
+
: true
|
|
56
|
+
: false
|
|
41
57
|
|
|
42
|
-
export type
|
|
43
|
-
|
|
44
|
-
?
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
export type Assign<TLeft, TRight> = TLeft extends any
|
|
59
|
+
? TRight extends any
|
|
60
|
+
? IsNonEmptyObject<TLeft> extends false
|
|
61
|
+
? TRight
|
|
62
|
+
: IsNonEmptyObject<TRight> extends false
|
|
63
|
+
? TLeft
|
|
64
|
+
: keyof TLeft & keyof TRight extends never
|
|
65
|
+
? TLeft & TRight
|
|
66
|
+
: Omit<TLeft, keyof TRight> & TRight
|
|
67
|
+
: never
|
|
68
|
+
: never
|
|
69
|
+
|
|
70
|
+
export type IntersectAssign<TLeft, TRight> = TLeft extends any
|
|
71
|
+
? TRight extends any
|
|
72
|
+
? IsNonEmptyObject<TLeft> extends false
|
|
73
|
+
? TRight
|
|
74
|
+
: IsNonEmptyObject<TRight> extends false
|
|
75
|
+
? TLeft
|
|
76
|
+
: TRight & TLeft
|
|
77
|
+
: never
|
|
78
|
+
: never
|
|
48
79
|
|
|
49
80
|
export type Timeout = ReturnType<typeof setTimeout>
|
|
50
81
|
|
|
@@ -52,50 +83,165 @@ export type Updater<TPrevious, TResult = TPrevious> =
|
|
|
52
83
|
| TResult
|
|
53
84
|
| ((prev?: TPrevious) => TResult)
|
|
54
85
|
|
|
55
|
-
export type
|
|
56
|
-
|
|
86
|
+
export type NonNullableUpdater<TPrevious, TResult = TPrevious> =
|
|
87
|
+
| TResult
|
|
88
|
+
| ((prev: TPrevious) => TResult)
|
|
89
|
+
|
|
90
|
+
export type ExtractObjects<TUnion> = TUnion extends MergeAllPrimitive
|
|
91
|
+
? never
|
|
92
|
+
: TUnion
|
|
93
|
+
|
|
94
|
+
export type PartialMergeAllObject<TUnion> =
|
|
95
|
+
ExtractObjects<TUnion> extends infer TObj
|
|
96
|
+
? {
|
|
97
|
+
[TKey in TObj extends any ? keyof TObj : never]?: TObj extends any
|
|
98
|
+
? TKey extends keyof TObj
|
|
99
|
+
? TObj[TKey]
|
|
100
|
+
: never
|
|
101
|
+
: never
|
|
102
|
+
}
|
|
103
|
+
: never
|
|
104
|
+
|
|
105
|
+
export type MergeAllPrimitive =
|
|
106
|
+
| ReadonlyArray<any>
|
|
107
|
+
| number
|
|
108
|
+
| string
|
|
109
|
+
| bigint
|
|
110
|
+
| boolean
|
|
111
|
+
| symbol
|
|
112
|
+
| undefined
|
|
113
|
+
| null
|
|
114
|
+
|
|
115
|
+
export type ExtractPrimitives<TUnion> = TUnion extends MergeAllPrimitive
|
|
116
|
+
? TUnion
|
|
117
|
+
: TUnion extends object
|
|
118
|
+
? never
|
|
119
|
+
: TUnion
|
|
120
|
+
|
|
121
|
+
export type PartialMergeAll<TUnion> =
|
|
122
|
+
| ExtractPrimitives<TUnion>
|
|
123
|
+
| PartialMergeAllObject<TUnion>
|
|
124
|
+
|
|
125
|
+
export type Constrain<T, TConstraint, TDefault = TConstraint> =
|
|
126
|
+
| (T extends TConstraint ? T : never)
|
|
127
|
+
| TDefault
|
|
128
|
+
|
|
129
|
+
export type ConstrainLiteral<T, TConstraint, TDefault = TConstraint> =
|
|
130
|
+
| (T & TConstraint)
|
|
131
|
+
| TDefault
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* To be added to router types
|
|
135
|
+
*/
|
|
136
|
+
export type UnionToIntersection<T> = (
|
|
137
|
+
T extends any ? (arg: T) => any : never
|
|
138
|
+
) extends (arg: infer T) => any
|
|
139
|
+
? T
|
|
140
|
+
: never
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Merges everything in a union into one object.
|
|
144
|
+
* This mapped type is homomorphic which means it preserves stuff! :)
|
|
145
|
+
*/
|
|
146
|
+
export type MergeAllObjects<
|
|
147
|
+
TUnion,
|
|
148
|
+
TIntersected = UnionToIntersection<ExtractObjects<TUnion>>,
|
|
149
|
+
> = [keyof TIntersected] extends [never]
|
|
150
|
+
? never
|
|
151
|
+
: {
|
|
152
|
+
[TKey in keyof TIntersected]: TUnion extends any
|
|
153
|
+
? TUnion[TKey & keyof TUnion]
|
|
154
|
+
: never
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export type MergeAll<TUnion> =
|
|
158
|
+
| MergeAllObjects<TUnion>
|
|
159
|
+
| ExtractPrimitives<TUnion>
|
|
160
|
+
|
|
161
|
+
export type ValidateJSON<T> = ((...args: Array<any>) => any) extends T
|
|
162
|
+
? unknown extends T
|
|
163
|
+
? never
|
|
164
|
+
: 'Function is not serializable'
|
|
165
|
+
: { [K in keyof T]: ValidateJSON<T[K]> }
|
|
166
|
+
|
|
167
|
+
export function last<T>(arr: Array<T>) {
|
|
168
|
+
return arr[arr.length - 1]
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function isFunction(d: any): d is Function {
|
|
172
|
+
return typeof d === 'function'
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function functionalUpdate<TPrevious, TResult = TPrevious>(
|
|
176
|
+
updater: Updater<TPrevious, TResult> | NonNullableUpdater<TPrevious, TResult>,
|
|
177
|
+
previous: TPrevious,
|
|
178
|
+
): TResult {
|
|
179
|
+
if (isFunction(updater)) {
|
|
180
|
+
return updater(previous)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return updater
|
|
57
184
|
}
|
|
58
185
|
|
|
59
|
-
export
|
|
60
|
-
|
|
186
|
+
export function pick<TValue, TKey extends keyof TValue>(
|
|
187
|
+
parent: TValue,
|
|
188
|
+
keys: Array<TKey>,
|
|
189
|
+
): Pick<TValue, TKey> {
|
|
190
|
+
return keys.reduce((obj: any, key: TKey) => {
|
|
191
|
+
obj[key] = parent[key]
|
|
192
|
+
return obj
|
|
193
|
+
}, {} as any)
|
|
61
194
|
}
|
|
62
195
|
|
|
63
196
|
/**
|
|
64
|
-
* This function returns `
|
|
197
|
+
* This function returns `prev` if `_next` is deeply equal.
|
|
65
198
|
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
66
|
-
* This can be used for structural sharing between JSON values for example.
|
|
199
|
+
* This can be used for structural sharing between immutable JSON values for example.
|
|
200
|
+
* Do not use this with signals
|
|
67
201
|
*/
|
|
68
|
-
export function replaceEqualDeep(prev: any,
|
|
69
|
-
if (prev ===
|
|
202
|
+
export function replaceEqualDeep<T>(prev: any, _next: T): T {
|
|
203
|
+
if (prev === _next) {
|
|
70
204
|
return prev
|
|
71
205
|
}
|
|
72
206
|
|
|
73
|
-
const
|
|
207
|
+
const next = _next as any
|
|
208
|
+
|
|
209
|
+
const array = isPlainArray(prev) && isPlainArray(next)
|
|
74
210
|
|
|
75
211
|
if (array || (isPlainObject(prev) && isPlainObject(next))) {
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
212
|
+
const prevItems = array ? prev : Object.keys(prev)
|
|
213
|
+
const prevSize = prevItems.length
|
|
214
|
+
const nextItems = array ? next : Object.keys(next)
|
|
215
|
+
const nextSize = nextItems.length
|
|
79
216
|
const copy: any = array ? [] : {}
|
|
80
217
|
|
|
81
218
|
let equalItems = 0
|
|
82
219
|
|
|
83
|
-
for (let i = 0; i <
|
|
84
|
-
const key = array ? i :
|
|
85
|
-
|
|
86
|
-
|
|
220
|
+
for (let i = 0; i < nextSize; i++) {
|
|
221
|
+
const key = array ? i : (nextItems[i] as any)
|
|
222
|
+
if (
|
|
223
|
+
((!array && prevItems.includes(key)) || array) &&
|
|
224
|
+
prev[key] === undefined &&
|
|
225
|
+
next[key] === undefined
|
|
226
|
+
) {
|
|
227
|
+
copy[key] = undefined
|
|
87
228
|
equalItems++
|
|
229
|
+
} else {
|
|
230
|
+
copy[key] = replaceEqualDeep(prev[key], next[key])
|
|
231
|
+
if (copy[key] === prev[key] && prev[key] !== undefined) {
|
|
232
|
+
equalItems++
|
|
233
|
+
}
|
|
88
234
|
}
|
|
89
235
|
}
|
|
90
236
|
|
|
91
|
-
return
|
|
237
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy
|
|
92
238
|
}
|
|
93
239
|
|
|
94
240
|
return next
|
|
95
241
|
}
|
|
96
242
|
|
|
97
243
|
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
98
|
-
function isPlainObject(o: any) {
|
|
244
|
+
export function isPlainObject(o: any) {
|
|
99
245
|
if (!hasObjectPrototype(o)) {
|
|
100
246
|
return false
|
|
101
247
|
}
|
|
@@ -125,40 +271,133 @@ function hasObjectPrototype(o: any) {
|
|
|
125
271
|
return Object.prototype.toString.call(o) === '[object Object]'
|
|
126
272
|
}
|
|
127
273
|
|
|
128
|
-
export function
|
|
129
|
-
return
|
|
274
|
+
export function isPlainArray(value: unknown): value is Array<unknown> {
|
|
275
|
+
return Array.isArray(value) && value.length === Object.keys(value).length
|
|
130
276
|
}
|
|
131
277
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
278
|
+
function getObjectKeys(obj: any, ignoreUndefined: boolean) {
|
|
279
|
+
let keys = Object.keys(obj)
|
|
280
|
+
if (ignoreUndefined) {
|
|
281
|
+
keys = keys.filter((key) => obj[key] !== undefined)
|
|
282
|
+
}
|
|
283
|
+
return keys
|
|
284
|
+
}
|
|
135
285
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
286
|
+
export function deepEqual(
|
|
287
|
+
a: any,
|
|
288
|
+
b: any,
|
|
289
|
+
opts?: { partial?: boolean; ignoreUndefined?: boolean },
|
|
290
|
+
): boolean {
|
|
291
|
+
if (a === b) {
|
|
292
|
+
return true
|
|
139
293
|
}
|
|
140
294
|
|
|
141
|
-
|
|
295
|
+
if (typeof a !== typeof b) {
|
|
296
|
+
return false
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (isPlainObject(a) && isPlainObject(b)) {
|
|
300
|
+
const ignoreUndefined = opts?.ignoreUndefined ?? true
|
|
301
|
+
const aKeys = getObjectKeys(a, ignoreUndefined)
|
|
302
|
+
const bKeys = getObjectKeys(b, ignoreUndefined)
|
|
303
|
+
|
|
304
|
+
if (!opts?.partial && aKeys.length !== bKeys.length) {
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return bKeys.every((key) => deepEqual(a[key], b[key], opts))
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
312
|
+
if (a.length !== b.length) {
|
|
313
|
+
return false
|
|
314
|
+
}
|
|
315
|
+
return !a.some((item, index) => !deepEqual(item, b[index], opts))
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return false
|
|
142
319
|
}
|
|
143
320
|
|
|
144
|
-
|
|
145
|
-
|
|
321
|
+
export type StringLiteral<T> = T extends string
|
|
322
|
+
? string extends T
|
|
323
|
+
? string
|
|
324
|
+
: T
|
|
325
|
+
: never
|
|
326
|
+
|
|
327
|
+
export type ThrowOrOptional<T, TThrow extends boolean> = TThrow extends true
|
|
328
|
+
? T
|
|
329
|
+
: T | undefined
|
|
330
|
+
|
|
331
|
+
export type ControlledPromise<T> = Promise<T> & {
|
|
332
|
+
resolve: (value: T) => void
|
|
333
|
+
reject: (value: any) => void
|
|
334
|
+
status: 'pending' | 'resolved' | 'rejected'
|
|
335
|
+
value?: T
|
|
146
336
|
}
|
|
147
337
|
|
|
148
|
-
export function
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
338
|
+
export function createControlledPromise<T>(onResolve?: (value: T) => void) {
|
|
339
|
+
let resolveLoadPromise!: (value: T) => void
|
|
340
|
+
let rejectLoadPromise!: (value: any) => void
|
|
341
|
+
|
|
342
|
+
const controlledPromise = new Promise<T>((resolve, reject) => {
|
|
343
|
+
resolveLoadPromise = resolve
|
|
344
|
+
rejectLoadPromise = reject
|
|
345
|
+
}) as ControlledPromise<T>
|
|
346
|
+
|
|
347
|
+
controlledPromise.status = 'pending'
|
|
348
|
+
|
|
349
|
+
controlledPromise.resolve = (value: T) => {
|
|
350
|
+
controlledPromise.status = 'resolved'
|
|
351
|
+
controlledPromise.value = value
|
|
352
|
+
resolveLoadPromise(value)
|
|
353
|
+
onResolve?.(value)
|
|
154
354
|
}
|
|
155
355
|
|
|
156
|
-
|
|
356
|
+
controlledPromise.reject = (e) => {
|
|
357
|
+
controlledPromise.status = 'rejected'
|
|
358
|
+
rejectLoadPromise(e)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return controlledPromise
|
|
157
362
|
}
|
|
158
363
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
364
|
+
/**
|
|
365
|
+
*
|
|
366
|
+
* @deprecated use `jsesc` instead
|
|
367
|
+
*/
|
|
368
|
+
export function escapeJSON(jsonString: string) {
|
|
369
|
+
return jsonString
|
|
370
|
+
.replace(/\\/g, '\\\\') // Escape backslashes
|
|
371
|
+
.replace(/'/g, "\\'") // Escape single quotes
|
|
372
|
+
.replace(/"/g, '\\"') // Escape double quotes
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function shallow<T>(objA: T, objB: T) {
|
|
376
|
+
if (Object.is(objA, objB)) {
|
|
377
|
+
return true
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (
|
|
381
|
+
typeof objA !== 'object' ||
|
|
382
|
+
objA === null ||
|
|
383
|
+
typeof objB !== 'object' ||
|
|
384
|
+
objB === null
|
|
385
|
+
) {
|
|
386
|
+
return false
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const keysA = Object.keys(objA)
|
|
390
|
+
if (keysA.length !== Object.keys(objB).length) {
|
|
391
|
+
return false
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
for (const item of keysA) {
|
|
395
|
+
if (
|
|
396
|
+
!Object.prototype.hasOwnProperty.call(objB, item) ||
|
|
397
|
+
!Object.is(objA[item as keyof T], objB[item as keyof T])
|
|
398
|
+
) {
|
|
399
|
+
return false
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
return true
|
|
164
403
|
}
|