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/ref/core.ts
CHANGED
|
@@ -1,345 +1,339 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
target
|
|
250
|
-
|
|
251
|
-
options
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
oldTarget
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
data.all.add(node)
|
|
341
|
-
const refsByThisType = getOrCreate(data.byType, node.constructor, () => new Set())
|
|
342
|
-
refsByThisType.add(node)
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
})
|
|
1
|
+
import { action, type ObservableSet, observable, reaction, when } from "mobx"
|
|
2
|
+
import { isModel } from "../model/utils"
|
|
3
|
+
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
4
|
+
import { model } from "../modelShared/modelDecorator"
|
|
5
|
+
import {
|
|
6
|
+
getDeepObjectChildren,
|
|
7
|
+
registerDeepObjectChildrenExtension,
|
|
8
|
+
} from "../parent/coreObjectChildren"
|
|
9
|
+
import { fastGetRoot } from "../parent/path"
|
|
10
|
+
import { type ComputedWalkTreeAggregate, computedWalkTreeAggregate } from "../parent/walkTree"
|
|
11
|
+
import { assertTweakedObject } from "../tweaker/core"
|
|
12
|
+
import { assertIsObject, failure } from "../utils"
|
|
13
|
+
import { getOrCreate } from "../utils/mapUtils"
|
|
14
|
+
import { Ref, type RefConstructor } from "./Ref"
|
|
15
|
+
|
|
16
|
+
interface BackRefs<T extends object> {
|
|
17
|
+
all: ObservableSet<Ref<T>>
|
|
18
|
+
byType: WeakMap<RefConstructor<T>, ObservableSet<Ref<T>>>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Back-references from object to the references that point to it.
|
|
23
|
+
*/
|
|
24
|
+
const objectBackRefs = new WeakMap<object, BackRefs<any>>()
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Reference resolver type.
|
|
28
|
+
*/
|
|
29
|
+
export type RefResolver<T extends object> = (ref: Ref<T>) => T | undefined
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Reference ID resolver type.
|
|
33
|
+
*/
|
|
34
|
+
export type RefIdResolver = (target: object) => string | undefined
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Type for the callback called when a reference resolved value changes.
|
|
38
|
+
*/
|
|
39
|
+
export type RefOnResolvedValueChange<T extends object> = (
|
|
40
|
+
ref: Ref<T>,
|
|
41
|
+
newValue: T | undefined,
|
|
42
|
+
oldValue: T | undefined
|
|
43
|
+
) => void
|
|
44
|
+
|
|
45
|
+
const trackedRefs = new WeakSet<Ref<object>>()
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export function internalCustomRef<T extends object>(
|
|
51
|
+
modelTypeId: string,
|
|
52
|
+
resolverGen: (ref: Ref<T>) => RefResolver<T>,
|
|
53
|
+
getId: RefIdResolver,
|
|
54
|
+
onResolvedValueChange: RefOnResolvedValueChange<T> | undefined
|
|
55
|
+
): RefConstructor<T> {
|
|
56
|
+
class CustomRefBase extends Ref<T> {
|
|
57
|
+
private resolver?: RefResolver<T>
|
|
58
|
+
private trackingStarted = false
|
|
59
|
+
|
|
60
|
+
protected resolve(): T | undefined {
|
|
61
|
+
if (!this.resolver) {
|
|
62
|
+
this.resolver = resolverGen(this)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.resolver(this)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private savedOldTarget: T | undefined
|
|
69
|
+
|
|
70
|
+
protected internalForceUpdateBackRefs(newTarget: T | undefined) {
|
|
71
|
+
const oldTarget = this.savedOldTarget
|
|
72
|
+
// update early in case of thrown exceptions
|
|
73
|
+
this.savedOldTarget = newTarget
|
|
74
|
+
|
|
75
|
+
if (newTarget === oldTarget) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
updateBackRefs(this, thisRefConstructor, newTarget, oldTarget)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
protected startTracking(initialTarget: T | undefined): boolean {
|
|
83
|
+
if (this.trackingStarted) {
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
this.trackingStarted = true
|
|
88
|
+
trackedRefs.add(this as Ref<object>)
|
|
89
|
+
this.internalForceUpdateBackRefs(initialTarget)
|
|
90
|
+
|
|
91
|
+
// according to mwestrate this won't leak as long as we don't keep the disposer around
|
|
92
|
+
reaction(
|
|
93
|
+
() => this.maybeCurrent,
|
|
94
|
+
(newTarget, oldTarget) => {
|
|
95
|
+
this.internalForceUpdateBackRefs(newTarget)
|
|
96
|
+
|
|
97
|
+
if (onResolvedValueChange && newTarget !== oldTarget) {
|
|
98
|
+
onResolvedValueChange(this, newTarget, oldTarget)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@action
|
|
107
|
+
forceUpdateBackRefs() {
|
|
108
|
+
const currentTarget = this.maybeCurrent
|
|
109
|
+
if (!this.startTracking(currentTarget)) {
|
|
110
|
+
this.internalForceUpdateBackRefs(currentTarget)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const CustomRef = (() => {
|
|
116
|
+
if (onResolvedValueChange) {
|
|
117
|
+
@model(modelTypeId)
|
|
118
|
+
class TrackedCustomRef extends CustomRefBase {
|
|
119
|
+
onInit() {
|
|
120
|
+
this.startTracking(this.maybeCurrent)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return TrackedCustomRef
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
@model(modelTypeId)
|
|
128
|
+
class LazyCustomRef extends CustomRefBase {}
|
|
129
|
+
|
|
130
|
+
return LazyCustomRef
|
|
131
|
+
})()
|
|
132
|
+
|
|
133
|
+
const fn = (target: T) => {
|
|
134
|
+
let id: string | undefined
|
|
135
|
+
if (typeof target === "string") {
|
|
136
|
+
id = target
|
|
137
|
+
} else {
|
|
138
|
+
assertIsObject(target, "target")
|
|
139
|
+
id = getId(target)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (typeof id !== "string") {
|
|
143
|
+
throw failure("ref target object must have an id of string type")
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const ref = new CustomRef({
|
|
147
|
+
id,
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
return ref
|
|
151
|
+
}
|
|
152
|
+
fn.refClass = CustomRef
|
|
153
|
+
|
|
154
|
+
const thisRefConstructor = fn as any as RefConstructor<T>
|
|
155
|
+
|
|
156
|
+
return thisRefConstructor
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Uses a model `getRefId()` method whenever possible to get a reference ID.
|
|
161
|
+
* If the model does not have an implementation of that method it returns `undefined`.
|
|
162
|
+
* If the model has an implementation, but that implementation returns anything other than
|
|
163
|
+
* a `string` it will throw.
|
|
164
|
+
*
|
|
165
|
+
* @param target Target object to get the ID from.
|
|
166
|
+
* @returns The string ID or `undefined`.
|
|
167
|
+
*/
|
|
168
|
+
export function getModelRefId(target: object): string | undefined {
|
|
169
|
+
if (isModel(target)) {
|
|
170
|
+
const id = target.getRefId()
|
|
171
|
+
if (id !== undefined && typeof id !== "string") {
|
|
172
|
+
throw failure("'getRefId()' must return a string or undefined when present")
|
|
173
|
+
}
|
|
174
|
+
return id
|
|
175
|
+
}
|
|
176
|
+
return undefined
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// one computed id tree per id function
|
|
180
|
+
const computedIdTrees = new WeakMap<
|
|
181
|
+
(node: object) => string | undefined,
|
|
182
|
+
ComputedWalkTreeAggregate<string>
|
|
183
|
+
>()
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Resolves a node given its ID.
|
|
187
|
+
*
|
|
188
|
+
* @template T Target object type.
|
|
189
|
+
* @param root Node where to start the search. The search will be done on it and all its children.
|
|
190
|
+
* @param id ID to search for.
|
|
191
|
+
* @param getId Function that will be used to get the ID from an object (`getModelRefId` by default).
|
|
192
|
+
* @returns The node found or `undefined` if none.
|
|
193
|
+
*/
|
|
194
|
+
export function resolveId<T extends object>(
|
|
195
|
+
root: object,
|
|
196
|
+
id: string,
|
|
197
|
+
getId: RefIdResolver = getModelRefId
|
|
198
|
+
): T | undefined {
|
|
199
|
+
// cache/reuse computedIdTrees for same getId function
|
|
200
|
+
const computedIdTree = getOrCreate(computedIdTrees, getId, () =>
|
|
201
|
+
computedWalkTreeAggregate<string>((node) => getId(node))
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
const idMap = computedIdTree.walk(root)
|
|
205
|
+
return idMap ? (idMap.get(id) as T | undefined) : undefined
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function getBackRefs<T extends object>(
|
|
209
|
+
target: T,
|
|
210
|
+
refType?: RefConstructor<T>
|
|
211
|
+
): ObservableSet<Ref<T>> {
|
|
212
|
+
let backRefs = objectBackRefs.get(target) as BackRefs<T> | undefined
|
|
213
|
+
if (!backRefs) {
|
|
214
|
+
backRefs = {
|
|
215
|
+
all: observable.set(undefined, { deep: false }),
|
|
216
|
+
byType: new WeakMap(),
|
|
217
|
+
}
|
|
218
|
+
objectBackRefs.set(target, backRefs)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (refType) {
|
|
222
|
+
let byType = backRefs.byType.get(refType)
|
|
223
|
+
if (!byType) {
|
|
224
|
+
byType = observable.set(undefined, { deep: false })
|
|
225
|
+
backRefs.byType.set(refType, byType)
|
|
226
|
+
}
|
|
227
|
+
return byType
|
|
228
|
+
} else {
|
|
229
|
+
return backRefs.all
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Gets all references that resolve to a given object.
|
|
235
|
+
*
|
|
236
|
+
* @template T Referenced object type.
|
|
237
|
+
* @param target Node the references point to.
|
|
238
|
+
* @param refType Pass it to filter by only references of a given type, or omit / pass `undefined` to get references of any type.
|
|
239
|
+
* @param options Options.
|
|
240
|
+
* @returns An observable set with all reference objects that point to the given object.
|
|
241
|
+
*/
|
|
242
|
+
export function getRefsResolvingTo<T extends object>(
|
|
243
|
+
target: T,
|
|
244
|
+
refType?: RefConstructor<T>,
|
|
245
|
+
options?: {
|
|
246
|
+
updateAllRefsIfNeeded?: boolean
|
|
247
|
+
}
|
|
248
|
+
): ObservableSet<Ref<T>> {
|
|
249
|
+
assertTweakedObject(target, "target")
|
|
250
|
+
|
|
251
|
+
const shouldForceUpdateTrackedRefs = options?.updateAllRefsIfNeeded && isReactionDelayed()
|
|
252
|
+
const refsChecked = new Set<Ref<object>>()
|
|
253
|
+
const updateRef = (ref: Ref<any>) => {
|
|
254
|
+
if (!refsChecked.has(ref)) {
|
|
255
|
+
if (
|
|
256
|
+
(!refType || ref instanceof refType.refClass) &&
|
|
257
|
+
(shouldForceUpdateTrackedRefs || !trackedRefs.has(ref as Ref<object>))
|
|
258
|
+
) {
|
|
259
|
+
ref.forceUpdateBackRefs()
|
|
260
|
+
}
|
|
261
|
+
refsChecked.add(ref)
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (shouldForceUpdateTrackedRefs) {
|
|
266
|
+
// in this case the reference update might have been delayed
|
|
267
|
+
// so we will make a best effort to update them
|
|
268
|
+
const oldBackRefs = getBackRefs(target, refType)
|
|
269
|
+
oldBackRefs.forEach(updateRef)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const refsChildrenOfRoot = getDeepChildrenRefs(getDeepObjectChildren(fastGetRoot(target, true)))
|
|
273
|
+
let refs: Set<Ref<object>> | undefined
|
|
274
|
+
if (refType) {
|
|
275
|
+
refs = refsChildrenOfRoot.byType.get(refType.refClass)
|
|
276
|
+
} else {
|
|
277
|
+
refs = refsChildrenOfRoot.all
|
|
278
|
+
}
|
|
279
|
+
refs?.forEach(updateRef)
|
|
280
|
+
|
|
281
|
+
return getBackRefs(target, refType)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const updateBackRefs = action(
|
|
285
|
+
"updateBackRefs",
|
|
286
|
+
<T extends object>(
|
|
287
|
+
ref: Ref<T>,
|
|
288
|
+
refClass: RefConstructor<T>,
|
|
289
|
+
newTarget: T | undefined,
|
|
290
|
+
oldTarget: T | undefined
|
|
291
|
+
) => {
|
|
292
|
+
if (newTarget === oldTarget) {
|
|
293
|
+
return
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (oldTarget) {
|
|
297
|
+
getBackRefs(oldTarget).delete(ref)
|
|
298
|
+
getBackRefs(oldTarget, refClass as RefConstructor<any>).delete(ref)
|
|
299
|
+
}
|
|
300
|
+
if (newTarget) {
|
|
301
|
+
getBackRefs(newTarget).add(ref)
|
|
302
|
+
getBackRefs(newTarget, refClass as RefConstructor<any>).add(ref)
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
function isReactionDelayed() {
|
|
308
|
+
let reactionDelayed = true
|
|
309
|
+
const dispose = when(
|
|
310
|
+
() => true,
|
|
311
|
+
() => {
|
|
312
|
+
reactionDelayed = false
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
dispose()
|
|
316
|
+
return reactionDelayed
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
interface DeepChildrenRefs {
|
|
320
|
+
all: Set<Ref<any>>
|
|
321
|
+
byType: WeakMap<ModelClass<Ref<any>>, Set<Ref<any>>>
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const getDeepChildrenRefs = registerDeepObjectChildrenExtension<DeepChildrenRefs>({
|
|
325
|
+
initData() {
|
|
326
|
+
return {
|
|
327
|
+
all: new Set(),
|
|
328
|
+
byType: new WeakMap(),
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
addNode(node, data) {
|
|
333
|
+
if (node instanceof Ref) {
|
|
334
|
+
data.all.add(node)
|
|
335
|
+
const refsByThisType = getOrCreate(data.byType, node.constructor, () => new Set())
|
|
336
|
+
refsByThisType.add(node)
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
})
|