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
|
@@ -1,143 +1,142 @@
|
|
|
1
|
-
import { modelTypeKey } from "../../model/metadata"
|
|
2
|
-
import { modelInfoByClass } from "../../modelShared/modelInfo"
|
|
3
|
-
import { isObject } from "../../utils"
|
|
4
|
-
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
5
|
-
import { ObjectMap } from "../../wrappers/ObjectMap"
|
|
6
|
-
import { getTypeInfo } from "../getTypeInfo"
|
|
7
|
-
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
8
|
-
import type { AnyStandardType, AnyType, ModelType, TypeToData } from "../schemas"
|
|
9
|
-
import { TypeCheckError } from "../TypeCheckError"
|
|
10
|
-
import {
|
|
11
|
-
lateTypeChecker,
|
|
12
|
-
TypeChecker,
|
|
13
|
-
TypeCheckerBaseType,
|
|
14
|
-
TypeInfo,
|
|
15
|
-
TypeInfoGen,
|
|
16
|
-
} from "../TypeChecker"
|
|
17
|
-
import { resolveCodecSupport } from "../utility/typesCodec"
|
|
18
|
-
import { typesObject } from "./typesObject"
|
|
19
|
-
import { typesRecord } from "./typesRecord"
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A type that represents an object-like map ObjectMap.
|
|
23
|
-
*
|
|
24
|
-
* Example:
|
|
25
|
-
* ```ts
|
|
26
|
-
* const numberMapType = types.objectMap(types.number)
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @template T Value type.
|
|
30
|
-
* @param valueType Value type.
|
|
31
|
-
* @returns
|
|
32
|
-
*/
|
|
33
|
-
export function typesObjectMap<T extends AnyType>(
|
|
34
|
-
valueType: T
|
|
35
|
-
): ModelType<ObjectMap<TypeToData<T>>> {
|
|
36
|
-
const typeInfoGen: TypeInfoGen = (t) => new ObjectMapTypeInfo(t, resolveStandardType(valueType))
|
|
37
|
-
|
|
38
|
-
return lateTypeChecker(() => {
|
|
39
|
-
const modelInfo = modelInfoByClass.get(ObjectMap)!
|
|
40
|
-
|
|
41
|
-
const valueChecker = resolveTypeChecker(valueType)
|
|
42
|
-
const valueSupport = resolveCodecSupport(valueType)
|
|
43
|
-
const storedValueChecker = resolveTypeChecker(valueSupport.storedType)
|
|
44
|
-
|
|
45
|
-
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
46
|
-
`ObjectMap<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
47
|
-
|
|
48
|
-
const dataTypeChecker = typesObject(() => ({
|
|
49
|
-
items: typesRecord(valueSupport.storedType as any),
|
|
50
|
-
}))
|
|
51
|
-
const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker)
|
|
52
|
-
|
|
53
|
-
const thisTc: TypeChecker = new TypeChecker(
|
|
54
|
-
TypeCheckerBaseType.Object,
|
|
55
|
-
|
|
56
|
-
(obj, path, typeCheckedValue) => {
|
|
57
|
-
if (!(obj instanceof ObjectMap)) {
|
|
58
|
-
return new TypeCheckError({
|
|
59
|
-
path,
|
|
60
|
-
expectedTypeName: getTypeName(thisTc),
|
|
61
|
-
actualValue: obj,
|
|
62
|
-
typeCheckedValue,
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return resolvedDataTypeChecker.check(obj.$, path, typeCheckedValue)
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
getTypeName,
|
|
70
|
-
typeInfoGen,
|
|
71
|
-
|
|
72
|
-
(obj) => {
|
|
73
|
-
if (!isObject(obj)) {
|
|
74
|
-
return null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (obj[modelTypeKey] !== undefined) {
|
|
78
|
-
// fast check
|
|
79
|
-
return obj[modelTypeKey] === modelInfo.name ? thisTc : null
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
return resolvedDataTypeChecker.snapshotType(obj) ? thisTc : null
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
(sn: { items: Record<string, unknown> }) => {
|
|
86
|
-
const newItems: (typeof sn)["items"] = {}
|
|
87
|
-
|
|
88
|
-
withErrorPathSegment("items", () => {
|
|
89
|
-
for (const k of Object.keys(sn.items)) {
|
|
90
|
-
newItems[k] = withErrorPathSegment(k, () =>
|
|
91
|
-
storedValueChecker.fromSnapshotProcessor(sn.items[k])
|
|
92
|
-
)
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
...sn,
|
|
98
|
-
[modelTypeKey]: modelInfo.name,
|
|
99
|
-
items: newItems,
|
|
100
|
-
}
|
|
101
|
-
},
|
|
102
|
-
|
|
103
|
-
(sn: { items: Record<string, unknown>; [modelTypeKey]?: string }) => {
|
|
104
|
-
const newItems: (typeof sn)["items"] = {}
|
|
105
|
-
|
|
106
|
-
withErrorPathSegment("items", () => {
|
|
107
|
-
for (const k of Object.keys(sn.items)) {
|
|
108
|
-
newItems[k] = withErrorPathSegment(k, () =>
|
|
109
|
-
storedValueChecker.toSnapshotProcessor(sn.items[k])
|
|
110
|
-
)
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
const snCopy = {
|
|
115
|
-
...sn,
|
|
116
|
-
items: newItems,
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return snCopy
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
return thisTc
|
|
124
|
-
}, typeInfoGen) as any
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* `types.objectMap` type info.
|
|
129
|
-
*/
|
|
130
|
-
export class ObjectMapTypeInfo extends TypeInfo {
|
|
131
|
-
readonly kind = "objectMap"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
1
|
+
import { modelTypeKey } from "../../model/metadata"
|
|
2
|
+
import { modelInfoByClass } from "../../modelShared/modelInfo"
|
|
3
|
+
import { isObject } from "../../utils"
|
|
4
|
+
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
5
|
+
import { ObjectMap } from "../../wrappers/ObjectMap"
|
|
6
|
+
import { getTypeInfo } from "../getTypeInfo"
|
|
7
|
+
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
8
|
+
import type { AnyStandardType, AnyType, ModelType, TypeToData } from "../schemas"
|
|
9
|
+
import { TypeCheckError } from "../TypeCheckError"
|
|
10
|
+
import {
|
|
11
|
+
lateTypeChecker,
|
|
12
|
+
TypeChecker,
|
|
13
|
+
TypeCheckerBaseType,
|
|
14
|
+
TypeInfo,
|
|
15
|
+
type TypeInfoGen,
|
|
16
|
+
} from "../TypeChecker"
|
|
17
|
+
import { resolveCodecSupport } from "../utility/typesCodec"
|
|
18
|
+
import { typesObject } from "./typesObject"
|
|
19
|
+
import { typesRecord } from "./typesRecord"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A type that represents an object-like map ObjectMap.
|
|
23
|
+
*
|
|
24
|
+
* Example:
|
|
25
|
+
* ```ts
|
|
26
|
+
* const numberMapType = types.objectMap(types.number)
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @template T Value type.
|
|
30
|
+
* @param valueType Value type.
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
export function typesObjectMap<T extends AnyType>(
|
|
34
|
+
valueType: T
|
|
35
|
+
): ModelType<ObjectMap<TypeToData<T>>> {
|
|
36
|
+
const typeInfoGen: TypeInfoGen = (t) => new ObjectMapTypeInfo(t, resolveStandardType(valueType))
|
|
37
|
+
|
|
38
|
+
return lateTypeChecker(() => {
|
|
39
|
+
const modelInfo = modelInfoByClass.get(ObjectMap)!
|
|
40
|
+
|
|
41
|
+
const valueChecker = resolveTypeChecker(valueType)
|
|
42
|
+
const valueSupport = resolveCodecSupport(valueType)
|
|
43
|
+
const storedValueChecker = resolveTypeChecker(valueSupport.storedType)
|
|
44
|
+
|
|
45
|
+
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
46
|
+
`ObjectMap<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
47
|
+
|
|
48
|
+
const dataTypeChecker = typesObject(() => ({
|
|
49
|
+
items: typesRecord(valueSupport.storedType as any),
|
|
50
|
+
}))
|
|
51
|
+
const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker)
|
|
52
|
+
|
|
53
|
+
const thisTc: TypeChecker = new TypeChecker(
|
|
54
|
+
TypeCheckerBaseType.Object,
|
|
55
|
+
|
|
56
|
+
(obj, path, typeCheckedValue) => {
|
|
57
|
+
if (!(obj instanceof ObjectMap)) {
|
|
58
|
+
return new TypeCheckError({
|
|
59
|
+
path,
|
|
60
|
+
expectedTypeName: getTypeName(thisTc),
|
|
61
|
+
actualValue: obj,
|
|
62
|
+
typeCheckedValue,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return resolvedDataTypeChecker.check(obj.$, path, typeCheckedValue)
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
getTypeName,
|
|
70
|
+
typeInfoGen,
|
|
71
|
+
|
|
72
|
+
(obj) => {
|
|
73
|
+
if (!isObject(obj)) {
|
|
74
|
+
return null
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (obj[modelTypeKey] !== undefined) {
|
|
78
|
+
// fast check
|
|
79
|
+
return obj[modelTypeKey] === modelInfo.name ? thisTc : null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return resolvedDataTypeChecker.snapshotType(obj) ? thisTc : null
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
(sn: { items: Record<string, unknown> }) => {
|
|
86
|
+
const newItems: (typeof sn)["items"] = {}
|
|
87
|
+
|
|
88
|
+
withErrorPathSegment("items", () => {
|
|
89
|
+
for (const k of Object.keys(sn.items)) {
|
|
90
|
+
newItems[k] = withErrorPathSegment(k, () =>
|
|
91
|
+
storedValueChecker.fromSnapshotProcessor(sn.items[k])
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
...sn,
|
|
98
|
+
[modelTypeKey]: modelInfo.name,
|
|
99
|
+
items: newItems,
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
(sn: { items: Record<string, unknown>; [modelTypeKey]?: string }) => {
|
|
104
|
+
const newItems: (typeof sn)["items"] = {}
|
|
105
|
+
|
|
106
|
+
withErrorPathSegment("items", () => {
|
|
107
|
+
for (const k of Object.keys(sn.items)) {
|
|
108
|
+
newItems[k] = withErrorPathSegment(k, () =>
|
|
109
|
+
storedValueChecker.toSnapshotProcessor(sn.items[k])
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const snCopy = {
|
|
115
|
+
...sn,
|
|
116
|
+
items: newItems,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return snCopy
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
return thisTc
|
|
124
|
+
}, typeInfoGen) as any
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* `types.objectMap` type info.
|
|
129
|
+
*/
|
|
130
|
+
export class ObjectMapTypeInfo extends TypeInfo {
|
|
131
|
+
readonly kind = "objectMap"
|
|
132
|
+
readonly valueType: AnyStandardType
|
|
133
|
+
|
|
134
|
+
get valueTypeInfo(): TypeInfo {
|
|
135
|
+
return getTypeInfo(this.valueType)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
constructor(thisType: AnyStandardType, valueType: AnyStandardType) {
|
|
139
|
+
super(thisType)
|
|
140
|
+
this.valueType = valueType
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -1,157 +1,156 @@
|
|
|
1
|
-
import { isObservableObject, keys } from "mobx"
|
|
2
|
-
import type { Path } from "../../parent/pathTypes"
|
|
3
|
-
import { failure, isObject } from "../../utils"
|
|
4
|
-
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
5
|
-
import { createPerEntryCachedCheck, recordCachePruning } from "../createPerEntryCachedCheck"
|
|
6
|
-
import { getTypeInfo } from "../getTypeInfo"
|
|
7
|
-
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
8
|
-
import type { AnyStandardType, AnyType, RecordType } from "../schemas"
|
|
9
|
-
import { TypeCheckError } from "../TypeCheckError"
|
|
10
|
-
import {
|
|
11
|
-
lateTypeChecker,
|
|
12
|
-
TypeChecker,
|
|
13
|
-
TypeCheckerBaseType,
|
|
14
|
-
TypeInfo,
|
|
15
|
-
TypeInfoGen,
|
|
16
|
-
} from "../TypeChecker"
|
|
17
|
-
import { prependPathElementToTypeCheckError } from "../typeCheckErrorUtils"
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A type that represents an object-like map, an object with string keys and values all of a same given type.
|
|
21
|
-
*
|
|
22
|
-
* Example:
|
|
23
|
-
* ```ts
|
|
24
|
-
* // { [k: string]: number }
|
|
25
|
-
* const numberMapType = types.record(types.number)
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* @template T Type.
|
|
29
|
-
* @param valueType Type of the values of the object-like map.
|
|
30
|
-
* @returns
|
|
31
|
-
*/
|
|
32
|
-
export function typesRecord<T extends AnyType>(valueType: T): RecordType<T> {
|
|
33
|
-
const typeInfoGen: TypeInfoGen = (tc) => new RecordTypeInfo(tc, resolveStandardType(valueType))
|
|
34
|
-
|
|
35
|
-
return lateTypeChecker(() => {
|
|
36
|
-
const valueChecker = resolveTypeChecker(valueType)
|
|
37
|
-
const emptyChildPath: Path = []
|
|
38
|
-
|
|
39
|
-
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
40
|
-
`Record<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
41
|
-
|
|
42
|
-
const applySnapshotProcessor = (obj: Record<string, unknown>, mode: "from" | "to") => {
|
|
43
|
-
if (valueChecker.unchecked) {
|
|
44
|
-
return obj
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const newObj: typeof obj = {}
|
|
48
|
-
|
|
49
|
-
const keys = Object.keys(obj)
|
|
50
|
-
for (let i = 0; i < keys.length; i++) {
|
|
51
|
-
const k = keys[i]
|
|
52
|
-
const v = withErrorPathSegment(k, () =>
|
|
53
|
-
mode === "from"
|
|
54
|
-
? valueChecker.fromSnapshotProcessor(obj[k])
|
|
55
|
-
: valueChecker.toSnapshotProcessor(obj[k])
|
|
56
|
-
)
|
|
57
|
-
newObj[k] = v
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return newObj
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const checkRecordValues = createPerEntryCachedCheck(
|
|
64
|
-
(obj, checkEntry) => {
|
|
65
|
-
// Use keys() from MobX for observable objects to track key additions/removals
|
|
66
|
-
// in MobX 4 (which lacks Proxy). Object.keys() doesn't establish MobX tracking
|
|
67
|
-
// in MobX 4, so the aggregation computed would miss newly added keys.
|
|
68
|
-
const objKeys = isObservableObject(obj) ? keys(obj) : Object.keys(obj)
|
|
69
|
-
for (let i = 0; i < objKeys.length; i++) {
|
|
70
|
-
const error = checkEntry(objKeys[i])
|
|
71
|
-
if (error) return error
|
|
72
|
-
}
|
|
73
|
-
return null
|
|
74
|
-
},
|
|
75
|
-
(obj, key, path, typeCheckedValue) => {
|
|
76
|
-
if (typeof key !== "string") {
|
|
77
|
-
throw failure(`record type keys must be strings, got ${typeof key}`)
|
|
78
|
-
}
|
|
79
|
-
const error = valueChecker.check(obj[key], emptyChildPath, typeCheckedValue)
|
|
80
|
-
return error ? prependPathElementToTypeCheckError(error, path, key, typeCheckedValue) : null
|
|
81
|
-
},
|
|
82
|
-
recordCachePruning
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
const thisTc: TypeChecker = new TypeChecker(
|
|
86
|
-
TypeCheckerBaseType.Object,
|
|
87
|
-
|
|
88
|
-
(obj, path, typeCheckedValue) => {
|
|
89
|
-
if (!isObject(obj)) {
|
|
90
|
-
return new TypeCheckError({
|
|
91
|
-
path,
|
|
92
|
-
expectedTypeName: getTypeName(thisTc),
|
|
93
|
-
actualValue: obj,
|
|
94
|
-
typeCheckedValue,
|
|
95
|
-
})
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (valueChecker.unchecked || valueChecker.skipCheck) {
|
|
99
|
-
return null
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return checkRecordValues(obj, path, typeCheckedValue)
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
getTypeName,
|
|
106
|
-
typeInfoGen,
|
|
107
|
-
|
|
108
|
-
(obj) => {
|
|
109
|
-
if (!isObject(obj)) {
|
|
110
|
-
return null
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
if (!valueChecker.unchecked) {
|
|
114
|
-
const keys = Object.keys(obj)
|
|
115
|
-
for (let i = 0; i < keys.length; i++) {
|
|
116
|
-
const k = keys[i]
|
|
117
|
-
const v = obj[k]
|
|
118
|
-
const valueActualChecker = valueChecker.snapshotType(v)
|
|
119
|
-
if (!valueActualChecker) {
|
|
120
|
-
return null
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return thisTc
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
(obj: Record<string, unknown>) => {
|
|
129
|
-
return applySnapshotProcessor(obj, "from")
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
(obj: Record<string, unknown>) => {
|
|
133
|
-
return applySnapshotProcessor(obj, "to")
|
|
134
|
-
}
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
return thisTc
|
|
138
|
-
}, typeInfoGen) as any
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* `types.record` type info.
|
|
143
|
-
*/
|
|
144
|
-
export class RecordTypeInfo extends TypeInfo {
|
|
145
|
-
readonly kind = "record"
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
1
|
+
import { isObservableObject, keys } from "mobx"
|
|
2
|
+
import type { Path } from "../../parent/pathTypes"
|
|
3
|
+
import { failure, isObject } from "../../utils"
|
|
4
|
+
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
5
|
+
import { createPerEntryCachedCheck, recordCachePruning } from "../createPerEntryCachedCheck"
|
|
6
|
+
import { getTypeInfo } from "../getTypeInfo"
|
|
7
|
+
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
8
|
+
import type { AnyStandardType, AnyType, RecordType } from "../schemas"
|
|
9
|
+
import { TypeCheckError } from "../TypeCheckError"
|
|
10
|
+
import {
|
|
11
|
+
lateTypeChecker,
|
|
12
|
+
TypeChecker,
|
|
13
|
+
TypeCheckerBaseType,
|
|
14
|
+
TypeInfo,
|
|
15
|
+
type TypeInfoGen,
|
|
16
|
+
} from "../TypeChecker"
|
|
17
|
+
import { prependPathElementToTypeCheckError } from "../typeCheckErrorUtils"
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A type that represents an object-like map, an object with string keys and values all of a same given type.
|
|
21
|
+
*
|
|
22
|
+
* Example:
|
|
23
|
+
* ```ts
|
|
24
|
+
* // { [k: string]: number }
|
|
25
|
+
* const numberMapType = types.record(types.number)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @template T Type.
|
|
29
|
+
* @param valueType Type of the values of the object-like map.
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
export function typesRecord<T extends AnyType>(valueType: T): RecordType<T> {
|
|
33
|
+
const typeInfoGen: TypeInfoGen = (tc) => new RecordTypeInfo(tc, resolveStandardType(valueType))
|
|
34
|
+
|
|
35
|
+
return lateTypeChecker(() => {
|
|
36
|
+
const valueChecker = resolveTypeChecker(valueType)
|
|
37
|
+
const emptyChildPath: Path = []
|
|
38
|
+
|
|
39
|
+
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
40
|
+
`Record<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
41
|
+
|
|
42
|
+
const applySnapshotProcessor = (obj: Record<string, unknown>, mode: "from" | "to") => {
|
|
43
|
+
if (valueChecker.unchecked) {
|
|
44
|
+
return obj
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const newObj: typeof obj = {}
|
|
48
|
+
|
|
49
|
+
const keys = Object.keys(obj)
|
|
50
|
+
for (let i = 0; i < keys.length; i++) {
|
|
51
|
+
const k = keys[i]
|
|
52
|
+
const v = withErrorPathSegment(k, () =>
|
|
53
|
+
mode === "from"
|
|
54
|
+
? valueChecker.fromSnapshotProcessor(obj[k])
|
|
55
|
+
: valueChecker.toSnapshotProcessor(obj[k])
|
|
56
|
+
)
|
|
57
|
+
newObj[k] = v
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return newObj
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const checkRecordValues = createPerEntryCachedCheck(
|
|
64
|
+
(obj, checkEntry) => {
|
|
65
|
+
// Use keys() from MobX for observable objects to track key additions/removals
|
|
66
|
+
// in MobX 4 (which lacks Proxy). Object.keys() doesn't establish MobX tracking
|
|
67
|
+
// in MobX 4, so the aggregation computed would miss newly added keys.
|
|
68
|
+
const objKeys = isObservableObject(obj) ? keys(obj) : Object.keys(obj)
|
|
69
|
+
for (let i = 0; i < objKeys.length; i++) {
|
|
70
|
+
const error = checkEntry(objKeys[i])
|
|
71
|
+
if (error) return error
|
|
72
|
+
}
|
|
73
|
+
return null
|
|
74
|
+
},
|
|
75
|
+
(obj, key, path, typeCheckedValue) => {
|
|
76
|
+
if (typeof key !== "string") {
|
|
77
|
+
throw failure(`record type keys must be strings, got ${typeof key}`)
|
|
78
|
+
}
|
|
79
|
+
const error = valueChecker.check(obj[key], emptyChildPath, typeCheckedValue)
|
|
80
|
+
return error ? prependPathElementToTypeCheckError(error, path, key, typeCheckedValue) : null
|
|
81
|
+
},
|
|
82
|
+
recordCachePruning
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
const thisTc: TypeChecker = new TypeChecker(
|
|
86
|
+
TypeCheckerBaseType.Object,
|
|
87
|
+
|
|
88
|
+
(obj, path, typeCheckedValue) => {
|
|
89
|
+
if (!isObject(obj)) {
|
|
90
|
+
return new TypeCheckError({
|
|
91
|
+
path,
|
|
92
|
+
expectedTypeName: getTypeName(thisTc),
|
|
93
|
+
actualValue: obj,
|
|
94
|
+
typeCheckedValue,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (valueChecker.unchecked || valueChecker.skipCheck) {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return checkRecordValues(obj, path, typeCheckedValue)
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
getTypeName,
|
|
106
|
+
typeInfoGen,
|
|
107
|
+
|
|
108
|
+
(obj) => {
|
|
109
|
+
if (!isObject(obj)) {
|
|
110
|
+
return null
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!valueChecker.unchecked) {
|
|
114
|
+
const keys = Object.keys(obj)
|
|
115
|
+
for (let i = 0; i < keys.length; i++) {
|
|
116
|
+
const k = keys[i]
|
|
117
|
+
const v = obj[k]
|
|
118
|
+
const valueActualChecker = valueChecker.snapshotType(v)
|
|
119
|
+
if (!valueActualChecker) {
|
|
120
|
+
return null
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return thisTc
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
(obj: Record<string, unknown>) => {
|
|
129
|
+
return applySnapshotProcessor(obj, "from")
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
(obj: Record<string, unknown>) => {
|
|
133
|
+
return applySnapshotProcessor(obj, "to")
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return thisTc
|
|
138
|
+
}, typeInfoGen) as any
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* `types.record` type info.
|
|
143
|
+
*/
|
|
144
|
+
export class RecordTypeInfo extends TypeInfo {
|
|
145
|
+
readonly kind = "record"
|
|
146
|
+
readonly valueType: AnyStandardType
|
|
147
|
+
|
|
148
|
+
get valueTypeInfo(): TypeInfo {
|
|
149
|
+
return getTypeInfo(this.valueType)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
constructor(thisType: AnyStandardType, valueType: AnyStandardType) {
|
|
153
|
+
super(thisType)
|
|
154
|
+
this.valueType = valueType
|
|
155
|
+
}
|
|
156
|
+
}
|