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/model/BaseModel.ts
CHANGED
|
@@ -1,273 +1,275 @@
|
|
|
1
|
-
import { observable } from "mobx"
|
|
2
|
-
import {
|
|
3
|
-
fromSnapshotOverrideTypeSymbol,
|
|
4
|
-
ModelClass,
|
|
5
|
-
propsTypeSymbol,
|
|
6
|
-
toSnapshotOverrideTypeSymbol,
|
|
7
|
-
} from "../modelShared/BaseModelShared"
|
|
8
|
-
import { modelInfoByClass } from "../modelShared/modelInfo"
|
|
9
|
-
import type {
|
|
10
|
-
ModelProps,
|
|
11
|
-
ModelPropsToTransformedCreationData,
|
|
12
|
-
ModelPropsToUntransformedData,
|
|
13
|
-
} from "../modelShared/prop"
|
|
14
|
-
import { getSnapshot } from "../snapshot/getSnapshot"
|
|
15
|
-
import type { SnapshotInOfModel, SnapshotOutOfModel } from "../snapshot/SnapshotOf"
|
|
16
|
-
import { typesModel } from "../types/objectBased/typesModel"
|
|
17
|
-
import type { TypeCheckError } from "../types/TypeCheckError"
|
|
18
|
-
import { typeCheck } from "../types/typeCheck"
|
|
19
|
-
import { assertIsObject, failure } from "../utils"
|
|
20
|
-
import { getModelIdPropertyName } from "./getModelMetadata"
|
|
21
|
-
import type { ModelConstructorOptions } from "./ModelConstructorOptions"
|
|
22
|
-
import { modelIdKey, modelTypeKey } from "./metadata"
|
|
23
|
-
import { internalFromSnapshotModel, internalNewModel } from "./newModel"
|
|
24
|
-
import { assertIsModelClass } from "./utils"
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @ignore
|
|
28
|
-
*/
|
|
29
|
-
export const modelIdPropertyNameSymbol = Symbol("modelIdPropertyName")
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @ignore
|
|
33
|
-
*/
|
|
34
|
-
export type ModelIdPropertyType<TProps extends ModelProps, ModelIdPropertyName extends string> = [
|
|
35
|
-
ModelIdPropertyName,
|
|
36
|
-
] extends [never]
|
|
37
|
-
? never
|
|
38
|
-
: ModelPropsToUntransformedData<Pick<TProps, ModelIdPropertyName>>[ModelIdPropertyName]
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Base abstract class for models. Use `Model` instead when extending.
|
|
42
|
-
*
|
|
43
|
-
* Never override the constructor, use `onInit` or `onAttachedToRootStore` instead.
|
|
44
|
-
*
|
|
45
|
-
* @template Data Data type.
|
|
46
|
-
* @template CreationData Creation data type.
|
|
47
|
-
* @template ModelIdPropertyName Model id property name.
|
|
48
|
-
*/
|
|
49
|
-
export abstract class BaseModel<
|
|
50
|
-
TProps extends ModelProps,
|
|
51
|
-
FromSnapshotOverride extends Record<string, any>,
|
|
52
|
-
ToSnapshotOverride extends Record<string, any>,
|
|
53
|
-
ModelIdPropertyName extends string = never,
|
|
54
|
-
> {
|
|
55
|
-
// just to make typing work properly
|
|
56
|
-
[propsTypeSymbol]!: TProps;
|
|
57
|
-
[fromSnapshotOverrideTypeSymbol]!: FromSnapshotOverride;
|
|
58
|
-
[toSnapshotOverrideTypeSymbol]!: ToSnapshotOverride;
|
|
59
|
-
[modelIdPropertyNameSymbol]!: ModelIdPropertyName
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Model type name.
|
|
63
|
-
*/
|
|
64
|
-
readonly [modelTypeKey]!: string
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Model internal id. Can be modified inside a model action.
|
|
68
|
-
* It will return `undefined` if there's no id prop set.
|
|
69
|
-
*/
|
|
70
|
-
get [modelIdKey](): ModelIdPropertyType<TProps, ModelIdPropertyName> {
|
|
71
|
-
const idProp = getModelIdPropertyName(this.constructor as any)
|
|
72
|
-
return (idProp ? (this.$ as any)[idProp] : undefined) as ModelIdPropertyType<
|
|
73
|
-
TProps,
|
|
74
|
-
ModelIdPropertyName
|
|
75
|
-
>
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
set [modelIdKey](newId: ModelIdPropertyType<TProps, ModelIdPropertyName>) {
|
|
79
|
-
const idProp = getModelIdPropertyName(this.constructor as any)
|
|
80
|
-
if (!idProp) {
|
|
81
|
-
throw failure("$modelId cannot be set when there is no idProp set in the model")
|
|
82
|
-
}
|
|
83
|
-
;(this.$ as any)[idProp] = newId
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Can be overridden to offer a reference id to be used in reference resolution.
|
|
88
|
-
* By default it will use the `idProp` if available or return `undefined` otherwise.
|
|
89
|
-
*/
|
|
90
|
-
getRefId(): string | undefined {
|
|
91
|
-
return this[modelIdKey]
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Called after the model has been created.
|
|
96
|
-
*/
|
|
97
|
-
protected onInit?(): void
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Data part of the model, which is observable and will be serialized in snapshots.
|
|
101
|
-
* Use it if one of the data properties matches one of the model properties/functions.
|
|
102
|
-
*/
|
|
103
|
-
readonly $!: ModelPropsToUntransformedData<TProps>
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Optional hook that will run once this model instance is attached to the tree of a model marked as
|
|
107
|
-
* root store via `registerRootStore`.
|
|
108
|
-
* Basically this is the place where you know the full root store is complete and where things such as
|
|
109
|
-
* middlewares, effects (reactions, etc), and other side effects should be registered, since it means
|
|
110
|
-
* that the model is now part of the active application state.
|
|
111
|
-
*
|
|
112
|
-
* It can return a disposer that will be run once this model instance is detached from such root store tree.
|
|
113
|
-
*
|
|
114
|
-
* @param rootStore
|
|
115
|
-
* @returns
|
|
116
|
-
*/
|
|
117
|
-
protected onAttachedToRootStore?(rootStore: object): (() => void) | void
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Performs a type check over the model instance.
|
|
121
|
-
* For this to work a data type has to be declared as part of the model properties.
|
|
122
|
-
*
|
|
123
|
-
* @returns A `TypeCheckError` or `null` if there is no error.
|
|
124
|
-
*/
|
|
125
|
-
typeCheck(): TypeCheckError | null {
|
|
126
|
-
const type = typesModel<this>(this.constructor as any)
|
|
127
|
-
return typeCheck(type, this as any)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Creates an instance of a model.
|
|
132
|
-
*/
|
|
133
|
-
constructor(data: ModelPropsToTransformedCreationData<TProps>) {
|
|
134
|
-
const initialData = data as any
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
delete
|
|
145
|
-
delete self[
|
|
146
|
-
delete self[
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
"
|
|
192
|
-
"
|
|
193
|
-
"
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
* @
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
* @
|
|
227
|
-
* @
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
* @
|
|
251
|
-
* @
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
1
|
+
import { observable } from "mobx"
|
|
2
|
+
import {
|
|
3
|
+
fromSnapshotOverrideTypeSymbol,
|
|
4
|
+
type ModelClass,
|
|
5
|
+
propsTypeSymbol,
|
|
6
|
+
toSnapshotOverrideTypeSymbol,
|
|
7
|
+
} from "../modelShared/BaseModelShared"
|
|
8
|
+
import { modelInfoByClass } from "../modelShared/modelInfo"
|
|
9
|
+
import type {
|
|
10
|
+
ModelProps,
|
|
11
|
+
ModelPropsToTransformedCreationData,
|
|
12
|
+
ModelPropsToUntransformedData,
|
|
13
|
+
} from "../modelShared/prop"
|
|
14
|
+
import { getSnapshot } from "../snapshot/getSnapshot"
|
|
15
|
+
import type { SnapshotInOfModel, SnapshotOutOfModel } from "../snapshot/SnapshotOf"
|
|
16
|
+
import { typesModel } from "../types/objectBased/typesModel"
|
|
17
|
+
import type { TypeCheckError } from "../types/TypeCheckError"
|
|
18
|
+
import { typeCheck } from "../types/typeCheck"
|
|
19
|
+
import { assertIsObject, failure } from "../utils"
|
|
20
|
+
import { getModelIdPropertyName } from "./getModelMetadata"
|
|
21
|
+
import type { ModelConstructorOptions } from "./ModelConstructorOptions"
|
|
22
|
+
import { modelIdKey, modelTypeKey } from "./metadata"
|
|
23
|
+
import { internalFromSnapshotModel, internalNewModel } from "./newModel"
|
|
24
|
+
import { assertIsModelClass } from "./utils"
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @ignore
|
|
28
|
+
*/
|
|
29
|
+
export const modelIdPropertyNameSymbol = Symbol("modelIdPropertyName")
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @ignore
|
|
33
|
+
*/
|
|
34
|
+
export type ModelIdPropertyType<TProps extends ModelProps, ModelIdPropertyName extends string> = [
|
|
35
|
+
ModelIdPropertyName,
|
|
36
|
+
] extends [never]
|
|
37
|
+
? never
|
|
38
|
+
: ModelPropsToUntransformedData<Pick<TProps, ModelIdPropertyName>>[ModelIdPropertyName]
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Base abstract class for models. Use `Model` instead when extending.
|
|
42
|
+
*
|
|
43
|
+
* Never override the constructor, use `onInit` or `onAttachedToRootStore` instead.
|
|
44
|
+
*
|
|
45
|
+
* @template Data Data type.
|
|
46
|
+
* @template CreationData Creation data type.
|
|
47
|
+
* @template ModelIdPropertyName Model id property name.
|
|
48
|
+
*/
|
|
49
|
+
export abstract class BaseModel<
|
|
50
|
+
TProps extends ModelProps,
|
|
51
|
+
FromSnapshotOverride extends Record<string, any>,
|
|
52
|
+
ToSnapshotOverride extends Record<string, any>,
|
|
53
|
+
ModelIdPropertyName extends string = never,
|
|
54
|
+
> {
|
|
55
|
+
// just to make typing work properly
|
|
56
|
+
[propsTypeSymbol]!: TProps;
|
|
57
|
+
[fromSnapshotOverrideTypeSymbol]!: FromSnapshotOverride;
|
|
58
|
+
[toSnapshotOverrideTypeSymbol]!: ToSnapshotOverride;
|
|
59
|
+
[modelIdPropertyNameSymbol]!: ModelIdPropertyName
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Model type name.
|
|
63
|
+
*/
|
|
64
|
+
readonly [modelTypeKey]!: string
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Model internal id. Can be modified inside a model action.
|
|
68
|
+
* It will return `undefined` if there's no id prop set.
|
|
69
|
+
*/
|
|
70
|
+
get [modelIdKey](): ModelIdPropertyType<TProps, ModelIdPropertyName> {
|
|
71
|
+
const idProp = getModelIdPropertyName(this.constructor as any)
|
|
72
|
+
return (idProp ? (this.$ as any)[idProp] : undefined) as ModelIdPropertyType<
|
|
73
|
+
TProps,
|
|
74
|
+
ModelIdPropertyName
|
|
75
|
+
>
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
set [modelIdKey](newId: ModelIdPropertyType<TProps, ModelIdPropertyName>) {
|
|
79
|
+
const idProp = getModelIdPropertyName(this.constructor as any)
|
|
80
|
+
if (!idProp) {
|
|
81
|
+
throw failure("$modelId cannot be set when there is no idProp set in the model")
|
|
82
|
+
}
|
|
83
|
+
;(this.$ as any)[idProp] = newId
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Can be overridden to offer a reference id to be used in reference resolution.
|
|
88
|
+
* By default it will use the `idProp` if available or return `undefined` otherwise.
|
|
89
|
+
*/
|
|
90
|
+
getRefId(): string | undefined {
|
|
91
|
+
return this[modelIdKey]
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Called after the model has been created.
|
|
96
|
+
*/
|
|
97
|
+
protected onInit?(): void
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Data part of the model, which is observable and will be serialized in snapshots.
|
|
101
|
+
* Use it if one of the data properties matches one of the model properties/functions.
|
|
102
|
+
*/
|
|
103
|
+
readonly $!: ModelPropsToUntransformedData<TProps>
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Optional hook that will run once this model instance is attached to the tree of a model marked as
|
|
107
|
+
* root store via `registerRootStore`.
|
|
108
|
+
* Basically this is the place where you know the full root store is complete and where things such as
|
|
109
|
+
* middlewares, effects (reactions, etc), and other side effects should be registered, since it means
|
|
110
|
+
* that the model is now part of the active application state.
|
|
111
|
+
*
|
|
112
|
+
* It can return a disposer that will be run once this model instance is detached from such root store tree.
|
|
113
|
+
*
|
|
114
|
+
* @param rootStore
|
|
115
|
+
* @returns
|
|
116
|
+
*/
|
|
117
|
+
protected onAttachedToRootStore?(rootStore: object): (() => void) | void
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Performs a type check over the model instance.
|
|
121
|
+
* For this to work a data type has to be declared as part of the model properties.
|
|
122
|
+
*
|
|
123
|
+
* @returns A `TypeCheckError` or `null` if there is no error.
|
|
124
|
+
*/
|
|
125
|
+
typeCheck(): TypeCheckError | null {
|
|
126
|
+
const type = typesModel<this>(this.constructor as any)
|
|
127
|
+
return typeCheck(type, this as any)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Creates an instance of a model.
|
|
132
|
+
*/
|
|
133
|
+
constructor(data: ModelPropsToTransformedCreationData<TProps>) {
|
|
134
|
+
const initialData = data as any
|
|
135
|
+
const constructorOptions =
|
|
136
|
+
// biome-ignore lint/complexity/noArguments: internal factory code passes hidden constructor options through super().
|
|
137
|
+
arguments[1] as ModelConstructorOptions
|
|
138
|
+
const { snapshotInitialData, modelClass, generateNewIds } = constructorOptions
|
|
139
|
+
|
|
140
|
+
Object.setPrototypeOf(this, modelClass!.prototype)
|
|
141
|
+
|
|
142
|
+
const self = this as any
|
|
143
|
+
|
|
144
|
+
// delete unnecessary props
|
|
145
|
+
delete self[propsTypeSymbol]
|
|
146
|
+
delete self[fromSnapshotOverrideTypeSymbol]
|
|
147
|
+
delete self[toSnapshotOverrideTypeSymbol]
|
|
148
|
+
delete self[modelIdPropertyNameSymbol]
|
|
149
|
+
|
|
150
|
+
if (snapshotInitialData) {
|
|
151
|
+
// from snapshot
|
|
152
|
+
internalFromSnapshotModel(this, snapshotInitialData, modelClass!, !!generateNewIds)
|
|
153
|
+
} else {
|
|
154
|
+
// plain new
|
|
155
|
+
assertIsObject(initialData, "initialData")
|
|
156
|
+
|
|
157
|
+
internalNewModel(
|
|
158
|
+
this,
|
|
159
|
+
observable.object(initialData as any, undefined, { deep: false }),
|
|
160
|
+
modelClass!
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
toString(options?: { withData?: boolean }) {
|
|
166
|
+
const finalOptions = {
|
|
167
|
+
withData: true,
|
|
168
|
+
...options,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const firstPart = `${this.constructor.name}#${this[modelTypeKey]}`
|
|
172
|
+
|
|
173
|
+
return finalOptions.withData
|
|
174
|
+
? `[${firstPart} ${JSON.stringify(getSnapshot(this))}]`
|
|
175
|
+
: `[${firstPart}]`
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* @ignore
|
|
181
|
+
*/
|
|
182
|
+
export type BaseModelKeys = keyof AnyModel | "onInit" | "onAttachedToRootStore"
|
|
183
|
+
|
|
184
|
+
// these props will never be hoisted to this (except for model id)
|
|
185
|
+
/**
|
|
186
|
+
* @internal
|
|
187
|
+
*/
|
|
188
|
+
export const baseModelPropNames = new Set<BaseModelKeys>([
|
|
189
|
+
modelTypeKey,
|
|
190
|
+
modelIdKey,
|
|
191
|
+
"onInit",
|
|
192
|
+
"$",
|
|
193
|
+
"getRefId",
|
|
194
|
+
"onAttachedToRootStore",
|
|
195
|
+
"typeCheck",
|
|
196
|
+
])
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Any kind of model instance.
|
|
200
|
+
*/
|
|
201
|
+
export interface AnyModel extends BaseModel<any, any, any, any> {}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @deprecated Should not be needed anymore.
|
|
205
|
+
*
|
|
206
|
+
* Tricks TypeScript into accepting abstract classes as a parameter for `ExtendedModel`.
|
|
207
|
+
* Does nothing in runtime.
|
|
208
|
+
*
|
|
209
|
+
* @template T Abstract model class type.
|
|
210
|
+
* @param type Abstract model class.
|
|
211
|
+
* @returns
|
|
212
|
+
*/
|
|
213
|
+
export function abstractModelClass<T>(type: T): T & Object {
|
|
214
|
+
return type as any
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* The model id property name.
|
|
219
|
+
*/
|
|
220
|
+
export type ModelIdPropertyName<M extends AnyModel> = M[typeof modelIdPropertyNameSymbol]
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Add missing model metadata to a model creation snapshot to generate a proper model snapshot.
|
|
224
|
+
* Usually used alongside `fromSnapshot`.
|
|
225
|
+
*
|
|
226
|
+
* @template M Model type.
|
|
227
|
+
* @param modelClass Model class.
|
|
228
|
+
* @param snapshot Model creation snapshot without metadata.
|
|
229
|
+
* @returns The model snapshot (including metadata).
|
|
230
|
+
*/
|
|
231
|
+
export function modelSnapshotInWithMetadata<M extends AnyModel>(
|
|
232
|
+
modelClass: ModelClass<M>,
|
|
233
|
+
snapshot: Omit<SnapshotInOfModel<M>, typeof modelTypeKey>
|
|
234
|
+
): SnapshotInOfModel<M> {
|
|
235
|
+
assertIsModelClass(modelClass, "modelClass")
|
|
236
|
+
assertIsObject(snapshot, "initialData")
|
|
237
|
+
|
|
238
|
+
const modelInfo = modelInfoByClass.get(modelClass)!
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
...snapshot,
|
|
242
|
+
[modelTypeKey]: modelInfo.name,
|
|
243
|
+
} as any
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Add missing model metadata to a model output snapshot to generate a proper model snapshot.
|
|
248
|
+
* Usually used alongside `applySnapshot`.
|
|
249
|
+
*
|
|
250
|
+
* @template M Model type.
|
|
251
|
+
* @param modelClass Model class.
|
|
252
|
+
* @param snapshot Model output snapshot without metadata.
|
|
253
|
+
* @returns The model snapshot (including metadata).
|
|
254
|
+
*/
|
|
255
|
+
export function modelSnapshotOutWithMetadata<M extends AnyModel>(
|
|
256
|
+
modelClass: ModelClass<M>,
|
|
257
|
+
snapshot: Omit<SnapshotOutOfModel<M>, typeof modelTypeKey>
|
|
258
|
+
): SnapshotOutOfModel<M> {
|
|
259
|
+
assertIsModelClass(modelClass, "modelClass")
|
|
260
|
+
assertIsObject(snapshot, "initialData")
|
|
261
|
+
|
|
262
|
+
const modelInfo = modelInfoByClass.get(modelClass)!
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
...snapshot,
|
|
266
|
+
[modelTypeKey]: modelInfo.name,
|
|
267
|
+
} as any
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* A model class declaration, made of a base model and the model interface.
|
|
272
|
+
*/
|
|
273
|
+
export type ModelClassDeclaration<BaseModelClass, ModelInterface> = BaseModelClass & {
|
|
274
|
+
new (...args: any[]): ModelInterface
|
|
275
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
2
|
-
import type { AnyModel } from "./BaseModel"
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
export interface ModelConstructorOptions {
|
|
8
|
-
snapshotInitialData?: {
|
|
9
|
-
unprocessedSnapshot: any
|
|
10
|
-
unprocessedModelType: unknown
|
|
11
|
-
snapshotToInitialData(processedSnapshot: any): any
|
|
12
|
-
}
|
|
13
|
-
modelClass?: ModelClass<AnyModel>
|
|
14
|
-
generateNewIds?: boolean
|
|
15
|
-
}
|
|
1
|
+
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
2
|
+
import type { AnyModel } from "./BaseModel"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export interface ModelConstructorOptions {
|
|
8
|
+
snapshotInitialData?: {
|
|
9
|
+
unprocessedSnapshot: any
|
|
10
|
+
unprocessedModelType: unknown
|
|
11
|
+
snapshotToInitialData(processedSnapshot: any): any
|
|
12
|
+
}
|
|
13
|
+
modelClass?: ModelClass<AnyModel>
|
|
14
|
+
generateNewIds?: boolean
|
|
15
|
+
}
|