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.
Files changed (174) hide show
  1. package/CHANGELOG.md +864 -853
  2. package/README.md +61 -61
  3. package/dist/mobx-keystone.esm.js +11336 -11148
  4. package/dist/mobx-keystone.esm.mjs +11336 -11148
  5. package/dist/mobx-keystone.umd.js +12229 -11738
  6. package/dist/types/actionMiddlewares/undoMiddleware.d.ts +1 -1
  7. package/dist/types/modelShared/prop.d.ts +5 -0
  8. package/dist/types/redux/connectReduxDevTools.d.ts +17 -4
  9. package/dist/types/ref/Ref.d.ts +1 -1
  10. package/dist/types/treeUtils/sandbox.d.ts +1 -1
  11. package/dist/types/types/TypeChecker.d.ts +1 -1
  12. package/dist/types/types/arrayBased/typesArray.d.ts +1 -1
  13. package/dist/types/types/arrayBased/typesTuple.d.ts +1 -1
  14. package/dist/types/types/objectBased/typesArraySet.d.ts +1 -1
  15. package/dist/types/types/objectBased/typesDataModelData.d.ts +1 -1
  16. package/dist/types/types/objectBased/typesModel.d.ts +1 -1
  17. package/dist/types/types/objectBased/typesObject.d.ts +3 -3
  18. package/dist/types/types/objectBased/typesObjectMap.d.ts +1 -1
  19. package/dist/types/types/objectBased/typesRecord.d.ts +1 -1
  20. package/dist/types/types/primitiveBased/typesPrimitive.d.ts +1 -1
  21. package/dist/types/types/types.d.ts +3 -3
  22. package/dist/types/types/utility/typesCodec.d.ts +1 -6
  23. package/dist/types/types/utility/typesCodecCore.d.ts +1 -1
  24. package/dist/types/types/utility/typesOr.d.ts +1 -1
  25. package/dist/types/types/utility/typesRefinement.d.ts +1 -1
  26. package/dist/types/types/utility/typesSkipCheck.d.ts +1 -1
  27. package/dist/types/types/utility/typesTag.d.ts +1 -1
  28. package/dist/types/wrappers/ObjectMap.d.ts +2 -0
  29. package/dist/types/wrappers/asMap.d.ts +10 -6
  30. package/package.json +14 -12
  31. package/src/action/applyAction.ts +125 -114
  32. package/src/action/applyMethodCall.ts +37 -37
  33. package/src/action/isModelAction.ts +16 -16
  34. package/src/action/middleware.ts +137 -137
  35. package/src/action/modelFlow.ts +240 -240
  36. package/src/action/modelFlowPromiseGenerator.ts +127 -125
  37. package/src/action/pendingActions.ts +42 -42
  38. package/src/action/wrapInAction.ts +156 -156
  39. package/src/actionMiddlewares/actionSerialization/actionSerialization.ts +1 -1
  40. package/src/actionMiddlewares/actionSerialization/applySerializedAction.ts +172 -172
  41. package/src/actionMiddlewares/actionSerialization/arraySerializer.ts +20 -20
  42. package/src/actionMiddlewares/actionSerialization/dateSerializer.ts +17 -17
  43. package/src/actionMiddlewares/actionSerialization/mapSerializer.ts +42 -42
  44. package/src/actionMiddlewares/actionSerialization/objectPathSerializer.ts +50 -50
  45. package/src/actionMiddlewares/actionSerialization/objectSnapshotSerializer.ts +21 -21
  46. package/src/actionMiddlewares/actionSerialization/plainObjectSerializer.ts +24 -32
  47. package/src/actionMiddlewares/actionSerialization/primitiveSerializer.ts +51 -51
  48. package/src/actionMiddlewares/actionSerialization/setSerializer.ts +37 -37
  49. package/src/actionMiddlewares/actionTrackingMiddleware.ts +3 -3
  50. package/src/actionMiddlewares/onActionMiddleware.ts +2 -2
  51. package/src/actionMiddlewares/readonlyMiddleware.ts +2 -2
  52. package/src/actionMiddlewares/transactionMiddleware.ts +4 -4
  53. package/src/actionMiddlewares/undoMiddleware.ts +804 -796
  54. package/src/actionMiddlewares/utils.ts +2 -2
  55. package/src/computedTree/computedTree.ts +143 -143
  56. package/src/context/context.ts +1 -1
  57. package/src/dataModel/BaseDataModel.ts +194 -192
  58. package/src/dataModel/actions.ts +1 -1
  59. package/src/dataModel/newDataModel.ts +57 -57
  60. package/src/deepChange/index.ts +1 -1
  61. package/src/deepChange/onDeepChange.ts +244 -244
  62. package/src/frozen/Frozen.ts +146 -146
  63. package/src/globalConfig/globalConfig.ts +107 -107
  64. package/src/index.ts +24 -24
  65. package/src/model/BaseModel.ts +275 -273
  66. package/src/model/ModelConstructorOptions.ts +15 -15
  67. package/src/model/getModelMetadata.ts +51 -51
  68. package/src/model/index.ts +6 -6
  69. package/src/model/mixins.ts +288 -288
  70. package/src/model/newModel.ts +301 -301
  71. package/src/model/utils.ts +249 -249
  72. package/src/modelShared/modelDecorator.ts +260 -253
  73. package/src/modelShared/modelInfo.ts +50 -50
  74. package/src/modelShared/modelSymbols.ts +3 -3
  75. package/src/modelShared/newModel.ts +25 -25
  76. package/src/modelShared/prop.ts +713 -684
  77. package/src/modelShared/sharedInternalModel.ts +427 -417
  78. package/src/modelShared/utils.ts +24 -24
  79. package/src/parent/core.ts +65 -65
  80. package/src/parent/coreObjectChildren.ts +180 -180
  81. package/src/parent/detach.ts +47 -47
  82. package/src/parent/findParent.ts +1 -1
  83. package/src/parent/getChildrenObjects.ts +25 -25
  84. package/src/parent/path.ts +386 -381
  85. package/src/parent/setParent.ts +149 -149
  86. package/src/parent/walkTree.ts +1 -1
  87. package/src/patch/applyPatches.ts +187 -187
  88. package/src/patch/jsonPatch.ts +108 -108
  89. package/src/patch/patchRecorder.ts +6 -1
  90. package/src/redux/connectReduxDevTools.ts +39 -7
  91. package/src/redux/redux.ts +6 -2
  92. package/src/ref/Ref.ts +1 -1
  93. package/src/ref/core.ts +339 -345
  94. package/src/ref/customRef.ts +3 -3
  95. package/src/ref/rootRef.ts +100 -100
  96. package/src/rootStore/attachDetach.ts +89 -89
  97. package/src/rootStore/rootStore.ts +1 -1
  98. package/src/snapshot/SnapshotOf.ts +104 -104
  99. package/src/snapshot/SnapshotProcessingError.ts +45 -45
  100. package/src/snapshot/applySnapshot.ts +177 -181
  101. package/src/snapshot/cloneTreeValue.ts +30 -30
  102. package/src/snapshot/fromArraySnapshot.ts +27 -33
  103. package/src/snapshot/fromModelSnapshot.ts +70 -70
  104. package/src/snapshot/fromPlainObjectSnapshot.ts +47 -42
  105. package/src/snapshot/fromSnapshot.ts +198 -198
  106. package/src/snapshot/getSnapshot.ts +80 -79
  107. package/src/snapshot/index.ts +8 -8
  108. package/src/snapshot/internal.ts +230 -230
  109. package/src/snapshot/reconcileArraySnapshot.ts +70 -70
  110. package/src/snapshot/reconcileModelSnapshot.ts +155 -150
  111. package/src/snapshot/reconcilePlainObjectSnapshot.ts +72 -72
  112. package/src/snapshot/reconcileSnapshot.ts +88 -88
  113. package/src/standardActions/actions.ts +64 -64
  114. package/src/standardActions/objectActions.ts +60 -60
  115. package/src/transforms/ImmutableDate.ts +93 -93
  116. package/src/transforms/asMap.ts +50 -50
  117. package/src/transforms/asSet.ts +22 -22
  118. package/src/transforms/bigint.ts +20 -20
  119. package/src/transforms/date.ts +40 -40
  120. package/src/treeUtils/deepEquals.ts +55 -55
  121. package/src/treeUtils/sandbox.ts +6 -3
  122. package/src/tweaker/TweakerPriority.ts +9 -9
  123. package/src/tweaker/tweak.ts +4 -3
  124. package/src/tweaker/tweakArray.ts +530 -475
  125. package/src/tweaker/tweakFrozen.ts +42 -42
  126. package/src/tweaker/tweakModel.ts +1 -1
  127. package/src/tweaker/tweakPlainObject.ts +355 -355
  128. package/src/tweaker/typeChecking.ts +101 -101
  129. package/src/types/SnapshotTypeMismatchError.ts +46 -46
  130. package/src/types/TypeCheckError.ts +183 -184
  131. package/src/types/TypeChecker.ts +202 -185
  132. package/src/types/arrayBased/typesArray.ts +136 -137
  133. package/src/types/arrayBased/typesTuple.ts +138 -139
  134. package/src/types/createPerEntryCachedCheck.ts +166 -160
  135. package/src/types/index.ts +6 -6
  136. package/src/types/objectBased/typesArraySet.ts +133 -134
  137. package/src/types/objectBased/typesDataModelData.ts +203 -204
  138. package/src/types/objectBased/typesModel.ts +220 -221
  139. package/src/types/objectBased/typesObject.ts +308 -310
  140. package/src/types/objectBased/typesObjectMap.ts +142 -143
  141. package/src/types/objectBased/typesRecord.ts +156 -157
  142. package/src/types/objectBased/typesRef.ts +89 -89
  143. package/src/types/primitiveBased/typesEnum.ts +63 -63
  144. package/src/types/primitiveBased/typesPrimitive.ts +219 -220
  145. package/src/types/registerDefaultStandardTypeResolvers.ts +21 -21
  146. package/src/types/resolveTypeChecker.ts +78 -78
  147. package/src/types/schemas.ts +208 -208
  148. package/src/types/tProp.ts +277 -268
  149. package/src/types/typeCheck.ts +21 -21
  150. package/src/types/typeCheckErrorUtils.ts +23 -23
  151. package/src/types/types.ts +142 -142
  152. package/src/types/utility/typeToStoredData.ts +37 -37
  153. package/src/types/utility/typesBigInt.ts +15 -15
  154. package/src/types/utility/typesCodec.ts +41 -38
  155. package/src/types/utility/typesCodecCore.ts +178 -178
  156. package/src/types/utility/typesCodecSupport.ts +806 -806
  157. package/src/types/utility/typesDate.ts +27 -27
  158. package/src/types/utility/typesMap.ts +253 -222
  159. package/src/types/utility/typesOr.ts +263 -259
  160. package/src/types/utility/typesRefinement.ts +131 -125
  161. package/src/types/utility/typesSet.ts +110 -110
  162. package/src/types/utility/typesSkipCheck.ts +69 -70
  163. package/src/types/utility/typesTag.ts +88 -82
  164. package/src/types/utility/typesUnchecked.ts +40 -40
  165. package/src/utils/AnyFunction.ts +4 -4
  166. package/src/utils/ModelPool.ts +59 -59
  167. package/src/utils/chainFns.ts +18 -18
  168. package/src/utils/decorators.ts +274 -274
  169. package/src/utils/errorDiagnostics.ts +204 -204
  170. package/src/utils/index.ts +443 -372
  171. package/src/wrappers/ArraySet.ts +156 -156
  172. package/src/wrappers/ObjectMap.ts +155 -136
  173. package/src/wrappers/asMap.ts +65 -30
  174. package/src/wrappers/asSet.ts +3 -3
@@ -1,70 +1,70 @@
1
- import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
2
- import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
3
- import { isArray } from "../utils"
4
- import { withErrorPathSegment } from "../utils/errorDiagnostics"
5
- import { ModelPool } from "../utils/ModelPool"
6
- import { setIfDifferent } from "../utils/setIfDifferent"
7
- import { fromSnapshot } from "./fromSnapshot"
8
- import { getSnapshot } from "./getSnapshot"
9
- import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
10
- import type { SnapshotInOfObject } from "./SnapshotOf"
11
- import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
12
-
13
- function reconcileArraySnapshot(
14
- value: any,
15
- sn: SnapshotInOfObject<any[]>,
16
- modelPool: ModelPool
17
- ): any[] {
18
- if (!isArray(value)) {
19
- // no reconciliation possible
20
- return fromSnapshot(sn)
21
- }
22
-
23
- const snapshotBeforeChanges = getSnapshot(value)
24
-
25
- withoutTypeChecking(() => {
26
- // remove excess items
27
- if (value.length > sn.length) {
28
- value.splice(sn.length, value.length - sn.length)
29
- }
30
-
31
- // reconcile present items
32
- for (let i = 0; i < value.length; i++) {
33
- const oldValue = value[i]
34
- const newValue = withErrorPathSegment(i, () =>
35
- reconcileSnapshot(oldValue, sn[i], modelPool, value)
36
- )
37
-
38
- detachIfNeeded(newValue, oldValue, modelPool)
39
-
40
- setIfDifferent(value, i, newValue)
41
- }
42
-
43
- // add excess items
44
- for (let i = value.length; i < sn.length; i++) {
45
- const newValue = withErrorPathSegment(i, () =>
46
- reconcileSnapshot(undefined, sn[i], modelPool, value)
47
- )
48
-
49
- detachIfNeeded(newValue, undefined, modelPool)
50
-
51
- value.push(newValue)
52
- }
53
- })
54
-
55
- runTypeCheckingAfterChange(value, undefined, snapshotBeforeChanges)
56
-
57
- return value
58
- }
59
-
60
- /**
61
- * @internal
62
- */
63
- export function registerArraySnapshotReconciler() {
64
- registerReconciler(SnapshotterAndReconcilerPriority.Array, (value, sn, modelPool) => {
65
- if (isArray(sn)) {
66
- return reconcileArraySnapshot(value, sn, modelPool)
67
- }
68
- return undefined
69
- })
70
- }
1
+ import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
2
+ import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
3
+ import { isArray } from "../utils"
4
+ import { withErrorPathSegment } from "../utils/errorDiagnostics"
5
+ import type { ModelPool } from "../utils/ModelPool"
6
+ import { setIfDifferent } from "../utils/setIfDifferent"
7
+ import { fromSnapshot } from "./fromSnapshot"
8
+ import { getSnapshot } from "./getSnapshot"
9
+ import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
10
+ import type { SnapshotInOfObject } from "./SnapshotOf"
11
+ import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
12
+
13
+ function reconcileArraySnapshot(
14
+ value: any,
15
+ sn: SnapshotInOfObject<any[]>,
16
+ modelPool: ModelPool
17
+ ): any[] {
18
+ if (!isArray(value)) {
19
+ // no reconciliation possible
20
+ return fromSnapshot(sn)
21
+ }
22
+
23
+ const snapshotBeforeChanges = getSnapshot(value)
24
+
25
+ withoutTypeChecking(() => {
26
+ // remove excess items
27
+ if (value.length > sn.length) {
28
+ value.splice(sn.length, value.length - sn.length)
29
+ }
30
+
31
+ // reconcile present items
32
+ for (let i = 0; i < value.length; i++) {
33
+ const oldValue = value[i]
34
+ const newValue = withErrorPathSegment(i, () =>
35
+ reconcileSnapshot(oldValue, sn[i], modelPool, value)
36
+ )
37
+
38
+ detachIfNeeded(newValue, oldValue, modelPool)
39
+
40
+ setIfDifferent(value, i, newValue)
41
+ }
42
+
43
+ // add excess items
44
+ for (let i = value.length; i < sn.length; i++) {
45
+ const newValue = withErrorPathSegment(i, () =>
46
+ reconcileSnapshot(undefined, sn[i], modelPool, value)
47
+ )
48
+
49
+ detachIfNeeded(newValue, undefined, modelPool)
50
+
51
+ value.push(newValue)
52
+ }
53
+ })
54
+
55
+ runTypeCheckingAfterChange(value, undefined, snapshotBeforeChanges)
56
+
57
+ return value
58
+ }
59
+
60
+ /**
61
+ * @internal
62
+ */
63
+ export function registerArraySnapshotReconciler() {
64
+ registerReconciler(SnapshotterAndReconcilerPriority.Array, (value, sn, modelPool) => {
65
+ if (isArray(sn)) {
66
+ return reconcileArraySnapshot(value, sn, modelPool)
67
+ }
68
+ return undefined
69
+ })
70
+ }
@@ -1,150 +1,155 @@
1
- import { remove } from "mobx"
2
- import type { AnyModel } from "../model/BaseModel"
3
- import { getModelIdPropertyName } from "../model/getModelMetadata"
4
- import { isReservedModelKey, modelIdKey, modelTypeKey } from "../model/metadata"
5
- import { getModelOrSnapshotTypeAndId, getSnapshotModelType, isModel } from "../model/utils"
6
- import type { ModelClass } from "../modelShared/BaseModelShared"
7
- import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
8
- import { getInternalModelClassPropsInfo } from "../modelShared/modelPropsInfo"
9
- import { AnyModelProp, getModelPropDefaultValue, noDefaultValue } from "../modelShared/prop"
10
- import { deepEquals } from "../treeUtils/deepEquals"
11
- import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
12
- import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
13
- import { isArray } from "../utils"
14
- import {
15
- withErrorModelTrailEntry,
16
- withErrorPathSegment,
17
- } from "../utils/errorDiagnostics"
18
- import type { ModelPool } from "../utils/ModelPool"
19
- import { setIfDifferent } from "../utils/setIfDifferent"
20
- import { fromSnapshot } from "./fromSnapshot"
21
- import { getSnapshot } from "./getSnapshot"
22
- import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
23
- import type { SnapshotInOfModel } from "./SnapshotOf"
24
- import { SnapshotProcessingError } from "./SnapshotProcessingError"
25
- import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
26
-
27
- function reconcileModelSnapshot(
28
- value: any,
29
- sn: SnapshotInOfModel<AnyModel>,
30
- modelPool: ModelPool,
31
- parent: any
32
- ): AnyModel {
33
- const type = sn[modelTypeKey]!
34
-
35
- const modelInfo = getModelInfoForName(type)
36
- if (!modelInfo) {
37
- throw new SnapshotProcessingError({
38
- message: getModelNotRegisteredErrorMessage(type),
39
- actualSnapshot: sn,
40
- })
41
- }
42
-
43
- const modelClass = modelInfo.class as ModelClass<AnyModel>
44
- const trailModelId = getModelOrSnapshotTypeAndId(sn)?.modelId
45
-
46
- return withErrorModelTrailEntry(type, trailModelId, () => {
47
- // try to use model from pool if possible
48
- const modelInPool = modelPool.findModelForSnapshot(sn)
49
- if (modelInPool) {
50
- value = modelInPool
51
- }
52
-
53
- // we don't check by actual instance since the class might be a different one due to hot reloading
54
- if (!isModel(value) || value[modelTypeKey] !== type) {
55
- // different kind of model type, no reconciliation possible
56
- return fromSnapshot<AnyModel>(sn)
57
- }
58
-
59
- const modelProps = getInternalModelClassPropsInfo(modelClass)
60
- const modelIdPropertyName = getModelIdPropertyName(modelClass)
61
-
62
- if (modelIdPropertyName) {
63
- const id = sn[modelIdPropertyName]
64
-
65
- if (value[modelIdKey] !== id) {
66
- // different id, no reconciliation possible
67
- return fromSnapshot<AnyModel>(sn)
68
- }
69
- } else if (isArray(parent)) {
70
- // no id and inside an array? no reconciliation possible,
71
- // unless the snapshots are equivalent (note deep equals will use the snapshot of value auto)
72
- if (!deepEquals(value, sn)) {
73
- return fromSnapshot<AnyModel>(sn)
74
- }
75
- }
76
-
77
- const modelObj: AnyModel = value
78
- const snapshotBeforeChanges = getSnapshot(modelObj)
79
-
80
- withoutTypeChecking(() => {
81
- const modelClass: ModelClass<AnyModel> = (modelObj as any).constructor
82
- const processedSn = modelClass.fromSnapshotProcessor
83
- ? modelClass.fromSnapshotProcessor(sn)
84
- : sn
85
-
86
- const data = modelObj.$
87
-
88
- // remove excess props
89
- const dataKeys = Object.keys(data)
90
- const dataKeysLen = dataKeys.length
91
- for (let i = 0; i < dataKeysLen; i++) {
92
- const k = dataKeys[i]
93
- if (!(k in processedSn)) {
94
- // use default value if applicable
95
- const modelProp = modelProps[k] as AnyModelProp | undefined
96
- const defaultValue = modelProp ? getModelPropDefaultValue(modelProp) : noDefaultValue
97
- if (defaultValue === noDefaultValue) {
98
- remove(data, k)
99
- } else {
100
- setIfDifferent(data, k, defaultValue)
101
- }
102
- }
103
- }
104
-
105
- // reconcile the rest
106
- const processedSnKeys = Object.keys(processedSn)
107
- const processedSnKeysLen = processedSnKeys.length
108
- for (let i = 0; i < processedSnKeysLen; i++) {
109
- const k = processedSnKeys[i]
110
- if (!isReservedModelKey(k)) {
111
- const v = processedSn[k]
112
-
113
- const oldValue = data[k]
114
- let newValue = withErrorPathSegment(k, () =>
115
- reconcileSnapshot(oldValue, v, modelPool, modelObj)
116
- )
117
-
118
- // use default value if applicable
119
- if (newValue == null) {
120
- const modelProp = modelProps[k] as AnyModelProp | undefined
121
- const defaultValue = modelProp ? getModelPropDefaultValue(modelProp) : noDefaultValue
122
- if (defaultValue !== noDefaultValue) {
123
- newValue = defaultValue
124
- }
125
- }
126
-
127
- detachIfNeeded(newValue, oldValue, modelPool)
128
-
129
- setIfDifferent(data, k, newValue)
130
- }
131
- }
132
- })
133
-
134
- runTypeCheckingAfterChange(modelObj, undefined, snapshotBeforeChanges)
135
-
136
- return modelObj
137
- })
138
- }
139
-
140
- /**
141
- * @internal
142
- */
143
- export function registerModelSnapshotReconciler() {
144
- registerReconciler(SnapshotterAndReconcilerPriority.Model, (value, sn, modelPool, parent) => {
145
- if (getSnapshotModelType(sn) !== undefined) {
146
- return reconcileModelSnapshot(value, sn, modelPool, parent)
147
- }
148
- return undefined
149
- })
150
- }
1
+ import { remove } from "mobx"
2
+ import type { AnyModel } from "../model/BaseModel"
3
+ import { getModelIdPropertyName } from "../model/getModelMetadata"
4
+ import { isReservedModelKey, modelIdKey, modelTypeKey } from "../model/metadata"
5
+ import { getModelOrSnapshotTypeAndId, getSnapshotModelType, isModel } from "../model/utils"
6
+ import type { ModelClass } from "../modelShared/BaseModelShared"
7
+ import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
8
+ import { getInternalModelClassPropsInfo } from "../modelShared/modelPropsInfo"
9
+ import {
10
+ type AnyModelProp,
11
+ getModelPropStoredDefaultValue,
12
+ noDefaultValue,
13
+ } from "../modelShared/prop"
14
+ import { deepEquals } from "../treeUtils/deepEquals"
15
+ import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
16
+ import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
17
+ import { isArray } from "../utils"
18
+ import { withErrorModelTrailEntry, withErrorPathSegment } from "../utils/errorDiagnostics"
19
+ import type { ModelPool } from "../utils/ModelPool"
20
+ import { setIfDifferent } from "../utils/setIfDifferent"
21
+ import { fromSnapshot } from "./fromSnapshot"
22
+ import { getSnapshot } from "./getSnapshot"
23
+ import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
24
+ import type { SnapshotInOfModel } from "./SnapshotOf"
25
+ import { SnapshotProcessingError } from "./SnapshotProcessingError"
26
+ import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
27
+
28
+ function reconcileModelSnapshot(
29
+ value: any,
30
+ sn: SnapshotInOfModel<AnyModel>,
31
+ modelPool: ModelPool,
32
+ parent: any
33
+ ): AnyModel {
34
+ const type = sn[modelTypeKey]!
35
+
36
+ const modelInfo = getModelInfoForName(type)
37
+ if (!modelInfo) {
38
+ throw new SnapshotProcessingError({
39
+ message: getModelNotRegisteredErrorMessage(type),
40
+ actualSnapshot: sn,
41
+ })
42
+ }
43
+
44
+ const modelClass = modelInfo.class as ModelClass<AnyModel>
45
+ const trailModelId = getModelOrSnapshotTypeAndId(sn)?.modelId
46
+
47
+ return withErrorModelTrailEntry(type, trailModelId, () => {
48
+ // try to use model from pool if possible
49
+ const modelInPool = modelPool.findModelForSnapshot(sn)
50
+ if (modelInPool) {
51
+ value = modelInPool
52
+ }
53
+
54
+ // we don't check by actual instance since the class might be a different one due to hot reloading
55
+ if (!isModel(value) || value[modelTypeKey] !== type) {
56
+ // different kind of model type, no reconciliation possible
57
+ return fromSnapshot<AnyModel>(sn)
58
+ }
59
+
60
+ const modelProps = getInternalModelClassPropsInfo(modelClass)
61
+ const modelIdPropertyName = getModelIdPropertyName(modelClass)
62
+
63
+ if (modelIdPropertyName) {
64
+ const id = sn[modelIdPropertyName]
65
+
66
+ if (value[modelIdKey] !== id) {
67
+ // different id, no reconciliation possible
68
+ return fromSnapshot<AnyModel>(sn)
69
+ }
70
+ } else if (isArray(parent)) {
71
+ // no id and inside an array? no reconciliation possible,
72
+ // unless the snapshots are equivalent (note deep equals will use the snapshot of value auto)
73
+ if (!deepEquals(value, sn)) {
74
+ return fromSnapshot<AnyModel>(sn)
75
+ }
76
+ }
77
+
78
+ const modelObj: AnyModel = value
79
+ const snapshotBeforeChanges = getSnapshot(modelObj)
80
+
81
+ withoutTypeChecking(() => {
82
+ const modelClass: ModelClass<AnyModel> = (modelObj as any).constructor
83
+ const processedSn = modelClass.fromSnapshotProcessor
84
+ ? modelClass.fromSnapshotProcessor(sn)
85
+ : sn
86
+
87
+ const data = modelObj.$
88
+
89
+ // remove excess props
90
+ const dataKeys = Object.keys(data)
91
+ const dataKeysLen = dataKeys.length
92
+ for (let i = 0; i < dataKeysLen; i++) {
93
+ const k = dataKeys[i]
94
+ if (!(k in processedSn)) {
95
+ // use default value if applicable
96
+ const modelProp = modelProps[k] as AnyModelProp | undefined
97
+ const defaultValue = modelProp
98
+ ? getModelPropStoredDefaultValue(modelProp, modelObj, k)
99
+ : noDefaultValue
100
+ if (defaultValue === noDefaultValue) {
101
+ remove(data, k)
102
+ } else {
103
+ setIfDifferent(data, k, defaultValue)
104
+ }
105
+ }
106
+ }
107
+
108
+ // reconcile the rest
109
+ const processedSnKeys = Object.keys(processedSn)
110
+ const processedSnKeysLen = processedSnKeys.length
111
+ for (let i = 0; i < processedSnKeysLen; i++) {
112
+ const k = processedSnKeys[i]
113
+ if (!isReservedModelKey(k)) {
114
+ const v = processedSn[k]
115
+
116
+ const oldValue = data[k]
117
+ let newValue = withErrorPathSegment(k, () =>
118
+ reconcileSnapshot(oldValue, v, modelPool, modelObj)
119
+ )
120
+
121
+ // use default value if applicable
122
+ if (newValue == null) {
123
+ const modelProp = modelProps[k] as AnyModelProp | undefined
124
+ const defaultValue = modelProp
125
+ ? getModelPropStoredDefaultValue(modelProp, modelObj, k)
126
+ : noDefaultValue
127
+ if (defaultValue !== noDefaultValue) {
128
+ newValue = defaultValue
129
+ }
130
+ }
131
+
132
+ detachIfNeeded(newValue, oldValue, modelPool)
133
+
134
+ setIfDifferent(data, k, newValue)
135
+ }
136
+ }
137
+ })
138
+
139
+ runTypeCheckingAfterChange(modelObj, undefined, snapshotBeforeChanges)
140
+
141
+ return modelObj
142
+ })
143
+ }
144
+
145
+ /**
146
+ * @internal
147
+ */
148
+ export function registerModelSnapshotReconciler() {
149
+ registerReconciler(SnapshotterAndReconcilerPriority.Model, (value, sn, modelPool, parent) => {
150
+ if (getSnapshotModelType(sn) !== undefined) {
151
+ return reconcileModelSnapshot(value, sn, modelPool, parent)
152
+ }
153
+ return undefined
154
+ })
155
+ }
@@ -1,72 +1,72 @@
1
- import { isObservableObject, remove } from "mobx"
2
- import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
3
- import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
4
- import { isPlainObject } from "../utils"
5
- import { withErrorPathSegment } from "../utils/errorDiagnostics"
6
- import type { ModelPool } from "../utils/ModelPool"
7
- import { setIfDifferent } from "../utils/setIfDifferent"
8
- import { fromSnapshot } from "./fromSnapshot"
9
- import { getSnapshot } from "./getSnapshot"
10
- import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
11
- import type { SnapshotInOfObject } from "./SnapshotOf"
12
- import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
13
-
14
- function reconcilePlainObjectSnapshot(
15
- value: any,
16
- sn: SnapshotInOfObject<any>,
17
- modelPool: ModelPool
18
- ): object {
19
- // plain obj
20
- if (!(isPlainObject(value) || isObservableObject(value))) {
21
- // no reconciliation possible
22
- return fromSnapshot(sn)
23
- }
24
-
25
- const plainObj = value
26
- const snapshotBeforeChanges = getSnapshot(plainObj)
27
-
28
- withoutTypeChecking(() => {
29
- // remove excess props
30
- const plainObjKeys = Object.keys(plainObj)
31
- const plainObjKeysLen = plainObjKeys.length
32
- for (let i = 0; i < plainObjKeysLen; i++) {
33
- const k = plainObjKeys[i]
34
- if (!(k in sn)) {
35
- remove(plainObj, k)
36
- }
37
- }
38
-
39
- // reconcile the rest
40
- const snKeys = Object.keys(sn)
41
- const snKeysLen = snKeys.length
42
- for (let i = 0; i < snKeysLen; i++) {
43
- const k = snKeys[i]
44
- const v = sn[k]
45
-
46
- const oldValue = plainObj[k]
47
- const newValue = withErrorPathSegment(k, () =>
48
- reconcileSnapshot(oldValue, v, modelPool, plainObj)
49
- )
50
-
51
- detachIfNeeded(newValue, oldValue, modelPool)
52
-
53
- setIfDifferent(plainObj, k, newValue)
54
- }
55
- })
56
-
57
- runTypeCheckingAfterChange(plainObj, undefined, snapshotBeforeChanges)
58
-
59
- return plainObj
60
- }
61
-
62
- /**
63
- * @internal
64
- */
65
- export function registerPlainObjectSnapshotReconciler() {
66
- registerReconciler(SnapshotterAndReconcilerPriority.PlainObject, (value, sn, modelPool) => {
67
- if (isPlainObject(sn)) {
68
- return reconcilePlainObjectSnapshot(value, sn, modelPool)
69
- }
70
- return undefined
71
- })
72
- }
1
+ import { isObservableObject, remove } from "mobx"
2
+ import { runTypeCheckingAfterChange } from "../tweaker/typeChecking"
3
+ import { withoutTypeChecking } from "../tweaker/withoutTypeChecking"
4
+ import { isPlainObject } from "../utils"
5
+ import { withErrorPathSegment } from "../utils/errorDiagnostics"
6
+ import type { ModelPool } from "../utils/ModelPool"
7
+ import { setIfDifferent } from "../utils/setIfDifferent"
8
+ import { fromSnapshot } from "./fromSnapshot"
9
+ import { getSnapshot } from "./getSnapshot"
10
+ import { detachIfNeeded, reconcileSnapshot, registerReconciler } from "./reconcileSnapshot"
11
+ import type { SnapshotInOfObject } from "./SnapshotOf"
12
+ import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
13
+
14
+ function reconcilePlainObjectSnapshot(
15
+ value: any,
16
+ sn: SnapshotInOfObject<any>,
17
+ modelPool: ModelPool
18
+ ): object {
19
+ // plain obj
20
+ if (!(isPlainObject(value) || isObservableObject(value))) {
21
+ // no reconciliation possible
22
+ return fromSnapshot(sn)
23
+ }
24
+
25
+ const plainObj = value
26
+ const snapshotBeforeChanges = getSnapshot(plainObj)
27
+
28
+ withoutTypeChecking(() => {
29
+ // remove excess props
30
+ const plainObjKeys = Object.keys(plainObj)
31
+ const plainObjKeysLen = plainObjKeys.length
32
+ for (let i = 0; i < plainObjKeysLen; i++) {
33
+ const k = plainObjKeys[i]
34
+ if (!(k in sn)) {
35
+ remove(plainObj, k)
36
+ }
37
+ }
38
+
39
+ // reconcile the rest
40
+ const snKeys = Object.keys(sn)
41
+ const snKeysLen = snKeys.length
42
+ for (let i = 0; i < snKeysLen; i++) {
43
+ const k = snKeys[i]
44
+ const v = sn[k]
45
+
46
+ const oldValue = plainObj[k]
47
+ const newValue = withErrorPathSegment(k, () =>
48
+ reconcileSnapshot(oldValue, v, modelPool, plainObj)
49
+ )
50
+
51
+ detachIfNeeded(newValue, oldValue, modelPool)
52
+
53
+ setIfDifferent(plainObj, k, newValue)
54
+ }
55
+ })
56
+
57
+ runTypeCheckingAfterChange(plainObj, undefined, snapshotBeforeChanges)
58
+
59
+ return plainObj
60
+ }
61
+
62
+ /**
63
+ * @internal
64
+ */
65
+ export function registerPlainObjectSnapshotReconciler() {
66
+ registerReconciler(SnapshotterAndReconcilerPriority.PlainObject, (value, sn, modelPool) => {
67
+ if (isPlainObject(sn)) {
68
+ return reconcilePlainObjectSnapshot(value, sn, modelPool)
69
+ }
70
+ return undefined
71
+ })
72
+ }