mobx-keystone 2.1.0 → 2.3.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/CHANGELOG.md +17 -0
- package/README.md +1 -1
- package/dist/mobx-keystone.esm.js +555 -516
- package/dist/mobx-keystone.esm.mjs +555 -516
- package/dist/mobx-keystone.umd.js +558 -519
- package/dist/types/actionMiddlewares/undoMiddleware.d.ts +2 -10
- package/dist/types/modelShared/modelDecorator.d.ts +5 -2
- package/dist/types/modelShared/prop.d.ts +42 -29
- package/dist/types/ref/Ref.d.ts +1 -4
- package/dist/types/snapshot/SnapshotOf.d.ts +4 -4
- package/dist/types/snapshot/applySnapshot.d.ts +1 -1
- package/dist/types/snapshot/fromSnapshot.d.ts +2 -2
- package/dist/types/snapshot/getSnapshot.d.ts +1 -1
- package/dist/types/types/SnapshotTypeMismatchError.d.ts +3 -1
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/modelTypeMatching.d.ts +1 -0
- package/dist/types/types/schemas.d.ts +41 -37
- package/dist/types/types/tProp.d.ts +12 -6
- package/dist/types/types/types.d.ts +6 -6
- package/dist/types/types/utility/typeToStoredData.d.ts +14 -10
- package/dist/types/types/utility/typesCodecCore.d.ts +3 -0
- package/dist/types/utils/ModelPool.d.ts +0 -1
- package/dist/types/utils/types.d.ts +6 -0
- package/dist/types/wrappers/ArraySet.d.ts +1 -0
- package/package.json +13 -11
- package/src/action/modelFlow.ts +35 -66
- package/src/actionMiddlewares/actionTrackingMiddleware.ts +41 -71
- package/src/actionMiddlewares/transactionMiddleware.ts +1 -1
- package/src/actionMiddlewares/undoMiddleware.ts +16 -22
- package/src/context/context.ts +15 -36
- package/src/dataModel/utils.ts +5 -28
- package/src/deepChange/onDeepChange.ts +44 -126
- package/src/model/BaseModel.ts +1 -1
- package/src/model/utils.ts +5 -10
- package/src/modelShared/modelDecorator.ts +13 -10
- package/src/modelShared/modelInfo.ts +75 -0
- package/src/modelShared/prop.ts +115 -111
- package/src/modelShared/sharedInternalModel.ts +2 -2
- package/src/parent/arrayPaths.ts +1 -4
- package/src/parent/path.ts +0 -10
- package/src/patch/patchRecorder.ts +13 -28
- package/src/ref/core.ts +6 -19
- package/src/rootStore/rootStore.ts +1 -3
- package/src/snapshot/SnapshotOf.ts +24 -48
- package/src/snapshot/applySnapshot.ts +1 -1
- package/src/snapshot/fromSnapshot.ts +10 -3
- package/src/snapshot/getSnapshot.ts +1 -1
- package/src/snapshot/internal.ts +0 -2
- package/src/snapshot/reconcileModelSnapshot.ts +5 -3
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +3 -1
- package/src/treeUtils/draft.ts +6 -1
- package/src/treeUtils/sandbox.ts +10 -7
- package/src/tweaker/tweakArray.ts +20 -50
- package/src/tweaker/tweakPlainObject.ts +9 -15
- package/src/types/SnapshotTypeMismatchError.ts +3 -1
- package/src/types/arrayBased/typesArray.ts +13 -19
- package/src/types/arrayBased/typesTuple.ts +16 -25
- package/src/types/createCachedTypeCheck.ts +17 -30
- package/src/types/index.ts +1 -0
- package/src/types/modelTypeMatching.ts +276 -0
- package/src/types/objectBased/typesDataModelData.ts +7 -8
- package/src/types/objectBased/typesModel.ts +23 -6
- package/src/types/objectBased/typesObject.ts +11 -15
- package/src/types/objectBased/typesRecord.ts +11 -15
- package/src/types/objectBased/typesRef.ts +23 -4
- package/src/types/schemas.ts +59 -71
- package/src/types/tProp.ts +29 -29
- package/src/types/utility/typeToStoredData.ts +22 -21
- package/src/types/utility/typesCodecCore.ts +8 -1
- package/src/types/utility/typesCodecSupport.ts +16 -10
- package/src/types/utility/typesMap.ts +43 -51
- package/src/types/utility/typesOr.ts +38 -8
- package/src/types/utility/typesRefinement.ts +7 -8
- package/src/types/utility/typesSkipCheck.ts +7 -8
- package/src/types/utility/typesTag.ts +7 -8
- package/src/utils/ModelPool.ts +1 -18
- package/src/utils/decorators.ts +5 -5
- package/src/utils/index.ts +1 -20
- package/src/utils/types.ts +5 -0
- package/src/wrappers/ArraySet.ts +27 -14
- package/src/wrappers/ObjectMap.ts +1 -6
- package/src/wrappers/asMap.ts +1 -21
- package/src/wrappers/asSet.ts +0 -8
|
@@ -48,7 +48,9 @@ function reconcilePlainObjectSnapshot(
|
|
|
48
48
|
const k = snKeys[i]
|
|
49
49
|
const v = sn[k]
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// an inherited member such as `toString` is no old value (but `__proto__`
|
|
52
|
+
// still reads the prototype, which is rejected as it is no tree node)
|
|
53
|
+
const oldValue = k === "__proto__" || hasOwnProp(plainObj, k) ? plainObj[k] : undefined
|
|
52
54
|
const newValue = withErrorPathSegment(k, () =>
|
|
53
55
|
reconcileSnapshot(oldValue, v, modelPool, plainObj)
|
|
54
56
|
)
|
package/src/treeUtils/draft.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { applySnapshot } from "../snapshot/applySnapshot"
|
|
|
6
6
|
import { fromSnapshot } from "../snapshot/fromSnapshot"
|
|
7
7
|
import { getSnapshot } from "../snapshot/getSnapshot"
|
|
8
8
|
import { assertTweakedObject } from "../tweaker/core"
|
|
9
|
-
import { failure, mobxAction, mobxComputed } from "../utils"
|
|
9
|
+
import { failure, getMobxVersion, makeObservableCompat, mobxAction, mobxComputed } from "../utils"
|
|
10
10
|
import { deepEquals } from "./deepEquals"
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -157,6 +157,11 @@ export class Draft<T extends object> {
|
|
|
157
157
|
assertTweakedObject(original, "original")
|
|
158
158
|
|
|
159
159
|
this.originalData = original
|
|
160
|
+
|
|
161
|
+
if (getMobxVersion() >= 6) {
|
|
162
|
+
makeObservableCompat(this)
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
this.data = fromSnapshot(this.originalSnapshot, { generateNewIds: false })
|
|
161
166
|
}
|
|
162
167
|
}
|
package/src/treeUtils/sandbox.ts
CHANGED
|
@@ -233,9 +233,11 @@ export class SandboxManager {
|
|
|
233
233
|
// see the reverted intermediate state.
|
|
234
234
|
runInAction(() => {
|
|
235
235
|
this.allowWrite(() => {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
236
|
+
applyPatches(
|
|
237
|
+
this.subtreeRootClone,
|
|
238
|
+
events.map((event) => event.inversePatches),
|
|
239
|
+
true
|
|
240
|
+
)
|
|
239
241
|
})
|
|
240
242
|
applyPatches(
|
|
241
243
|
this.subtreeRoot,
|
|
@@ -249,10 +251,11 @@ export class SandboxManager {
|
|
|
249
251
|
const wasRecording = recorder.recording
|
|
250
252
|
recorder.recording = false
|
|
251
253
|
try {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
254
|
+
applyPatches(
|
|
255
|
+
this.subtreeRootClone,
|
|
256
|
+
recorder.events.slice(numRecorderEvents).map((event) => event.inversePatches),
|
|
257
|
+
true
|
|
258
|
+
)
|
|
256
259
|
recorder.events.splice(numRecorderEvents)
|
|
257
260
|
} finally {
|
|
258
261
|
recorder.recording = wasRecording
|
|
@@ -289,7 +289,6 @@ function arrayDidChangeUpdate(
|
|
|
289
289
|
) {
|
|
290
290
|
const k = change.index
|
|
291
291
|
const val = change.newValue
|
|
292
|
-
const oldVal = oldSnapshot[k]
|
|
293
292
|
let newVal: any
|
|
294
293
|
if (isPrimitive(val)) {
|
|
295
294
|
newVal = val
|
|
@@ -299,15 +298,14 @@ function arrayDidChangeUpdate(
|
|
|
299
298
|
}
|
|
300
299
|
const mutate = mutateSet.bind(undefined, k, newVal)
|
|
301
300
|
|
|
302
|
-
if (
|
|
301
|
+
if (shouldBuildInversePatches) {
|
|
303
302
|
const path = [k]
|
|
304
303
|
const patches = shouldEmitPatches
|
|
305
304
|
? [{ op: "replace" as const, path, value: freezeInternalSnapshot(newVal) }]
|
|
306
305
|
: undefined
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
patchRecorder.record(patches, invPatches)
|
|
306
|
+
patchRecorder.record(patches, [
|
|
307
|
+
{ op: "replace" as const, path, value: freezeInternalSnapshot(oldSnapshot[k]) },
|
|
308
|
+
])
|
|
311
309
|
}
|
|
312
310
|
return mutate
|
|
313
311
|
}
|
|
@@ -335,17 +333,16 @@ function arrayDidChangeSplice(
|
|
|
335
333
|
|
|
336
334
|
const mutate = mutateSplice.bind(undefined, index, removedCount, addedItems)
|
|
337
335
|
|
|
338
|
-
// With neither patch listeners nor type checking, there is no
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
if (!shouldEmitPatches && !shouldBuildInversePatches) {
|
|
336
|
+
// With neither patch listeners nor type checking, there is no patch data to
|
|
337
|
+
// build. The snapshot mutation above is all the post-change work we need.
|
|
338
|
+
if (!shouldBuildInversePatches) {
|
|
342
339
|
return mutate
|
|
343
340
|
}
|
|
344
341
|
|
|
345
342
|
const oldLen = oldSnapshot.length
|
|
346
343
|
|
|
347
344
|
const patches: Patch[] | undefined = shouldEmitPatches ? [] : undefined
|
|
348
|
-
const invPatches: Patch[]
|
|
345
|
+
const invPatches: Patch[] = []
|
|
349
346
|
|
|
350
347
|
// optimization: if we add as many as we remove then remove/readd instead
|
|
351
348
|
|
|
@@ -357,13 +354,13 @@ function arrayDidChangeSplice(
|
|
|
357
354
|
|
|
358
355
|
if (addedCount === removedCount) {
|
|
359
356
|
const readdPatches: Patch[] | undefined = shouldEmitPatches ? [] : undefined
|
|
360
|
-
const readdInvPatches: Patch[]
|
|
357
|
+
const readdInvPatches: Patch[] = []
|
|
361
358
|
let removed = 0
|
|
362
359
|
|
|
363
360
|
for (let i = 0; i < addedCount; i++) {
|
|
364
361
|
const realIndex = index + i
|
|
365
362
|
|
|
366
|
-
const newVal =
|
|
363
|
+
const newVal = addedItems[i]
|
|
367
364
|
const oldVal = oldSnapshot[realIndex]
|
|
368
365
|
|
|
369
366
|
if (newVal !== oldVal) {
|
|
@@ -372,7 +369,7 @@ function arrayDidChangeSplice(
|
|
|
372
369
|
op: "remove",
|
|
373
370
|
path: removePath,
|
|
374
371
|
})
|
|
375
|
-
invPatches
|
|
372
|
+
invPatches.push({
|
|
376
373
|
op: "remove",
|
|
377
374
|
path: removePath,
|
|
378
375
|
})
|
|
@@ -386,7 +383,7 @@ function arrayDidChangeSplice(
|
|
|
386
383
|
value: freezeInternalSnapshot(newVal),
|
|
387
384
|
})
|
|
388
385
|
|
|
389
|
-
readdInvPatches
|
|
386
|
+
readdInvPatches.push({
|
|
390
387
|
op: "add",
|
|
391
388
|
path: readdPath,
|
|
392
389
|
value: freezeInternalSnapshot(oldVal),
|
|
@@ -394,17 +391,13 @@ function arrayDidChangeSplice(
|
|
|
394
391
|
}
|
|
395
392
|
}
|
|
396
393
|
|
|
397
|
-
if (patches && readdPatches
|
|
394
|
+
if (patches && readdPatches) {
|
|
398
395
|
for (const patch of readdPatches) patches.push(patch)
|
|
399
396
|
}
|
|
400
|
-
|
|
401
|
-
for (const patch of readdInvPatches) invPatches.push(patch)
|
|
402
|
-
}
|
|
397
|
+
for (const patch of readdInvPatches) invPatches.push(patch)
|
|
403
398
|
// We need to reverse once since inverse patches are applied in reverse.
|
|
404
399
|
// Repeated unshift calls here would make a large splice quadratic.
|
|
405
|
-
|
|
406
|
-
invPatches.reverse()
|
|
407
|
-
}
|
|
400
|
+
invPatches.reverse()
|
|
408
401
|
} else {
|
|
409
402
|
const interimLen = oldLen - removedCount
|
|
410
403
|
|
|
@@ -433,7 +426,7 @@ function arrayDidChangeSplice(
|
|
|
433
426
|
}
|
|
434
427
|
|
|
435
428
|
// add 0, 1, 2... since inverse patches are applied in reverse
|
|
436
|
-
invPatches
|
|
429
|
+
invPatches.push({
|
|
437
430
|
op: "add",
|
|
438
431
|
path,
|
|
439
432
|
value: freezeInternalSnapshot(oldSnapshot[realIndex]),
|
|
@@ -446,7 +439,7 @@ function arrayDidChangeSplice(
|
|
|
446
439
|
// optimization, for inverse patches, when adding from the end set the length to restore instead
|
|
447
440
|
const restoreUsingSetLength = index >= interimLen
|
|
448
441
|
if (restoreUsingSetLength) {
|
|
449
|
-
invPatches
|
|
442
|
+
invPatches.push({
|
|
450
443
|
op: "replace",
|
|
451
444
|
path: ["length"],
|
|
452
445
|
value: interimLen,
|
|
@@ -461,14 +454,12 @@ function arrayDidChangeSplice(
|
|
|
461
454
|
patches?.push({
|
|
462
455
|
op: "add",
|
|
463
456
|
path,
|
|
464
|
-
value: freezeInternalSnapshot(
|
|
465
|
-
getValueAfterSplice(oldSnapshot, realIndex, index, removedCount, addedItems)
|
|
466
|
-
),
|
|
457
|
+
value: freezeInternalSnapshot(addedItems[i]),
|
|
467
458
|
})
|
|
468
459
|
|
|
469
460
|
// remove ...2, 1, 0 since inverse patches are applied in reverse
|
|
470
461
|
if (!restoreUsingSetLength) {
|
|
471
|
-
invPatches
|
|
462
|
+
invPatches.push({
|
|
472
463
|
op: "remove",
|
|
473
464
|
path,
|
|
474
465
|
})
|
|
@@ -477,9 +468,7 @@ function arrayDidChangeSplice(
|
|
|
477
468
|
}
|
|
478
469
|
}
|
|
479
470
|
|
|
480
|
-
|
|
481
|
-
patchRecorder.record(patches, invPatches)
|
|
482
|
-
}
|
|
471
|
+
patchRecorder.record(patches, invPatches)
|
|
483
472
|
return mutate
|
|
484
473
|
}
|
|
485
474
|
|
|
@@ -676,22 +665,3 @@ class ObservableArrayReplacementQueue {
|
|
|
676
665
|
}
|
|
677
666
|
}
|
|
678
667
|
}
|
|
679
|
-
|
|
680
|
-
function getValueAfterSplice<T>(
|
|
681
|
-
array: readonly T[],
|
|
682
|
-
i: number,
|
|
683
|
-
index: number,
|
|
684
|
-
remove: number,
|
|
685
|
-
addedItems: readonly T[]
|
|
686
|
-
) {
|
|
687
|
-
const base = i - index
|
|
688
|
-
if (base < 0) {
|
|
689
|
-
return array[i]
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
if (base < addedItems.length) {
|
|
693
|
-
return addedItems[base]
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
return array[i - addedItems.length + remove]
|
|
697
|
-
}
|
|
@@ -295,16 +295,14 @@ function objectDidChangeRemove(
|
|
|
295
295
|
shouldBuildInversePatches: boolean
|
|
296
296
|
) {
|
|
297
297
|
const k = change.name
|
|
298
|
-
const oldVal = oldUntransformedSn[k]
|
|
299
298
|
const mutate = mutateDelete.bind(undefined, k)
|
|
300
299
|
|
|
301
|
-
if (
|
|
300
|
+
if (shouldBuildInversePatches) {
|
|
302
301
|
const path = [k as string]
|
|
303
302
|
const patches = shouldEmitPatches ? [{ op: "remove" as const, path }] : undefined
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
patchRecorder.record(patches, invPatches)
|
|
303
|
+
patchRecorder.record(patches, [
|
|
304
|
+
{ op: "add" as const, path, value: freezeInternalSnapshot(oldUntransformedSn[k]) },
|
|
305
|
+
])
|
|
308
306
|
}
|
|
309
307
|
return mutate
|
|
310
308
|
}
|
|
@@ -318,8 +316,6 @@ function objectDidChangeAddOrUpdate(
|
|
|
318
316
|
const k = change.name
|
|
319
317
|
const val = change.newValue
|
|
320
318
|
|
|
321
|
-
const oldVal = oldUntransformedSn[k]
|
|
322
|
-
|
|
323
319
|
let newVal: any
|
|
324
320
|
if (isPrimitive(val)) {
|
|
325
321
|
newVal = val
|
|
@@ -330,22 +326,20 @@ function objectDidChangeAddOrUpdate(
|
|
|
330
326
|
|
|
331
327
|
const mutate = mutateSet.bind(undefined, k, newVal)
|
|
332
328
|
|
|
333
|
-
if (
|
|
329
|
+
if (shouldBuildInversePatches) {
|
|
334
330
|
const path = [k as string]
|
|
335
331
|
if (change.type === "add") {
|
|
336
332
|
const patches = shouldEmitPatches
|
|
337
333
|
? [{ op: "add" as const, path, value: freezeInternalSnapshot(newVal) }]
|
|
338
334
|
: undefined
|
|
339
|
-
|
|
340
|
-
patchRecorder.record(patches, invPatches)
|
|
335
|
+
patchRecorder.record(patches, [{ op: "remove" as const, path }])
|
|
341
336
|
} else {
|
|
342
337
|
const patches = shouldEmitPatches
|
|
343
338
|
? [{ op: "replace" as const, path, value: freezeInternalSnapshot(newVal) }]
|
|
344
339
|
: undefined
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
patchRecorder.record(patches, invPatches)
|
|
340
|
+
patchRecorder.record(patches, [
|
|
341
|
+
{ op: "replace" as const, path, value: freezeInternalSnapshot(oldUntransformedSn[k]) },
|
|
342
|
+
])
|
|
349
343
|
}
|
|
350
344
|
}
|
|
351
345
|
|
|
@@ -14,7 +14,9 @@ export interface SnapshotTypeMismatchErrorData {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
|
-
* Thrown when a snapshot value does not match any of the expected types in a union
|
|
17
|
+
* Thrown when a snapshot value does not match any of the expected types in a union, or when a
|
|
18
|
+
* model snapshot names a model (`$modelType`) that is not the expected model or a subclass of it
|
|
19
|
+
* (extends `MobxKeystoneError`).
|
|
18
20
|
*
|
|
19
21
|
* Use `instanceof SnapshotTypeMismatchError` to distinguish snapshot type-mismatch errors
|
|
20
22
|
* from other `MobxKeystoneError` instances.
|
|
@@ -50,6 +50,16 @@ export function typesArray<T extends AnyType>(itemType: T): ArrayType<T[]> {
|
|
|
50
50
|
}
|
|
51
51
|
)
|
|
52
52
|
|
|
53
|
+
const processorPlan = snapshotProcessorPlan(
|
|
54
|
+
() => [itemChecker],
|
|
55
|
+
([itemProcessor]) =>
|
|
56
|
+
itemProcessor
|
|
57
|
+
? (sn: unknown[]) => {
|
|
58
|
+
return sn.map((item, i) => withErrorPathSegment(i, () => itemProcessor(item)))
|
|
59
|
+
}
|
|
60
|
+
: undefined
|
|
61
|
+
)
|
|
62
|
+
|
|
53
63
|
const thisTc: TypeChecker = new TypeChecker(
|
|
54
64
|
TypeCheckerBaseType.Array,
|
|
55
65
|
|
|
@@ -89,25 +99,9 @@ export function typesArray<T extends AnyType>(itemType: T): ArrayType<T[]> {
|
|
|
89
99
|
return thisTc
|
|
90
100
|
},
|
|
91
101
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
itemProcessor
|
|
96
|
-
? (sn: unknown[]) => {
|
|
97
|
-
return sn.map((item, i) => withErrorPathSegment(i, () => itemProcessor(item)))
|
|
98
|
-
}
|
|
99
|
-
: undefined
|
|
100
|
-
),
|
|
101
|
-
|
|
102
|
-
snapshotProcessorPlan(
|
|
103
|
-
() => [itemChecker],
|
|
104
|
-
([itemProcessor]) =>
|
|
105
|
-
itemProcessor
|
|
106
|
-
? (sn: unknown[]) => {
|
|
107
|
-
return sn.map((item, i) => withErrorPathSegment(i, () => itemProcessor(item)))
|
|
108
|
-
}
|
|
109
|
-
: undefined
|
|
110
|
-
)
|
|
102
|
+
processorPlan,
|
|
103
|
+
|
|
104
|
+
processorPlan
|
|
111
105
|
)
|
|
112
106
|
|
|
113
107
|
return thisTc
|
|
@@ -68,6 +68,19 @@ export function typesTuple<T extends AnyType[]>(...itemTypes: T): ArrayType<T> {
|
|
|
68
68
|
// computeds cannot isolate tuple-item changes and only add allocation overhead.
|
|
69
69
|
const checkTupleItems = createWholeContainerCachedCheck(checkTupleItemsImperatively)
|
|
70
70
|
|
|
71
|
+
const processorPlan = snapshotProcessorPlan(
|
|
72
|
+
() => checkers,
|
|
73
|
+
(processors) =>
|
|
74
|
+
processors.some(Boolean)
|
|
75
|
+
? (array: unknown[]) => {
|
|
76
|
+
return array.map((item, i) => {
|
|
77
|
+
const processor = processors[i]
|
|
78
|
+
return processor ? withErrorPathSegment(i, () => processor(item)) : item
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
: undefined
|
|
82
|
+
)
|
|
83
|
+
|
|
71
84
|
const thisTc: TypeChecker = new TypeChecker(
|
|
72
85
|
TypeCheckerBaseType.Array,
|
|
73
86
|
|
|
@@ -102,31 +115,9 @@ export function typesTuple<T extends AnyType[]>(...itemTypes: T): ArrayType<T> {
|
|
|
102
115
|
return thisTc
|
|
103
116
|
},
|
|
104
117
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
processors.some(Boolean)
|
|
109
|
-
? (array: unknown[]) => {
|
|
110
|
-
return array.map((item, i) => {
|
|
111
|
-
const processor = processors[i]
|
|
112
|
-
return processor ? withErrorPathSegment(i, () => processor(item)) : item
|
|
113
|
-
})
|
|
114
|
-
}
|
|
115
|
-
: undefined
|
|
116
|
-
),
|
|
117
|
-
|
|
118
|
-
snapshotProcessorPlan(
|
|
119
|
-
() => checkers,
|
|
120
|
-
(processors) =>
|
|
121
|
-
processors.some(Boolean)
|
|
122
|
-
? (array: unknown[]) => {
|
|
123
|
-
return array.map((item, i) => {
|
|
124
|
-
const processor = processors[i]
|
|
125
|
-
return processor ? withErrorPathSegment(i, () => processor(item)) : item
|
|
126
|
-
})
|
|
127
|
-
}
|
|
128
|
-
: undefined
|
|
129
|
-
)
|
|
118
|
+
processorPlan,
|
|
119
|
+
|
|
120
|
+
processorPlan
|
|
130
121
|
)
|
|
131
122
|
|
|
132
123
|
return thisTc
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from "../tweaker/tweakedChangeListeners"
|
|
20
20
|
import { getMobxVersion } from "../utils"
|
|
21
21
|
import { ChunkedSequence, ChunkedSet, chunkSize, type SequenceChunk } from "../utils/chunks"
|
|
22
|
+
import { getOrCreate } from "../utils/mapUtils"
|
|
22
23
|
import { TypeCheckError } from "./TypeCheckError"
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -79,11 +80,7 @@ function checkUncached(
|
|
|
79
80
|
typeCheckedValue: any,
|
|
80
81
|
check: () => TypeCheckError | null
|
|
81
82
|
): TypeCheckError | null {
|
|
82
|
-
|
|
83
|
-
if (!results) {
|
|
84
|
-
results = new Map()
|
|
85
|
-
uncachedResults!.set(checker, results)
|
|
86
|
-
}
|
|
83
|
+
const results = getOrCreate(uncachedResults!, checker, () => new Map())
|
|
87
84
|
let error = results.get(value)
|
|
88
85
|
if (error === undefined) {
|
|
89
86
|
error = check()
|
|
@@ -152,11 +149,9 @@ export function createWholeContainerCachedCheck(
|
|
|
152
149
|
)
|
|
153
150
|
}
|
|
154
151
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
cache.set(value, cached)
|
|
159
|
-
}
|
|
152
|
+
const cached = getOrCreate(cache, value, () =>
|
|
153
|
+
computed(() => check(value, emptyPath, undefined), { keepAlive: true })
|
|
154
|
+
)
|
|
160
155
|
const error = cached.get()
|
|
161
156
|
return contextualizeCachedError(error, path, typeCheckedValue)
|
|
162
157
|
}
|
|
@@ -167,6 +162,10 @@ export function createWholeContainerCachedCheck(
|
|
|
167
162
|
// check new chunks twice.
|
|
168
163
|
const needsBatchToCacheChunks = getMobxVersion() < 6
|
|
169
164
|
|
|
165
|
+
function checkChunks<T>(fn: () => T): T {
|
|
166
|
+
return needsBatchToCacheChunks ? transaction(fn) : fn()
|
|
167
|
+
}
|
|
168
|
+
|
|
170
169
|
/**
|
|
171
170
|
* Checks the items of an array, starting at `firstIndex`, and returns the first
|
|
172
171
|
* error, or null.
|
|
@@ -328,14 +327,8 @@ class RecordChunks
|
|
|
328
327
|
readonly atom = createAtom("recordTypeCheckChunks")
|
|
329
328
|
private readonly record: object
|
|
330
329
|
private readonly checkKey: (key: string) => TypeCheckError | null
|
|
331
|
-
private readonly getEntry = (key: string): CachedEntry =>
|
|
332
|
-
|
|
333
|
-
if (!entry) {
|
|
334
|
-
entry = computed(() => this.checkKey(key))
|
|
335
|
-
this.entries.set(key, entry)
|
|
336
|
-
}
|
|
337
|
-
return entry
|
|
338
|
-
}
|
|
330
|
+
private readonly getEntry = (key: string): CachedEntry =>
|
|
331
|
+
getOrCreate(this.entries, key, () => computed(() => this.checkKey(key)))
|
|
339
332
|
|
|
340
333
|
constructor(record: object, checkKey: (key: string) => TypeCheckError | null) {
|
|
341
334
|
super()
|
|
@@ -458,10 +451,7 @@ export function createChunkedRecordCachedCheck(
|
|
|
458
451
|
const chunks = cached?.chunks
|
|
459
452
|
return checkUncached(cache, value, path, typeCheckedValue, () => {
|
|
460
453
|
if (chunks && typeof key === "string") {
|
|
461
|
-
|
|
462
|
-
? transaction(() => chunks.hasError(key))
|
|
463
|
-
: chunks.hasError(key)
|
|
464
|
-
if (!hasError) {
|
|
454
|
+
if (!checkChunks(() => chunks.hasError(key))) {
|
|
465
455
|
return null
|
|
466
456
|
}
|
|
467
457
|
}
|
|
@@ -475,11 +465,10 @@ export function createChunkedRecordCachedCheck(
|
|
|
475
465
|
addTweakedChangeListener<object>(value, chunks)
|
|
476
466
|
const check = computed(
|
|
477
467
|
() => {
|
|
478
|
-
const hasError = needsBatchToCacheChunks
|
|
479
|
-
? transaction(() => chunks.hasError())
|
|
480
|
-
: chunks.hasError()
|
|
481
468
|
// any added or removed key changes a chunk, so this runs again then
|
|
482
|
-
return
|
|
469
|
+
return checkChunks(() => chunks.hasError())
|
|
470
|
+
? checkAllEntries(value, emptyPath, undefined)
|
|
471
|
+
: null
|
|
483
472
|
},
|
|
484
473
|
{ keepAlive: true }
|
|
485
474
|
)
|
|
@@ -535,9 +524,7 @@ export function createChunkedArrayCachedCheck(
|
|
|
535
524
|
if (!chunks || typeof index !== "number") {
|
|
536
525
|
return checkItems(array, 0, emptyPath, undefined)
|
|
537
526
|
}
|
|
538
|
-
return
|
|
539
|
-
? transaction(() => chunks.check(index))
|
|
540
|
-
: chunks.check(index)
|
|
527
|
+
return checkChunks(() => chunks.check(index))
|
|
541
528
|
})
|
|
542
529
|
}
|
|
543
530
|
|
|
@@ -561,7 +548,7 @@ export function createChunkedArrayCachedCheck(
|
|
|
561
548
|
}
|
|
562
549
|
|
|
563
550
|
const chunks = state.chunks
|
|
564
|
-
return
|
|
551
|
+
return checkChunks(() => chunks.check())
|
|
565
552
|
},
|
|
566
553
|
{ keepAlive: true }
|
|
567
554
|
),
|
package/src/types/index.ts
CHANGED