mobx-keystone 1.20.0 → 1.22.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 +864 -853
- package/README.md +61 -61
- package/dist/mobx-keystone.esm.js +11336 -11148
- package/dist/mobx-keystone.esm.mjs +11336 -11148
- package/dist/mobx-keystone.umd.js +12229 -11738
- package/dist/types/actionMiddlewares/undoMiddleware.d.ts +1 -1
- package/dist/types/modelShared/prop.d.ts +5 -0
- package/dist/types/redux/connectReduxDevTools.d.ts +17 -4
- package/dist/types/ref/Ref.d.ts +1 -1
- package/dist/types/treeUtils/sandbox.d.ts +1 -1
- package/dist/types/types/TypeChecker.d.ts +1 -1
- package/dist/types/types/arrayBased/typesArray.d.ts +1 -1
- package/dist/types/types/arrayBased/typesTuple.d.ts +1 -1
- package/dist/types/types/objectBased/typesArraySet.d.ts +1 -1
- package/dist/types/types/objectBased/typesDataModelData.d.ts +1 -1
- package/dist/types/types/objectBased/typesModel.d.ts +1 -1
- package/dist/types/types/objectBased/typesObject.d.ts +3 -3
- package/dist/types/types/objectBased/typesObjectMap.d.ts +1 -1
- package/dist/types/types/objectBased/typesRecord.d.ts +1 -1
- package/dist/types/types/primitiveBased/typesPrimitive.d.ts +1 -1
- package/dist/types/types/types.d.ts +3 -3
- package/dist/types/types/utility/typesCodec.d.ts +1 -6
- package/dist/types/types/utility/typesCodecCore.d.ts +1 -1
- package/dist/types/types/utility/typesOr.d.ts +1 -1
- package/dist/types/types/utility/typesRefinement.d.ts +1 -1
- package/dist/types/types/utility/typesSkipCheck.d.ts +1 -1
- package/dist/types/types/utility/typesTag.d.ts +1 -1
- package/dist/types/wrappers/ObjectMap.d.ts +2 -0
- package/dist/types/wrappers/asMap.d.ts +10 -6
- package/package.json +14 -12
- package/src/action/applyAction.ts +125 -114
- package/src/action/applyMethodCall.ts +37 -37
- package/src/action/isModelAction.ts +16 -16
- package/src/action/middleware.ts +137 -137
- package/src/action/modelFlow.ts +240 -240
- package/src/action/modelFlowPromiseGenerator.ts +127 -125
- package/src/action/pendingActions.ts +42 -42
- package/src/action/wrapInAction.ts +156 -156
- package/src/actionMiddlewares/actionSerialization/actionSerialization.ts +1 -1
- package/src/actionMiddlewares/actionSerialization/applySerializedAction.ts +172 -172
- package/src/actionMiddlewares/actionSerialization/arraySerializer.ts +20 -20
- package/src/actionMiddlewares/actionSerialization/dateSerializer.ts +17 -17
- package/src/actionMiddlewares/actionSerialization/mapSerializer.ts +42 -42
- package/src/actionMiddlewares/actionSerialization/objectPathSerializer.ts +50 -50
- package/src/actionMiddlewares/actionSerialization/objectSnapshotSerializer.ts +21 -21
- package/src/actionMiddlewares/actionSerialization/plainObjectSerializer.ts +24 -32
- package/src/actionMiddlewares/actionSerialization/primitiveSerializer.ts +51 -51
- package/src/actionMiddlewares/actionSerialization/setSerializer.ts +37 -37
- package/src/actionMiddlewares/actionTrackingMiddleware.ts +3 -3
- package/src/actionMiddlewares/onActionMiddleware.ts +2 -2
- package/src/actionMiddlewares/readonlyMiddleware.ts +2 -2
- package/src/actionMiddlewares/transactionMiddleware.ts +4 -4
- package/src/actionMiddlewares/undoMiddleware.ts +804 -796
- package/src/actionMiddlewares/utils.ts +2 -2
- package/src/computedTree/computedTree.ts +143 -143
- package/src/context/context.ts +1 -1
- package/src/dataModel/BaseDataModel.ts +194 -192
- package/src/dataModel/actions.ts +1 -1
- package/src/dataModel/newDataModel.ts +57 -57
- package/src/deepChange/index.ts +1 -1
- package/src/deepChange/onDeepChange.ts +244 -244
- package/src/frozen/Frozen.ts +146 -146
- package/src/globalConfig/globalConfig.ts +107 -107
- package/src/index.ts +24 -24
- package/src/model/BaseModel.ts +275 -273
- package/src/model/ModelConstructorOptions.ts +15 -15
- package/src/model/getModelMetadata.ts +51 -51
- package/src/model/index.ts +6 -6
- package/src/model/mixins.ts +288 -288
- package/src/model/newModel.ts +301 -301
- package/src/model/utils.ts +249 -249
- package/src/modelShared/modelDecorator.ts +260 -253
- package/src/modelShared/modelInfo.ts +50 -50
- package/src/modelShared/modelSymbols.ts +3 -3
- package/src/modelShared/newModel.ts +25 -25
- package/src/modelShared/prop.ts +713 -684
- package/src/modelShared/sharedInternalModel.ts +427 -417
- package/src/modelShared/utils.ts +24 -24
- package/src/parent/core.ts +65 -65
- package/src/parent/coreObjectChildren.ts +180 -180
- package/src/parent/detach.ts +47 -47
- package/src/parent/findParent.ts +1 -1
- package/src/parent/getChildrenObjects.ts +25 -25
- package/src/parent/path.ts +386 -381
- package/src/parent/setParent.ts +149 -149
- package/src/parent/walkTree.ts +1 -1
- package/src/patch/applyPatches.ts +187 -187
- package/src/patch/jsonPatch.ts +108 -108
- package/src/patch/patchRecorder.ts +6 -1
- package/src/redux/connectReduxDevTools.ts +39 -7
- package/src/redux/redux.ts +6 -2
- package/src/ref/Ref.ts +1 -1
- package/src/ref/core.ts +339 -345
- package/src/ref/customRef.ts +3 -3
- package/src/ref/rootRef.ts +100 -100
- package/src/rootStore/attachDetach.ts +89 -89
- package/src/rootStore/rootStore.ts +1 -1
- package/src/snapshot/SnapshotOf.ts +104 -104
- package/src/snapshot/SnapshotProcessingError.ts +45 -45
- package/src/snapshot/applySnapshot.ts +177 -181
- package/src/snapshot/cloneTreeValue.ts +30 -30
- package/src/snapshot/fromArraySnapshot.ts +27 -33
- package/src/snapshot/fromModelSnapshot.ts +70 -70
- package/src/snapshot/fromPlainObjectSnapshot.ts +47 -42
- package/src/snapshot/fromSnapshot.ts +198 -198
- package/src/snapshot/getSnapshot.ts +80 -79
- package/src/snapshot/index.ts +8 -8
- package/src/snapshot/internal.ts +230 -230
- package/src/snapshot/reconcileArraySnapshot.ts +70 -70
- package/src/snapshot/reconcileModelSnapshot.ts +155 -150
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +72 -72
- package/src/snapshot/reconcileSnapshot.ts +88 -88
- package/src/standardActions/actions.ts +64 -64
- package/src/standardActions/objectActions.ts +60 -60
- package/src/transforms/ImmutableDate.ts +93 -93
- package/src/transforms/asMap.ts +50 -50
- package/src/transforms/asSet.ts +22 -22
- package/src/transforms/bigint.ts +20 -20
- package/src/transforms/date.ts +40 -40
- package/src/treeUtils/deepEquals.ts +55 -55
- package/src/treeUtils/sandbox.ts +6 -3
- package/src/tweaker/TweakerPriority.ts +9 -9
- package/src/tweaker/tweak.ts +4 -3
- package/src/tweaker/tweakArray.ts +530 -475
- package/src/tweaker/tweakFrozen.ts +42 -42
- package/src/tweaker/tweakModel.ts +1 -1
- package/src/tweaker/tweakPlainObject.ts +355 -355
- package/src/tweaker/typeChecking.ts +101 -101
- package/src/types/SnapshotTypeMismatchError.ts +46 -46
- package/src/types/TypeCheckError.ts +183 -184
- package/src/types/TypeChecker.ts +202 -185
- package/src/types/arrayBased/typesArray.ts +136 -137
- package/src/types/arrayBased/typesTuple.ts +138 -139
- package/src/types/createPerEntryCachedCheck.ts +166 -160
- package/src/types/index.ts +6 -6
- package/src/types/objectBased/typesArraySet.ts +133 -134
- package/src/types/objectBased/typesDataModelData.ts +203 -204
- package/src/types/objectBased/typesModel.ts +220 -221
- package/src/types/objectBased/typesObject.ts +308 -310
- package/src/types/objectBased/typesObjectMap.ts +142 -143
- package/src/types/objectBased/typesRecord.ts +156 -157
- package/src/types/objectBased/typesRef.ts +89 -89
- package/src/types/primitiveBased/typesEnum.ts +63 -63
- package/src/types/primitiveBased/typesPrimitive.ts +219 -220
- package/src/types/registerDefaultStandardTypeResolvers.ts +21 -21
- package/src/types/resolveTypeChecker.ts +78 -78
- package/src/types/schemas.ts +208 -208
- package/src/types/tProp.ts +277 -268
- package/src/types/typeCheck.ts +21 -21
- package/src/types/typeCheckErrorUtils.ts +23 -23
- package/src/types/types.ts +142 -142
- package/src/types/utility/typeToStoredData.ts +37 -37
- package/src/types/utility/typesBigInt.ts +15 -15
- package/src/types/utility/typesCodec.ts +41 -38
- package/src/types/utility/typesCodecCore.ts +178 -178
- package/src/types/utility/typesCodecSupport.ts +806 -806
- package/src/types/utility/typesDate.ts +27 -27
- package/src/types/utility/typesMap.ts +253 -222
- package/src/types/utility/typesOr.ts +263 -259
- package/src/types/utility/typesRefinement.ts +131 -125
- package/src/types/utility/typesSet.ts +110 -110
- package/src/types/utility/typesSkipCheck.ts +69 -70
- package/src/types/utility/typesTag.ts +88 -82
- package/src/types/utility/typesUnchecked.ts +40 -40
- package/src/utils/AnyFunction.ts +4 -4
- package/src/utils/ModelPool.ts +59 -59
- package/src/utils/chainFns.ts +18 -18
- package/src/utils/decorators.ts +274 -274
- package/src/utils/errorDiagnostics.ts +204 -204
- package/src/utils/index.ts +443 -372
- package/src/wrappers/ArraySet.ts +156 -156
- package/src/wrappers/ObjectMap.ts +155 -136
- package/src/wrappers/asMap.ts +65 -30
- package/src/wrappers/asSet.ts +3 -3
package/src/parent/setParent.ts
CHANGED
|
@@ -1,149 +1,149 @@
|
|
|
1
|
-
import { action } from "mobx"
|
|
2
|
-
import { enqueuePendingAction } from "../action/pendingActions"
|
|
3
|
-
import { BaseModel } from "../model/BaseModel"
|
|
4
|
-
import { getModelMetadata } from "../model/getModelMetadata"
|
|
5
|
-
import { isModel } from "../model/utils"
|
|
6
|
-
import { attachToRootStore, detachFromRootStore } from "../rootStore/attachDetach"
|
|
7
|
-
import { fastIsRootStoreNoAtom } from "../rootStore/rootStore"
|
|
8
|
-
import { clone } from "../snapshot/clone"
|
|
9
|
-
import { isTweakedObject } from "../tweaker/core"
|
|
10
|
-
import { tryUntweak } from "../tweaker/tweak"
|
|
11
|
-
import { failure, inDevMode, isPrimitive } from "../utils"
|
|
12
|
-
import {
|
|
13
|
-
dataObjectParent,
|
|
14
|
-
dataToModelNode,
|
|
15
|
-
objectParents,
|
|
16
|
-
parentPathEquals,
|
|
17
|
-
reportParentPathChanged,
|
|
18
|
-
} from "./core"
|
|
19
|
-
import { addObjectChild, removeObjectChild } from "./coreObjectChildren"
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* @internal
|
|
24
|
-
*/
|
|
25
|
-
export const setParent = action(
|
|
26
|
-
"setParent",
|
|
27
|
-
(
|
|
28
|
-
value: any,
|
|
29
|
-
parentPath: ParentPath<any> | undefined,
|
|
30
|
-
indexChangeAllowed: boolean,
|
|
31
|
-
isDataObject: boolean,
|
|
32
|
-
cloneIfApplicable: boolean
|
|
33
|
-
): any => {
|
|
34
|
-
if (isPrimitive(value)) {
|
|
35
|
-
return value
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (inDevMode) {
|
|
39
|
-
if (indexChangeAllowed && cloneIfApplicable) {
|
|
40
|
-
throw failure(
|
|
41
|
-
"assertion failed: 'indexChangeAllowed' and 'cloneIfApplicable' cannot be set at the same time"
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
if (typeof value === "function" || typeof value === "symbol") {
|
|
45
|
-
throw failure(`assertion failed: value cannot be a function or a symbol`)
|
|
46
|
-
}
|
|
47
|
-
if (!isTweakedObject(value, true)) {
|
|
48
|
-
throw failure(`assertion failed: value is not ready to take a parent`)
|
|
49
|
-
}
|
|
50
|
-
if (parentPath && !isTweakedObject(parentPath.parent, true)) {
|
|
51
|
-
throw failure(`assertion failed: parent is not ready to take children`)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let oldParentPath = fastGetParentPath(value, false)
|
|
56
|
-
if (parentPathEquals(oldParentPath, parentPath)) {
|
|
57
|
-
return value
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (fastIsRootStoreNoAtom(value)) {
|
|
61
|
-
throw failure("root stores cannot be attached to any parents")
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (isDataObject) {
|
|
65
|
-
dataObjectParent.set(value, parentPath!.parent)
|
|
66
|
-
// data object will proxy to use the actual parent model for child/parent stuff
|
|
67
|
-
return value
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// make sure the new parent actually points to models when we give model data objs
|
|
71
|
-
if (parentPath) {
|
|
72
|
-
const actualParent = dataToModelNode(parentPath.parent)
|
|
73
|
-
if (parentPath.parent !== actualParent) {
|
|
74
|
-
parentPath = {
|
|
75
|
-
parent: actualParent,
|
|
76
|
-
path: parentPath.path,
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// value type models should be cloned when they are about to be assigned to a new parent
|
|
82
|
-
// and they had one previously
|
|
83
|
-
if (
|
|
84
|
-
cloneIfApplicable &&
|
|
85
|
-
parentPath?.parent &&
|
|
86
|
-
oldParentPath?.parent &&
|
|
87
|
-
isModel(value) &&
|
|
88
|
-
getModelMetadata(value).valueType
|
|
89
|
-
) {
|
|
90
|
-
value = clone(value, { generateNewIds: true })
|
|
91
|
-
oldParentPath = fastGetParentPath(value, false)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (oldParentPath && parentPath) {
|
|
95
|
-
if (oldParentPath.parent === parentPath.parent && indexChangeAllowed) {
|
|
96
|
-
// just changing the index
|
|
97
|
-
objectParents.set(value, parentPath)
|
|
98
|
-
reportParentPathChanged(value)
|
|
99
|
-
return value
|
|
100
|
-
} else {
|
|
101
|
-
throw failure("an object cannot be assigned a new parent when it already has one")
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const postUntweaker = parentPath ? undefined : tryUntweak(value)
|
|
106
|
-
|
|
107
|
-
const valueIsModel = value instanceof BaseModel
|
|
108
|
-
|
|
109
|
-
let oldRoot: any
|
|
110
|
-
let oldRootStore: any
|
|
111
|
-
if (valueIsModel) {
|
|
112
|
-
oldRoot = fastGetRoot(value, false)
|
|
113
|
-
oldRootStore = fastIsRootStoreNoAtom(oldRoot) ? oldRoot : undefined
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// detach from old
|
|
117
|
-
if (oldParentPath?.parent) {
|
|
118
|
-
removeObjectChild(oldParentPath.parent, value)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// attach to new
|
|
122
|
-
objectParents.set(value, parentPath)
|
|
123
|
-
if (parentPath?.parent) {
|
|
124
|
-
addObjectChild(parentPath.parent, value)
|
|
125
|
-
}
|
|
126
|
-
reportParentPathChanged(value)
|
|
127
|
-
|
|
128
|
-
if (valueIsModel) {
|
|
129
|
-
const newRoot = fastGetRoot(value, false)
|
|
130
|
-
const newRootStore = fastIsRootStoreNoAtom(newRoot) ? newRoot : undefined
|
|
131
|
-
|
|
132
|
-
// invoke model root store events
|
|
133
|
-
if (oldRootStore !== newRootStore && (oldRootStore || newRootStore)) {
|
|
134
|
-
enqueuePendingAction(() => {
|
|
135
|
-
if (oldRootStore) {
|
|
136
|
-
detachFromRootStore(value)
|
|
137
|
-
}
|
|
138
|
-
if (newRootStore) {
|
|
139
|
-
attachToRootStore(newRootStore, value)
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
postUntweaker?.()
|
|
146
|
-
|
|
147
|
-
return value
|
|
148
|
-
}
|
|
149
|
-
)
|
|
1
|
+
import { action } from "mobx"
|
|
2
|
+
import { enqueuePendingAction } from "../action/pendingActions"
|
|
3
|
+
import { BaseModel } from "../model/BaseModel"
|
|
4
|
+
import { getModelMetadata } from "../model/getModelMetadata"
|
|
5
|
+
import { isModel } from "../model/utils"
|
|
6
|
+
import { attachToRootStore, detachFromRootStore } from "../rootStore/attachDetach"
|
|
7
|
+
import { fastIsRootStoreNoAtom } from "../rootStore/rootStore"
|
|
8
|
+
import { clone } from "../snapshot/clone"
|
|
9
|
+
import { isTweakedObject } from "../tweaker/core"
|
|
10
|
+
import { tryUntweak } from "../tweaker/tweak"
|
|
11
|
+
import { failure, inDevMode, isPrimitive } from "../utils"
|
|
12
|
+
import {
|
|
13
|
+
dataObjectParent,
|
|
14
|
+
dataToModelNode,
|
|
15
|
+
objectParents,
|
|
16
|
+
parentPathEquals,
|
|
17
|
+
reportParentPathChanged,
|
|
18
|
+
} from "./core"
|
|
19
|
+
import { addObjectChild, removeObjectChild } from "./coreObjectChildren"
|
|
20
|
+
import { fastGetParentPath, fastGetRoot, type ParentPath } from "./path"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export const setParent = action(
|
|
26
|
+
"setParent",
|
|
27
|
+
(
|
|
28
|
+
value: any,
|
|
29
|
+
parentPath: ParentPath<any> | undefined,
|
|
30
|
+
indexChangeAllowed: boolean,
|
|
31
|
+
isDataObject: boolean,
|
|
32
|
+
cloneIfApplicable: boolean
|
|
33
|
+
): any => {
|
|
34
|
+
if (isPrimitive(value)) {
|
|
35
|
+
return value
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (inDevMode) {
|
|
39
|
+
if (indexChangeAllowed && cloneIfApplicable) {
|
|
40
|
+
throw failure(
|
|
41
|
+
"assertion failed: 'indexChangeAllowed' and 'cloneIfApplicable' cannot be set at the same time"
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
if (typeof value === "function" || typeof value === "symbol") {
|
|
45
|
+
throw failure(`assertion failed: value cannot be a function or a symbol`)
|
|
46
|
+
}
|
|
47
|
+
if (!isTweakedObject(value, true)) {
|
|
48
|
+
throw failure(`assertion failed: value is not ready to take a parent`)
|
|
49
|
+
}
|
|
50
|
+
if (parentPath && !isTweakedObject(parentPath.parent, true)) {
|
|
51
|
+
throw failure(`assertion failed: parent is not ready to take children`)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let oldParentPath = fastGetParentPath(value, false)
|
|
56
|
+
if (parentPathEquals(oldParentPath, parentPath)) {
|
|
57
|
+
return value
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (fastIsRootStoreNoAtom(value)) {
|
|
61
|
+
throw failure("root stores cannot be attached to any parents")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (isDataObject) {
|
|
65
|
+
dataObjectParent.set(value, parentPath!.parent)
|
|
66
|
+
// data object will proxy to use the actual parent model for child/parent stuff
|
|
67
|
+
return value
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// make sure the new parent actually points to models when we give model data objs
|
|
71
|
+
if (parentPath) {
|
|
72
|
+
const actualParent = dataToModelNode(parentPath.parent)
|
|
73
|
+
if (parentPath.parent !== actualParent) {
|
|
74
|
+
parentPath = {
|
|
75
|
+
parent: actualParent,
|
|
76
|
+
path: parentPath.path,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// value type models should be cloned when they are about to be assigned to a new parent
|
|
82
|
+
// and they had one previously
|
|
83
|
+
if (
|
|
84
|
+
cloneIfApplicable &&
|
|
85
|
+
parentPath?.parent &&
|
|
86
|
+
oldParentPath?.parent &&
|
|
87
|
+
isModel(value) &&
|
|
88
|
+
getModelMetadata(value).valueType
|
|
89
|
+
) {
|
|
90
|
+
value = clone(value, { generateNewIds: true })
|
|
91
|
+
oldParentPath = fastGetParentPath(value, false)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (oldParentPath && parentPath) {
|
|
95
|
+
if (oldParentPath.parent === parentPath.parent && indexChangeAllowed) {
|
|
96
|
+
// just changing the index
|
|
97
|
+
objectParents.set(value, parentPath)
|
|
98
|
+
reportParentPathChanged(value)
|
|
99
|
+
return value
|
|
100
|
+
} else {
|
|
101
|
+
throw failure("an object cannot be assigned a new parent when it already has one")
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const postUntweaker = parentPath ? undefined : tryUntweak(value)
|
|
106
|
+
|
|
107
|
+
const valueIsModel = value instanceof BaseModel
|
|
108
|
+
|
|
109
|
+
let oldRoot: any
|
|
110
|
+
let oldRootStore: any
|
|
111
|
+
if (valueIsModel) {
|
|
112
|
+
oldRoot = fastGetRoot(value, false)
|
|
113
|
+
oldRootStore = fastIsRootStoreNoAtom(oldRoot) ? oldRoot : undefined
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// detach from old
|
|
117
|
+
if (oldParentPath?.parent) {
|
|
118
|
+
removeObjectChild(oldParentPath.parent, value)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// attach to new
|
|
122
|
+
objectParents.set(value, parentPath)
|
|
123
|
+
if (parentPath?.parent) {
|
|
124
|
+
addObjectChild(parentPath.parent, value)
|
|
125
|
+
}
|
|
126
|
+
reportParentPathChanged(value)
|
|
127
|
+
|
|
128
|
+
if (valueIsModel) {
|
|
129
|
+
const newRoot = fastGetRoot(value, false)
|
|
130
|
+
const newRootStore = fastIsRootStoreNoAtom(newRoot) ? newRoot : undefined
|
|
131
|
+
|
|
132
|
+
// invoke model root store events
|
|
133
|
+
if (oldRootStore !== newRootStore && (oldRootStore || newRootStore)) {
|
|
134
|
+
enqueuePendingAction(() => {
|
|
135
|
+
if (oldRootStore) {
|
|
136
|
+
detachFromRootStore(value)
|
|
137
|
+
}
|
|
138
|
+
if (newRootStore) {
|
|
139
|
+
attachToRootStore(newRootStore, value)
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
postUntweaker?.()
|
|
146
|
+
|
|
147
|
+
return value
|
|
148
|
+
}
|
|
149
|
+
)
|
package/src/parent/walkTree.ts
CHANGED
|
@@ -1,187 +1,187 @@
|
|
|
1
|
-
import { remove } from "mobx"
|
|
2
|
-
import { BuiltInAction } from "../action/builtInActions"
|
|
3
|
-
import { ActionContextActionType } from "../action/context"
|
|
4
|
-
import { wrapInAction } from "../action/wrapInAction"
|
|
5
|
-
import { modelToDataNode } from "../parent/core"
|
|
6
|
-
import type { PathElement } from "../parent/pathTypes"
|
|
7
|
-
import type { Patch } from "../patch/Patch"
|
|
8
|
-
import { reconcileSnapshot } from "../snapshot/reconcileSnapshot"
|
|
9
|
-
import { assertTweakedObject } from "../tweaker/core"
|
|
10
|
-
import { failure, inDevMode, isArray, lazy } from "../utils"
|
|
11
|
-
import { runWithErrorDiagnosticsContext, withErrorPathSegments } from "../utils/errorDiagnostics"
|
|
12
|
-
import { ModelPool } from "../utils/ModelPool"
|
|
13
|
-
import { setIfDifferent } from "../utils/setIfDifferent"
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Applies the given patches to the given target object.
|
|
17
|
-
*
|
|
18
|
-
* @param node Target object.
|
|
19
|
-
* @param patches List of patches to apply.
|
|
20
|
-
* @param reverse Whether patches are applied in reverse order.
|
|
21
|
-
*/
|
|
22
|
-
export function applyPatches(
|
|
23
|
-
node: object,
|
|
24
|
-
patches: ReadonlyArray<Patch> | ReadonlyArray<ReadonlyArray<Patch>>,
|
|
25
|
-
reverse = false
|
|
26
|
-
): void {
|
|
27
|
-
assertTweakedObject(node, "node")
|
|
28
|
-
|
|
29
|
-
if (patches.length <= 0) {
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
wrappedInternalApplyPatches().call(node, patches, reverse)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @internal
|
|
38
|
-
*/
|
|
39
|
-
export function internalApplyPatches(
|
|
40
|
-
this: object,
|
|
41
|
-
patches: ReadonlyArray<Patch> | ReadonlyArray<ReadonlyArray<Patch>>,
|
|
42
|
-
reverse = false
|
|
43
|
-
): void {
|
|
44
|
-
runWithErrorDiagnosticsContext(() => {
|
|
45
|
-
const obj = this
|
|
46
|
-
const modelPool = new ModelPool(obj)
|
|
47
|
-
|
|
48
|
-
if (reverse) {
|
|
49
|
-
let i = patches.length
|
|
50
|
-
while (i--) {
|
|
51
|
-
const p = patches[i]
|
|
52
|
-
if (isArray(p)) {
|
|
53
|
-
let j = p.length
|
|
54
|
-
while (j--) {
|
|
55
|
-
applySinglePatchWithPath(obj, p[j], modelPool)
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
applySinglePatchWithPath(obj, p as Patch, modelPool)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
} else {
|
|
62
|
-
const len = patches.length
|
|
63
|
-
for (let i = 0; i < len; i++) {
|
|
64
|
-
const p = patches[i]
|
|
65
|
-
if (isArray(p)) {
|
|
66
|
-
const len2 = p.length
|
|
67
|
-
for (let j = 0; j < len2; j++) {
|
|
68
|
-
applySinglePatchWithPath(obj, p[j], modelPool)
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
applySinglePatchWithPath(obj, p as Patch, modelPool)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const wrappedInternalApplyPatches = lazy(() =>
|
|
79
|
-
wrapInAction({
|
|
80
|
-
nameOrNameFn: BuiltInAction.ApplyPatches,
|
|
81
|
-
fn: internalApplyPatches,
|
|
82
|
-
actionType: ActionContextActionType.Sync,
|
|
83
|
-
})
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
function applySinglePatch(obj: object, patch: Patch, modelPool: ModelPool): void {
|
|
87
|
-
const { target, prop } = pathArrayToObjectAndProp(obj, patch.path)
|
|
88
|
-
|
|
89
|
-
if (isArray(target)) {
|
|
90
|
-
switch (patch.op) {
|
|
91
|
-
case "add": {
|
|
92
|
-
const index = +prop!
|
|
93
|
-
// reconcile from the pool if possible
|
|
94
|
-
const newValue = reconcileSnapshot(undefined, patch.value, modelPool, target)
|
|
95
|
-
if (index < 0) {
|
|
96
|
-
// extension needed by mobx-keystone-yjs
|
|
97
|
-
target.push(newValue)
|
|
98
|
-
} else {
|
|
99
|
-
target.splice(index, 0, newValue)
|
|
100
|
-
}
|
|
101
|
-
break
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
case "remove": {
|
|
105
|
-
const index = +prop!
|
|
106
|
-
// no reconciliation, removing
|
|
107
|
-
target.splice(index, 1)
|
|
108
|
-
break
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
case "replace": {
|
|
112
|
-
if (prop === "length") {
|
|
113
|
-
target.length = patch.value
|
|
114
|
-
} else {
|
|
115
|
-
const index = +prop!
|
|
116
|
-
// try to reconcile
|
|
117
|
-
const newValue = reconcileSnapshot(target[index], patch.value, modelPool, target)
|
|
118
|
-
setIfDifferent(target, index as any, newValue)
|
|
119
|
-
}
|
|
120
|
-
break
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
default:
|
|
124
|
-
throw failure(`unsupported patch operation: ${(patch as any).op}`)
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
|
-
switch (patch.op) {
|
|
128
|
-
case "add": {
|
|
129
|
-
// reconcile from the pool if possible
|
|
130
|
-
const newValue = reconcileSnapshot(undefined, patch.value, modelPool, target)
|
|
131
|
-
setIfDifferent(target, prop!, newValue)
|
|
132
|
-
break
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
case "remove": {
|
|
136
|
-
// no reconciliation, removing
|
|
137
|
-
remove(target, prop)
|
|
138
|
-
break
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
case "replace": {
|
|
142
|
-
// try to reconcile
|
|
143
|
-
// we don't need to tweak the pool since reconcileSnapshot will do that for us
|
|
144
|
-
const newValue = reconcileSnapshot(target[prop!], patch.value, modelPool, target)
|
|
145
|
-
setIfDifferent(target, prop!, newValue)
|
|
146
|
-
break
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
default:
|
|
150
|
-
throw failure(`unsupported patch operation: ${(patch as any).op}`)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function applySinglePatchWithPath(obj: object, patch: Patch, modelPool: ModelPool): void {
|
|
156
|
-
withErrorPathSegments(patch.path, () => {
|
|
157
|
-
applySinglePatch(obj, patch, modelPool)
|
|
158
|
-
})
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function pathArrayToObjectAndProp(
|
|
162
|
-
obj: object,
|
|
163
|
-
path: Patch["path"]
|
|
164
|
-
): { target: any; prop?: PathElement } {
|
|
165
|
-
if (inDevMode) {
|
|
166
|
-
if (!isArray(path)) {
|
|
167
|
-
throw failure(`invalid path: ${path}`)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
let target: any = modelToDataNode(obj)
|
|
172
|
-
|
|
173
|
-
if (path.length === 0) {
|
|
174
|
-
return {
|
|
175
|
-
target,
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
for (let i = 0; i <= path.length - 2; i++) {
|
|
180
|
-
target = modelToDataNode(target[path[i]])
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
target,
|
|
185
|
-
prop: path[path.length - 1],
|
|
186
|
-
}
|
|
187
|
-
}
|
|
1
|
+
import { remove } from "mobx"
|
|
2
|
+
import { BuiltInAction } from "../action/builtInActions"
|
|
3
|
+
import { ActionContextActionType } from "../action/context"
|
|
4
|
+
import { wrapInAction } from "../action/wrapInAction"
|
|
5
|
+
import { modelToDataNode } from "../parent/core"
|
|
6
|
+
import type { PathElement } from "../parent/pathTypes"
|
|
7
|
+
import type { Patch } from "../patch/Patch"
|
|
8
|
+
import { reconcileSnapshot } from "../snapshot/reconcileSnapshot"
|
|
9
|
+
import { assertTweakedObject } from "../tweaker/core"
|
|
10
|
+
import { failure, inDevMode, isArray, lazy } from "../utils"
|
|
11
|
+
import { runWithErrorDiagnosticsContext, withErrorPathSegments } from "../utils/errorDiagnostics"
|
|
12
|
+
import { ModelPool } from "../utils/ModelPool"
|
|
13
|
+
import { setIfDifferent } from "../utils/setIfDifferent"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Applies the given patches to the given target object.
|
|
17
|
+
*
|
|
18
|
+
* @param node Target object.
|
|
19
|
+
* @param patches List of patches to apply.
|
|
20
|
+
* @param reverse Whether patches are applied in reverse order.
|
|
21
|
+
*/
|
|
22
|
+
export function applyPatches(
|
|
23
|
+
node: object,
|
|
24
|
+
patches: ReadonlyArray<Patch> | ReadonlyArray<ReadonlyArray<Patch>>,
|
|
25
|
+
reverse = false
|
|
26
|
+
): void {
|
|
27
|
+
assertTweakedObject(node, "node")
|
|
28
|
+
|
|
29
|
+
if (patches.length <= 0) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
wrappedInternalApplyPatches().call(node, patches, reverse)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
39
|
+
export function internalApplyPatches(
|
|
40
|
+
this: object,
|
|
41
|
+
patches: ReadonlyArray<Patch> | ReadonlyArray<ReadonlyArray<Patch>>,
|
|
42
|
+
reverse = false
|
|
43
|
+
): void {
|
|
44
|
+
runWithErrorDiagnosticsContext(() => {
|
|
45
|
+
const obj = this
|
|
46
|
+
const modelPool = new ModelPool(obj)
|
|
47
|
+
|
|
48
|
+
if (reverse) {
|
|
49
|
+
let i = patches.length
|
|
50
|
+
while (i--) {
|
|
51
|
+
const p = patches[i]
|
|
52
|
+
if (isArray(p)) {
|
|
53
|
+
let j = p.length
|
|
54
|
+
while (j--) {
|
|
55
|
+
applySinglePatchWithPath(obj, p[j], modelPool)
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
applySinglePatchWithPath(obj, p as Patch, modelPool)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
const len = patches.length
|
|
63
|
+
for (let i = 0; i < len; i++) {
|
|
64
|
+
const p = patches[i]
|
|
65
|
+
if (isArray(p)) {
|
|
66
|
+
const len2 = p.length
|
|
67
|
+
for (let j = 0; j < len2; j++) {
|
|
68
|
+
applySinglePatchWithPath(obj, p[j], modelPool)
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
applySinglePatchWithPath(obj, p as Patch, modelPool)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const wrappedInternalApplyPatches = lazy(() =>
|
|
79
|
+
wrapInAction({
|
|
80
|
+
nameOrNameFn: BuiltInAction.ApplyPatches,
|
|
81
|
+
fn: internalApplyPatches,
|
|
82
|
+
actionType: ActionContextActionType.Sync,
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
function applySinglePatch(obj: object, patch: Patch, modelPool: ModelPool): void {
|
|
87
|
+
const { target, prop } = pathArrayToObjectAndProp(obj, patch.path)
|
|
88
|
+
|
|
89
|
+
if (isArray(target)) {
|
|
90
|
+
switch (patch.op) {
|
|
91
|
+
case "add": {
|
|
92
|
+
const index = +prop!
|
|
93
|
+
// reconcile from the pool if possible
|
|
94
|
+
const newValue = reconcileSnapshot(undefined, patch.value, modelPool, target)
|
|
95
|
+
if (index < 0) {
|
|
96
|
+
// extension needed by mobx-keystone-yjs
|
|
97
|
+
target.push(newValue)
|
|
98
|
+
} else {
|
|
99
|
+
target.splice(index, 0, newValue)
|
|
100
|
+
}
|
|
101
|
+
break
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
case "remove": {
|
|
105
|
+
const index = +prop!
|
|
106
|
+
// no reconciliation, removing
|
|
107
|
+
target.splice(index, 1)
|
|
108
|
+
break
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
case "replace": {
|
|
112
|
+
if (prop === "length") {
|
|
113
|
+
target.length = patch.value
|
|
114
|
+
} else {
|
|
115
|
+
const index = +prop!
|
|
116
|
+
// try to reconcile
|
|
117
|
+
const newValue = reconcileSnapshot(target[index], patch.value, modelPool, target)
|
|
118
|
+
setIfDifferent(target, index as any, newValue)
|
|
119
|
+
}
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
default:
|
|
124
|
+
throw failure(`unsupported patch operation: ${(patch as any).op}`)
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
switch (patch.op) {
|
|
128
|
+
case "add": {
|
|
129
|
+
// reconcile from the pool if possible
|
|
130
|
+
const newValue = reconcileSnapshot(undefined, patch.value, modelPool, target)
|
|
131
|
+
setIfDifferent(target, prop!, newValue)
|
|
132
|
+
break
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
case "remove": {
|
|
136
|
+
// no reconciliation, removing
|
|
137
|
+
remove(target, prop)
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
case "replace": {
|
|
142
|
+
// try to reconcile
|
|
143
|
+
// we don't need to tweak the pool since reconcileSnapshot will do that for us
|
|
144
|
+
const newValue = reconcileSnapshot(target[prop!], patch.value, modelPool, target)
|
|
145
|
+
setIfDifferent(target, prop!, newValue)
|
|
146
|
+
break
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
default:
|
|
150
|
+
throw failure(`unsupported patch operation: ${(patch as any).op}`)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function applySinglePatchWithPath(obj: object, patch: Patch, modelPool: ModelPool): void {
|
|
156
|
+
withErrorPathSegments(patch.path, () => {
|
|
157
|
+
applySinglePatch(obj, patch, modelPool)
|
|
158
|
+
})
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function pathArrayToObjectAndProp(
|
|
162
|
+
obj: object,
|
|
163
|
+
path: Patch["path"]
|
|
164
|
+
): { target: any; prop?: PathElement } {
|
|
165
|
+
if (inDevMode) {
|
|
166
|
+
if (!isArray(path)) {
|
|
167
|
+
throw failure(`invalid path: ${path}`)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
let target: any = modelToDataNode(obj)
|
|
172
|
+
|
|
173
|
+
if (path.length === 0) {
|
|
174
|
+
return {
|
|
175
|
+
target,
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (let i = 0; i <= path.length - 2; i++) {
|
|
180
|
+
target = modelToDataNode(target[path[i]])
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
target,
|
|
185
|
+
prop: path[path.length - 1],
|
|
186
|
+
}
|
|
187
|
+
}
|