mobx-keystone 1.20.0 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +864 -853
- package/README.md +61 -61
- package/dist/mobx-keystone.esm.js +11336 -11148
- package/dist/mobx-keystone.esm.mjs +11336 -11148
- package/dist/mobx-keystone.umd.js +12229 -11738
- package/dist/types/actionMiddlewares/undoMiddleware.d.ts +1 -1
- package/dist/types/modelShared/prop.d.ts +5 -0
- package/dist/types/redux/connectReduxDevTools.d.ts +17 -4
- package/dist/types/ref/Ref.d.ts +1 -1
- package/dist/types/treeUtils/sandbox.d.ts +1 -1
- package/dist/types/types/TypeChecker.d.ts +1 -1
- package/dist/types/types/arrayBased/typesArray.d.ts +1 -1
- package/dist/types/types/arrayBased/typesTuple.d.ts +1 -1
- package/dist/types/types/objectBased/typesArraySet.d.ts +1 -1
- package/dist/types/types/objectBased/typesDataModelData.d.ts +1 -1
- package/dist/types/types/objectBased/typesModel.d.ts +1 -1
- package/dist/types/types/objectBased/typesObject.d.ts +3 -3
- package/dist/types/types/objectBased/typesObjectMap.d.ts +1 -1
- package/dist/types/types/objectBased/typesRecord.d.ts +1 -1
- package/dist/types/types/primitiveBased/typesPrimitive.d.ts +1 -1
- package/dist/types/types/types.d.ts +3 -3
- package/dist/types/types/utility/typesCodec.d.ts +1 -6
- package/dist/types/types/utility/typesCodecCore.d.ts +1 -1
- package/dist/types/types/utility/typesOr.d.ts +1 -1
- package/dist/types/types/utility/typesRefinement.d.ts +1 -1
- package/dist/types/types/utility/typesSkipCheck.d.ts +1 -1
- package/dist/types/types/utility/typesTag.d.ts +1 -1
- package/dist/types/wrappers/ObjectMap.d.ts +2 -0
- package/dist/types/wrappers/asMap.d.ts +10 -6
- package/package.json +14 -12
- package/src/action/applyAction.ts +125 -114
- package/src/action/applyMethodCall.ts +37 -37
- package/src/action/isModelAction.ts +16 -16
- package/src/action/middleware.ts +137 -137
- package/src/action/modelFlow.ts +240 -240
- package/src/action/modelFlowPromiseGenerator.ts +127 -125
- package/src/action/pendingActions.ts +42 -42
- package/src/action/wrapInAction.ts +156 -156
- package/src/actionMiddlewares/actionSerialization/actionSerialization.ts +1 -1
- package/src/actionMiddlewares/actionSerialization/applySerializedAction.ts +172 -172
- package/src/actionMiddlewares/actionSerialization/arraySerializer.ts +20 -20
- package/src/actionMiddlewares/actionSerialization/dateSerializer.ts +17 -17
- package/src/actionMiddlewares/actionSerialization/mapSerializer.ts +42 -42
- package/src/actionMiddlewares/actionSerialization/objectPathSerializer.ts +50 -50
- package/src/actionMiddlewares/actionSerialization/objectSnapshotSerializer.ts +21 -21
- package/src/actionMiddlewares/actionSerialization/plainObjectSerializer.ts +24 -32
- package/src/actionMiddlewares/actionSerialization/primitiveSerializer.ts +51 -51
- package/src/actionMiddlewares/actionSerialization/setSerializer.ts +37 -37
- package/src/actionMiddlewares/actionTrackingMiddleware.ts +3 -3
- package/src/actionMiddlewares/onActionMiddleware.ts +2 -2
- package/src/actionMiddlewares/readonlyMiddleware.ts +2 -2
- package/src/actionMiddlewares/transactionMiddleware.ts +4 -4
- package/src/actionMiddlewares/undoMiddleware.ts +804 -796
- package/src/actionMiddlewares/utils.ts +2 -2
- package/src/computedTree/computedTree.ts +143 -143
- package/src/context/context.ts +1 -1
- package/src/dataModel/BaseDataModel.ts +194 -192
- package/src/dataModel/actions.ts +1 -1
- package/src/dataModel/newDataModel.ts +57 -57
- package/src/deepChange/index.ts +1 -1
- package/src/deepChange/onDeepChange.ts +244 -244
- package/src/frozen/Frozen.ts +146 -146
- package/src/globalConfig/globalConfig.ts +107 -107
- package/src/index.ts +24 -24
- package/src/model/BaseModel.ts +275 -273
- package/src/model/ModelConstructorOptions.ts +15 -15
- package/src/model/getModelMetadata.ts +51 -51
- package/src/model/index.ts +6 -6
- package/src/model/mixins.ts +288 -288
- package/src/model/newModel.ts +301 -301
- package/src/model/utils.ts +249 -249
- package/src/modelShared/modelDecorator.ts +260 -253
- package/src/modelShared/modelInfo.ts +50 -50
- package/src/modelShared/modelSymbols.ts +3 -3
- package/src/modelShared/newModel.ts +25 -25
- package/src/modelShared/prop.ts +713 -684
- package/src/modelShared/sharedInternalModel.ts +427 -417
- package/src/modelShared/utils.ts +24 -24
- package/src/parent/core.ts +65 -65
- package/src/parent/coreObjectChildren.ts +180 -180
- package/src/parent/detach.ts +47 -47
- package/src/parent/findParent.ts +1 -1
- package/src/parent/getChildrenObjects.ts +25 -25
- package/src/parent/path.ts +386 -381
- package/src/parent/setParent.ts +149 -149
- package/src/parent/walkTree.ts +1 -1
- package/src/patch/applyPatches.ts +187 -187
- package/src/patch/jsonPatch.ts +108 -108
- package/src/patch/patchRecorder.ts +6 -1
- package/src/redux/connectReduxDevTools.ts +39 -7
- package/src/redux/redux.ts +6 -2
- package/src/ref/Ref.ts +1 -1
- package/src/ref/core.ts +339 -345
- package/src/ref/customRef.ts +3 -3
- package/src/ref/rootRef.ts +100 -100
- package/src/rootStore/attachDetach.ts +89 -89
- package/src/rootStore/rootStore.ts +1 -1
- package/src/snapshot/SnapshotOf.ts +104 -104
- package/src/snapshot/SnapshotProcessingError.ts +45 -45
- package/src/snapshot/applySnapshot.ts +177 -181
- package/src/snapshot/cloneTreeValue.ts +30 -30
- package/src/snapshot/fromArraySnapshot.ts +27 -33
- package/src/snapshot/fromModelSnapshot.ts +70 -70
- package/src/snapshot/fromPlainObjectSnapshot.ts +47 -42
- package/src/snapshot/fromSnapshot.ts +198 -198
- package/src/snapshot/getSnapshot.ts +80 -79
- package/src/snapshot/index.ts +8 -8
- package/src/snapshot/internal.ts +230 -230
- package/src/snapshot/reconcileArraySnapshot.ts +70 -70
- package/src/snapshot/reconcileModelSnapshot.ts +155 -150
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +72 -72
- package/src/snapshot/reconcileSnapshot.ts +88 -88
- package/src/standardActions/actions.ts +64 -64
- package/src/standardActions/objectActions.ts +60 -60
- package/src/transforms/ImmutableDate.ts +93 -93
- package/src/transforms/asMap.ts +50 -50
- package/src/transforms/asSet.ts +22 -22
- package/src/transforms/bigint.ts +20 -20
- package/src/transforms/date.ts +40 -40
- package/src/treeUtils/deepEquals.ts +55 -55
- package/src/treeUtils/sandbox.ts +6 -3
- package/src/tweaker/TweakerPriority.ts +9 -9
- package/src/tweaker/tweak.ts +4 -3
- package/src/tweaker/tweakArray.ts +530 -475
- package/src/tweaker/tweakFrozen.ts +42 -42
- package/src/tweaker/tweakModel.ts +1 -1
- package/src/tweaker/tweakPlainObject.ts +355 -355
- package/src/tweaker/typeChecking.ts +101 -101
- package/src/types/SnapshotTypeMismatchError.ts +46 -46
- package/src/types/TypeCheckError.ts +183 -184
- package/src/types/TypeChecker.ts +202 -185
- package/src/types/arrayBased/typesArray.ts +136 -137
- package/src/types/arrayBased/typesTuple.ts +138 -139
- package/src/types/createPerEntryCachedCheck.ts +166 -160
- package/src/types/index.ts +6 -6
- package/src/types/objectBased/typesArraySet.ts +133 -134
- package/src/types/objectBased/typesDataModelData.ts +203 -204
- package/src/types/objectBased/typesModel.ts +220 -221
- package/src/types/objectBased/typesObject.ts +308 -310
- package/src/types/objectBased/typesObjectMap.ts +142 -143
- package/src/types/objectBased/typesRecord.ts +156 -157
- package/src/types/objectBased/typesRef.ts +89 -89
- package/src/types/primitiveBased/typesEnum.ts +63 -63
- package/src/types/primitiveBased/typesPrimitive.ts +219 -220
- package/src/types/registerDefaultStandardTypeResolvers.ts +21 -21
- package/src/types/resolveTypeChecker.ts +78 -78
- package/src/types/schemas.ts +208 -208
- package/src/types/tProp.ts +277 -268
- package/src/types/typeCheck.ts +21 -21
- package/src/types/typeCheckErrorUtils.ts +23 -23
- package/src/types/types.ts +142 -142
- package/src/types/utility/typeToStoredData.ts +37 -37
- package/src/types/utility/typesBigInt.ts +15 -15
- package/src/types/utility/typesCodec.ts +41 -38
- package/src/types/utility/typesCodecCore.ts +178 -178
- package/src/types/utility/typesCodecSupport.ts +806 -806
- package/src/types/utility/typesDate.ts +27 -27
- package/src/types/utility/typesMap.ts +253 -222
- package/src/types/utility/typesOr.ts +263 -259
- package/src/types/utility/typesRefinement.ts +131 -125
- package/src/types/utility/typesSet.ts +110 -110
- package/src/types/utility/typesSkipCheck.ts +69 -70
- package/src/types/utility/typesTag.ts +88 -82
- package/src/types/utility/typesUnchecked.ts +40 -40
- package/src/utils/AnyFunction.ts +4 -4
- package/src/utils/ModelPool.ts +59 -59
- package/src/utils/chainFns.ts +18 -18
- package/src/utils/decorators.ts +274 -274
- package/src/utils/errorDiagnostics.ts +204 -204
- package/src/utils/index.ts +443 -372
- package/src/wrappers/ArraySet.ts +156 -156
- package/src/wrappers/ObjectMap.ts +155 -136
- package/src/wrappers/asMap.ts +65 -30
- package/src/wrappers/asSet.ts +3 -3
package/src/types/TypeChecker.ts
CHANGED
|
@@ -1,185 +1,202 @@
|
|
|
1
|
-
import type { Path } from "../parent/pathTypes"
|
|
2
|
-
import { isArray, isObject, isPrimitive, lazy } from "../utils"
|
|
3
|
-
import { getOrCreate } from "../utils/mapUtils"
|
|
4
|
-
import type { AnyStandardType } from "./schemas"
|
|
5
|
-
import { TypeCheckError } from "./TypeCheckError"
|
|
6
|
-
|
|
7
|
-
type CheckFunction = (value: any, path: Path, typeCheckedValue: any) => TypeCheckError | null
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @internal
|
|
11
|
-
*/
|
|
12
|
-
export enum TypeCheckerBaseType {
|
|
13
|
-
Object = "object",
|
|
14
|
-
Array = "array",
|
|
15
|
-
Primitive = "primitive",
|
|
16
|
-
Any = "any",
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @internal
|
|
21
|
-
*/
|
|
22
|
-
export function getTypeCheckerBaseTypeFromValue(value: any): TypeCheckerBaseType {
|
|
23
|
-
// array must be before object since arrays are also objects
|
|
24
|
-
if (isArray(value)) {
|
|
25
|
-
return TypeCheckerBaseType.Array
|
|
26
|
-
}
|
|
27
|
-
if (isObject(value)) {
|
|
28
|
-
return TypeCheckerBaseType.Object
|
|
29
|
-
}
|
|
30
|
-
if (isPrimitive(value)) {
|
|
31
|
-
return TypeCheckerBaseType.Primitive
|
|
32
|
-
}
|
|
33
|
-
return TypeCheckerBaseType.Any
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const typeCheckersWithCachedSnapshotProcessorResultsOfObject = new WeakMap<
|
|
37
|
-
object,
|
|
38
|
-
Set<TypeChecker>
|
|
39
|
-
>()
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* @internal
|
|
43
|
-
*/
|
|
44
|
-
export function invalidateCachedToSnapshotProcessorResult(obj: object) {
|
|
45
|
-
const set = typeCheckersWithCachedSnapshotProcessorResultsOfObject.get(obj)
|
|
46
|
-
|
|
47
|
-
if (set) {
|
|
48
|
-
set.forEach((typeChecker) => {
|
|
49
|
-
typeChecker.invalidateSnapshotProcessorCachedResult(obj)
|
|
50
|
-
})
|
|
51
|
-
typeCheckersWithCachedSnapshotProcessorResultsOfObject.delete(obj)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @internal
|
|
57
|
-
*/
|
|
58
|
-
export class TypeChecker {
|
|
59
|
-
unchecked: boolean
|
|
60
|
-
skipCheck = false
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
this._toSnapshotProcessorCache.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
1
|
+
import type { Path } from "../parent/pathTypes"
|
|
2
|
+
import { isArray, isObject, isPrimitive, lazy } from "../utils"
|
|
3
|
+
import { getOrCreate } from "../utils/mapUtils"
|
|
4
|
+
import type { AnyStandardType } from "./schemas"
|
|
5
|
+
import type { TypeCheckError } from "./TypeCheckError"
|
|
6
|
+
|
|
7
|
+
type CheckFunction = (value: any, path: Path, typeCheckedValue: any) => TypeCheckError | null
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
*/
|
|
12
|
+
export enum TypeCheckerBaseType {
|
|
13
|
+
Object = "object",
|
|
14
|
+
Array = "array",
|
|
15
|
+
Primitive = "primitive",
|
|
16
|
+
Any = "any",
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export function getTypeCheckerBaseTypeFromValue(value: any): TypeCheckerBaseType {
|
|
23
|
+
// array must be before object since arrays are also objects
|
|
24
|
+
if (isArray(value)) {
|
|
25
|
+
return TypeCheckerBaseType.Array
|
|
26
|
+
}
|
|
27
|
+
if (isObject(value)) {
|
|
28
|
+
return TypeCheckerBaseType.Object
|
|
29
|
+
}
|
|
30
|
+
if (isPrimitive(value)) {
|
|
31
|
+
return TypeCheckerBaseType.Primitive
|
|
32
|
+
}
|
|
33
|
+
return TypeCheckerBaseType.Any
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const typeCheckersWithCachedSnapshotProcessorResultsOfObject = new WeakMap<
|
|
37
|
+
object,
|
|
38
|
+
Set<TypeChecker>
|
|
39
|
+
>()
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export function invalidateCachedToSnapshotProcessorResult(obj: object) {
|
|
45
|
+
const set = typeCheckersWithCachedSnapshotProcessorResultsOfObject.get(obj)
|
|
46
|
+
|
|
47
|
+
if (set) {
|
|
48
|
+
set.forEach((typeChecker) => {
|
|
49
|
+
typeChecker.invalidateSnapshotProcessorCachedResult(obj)
|
|
50
|
+
})
|
|
51
|
+
typeCheckersWithCachedSnapshotProcessorResultsOfObject.delete(obj)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @internal
|
|
57
|
+
*/
|
|
58
|
+
export class TypeChecker {
|
|
59
|
+
unchecked: boolean
|
|
60
|
+
skipCheck = false
|
|
61
|
+
readonly baseType: TypeCheckerBaseType
|
|
62
|
+
private readonly _check: CheckFunction | null
|
|
63
|
+
readonly getTypeName: (...recursiveTypeCheckers: TypeChecker[]) => string
|
|
64
|
+
readonly typeInfoGen: TypeInfoGen
|
|
65
|
+
readonly snapshotType: (sn: unknown) => TypeChecker | null
|
|
66
|
+
private readonly _fromSnapshotProcessor: (sn: any) => unknown
|
|
67
|
+
private readonly _toSnapshotProcessor: (sn: any) => unknown
|
|
68
|
+
|
|
69
|
+
check(value: any, path: Path, typeCheckedValue: any): TypeCheckError | null {
|
|
70
|
+
if (this.unchecked || this.skipCheck) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return this._check!(value, path, typeCheckedValue)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private _cachedTypeInfoGen: TypeInfoGen
|
|
78
|
+
|
|
79
|
+
get typeInfo() {
|
|
80
|
+
return this._cachedTypeInfoGen(this as any)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
constructor(
|
|
84
|
+
baseType: TypeCheckerBaseType,
|
|
85
|
+
_check: CheckFunction | null,
|
|
86
|
+
getTypeName: (...recursiveTypeCheckers: TypeChecker[]) => string,
|
|
87
|
+
typeInfoGen: TypeInfoGen,
|
|
88
|
+
snapshotType: (sn: unknown) => TypeChecker | null,
|
|
89
|
+
_fromSnapshotProcessor: (sn: any) => unknown,
|
|
90
|
+
_toSnapshotProcessor: (sn: any) => unknown
|
|
91
|
+
) {
|
|
92
|
+
this.baseType = baseType
|
|
93
|
+
this._check = _check
|
|
94
|
+
this.getTypeName = getTypeName
|
|
95
|
+
this.typeInfoGen = typeInfoGen
|
|
96
|
+
this.snapshotType = snapshotType
|
|
97
|
+
this._fromSnapshotProcessor = _fromSnapshotProcessor
|
|
98
|
+
this._toSnapshotProcessor = _toSnapshotProcessor
|
|
99
|
+
this.unchecked = !_check
|
|
100
|
+
this._cachedTypeInfoGen = lazy(typeInfoGen)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
fromSnapshotProcessor = (sn: any): unknown => {
|
|
104
|
+
// we cannot cache fromSnapshotProcessor since nobody ensures us
|
|
105
|
+
// the original snapshot won't be tweaked after use
|
|
106
|
+
return this._fromSnapshotProcessor(sn)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private readonly _toSnapshotProcessorCache = new WeakMap<object, unknown>()
|
|
110
|
+
|
|
111
|
+
invalidateSnapshotProcessorCachedResult(obj: object) {
|
|
112
|
+
this._toSnapshotProcessorCache.delete(obj)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
toSnapshotProcessor = (sn: any): unknown => {
|
|
116
|
+
if (typeof sn !== "object" || sn === null) {
|
|
117
|
+
// not cacheable
|
|
118
|
+
return this._toSnapshotProcessor(sn)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (this._toSnapshotProcessorCache.has(sn)) {
|
|
122
|
+
return this._toSnapshotProcessorCache.get(sn)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const val = this._toSnapshotProcessor(sn)
|
|
126
|
+
this._toSnapshotProcessorCache.set(sn, val)
|
|
127
|
+
|
|
128
|
+
// register this type checker as listener of that sn changes
|
|
129
|
+
const typeCheckerSet = getOrCreate(
|
|
130
|
+
typeCheckersWithCachedSnapshotProcessorResultsOfObject,
|
|
131
|
+
sn,
|
|
132
|
+
() => new Set()
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
typeCheckerSet.add(this)
|
|
136
|
+
|
|
137
|
+
return val
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const lateTypeCheckerSymbol = Symbol("lateTypeCheker")
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* @internal
|
|
145
|
+
*/
|
|
146
|
+
export interface LateTypeChecker {
|
|
147
|
+
[lateTypeCheckerSymbol]: true
|
|
148
|
+
(): TypeChecker
|
|
149
|
+
typeInfo: TypeInfo
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @internal
|
|
154
|
+
*/
|
|
155
|
+
export function lateTypeChecker(fn: () => TypeChecker, typeInfoGen: TypeInfoGen): LateTypeChecker {
|
|
156
|
+
let cached: TypeChecker | undefined
|
|
157
|
+
const ltc = () => {
|
|
158
|
+
if (cached) {
|
|
159
|
+
return cached
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
cached = fn()
|
|
163
|
+
return cached
|
|
164
|
+
}
|
|
165
|
+
;(ltc as LateTypeChecker)[lateTypeCheckerSymbol] = true
|
|
166
|
+
|
|
167
|
+
const cachedTypeInfoGen = lazy(typeInfoGen)
|
|
168
|
+
|
|
169
|
+
Object.defineProperty(ltc, "typeInfo", {
|
|
170
|
+
enumerable: true,
|
|
171
|
+
configurable: false,
|
|
172
|
+
get() {
|
|
173
|
+
return cachedTypeInfoGen(ltc as any)
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
return ltc as LateTypeChecker
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* @internal
|
|
182
|
+
*/
|
|
183
|
+
export function isLateTypeChecker(ltc: unknown): ltc is LateTypeChecker {
|
|
184
|
+
return typeof ltc === "function" && lateTypeCheckerSymbol in ltc
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Type info base class.
|
|
189
|
+
*/
|
|
190
|
+
export class TypeInfo {
|
|
191
|
+
readonly kind: string = "typeInfo"
|
|
192
|
+
readonly thisType: AnyStandardType
|
|
193
|
+
|
|
194
|
+
constructor(thisType: AnyStandardType) {
|
|
195
|
+
this.thisType = thisType
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @internal
|
|
201
|
+
*/
|
|
202
|
+
export type TypeInfoGen = (t: AnyStandardType) => TypeInfo
|
|
@@ -1,137 +1,136 @@
|
|
|
1
|
-
import type { Path } from "../../parent/pathTypes"
|
|
2
|
-
import { isArray } from "../../utils"
|
|
3
|
-
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
4
|
-
import { arrayCachePruning, createPerEntryCachedCheck } from "../createPerEntryCachedCheck"
|
|
5
|
-
import { getTypeInfo } from "../getTypeInfo"
|
|
6
|
-
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
7
|
-
import type { AnyStandardType, AnyType, ArrayType } from "../schemas"
|
|
8
|
-
import { TypeCheckError } from "../TypeCheckError"
|
|
9
|
-
import {
|
|
10
|
-
lateTypeChecker,
|
|
11
|
-
TypeChecker,
|
|
12
|
-
TypeCheckerBaseType,
|
|
13
|
-
TypeInfo,
|
|
14
|
-
TypeInfoGen,
|
|
15
|
-
} from "../TypeChecker"
|
|
16
|
-
import { prependPathElementToTypeCheckError } from "../typeCheckErrorUtils"
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A type that represents an array of values of a given type.
|
|
20
|
-
*
|
|
21
|
-
* Example:
|
|
22
|
-
* ```ts
|
|
23
|
-
* const numberArrayType = types.array(types.number)
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @template T Item type.
|
|
27
|
-
* @param itemType Type of inner items.
|
|
28
|
-
* @returns
|
|
29
|
-
*/
|
|
30
|
-
export function typesArray<T extends AnyType>(itemType: T): ArrayType<T[]> {
|
|
31
|
-
const typeInfoGen: TypeInfoGen = (t) => new ArrayTypeInfo(t, resolveStandardType(itemType))
|
|
32
|
-
|
|
33
|
-
return lateTypeChecker(() => {
|
|
34
|
-
const itemChecker = resolveTypeChecker(itemType)
|
|
35
|
-
const emptyChildPath: Path = []
|
|
36
|
-
|
|
37
|
-
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
38
|
-
`Array<${itemChecker.getTypeName(...recursiveTypeCheckers, itemChecker)}>`
|
|
39
|
-
|
|
40
|
-
const checkArrayItems = createPerEntryCachedCheck<number>(
|
|
41
|
-
(array, checkEntry) => {
|
|
42
|
-
for (let i = 0; i < array.length; i++) {
|
|
43
|
-
const error = checkEntry(i)
|
|
44
|
-
if (error) return error
|
|
45
|
-
}
|
|
46
|
-
return null
|
|
47
|
-
},
|
|
48
|
-
(array, index, path, typeCheckedValue) => {
|
|
49
|
-
const error = itemChecker.check(array[index], emptyChildPath, typeCheckedValue)
|
|
50
|
-
return error
|
|
51
|
-
? prependPathElementToTypeCheckError(error, path, index, typeCheckedValue)
|
|
52
|
-
: null
|
|
53
|
-
},
|
|
54
|
-
arrayCachePruning
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
const thisTc: TypeChecker = new TypeChecker(
|
|
58
|
-
TypeCheckerBaseType.Array,
|
|
59
|
-
|
|
60
|
-
(array, path, typeCheckedValue) => {
|
|
61
|
-
if (!isArray(array)) {
|
|
62
|
-
return new TypeCheckError({
|
|
63
|
-
path,
|
|
64
|
-
expectedTypeName: getTypeName(thisTc),
|
|
65
|
-
actualValue: array,
|
|
66
|
-
typeCheckedValue,
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (itemChecker.unchecked || itemChecker.skipCheck) {
|
|
71
|
-
return null
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return checkArrayItems(array, path, typeCheckedValue)
|
|
75
|
-
},
|
|
76
|
-
getTypeName,
|
|
77
|
-
typeInfoGen,
|
|
78
|
-
|
|
79
|
-
(array) => {
|
|
80
|
-
if (!isArray(array)) {
|
|
81
|
-
return null
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!itemChecker.unchecked) {
|
|
85
|
-
for (let i = 0; i < array.length; i++) {
|
|
86
|
-
const itemActualChecker = itemChecker.snapshotType(array[i])
|
|
87
|
-
if (!itemActualChecker) {
|
|
88
|
-
return null
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return thisTc
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
(sn: unknown[]) => {
|
|
97
|
-
if (itemChecker.unchecked) {
|
|
98
|
-
return sn
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return sn.map((item, i) =>
|
|
102
|
-
withErrorPathSegment(i, () => itemChecker.fromSnapshotProcessor(item))
|
|
103
|
-
)
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
(sn: unknown[]) => {
|
|
107
|
-
if (itemChecker.unchecked) {
|
|
108
|
-
return sn
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return sn.map((item, i) =>
|
|
112
|
-
withErrorPathSegment(i, () => itemChecker.toSnapshotProcessor(item))
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return thisTc
|
|
118
|
-
}, typeInfoGen) as any
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* `types.array` type info.
|
|
123
|
-
*/
|
|
124
|
-
export class ArrayTypeInfo extends TypeInfo {
|
|
125
|
-
readonly kind = "array"
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
1
|
+
import type { Path } from "../../parent/pathTypes"
|
|
2
|
+
import { isArray } from "../../utils"
|
|
3
|
+
import { withErrorPathSegment } from "../../utils/errorDiagnostics"
|
|
4
|
+
import { arrayCachePruning, createPerEntryCachedCheck } from "../createPerEntryCachedCheck"
|
|
5
|
+
import { getTypeInfo } from "../getTypeInfo"
|
|
6
|
+
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
7
|
+
import type { AnyStandardType, AnyType, ArrayType } from "../schemas"
|
|
8
|
+
import { TypeCheckError } from "../TypeCheckError"
|
|
9
|
+
import {
|
|
10
|
+
lateTypeChecker,
|
|
11
|
+
TypeChecker,
|
|
12
|
+
TypeCheckerBaseType,
|
|
13
|
+
TypeInfo,
|
|
14
|
+
type TypeInfoGen,
|
|
15
|
+
} from "../TypeChecker"
|
|
16
|
+
import { prependPathElementToTypeCheckError } from "../typeCheckErrorUtils"
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A type that represents an array of values of a given type.
|
|
20
|
+
*
|
|
21
|
+
* Example:
|
|
22
|
+
* ```ts
|
|
23
|
+
* const numberArrayType = types.array(types.number)
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @template T Item type.
|
|
27
|
+
* @param itemType Type of inner items.
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
export function typesArray<T extends AnyType>(itemType: T): ArrayType<T[]> {
|
|
31
|
+
const typeInfoGen: TypeInfoGen = (t) => new ArrayTypeInfo(t, resolveStandardType(itemType))
|
|
32
|
+
|
|
33
|
+
return lateTypeChecker(() => {
|
|
34
|
+
const itemChecker = resolveTypeChecker(itemType)
|
|
35
|
+
const emptyChildPath: Path = []
|
|
36
|
+
|
|
37
|
+
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
38
|
+
`Array<${itemChecker.getTypeName(...recursiveTypeCheckers, itemChecker)}>`
|
|
39
|
+
|
|
40
|
+
const checkArrayItems = createPerEntryCachedCheck<number>(
|
|
41
|
+
(array, checkEntry) => {
|
|
42
|
+
for (let i = 0; i < array.length; i++) {
|
|
43
|
+
const error = checkEntry(i)
|
|
44
|
+
if (error) return error
|
|
45
|
+
}
|
|
46
|
+
return null
|
|
47
|
+
},
|
|
48
|
+
(array, index, path, typeCheckedValue) => {
|
|
49
|
+
const error = itemChecker.check(array[index], emptyChildPath, typeCheckedValue)
|
|
50
|
+
return error
|
|
51
|
+
? prependPathElementToTypeCheckError(error, path, index, typeCheckedValue)
|
|
52
|
+
: null
|
|
53
|
+
},
|
|
54
|
+
arrayCachePruning
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const thisTc: TypeChecker = new TypeChecker(
|
|
58
|
+
TypeCheckerBaseType.Array,
|
|
59
|
+
|
|
60
|
+
(array, path, typeCheckedValue) => {
|
|
61
|
+
if (!isArray(array)) {
|
|
62
|
+
return new TypeCheckError({
|
|
63
|
+
path,
|
|
64
|
+
expectedTypeName: getTypeName(thisTc),
|
|
65
|
+
actualValue: array,
|
|
66
|
+
typeCheckedValue,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (itemChecker.unchecked || itemChecker.skipCheck) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return checkArrayItems(array, path, typeCheckedValue)
|
|
75
|
+
},
|
|
76
|
+
getTypeName,
|
|
77
|
+
typeInfoGen,
|
|
78
|
+
|
|
79
|
+
(array) => {
|
|
80
|
+
if (!isArray(array)) {
|
|
81
|
+
return null
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!itemChecker.unchecked) {
|
|
85
|
+
for (let i = 0; i < array.length; i++) {
|
|
86
|
+
const itemActualChecker = itemChecker.snapshotType(array[i])
|
|
87
|
+
if (!itemActualChecker) {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return thisTc
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
(sn: unknown[]) => {
|
|
97
|
+
if (itemChecker.unchecked) {
|
|
98
|
+
return sn
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return sn.map((item, i) =>
|
|
102
|
+
withErrorPathSegment(i, () => itemChecker.fromSnapshotProcessor(item))
|
|
103
|
+
)
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
(sn: unknown[]) => {
|
|
107
|
+
if (itemChecker.unchecked) {
|
|
108
|
+
return sn
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return sn.map((item, i) =>
|
|
112
|
+
withErrorPathSegment(i, () => itemChecker.toSnapshotProcessor(item))
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return thisTc
|
|
118
|
+
}, typeInfoGen) as any
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* `types.array` type info.
|
|
123
|
+
*/
|
|
124
|
+
export class ArrayTypeInfo extends TypeInfo {
|
|
125
|
+
readonly kind = "array"
|
|
126
|
+
readonly itemType: AnyStandardType
|
|
127
|
+
|
|
128
|
+
get itemTypeInfo(): TypeInfo {
|
|
129
|
+
return getTypeInfo(this.itemType)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
constructor(thisType: AnyStandardType, itemType: AnyStandardType) {
|
|
133
|
+
super(thisType)
|
|
134
|
+
this.itemType = itemType
|
|
135
|
+
}
|
|
136
|
+
}
|