mobx-keystone 1.22.0 → 1.24.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 +12 -0
- package/LICENSE +21 -21
- package/README.md +1 -1
- package/dist/mobx-keystone.esm.js +7198 -6242
- package/dist/mobx-keystone.esm.mjs +7198 -6242
- package/dist/mobx-keystone.umd.js +7217 -6243
- package/dist/types/action/runUnprotected.d.ts +8 -4
- package/dist/types/model/Model.d.ts +5 -0
- package/dist/types/modelShared/modelDecorator.d.ts +1 -1
- package/dist/types/modelShared/prop.d.ts +8 -4
- package/dist/types/snapshot/modelInitialData.d.ts +1 -0
- package/dist/types/tweaker/treeNodeMetadata.d.ts +1 -0
- package/dist/types/types/createCachedTypeCheck.d.ts +1 -0
- package/dist/types/utils/index.d.ts +24 -0
- package/package.json +15 -11
- package/src/action/middleware.ts +5 -18
- package/src/action/mutationBatch.ts +72 -0
- package/src/action/runUnprotected.ts +21 -8
- package/src/action/wrapInAction.ts +45 -15
- package/src/actionMiddlewares/undoMiddleware.ts +19 -13
- package/src/dataModel/BaseDataModel.ts +4 -8
- package/src/deepChange/onDeepChange.ts +246 -16
- package/src/model/BaseModel.ts +4 -12
- package/src/model/Model.ts +5 -0
- package/src/model/newModel.ts +68 -36
- package/src/modelShared/modelDecorator.ts +64 -53
- package/src/modelShared/prop.ts +105 -63
- package/src/modelShared/sharedInternalModel.ts +91 -60
- package/src/parent/core.ts +16 -10
- package/src/parent/coreObjectChildren.ts +219 -21
- package/src/parent/path.ts +6 -5
- package/src/parent/setParent.ts +5 -5
- package/src/patch/emitPatch.ts +102 -20
- package/src/ref/Ref.ts +4 -5
- package/src/ref/core.ts +2 -2
- package/src/snapshot/fromArraySnapshot.ts +11 -2
- package/src/snapshot/fromModelSnapshot.ts +10 -3
- package/src/snapshot/fromPlainObjectSnapshot.ts +18 -7
- package/src/snapshot/fromSnapshot.ts +31 -9
- package/src/snapshot/getSnapshot.ts +8 -3
- package/src/snapshot/internal.ts +243 -82
- package/src/snapshot/modelInitialData.ts +41 -0
- package/src/snapshot/reconcileArraySnapshot.ts +9 -3
- package/src/snapshot/reconcileModelSnapshot.ts +97 -17
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +9 -3
- package/src/treeUtils/draft.ts +7 -8
- package/src/tweaker/core.ts +30 -5
- package/src/tweaker/treeNodeMetadata.ts +38 -0
- package/src/tweaker/tweak.ts +15 -4
- package/src/tweaker/tweakArray.ts +159 -121
- package/src/tweaker/tweakFrozen.ts +2 -2
- package/src/tweaker/tweakModel.ts +2 -2
- package/src/tweaker/tweakPlainObject.ts +117 -124
- package/src/tweaker/typeChecking.ts +10 -1
- package/src/types/TypeChecker.ts +261 -15
- package/src/types/arrayBased/typesArray.ts +38 -40
- package/src/types/arrayBased/typesTuple.ts +51 -34
- package/src/types/createCachedTypeCheck.ts +181 -0
- package/src/types/objectBased/typesArraySet.ts +42 -32
- package/src/types/objectBased/typesDataModelData.ts +18 -11
- package/src/types/objectBased/typesModel.ts +1 -1
- package/src/types/objectBased/typesObject.ts +57 -28
- package/src/types/objectBased/typesObjectMap.ts +51 -40
- package/src/types/objectBased/typesRecord.ts +59 -39
- package/src/types/objectBased/typesRef.ts +1 -1
- package/src/types/primitiveBased/typesPrimitive.ts +9 -9
- package/src/types/tProp.ts +80 -44
- package/src/types/utility/typesOr.ts +35 -24
- package/src/types/utility/typesRefinement.ts +21 -8
- package/src/types/utility/typesSkipCheck.ts +21 -8
- package/src/types/utility/typesTag.ts +21 -9
- package/src/types/utility/typesUnchecked.ts +2 -3
- package/src/utils/ModelPool.ts +34 -19
- package/src/utils/errorDiagnostics.ts +60 -18
- package/src/utils/index.ts +142 -9
- package/src/types/createPerEntryCachedCheck.ts +0 -166
- /package/dist/types/{types/createPerEntryCachedCheck.d.ts → action/mutationBatch.d.ts} +0 -0
package/src/ref/Ref.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { computed } from "mobx"
|
|
2
1
|
import { Model } from "../model/Model"
|
|
3
2
|
import { modelTypeKey } from "../model/metadata"
|
|
4
3
|
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
5
4
|
import { typesString } from "../types/primitiveBased/typesPrimitive"
|
|
6
5
|
import { tProp } from "../types/tProp"
|
|
7
|
-
import { failure } from "../utils"
|
|
6
|
+
import { failure, mobxComputed } from "../utils"
|
|
8
7
|
|
|
9
8
|
/**
|
|
10
9
|
* A reference model base type.
|
|
@@ -21,7 +20,7 @@ export abstract class Ref<T extends object> extends Model({
|
|
|
21
20
|
/**
|
|
22
21
|
* The object this reference points to, or `undefined` if the reference is currently invalid.
|
|
23
22
|
*/
|
|
24
|
-
@
|
|
23
|
+
@mobxComputed
|
|
25
24
|
get maybeCurrent(): T | undefined {
|
|
26
25
|
return this.resolve()
|
|
27
26
|
}
|
|
@@ -29,7 +28,7 @@ export abstract class Ref<T extends object> extends Model({
|
|
|
29
28
|
/**
|
|
30
29
|
* If the reference is currently valid.
|
|
31
30
|
*/
|
|
32
|
-
@
|
|
31
|
+
@mobxComputed
|
|
33
32
|
get isValid(): boolean {
|
|
34
33
|
return !!this.maybeCurrent
|
|
35
34
|
}
|
|
@@ -37,7 +36,7 @@ export abstract class Ref<T extends object> extends Model({
|
|
|
37
36
|
/**
|
|
38
37
|
* The object this reference points to, or throws if invalid.
|
|
39
38
|
*/
|
|
40
|
-
@
|
|
39
|
+
@mobxComputed
|
|
41
40
|
get current(): T {
|
|
42
41
|
const current = this.maybeCurrent
|
|
43
42
|
|
package/src/ref/core.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { fastGetRoot } from "../parent/path"
|
|
10
10
|
import { type ComputedWalkTreeAggregate, computedWalkTreeAggregate } from "../parent/walkTree"
|
|
11
11
|
import { assertTweakedObject } from "../tweaker/core"
|
|
12
|
-
import { assertIsObject, failure } from "../utils"
|
|
12
|
+
import { assertIsObject, failure, mobxAction } from "../utils"
|
|
13
13
|
import { getOrCreate } from "../utils/mapUtils"
|
|
14
14
|
import { Ref, type RefConstructor } from "./Ref"
|
|
15
15
|
|
|
@@ -103,7 +103,7 @@ export function internalCustomRef<T extends object>(
|
|
|
103
103
|
return true
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
@
|
|
106
|
+
@mobxAction
|
|
107
107
|
forceUpdateBackRefs() {
|
|
108
108
|
const currentTarget = this.maybeCurrent
|
|
109
109
|
if (!this.startTracking(currentTarget)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { tweakArray } from "../tweaker/tweakArray"
|
|
2
2
|
import { isArray } from "../utils"
|
|
3
|
-
import {
|
|
3
|
+
import { getCurrentErrorDiagnosticsContext } from "../utils/errorDiagnostics"
|
|
4
4
|
import { type FromSnapshotContext, internalFromSnapshot, registerSnapshotter } from "./fromSnapshot"
|
|
5
5
|
import type { SnapshotInOfObject } from "./SnapshotOf"
|
|
6
6
|
import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
|
|
@@ -8,8 +8,17 @@ import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPrio
|
|
|
8
8
|
function fromArraySnapshot(sn: SnapshotInOfObject<any>, ctx: FromSnapshotContext): any[] {
|
|
9
9
|
const ln = sn.length
|
|
10
10
|
const arr: any[] = new Array(ln)
|
|
11
|
+
// Hydration visits every slot. Keep this direct stack use rather than
|
|
12
|
+
// withErrorPathSegment: it avoids one callback closure per item and has a
|
|
13
|
+
// measured production hydration win.
|
|
14
|
+
const errorDiagnosticsContext = getCurrentErrorDiagnosticsContext()
|
|
11
15
|
for (let i = 0; i < ln; i++) {
|
|
12
|
-
|
|
16
|
+
errorDiagnosticsContext?.pushPath(i)
|
|
17
|
+
try {
|
|
18
|
+
arr[i] = internalFromSnapshot(sn[i], ctx)
|
|
19
|
+
} finally {
|
|
20
|
+
errorDiagnosticsContext?.popPath()
|
|
21
|
+
}
|
|
13
22
|
}
|
|
14
23
|
return tweakArray(arr, undefined, true)
|
|
15
24
|
}
|
|
@@ -5,7 +5,7 @@ import { modelTypeKey } from "../model/metadata"
|
|
|
5
5
|
import { getModelOrSnapshotTypeAndId, getSnapshotModelType } from "../model/utils"
|
|
6
6
|
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
7
7
|
import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
|
|
8
|
-
import {
|
|
8
|
+
import { getCurrentErrorDiagnosticsContext } from "../utils/errorDiagnostics"
|
|
9
9
|
import { type FromSnapshotContext, registerSnapshotter } from "./fromSnapshot"
|
|
10
10
|
import type { SnapshotInOfModel } from "./SnapshotOf"
|
|
11
11
|
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
@@ -40,7 +40,12 @@ function fromModelSnapshot(sn: SnapshotInOfModel<AnyModel>, ctx: FromSnapshotCon
|
|
|
40
40
|
const modelTypeAndId = getModelOrSnapshotTypeAndId(sn)
|
|
41
41
|
const modelId = modelTypeAndId?.modelId
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// Hydration constructs every model. Keep this direct stack use rather than
|
|
44
|
+
// withErrorModelTrailEntry: it avoids one callback closure per model and
|
|
45
|
+
// has a measured production hydration win.
|
|
46
|
+
const errorDiagnosticsContext = getCurrentErrorDiagnosticsContext()
|
|
47
|
+
errorDiagnosticsContext?.pushModelTrail(type, modelId)
|
|
48
|
+
try {
|
|
44
49
|
return new (modelInfo.class as any)(undefined, {
|
|
45
50
|
snapshotInitialData: {
|
|
46
51
|
unprocessedSnapshot: sn,
|
|
@@ -54,7 +59,9 @@ function fromModelSnapshot(sn: SnapshotInOfModel<AnyModel>, ctx: FromSnapshotCon
|
|
|
54
59
|
},
|
|
55
60
|
generateNewIds: ctx.options.generateNewIds,
|
|
56
61
|
} satisfies ModelConstructorOptions)
|
|
57
|
-
}
|
|
62
|
+
} finally {
|
|
63
|
+
errorDiagnosticsContext?.popModelTrail()
|
|
64
|
+
}
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { observable } from "mobx"
|
|
2
2
|
import { tweakPlainObject } from "../tweaker/tweakPlainObject"
|
|
3
|
-
import { isPlainObject,
|
|
4
|
-
import {
|
|
3
|
+
import { isPlainObject, setProtoProp } from "../utils"
|
|
4
|
+
import { getCurrentErrorDiagnosticsContext } from "../utils/errorDiagnostics"
|
|
5
5
|
import {
|
|
6
6
|
type FromSnapshotContext,
|
|
7
7
|
internalFromSnapshot,
|
|
@@ -13,17 +13,28 @@ import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPrio
|
|
|
13
13
|
|
|
14
14
|
function fromPlainObjectSnapshot(sn: SnapshotInOfObject<any>, ctx: FromSnapshotContext): object {
|
|
15
15
|
const plainObj: Record<string, unknown> = {}
|
|
16
|
+
// Hydration visits every property. Keep this direct stack use rather than
|
|
17
|
+
// withErrorPathSegment: it avoids one callback closure per property and has
|
|
18
|
+
// a measured production hydration win.
|
|
19
|
+
const errorDiagnosticsContext = getCurrentErrorDiagnosticsContext()
|
|
16
20
|
|
|
17
21
|
const snKeys = Object.keys(sn)
|
|
18
22
|
const snKeysLen = snKeys.length
|
|
19
23
|
for (let i = 0; i < snKeysLen; i++) {
|
|
20
24
|
const k = snKeys[i]
|
|
21
25
|
const v = sn[k]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
errorDiagnosticsContext?.pushPath(k)
|
|
27
|
+
let snapshotValue: unknown
|
|
28
|
+
try {
|
|
29
|
+
snapshotValue = internalFromSnapshot(v, ctx)
|
|
30
|
+
} finally {
|
|
31
|
+
errorDiagnosticsContext?.popPath()
|
|
32
|
+
}
|
|
33
|
+
if (k === "__proto__") {
|
|
34
|
+
setProtoProp(plainObj, snapshotValue)
|
|
35
|
+
} else {
|
|
36
|
+
plainObj[k] = snapshotValue
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
39
|
return tweakPlainObject(
|
|
29
40
|
observable.object(plainObj, undefined, observableOptions),
|
|
@@ -5,8 +5,12 @@ import { resolveStandardTypeNoThrow, resolveTypeChecker } from "../types/resolve
|
|
|
5
5
|
import type { AnyType, TypeToData, TypeToSnapshotIn } from "../types/schemas"
|
|
6
6
|
import { isLateTypeChecker, TypeChecker } from "../types/TypeChecker"
|
|
7
7
|
import { resolveCodecSupport } from "../types/utility/typesCodec"
|
|
8
|
-
import { isMap, isPrimitive, isSet,
|
|
9
|
-
import {
|
|
8
|
+
import { isMap, isPrimitive, isSet, setProtoProp } from "../utils"
|
|
9
|
+
import {
|
|
10
|
+
getCurrentErrorDiagnosticsContext,
|
|
11
|
+
runWithErrorDiagnosticsContext,
|
|
12
|
+
} from "../utils/errorDiagnostics"
|
|
13
|
+
import { setModelInitialDataSnapshot } from "./modelInitialData"
|
|
10
14
|
import { registerDefaultSnapshotters } from "./registerDefaultSnapshotters"
|
|
11
15
|
import type { SnapshotInOf, SnapshotInOfModel, SnapshotOutOf } from "./SnapshotOf"
|
|
12
16
|
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
@@ -87,9 +91,8 @@ export function fromSnapshot<T>(arg1: any, arg2: any, arg3?: any): T {
|
|
|
87
91
|
|
|
88
92
|
if (codecSupport.hasCodec) {
|
|
89
93
|
unprocessedSnapshot = arg2
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
)
|
|
94
|
+
const processor = resolveTypeChecker(codecSupport.storedType).getFromSnapshotProcessor()
|
|
95
|
+
snapshot = processor ? processor(unprocessedSnapshot) : unprocessedSnapshot
|
|
93
96
|
options = arg3
|
|
94
97
|
const storedValue = fromSnapshotAction(snapshot, unprocessedSnapshot, options)
|
|
95
98
|
return codecSupport.adapter.toRuntime(storedValue)
|
|
@@ -97,7 +100,8 @@ export function fromSnapshot<T>(arg1: any, arg2: any, arg3?: any): T {
|
|
|
97
100
|
|
|
98
101
|
const typeChecker = resolveTypeChecker(resolvedType)
|
|
99
102
|
unprocessedSnapshot = arg2
|
|
100
|
-
|
|
103
|
+
const processor = typeChecker.getFromSnapshotProcessor()
|
|
104
|
+
snapshot = processor ? processor(unprocessedSnapshot) : unprocessedSnapshot
|
|
101
105
|
options = arg3
|
|
102
106
|
} else {
|
|
103
107
|
snapshot = arg1
|
|
@@ -179,6 +183,11 @@ function snapshotToInitialData(
|
|
|
179
183
|
processedSn: SnapshotInOfModel<AnyModel>
|
|
180
184
|
): any {
|
|
181
185
|
const initialData: Record<string, unknown> = {}
|
|
186
|
+
let allValuesPrimitive = true
|
|
187
|
+
// Model hydration visits every data slot. Keep this direct stack use rather
|
|
188
|
+
// than withErrorPathSegment: it avoids one callback closure per slot and
|
|
189
|
+
// has a measured production hydration win.
|
|
190
|
+
const errorDiagnosticsContext = getCurrentErrorDiagnosticsContext()
|
|
182
191
|
|
|
183
192
|
const processedSnKeys = Object.keys(processedSn)
|
|
184
193
|
const processedSnKeysLen = processedSnKeys.length
|
|
@@ -186,11 +195,24 @@ function snapshotToInitialData(
|
|
|
186
195
|
const k = processedSnKeys[i]
|
|
187
196
|
if (!isReservedModelKey(k)) {
|
|
188
197
|
const v = processedSn[k]
|
|
189
|
-
|
|
190
|
-
|
|
198
|
+
errorDiagnosticsContext?.pushPath(k)
|
|
199
|
+
let snapshotValue: unknown
|
|
200
|
+
try {
|
|
201
|
+
snapshotValue = internalFromSnapshot(v, ctx)
|
|
202
|
+
} finally {
|
|
203
|
+
errorDiagnosticsContext?.popPath()
|
|
204
|
+
}
|
|
205
|
+
allValuesPrimitive &&= isPrimitive(snapshotValue)
|
|
206
|
+
if (k === "__proto__") {
|
|
207
|
+
setProtoProp(initialData, snapshotValue)
|
|
208
|
+
} else {
|
|
209
|
+
initialData[k] = snapshotValue
|
|
210
|
+
}
|
|
191
211
|
}
|
|
192
212
|
}
|
|
193
|
-
|
|
213
|
+
const observableInitialData = observable.object(initialData, undefined, observableOptions)
|
|
214
|
+
setModelInitialDataSnapshot(observableInitialData, initialData, allValuesPrimitive)
|
|
215
|
+
return observableInitialData
|
|
194
216
|
}
|
|
195
217
|
|
|
196
218
|
export const observableOptions = {
|
|
@@ -5,6 +5,7 @@ import type { AnyType, TypeToData, TypeToSnapshotOut } from "../types/schemas"
|
|
|
5
5
|
import { resolveCodecSupport } from "../types/utility/typesCodec"
|
|
6
6
|
import { failure, identityFn, isPrimitive } from "../utils"
|
|
7
7
|
import {
|
|
8
|
+
flushInternalSnapshot,
|
|
8
9
|
freezeInternalSnapshot,
|
|
9
10
|
getInternalSnapshot,
|
|
10
11
|
reportInternalSnapshotObserved,
|
|
@@ -48,16 +49,19 @@ export function getSnapshot(...args: [arg1: any] | [arg1: any, arg2: any]): any
|
|
|
48
49
|
const storedValue = codecSupport.adapter.toStored(arg2)
|
|
49
50
|
|
|
50
51
|
if (isPrimitive(storedValue)) {
|
|
51
|
-
|
|
52
|
+
const processor = storedTypeChecker.getToSnapshotProcessor()
|
|
53
|
+
return processor ? processor(storedValue) : storedValue
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
const storedTree = isTweakedObject(storedValue, true)
|
|
55
57
|
? storedValue
|
|
56
58
|
: toTreeNode(codecSupport.storedType, storedValue)
|
|
57
|
-
|
|
59
|
+
const storedSnapshot = getSnapshot(storedTree)
|
|
60
|
+
const processor = storedTypeChecker.getToSnapshotProcessor()
|
|
61
|
+
return processor ? processor(storedSnapshot) : storedSnapshot
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
toSnapshotProcessor = resolveTypeChecker(arg1).
|
|
64
|
+
toSnapshotProcessor = resolveTypeChecker(arg1).getToSnapshotProcessor() ?? identityFn
|
|
61
65
|
nodeOrPrimitive = arg2
|
|
62
66
|
} else {
|
|
63
67
|
nodeOrPrimitive = arg1
|
|
@@ -74,6 +78,7 @@ export function getSnapshot(...args: [arg1: any] | [arg1: any, arg2: any]): any
|
|
|
74
78
|
throw failure("getSnapshot is not supported for this kind of object")
|
|
75
79
|
}
|
|
76
80
|
|
|
81
|
+
flushInternalSnapshot(nodeOrPrimitive, true)
|
|
77
82
|
freezeInternalSnapshot(snapshot.transformed)
|
|
78
83
|
reportInternalSnapshotObserved(snapshot)
|
|
79
84
|
return toSnapshotProcessor(snapshot.transformed)
|