mobx-keystone 2.0.0 → 2.2.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 +33 -0
- package/README.md +1 -1
- package/dist/mobx-keystone.esm.js +2561 -1214
- package/dist/mobx-keystone.esm.mjs +2561 -1214
- package/dist/mobx-keystone.umd.js +2566 -1220
- package/dist/types/actionMiddlewares/transactionMiddleware.d.ts +1 -1
- package/dist/types/actionMiddlewares/undoMiddleware.d.ts +11 -12
- package/dist/types/modelShared/modelDecorator.d.ts +5 -2
- package/dist/types/modelShared/prop.d.ts +42 -29
- package/dist/types/parent/arrayPaths.d.ts +1 -0
- package/dist/types/parent/treeOrder.d.ts +1 -0
- package/dist/types/patch/applyPatches.d.ts +2 -1
- package/dist/types/ref/Ref.d.ts +1 -4
- package/dist/types/ref/modelRefIdIndex.d.ts +1 -0
- package/dist/types/ref/nodesById.d.ts +1 -0
- package/dist/types/ref/refIdIndex.d.ts +1 -0
- package/dist/types/snapshot/SnapshotOf.d.ts +4 -4
- package/dist/types/snapshot/applySnapshot.d.ts +2 -1
- package/dist/types/snapshot/fromSnapshot.d.ts +2 -5
- package/dist/types/snapshot/getSnapshot.d.ts +1 -1
- package/dist/types/tweaker/changeRollback.d.ts +1 -0
- package/dist/types/tweaker/tweakedChangeListeners.d.ts +1 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/schemas.d.ts +41 -37
- package/dist/types/types/tProp.d.ts +12 -6
- package/dist/types/types/types.d.ts +6 -6
- package/dist/types/types/utility/typeToStoredData.d.ts +14 -10
- package/dist/types/types/utility/typesCodecCore.d.ts +3 -0
- package/dist/types/utils/ModelPool.d.ts +7 -2
- package/dist/types/utils/chunks.d.ts +1 -0
- package/dist/types/utils/types.d.ts +6 -0
- package/dist/types/wrappers/ArraySet.d.ts +1 -0
- package/package.json +5 -3
- package/src/action/modelFlow.ts +35 -66
- package/src/actionMiddlewares/actionTrackingMiddleware.ts +41 -71
- package/src/actionMiddlewares/transactionMiddleware.ts +41 -42
- package/src/actionMiddlewares/undoMiddleware.ts +63 -35
- package/src/context/context.ts +15 -36
- package/src/dataModel/utils.ts +5 -28
- package/src/deepChange/onDeepChange.ts +44 -126
- package/src/model/BaseModel.ts +7 -5
- package/src/model/utils.ts +5 -10
- package/src/modelShared/modelDecorator.ts +16 -30
- package/src/modelShared/prop.ts +115 -111
- package/src/modelShared/sharedInternalModel.ts +2 -2
- package/src/parent/arrayPaths.ts +239 -0
- package/src/parent/coreObjectChildren.ts +300 -48
- package/src/parent/onChildAttachedTo.ts +130 -44
- package/src/parent/path.ts +10 -12
- package/src/parent/setParent.ts +27 -15
- package/src/parent/treeOrder.ts +53 -0
- package/src/parent/walkTree.ts +0 -73
- package/src/patch/applyPatches.ts +31 -26
- package/src/patch/patchRecorder.ts +13 -28
- package/src/ref/core.ts +69 -46
- package/src/ref/modelRefIdIndex.ts +131 -0
- package/src/ref/nodesById.ts +60 -0
- package/src/ref/refIdIndex.ts +209 -0
- package/src/rootStore/rootStore.ts +1 -3
- package/src/snapshot/SnapshotOf.ts +24 -48
- package/src/snapshot/applySnapshot.ts +27 -19
- package/src/snapshot/fromPlainObjectSnapshot.ts +3 -8
- package/src/snapshot/fromSnapshot.ts +12 -9
- package/src/snapshot/getSnapshot.ts +1 -1
- package/src/snapshot/internal.ts +67 -12
- package/src/snapshot/reconcileModelSnapshot.ts +5 -3
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +3 -1
- package/src/treeUtils/draft.ts +6 -1
- package/src/treeUtils/sandbox.ts +10 -7
- package/src/tweaker/changeRollback.ts +218 -0
- package/src/tweaker/core.ts +33 -20
- package/src/tweaker/treeNodeMetadata.ts +12 -2
- package/src/tweaker/tweak.ts +181 -18
- package/src/tweaker/tweakArray.ts +127 -77
- package/src/tweaker/tweakPlainObject.ts +65 -46
- package/src/tweaker/tweakedChangeListeners.ts +61 -0
- package/src/tweaker/typeChecking.ts +5 -104
- package/src/types/arrayBased/typesArray.ts +23 -30
- package/src/types/arrayBased/typesTuple.ts +16 -25
- package/src/types/createCachedTypeCheck.ts +509 -94
- package/src/types/index.ts +1 -0
- package/src/types/objectBased/typesDataModelData.ts +7 -8
- package/src/types/objectBased/typesObject.ts +11 -15
- package/src/types/objectBased/typesRecord.ts +12 -19
- package/src/types/schemas.ts +59 -71
- package/src/types/tProp.ts +29 -29
- package/src/types/utility/typeToStoredData.ts +22 -21
- package/src/types/utility/typesCodecCore.ts +5 -0
- package/src/types/utility/typesCodecSupport.ts +3 -3
- package/src/types/utility/typesMap.ts +43 -51
- package/src/types/utility/typesRefinement.ts +7 -8
- package/src/types/utility/typesSkipCheck.ts +7 -8
- package/src/types/utility/typesTag.ts +7 -8
- package/src/utils/ModelPool.ts +76 -37
- package/src/utils/chunks.ts +271 -0
- package/src/utils/decorators.ts +5 -5
- package/src/utils/index.ts +38 -20
- package/src/utils/types.ts +5 -0
- package/src/wrappers/ArraySet.ts +27 -14
- package/src/wrappers/ObjectMap.ts +1 -6
- package/src/wrappers/asMap.ts +1 -21
- package/src/wrappers/asSet.ts +0 -8
package/src/utils/index.ts
CHANGED
|
@@ -267,15 +267,6 @@ export function assertIsObject(value: unknown, argName: string): asserts value i
|
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
/**
|
|
271
|
-
* @internal
|
|
272
|
-
*/
|
|
273
|
-
export function assertIsPlainObject(value: unknown, argName: string): asserts value is object {
|
|
274
|
-
if (!isPlainObject(value)) {
|
|
275
|
-
throw failure(`${argName} must be a plain object`)
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
270
|
/**
|
|
280
271
|
* @internal
|
|
281
272
|
*/
|
|
@@ -342,15 +333,6 @@ export function assertIsPrimitive(
|
|
|
342
333
|
}
|
|
343
334
|
}
|
|
344
335
|
|
|
345
|
-
/**
|
|
346
|
-
* @internal
|
|
347
|
-
*/
|
|
348
|
-
export function assertIsString(value: unknown, argName: string): asserts value is string {
|
|
349
|
-
if (typeof value !== "string") {
|
|
350
|
-
throw failure(`${argName} must be a string`)
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
336
|
/**
|
|
355
337
|
* @internal
|
|
356
338
|
*/
|
|
@@ -372,8 +354,7 @@ export function addLateInitializationFunction(
|
|
|
372
354
|
fn: (instance: any) => void
|
|
373
355
|
) {
|
|
374
356
|
let array: LateInitializationFunctionsArray | undefined = target[symbol]
|
|
375
|
-
|
|
376
|
-
if (!(array && Object.prototype.hasOwnProperty.call(target, symbol))) {
|
|
357
|
+
if (!(array && hasOwnProp(target, symbol))) {
|
|
377
358
|
// leave base array unmodified, create new array in the derived class
|
|
378
359
|
array = array ? array.slice() : []
|
|
379
360
|
addHiddenProp(target, symbol, array)
|
|
@@ -558,6 +539,43 @@ function isStandardDecoratorContext(value: unknown): boolean {
|
|
|
558
539
|
)
|
|
559
540
|
}
|
|
560
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Options for the observable objects of tree nodes. Their values are never
|
|
544
|
+
* functions nor getters, so the shared `observable.ref` annotation (MobX 7
|
|
545
|
+
* `observableRef`) is equivalent to `deep: false` alone, which MobX 6+ would
|
|
546
|
+
* allocate an annotation for on every object.
|
|
547
|
+
*
|
|
548
|
+
* @internal
|
|
549
|
+
*/
|
|
550
|
+
export const nodeObservableOptions = {
|
|
551
|
+
deep: false,
|
|
552
|
+
defaultDecorator:
|
|
553
|
+
// (computed so bundlers do not warn about the export missing in MobX < 7)
|
|
554
|
+
(mobx as any)[["observable", "Ref"].join("")] ?? (mobx.observable as any).ref,
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// the key MobX 6 stores legacy decorator annotations under (null if unknown)
|
|
558
|
+
let storedMobxAnnotationsKey: symbol | null | undefined
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Whether an instance has legacy decorator annotations for MobX 6
|
|
562
|
+
* `makeObservable` to apply. When their key cannot be found it answers true,
|
|
563
|
+
* so `makeObservable` is still called.
|
|
564
|
+
*
|
|
565
|
+
* @internal
|
|
566
|
+
*/
|
|
567
|
+
export function hasStoredMobxAnnotations(instance: object): boolean {
|
|
568
|
+
if (storedMobxAnnotationsKey === undefined) {
|
|
569
|
+
// a legacy decorator call stores its annotation under that key
|
|
570
|
+
const probe = {}
|
|
571
|
+
;(mobx.observable as any)(probe, "probe")
|
|
572
|
+
storedMobxAnnotationsKey = Object.getOwnPropertySymbols(probe)[0] ?? null
|
|
573
|
+
}
|
|
574
|
+
return (
|
|
575
|
+
storedMobxAnnotationsKey === null || (instance as any)[storedMobxAnnotationsKey] !== undefined
|
|
576
|
+
)
|
|
577
|
+
}
|
|
578
|
+
|
|
561
579
|
/**
|
|
562
580
|
* Calls `makeObservable` across MobX versions. MobX 7 requires an annotations
|
|
563
581
|
* object, while MobX 6 and older versions use decorator metadata when no
|
package/src/utils/types.ts
CHANGED
|
@@ -46,3 +46,8 @@ export type IsNeverType<T, IfNever, IfNotNever> = [T] extends [never] ? IfNever
|
|
|
46
46
|
* @ignore
|
|
47
47
|
*/
|
|
48
48
|
export type Flatten<T> = T extends Record<any, any> ? { [P in keyof T]: T[P] } : T
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @ignore
|
|
52
|
+
*/
|
|
53
|
+
export type SimplifyObject<T> = { [P in keyof T]: T[P] } & {}
|
package/src/wrappers/ArraySet.ts
CHANGED
|
@@ -8,6 +8,15 @@ import { typesArray } from "../types/arrayBased/typesArray"
|
|
|
8
8
|
import { tProp } from "../types/tProp"
|
|
9
9
|
import { typesUnchecked } from "../types/utility/typesUnchecked"
|
|
10
10
|
import { namespace } from "../utils"
|
|
11
|
+
import {
|
|
12
|
+
isSetLikeDisjointFrom,
|
|
13
|
+
isSetLikeSubsetOf,
|
|
14
|
+
isSetLikeSupersetOf,
|
|
15
|
+
setLikeDifference,
|
|
16
|
+
setLikeIntersection,
|
|
17
|
+
setLikeSymmetricDifference,
|
|
18
|
+
setLikeUnion,
|
|
19
|
+
} from "../utils/setLike"
|
|
11
20
|
|
|
12
21
|
const arraySetBase = Model({
|
|
13
22
|
[modelIdKey]: idProp,
|
|
@@ -96,39 +105,43 @@ export class ArraySet<V> extends arraySetBase implements Set<V> {
|
|
|
96
105
|
|
|
97
106
|
readonly [Symbol.toStringTag] = "ArraySet"
|
|
98
107
|
|
|
108
|
+
// `has` scans the items, so the set operations look values up in a set built
|
|
109
|
+
// on the first lookup instead (not before, since many of them never look up)
|
|
110
|
+
private toSetLike(): ReadonlySetLike<V> {
|
|
111
|
+
let lookup: Set<V> | undefined
|
|
112
|
+
return {
|
|
113
|
+
size: this.items.length,
|
|
114
|
+
has: (value) => (lookup ??= new Set(this.items)).has(value),
|
|
115
|
+
keys: () => this.values(),
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
99
119
|
union<U>(other: ReadonlySetLike<U>): Set<V | U> {
|
|
100
|
-
|
|
101
|
-
return s.union(other)
|
|
120
|
+
return setLikeUnion(this.toSetLike(), other)
|
|
102
121
|
}
|
|
103
122
|
|
|
104
123
|
intersection<U>(other: ReadonlySetLike<U>): Set<V & U> {
|
|
105
|
-
|
|
106
|
-
return s.intersection(other)
|
|
124
|
+
return setLikeIntersection(this.toSetLike(), other)
|
|
107
125
|
}
|
|
108
126
|
|
|
109
127
|
difference<U>(other: ReadonlySetLike<U>): Set<V> {
|
|
110
|
-
|
|
111
|
-
return s.difference(other)
|
|
128
|
+
return setLikeDifference(this.toSetLike(), other)
|
|
112
129
|
}
|
|
113
130
|
|
|
114
131
|
symmetricDifference<U>(other: ReadonlySetLike<U>): Set<V | U> {
|
|
115
|
-
|
|
116
|
-
return s.symmetricDifference(other)
|
|
132
|
+
return setLikeSymmetricDifference(this.toSetLike(), other)
|
|
117
133
|
}
|
|
118
134
|
|
|
119
135
|
isSubsetOf(other: ReadonlySetLike<unknown>): boolean {
|
|
120
|
-
|
|
121
|
-
return s.isSubsetOf(other)
|
|
136
|
+
return isSetLikeSubsetOf(this.toSetLike(), other)
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
isSupersetOf(other: ReadonlySetLike<unknown>): boolean {
|
|
125
|
-
|
|
126
|
-
return s.isSupersetOf(other)
|
|
140
|
+
return isSetLikeSupersetOf(this.toSetLike(), other)
|
|
127
141
|
}
|
|
128
142
|
|
|
129
143
|
isDisjointFrom(other: ReadonlySetLike<unknown>): boolean {
|
|
130
|
-
|
|
131
|
-
return s.isDisjointFrom(other)
|
|
144
|
+
return isSetLikeDisjointFrom(this.toSetLike(), other)
|
|
132
145
|
}
|
|
133
146
|
}
|
|
134
147
|
|
|
@@ -70,12 +70,7 @@ export class ObjectMap<V> extends objectMapBase implements Map<string, V> {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
getOrInsert(key: string, defaultValue: V): V {
|
|
73
|
-
|
|
74
|
-
return this.get(key) as V
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
this.set(key, defaultValue)
|
|
78
|
-
return this.get(key) as V
|
|
73
|
+
return this.getOrInsertComputed(key, () => defaultValue)
|
|
79
74
|
}
|
|
80
75
|
|
|
81
76
|
getOrInsertComputed(key: string, callback: (key: string) => V): V {
|
package/src/wrappers/asMap.ts
CHANGED
|
@@ -4,8 +4,6 @@ import {
|
|
|
4
4
|
type IObjectDidChange,
|
|
5
5
|
type IObservableArray,
|
|
6
6
|
intercept,
|
|
7
|
-
isObservableArray,
|
|
8
|
-
isObservableObject,
|
|
9
7
|
type ObservableMap,
|
|
10
8
|
observable,
|
|
11
9
|
observe,
|
|
@@ -21,7 +19,6 @@ import {
|
|
|
21
19
|
failure,
|
|
22
20
|
getMobxVersion,
|
|
23
21
|
hasOwnProp,
|
|
24
|
-
inDevMode,
|
|
25
22
|
isArray,
|
|
26
23
|
isEqualOrBothNaN,
|
|
27
24
|
setProtoProp,
|
|
@@ -44,12 +41,7 @@ function addTs6MapExtras<K, V>(map: ObservableMap<K, V>): ObservableMap<K, V> &
|
|
|
44
41
|
|
|
45
42
|
if (!mapWithExtras.getOrInsert) {
|
|
46
43
|
mapWithExtras.getOrInsert = function (key: K, defaultValue: V): V {
|
|
47
|
-
|
|
48
|
-
return this.get(key) as V
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this.set(key, defaultValue)
|
|
52
|
-
return this.get(key) as V
|
|
44
|
+
return this.getOrInsertComputed(key, () => defaultValue)
|
|
53
45
|
}
|
|
54
46
|
}
|
|
55
47
|
|
|
@@ -70,12 +62,6 @@ function addTs6MapExtras<K, V>(map: ObservableMap<K, V>): ObservableMap<K, V> &
|
|
|
70
62
|
|
|
71
63
|
const observableMapBackedByObservableObject = action(
|
|
72
64
|
<T>(obj: object): ObservableMapWithDataObject<string, T, typeof obj> => {
|
|
73
|
-
if (inDevMode) {
|
|
74
|
-
if (!isObservableObject(obj)) {
|
|
75
|
-
throw failure("assertion failed: expected an observable object")
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
65
|
const map = transaction(() =>
|
|
80
66
|
untracked(() => {
|
|
81
67
|
const map = observable.map<string, T>(undefined, { deep: false })
|
|
@@ -175,12 +161,6 @@ const observableMapBackedByObservableObject = action(
|
|
|
175
161
|
const observableMapBackedByObservableArray = <K, T>(
|
|
176
162
|
array: IObservableArray<[K, T]>
|
|
177
163
|
): ObservableMapWithDataObject<K, T, typeof array> => {
|
|
178
|
-
if (inDevMode) {
|
|
179
|
-
if (!isObservableArray(array)) {
|
|
180
|
-
throw failure("assertion failed: expected an observable array")
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
164
|
const map: ObservableMap<K, T> = untracked(() => {
|
|
185
165
|
if (getMobxVersion() >= 6) {
|
|
186
166
|
return observable.map<K, T>(array, { deep: false })
|
package/src/wrappers/asSet.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
type IObservableArray,
|
|
4
4
|
type ISetWillChange,
|
|
5
5
|
intercept,
|
|
6
|
-
isObservableArray,
|
|
7
6
|
type ObservableSet,
|
|
8
7
|
observable,
|
|
9
8
|
observe,
|
|
@@ -16,7 +15,6 @@ import {
|
|
|
16
15
|
assertIsSet,
|
|
17
16
|
failure,
|
|
18
17
|
getMobxVersion,
|
|
19
|
-
inDevMode,
|
|
20
18
|
isEqualOrBothNaN,
|
|
21
19
|
} from "../utils"
|
|
22
20
|
import { tag } from "../utils/tag"
|
|
@@ -24,12 +22,6 @@ import { tag } from "../utils/tag"
|
|
|
24
22
|
const observableSetBackedByObservableArray = <T>(
|
|
25
23
|
array: IObservableArray<T>
|
|
26
24
|
): ObservableSet<T> & { dataObject: typeof array } => {
|
|
27
|
-
if (inDevMode) {
|
|
28
|
-
if (!isObservableArray(array)) {
|
|
29
|
-
throw failure("assertion failed: expected an observable array")
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
25
|
const set = transaction(() =>
|
|
34
26
|
untracked(() => {
|
|
35
27
|
if (getMobxVersion() >= 6) {
|