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,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 { snapshotInitialData, modelClass, generateNewIds }: ModelConstructorOptions =
136
- arguments[1]
137
-
138
- Object.setPrototypeOf(this, modelClass!.prototype)
139
-
140
- const self = this as any
141
-
142
- // delete unnecessary props
143
- delete self[propsTypeSymbol]
144
- delete self[fromSnapshotOverrideTypeSymbol]
145
- delete self[toSnapshotOverrideTypeSymbol]
146
- delete self[modelIdPropertyNameSymbol]
147
-
148
- if (snapshotInitialData) {
149
- // from snapshot
150
- internalFromSnapshotModel(this, snapshotInitialData, modelClass!, !!generateNewIds)
151
- } else {
152
- // plain new
153
- assertIsObject(initialData, "initialData")
154
-
155
- internalNewModel(
156
- this,
157
- observable.object(initialData as any, undefined, { deep: false }),
158
- modelClass!
159
- )
160
- }
161
- }
162
-
163
- toString(options?: { withData?: boolean }) {
164
- const finalOptions = {
165
- withData: true,
166
- ...options,
167
- }
168
-
169
- const firstPart = `${this.constructor.name}#${this[modelTypeKey]}`
170
-
171
- return finalOptions.withData
172
- ? `[${firstPart} ${JSON.stringify(getSnapshot(this))}]`
173
- : `[${firstPart}]`
174
- }
175
- }
176
-
177
- /**
178
- * @ignore
179
- */
180
- export type BaseModelKeys = keyof AnyModel | "onInit" | "onAttachedToRootStore"
181
-
182
- // these props will never be hoisted to this (except for model id)
183
- /**
184
- * @internal
185
- */
186
- export const baseModelPropNames = new Set<BaseModelKeys>([
187
- modelTypeKey,
188
- modelIdKey,
189
- "onInit",
190
- "$",
191
- "getRefId",
192
- "onAttachedToRootStore",
193
- "typeCheck",
194
- ])
195
-
196
- /**
197
- * Any kind of model instance.
198
- */
199
- export interface AnyModel extends BaseModel<any, any, any, any> {}
200
-
201
- /**
202
- * @deprecated Should not be needed anymore.
203
- *
204
- * Tricks TypeScript into accepting abstract classes as a parameter for `ExtendedModel`.
205
- * Does nothing in runtime.
206
- *
207
- * @template T Abstract model class type.
208
- * @param type Abstract model class.
209
- * @returns
210
- */
211
- export function abstractModelClass<T>(type: T): T & Object {
212
- return type as any
213
- }
214
-
215
- /**
216
- * The model id property name.
217
- */
218
- export type ModelIdPropertyName<M extends AnyModel> = M[typeof modelIdPropertyNameSymbol]
219
-
220
- /**
221
- * Add missing model metadata to a model creation snapshot to generate a proper model snapshot.
222
- * Usually used alongside `fromSnapshot`.
223
- *
224
- * @template M Model type.
225
- * @param modelClass Model class.
226
- * @param snapshot Model creation snapshot without metadata.
227
- * @returns The model snapshot (including metadata).
228
- */
229
- export function modelSnapshotInWithMetadata<M extends AnyModel>(
230
- modelClass: ModelClass<M>,
231
- snapshot: Omit<SnapshotInOfModel<M>, typeof modelTypeKey>
232
- ): SnapshotInOfModel<M> {
233
- assertIsModelClass(modelClass, "modelClass")
234
- assertIsObject(snapshot, "initialData")
235
-
236
- const modelInfo = modelInfoByClass.get(modelClass)!
237
-
238
- return {
239
- ...snapshot,
240
- [modelTypeKey]: modelInfo.name,
241
- } as any
242
- }
243
-
244
- /**
245
- * Add missing model metadata to a model output snapshot to generate a proper model snapshot.
246
- * Usually used alongside `applySnapshot`.
247
- *
248
- * @template M Model type.
249
- * @param modelClass Model class.
250
- * @param snapshot Model output snapshot without metadata.
251
- * @returns The model snapshot (including metadata).
252
- */
253
- export function modelSnapshotOutWithMetadata<M extends AnyModel>(
254
- modelClass: ModelClass<M>,
255
- snapshot: Omit<SnapshotOutOfModel<M>, typeof modelTypeKey>
256
- ): SnapshotOutOfModel<M> {
257
- assertIsModelClass(modelClass, "modelClass")
258
- assertIsObject(snapshot, "initialData")
259
-
260
- const modelInfo = modelInfoByClass.get(modelClass)!
261
-
262
- return {
263
- ...snapshot,
264
- [modelTypeKey]: modelInfo.name,
265
- } as any
266
- }
267
-
268
- /**
269
- * A model class declaration, made of a base model and the model interface.
270
- */
271
- export type ModelClassDeclaration<BaseModelClass, ModelInterface> = BaseModelClass & {
272
- new (...args: any[]): ModelInterface
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
+ }