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,70 +1,70 @@
|
|
|
1
|
-
import { AnyModel } from "../model/BaseModel"
|
|
2
|
-
import { getModelIdPropertyName } from "../model/getModelMetadata"
|
|
3
|
-
import { ModelConstructorOptions } from "../model/ModelConstructorOptions"
|
|
4
|
-
import { modelTypeKey } from "../model/metadata"
|
|
5
|
-
import { getModelOrSnapshotTypeAndId, getSnapshotModelType } from "../model/utils"
|
|
6
|
-
import { ModelClass } from "../modelShared/BaseModelShared"
|
|
7
|
-
import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
|
|
8
|
-
import { withErrorModelTrailEntry } from "../utils/errorDiagnostics"
|
|
9
|
-
import { FromSnapshotContext, registerSnapshotter } from "./fromSnapshot"
|
|
10
|
-
import { SnapshotInOfModel } from "./SnapshotOf"
|
|
11
|
-
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
12
|
-
import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
|
|
13
|
-
|
|
14
|
-
function fromModelSnapshot(sn: SnapshotInOfModel<AnyModel>, ctx: FromSnapshotContext): AnyModel {
|
|
15
|
-
const type = sn[modelTypeKey]
|
|
16
|
-
|
|
17
|
-
if (!type) {
|
|
18
|
-
throw new SnapshotProcessingError({
|
|
19
|
-
message: `a model snapshot must contain a type key (${modelTypeKey}), but none was found`,
|
|
20
|
-
actualSnapshot: sn,
|
|
21
|
-
})
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const modelInfo = getModelInfoForName(type)
|
|
25
|
-
if (!modelInfo) {
|
|
26
|
-
throw new SnapshotProcessingError({
|
|
27
|
-
message: getModelNotRegisteredErrorMessage(type),
|
|
28
|
-
actualSnapshot: sn,
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const modelIdPropertyName = getModelIdPropertyName(modelInfo.class as ModelClass<AnyModel>)
|
|
33
|
-
if (modelIdPropertyName && sn[modelIdPropertyName] === undefined) {
|
|
34
|
-
throw new SnapshotProcessingError({
|
|
35
|
-
message: `a model snapshot of type '${type}' must contain an id key (${modelIdPropertyName}), but none was found`,
|
|
36
|
-
actualSnapshot: sn,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const modelTypeAndId = getModelOrSnapshotTypeAndId(sn)
|
|
41
|
-
const modelId = modelTypeAndId?.modelId
|
|
42
|
-
|
|
43
|
-
return withErrorModelTrailEntry(type, modelId, () => {
|
|
44
|
-
return new (modelInfo.class as any)(undefined, {
|
|
45
|
-
snapshotInitialData: {
|
|
46
|
-
unprocessedSnapshot: sn,
|
|
47
|
-
unprocessedModelType:
|
|
48
|
-
typeof ctx.untypedSnapshot === "object" &&
|
|
49
|
-
ctx.untypedSnapshot &&
|
|
50
|
-
modelTypeKey in ctx.untypedSnapshot
|
|
51
|
-
? ctx.untypedSnapshot[modelTypeKey]
|
|
52
|
-
: undefined,
|
|
53
|
-
snapshotToInitialData: ctx.snapshotToInitialData,
|
|
54
|
-
},
|
|
55
|
-
generateNewIds: ctx.options.generateNewIds,
|
|
56
|
-
} satisfies ModelConstructorOptions)
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @internal
|
|
62
|
-
*/
|
|
63
|
-
export function registerFromModelSnapshotter() {
|
|
64
|
-
registerSnapshotter(SnapshotterAndReconcilerPriority.Model, (sn, ctx) => {
|
|
65
|
-
if (getSnapshotModelType(sn) !== undefined) {
|
|
66
|
-
return fromModelSnapshot(sn, ctx)
|
|
67
|
-
}
|
|
68
|
-
return undefined
|
|
69
|
-
})
|
|
70
|
-
}
|
|
1
|
+
import type { AnyModel } from "../model/BaseModel"
|
|
2
|
+
import { getModelIdPropertyName } from "../model/getModelMetadata"
|
|
3
|
+
import type { ModelConstructorOptions } from "../model/ModelConstructorOptions"
|
|
4
|
+
import { modelTypeKey } from "../model/metadata"
|
|
5
|
+
import { getModelOrSnapshotTypeAndId, getSnapshotModelType } from "../model/utils"
|
|
6
|
+
import type { ModelClass } from "../modelShared/BaseModelShared"
|
|
7
|
+
import { getModelInfoForName, getModelNotRegisteredErrorMessage } from "../modelShared/modelInfo"
|
|
8
|
+
import { withErrorModelTrailEntry } from "../utils/errorDiagnostics"
|
|
9
|
+
import { type FromSnapshotContext, registerSnapshotter } from "./fromSnapshot"
|
|
10
|
+
import type { SnapshotInOfModel } from "./SnapshotOf"
|
|
11
|
+
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
12
|
+
import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
|
|
13
|
+
|
|
14
|
+
function fromModelSnapshot(sn: SnapshotInOfModel<AnyModel>, ctx: FromSnapshotContext): AnyModel {
|
|
15
|
+
const type = sn[modelTypeKey]
|
|
16
|
+
|
|
17
|
+
if (!type) {
|
|
18
|
+
throw new SnapshotProcessingError({
|
|
19
|
+
message: `a model snapshot must contain a type key (${modelTypeKey}), but none was found`,
|
|
20
|
+
actualSnapshot: sn,
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const modelInfo = getModelInfoForName(type)
|
|
25
|
+
if (!modelInfo) {
|
|
26
|
+
throw new SnapshotProcessingError({
|
|
27
|
+
message: getModelNotRegisteredErrorMessage(type),
|
|
28
|
+
actualSnapshot: sn,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const modelIdPropertyName = getModelIdPropertyName(modelInfo.class as ModelClass<AnyModel>)
|
|
33
|
+
if (modelIdPropertyName && sn[modelIdPropertyName] === undefined) {
|
|
34
|
+
throw new SnapshotProcessingError({
|
|
35
|
+
message: `a model snapshot of type '${type}' must contain an id key (${modelIdPropertyName}), but none was found`,
|
|
36
|
+
actualSnapshot: sn,
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const modelTypeAndId = getModelOrSnapshotTypeAndId(sn)
|
|
41
|
+
const modelId = modelTypeAndId?.modelId
|
|
42
|
+
|
|
43
|
+
return withErrorModelTrailEntry(type, modelId, () => {
|
|
44
|
+
return new (modelInfo.class as any)(undefined, {
|
|
45
|
+
snapshotInitialData: {
|
|
46
|
+
unprocessedSnapshot: sn,
|
|
47
|
+
unprocessedModelType:
|
|
48
|
+
typeof ctx.untypedSnapshot === "object" &&
|
|
49
|
+
ctx.untypedSnapshot &&
|
|
50
|
+
modelTypeKey in ctx.untypedSnapshot
|
|
51
|
+
? ctx.untypedSnapshot[modelTypeKey]
|
|
52
|
+
: undefined,
|
|
53
|
+
snapshotToInitialData: ctx.snapshotToInitialData,
|
|
54
|
+
},
|
|
55
|
+
generateNewIds: ctx.options.generateNewIds,
|
|
56
|
+
} satisfies ModelConstructorOptions)
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export function registerFromModelSnapshotter() {
|
|
64
|
+
registerSnapshotter(SnapshotterAndReconcilerPriority.Model, (sn, ctx) => {
|
|
65
|
+
if (getSnapshotModelType(sn) !== undefined) {
|
|
66
|
+
return fromModelSnapshot(sn, ctx)
|
|
67
|
+
}
|
|
68
|
+
return undefined
|
|
69
|
+
})
|
|
70
|
+
}
|
|
@@ -1,42 +1,47 @@
|
|
|
1
|
-
import { observable
|
|
2
|
-
import { tweakPlainObject } from "../tweaker/tweakPlainObject"
|
|
3
|
-
import { isPlainObject } from "../utils"
|
|
4
|
-
import { withErrorPathSegment } from "../utils/errorDiagnostics"
|
|
5
|
-
import {
|
|
6
|
-
FromSnapshotContext,
|
|
7
|
-
internalFromSnapshot,
|
|
8
|
-
observableOptions,
|
|
9
|
-
registerSnapshotter,
|
|
10
|
-
} from "./fromSnapshot"
|
|
11
|
-
import { SnapshotInOfObject } from "./SnapshotOf"
|
|
12
|
-
import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
|
|
13
|
-
|
|
14
|
-
function fromPlainObjectSnapshot(sn: SnapshotInOfObject<any>, ctx: FromSnapshotContext): object {
|
|
15
|
-
const plainObj =
|
|
16
|
-
|
|
17
|
-
const snKeys = Object.keys(sn)
|
|
18
|
-
const snKeysLen = snKeys.length
|
|
19
|
-
for (let i = 0; i < snKeysLen; i++) {
|
|
20
|
-
const k = snKeys[i]
|
|
21
|
-
const v = sn[k]
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
k,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
import { observable } from "mobx"
|
|
2
|
+
import { tweakPlainObject } from "../tweaker/tweakPlainObject"
|
|
3
|
+
import { isPlainObject, setOwnProp } from "../utils"
|
|
4
|
+
import { withErrorPathSegment } from "../utils/errorDiagnostics"
|
|
5
|
+
import {
|
|
6
|
+
type FromSnapshotContext,
|
|
7
|
+
internalFromSnapshot,
|
|
8
|
+
observableOptions,
|
|
9
|
+
registerSnapshotter,
|
|
10
|
+
} from "./fromSnapshot"
|
|
11
|
+
import type { SnapshotInOfObject } from "./SnapshotOf"
|
|
12
|
+
import { SnapshotterAndReconcilerPriority } from "./SnapshotterAndReconcilerPriority"
|
|
13
|
+
|
|
14
|
+
function fromPlainObjectSnapshot(sn: SnapshotInOfObject<any>, ctx: FromSnapshotContext): object {
|
|
15
|
+
const plainObj: Record<string, unknown> = {}
|
|
16
|
+
|
|
17
|
+
const snKeys = Object.keys(sn)
|
|
18
|
+
const snKeysLen = snKeys.length
|
|
19
|
+
for (let i = 0; i < snKeysLen; i++) {
|
|
20
|
+
const k = snKeys[i]
|
|
21
|
+
const v = sn[k]
|
|
22
|
+
setOwnProp(
|
|
23
|
+
plainObj,
|
|
24
|
+
k,
|
|
25
|
+
withErrorPathSegment(k, () => internalFromSnapshot(v, ctx))
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
return tweakPlainObject(
|
|
29
|
+
observable.object(plainObj, undefined, observableOptions),
|
|
30
|
+
undefined,
|
|
31
|
+
undefined,
|
|
32
|
+
true,
|
|
33
|
+
false
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
40
|
+
export function registerFromPlainObjectSnapshotter() {
|
|
41
|
+
registerSnapshotter(SnapshotterAndReconcilerPriority.PlainObject, (sn, ctx) => {
|
|
42
|
+
if (isPlainObject(sn)) {
|
|
43
|
+
return fromPlainObjectSnapshot(sn, ctx)
|
|
44
|
+
}
|
|
45
|
+
return undefined
|
|
46
|
+
})
|
|
47
|
+
}
|
|
@@ -1,198 +1,198 @@
|
|
|
1
|
-
import { action, observable
|
|
2
|
-
import type { AnyModel } from "../model/BaseModel"
|
|
3
|
-
import { isReservedModelKey } from "../model/metadata"
|
|
4
|
-
import { resolveStandardTypeNoThrow, resolveTypeChecker } from "../types/resolveTypeChecker"
|
|
5
|
-
import type { AnyType, TypeToData, TypeToSnapshotIn } from "../types/schemas"
|
|
6
|
-
import { isLateTypeChecker, TypeChecker } from "../types/TypeChecker"
|
|
7
|
-
import { resolveCodecSupport } from "../types/utility/typesCodec"
|
|
8
|
-
import { isMap, isPrimitive, isSet } from "../utils"
|
|
9
|
-
import { runWithErrorDiagnosticsContext, withErrorPathSegment } from "../utils/errorDiagnostics"
|
|
10
|
-
import { registerDefaultSnapshotters } from "./registerDefaultSnapshotters"
|
|
11
|
-
import type { SnapshotInOf, SnapshotInOfModel, SnapshotOutOf } from "./SnapshotOf"
|
|
12
|
-
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @internal
|
|
16
|
-
*/
|
|
17
|
-
export type Snapshotter = (sn: any, ctx: FromSnapshotContext) => any
|
|
18
|
-
|
|
19
|
-
const snapshotters: { priority: number; snapshotter: Snapshotter }[] = []
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @internal
|
|
23
|
-
*/
|
|
24
|
-
export function registerSnapshotter(priority: number, snapshotter: Snapshotter): void {
|
|
25
|
-
snapshotters.push({ priority, snapshotter })
|
|
26
|
-
snapshotters.sort((a, b) => a.priority - b.priority)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* From snapshot options.
|
|
31
|
-
*/
|
|
32
|
-
export interface FromSnapshotOptions {
|
|
33
|
-
/**
|
|
34
|
-
* Pass `true` to generate new internal ids for models rather than reusing them. (Default is `false`)
|
|
35
|
-
*/
|
|
36
|
-
generateNewIds: boolean
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* @internal
|
|
41
|
-
*/
|
|
42
|
-
export interface FromSnapshotContext {
|
|
43
|
-
options: FromSnapshotOptions
|
|
44
|
-
snapshotToInitialData: (processedSn: SnapshotInOfModel<AnyModel>) => any
|
|
45
|
-
untypedSnapshot: unknown
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Given a type deserializes a data structure from its snapshot form.
|
|
50
|
-
*
|
|
51
|
-
* @template TType Object type.
|
|
52
|
-
* @param type Type.
|
|
53
|
-
* @param snapshot Snapshot, even if a primitive.
|
|
54
|
-
* @param options Options.
|
|
55
|
-
* @returns The deserialized object.
|
|
56
|
-
*/
|
|
57
|
-
export function fromSnapshot<TType extends AnyType>(
|
|
58
|
-
type: TType,
|
|
59
|
-
snapshot: TypeToSnapshotIn<TType>,
|
|
60
|
-
options?: Partial<FromSnapshotOptions>
|
|
61
|
-
): TypeToData<TType>
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Deserializes a data structure from its snapshot form.
|
|
65
|
-
*
|
|
66
|
-
* @template T Object type.
|
|
67
|
-
* @param snapshot Snapshot, even if a primitive.
|
|
68
|
-
* @param options Options.
|
|
69
|
-
* @returns The deserialized object.
|
|
70
|
-
*/
|
|
71
|
-
export function fromSnapshot<T>(
|
|
72
|
-
snapshot: SnapshotInOf<T> | SnapshotOutOf<T>,
|
|
73
|
-
options?: Partial<FromSnapshotOptions>
|
|
74
|
-
): T
|
|
75
|
-
|
|
76
|
-
export function fromSnapshot<T>(arg1: any, arg2: any, arg3?: any): T {
|
|
77
|
-
return runWithErrorDiagnosticsContext(() => {
|
|
78
|
-
let snapshot: any
|
|
79
|
-
let unprocessedSnapshot: unknown
|
|
80
|
-
let options: Partial<FromSnapshotOptions> | undefined
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
return initialData
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
export const observableOptions = {
|
|
197
|
-
deep: false,
|
|
198
|
-
}
|
|
1
|
+
import { action, observable } from "mobx"
|
|
2
|
+
import type { AnyModel } from "../model/BaseModel"
|
|
3
|
+
import { isReservedModelKey } from "../model/metadata"
|
|
4
|
+
import { resolveStandardTypeNoThrow, resolveTypeChecker } from "../types/resolveTypeChecker"
|
|
5
|
+
import type { AnyType, TypeToData, TypeToSnapshotIn } from "../types/schemas"
|
|
6
|
+
import { isLateTypeChecker, TypeChecker } from "../types/TypeChecker"
|
|
7
|
+
import { resolveCodecSupport } from "../types/utility/typesCodec"
|
|
8
|
+
import { isMap, isPrimitive, isSet, setOwnProp } from "../utils"
|
|
9
|
+
import { runWithErrorDiagnosticsContext, withErrorPathSegment } from "../utils/errorDiagnostics"
|
|
10
|
+
import { registerDefaultSnapshotters } from "./registerDefaultSnapshotters"
|
|
11
|
+
import type { SnapshotInOf, SnapshotInOfModel, SnapshotOutOf } from "./SnapshotOf"
|
|
12
|
+
import { SnapshotProcessingError } from "./SnapshotProcessingError"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export type Snapshotter = (sn: any, ctx: FromSnapshotContext) => any
|
|
18
|
+
|
|
19
|
+
const snapshotters: { priority: number; snapshotter: Snapshotter }[] = []
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function registerSnapshotter(priority: number, snapshotter: Snapshotter): void {
|
|
25
|
+
snapshotters.push({ priority, snapshotter })
|
|
26
|
+
snapshotters.sort((a, b) => a.priority - b.priority)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* From snapshot options.
|
|
31
|
+
*/
|
|
32
|
+
export interface FromSnapshotOptions {
|
|
33
|
+
/**
|
|
34
|
+
* Pass `true` to generate new internal ids for models rather than reusing them. (Default is `false`)
|
|
35
|
+
*/
|
|
36
|
+
generateNewIds: boolean
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @internal
|
|
41
|
+
*/
|
|
42
|
+
export interface FromSnapshotContext {
|
|
43
|
+
options: FromSnapshotOptions
|
|
44
|
+
snapshotToInitialData: (processedSn: SnapshotInOfModel<AnyModel>) => any
|
|
45
|
+
untypedSnapshot: unknown
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Given a type deserializes a data structure from its snapshot form.
|
|
50
|
+
*
|
|
51
|
+
* @template TType Object type.
|
|
52
|
+
* @param type Type.
|
|
53
|
+
* @param snapshot Snapshot, even if a primitive.
|
|
54
|
+
* @param options Options.
|
|
55
|
+
* @returns The deserialized object.
|
|
56
|
+
*/
|
|
57
|
+
export function fromSnapshot<TType extends AnyType>(
|
|
58
|
+
type: TType,
|
|
59
|
+
snapshot: TypeToSnapshotIn<TType>,
|
|
60
|
+
options?: Partial<FromSnapshotOptions>
|
|
61
|
+
): TypeToData<TType>
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Deserializes a data structure from its snapshot form.
|
|
65
|
+
*
|
|
66
|
+
* @template T Object type.
|
|
67
|
+
* @param snapshot Snapshot, even if a primitive.
|
|
68
|
+
* @param options Options.
|
|
69
|
+
* @returns The deserialized object.
|
|
70
|
+
*/
|
|
71
|
+
export function fromSnapshot<T>(
|
|
72
|
+
snapshot: SnapshotInOf<T> | SnapshotOutOf<T>,
|
|
73
|
+
options?: Partial<FromSnapshotOptions>
|
|
74
|
+
): T
|
|
75
|
+
|
|
76
|
+
export function fromSnapshot<T>(arg1: any, arg2: any, arg3?: any): T {
|
|
77
|
+
return runWithErrorDiagnosticsContext(() => {
|
|
78
|
+
let snapshot: any
|
|
79
|
+
let unprocessedSnapshot: unknown
|
|
80
|
+
let options: Partial<FromSnapshotOptions> | undefined
|
|
81
|
+
// biome-ignore lint/complexity/noArguments: overload resolution needs the real call arity to distinguish omitted snapshots from omitted type args.
|
|
82
|
+
const standardType = arguments.length >= 2 ? resolveStandardTypeNoThrow(arg1) : undefined
|
|
83
|
+
|
|
84
|
+
if (isLateTypeChecker(arg1) || arg1 instanceof TypeChecker || standardType) {
|
|
85
|
+
const resolvedType = standardType ?? arg1
|
|
86
|
+
const codecSupport = resolveCodecSupport(resolvedType)
|
|
87
|
+
|
|
88
|
+
if (codecSupport.hasCodec) {
|
|
89
|
+
unprocessedSnapshot = arg2
|
|
90
|
+
snapshot = resolveTypeChecker(codecSupport.storedType).fromSnapshotProcessor(
|
|
91
|
+
unprocessedSnapshot
|
|
92
|
+
)
|
|
93
|
+
options = arg3
|
|
94
|
+
const storedValue = fromSnapshotAction(snapshot, unprocessedSnapshot, options)
|
|
95
|
+
return codecSupport.adapter.toRuntime(storedValue)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const typeChecker = resolveTypeChecker(resolvedType)
|
|
99
|
+
unprocessedSnapshot = arg2
|
|
100
|
+
snapshot = typeChecker.fromSnapshotProcessor(unprocessedSnapshot)
|
|
101
|
+
options = arg3
|
|
102
|
+
} else {
|
|
103
|
+
snapshot = arg1
|
|
104
|
+
unprocessedSnapshot = snapshot
|
|
105
|
+
options = arg2
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return fromSnapshotAction(snapshot, unprocessedSnapshot, options)
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const fromSnapshotAction = action(
|
|
113
|
+
"fromSnapshot",
|
|
114
|
+
<T>(
|
|
115
|
+
snapshot: SnapshotInOf<T>,
|
|
116
|
+
unprocessedSnapshot: unknown,
|
|
117
|
+
options: Partial<FromSnapshotOptions> | undefined
|
|
118
|
+
): T => {
|
|
119
|
+
const opts = {
|
|
120
|
+
generateNewIds: false,
|
|
121
|
+
overrideRootModelId: undefined,
|
|
122
|
+
...options,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const ctx: Partial<FromSnapshotContext> = {
|
|
126
|
+
options: opts,
|
|
127
|
+
untypedSnapshot: unprocessedSnapshot,
|
|
128
|
+
}
|
|
129
|
+
ctx.snapshotToInitialData = snapshotToInitialData.bind(undefined, ctx as FromSnapshotContext)
|
|
130
|
+
|
|
131
|
+
return internalFromSnapshot<T>(snapshot, ctx as FromSnapshotContext)
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @internal
|
|
137
|
+
*/
|
|
138
|
+
export function internalFromSnapshot<T>(
|
|
139
|
+
sn: SnapshotInOf<T> | SnapshotOutOf<T>,
|
|
140
|
+
ctx: FromSnapshotContext
|
|
141
|
+
): T {
|
|
142
|
+
if (isPrimitive(sn)) {
|
|
143
|
+
return sn as any
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
registerDefaultSnapshotters()
|
|
147
|
+
|
|
148
|
+
const snapshotterLen = snapshotters.length
|
|
149
|
+
for (let i = 0; i < snapshotterLen; i++) {
|
|
150
|
+
const { snapshotter } = snapshotters[i]
|
|
151
|
+
const ret = snapshotter(sn, ctx)
|
|
152
|
+
if (ret !== undefined) {
|
|
153
|
+
return ret
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (isMap(sn)) {
|
|
158
|
+
throw new SnapshotProcessingError({
|
|
159
|
+
message: "a snapshot must not contain maps",
|
|
160
|
+
actualSnapshot: sn,
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (isSet(sn)) {
|
|
165
|
+
throw new SnapshotProcessingError({
|
|
166
|
+
message: "a snapshot must not contain sets",
|
|
167
|
+
actualSnapshot: sn,
|
|
168
|
+
})
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
throw new SnapshotProcessingError({
|
|
172
|
+
message: "unsupported snapshot",
|
|
173
|
+
actualSnapshot: sn,
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function snapshotToInitialData(
|
|
178
|
+
ctx: FromSnapshotContext,
|
|
179
|
+
processedSn: SnapshotInOfModel<AnyModel>
|
|
180
|
+
): any {
|
|
181
|
+
const initialData: Record<string, unknown> = {}
|
|
182
|
+
|
|
183
|
+
const processedSnKeys = Object.keys(processedSn)
|
|
184
|
+
const processedSnKeysLen = processedSnKeys.length
|
|
185
|
+
for (let i = 0; i < processedSnKeysLen; i++) {
|
|
186
|
+
const k = processedSnKeys[i]
|
|
187
|
+
if (!isReservedModelKey(k)) {
|
|
188
|
+
const v = processedSn[k]
|
|
189
|
+
const snapshotValue = withErrorPathSegment(k, () => internalFromSnapshot(v, ctx))
|
|
190
|
+
setOwnProp(initialData, k, snapshotValue)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return observable.object(initialData, undefined, observableOptions)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export const observableOptions = {
|
|
197
|
+
deep: false,
|
|
198
|
+
}
|