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,27 +1,27 @@
1
- import { isoStringToDateTransform, timestampToDateTransform } from "../../transforms/date"
2
- import { TypeCheckerBaseType } from "../TypeChecker"
3
- import { createCodecType } from "./typesCodecCore"
4
-
5
- export const typesDateAsTimestamp = createCodecType(
6
- {
7
- typeName: "dateAsTimestamp",
8
- encodedType: Number,
9
- is(value): value is Date {
10
- return value instanceof Date
11
- },
12
- ...timestampToDateTransform(),
13
- },
14
- TypeCheckerBaseType.Object
15
- )
16
-
17
- export const typesDateAsIsoString = createCodecType(
18
- {
19
- typeName: "dateAsIsoString",
20
- encodedType: String,
21
- is(value): value is Date {
22
- return value instanceof Date
23
- },
24
- ...isoStringToDateTransform(),
25
- },
26
- TypeCheckerBaseType.Object
27
- )
1
+ import { isoStringToDateTransform, timestampToDateTransform } from "../../transforms/date"
2
+ import { TypeCheckerBaseType } from "../TypeChecker"
3
+ import { createCodecType } from "./typesCodecCore"
4
+
5
+ export const typesDateAsTimestamp = createCodecType(
6
+ {
7
+ typeName: "dateAsTimestamp",
8
+ encodedType: Number,
9
+ is(value): value is Date {
10
+ return value instanceof Date
11
+ },
12
+ ...timestampToDateTransform(),
13
+ },
14
+ TypeCheckerBaseType.Object
15
+ )
16
+
17
+ export const typesDateAsIsoString = createCodecType(
18
+ {
19
+ typeName: "dateAsIsoString",
20
+ encodedType: String,
21
+ is(value): value is Date {
22
+ return value instanceof Date
23
+ },
24
+ ...isoStringToDateTransform(),
25
+ },
26
+ TypeCheckerBaseType.Object
27
+ )
@@ -1,222 +1,253 @@
1
- import type { ModelPropTransform } from "../../modelShared/prop"
2
- import { isMap } from "../../utils"
3
- import { asMap } from "../../wrappers/asMap"
4
- import { typesArray } from "../arrayBased/typesArray"
5
- import { typesTuple } from "../arrayBased/typesTuple"
6
- import { typesRecord } from "../objectBased/typesRecord"
7
- import type { AnyType, ArrayType, RecordType, TypeToData } from "../schemas"
8
- import { TypeCheckerBaseType } from "../TypeChecker"
9
- import type { CodecFromEncoded, RuntimeAdapter } from "./typesCodecCore"
10
- import { createCodecType, identityRuntimeAdapter } from "./typesCodecCore"
11
- import { resolveCodecSupport } from "./typesCodecSupport"
12
-
13
- /**
14
- * Creates a Map proxy that adapts stored keys/values to runtime keys/values.
15
- * Shared by object-backed and array-backed map transforms.
16
- */
17
- function makeMapProxy<TKeyStored, TKeyRuntime, TValueStored, TValueRuntime>(
18
- storedMap: Map<TKeyStored, TValueStored>,
19
- keyAdapter: RuntimeAdapter<TKeyStored, TKeyRuntime>,
20
- valueAdapter: RuntimeAdapter<TValueStored, TValueRuntime>
21
- ): Map<TKeyRuntime, TValueRuntime> {
22
- return new Proxy(storedMap, {
23
- get(target, prop, receiver) {
24
- switch (prop) {
25
- case "get":
26
- return (key: TKeyRuntime) => {
27
- const storedKey = keyAdapter.toStored(key)
28
- if (!target.has(storedKey)) {
29
- return undefined
30
- }
31
-
32
- return valueAdapter.toRuntime(
33
- target.get(storedKey) as TValueStored,
34
- (newStoredValue) => {
35
- target.set(storedKey, newStoredValue)
36
- }
37
- )
38
- }
39
- case "set":
40
- return (key: TKeyRuntime, value: TValueRuntime) => {
41
- target.set(keyAdapter.toStored(key), valueAdapter.toStored(value))
42
- return receiver
43
- }
44
- case "has":
45
- return (key: TKeyRuntime) => target.has(keyAdapter.toStored(key))
46
- case "delete":
47
- return (key: TKeyRuntime) => target.delete(keyAdapter.toStored(key))
48
- case "clear":
49
- return () => target.clear()
50
- case "size":
51
- return target.size
52
- case "forEach":
53
- return (
54
- callback: (
55
- value: TValueRuntime,
56
- key: TKeyRuntime,
57
- map: Map<TKeyRuntime, TValueRuntime>
58
- ) => void,
59
- thisArg?: unknown
60
- ) => {
61
- target.forEach((value, key) => {
62
- callback.call(
63
- thisArg,
64
- valueAdapter.toRuntime(value, (newStoredValue) => {
65
- target.set(key, newStoredValue)
66
- }),
67
- keyAdapter.toRuntime(key),
68
- receiver
69
- )
70
- })
71
- }
72
- case "entries":
73
- case Symbol.iterator:
74
- return function* () {
75
- for (const [key, value] of target.entries()) {
76
- yield [
77
- keyAdapter.toRuntime(key),
78
- valueAdapter.toRuntime(value, (newStoredValue) => {
79
- target.set(key, newStoredValue)
80
- }),
81
- ] as const
82
- }
83
- }
84
- case "keys":
85
- return function* () {
86
- for (const key of target.keys()) {
87
- yield keyAdapter.toRuntime(key)
88
- }
89
- }
90
- case "values":
91
- return function* () {
92
- for (const [key, value] of target.entries()) {
93
- yield valueAdapter.toRuntime(value, (newStoredValue) => {
94
- target.set(key, newStoredValue)
95
- })
96
- }
97
- }
98
- default:
99
- return Reflect.get(target, prop, receiver)
100
- }
101
- },
102
- }) as unknown as Map<TKeyRuntime, TValueRuntime>
103
- }
104
-
105
- function makeObjectBackedMapTransform<TStoredValue, TRuntimeValue>(
106
- valueAdapter: RuntimeAdapter<TStoredValue, TRuntimeValue>
107
- ): ModelPropTransform<Record<string, TStoredValue>, Map<string, TRuntimeValue>> {
108
- const storedByRuntime = new WeakMap<Map<string, TRuntimeValue>, Record<string, TStoredValue>>()
109
-
110
- return {
111
- transform({ originalValue, cachedTransformedValue }) {
112
- if (cachedTransformedValue) {
113
- return cachedTransformedValue
114
- }
115
-
116
- const runtimeMap = makeMapProxy(asMap(originalValue), identityRuntimeAdapter, valueAdapter)
117
-
118
- storedByRuntime.set(runtimeMap, originalValue)
119
- return runtimeMap
120
- },
121
-
122
- untransform({ transformedValue }) {
123
- const cachedStored = storedByRuntime.get(transformedValue)
124
- if (cachedStored) {
125
- return cachedStored
126
- }
127
-
128
- const result: Record<string, TStoredValue> = {}
129
- transformedValue.forEach((value, key) => {
130
- result[key] = valueAdapter.toStored(value)
131
- })
132
- return result
133
- },
134
- }
135
- }
136
-
137
- function makeArrayBackedMapTransform<TKeyStored, TKeyRuntime, TValueStored, TValueRuntime>(
138
- keyAdapter: RuntimeAdapter<TKeyStored, TKeyRuntime>,
139
- valueAdapter: RuntimeAdapter<TValueStored, TValueRuntime>
140
- ): ModelPropTransform<Array<[TKeyStored, TValueStored]>, Map<TKeyRuntime, TValueRuntime>> {
141
- const storedByRuntime = new WeakMap<
142
- Map<TKeyRuntime, TValueRuntime>,
143
- Array<[TKeyStored, TValueStored]>
144
- >()
145
-
146
- return {
147
- transform({ originalValue, cachedTransformedValue }) {
148
- if (cachedTransformedValue) {
149
- return cachedTransformedValue
150
- }
151
-
152
- const runtimeMap = makeMapProxy(asMap(originalValue), keyAdapter, valueAdapter)
153
-
154
- storedByRuntime.set(runtimeMap, originalValue)
155
- return runtimeMap
156
- },
157
-
158
- untransform({ transformedValue }) {
159
- const cachedStored = storedByRuntime.get(transformedValue)
160
- if (cachedStored) {
161
- return cachedStored
162
- }
163
-
164
- const result: Array<[TKeyStored, TValueStored]> = []
165
- transformedValue.forEach((value, key) => {
166
- result.push([keyAdapter.toStored(key), valueAdapter.toStored(value)])
167
- })
168
- return result
169
- },
170
- }
171
- }
172
-
173
- export function typesMapFromObject<TValueType extends AnyType>(
174
- valueType: TValueType
175
- ): CodecFromEncoded<RecordType<TValueType>, Map<string, TypeToData<TValueType>>> {
176
- const valueSupport = resolveCodecSupport(valueType)
177
-
178
- return createCodecType(
179
- {
180
- typeName: "mapFromObject",
181
- encodedType: typesRecord(valueSupport.storedType),
182
- is(value): value is Map<string, TypeToData<TValueType>> {
183
- if (!isMap(value)) {
184
- return false
185
- }
186
-
187
- for (const key of value.keys()) {
188
- if (typeof key !== "string") {
189
- return false
190
- }
191
- }
192
-
193
- return true
194
- },
195
- ...makeObjectBackedMapTransform(valueSupport.adapter),
196
- },
197
- TypeCheckerBaseType.Object
198
- )
199
- }
200
-
201
- export function typesMapFromArray<TKeyType extends AnyType, TValueType extends AnyType>(
202
- keyType: TKeyType,
203
- valueType: TValueType
204
- ): CodecFromEncoded<
205
- ArrayType<ArrayType<[TKeyType, TValueType]>[]>,
206
- Map<TypeToData<TKeyType>, TypeToData<TValueType>>
207
- > {
208
- const keySupport = resolveCodecSupport(keyType)
209
- const valueSupport = resolveCodecSupport(valueType)
210
-
211
- return createCodecType(
212
- {
213
- typeName: "mapFromArray",
214
- encodedType: typesArray(typesTuple(keySupport.storedType, valueSupport.storedType)),
215
- is(value): value is Map<TypeToData<TKeyType>, TypeToData<TValueType>> {
216
- return isMap(value)
217
- },
218
- ...makeArrayBackedMapTransform(keySupport.adapter, valueSupport.adapter),
219
- },
220
- TypeCheckerBaseType.Object
221
- )
222
- }
1
+ import type { ModelPropTransform } from "../../modelShared/prop"
2
+ import { isMap } from "../../utils"
3
+ import { asMap } from "../../wrappers/asMap"
4
+ import { typesArray } from "../arrayBased/typesArray"
5
+ import { typesTuple } from "../arrayBased/typesTuple"
6
+ import { typesRecord } from "../objectBased/typesRecord"
7
+ import type { AnyType, ArrayType, RecordType, TypeToData } from "../schemas"
8
+ import { TypeCheckerBaseType } from "../TypeChecker"
9
+ import type { CodecFromEncoded, RuntimeAdapter } from "./typesCodecCore"
10
+ import { createCodecType, identityRuntimeAdapter } from "./typesCodecCore"
11
+ import { resolveCodecSupport } from "./typesCodecSupport"
12
+
13
+ /**
14
+ * Creates a Map proxy that adapts stored keys/values to runtime keys/values.
15
+ * Shared by object-backed and array-backed map transforms.
16
+ */
17
+ function makeMapProxy<TKeyStored, TKeyRuntime, TValueStored, TValueRuntime>(
18
+ storedMap: Map<TKeyStored, TValueStored>,
19
+ keyAdapter: RuntimeAdapter<TKeyStored, TKeyRuntime>,
20
+ valueAdapter: RuntimeAdapter<TValueStored, TValueRuntime>
21
+ ): Map<TKeyRuntime, TValueRuntime> {
22
+ return new Proxy(storedMap, {
23
+ get(target, prop, receiver) {
24
+ switch (prop) {
25
+ case "get":
26
+ return (key: TKeyRuntime) => {
27
+ const storedKey = keyAdapter.toStored(key)
28
+ if (!target.has(storedKey)) {
29
+ return undefined
30
+ }
31
+
32
+ return valueAdapter.toRuntime(
33
+ target.get(storedKey) as TValueStored,
34
+ (newStoredValue) => {
35
+ target.set(storedKey, newStoredValue)
36
+ }
37
+ )
38
+ }
39
+ case "getOrInsert":
40
+ return (key: TKeyRuntime, defaultValue: TValueRuntime) => {
41
+ const storedKey = keyAdapter.toStored(key)
42
+ if (target.has(storedKey)) {
43
+ return valueAdapter.toRuntime(
44
+ target.get(storedKey) as TValueStored,
45
+ (newStoredValue) => {
46
+ target.set(storedKey, newStoredValue)
47
+ }
48
+ )
49
+ }
50
+
51
+ target.set(storedKey, valueAdapter.toStored(defaultValue))
52
+ return defaultValue
53
+ }
54
+ case "getOrInsertComputed":
55
+ return (key: TKeyRuntime, callback: (key: TKeyRuntime) => TValueRuntime) => {
56
+ const storedKey = keyAdapter.toStored(key)
57
+ if (target.has(storedKey)) {
58
+ return valueAdapter.toRuntime(
59
+ target.get(storedKey) as TValueStored,
60
+ (newStoredValue) => {
61
+ target.set(storedKey, newStoredValue)
62
+ }
63
+ )
64
+ }
65
+
66
+ const value = callback(key)
67
+ target.set(storedKey, valueAdapter.toStored(value))
68
+ return value
69
+ }
70
+ case "set":
71
+ return (key: TKeyRuntime, value: TValueRuntime) => {
72
+ target.set(keyAdapter.toStored(key), valueAdapter.toStored(value))
73
+ return receiver
74
+ }
75
+ case "has":
76
+ return (key: TKeyRuntime) => target.has(keyAdapter.toStored(key))
77
+ case "delete":
78
+ return (key: TKeyRuntime) => target.delete(keyAdapter.toStored(key))
79
+ case "clear":
80
+ return () => target.clear()
81
+ case "size":
82
+ return target.size
83
+ case "forEach":
84
+ return (
85
+ callback: (
86
+ value: TValueRuntime,
87
+ key: TKeyRuntime,
88
+ map: Map<TKeyRuntime, TValueRuntime>
89
+ ) => void,
90
+ thisArg?: unknown
91
+ ) => {
92
+ target.forEach((value, key) => {
93
+ callback.call(
94
+ thisArg,
95
+ valueAdapter.toRuntime(value, (newStoredValue) => {
96
+ target.set(key, newStoredValue)
97
+ }),
98
+ keyAdapter.toRuntime(key),
99
+ receiver
100
+ )
101
+ })
102
+ }
103
+ case "entries":
104
+ case Symbol.iterator:
105
+ return function* () {
106
+ for (const [key, value] of target.entries()) {
107
+ yield [
108
+ keyAdapter.toRuntime(key),
109
+ valueAdapter.toRuntime(value, (newStoredValue) => {
110
+ target.set(key, newStoredValue)
111
+ }),
112
+ ] as const
113
+ }
114
+ }
115
+ case "keys":
116
+ return function* () {
117
+ for (const key of target.keys()) {
118
+ yield keyAdapter.toRuntime(key)
119
+ }
120
+ }
121
+ case "values":
122
+ return function* () {
123
+ for (const [key, value] of target.entries()) {
124
+ yield valueAdapter.toRuntime(value, (newStoredValue) => {
125
+ target.set(key, newStoredValue)
126
+ })
127
+ }
128
+ }
129
+ default:
130
+ return Reflect.get(target, prop, receiver)
131
+ }
132
+ },
133
+ }) as unknown as Map<TKeyRuntime, TValueRuntime>
134
+ }
135
+
136
+ function makeObjectBackedMapTransform<TStoredValue, TRuntimeValue>(
137
+ valueAdapter: RuntimeAdapter<TStoredValue, TRuntimeValue>
138
+ ): ModelPropTransform<Record<string, TStoredValue>, Map<string, TRuntimeValue>> {
139
+ const storedByRuntime = new WeakMap<Map<string, TRuntimeValue>, Record<string, TStoredValue>>()
140
+
141
+ return {
142
+ transform({ originalValue, cachedTransformedValue }) {
143
+ if (cachedTransformedValue) {
144
+ return cachedTransformedValue
145
+ }
146
+
147
+ const runtimeMap = makeMapProxy(asMap(originalValue), identityRuntimeAdapter, valueAdapter)
148
+
149
+ storedByRuntime.set(runtimeMap, originalValue)
150
+ return runtimeMap
151
+ },
152
+
153
+ untransform({ transformedValue }) {
154
+ const cachedStored = storedByRuntime.get(transformedValue)
155
+ if (cachedStored) {
156
+ return cachedStored
157
+ }
158
+
159
+ const result: Record<string, TStoredValue> = {}
160
+ transformedValue.forEach((value, key) => {
161
+ result[key] = valueAdapter.toStored(value)
162
+ })
163
+ return result
164
+ },
165
+ }
166
+ }
167
+
168
+ function makeArrayBackedMapTransform<TKeyStored, TKeyRuntime, TValueStored, TValueRuntime>(
169
+ keyAdapter: RuntimeAdapter<TKeyStored, TKeyRuntime>,
170
+ valueAdapter: RuntimeAdapter<TValueStored, TValueRuntime>
171
+ ): ModelPropTransform<Array<[TKeyStored, TValueStored]>, Map<TKeyRuntime, TValueRuntime>> {
172
+ const storedByRuntime = new WeakMap<
173
+ Map<TKeyRuntime, TValueRuntime>,
174
+ Array<[TKeyStored, TValueStored]>
175
+ >()
176
+
177
+ return {
178
+ transform({ originalValue, cachedTransformedValue }) {
179
+ if (cachedTransformedValue) {
180
+ return cachedTransformedValue
181
+ }
182
+
183
+ const runtimeMap = makeMapProxy(asMap(originalValue), keyAdapter, valueAdapter)
184
+
185
+ storedByRuntime.set(runtimeMap, originalValue)
186
+ return runtimeMap
187
+ },
188
+
189
+ untransform({ transformedValue }) {
190
+ const cachedStored = storedByRuntime.get(transformedValue)
191
+ if (cachedStored) {
192
+ return cachedStored
193
+ }
194
+
195
+ const result: Array<[TKeyStored, TValueStored]> = []
196
+ transformedValue.forEach((value, key) => {
197
+ result.push([keyAdapter.toStored(key), valueAdapter.toStored(value)])
198
+ })
199
+ return result
200
+ },
201
+ }
202
+ }
203
+
204
+ export function typesMapFromObject<TValueType extends AnyType>(
205
+ valueType: TValueType
206
+ ): CodecFromEncoded<RecordType<TValueType>, Map<string, TypeToData<TValueType>>> {
207
+ const valueSupport = resolveCodecSupport(valueType)
208
+
209
+ return createCodecType(
210
+ {
211
+ typeName: "mapFromObject",
212
+ encodedType: typesRecord(valueSupport.storedType),
213
+ is(value): value is Map<string, TypeToData<TValueType>> {
214
+ if (!isMap(value)) {
215
+ return false
216
+ }
217
+
218
+ for (const key of value.keys()) {
219
+ if (typeof key !== "string") {
220
+ return false
221
+ }
222
+ }
223
+
224
+ return true
225
+ },
226
+ ...makeObjectBackedMapTransform(valueSupport.adapter),
227
+ },
228
+ TypeCheckerBaseType.Object
229
+ )
230
+ }
231
+
232
+ export function typesMapFromArray<TKeyType extends AnyType, TValueType extends AnyType>(
233
+ keyType: TKeyType,
234
+ valueType: TValueType
235
+ ): CodecFromEncoded<
236
+ ArrayType<ArrayType<[TKeyType, TValueType]>[]>,
237
+ Map<TypeToData<TKeyType>, TypeToData<TValueType>>
238
+ > {
239
+ const keySupport = resolveCodecSupport(keyType)
240
+ const valueSupport = resolveCodecSupport(valueType)
241
+
242
+ return createCodecType(
243
+ {
244
+ typeName: "mapFromArray",
245
+ encodedType: typesArray(typesTuple(keySupport.storedType, valueSupport.storedType)),
246
+ is(value): value is Map<TypeToData<TKeyType>, TypeToData<TValueType>> {
247
+ return isMap(value)
248
+ },
249
+ ...makeArrayBackedMapTransform(keySupport.adapter, valueSupport.adapter),
250
+ },
251
+ TypeCheckerBaseType.Object
252
+ )
253
+ }