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,134 +1,133 @@
|
|
|
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 { ArraySet } from "../../wrappers/ArraySet"
|
|
6
|
-
import { typesArray } from "../arrayBased/typesArray"
|
|
7
|
-
import { getTypeInfo } from "../getTypeInfo"
|
|
8
|
-
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
9
|
-
import type { AnyStandardType, AnyType, ModelType, TypeToData } from "../schemas"
|
|
10
|
-
import { TypeCheckError } from "../TypeCheckError"
|
|
11
|
-
import {
|
|
12
|
-
lateTypeChecker,
|
|
13
|
-
TypeChecker,
|
|
14
|
-
TypeCheckerBaseType,
|
|
15
|
-
TypeInfo,
|
|
16
|
-
TypeInfoGen,
|
|
17
|
-
} from "../TypeChecker"
|
|
18
|
-
import { resolveCodecSupport } from "../utility/typesCodec"
|
|
19
|
-
import { typesObject } from "./typesObject"
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* A type that represents an array backed set ArraySet.
|
|
23
|
-
*
|
|
24
|
-
* Example:
|
|
25
|
-
* ```ts
|
|
26
|
-
* const numberSetType = types.arraySet(types.number)
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* @template T Value type.
|
|
30
|
-
* @param valueType Value type.
|
|
31
|
-
* @returns
|
|
32
|
-
*/
|
|
33
|
-
export function typesArraySet<T extends AnyType>(valueType: T): ModelType<ArraySet<TypeToData<T>>> {
|
|
34
|
-
const typeInfoGen: TypeInfoGen = (t) => new ArraySetTypeInfo(t, resolveStandardType(valueType))
|
|
35
|
-
|
|
36
|
-
return lateTypeChecker(() => {
|
|
37
|
-
const modelInfo = modelInfoByClass.get(ArraySet)!
|
|
38
|
-
|
|
39
|
-
const valueChecker = resolveTypeChecker(valueType)
|
|
40
|
-
const valueSupport = resolveCodecSupport(valueType)
|
|
41
|
-
const storedValueChecker = resolveTypeChecker(valueSupport.storedType)
|
|
42
|
-
|
|
43
|
-
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
44
|
-
`ArraySet<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
45
|
-
|
|
46
|
-
const dataTypeChecker = typesObject(() => ({
|
|
47
|
-
items: typesArray(valueSupport.storedType as any),
|
|
48
|
-
}))
|
|
49
|
-
|
|
50
|
-
const thisTc: TypeChecker = new TypeChecker(
|
|
51
|
-
TypeCheckerBaseType.Object, // because it is really a model
|
|
52
|
-
|
|
53
|
-
(obj, path, typeCheckedValue) => {
|
|
54
|
-
if (!(obj instanceof ArraySet)) {
|
|
55
|
-
return new TypeCheckError({
|
|
56
|
-
path,
|
|
57
|
-
expectedTypeName: getTypeName(thisTc),
|
|
58
|
-
actualValue: obj,
|
|
59
|
-
typeCheckedValue,
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const resolvedTc = resolveTypeChecker(dataTypeChecker)
|
|
64
|
-
return resolvedTc.check(obj.$, path, typeCheckedValue)
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
getTypeName,
|
|
68
|
-
typeInfoGen,
|
|
69
|
-
|
|
70
|
-
(obj) => {
|
|
71
|
-
if (!isObject(obj)) {
|
|
72
|
-
return null
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (obj[modelTypeKey] !== undefined) {
|
|
76
|
-
// fast check
|
|
77
|
-
return obj[modelTypeKey] === modelInfo.name ? thisTc : null
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const resolvedTc = resolveTypeChecker(dataTypeChecker)
|
|
81
|
-
return resolvedTc.snapshotType(obj) ? thisTc : null
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
(sn: { items: unknown[] }) => {
|
|
85
|
-
const items = withErrorPathSegment("items", () =>
|
|
86
|
-
sn.items.map((v, i) =>
|
|
87
|
-
withErrorPathSegment(i, () => storedValueChecker.fromSnapshotProcessor(v))
|
|
88
|
-
)
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
return {
|
|
92
|
-
...sn,
|
|
93
|
-
[modelTypeKey]: modelInfo.name,
|
|
94
|
-
items,
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
(sn: { items: unknown[]; [modelTypeKey]?: string }) => {
|
|
99
|
-
const items = withErrorPathSegment("items", () =>
|
|
100
|
-
sn.items.map((v, i) =>
|
|
101
|
-
withErrorPathSegment(i, () => storedValueChecker.toSnapshotProcessor(v))
|
|
102
|
-
)
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
const snCopy = {
|
|
106
|
-
...sn,
|
|
107
|
-
items,
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return snCopy
|
|
111
|
-
}
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
return thisTc
|
|
115
|
-
}, typeInfoGen) as any
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* `types.arraySet` type info.
|
|
120
|
-
*/
|
|
121
|
-
export class ArraySetTypeInfo extends TypeInfo {
|
|
122
|
-
readonly kind = "arraySet"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
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 { ArraySet } from "../../wrappers/ArraySet"
|
|
6
|
+
import { typesArray } from "../arrayBased/typesArray"
|
|
7
|
+
import { getTypeInfo } from "../getTypeInfo"
|
|
8
|
+
import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
|
|
9
|
+
import type { AnyStandardType, AnyType, ModelType, TypeToData } from "../schemas"
|
|
10
|
+
import { TypeCheckError } from "../TypeCheckError"
|
|
11
|
+
import {
|
|
12
|
+
lateTypeChecker,
|
|
13
|
+
TypeChecker,
|
|
14
|
+
TypeCheckerBaseType,
|
|
15
|
+
TypeInfo,
|
|
16
|
+
type TypeInfoGen,
|
|
17
|
+
} from "../TypeChecker"
|
|
18
|
+
import { resolveCodecSupport } from "../utility/typesCodec"
|
|
19
|
+
import { typesObject } from "./typesObject"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A type that represents an array backed set ArraySet.
|
|
23
|
+
*
|
|
24
|
+
* Example:
|
|
25
|
+
* ```ts
|
|
26
|
+
* const numberSetType = types.arraySet(types.number)
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @template T Value type.
|
|
30
|
+
* @param valueType Value type.
|
|
31
|
+
* @returns
|
|
32
|
+
*/
|
|
33
|
+
export function typesArraySet<T extends AnyType>(valueType: T): ModelType<ArraySet<TypeToData<T>>> {
|
|
34
|
+
const typeInfoGen: TypeInfoGen = (t) => new ArraySetTypeInfo(t, resolveStandardType(valueType))
|
|
35
|
+
|
|
36
|
+
return lateTypeChecker(() => {
|
|
37
|
+
const modelInfo = modelInfoByClass.get(ArraySet)!
|
|
38
|
+
|
|
39
|
+
const valueChecker = resolveTypeChecker(valueType)
|
|
40
|
+
const valueSupport = resolveCodecSupport(valueType)
|
|
41
|
+
const storedValueChecker = resolveTypeChecker(valueSupport.storedType)
|
|
42
|
+
|
|
43
|
+
const getTypeName = (...recursiveTypeCheckers: TypeChecker[]) =>
|
|
44
|
+
`ArraySet<${valueChecker.getTypeName(...recursiveTypeCheckers, valueChecker)}>`
|
|
45
|
+
|
|
46
|
+
const dataTypeChecker = typesObject(() => ({
|
|
47
|
+
items: typesArray(valueSupport.storedType as any),
|
|
48
|
+
}))
|
|
49
|
+
|
|
50
|
+
const thisTc: TypeChecker = new TypeChecker(
|
|
51
|
+
TypeCheckerBaseType.Object, // because it is really a model
|
|
52
|
+
|
|
53
|
+
(obj, path, typeCheckedValue) => {
|
|
54
|
+
if (!(obj instanceof ArraySet)) {
|
|
55
|
+
return new TypeCheckError({
|
|
56
|
+
path,
|
|
57
|
+
expectedTypeName: getTypeName(thisTc),
|
|
58
|
+
actualValue: obj,
|
|
59
|
+
typeCheckedValue,
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const resolvedTc = resolveTypeChecker(dataTypeChecker)
|
|
64
|
+
return resolvedTc.check(obj.$, path, typeCheckedValue)
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
getTypeName,
|
|
68
|
+
typeInfoGen,
|
|
69
|
+
|
|
70
|
+
(obj) => {
|
|
71
|
+
if (!isObject(obj)) {
|
|
72
|
+
return null
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (obj[modelTypeKey] !== undefined) {
|
|
76
|
+
// fast check
|
|
77
|
+
return obj[modelTypeKey] === modelInfo.name ? thisTc : null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const resolvedTc = resolveTypeChecker(dataTypeChecker)
|
|
81
|
+
return resolvedTc.snapshotType(obj) ? thisTc : null
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
(sn: { items: unknown[] }) => {
|
|
85
|
+
const items = withErrorPathSegment("items", () =>
|
|
86
|
+
sn.items.map((v, i) =>
|
|
87
|
+
withErrorPathSegment(i, () => storedValueChecker.fromSnapshotProcessor(v))
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
...sn,
|
|
93
|
+
[modelTypeKey]: modelInfo.name,
|
|
94
|
+
items,
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
(sn: { items: unknown[]; [modelTypeKey]?: string }) => {
|
|
99
|
+
const items = withErrorPathSegment("items", () =>
|
|
100
|
+
sn.items.map((v, i) =>
|
|
101
|
+
withErrorPathSegment(i, () => storedValueChecker.toSnapshotProcessor(v))
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
const snCopy = {
|
|
106
|
+
...sn,
|
|
107
|
+
items,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return snCopy
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
return thisTc
|
|
115
|
+
}, typeInfoGen) as any
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* `types.arraySet` type info.
|
|
120
|
+
*/
|
|
121
|
+
export class ArraySetTypeInfo extends TypeInfo {
|
|
122
|
+
readonly kind = "arraySet"
|
|
123
|
+
readonly valueType: AnyStandardType
|
|
124
|
+
|
|
125
|
+
get valueTypeInfo(): TypeInfo {
|
|
126
|
+
return getTypeInfo(this.valueType)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
constructor(originalType: AnyStandardType, valueType: AnyStandardType) {
|
|
130
|
+
super(originalType)
|
|
131
|
+
this.valueType = valueType
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -1,204 +1,203 @@
|
|
|
1
|
-
import type { O } from "ts-toolbelt"
|
|
2
|
-
import type { AnyDataModel } from "../../dataModel/BaseDataModel"
|
|
3
|
-
import { getDataModelMetadata } from "../../dataModel/getDataModelMetadata"
|
|
4
|
-
import { isDataModelClass } from "../../dataModel/utils"
|
|
5
|
-
import type {
|
|
6
|
-
ModelClass,
|
|
7
|
-
ModelData,
|
|
8
|
-
ModelUntransformedData,
|
|
9
|
-
} from "../../modelShared/BaseModelShared"
|
|
10
|
-
import { modelInfoByClass } from "../../modelShared/modelInfo"
|
|
11
|
-
import { getInternalModelClassPropsInfo } from "../../modelShared/modelPropsInfo"
|
|
12
|
-
import { noDefaultValue } from "../../modelShared/prop"
|
|
13
|
-
import { failure, lazy } from "../../utils"
|
|
14
|
-
import { getTypeInfo } from "../getTypeInfo"
|
|
15
|
-
import { registerStandardTypeResolver, resolveTypeChecker } from "../resolveTypeChecker"
|
|
16
|
-
import type { AnyStandardType, IdentityType } from "../schemas"
|
|
17
|
-
import {
|
|
18
|
-
lateTypeChecker,
|
|
19
|
-
TypeChecker,
|
|
20
|
-
TypeCheckerBaseType,
|
|
21
|
-
TypeInfo,
|
|
22
|
-
TypeInfoGen,
|
|
23
|
-
} from "../TypeChecker"
|
|
24
|
-
|
|
25
|
-
const cachedDataModelTypeChecker = new WeakMap<ModelClass<AnyDataModel>, TypeChecker>()
|
|
26
|
-
const dataModelDataStandardTypes = new WeakSet<object>()
|
|
27
|
-
|
|
28
|
-
type _Class<T> = abstract new (...args: any[]) => T
|
|
29
|
-
type _ClassOrObject<M, K> = K extends M ? object : _Class<K> | (() => _Class<K>)
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* A type that represents a data model data.
|
|
33
|
-
* The type referenced in the model decorator will be used for type checking.
|
|
34
|
-
*
|
|
35
|
-
* Example:
|
|
36
|
-
* ```ts
|
|
37
|
-
* const someDataModelDataType = types.dataModelData(SomeModel)
|
|
38
|
-
* // or for recursive models
|
|
39
|
-
* const someDataModelDataType = types.dataModelData<SomeModel>(() => SomeModel)
|
|
40
|
-
* ```
|
|
41
|
-
*
|
|
42
|
-
* @template M Data model type.
|
|
43
|
-
* @param modelClass Model class.
|
|
44
|
-
* @returns
|
|
45
|
-
*/
|
|
46
|
-
export function typesDataModelData<M = never, K = M>(
|
|
47
|
-
modelClass: _ClassOrObject<M, K>
|
|
48
|
-
): IdentityType<
|
|
49
|
-
| ModelUntransformedData<
|
|
50
|
-
K extends M ? (M extends AnyDataModel ? M : never) : K extends AnyDataModel ? K : never
|
|
51
|
-
>
|
|
52
|
-
| ModelData<
|
|
53
|
-
K extends M ? (M extends AnyDataModel ? M : never) : K extends AnyDataModel ? K : never
|
|
54
|
-
>
|
|
55
|
-
> {
|
|
56
|
-
// if we type it any stronger then recursive defs and so on stop working
|
|
57
|
-
|
|
58
|
-
if (!isDataModelClass(modelClass) && typeof modelClass === "function") {
|
|
59
|
-
// resolve later
|
|
60
|
-
const modelClassFn = modelClass as () => ModelClass<AnyDataModel>
|
|
61
|
-
const typeInfoGen: TypeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClassFn())
|
|
62
|
-
const tc = lateTypeChecker(() => typesDataModelData(modelClassFn()) as any, typeInfoGen) as any
|
|
63
|
-
dataModelDataStandardTypes.add(tc as object)
|
|
64
|
-
return tc
|
|
65
|
-
} else {
|
|
66
|
-
const modelClazz: ModelClass<AnyDataModel> = modelClass as any
|
|
67
|
-
|
|
68
|
-
const cachedTypeChecker = cachedDataModelTypeChecker.get(modelClazz)
|
|
69
|
-
if (cachedTypeChecker) {
|
|
70
|
-
return cachedTypeChecker as any
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const typeInfoGen: TypeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClazz)
|
|
74
|
-
|
|
75
|
-
const tc = lateTypeChecker(() => {
|
|
76
|
-
const modelInfo = modelInfoByClass.get(modelClazz)!
|
|
77
|
-
const typeName = `DataModelData(${modelInfo.name})`
|
|
78
|
-
|
|
79
|
-
const dataTypeChecker = getDataModelMetadata(modelClazz).dataType
|
|
80
|
-
if (!dataTypeChecker) {
|
|
81
|
-
throw failure(
|
|
82
|
-
`type checking cannot be performed over data model data of type '${modelInfo.name}' since that model type has no data type declared, consider adding a data type or using types.unchecked() instead`
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker)
|
|
87
|
-
|
|
88
|
-
const thisTc: TypeChecker = new TypeChecker(
|
|
89
|
-
TypeCheckerBaseType.Object,
|
|
90
|
-
|
|
91
|
-
(value, path, typeCheckedValue) => {
|
|
92
|
-
return resolvedDataTypeChecker.check(value, path, typeCheckedValue)
|
|
93
|
-
},
|
|
94
|
-
|
|
95
|
-
() => typeName,
|
|
96
|
-
typeInfoGen,
|
|
97
|
-
|
|
98
|
-
(value) => {
|
|
99
|
-
return resolvedDataTypeChecker.snapshotType(value) ? thisTc : null
|
|
100
|
-
},
|
|
101
|
-
|
|
102
|
-
(sn: Record<string, unknown>) => {
|
|
103
|
-
return resolvedDataTypeChecker.fromSnapshotProcessor(sn)
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
(sn: Record<string, unknown>) => {
|
|
107
|
-
return resolvedDataTypeChecker.toSnapshotProcessor(sn)
|
|
108
|
-
}
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
return thisTc
|
|
112
|
-
}, typeInfoGen) as any
|
|
113
|
-
|
|
114
|
-
cachedDataModelTypeChecker.set(modelClazz, tc)
|
|
115
|
-
dataModelDataStandardTypes.add(tc as object)
|
|
116
|
-
|
|
117
|
-
return tc
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* `types.dataModelData` type info for a model props.
|
|
123
|
-
*/
|
|
124
|
-
export interface DataModelDataTypeInfoProps {
|
|
125
|
-
readonly [propName: string]: Readonly<{
|
|
126
|
-
type: AnyStandardType | undefined
|
|
127
|
-
typeInfo: TypeInfo | undefined
|
|
128
|
-
hasDefault: boolean
|
|
129
|
-
default: any
|
|
130
|
-
}>
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* `types.dataModelData` type info.
|
|
135
|
-
*/
|
|
136
|
-
export class DataModelDataTypeInfo extends TypeInfo {
|
|
137
|
-
readonly kind = "dataModelData"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
1
|
+
import type { O } from "ts-toolbelt"
|
|
2
|
+
import type { AnyDataModel } from "../../dataModel/BaseDataModel"
|
|
3
|
+
import { getDataModelMetadata } from "../../dataModel/getDataModelMetadata"
|
|
4
|
+
import { isDataModelClass } from "../../dataModel/utils"
|
|
5
|
+
import type {
|
|
6
|
+
ModelClass,
|
|
7
|
+
ModelData,
|
|
8
|
+
ModelUntransformedData,
|
|
9
|
+
} from "../../modelShared/BaseModelShared"
|
|
10
|
+
import { modelInfoByClass } from "../../modelShared/modelInfo"
|
|
11
|
+
import { getInternalModelClassPropsInfo } from "../../modelShared/modelPropsInfo"
|
|
12
|
+
import { noDefaultValue } from "../../modelShared/prop"
|
|
13
|
+
import { failure, lazy } from "../../utils"
|
|
14
|
+
import { getTypeInfo } from "../getTypeInfo"
|
|
15
|
+
import { registerStandardTypeResolver, resolveTypeChecker } from "../resolveTypeChecker"
|
|
16
|
+
import type { AnyStandardType, IdentityType } from "../schemas"
|
|
17
|
+
import {
|
|
18
|
+
lateTypeChecker,
|
|
19
|
+
TypeChecker,
|
|
20
|
+
TypeCheckerBaseType,
|
|
21
|
+
TypeInfo,
|
|
22
|
+
type TypeInfoGen,
|
|
23
|
+
} from "../TypeChecker"
|
|
24
|
+
|
|
25
|
+
const cachedDataModelTypeChecker = new WeakMap<ModelClass<AnyDataModel>, TypeChecker>()
|
|
26
|
+
const dataModelDataStandardTypes = new WeakSet<object>()
|
|
27
|
+
|
|
28
|
+
type _Class<T> = abstract new (...args: any[]) => T
|
|
29
|
+
type _ClassOrObject<M, K> = K extends M ? object : _Class<K> | (() => _Class<K>)
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A type that represents a data model data.
|
|
33
|
+
* The type referenced in the model decorator will be used for type checking.
|
|
34
|
+
*
|
|
35
|
+
* Example:
|
|
36
|
+
* ```ts
|
|
37
|
+
* const someDataModelDataType = types.dataModelData(SomeModel)
|
|
38
|
+
* // or for recursive models
|
|
39
|
+
* const someDataModelDataType = types.dataModelData<SomeModel>(() => SomeModel)
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @template M Data model type.
|
|
43
|
+
* @param modelClass Model class.
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
export function typesDataModelData<M = never, K = M>(
|
|
47
|
+
modelClass: _ClassOrObject<M, K>
|
|
48
|
+
): IdentityType<
|
|
49
|
+
| ModelUntransformedData<
|
|
50
|
+
K extends M ? (M extends AnyDataModel ? M : never) : K extends AnyDataModel ? K : never
|
|
51
|
+
>
|
|
52
|
+
| ModelData<
|
|
53
|
+
K extends M ? (M extends AnyDataModel ? M : never) : K extends AnyDataModel ? K : never
|
|
54
|
+
>
|
|
55
|
+
> {
|
|
56
|
+
// if we type it any stronger then recursive defs and so on stop working
|
|
57
|
+
|
|
58
|
+
if (!isDataModelClass(modelClass) && typeof modelClass === "function") {
|
|
59
|
+
// resolve later
|
|
60
|
+
const modelClassFn = modelClass as () => ModelClass<AnyDataModel>
|
|
61
|
+
const typeInfoGen: TypeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClassFn())
|
|
62
|
+
const tc = lateTypeChecker(() => typesDataModelData(modelClassFn()) as any, typeInfoGen) as any
|
|
63
|
+
dataModelDataStandardTypes.add(tc as object)
|
|
64
|
+
return tc
|
|
65
|
+
} else {
|
|
66
|
+
const modelClazz: ModelClass<AnyDataModel> = modelClass as any
|
|
67
|
+
|
|
68
|
+
const cachedTypeChecker = cachedDataModelTypeChecker.get(modelClazz)
|
|
69
|
+
if (cachedTypeChecker) {
|
|
70
|
+
return cachedTypeChecker as any
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const typeInfoGen: TypeInfoGen = (t) => new DataModelDataTypeInfo(t, modelClazz)
|
|
74
|
+
|
|
75
|
+
const tc = lateTypeChecker(() => {
|
|
76
|
+
const modelInfo = modelInfoByClass.get(modelClazz)!
|
|
77
|
+
const typeName = `DataModelData(${modelInfo.name})`
|
|
78
|
+
|
|
79
|
+
const dataTypeChecker = getDataModelMetadata(modelClazz).dataType
|
|
80
|
+
if (!dataTypeChecker) {
|
|
81
|
+
throw failure(
|
|
82
|
+
`type checking cannot be performed over data model data of type '${modelInfo.name}' since that model type has no data type declared, consider adding a data type or using types.unchecked() instead`
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const resolvedDataTypeChecker = resolveTypeChecker(dataTypeChecker)
|
|
87
|
+
|
|
88
|
+
const thisTc: TypeChecker = new TypeChecker(
|
|
89
|
+
TypeCheckerBaseType.Object,
|
|
90
|
+
|
|
91
|
+
(value, path, typeCheckedValue) => {
|
|
92
|
+
return resolvedDataTypeChecker.check(value, path, typeCheckedValue)
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
() => typeName,
|
|
96
|
+
typeInfoGen,
|
|
97
|
+
|
|
98
|
+
(value) => {
|
|
99
|
+
return resolvedDataTypeChecker.snapshotType(value) ? thisTc : null
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
(sn: Record<string, unknown>) => {
|
|
103
|
+
return resolvedDataTypeChecker.fromSnapshotProcessor(sn)
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
(sn: Record<string, unknown>) => {
|
|
107
|
+
return resolvedDataTypeChecker.toSnapshotProcessor(sn)
|
|
108
|
+
}
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return thisTc
|
|
112
|
+
}, typeInfoGen) as any
|
|
113
|
+
|
|
114
|
+
cachedDataModelTypeChecker.set(modelClazz, tc)
|
|
115
|
+
dataModelDataStandardTypes.add(tc as object)
|
|
116
|
+
|
|
117
|
+
return tc
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* `types.dataModelData` type info for a model props.
|
|
123
|
+
*/
|
|
124
|
+
export interface DataModelDataTypeInfoProps {
|
|
125
|
+
readonly [propName: string]: Readonly<{
|
|
126
|
+
type: AnyStandardType | undefined
|
|
127
|
+
typeInfo: TypeInfo | undefined
|
|
128
|
+
hasDefault: boolean
|
|
129
|
+
default: any
|
|
130
|
+
}>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* `types.dataModelData` type info.
|
|
135
|
+
*/
|
|
136
|
+
export class DataModelDataTypeInfo extends TypeInfo {
|
|
137
|
+
readonly kind = "dataModelData"
|
|
138
|
+
readonly modelClass: ModelClass<AnyDataModel>
|
|
139
|
+
|
|
140
|
+
private _props = lazy(() => {
|
|
141
|
+
const objSchema = getInternalModelClassPropsInfo(this.modelClass)
|
|
142
|
+
|
|
143
|
+
const propTypes: O.Writable<DataModelDataTypeInfoProps> = {}
|
|
144
|
+
Object.keys(objSchema).forEach((propName) => {
|
|
145
|
+
const propData = objSchema[propName]
|
|
146
|
+
|
|
147
|
+
const type = propData._typeChecker
|
|
148
|
+
|
|
149
|
+
let typeInfo: TypeInfo | undefined
|
|
150
|
+
if (type) {
|
|
151
|
+
typeInfo = getTypeInfo(type)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let hasDefault = false
|
|
155
|
+
let defaultValue: any
|
|
156
|
+
if (propData._defaultFn !== noDefaultValue) {
|
|
157
|
+
defaultValue = propData._defaultFn
|
|
158
|
+
hasDefault = true
|
|
159
|
+
} else if (propData._defaultValue !== noDefaultValue) {
|
|
160
|
+
defaultValue = propData._defaultValue
|
|
161
|
+
hasDefault = true
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
propTypes[propName] = {
|
|
165
|
+
type,
|
|
166
|
+
typeInfo,
|
|
167
|
+
hasDefault,
|
|
168
|
+
default: defaultValue,
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
return propTypes
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
get props(): DataModelDataTypeInfoProps {
|
|
175
|
+
return this._props()
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
get modelType(): string {
|
|
179
|
+
const modelInfo = modelInfoByClass.get(this.modelClass)!
|
|
180
|
+
return modelInfo.name
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
constructor(thisType: AnyStandardType, modelClass: ModelClass<AnyDataModel>) {
|
|
184
|
+
super(thisType)
|
|
185
|
+
this.modelClass = modelClass
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* @internal
|
|
191
|
+
*/
|
|
192
|
+
export function registerDataModelDataStandardTypeResolver() {
|
|
193
|
+
registerStandardTypeResolver((v) => (isDataModelClass(v) ? typesDataModelData(v) : undefined))
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* @internal
|
|
198
|
+
*/
|
|
199
|
+
export function isDataModelDataStandardType(value: unknown): boolean {
|
|
200
|
+
return typeof value === "object" || typeof value === "function"
|
|
201
|
+
? dataModelDataStandardTypes.has(value as object)
|
|
202
|
+
: false
|
|
203
|
+
}
|