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,156 +1,156 @@
1
- import { values } from "mobx"
2
- import { modelAction } from "../action/modelAction"
3
- import type { AnyModel } from "../model/BaseModel"
4
- import { Model } from "../model/Model"
5
- import { modelIdKey } from "../model/metadata"
6
- import { model } from "../modelShared/modelDecorator"
7
- import { idProp } from "../modelShared/prop"
8
- import { typesArray } from "../types/arrayBased/typesArray"
9
- import { tProp } from "../types/tProp"
10
- import { typesUnchecked } from "../types/utility/typesUnchecked"
11
- import { namespace } from "../utils"
12
-
13
- const arraySetBase = Model({
14
- [modelIdKey]: idProp,
15
- items: tProp(typesArray(typesUnchecked<any>()), () => []), // will be properly checked by types.arraySet(subType)
16
- }) as abstract new (
17
- data: any
18
- ) => AnyModel & {
19
- readonly $: {
20
- items: any[]
21
- }
22
- readonly items: any[]
23
- }
24
-
25
- /**
26
- * A set that is backed by an array.
27
- * Use `arraySet` to create it.
28
- */
29
- @model(`${namespace}/ArraySet`)
30
- // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
31
- export class ArraySet<V> extends arraySetBase implements Set<V> {
32
- @modelAction
33
- add(value: V): this {
34
- const items = this.items
35
-
36
- if (!items.includes(value)) {
37
- items.push(value)
38
- }
39
- return this
40
- }
41
-
42
- @modelAction
43
- clear(): void {
44
- this.items.length = 0
45
- }
46
-
47
- @modelAction
48
- delete(value: V): boolean {
49
- const items = this.items
50
-
51
- const index = items.indexOf(value)
52
- if (index >= 0) {
53
- items.splice(index, 1)
54
- return true
55
- } else {
56
- return false
57
- }
58
- }
59
-
60
- forEach(callbackfn: (value: V, value2: V, set: Set<V>) => void, thisArg?: any): void {
61
- // we cannot use the set implementation since we need to pass this as set
62
- const items = this.items
63
- const len = items.length
64
- for (let i = 0; i < len; i++) {
65
- const k = items[i]
66
- callbackfn.call(thisArg, k, k, this)
67
- }
68
- }
69
-
70
- has(value: V): boolean {
71
- return this.items.includes(value)
72
- }
73
-
74
- get size(): number {
75
- return this.items.length
76
- }
77
-
78
- *keys(): ReturnType<Set<V>["keys"]> {
79
- // yes, values
80
- for (const value of values(this.items)) {
81
- yield value as V
82
- }
83
- }
84
-
85
- *values(): ReturnType<Set<V>["values"]> {
86
- for (const value of values(this.items)) {
87
- yield value as V
88
- }
89
- }
90
-
91
- *entries(): ReturnType<Set<V>["entries"]> {
92
- for (const v of this.items) {
93
- yield [v, v]
94
- }
95
- }
96
-
97
- [Symbol.iterator](): ReturnType<Set<V>[typeof Symbol.iterator]> {
98
- return this.values()
99
- }
100
-
101
- readonly [Symbol.toStringTag] = "ArraySet"
102
-
103
- union<U>(other: ReadonlySetLike<U>): Set<V | U> {
104
- const s = new Set(this)
105
- return s.union(other)
106
- }
107
-
108
- intersection<U>(other: ReadonlySetLike<U>): Set<V & U> {
109
- const s = new Set(this)
110
- return s.intersection(other)
111
- }
112
-
113
- difference<U>(other: ReadonlySetLike<U>): Set<V> {
114
- const s = new Set(this)
115
- return s.difference(other)
116
- }
117
-
118
- symmetricDifference<U>(other: ReadonlySetLike<U>): Set<V | U> {
119
- const s = new Set(this)
120
- return s.symmetricDifference(other)
121
- }
122
-
123
- isSubsetOf(other: ReadonlySetLike<unknown>): boolean {
124
- const s = new Set(this)
125
- return s.isSubsetOf(other)
126
- }
127
-
128
- isSupersetOf(other: ReadonlySetLike<unknown>): boolean {
129
- const s = new Set(this)
130
- return s.isSupersetOf(other)
131
- }
132
-
133
- isDisjointFrom(other: ReadonlySetLike<unknown>): boolean {
134
- const s = new Set(this)
135
- return s.isDisjointFrom(other)
136
- }
137
- }
138
-
139
- export interface ArraySet<V> {
140
- readonly $: {
141
- items: V[]
142
- }
143
- readonly items: V[]
144
- }
145
-
146
- /**
147
- * Creates a new ArraySet model instance.
148
- *
149
- * @template V Value type.
150
- * @param [values] Optional initial values.
151
- */
152
- export function arraySet<V>(values?: ReadonlyArray<V> | null): ArraySet<V> {
153
- const initialArr: V[] = values ? values.slice() : []
154
-
155
- return new ArraySet({ items: initialArr })
156
- }
1
+ import { values } from "mobx"
2
+ import { modelAction } from "../action/modelAction"
3
+ import type { AnyModel } from "../model/BaseModel"
4
+ import { Model } from "../model/Model"
5
+ import { modelIdKey } from "../model/metadata"
6
+ import { model } from "../modelShared/modelDecorator"
7
+ import { idProp } from "../modelShared/prop"
8
+ import { typesArray } from "../types/arrayBased/typesArray"
9
+ import { tProp } from "../types/tProp"
10
+ import { typesUnchecked } from "../types/utility/typesUnchecked"
11
+ import { namespace } from "../utils"
12
+
13
+ const arraySetBase = Model({
14
+ [modelIdKey]: idProp,
15
+ items: tProp(typesArray(typesUnchecked<any>()), () => []), // will be properly checked by types.arraySet(subType)
16
+ }) as abstract new (
17
+ data: any
18
+ ) => AnyModel & {
19
+ readonly $: {
20
+ items: any[]
21
+ }
22
+ readonly items: any[]
23
+ }
24
+
25
+ /**
26
+ * A set that is backed by an array.
27
+ * Use `arraySet` to create it.
28
+ */
29
+ @model(`${namespace}/ArraySet`)
30
+ // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
31
+ export class ArraySet<V> extends arraySetBase implements Set<V> {
32
+ @modelAction
33
+ add(value: V): this {
34
+ const items = this.items
35
+
36
+ if (!items.includes(value)) {
37
+ items.push(value)
38
+ }
39
+ return this
40
+ }
41
+
42
+ @modelAction
43
+ clear(): void {
44
+ this.items.length = 0
45
+ }
46
+
47
+ @modelAction
48
+ delete(value: V): boolean {
49
+ const items = this.items
50
+
51
+ const index = items.indexOf(value)
52
+ if (index >= 0) {
53
+ items.splice(index, 1)
54
+ return true
55
+ } else {
56
+ return false
57
+ }
58
+ }
59
+
60
+ forEach(callbackfn: (value: V, value2: V, set: Set<V>) => void, thisArg?: any): void {
61
+ // we cannot use the set implementation since we need to pass this as set
62
+ const items = this.items
63
+ const len = items.length
64
+ for (let i = 0; i < len; i++) {
65
+ const k = items[i]
66
+ callbackfn.call(thisArg, k, k, this)
67
+ }
68
+ }
69
+
70
+ has(value: V): boolean {
71
+ return this.items.includes(value)
72
+ }
73
+
74
+ get size(): number {
75
+ return this.items.length
76
+ }
77
+
78
+ *keys(): ReturnType<Set<V>["keys"]> {
79
+ // yes, values
80
+ for (const value of values(this.items)) {
81
+ yield value as V
82
+ }
83
+ }
84
+
85
+ *values(): ReturnType<Set<V>["values"]> {
86
+ for (const value of values(this.items)) {
87
+ yield value as V
88
+ }
89
+ }
90
+
91
+ *entries(): ReturnType<Set<V>["entries"]> {
92
+ for (const v of this.items) {
93
+ yield [v, v]
94
+ }
95
+ }
96
+
97
+ [Symbol.iterator](): ReturnType<Set<V>[typeof Symbol.iterator]> {
98
+ return this.values()
99
+ }
100
+
101
+ readonly [Symbol.toStringTag] = "ArraySet"
102
+
103
+ union<U>(other: ReadonlySetLike<U>): Set<V | U> {
104
+ const s = new Set(this)
105
+ return s.union(other)
106
+ }
107
+
108
+ intersection<U>(other: ReadonlySetLike<U>): Set<V & U> {
109
+ const s = new Set(this)
110
+ return s.intersection(other)
111
+ }
112
+
113
+ difference<U>(other: ReadonlySetLike<U>): Set<V> {
114
+ const s = new Set(this)
115
+ return s.difference(other)
116
+ }
117
+
118
+ symmetricDifference<U>(other: ReadonlySetLike<U>): Set<V | U> {
119
+ const s = new Set(this)
120
+ return s.symmetricDifference(other)
121
+ }
122
+
123
+ isSubsetOf(other: ReadonlySetLike<unknown>): boolean {
124
+ const s = new Set(this)
125
+ return s.isSubsetOf(other)
126
+ }
127
+
128
+ isSupersetOf(other: ReadonlySetLike<unknown>): boolean {
129
+ const s = new Set(this)
130
+ return s.isSupersetOf(other)
131
+ }
132
+
133
+ isDisjointFrom(other: ReadonlySetLike<unknown>): boolean {
134
+ const s = new Set(this)
135
+ return s.isDisjointFrom(other)
136
+ }
137
+ }
138
+
139
+ export interface ArraySet<V> {
140
+ readonly $: {
141
+ items: V[]
142
+ }
143
+ readonly items: V[]
144
+ }
145
+
146
+ /**
147
+ * Creates a new ArraySet model instance.
148
+ *
149
+ * @template V Value type.
150
+ * @param [values] Optional initial values.
151
+ */
152
+ export function arraySet<V>(values?: ReadonlyArray<V> | null): ArraySet<V> {
153
+ const initialArr: V[] = values ? values.slice() : []
154
+
155
+ return new ArraySet({ items: initialArr })
156
+ }
@@ -1,136 +1,155 @@
1
- import { entries, get, has, keys, remove, values } from "mobx"
2
- import { modelAction } from "../action/modelAction"
3
- import type { AnyModel } from "../model/BaseModel"
4
- import { Model } from "../model/Model"
5
- import { modelIdKey } from "../model/metadata"
6
- import { model } from "../modelShared/modelDecorator"
7
- import { idProp } from "../modelShared/prop"
8
- import { typesRecord } from "../types/objectBased/typesRecord"
9
- import { tProp } from "../types/tProp"
10
- import { typesUnchecked } from "../types/utility/typesUnchecked"
11
- import { namespace } from "../utils"
12
- import { setIfDifferent } from "../utils/setIfDifferent"
13
-
14
- const objectMapBase = Model({
15
- [modelIdKey]: idProp,
16
- items: tProp(typesRecord(typesUnchecked<any>()), () => ({})), // will be properly checked by types.objectMap(subType)
17
- }) as abstract new (
18
- data: any
19
- ) => AnyModel & {
20
- readonly $: {
21
- items: Record<string, any>
22
- }
23
- readonly items: Record<string, any>
24
- }
25
-
26
- /**
27
- * A map that is backed by an object-like map.
28
- * Use `objectMap` to create it.
29
- */
30
- @model(`${namespace}/ObjectMap`)
31
- // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
32
- export class ObjectMap<V> extends objectMapBase implements Map<string, V> {
33
- @modelAction
34
- clear(): void {
35
- const items = this.items
36
-
37
- const keys = Object.keys(items)
38
- const len = keys.length
39
- for (let i = 0; i < len; i++) {
40
- const k = keys[i]
41
- remove(items, k)
42
- }
43
- }
44
-
45
- @modelAction
46
- delete(key: string): boolean {
47
- const hasKey = this.has(key)
48
- if (hasKey) {
49
- remove(this.items, key)
50
- return true
51
- } else {
52
- return false
53
- }
54
- }
55
-
56
- forEach(callbackfn: (value: V, key: string, map: Map<string, V>) => void, thisArg?: any): void {
57
- // we cannot use the map implementation since we need to pass this as map
58
- const items = this.items
59
-
60
- const keys = Object.keys(items)
61
- const len = keys.length
62
- for (let i = 0; i < len; i++) {
63
- const k = keys[i]
64
- callbackfn.call(thisArg, items[k], k, this)
65
- }
66
- }
67
-
68
- get(key: string): V | undefined {
69
- return get(this.items, key)
70
- }
71
-
72
- has(key: string): boolean {
73
- return has(this.items, key)
74
- }
75
-
76
- @modelAction
77
- set(key: string, value: V): this {
78
- setIfDifferent(this.items, key, value)
79
- return this
80
- }
81
-
82
- get size(): number {
83
- return keys(this.items).length
84
- }
85
-
86
- *keys(): ReturnType<Map<string, V>["keys"]> {
87
- for (const key of keys(this.items)) {
88
- yield key as string
89
- }
90
- }
91
-
92
- *values(): ReturnType<Map<string, V>["values"]> {
93
- for (const value of values(this.items)) {
94
- yield value
95
- }
96
- }
97
-
98
- *entries(): ReturnType<Map<string, V>["entries"]> {
99
- for (const entry of entries(this.items)) {
100
- yield entry
101
- }
102
- }
103
-
104
- [Symbol.iterator](): ReturnType<Map<string, V>[typeof Symbol.iterator]> {
105
- return this.entries()
106
- }
107
-
108
- readonly [Symbol.toStringTag] = "ObjectMap"
109
- }
110
-
111
- export interface ObjectMap<V> {
112
- readonly $: {
113
- items: Record<string, V>
114
- }
115
- readonly items: Record<string, V>
116
- }
117
-
118
- /**
119
- * Creates a new ObjectMap model instance.
120
- *
121
- * @template V Value type.
122
- * @param [entries] Optional initial values.
123
- */
124
- export function objectMap<V>(entries?: ReadonlyArray<readonly [string, V]> | null): ObjectMap<V> {
125
- const initialObj: Record<string, V> = {}
126
-
127
- if (entries) {
128
- const len = entries.length
129
- for (let i = 0; i < len; i++) {
130
- const entry = entries[i]
131
- initialObj[entry[0]] = entry[1]
132
- }
133
- }
134
-
135
- return new ObjectMap({ items: initialObj })
136
- }
1
+ import { entries, get, has, keys, remove, values } from "mobx"
2
+ import { modelAction } from "../action/modelAction"
3
+ import type { AnyModel } from "../model/BaseModel"
4
+ import { Model } from "../model/Model"
5
+ import { modelIdKey } from "../model/metadata"
6
+ import { model } from "../modelShared/modelDecorator"
7
+ import { idProp } from "../modelShared/prop"
8
+ import { typesRecord } from "../types/objectBased/typesRecord"
9
+ import { tProp } from "../types/tProp"
10
+ import { typesUnchecked } from "../types/utility/typesUnchecked"
11
+ import { namespace } from "../utils"
12
+ import { setIfDifferent } from "../utils/setIfDifferent"
13
+
14
+ const objectMapBase = Model({
15
+ [modelIdKey]: idProp,
16
+ items: tProp(typesRecord(typesUnchecked<any>()), () => ({})), // will be properly checked by types.objectMap(subType)
17
+ }) as abstract new (
18
+ data: any
19
+ ) => AnyModel & {
20
+ readonly $: {
21
+ items: Record<string, any>
22
+ }
23
+ readonly items: Record<string, any>
24
+ }
25
+
26
+ /**
27
+ * A map that is backed by an object-like map.
28
+ * Use `objectMap` to create it.
29
+ */
30
+ @model(`${namespace}/ObjectMap`)
31
+ // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
32
+ export class ObjectMap<V> extends objectMapBase implements Map<string, V> {
33
+ @modelAction
34
+ clear(): void {
35
+ const items = this.items
36
+
37
+ const keys = Object.keys(items)
38
+ const len = keys.length
39
+ for (let i = 0; i < len; i++) {
40
+ const k = keys[i]
41
+ remove(items, k)
42
+ }
43
+ }
44
+
45
+ @modelAction
46
+ delete(key: string): boolean {
47
+ const hasKey = this.has(key)
48
+ if (hasKey) {
49
+ remove(this.items, key)
50
+ return true
51
+ } else {
52
+ return false
53
+ }
54
+ }
55
+
56
+ forEach(callbackfn: (value: V, key: string, map: Map<string, V>) => void, thisArg?: any): void {
57
+ // we cannot use the map implementation since we need to pass this as map
58
+ const items = this.items
59
+
60
+ const keys = Object.keys(items)
61
+ const len = keys.length
62
+ for (let i = 0; i < len; i++) {
63
+ const k = keys[i]
64
+ callbackfn.call(thisArg, items[k], k, this)
65
+ }
66
+ }
67
+
68
+ get(key: string): V | undefined {
69
+ return get(this.items, key)
70
+ }
71
+
72
+ getOrInsert(key: string, defaultValue: V): V {
73
+ if (this.has(key)) {
74
+ return this.get(key) as V
75
+ }
76
+
77
+ this.set(key, defaultValue)
78
+ return defaultValue
79
+ }
80
+
81
+ getOrInsertComputed(key: string, callback: (key: string) => V): V {
82
+ if (this.has(key)) {
83
+ return this.get(key) as V
84
+ }
85
+
86
+ const value = callback(key)
87
+ this.set(key, value)
88
+ return value
89
+ }
90
+
91
+ has(key: string): boolean {
92
+ return has(this.items, key)
93
+ }
94
+
95
+ @modelAction
96
+ set(key: string, value: V): this {
97
+ setIfDifferent(this.items, key, value)
98
+ return this
99
+ }
100
+
101
+ get size(): number {
102
+ return keys(this.items).length
103
+ }
104
+
105
+ *keys(): ReturnType<Map<string, V>["keys"]> {
106
+ for (const key of keys(this.items)) {
107
+ yield key as string
108
+ }
109
+ }
110
+
111
+ *values(): ReturnType<Map<string, V>["values"]> {
112
+ for (const value of values(this.items)) {
113
+ yield value
114
+ }
115
+ }
116
+
117
+ *entries(): ReturnType<Map<string, V>["entries"]> {
118
+ for (const entry of entries(this.items)) {
119
+ yield entry
120
+ }
121
+ }
122
+
123
+ [Symbol.iterator](): ReturnType<Map<string, V>[typeof Symbol.iterator]> {
124
+ return this.entries()
125
+ }
126
+
127
+ readonly [Symbol.toStringTag] = "ObjectMap"
128
+ }
129
+
130
+ export interface ObjectMap<V> {
131
+ readonly $: {
132
+ items: Record<string, V>
133
+ }
134
+ readonly items: Record<string, V>
135
+ }
136
+
137
+ /**
138
+ * Creates a new ObjectMap model instance.
139
+ *
140
+ * @template V Value type.
141
+ * @param [entries] Optional initial values.
142
+ */
143
+ export function objectMap<V>(entries?: ReadonlyArray<readonly [string, V]> | null): ObjectMap<V> {
144
+ const initialObj: Record<string, V> = {}
145
+
146
+ if (entries) {
147
+ const len = entries.length
148
+ for (let i = 0; i < len; i++) {
149
+ const entry = entries[i]
150
+ initialObj[entry[0]] = entry[1]
151
+ }
152
+ }
153
+
154
+ return new ObjectMap({ items: initialObj })
155
+ }