@tanstack/router-core 1.132.0-alpha.4 → 1.132.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/Matches.cjs +2 -1
- package/dist/cjs/Matches.cjs.map +1 -1
- package/dist/cjs/Matches.d.cts +2 -2
- package/dist/cjs/config.cjs +10 -0
- package/dist/cjs/config.cjs.map +1 -0
- package/dist/cjs/config.d.cts +17 -0
- package/dist/cjs/fileRoute.d.cts +3 -2
- package/dist/cjs/index.cjs +9 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +10 -5
- package/dist/cjs/load-matches.cjs +5 -3
- package/dist/cjs/load-matches.cjs.map +1 -1
- package/dist/cjs/location.d.cts +38 -0
- package/dist/cjs/path.cjs +27 -64
- package/dist/cjs/path.cjs.map +1 -1
- package/dist/cjs/path.d.cts +6 -7
- package/dist/cjs/process-route-tree.cjs +144 -0
- package/dist/cjs/process-route-tree.cjs.map +1 -0
- package/dist/cjs/process-route-tree.d.cts +10 -0
- package/dist/cjs/redirect.cjs +1 -1
- package/dist/cjs/redirect.cjs.map +1 -1
- package/dist/cjs/rewrite.cjs +63 -0
- package/dist/cjs/rewrite.cjs.map +1 -0
- package/dist/cjs/rewrite.d.cts +22 -0
- package/dist/cjs/route.cjs.map +1 -1
- package/dist/cjs/route.d.cts +62 -44
- package/dist/cjs/router.cjs +102 -210
- package/dist/cjs/router.cjs.map +1 -1
- package/dist/cjs/router.d.cts +81 -44
- package/dist/cjs/scroll-restoration.cjs.map +1 -1
- package/dist/cjs/scroll-restoration.d.cts +9 -0
- package/dist/cjs/ssr/createRequestHandler.cjs +4 -1
- package/dist/cjs/ssr/createRequestHandler.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.cjs +14 -12
- package/dist/cjs/ssr/serializer/transformer.cjs.map +1 -1
- package/dist/cjs/ssr/serializer/transformer.d.cts +55 -15
- package/dist/cjs/ssr/ssr-client.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.cjs +5 -2
- package/dist/cjs/ssr/ssr-server.cjs.map +1 -1
- package/dist/cjs/ssr/ssr-server.d.cts +4 -1
- package/dist/cjs/utils.cjs +68 -46
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/Matches.d.ts +2 -2
- package/dist/esm/Matches.js +2 -1
- package/dist/esm/Matches.js.map +1 -1
- package/dist/esm/config.d.ts +17 -0
- package/dist/esm/config.js +10 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/fileRoute.d.ts +3 -2
- package/dist/esm/index.d.ts +10 -5
- package/dist/esm/index.js +10 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/load-matches.js +5 -3
- package/dist/esm/load-matches.js.map +1 -1
- package/dist/esm/location.d.ts +38 -0
- package/dist/esm/path.d.ts +6 -7
- package/dist/esm/path.js +27 -64
- package/dist/esm/path.js.map +1 -1
- package/dist/esm/process-route-tree.d.ts +10 -0
- package/dist/esm/process-route-tree.js +144 -0
- package/dist/esm/process-route-tree.js.map +1 -0
- package/dist/esm/redirect.js +1 -1
- package/dist/esm/redirect.js.map +1 -1
- package/dist/esm/rewrite.d.ts +22 -0
- package/dist/esm/rewrite.js +63 -0
- package/dist/esm/rewrite.js.map +1 -0
- package/dist/esm/route.d.ts +62 -44
- package/dist/esm/route.js.map +1 -1
- package/dist/esm/router.d.ts +81 -44
- package/dist/esm/router.js +104 -212
- package/dist/esm/router.js.map +1 -1
- package/dist/esm/scroll-restoration.d.ts +9 -0
- package/dist/esm/scroll-restoration.js.map +1 -1
- package/dist/esm/ssr/createRequestHandler.js +4 -1
- package/dist/esm/ssr/createRequestHandler.js.map +1 -1
- package/dist/esm/ssr/serializer/transformer.d.ts +55 -15
- package/dist/esm/ssr/serializer/transformer.js +14 -12
- package/dist/esm/ssr/serializer/transformer.js.map +1 -1
- package/dist/esm/ssr/ssr-client.js.map +1 -1
- package/dist/esm/ssr/ssr-server.d.ts +4 -1
- package/dist/esm/ssr/ssr-server.js +5 -2
- package/dist/esm/ssr/ssr-server.js.map +1 -1
- package/dist/esm/utils.js +68 -46
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/Matches.ts +4 -3
- package/src/config.ts +42 -0
- package/src/fileRoute.ts +25 -3
- package/src/index.ts +23 -6
- package/src/load-matches.ts +31 -21
- package/src/location.ts +38 -0
- package/src/path.ts +44 -82
- package/src/process-route-tree.ts +233 -0
- package/src/redirect.ts +1 -1
- package/src/rewrite.ts +70 -0
- package/src/route.ts +311 -74
- package/src/router.ts +263 -389
- package/src/scroll-restoration.ts +1 -1
- package/src/ssr/createRequestHandler.ts +4 -1
- package/src/ssr/serializer/transformer.ts +168 -31
- package/src/ssr/server.ts +6 -0
- package/src/ssr/ssr-client.ts +2 -2
- package/src/ssr/ssr-server.ts +10 -7
- package/src/utils.ts +83 -61
|
@@ -358,7 +358,7 @@ export function setupScrollRestoration(router: AnyRouter, force?: boolean) {
|
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
/**
|
|
361
|
-
* @
|
|
361
|
+
* @private
|
|
362
362
|
* Handles hash-based scrolling after navigation completes.
|
|
363
363
|
* To be used in framework-specific <Transitioner> components during the onResolved event.
|
|
364
364
|
*
|
|
@@ -21,7 +21,10 @@ export function createRequestHandler<TRouter extends AnyRouter>({
|
|
|
21
21
|
return async (cb) => {
|
|
22
22
|
const router = createRouter()
|
|
23
23
|
|
|
24
|
-
attachRouterServerSsrUtils(
|
|
24
|
+
attachRouterServerSsrUtils({
|
|
25
|
+
router,
|
|
26
|
+
manifest: await getRouterManifest?.(),
|
|
27
|
+
})
|
|
25
28
|
|
|
26
29
|
const url = new URL(request.url, 'http://localhost')
|
|
27
30
|
|
|
@@ -1,39 +1,111 @@
|
|
|
1
1
|
import { createPlugin } from 'seroval'
|
|
2
2
|
import { GLOBAL_TSR } from '../constants'
|
|
3
|
-
import type { SerovalNode } from 'seroval'
|
|
3
|
+
import type { Plugin, SerovalNode } from 'seroval'
|
|
4
|
+
import type { RegisteredConfigType, SSROption } from '../../router'
|
|
5
|
+
import type { LooseReturnType } from '../../utils'
|
|
6
|
+
import type { AnyRoute, ResolveAllSSR } from '../../route'
|
|
4
7
|
|
|
5
|
-
export type
|
|
8
|
+
export type Serializable =
|
|
9
|
+
| number
|
|
10
|
+
| string
|
|
11
|
+
| boolean
|
|
12
|
+
| null
|
|
13
|
+
| undefined
|
|
14
|
+
| bigint
|
|
15
|
+
| Date
|
|
16
|
+
|
|
17
|
+
export function createSerializationAdapter<
|
|
18
|
+
TInput = unknown,
|
|
19
|
+
TOutput = unknown /* we need to check that this type is actually serializable taking into account all seroval native types and any custom plugin WE=router/start add!!! */,
|
|
20
|
+
>(
|
|
21
|
+
opts: CreateSerializationAdapterOptions<TInput, TOutput>,
|
|
22
|
+
): SerializationAdapter<TInput, TOutput> {
|
|
23
|
+
return opts as unknown as SerializationAdapter<TInput, TOutput>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface CreateSerializationAdapterOptions<TInput, TOutput> {
|
|
6
27
|
key: string
|
|
7
|
-
test: (value:
|
|
8
|
-
toSerializable: (value: TInput) =>
|
|
9
|
-
fromSerializable: (value:
|
|
28
|
+
test: (value: unknown) => value is TInput
|
|
29
|
+
toSerializable: (value: TInput) => ValidateSerializable<TOutput, Serializable>
|
|
30
|
+
fromSerializable: (value: TOutput) => TInput
|
|
10
31
|
}
|
|
11
32
|
|
|
12
|
-
export type
|
|
33
|
+
export type ValidateSerializable<T, TSerializable> = T extends TSerializable
|
|
34
|
+
? T
|
|
35
|
+
: T extends (...args: Array<any>) => any
|
|
36
|
+
? 'Function is not serializable'
|
|
37
|
+
: T extends Promise<any>
|
|
38
|
+
? ValidateSerializablePromise<T, TSerializable>
|
|
39
|
+
: T extends ReadableStream<any>
|
|
40
|
+
? ValidateReadableStream<T, TSerializable>
|
|
41
|
+
: T extends Set<any>
|
|
42
|
+
? ValidateSerializableSet<T, TSerializable>
|
|
43
|
+
: T extends Map<any, any>
|
|
44
|
+
? ValidateSerializableMap<T, TSerializable>
|
|
45
|
+
: {
|
|
46
|
+
[K in keyof T]: ValidateSerializable<T[K], TSerializable>
|
|
47
|
+
}
|
|
13
48
|
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
49
|
+
export type ValidateSerializablePromise<T, TSerializable> =
|
|
50
|
+
T extends Promise<infer TAwaited>
|
|
51
|
+
? Promise<ValidateSerializable<TAwaited, TSerializable>>
|
|
52
|
+
: never
|
|
53
|
+
|
|
54
|
+
export type ValidateReadableStream<T, TSerializable> =
|
|
55
|
+
T extends ReadableStream<infer TStreamed>
|
|
56
|
+
? ReadableStream<ValidateSerializable<TStreamed, TSerializable>>
|
|
57
|
+
: never
|
|
58
|
+
|
|
59
|
+
export type ValidateSerializableSet<T, TSerializable> =
|
|
60
|
+
T extends Set<infer TItem>
|
|
61
|
+
? Set<ValidateSerializable<TItem, TSerializable>>
|
|
62
|
+
: never
|
|
63
|
+
|
|
64
|
+
export type ValidateSerializableMap<T, TSerializable> =
|
|
65
|
+
T extends Map<infer TKey, infer TValue>
|
|
66
|
+
? Map<
|
|
67
|
+
ValidateSerializable<TKey, TSerializable>,
|
|
68
|
+
ValidateSerializable<TValue, TSerializable>
|
|
69
|
+
>
|
|
70
|
+
: never
|
|
71
|
+
|
|
72
|
+
export type RegisteredReadableStream =
|
|
73
|
+
unknown extends SerializerExtensions['ReadableStream']
|
|
74
|
+
? never
|
|
75
|
+
: SerializerExtensions['ReadableStream']
|
|
76
|
+
|
|
77
|
+
export interface DefaultSerializerExtensions {
|
|
78
|
+
ReadableStream: unknown
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface SerializerExtensions extends DefaultSerializerExtensions {}
|
|
82
|
+
|
|
83
|
+
export interface SerializationAdapter<TInput, TOutput> {
|
|
84
|
+
'~types': SerializationAdapterTypes<TInput, TOutput>
|
|
85
|
+
key: string
|
|
86
|
+
test: (value: unknown) => value is TInput
|
|
87
|
+
toSerializable: (value: TInput) => TOutput
|
|
88
|
+
fromSerializable: (value: TOutput) => TInput
|
|
89
|
+
makePlugin: (options: { didRun: boolean }) => Plugin<TInput, SerovalNode>
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface SerializationAdapterTypes<TInput, TOutput> {
|
|
93
|
+
input: TInput
|
|
94
|
+
output: TOutput
|
|
25
95
|
}
|
|
26
96
|
|
|
27
|
-
export
|
|
28
|
-
|
|
97
|
+
export type AnySerializationAdapter = SerializationAdapter<any, any>
|
|
98
|
+
|
|
99
|
+
export function makeSsrSerovalPlugin<TInput, TOutput>(
|
|
100
|
+
serializationAdapter: SerializationAdapter<TInput, TOutput>,
|
|
29
101
|
options: { didRun: boolean },
|
|
30
102
|
) {
|
|
31
103
|
return createPlugin<TInput, SerovalNode>({
|
|
32
|
-
tag: '$TSR/t/' +
|
|
33
|
-
test:
|
|
104
|
+
tag: '$TSR/t/' + serializationAdapter.key,
|
|
105
|
+
test: serializationAdapter.test,
|
|
34
106
|
parse: {
|
|
35
107
|
stream(value, ctx) {
|
|
36
|
-
return ctx.parse(
|
|
108
|
+
return ctx.parse(serializationAdapter.toSerializable(value))
|
|
37
109
|
},
|
|
38
110
|
},
|
|
39
111
|
serialize(node, ctx) {
|
|
@@ -41,7 +113,7 @@ export function makeSsrSerovalPlugin<TInput, TTransformed>(
|
|
|
41
113
|
return (
|
|
42
114
|
GLOBAL_TSR +
|
|
43
115
|
'.t.get("' +
|
|
44
|
-
|
|
116
|
+
serializationAdapter.key +
|
|
45
117
|
'")(' +
|
|
46
118
|
ctx.serialize(node) +
|
|
47
119
|
')'
|
|
@@ -52,27 +124,92 @@ export function makeSsrSerovalPlugin<TInput, TTransformed>(
|
|
|
52
124
|
})
|
|
53
125
|
}
|
|
54
126
|
|
|
55
|
-
export function makeSerovalPlugin<TInput,
|
|
56
|
-
|
|
127
|
+
export function makeSerovalPlugin<TInput, TOutput>(
|
|
128
|
+
serializationAdapter: SerializationAdapter<TInput, TOutput>,
|
|
57
129
|
) {
|
|
58
130
|
return createPlugin<TInput, SerovalNode>({
|
|
59
|
-
tag: '$TSR/t/' +
|
|
60
|
-
test:
|
|
131
|
+
tag: '$TSR/t/' + serializationAdapter.key,
|
|
132
|
+
test: serializationAdapter.test,
|
|
61
133
|
parse: {
|
|
62
134
|
sync(value, ctx) {
|
|
63
|
-
return ctx.parse(
|
|
135
|
+
return ctx.parse(serializationAdapter.toSerializable(value))
|
|
64
136
|
},
|
|
65
137
|
async async(value, ctx) {
|
|
66
|
-
return await ctx.parse(
|
|
138
|
+
return await ctx.parse(serializationAdapter.toSerializable(value))
|
|
67
139
|
},
|
|
68
140
|
stream(value, ctx) {
|
|
69
|
-
return ctx.parse(
|
|
141
|
+
return ctx.parse(serializationAdapter.toSerializable(value))
|
|
70
142
|
},
|
|
71
143
|
},
|
|
72
144
|
// we don't generate JS code outside of SSR (for now)
|
|
73
145
|
serialize: undefined as never,
|
|
74
146
|
deserialize(node, ctx) {
|
|
75
|
-
return
|
|
147
|
+
return serializationAdapter.fromSerializable(
|
|
148
|
+
ctx.deserialize(node) as TOutput,
|
|
149
|
+
)
|
|
76
150
|
},
|
|
77
151
|
})
|
|
78
152
|
}
|
|
153
|
+
|
|
154
|
+
export type ValidateSerializableInput<TRegister, T> = ValidateSerializable<
|
|
155
|
+
T,
|
|
156
|
+
RegisteredSerializableInput<TRegister>
|
|
157
|
+
>
|
|
158
|
+
|
|
159
|
+
export type RegisteredSerializableInput<TRegister> =
|
|
160
|
+
| (unknown extends RegisteredSerializationAdapters<TRegister>
|
|
161
|
+
? never
|
|
162
|
+
: RegisteredSerializationAdapters<TRegister> extends ReadonlyArray<AnySerializationAdapter>
|
|
163
|
+
? RegisteredSerializationAdapters<TRegister>[number]['~types']['input']
|
|
164
|
+
: never)
|
|
165
|
+
| Serializable
|
|
166
|
+
|
|
167
|
+
export type RegisteredSerializationAdapters<TRegister> = RegisteredConfigType<
|
|
168
|
+
TRegister,
|
|
169
|
+
'serializationAdapters'
|
|
170
|
+
>
|
|
171
|
+
|
|
172
|
+
export type ValidateSerializableInputResult<TRegister, T> =
|
|
173
|
+
ValidateSerializableResult<T, RegisteredSerializableInput<TRegister>>
|
|
174
|
+
|
|
175
|
+
export type ValidateSerializableResult<T, TSerializable> =
|
|
176
|
+
T extends TSerializable
|
|
177
|
+
? T
|
|
178
|
+
: unknown extends SerializerExtensions['ReadableStream']
|
|
179
|
+
? { [K in keyof T]: ValidateSerializableResult<T[K], TSerializable> }
|
|
180
|
+
: T extends SerializerExtensions['ReadableStream']
|
|
181
|
+
? ReadableStream
|
|
182
|
+
: { [K in keyof T]: ValidateSerializableResult<T[K], TSerializable> }
|
|
183
|
+
|
|
184
|
+
export type RegisteredSSROption<TRegister> =
|
|
185
|
+
unknown extends RegisteredConfigType<TRegister, 'defaultSsr'>
|
|
186
|
+
? SSROption
|
|
187
|
+
: RegisteredConfigType<TRegister, 'defaultSsr'>
|
|
188
|
+
|
|
189
|
+
export type ValidateSerializableLifecycleResult<
|
|
190
|
+
TRegister,
|
|
191
|
+
TParentRoute extends AnyRoute,
|
|
192
|
+
TSSR,
|
|
193
|
+
TFn,
|
|
194
|
+
> = false extends (TRegister extends { ssr: infer TSSR } ? TSSR : never)
|
|
195
|
+
? any
|
|
196
|
+
: ValidateSerializableLifecycleResultSSR<
|
|
197
|
+
TRegister,
|
|
198
|
+
TParentRoute,
|
|
199
|
+
TSSR,
|
|
200
|
+
TFn
|
|
201
|
+
> extends infer TInput
|
|
202
|
+
? TInput
|
|
203
|
+
: never
|
|
204
|
+
|
|
205
|
+
export type ValidateSerializableLifecycleResultSSR<
|
|
206
|
+
TRegister,
|
|
207
|
+
TParentRoute extends AnyRoute,
|
|
208
|
+
TSSR,
|
|
209
|
+
TFn,
|
|
210
|
+
> =
|
|
211
|
+
ResolveAllSSR<TParentRoute, TSSR> extends false
|
|
212
|
+
? any
|
|
213
|
+
: RegisteredSSROption<TRegister> extends false
|
|
214
|
+
? any
|
|
215
|
+
: ValidateSerializableInput<TRegister, LooseReturnType<TFn>>
|
package/src/ssr/server.ts
CHANGED
package/src/ssr/ssr-client.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { AnyRouteMatch, MakeRouteMatch } from '../Matches'
|
|
|
5
5
|
import type { AnyRouter } from '../router'
|
|
6
6
|
import type { Manifest } from '../manifest'
|
|
7
7
|
import type { RouteContextOptions } from '../route'
|
|
8
|
-
import type {
|
|
8
|
+
import type { AnySerializationAdapter } from './serializer/transformer'
|
|
9
9
|
import type { GLOBAL_TSR } from './constants'
|
|
10
10
|
|
|
11
11
|
declare global {
|
|
@@ -63,7 +63,7 @@ export async function hydrate(router: AnyRouter): Promise<any> {
|
|
|
63
63
|
)
|
|
64
64
|
|
|
65
65
|
const serializationAdapters = router.options.serializationAdapters as
|
|
66
|
-
| Array<
|
|
66
|
+
| Array<AnySerializationAdapter>
|
|
67
67
|
| undefined
|
|
68
68
|
|
|
69
69
|
if (serializationAdapters?.length) {
|
package/src/ssr/ssr-server.ts
CHANGED
|
@@ -10,7 +10,7 @@ import type { DehydratedMatch } from './ssr-client'
|
|
|
10
10
|
import type { DehydratedRouter } from './client'
|
|
11
11
|
import type { AnyRouteMatch } from '../Matches'
|
|
12
12
|
import type { Manifest } from '../manifest'
|
|
13
|
-
import type {
|
|
13
|
+
import type { AnySerializationAdapter } from './serializer/transformer'
|
|
14
14
|
|
|
15
15
|
declare module '../router' {
|
|
16
16
|
interface ServerSsr {
|
|
@@ -48,10 +48,13 @@ export function dehydrateMatch(match: AnyRouteMatch): DehydratedMatch {
|
|
|
48
48
|
return dehydratedMatch
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export function attachRouterServerSsrUtils(
|
|
52
|
-
router
|
|
53
|
-
manifest
|
|
54
|
-
|
|
51
|
+
export function attachRouterServerSsrUtils({
|
|
52
|
+
router,
|
|
53
|
+
manifest,
|
|
54
|
+
}: {
|
|
55
|
+
router: AnyRouter
|
|
56
|
+
manifest: Manifest | undefined
|
|
57
|
+
}) {
|
|
55
58
|
router.ssr = {
|
|
56
59
|
manifest,
|
|
57
60
|
}
|
|
@@ -81,7 +84,7 @@ export function attachRouterServerSsrUtils(
|
|
|
81
84
|
injectScript: (getScript) => {
|
|
82
85
|
return router.serverSsr!.injectHtml(async () => {
|
|
83
86
|
const script = await getScript()
|
|
84
|
-
return `<script class='$tsr'>${getInitialScript()}${script};$_TSR.c()</script>`
|
|
87
|
+
return `<script ${router.options.ssr?.nonce ? `nonce='${router.options.ssr.nonce}'` : ''} class='$tsr'>${getInitialScript()}${script};$_TSR.c()</script>`
|
|
85
88
|
})
|
|
86
89
|
},
|
|
87
90
|
dehydrate: async () => {
|
|
@@ -109,7 +112,7 @@ export function attachRouterServerSsrUtils(
|
|
|
109
112
|
const plugins =
|
|
110
113
|
(
|
|
111
114
|
router.options.serializationAdapters as
|
|
112
|
-
| Array<
|
|
115
|
+
| Array<AnySerializationAdapter>
|
|
113
116
|
| undefined
|
|
114
117
|
)?.map((t) => makeSsrSerovalPlugin(t, trackPlugins)) ?? []
|
|
115
118
|
crossSerializeStream(dehydratedRouter, {
|
package/src/utils.ts
CHANGED
|
@@ -203,6 +203,8 @@ export function functionalUpdate<TPrevious, TResult = TPrevious>(
|
|
|
203
203
|
return updater
|
|
204
204
|
}
|
|
205
205
|
|
|
206
|
+
const hasOwn = Object.prototype.hasOwnProperty
|
|
207
|
+
|
|
206
208
|
/**
|
|
207
209
|
* This function returns `prev` if `_next` is deeply equal.
|
|
208
210
|
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
@@ -218,57 +220,64 @@ export function replaceEqualDeep<T>(prev: any, _next: T): T {
|
|
|
218
220
|
|
|
219
221
|
const array = isPlainArray(prev) && isPlainArray(next)
|
|
220
222
|
|
|
221
|
-
if (array
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if (
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
223
|
+
if (!array && !(isPlainObject(prev) && isPlainObject(next))) return next
|
|
224
|
+
|
|
225
|
+
const prevItems = array ? prev : getEnumerableOwnKeys(prev)
|
|
226
|
+
if (!prevItems) return next
|
|
227
|
+
const nextItems = array ? next : getEnumerableOwnKeys(next)
|
|
228
|
+
if (!nextItems) return next
|
|
229
|
+
const prevSize = prevItems.length
|
|
230
|
+
const nextSize = nextItems.length
|
|
231
|
+
const copy: any = array ? new Array(nextSize) : {}
|
|
232
|
+
|
|
233
|
+
let equalItems = 0
|
|
234
|
+
|
|
235
|
+
for (let i = 0; i < nextSize; i++) {
|
|
236
|
+
const key = array ? i : (nextItems[i] as any)
|
|
237
|
+
const p = prev[key]
|
|
238
|
+
const n = next[key]
|
|
239
|
+
|
|
240
|
+
if (p === n) {
|
|
241
|
+
copy[key] = p
|
|
242
|
+
if (array ? i < prevSize : hasOwn.call(prev, key)) equalItems++
|
|
243
|
+
continue
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (
|
|
247
|
+
p === null ||
|
|
248
|
+
n === null ||
|
|
249
|
+
typeof p !== 'object' ||
|
|
250
|
+
typeof n !== 'object'
|
|
251
|
+
) {
|
|
252
|
+
copy[key] = n
|
|
253
|
+
continue
|
|
253
254
|
}
|
|
254
255
|
|
|
255
|
-
|
|
256
|
+
const v = replaceEqualDeep(p, n)
|
|
257
|
+
copy[key] = v
|
|
258
|
+
if (v === p) equalItems++
|
|
256
259
|
}
|
|
257
260
|
|
|
258
|
-
return
|
|
261
|
+
return prevSize === nextSize && equalItems === prevSize ? prev : copy
|
|
259
262
|
}
|
|
260
263
|
|
|
261
264
|
/**
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
* non-enumerable properties).
|
|
265
|
+
* Equivalent to `Reflect.ownKeys`, but ensures that objects are "clone-friendly":
|
|
266
|
+
* will return false if object has any non-enumerable properties.
|
|
265
267
|
*/
|
|
266
|
-
function
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
Object.
|
|
271
|
-
|
|
268
|
+
function getEnumerableOwnKeys(o: object) {
|
|
269
|
+
const keys = []
|
|
270
|
+
const names = Object.getOwnPropertyNames(o)
|
|
271
|
+
for (const name of names) {
|
|
272
|
+
if (!Object.prototype.propertyIsEnumerable.call(o, name)) return false
|
|
273
|
+
keys.push(name)
|
|
274
|
+
}
|
|
275
|
+
const symbols = Object.getOwnPropertySymbols(o)
|
|
276
|
+
for (const symbol of symbols) {
|
|
277
|
+
if (!Object.prototype.propertyIsEnumerable.call(o, symbol)) return false
|
|
278
|
+
keys.push(symbol)
|
|
279
|
+
}
|
|
280
|
+
return keys
|
|
272
281
|
}
|
|
273
282
|
|
|
274
283
|
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
@@ -306,14 +315,6 @@ export function isPlainArray(value: unknown): value is Array<unknown> {
|
|
|
306
315
|
return Array.isArray(value) && value.length === Object.keys(value).length
|
|
307
316
|
}
|
|
308
317
|
|
|
309
|
-
function getObjectKeys(obj: any, ignoreUndefined: boolean) {
|
|
310
|
-
let keys = Object.keys(obj)
|
|
311
|
-
if (ignoreUndefined) {
|
|
312
|
-
keys = keys.filter((key) => obj[key] !== undefined)
|
|
313
|
-
}
|
|
314
|
-
return keys
|
|
315
|
-
}
|
|
316
|
-
|
|
317
318
|
export function deepEqual(
|
|
318
319
|
a: any,
|
|
319
320
|
b: any,
|
|
@@ -327,23 +328,44 @@ export function deepEqual(
|
|
|
327
328
|
return false
|
|
328
329
|
}
|
|
329
330
|
|
|
331
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
332
|
+
if (a.length !== b.length) return false
|
|
333
|
+
for (let i = 0, l = a.length; i < l; i++) {
|
|
334
|
+
if (!deepEqual(a[i], b[i], opts)) return false
|
|
335
|
+
}
|
|
336
|
+
return true
|
|
337
|
+
}
|
|
338
|
+
|
|
330
339
|
if (isPlainObject(a) && isPlainObject(b)) {
|
|
331
340
|
const ignoreUndefined = opts?.ignoreUndefined ?? true
|
|
332
|
-
const aKeys = getObjectKeys(a, ignoreUndefined)
|
|
333
|
-
const bKeys = getObjectKeys(b, ignoreUndefined)
|
|
334
341
|
|
|
335
|
-
if (
|
|
336
|
-
|
|
342
|
+
if (opts?.partial) {
|
|
343
|
+
for (const k in b) {
|
|
344
|
+
if (!ignoreUndefined || b[k] !== undefined) {
|
|
345
|
+
if (!deepEqual(a[k], b[k], opts)) return false
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return true
|
|
337
349
|
}
|
|
338
350
|
|
|
339
|
-
|
|
340
|
-
|
|
351
|
+
let aCount = 0
|
|
352
|
+
if (!ignoreUndefined) {
|
|
353
|
+
aCount = Object.keys(a).length
|
|
354
|
+
} else {
|
|
355
|
+
for (const k in a) {
|
|
356
|
+
if (a[k] !== undefined) aCount++
|
|
357
|
+
}
|
|
358
|
+
}
|
|
341
359
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
360
|
+
let bCount = 0
|
|
361
|
+
for (const k in b) {
|
|
362
|
+
if (!ignoreUndefined || b[k] !== undefined) {
|
|
363
|
+
bCount++
|
|
364
|
+
if (bCount > aCount || !deepEqual(a[k], b[k], opts)) return false
|
|
365
|
+
}
|
|
345
366
|
}
|
|
346
|
-
|
|
367
|
+
|
|
368
|
+
return aCount === bCount
|
|
347
369
|
}
|
|
348
370
|
|
|
349
371
|
return false
|