mobx-keystone 1.25.0 → 2.1.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 +145 -0
- package/dist/mobx-keystone.esm.js +3627 -1540
- package/dist/mobx-keystone.esm.mjs +3627 -1540
- package/dist/mobx-keystone.umd.js +3638 -1543
- package/dist/types/actionMiddlewares/actionSerialization/dateSerializer.d.ts +1 -1
- package/dist/types/actionMiddlewares/transactionMiddleware.d.ts +1 -1
- package/dist/types/actionMiddlewares/undoMiddleware.d.ts +17 -10
- package/dist/types/dataModel/dataModelInstanceCache.d.ts +1 -0
- package/dist/types/deepChange/onDeepChange.d.ts +9 -0
- package/dist/types/parent/arrayPaths.d.ts +1 -0
- package/dist/types/parent/detach.d.ts +1 -1
- package/dist/types/parent/findChildren.d.ts +1 -1
- package/dist/types/parent/treeOrder.d.ts +1 -0
- package/dist/types/patch/applyPatches.d.ts +3 -0
- package/dist/types/redux/connectReduxDevTools.d.ts +2 -1
- package/dist/types/ref/modelRefIdIndex.d.ts +1 -0
- package/dist/types/ref/nodesById.d.ts +1 -0
- package/dist/types/ref/refIdIndex.d.ts +1 -0
- package/dist/types/snapshot/SnapshotOf.d.ts +2 -2
- package/dist/types/snapshot/applySnapshot.d.ts +1 -0
- package/dist/types/snapshot/fromSnapshot.d.ts +0 -3
- package/dist/types/standardActions/arrayActions.d.ts +1 -1
- package/dist/types/treeUtils/sandbox.d.ts +0 -4
- package/dist/types/tweaker/changeRollback.d.ts +1 -0
- package/dist/types/tweaker/tweakedChangeListeners.d.ts +1 -0
- package/dist/types/types/TypeCheckError.d.ts +1 -0
- package/dist/types/types/utility/typesRefinement.d.ts +2 -2
- package/dist/types/utils/ModelPool.d.ts +7 -1
- package/dist/types/utils/chunks.d.ts +1 -0
- package/dist/types/utils/forEachWithDelayedThrow.d.ts +1 -0
- package/dist/types/utils/index.d.ts +13 -0
- package/dist/types/utils/mapUtils.d.ts +2 -2
- package/dist/types/utils/setLike.d.ts +1 -0
- package/package.json +2 -2
- package/src/action/applyAction.ts +1 -1
- package/src/action/middleware.ts +17 -36
- package/src/action/modelFlow.ts +4 -5
- package/src/action/mutationBatch.ts +10 -10
- package/src/action/pendingActions.ts +3 -4
- package/src/actionMiddlewares/actionSerialization/actionSerialization.ts +19 -14
- package/src/actionMiddlewares/actionSerialization/applySerializedAction.ts +29 -20
- package/src/actionMiddlewares/actionSerialization/arraySerializer.ts +1 -1
- package/src/actionMiddlewares/actionSerialization/dateSerializer.ts +4 -3
- package/src/actionMiddlewares/actionSerialization/mapSerializer.ts +4 -12
- package/src/actionMiddlewares/actionSerialization/setSerializer.ts +4 -13
- package/src/actionMiddlewares/actionTrackingMiddleware.ts +11 -13
- package/src/actionMiddlewares/transactionMiddleware.ts +55 -25
- package/src/actionMiddlewares/undoMiddleware.ts +112 -59
- package/src/actionMiddlewares/utils.ts +2 -1
- package/src/computedTree/computedTree.ts +14 -3
- package/src/context/context.ts +17 -45
- package/src/dataModel/BaseDataModel.ts +20 -16
- package/src/dataModel/dataModelInstanceCache.ts +8 -0
- package/src/deepChange/onDeepChange.ts +179 -24
- package/src/frozen/Frozen.ts +50 -33
- package/src/model/BaseModel.ts +10 -13
- package/src/model/newModel.ts +21 -24
- package/src/model/utils.ts +2 -2
- package/src/modelShared/modelClassInitializer.ts +3 -2
- package/src/modelShared/modelDecorator.ts +39 -39
- package/src/modelShared/modelInfo.ts +1 -1
- package/src/modelShared/prop.ts +6 -9
- package/src/modelShared/sharedInternalModel.ts +16 -3
- package/src/parent/arrayPaths.ts +242 -0
- package/src/parent/coreObjectChildren.ts +300 -48
- package/src/parent/detach.ts +1 -1
- package/src/parent/findChildren.ts +4 -7
- package/src/parent/onChildAttachedTo.ts +157 -55
- package/src/parent/path.ts +15 -5
- package/src/parent/setParent.ts +34 -15
- package/src/parent/treeOrder.ts +53 -0
- package/src/parent/walkTree.ts +12 -101
- package/src/patch/applyPatches.ts +74 -34
- package/src/patch/emitPatch.ts +142 -26
- package/src/patch/jsonPatch.ts +5 -0
- package/src/patch/patchRecorder.ts +18 -14
- package/src/redux/connectReduxDevTools.ts +24 -18
- package/src/redux/redux.ts +5 -21
- package/src/ref/core.ts +81 -29
- package/src/ref/modelRefIdIndex.ts +131 -0
- package/src/ref/nodesById.ts +60 -0
- package/src/ref/refIdIndex.ts +209 -0
- package/src/rootStore/attachDetach.ts +27 -16
- package/src/rootStore/rootStore.ts +10 -6
- package/src/snapshot/SnapshotOf.ts +2 -2
- package/src/snapshot/applySnapshot.ts +27 -19
- package/src/snapshot/clone.ts +1 -2
- package/src/snapshot/cloneTreeValue.ts +1 -2
- package/src/snapshot/fromModelSnapshot.ts +6 -2
- package/src/snapshot/fromPlainObjectSnapshot.ts +3 -8
- package/src/snapshot/fromSnapshot.ts +2 -6
- package/src/snapshot/internal.ts +89 -19
- package/src/snapshot/onSnapshot.ts +12 -1
- package/src/snapshot/reconcileModelSnapshot.ts +6 -6
- package/src/snapshot/reconcilePlainObjectSnapshot.ts +5 -4
- package/src/standardActions/arrayActions.ts +12 -2
- package/src/standardActions/objectActions.ts +3 -2
- package/src/transforms/ImmutableDate.ts +4 -0
- package/src/transforms/asMap.ts +3 -1
- package/src/treeUtils/deepEquals.ts +15 -13
- package/src/treeUtils/draft.ts +8 -0
- package/src/treeUtils/sandbox.ts +31 -27
- package/src/tweaker/changeRollback.ts +218 -0
- package/src/tweaker/core.ts +33 -22
- package/src/tweaker/treeNodeMetadata.ts +12 -2
- package/src/tweaker/tweak.ts +183 -19
- package/src/tweaker/tweakArray.ts +176 -33
- package/src/tweaker/tweakPlainObject.ts +117 -39
- package/src/tweaker/tweakedChangeListeners.ts +61 -0
- package/src/tweaker/typeChecking.ts +25 -15
- package/src/types/TypeCheckError.ts +17 -19
- package/src/types/arrayBased/typesArray.ts +10 -11
- package/src/types/createCachedTypeCheck.ts +541 -88
- package/src/types/objectBased/typesDataModelData.ts +4 -2
- package/src/types/objectBased/typesModel.ts +4 -2
- package/src/types/objectBased/typesObject.ts +20 -16
- package/src/types/objectBased/typesRecord.ts +8 -18
- package/src/types/objectBased/typesRef.ts +2 -2
- package/src/types/primitiveBased/typesEnum.ts +4 -2
- package/src/types/primitiveBased/typesPrimitive.ts +9 -4
- package/src/types/typeCheckErrorUtils.ts +1 -0
- package/src/types/utility/typesCodecSupport.ts +97 -56
- package/src/types/utility/typesMap.ts +24 -41
- package/src/types/utility/typesRefinement.ts +3 -2
- package/src/types/utility/typesSet.ts +24 -0
- package/src/utils/ModelPool.ts +78 -22
- package/src/utils/chainFns.ts +4 -0
- package/src/utils/chunks.ts +271 -0
- package/src/utils/decorators.ts +1 -1
- package/src/utils/errorDiagnostics.ts +6 -2
- package/src/utils/forEachWithDelayedThrow.ts +83 -0
- package/src/utils/index.ts +71 -2
- package/src/utils/mapUtils.ts +3 -7
- package/src/utils/setIfDifferent.ts +3 -2
- package/src/utils/setLike.ts +134 -0
- package/src/wrappers/ArraySet.ts +5 -9
- package/src/wrappers/ObjectMap.ts +15 -11
- package/src/wrappers/asMap.ts +30 -18
- package/src/wrappers/asSet.ts +36 -12
- package/dist/types/action/modelFlowPromiseGenerator.d.ts +0 -1
- package/src/action/modelFlowPromiseGenerator.ts +0 -127
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ActionCallArgumentSerializer } from './core';
|
|
2
|
-
export declare const dateSerializer: ActionCallArgumentSerializer<Date, number>;
|
|
2
|
+
export declare const dateSerializer: ActionCallArgumentSerializer<Date, number | null>;
|
|
@@ -2,7 +2,7 @@ import { ActionMiddlewareDisposer } from '../action/middleware';
|
|
|
2
2
|
import { AnyModel } from '../model/BaseModel';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a transaction middleware, which reverts changes made by an action / child
|
|
5
|
-
* actions when the root action throws an exception
|
|
5
|
+
* actions when the root action throws an exception, restoring the values those changes replaced.
|
|
6
6
|
*
|
|
7
7
|
* @template M Model
|
|
8
8
|
* @param target Object with the root target model object (`model`) and root action name (`actionName`).
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ActionMiddlewareDisposer } from '../action/middleware';
|
|
2
|
+
import { Frozen } from '../frozen';
|
|
2
3
|
import { Path } from '../parent/pathTypes';
|
|
3
4
|
import { Patch } from '../patch';
|
|
5
|
+
import { FrozenData } from '../snapshot';
|
|
4
6
|
/**
|
|
5
7
|
* An undo/redo event without attached state.
|
|
6
8
|
*/
|
|
@@ -75,20 +77,25 @@ export interface UndoEventGroup {
|
|
|
75
77
|
readonly events: ReadonlyArray<UndoEventWithoutAttachedState>;
|
|
76
78
|
}
|
|
77
79
|
declare const UndoStore_base: import('..')._Model<unknown, {
|
|
78
|
-
undoEvents: import('..').OptionalModelProp<UndoEvent[]> & {
|
|
79
|
-
$storedValueType: UndoEvent[];
|
|
80
|
-
$storedCreationValueType: UndoEvent[] | null | undefined;
|
|
81
|
-
$typedFromSnapshotOverride: UndoEvent[] | null | undefined;
|
|
80
|
+
undoEvents: import('..').OptionalModelProp<Frozen<UndoEvent>[]> & {
|
|
81
|
+
$storedValueType: Frozen<UndoEvent>[];
|
|
82
|
+
$storedCreationValueType: Frozen<UndoEvent>[] | null | undefined;
|
|
83
|
+
$typedFromSnapshotOverride: import('..').SnapshotInOfFrozen<Frozen<UndoEvent>>[] | null | undefined;
|
|
82
84
|
};
|
|
83
|
-
redoEvents: import('..').OptionalModelProp<UndoEvent[]> & {
|
|
84
|
-
$storedValueType: UndoEvent[];
|
|
85
|
-
$storedCreationValueType: UndoEvent[] | null | undefined;
|
|
86
|
-
$typedFromSnapshotOverride: UndoEvent[] | null | undefined;
|
|
85
|
+
redoEvents: import('..').OptionalModelProp<Frozen<UndoEvent>[]> & {
|
|
86
|
+
$storedValueType: Frozen<UndoEvent>[];
|
|
87
|
+
$storedCreationValueType: Frozen<UndoEvent>[] | null | undefined;
|
|
88
|
+
$typedFromSnapshotOverride: import('..').SnapshotInOfFrozen<Frozen<UndoEvent>>[] | null | undefined;
|
|
87
89
|
};
|
|
88
|
-
},
|
|
90
|
+
}, {
|
|
91
|
+
undoEvents?: ReadonlyArray<UndoEvent | FrozenData<UndoEvent>>;
|
|
92
|
+
redoEvents?: ReadonlyArray<UndoEvent | FrozenData<UndoEvent>>;
|
|
93
|
+
}, never>;
|
|
89
94
|
/**
|
|
90
95
|
* Store model instance for undo/redo actions.
|
|
91
|
-
* Do not manipulate directly, other
|
|
96
|
+
* Do not manipulate directly, other than creating it.
|
|
97
|
+
*
|
|
98
|
+
* Events are stored as frozen data, since they never change once recorded.
|
|
92
99
|
*/
|
|
93
100
|
export declare class UndoStore extends UndoStore_base {
|
|
94
101
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,6 +11,8 @@ export declare enum DeepChangeType {
|
|
|
11
11
|
ObjectRemove = "objectRemove"
|
|
12
12
|
}
|
|
13
13
|
export interface DeepChangeBase {
|
|
14
|
+
/** Whether this notification overlaps a mutation made by a change listener. */
|
|
15
|
+
readonly isReentrant?: boolean;
|
|
14
16
|
readonly type: DeepChangeType;
|
|
15
17
|
readonly path: Path;
|
|
16
18
|
/**
|
|
@@ -78,6 +80,13 @@ export type OnDeepChangeListener = (change: DeepChange) => void;
|
|
|
78
80
|
/**
|
|
79
81
|
* Adds a listener that will be called every time a deep change is generated for the tree of the given target object.
|
|
80
82
|
* Unlike `onPatches`, this provides raw MobX change information including proper splice detection for arrays.
|
|
83
|
+
* Individual mutations notify listeners after automatic type checking succeeds and snapshots update;
|
|
84
|
+
* rejected mutations and their quiet rollbacks do not notify listeners.
|
|
85
|
+
* Listener errors do not stop delivery to other listeners. After delivery completes,
|
|
86
|
+
* a single error is rethrown unchanged and multiple errors are grouped in a MobxKeystoneAggregateError.
|
|
87
|
+
* Listeners added while callbacks for the same target are running start with the next
|
|
88
|
+
* change delivered to that target. Listeners disposed during delivery do not receive
|
|
89
|
+
* the current change if their callback has not run yet.
|
|
81
90
|
*
|
|
82
91
|
* @param subtreeRoot Subtree root object of the deep change listener.
|
|
83
92
|
* @param listener The listener function that will be called every time a change is generated for the object or its children.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Detaches a given object from a tree.
|
|
3
3
|
* If the parent is an object / model, detaching will delete the property.
|
|
4
4
|
* If the parent is an array detaching will remove the node by splicing it.
|
|
5
|
-
* If there's no parent it
|
|
5
|
+
* If there's no parent it does nothing.
|
|
6
6
|
*
|
|
7
7
|
* @param node Object to be detached.
|
|
8
8
|
*/
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param predicate Function that will be run for every child of the root object.
|
|
7
7
|
* @param [options] An optional object with the `deep` option (defaults to `false`) set to `true` to
|
|
8
8
|
* get the children deeply or `false` to get them shallowly.
|
|
9
|
-
* @returns A readonly
|
|
9
|
+
* @returns A readonly set with the matching children.
|
|
10
10
|
*/
|
|
11
11
|
export declare function findChildren<T extends object = any>(root: object, predicate: (node: object) => boolean, options?: {
|
|
12
12
|
deep?: boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Patch } from '../patch/Patch';
|
|
2
2
|
/**
|
|
3
3
|
* Applies the given patches to the given target object.
|
|
4
|
+
* Automatic type checking validates the completed batch, including nested lists.
|
|
5
|
+
* A batch that throws or is rejected is rolled back with compensating patches.
|
|
6
|
+
* Errors thrown by listeners do not roll it back.
|
|
4
7
|
*
|
|
5
8
|
* @param node Target object.
|
|
6
9
|
* @param patches List of patches to apply.
|
|
@@ -20,5 +20,6 @@ export interface ConnectReduxDevToolsOptions {
|
|
|
20
20
|
* @param remotedevConnection The result of a connect method from the remotedev package (usually the result of `remoteDev.connectViaExtension(...)`).
|
|
21
21
|
* @param target Object to use as root.
|
|
22
22
|
* @param [options] Optional options object.
|
|
23
|
+
* @returns An idempotent disposer that stops logging and unsubscribes from monitor messages.
|
|
23
24
|
*/
|
|
24
|
-
export declare function connectReduxDevTools(remotedevPackage: any, remotedevConnection: any, target: object, options?: ConnectReduxDevToolsOptions): void;
|
|
25
|
+
export declare function connectReduxDevTools(remotedevPackage: any, remotedevConnection: any, target: object, options?: ConnectReduxDevToolsOptions): () => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -34,13 +34,13 @@ export interface SnapshotInOfFrozen<F extends Frozen<any>> extends FrozenData<F[
|
|
|
34
34
|
}
|
|
35
35
|
export interface SnapshotInOfObjectMap<V> {
|
|
36
36
|
items?: {
|
|
37
|
-
[k: string]:
|
|
37
|
+
[k: string]: SnapshotInOf<V>;
|
|
38
38
|
};
|
|
39
39
|
[modelTypeKey]?: string;
|
|
40
40
|
[modelIdKey]: string;
|
|
41
41
|
}
|
|
42
42
|
export interface SnapshotInOfArraySet<V> {
|
|
43
|
-
items?:
|
|
43
|
+
items?: SnapshotInOf<V>[];
|
|
44
44
|
[modelTypeKey]?: string;
|
|
45
45
|
[modelIdKey]: string;
|
|
46
46
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SnapshotInOf, SnapshotOutOf } from './SnapshotOf';
|
|
2
2
|
/**
|
|
3
3
|
* Applies a full snapshot over an object, reconciling it with the current contents of the object.
|
|
4
|
+
* If it throws, the changes it made are rolled back (errors thrown by listeners do not roll them back).
|
|
4
5
|
*
|
|
5
6
|
* @template T Object type.
|
|
6
7
|
* @param node Target object (model object, object or array).
|
|
@@ -28,6 +28,3 @@ export declare function fromSnapshot<TType extends AnyType>(type: TType, snapsho
|
|
|
28
28
|
* @returns The deserialized object.
|
|
29
29
|
*/
|
|
30
30
|
export declare function fromSnapshot<T>(snapshot: SnapshotInOf<T> | SnapshotOutOf<T>, options?: Partial<FromSnapshotOptions>): T;
|
|
31
|
-
export declare const observableOptions: {
|
|
32
|
-
deep: boolean;
|
|
33
|
-
};
|
|
@@ -2,7 +2,7 @@ export declare const arrayActions: {
|
|
|
2
2
|
set: <T>(array: T[], index: number, value: any) => void;
|
|
3
3
|
delete: <T>(array: T[], index: number) => boolean;
|
|
4
4
|
setLength: <T>(array: T[], length: number) => void;
|
|
5
|
-
concat: <T>(array: T[], ...items: ConcatArray<T>[]) => T[];
|
|
5
|
+
concat: <T>(array: T[], ...items: (T | ConcatArray<T>)[]) => T[];
|
|
6
6
|
copyWithin: <T>(array: T[], target: number, start: number, end?: number) => T[];
|
|
7
7
|
fill: <T>(array: T[], value: T, start?: number, end?: number) => T[];
|
|
8
8
|
pop: <T>(array: T[]) => T | undefined;
|
|
@@ -42,10 +42,6 @@ export declare class SandboxManager {
|
|
|
42
42
|
* code block on a readonly node.
|
|
43
43
|
*/
|
|
44
44
|
private allowWrite;
|
|
45
|
-
/**
|
|
46
|
-
* Whether changes made in the sandbox are currently being committed to the original subtree.
|
|
47
|
-
*/
|
|
48
|
-
private isCommitting;
|
|
49
45
|
private readonly subtreeRoot;
|
|
50
46
|
/**
|
|
51
47
|
* Creates an instance of `SandboxManager`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -32,8 +32,8 @@ import { TypeInfo } from '../TypeChecker';
|
|
|
32
32
|
* @template T Base type.
|
|
33
33
|
* @param baseType Base type.
|
|
34
34
|
* @param checkFn Function that will receive the data (if it passes the base type
|
|
35
|
-
* check) and return null or
|
|
36
|
-
*
|
|
35
|
+
* check) and return null or true if there were no errors or either a TypeCheckError instance or
|
|
36
|
+
* false if there were.
|
|
37
37
|
* @returns
|
|
38
38
|
*/
|
|
39
39
|
export declare function typesRefinement<T extends AnyType>(baseType: T, checkFn: (data: TypeToData<T>) => TypeCheckError | null | boolean, typeName?: string): T;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import { AnyModel } from '../model/BaseModel';
|
|
2
|
+
/**
|
|
3
|
+
* A view of the models under a node, as they were when the pool was created.
|
|
4
|
+
* Must be released once no longer used.
|
|
5
|
+
*/
|
|
2
6
|
export declare class ModelPool {
|
|
3
|
-
private pool;
|
|
7
|
+
private readonly pool;
|
|
8
|
+
private readonly pinned;
|
|
4
9
|
constructor(root: object);
|
|
10
|
+
release(): void;
|
|
5
11
|
findModelByTypeAndId(modelType: string, modelId: string | undefined): AnyModel | undefined;
|
|
6
12
|
findModelForSnapshot(sn: any): AnyModel | undefined;
|
|
7
13
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
export declare class MobxKeystoneError extends Error {
|
|
5
5
|
constructor(msg: string);
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* A mobx-keystone error that groups several failures that happened while delivering
|
|
9
|
+
* a single notification, such as multiple patch listeners or root store hooks throwing.
|
|
10
|
+
*
|
|
11
|
+
* It is only used when more than one callback failed; a lone failure is rethrown as is.
|
|
12
|
+
*/
|
|
13
|
+
export declare class MobxKeystoneAggregateError extends MobxKeystoneError {
|
|
14
|
+
/**
|
|
15
|
+
* The values thrown by the failing callbacks, in the order they were thrown.
|
|
16
|
+
*/
|
|
17
|
+
readonly errors: readonly unknown[];
|
|
18
|
+
constructor(errors: readonly unknown[], msg: string);
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
21
|
* MobX method action decorator compatible with both legacy decorators and
|
|
9
22
|
* MobX 7's standard decorator API.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function getOrCreate<K, V
|
|
2
|
-
export declare function getOrCreate<K extends object, V
|
|
1
|
+
export declare function getOrCreate<K, V>(map: Map<K, V>, key: K, create: () => V): V;
|
|
2
|
+
export declare function getOrCreate<K extends object, V>(map: WeakMap<K, V>, key: K, create: () => V): V;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobx-keystone",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A MobX powered state management solution based on data trees with first class support for TypeScript, snapshots, patches and much more",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mobx",
|
|
@@ -78,12 +78,12 @@
|
|
|
78
78
|
"@types/node": "^26.4.1",
|
|
79
79
|
"@typescript/typescript6": "^6.0.2",
|
|
80
80
|
"@vitest/coverage-v8": "^5.0.0",
|
|
81
|
+
"expect-type": "^1.4.0",
|
|
81
82
|
"mobx-v4": "npm:mobx@^4.15.7",
|
|
82
83
|
"mobx-v5": "npm:mobx@^5.15.7",
|
|
83
84
|
"mobx-v6": "npm:mobx@^6.0.0",
|
|
84
85
|
"mobx-v7": "npm:mobx@^7.0.0",
|
|
85
86
|
"shx": "^0.4.0",
|
|
86
|
-
"spec.ts": "^1.1.3",
|
|
87
87
|
"ts-node": "^10.9.2",
|
|
88
88
|
"typedoc": "^0.28.20",
|
|
89
89
|
"typescript": "^7.0.2",
|
|
@@ -86,7 +86,7 @@ export function applyAction<TRet = any>(subtreeRoot: object, call: ActionCall):
|
|
|
86
86
|
)} could not be resolved`
|
|
87
87
|
)
|
|
88
88
|
}
|
|
89
|
-
assertTweakedObject(current,
|
|
89
|
+
assertTweakedObject(current, "resolved target", true)
|
|
90
90
|
|
|
91
91
|
if (isBuiltInAction(call.actionName)) {
|
|
92
92
|
const fnToCall = builtInActionToFunction[call.actionName] as AnyFunction | undefined
|
package/src/action/middleware.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fastGetParent } from "../parent/path"
|
|
2
2
|
import { assertTweakedObject } from "../tweaker/core"
|
|
3
|
-
import { assertIsFunction, assertIsObject,
|
|
3
|
+
import { assertIsFunction, assertIsObject, failure } from "../utils"
|
|
4
4
|
import type { ActionContext } from "./context"
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -37,33 +37,9 @@ const perObjectActionMiddlewares = new WeakMap<object, PartialActionMiddleware[]
|
|
|
37
37
|
/**
|
|
38
38
|
* @internal
|
|
39
39
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*/
|
|
44
|
-
export function forEachActionMiddleware(
|
|
45
|
-
obj: object,
|
|
46
|
-
callback: (middleware: PartialActionMiddleware) => void
|
|
47
|
-
): void {
|
|
48
|
-
// when we call a middleware we will call the middlewares of that object plus all parent objects
|
|
49
|
-
// the parent object middlewares are run last
|
|
50
|
-
|
|
51
|
-
// since an array like [a, b, c] will be called like c(b(a())) this means that we need to call
|
|
52
|
-
// the parent object ones at the end of the array
|
|
53
|
-
|
|
54
|
-
let current: unknown = obj
|
|
55
|
-
while (current) {
|
|
56
|
-
const objMwares = perObjectActionMiddlewares.get(current)
|
|
57
|
-
if (objMwares && objMwares.length > 0) {
|
|
58
|
-
objMwares.forEach(callback)
|
|
59
|
-
}
|
|
60
|
-
current = fastGetParent(current, false)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* @internal
|
|
65
|
-
*
|
|
66
|
-
* Returns the action middlewares to be run over a given object.
|
|
40
|
+
* Returns the action middlewares to be run over a given object, from the object itself to the
|
|
41
|
+
* topmost parent. Since an array like [a, b, c] will be called like c(b(a())) the caller runs
|
|
42
|
+
* them in reverse, so the parent object ones run last.
|
|
67
43
|
*
|
|
68
44
|
* @returns
|
|
69
45
|
*/
|
|
@@ -111,14 +87,19 @@ export function addActionMiddleware(mware: ActionMiddleware): ActionMiddlewareDi
|
|
|
111
87
|
|
|
112
88
|
const actualMware = { middleware, subtreeRoot, filter }
|
|
113
89
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
90
|
+
// Each action keeps the middleware arrays it collected. Update registrations by
|
|
91
|
+
// replacement so user code cannot shift or extend an in-progress chain.
|
|
92
|
+
const objMwares = perObjectActionMiddlewares.get(subtreeRoot) ?? []
|
|
93
|
+
perObjectActionMiddlewares.set(subtreeRoot, [...objMwares, actualMware])
|
|
94
|
+
|
|
95
|
+
let disposed = false
|
|
121
96
|
return () => {
|
|
122
|
-
|
|
97
|
+
if (disposed) return
|
|
98
|
+
disposed = true
|
|
99
|
+
const current = perObjectActionMiddlewares.get(subtreeRoot)!
|
|
100
|
+
perObjectActionMiddlewares.set(
|
|
101
|
+
subtreeRoot,
|
|
102
|
+
current.filter((entry) => entry !== actualMware)
|
|
103
|
+
)
|
|
123
104
|
}
|
|
124
105
|
}
|
package/src/action/modelFlow.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { O } from "ts-toolbelt"
|
|
|
2
2
|
import { failure } from "../utils"
|
|
3
3
|
import { copyFunctionMetadata, decorateWrapMethodOrField } from "../utils/decorators"
|
|
4
4
|
import { type ActionContext, ActionContextActionType, ActionContextAsyncStepType } from "./context"
|
|
5
|
-
import { promiseGenerator } from "./modelFlowPromiseGenerator"
|
|
6
5
|
import { type WrapInActionOverrideContextFn, wrapInAction } from "./wrapInAction"
|
|
7
6
|
|
|
8
7
|
const modelFlowSymbol = Symbol("modelFlow")
|
|
@@ -133,7 +132,7 @@ export function flow<R, Args extends any[]>({
|
|
|
133
132
|
function next(ret: any): void {
|
|
134
133
|
if (ret && typeof ret.then === "function") {
|
|
135
134
|
// an async iterator
|
|
136
|
-
ret.then(next, reject)
|
|
135
|
+
Promise.resolve(ret).then(next, reject).catch(reject)
|
|
137
136
|
} else if (ret.done) {
|
|
138
137
|
// done
|
|
139
138
|
wrapInAction({
|
|
@@ -154,7 +153,7 @@ export function flow<R, Args extends any[]>({
|
|
|
154
153
|
}).call(target, ret.value)
|
|
155
154
|
} else {
|
|
156
155
|
// continue
|
|
157
|
-
Promise.resolve(ret.value).then(onFulfilled, onRejected)
|
|
156
|
+
Promise.resolve(ret.value).then(onFulfilled, onRejected).catch(reject)
|
|
158
157
|
}
|
|
159
158
|
}
|
|
160
159
|
|
|
@@ -235,6 +234,6 @@ export function _async<A extends any[], R>(
|
|
|
235
234
|
* @param promise Promise.
|
|
236
235
|
* @returns
|
|
237
236
|
*/
|
|
238
|
-
export function _await<T>(promise: Promise<T>): Generator<Promise<T>, T, unknown> {
|
|
239
|
-
return
|
|
237
|
+
export function* _await<T>(promise: Promise<T>): Generator<Promise<T>, T, unknown> {
|
|
238
|
+
return (yield promise) as T
|
|
240
239
|
}
|
|
@@ -57,16 +57,16 @@ export function finishMutationBatch(): void {
|
|
|
57
57
|
if (typeof finishers === "function") {
|
|
58
58
|
finishers()
|
|
59
59
|
} else if (finishers) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
60
|
+
let lastError: { value: unknown } | undefined
|
|
61
|
+
for (let i = finishers.length - 1; i >= 0; i--) {
|
|
62
|
+
try {
|
|
63
|
+
finishers[i]()
|
|
64
|
+
} catch (value) {
|
|
65
|
+
lastError = { value }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (lastError) {
|
|
69
|
+
throw lastError.value
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { forEachWithDelayedThrow } from "../utils/forEachWithDelayedThrow"
|
|
1
2
|
import { getCurrentActionContext } from "./context"
|
|
2
3
|
import { getActionProtection } from "./protection"
|
|
3
4
|
|
|
@@ -32,11 +33,9 @@ export function tryRunPendingActions(): void {
|
|
|
32
33
|
pendingActionsRunning = true
|
|
33
34
|
|
|
34
35
|
try {
|
|
35
|
-
|
|
36
|
-
const nextAction = pendingActions.shift()!
|
|
37
|
-
nextAction()
|
|
38
|
-
}
|
|
36
|
+
forEachWithDelayedThrow(pendingActions, (nextAction) => nextAction())
|
|
39
37
|
} finally {
|
|
38
|
+
pendingActions.length = 0
|
|
40
39
|
pendingActionsRunning = false
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -2,6 +2,7 @@ import type { O } from "ts-toolbelt"
|
|
|
2
2
|
import type { ActionCall } from "../../action/applyAction"
|
|
3
3
|
import { assertTweakedObject } from "../../tweaker/core"
|
|
4
4
|
import { failure, isJSONPrimitive, isPlainObject } from "../../utils"
|
|
5
|
+
import { getSafeErrorValuePreview } from "../../utils/errorDiagnostics"
|
|
5
6
|
import type { JSONPrimitiveValue } from "../../utils/types"
|
|
6
7
|
import { arraySerializer } from "./arraySerializer"
|
|
7
8
|
import { type ActionCallArgumentSerializer, cannotSerialize } from "./core"
|
|
@@ -13,7 +14,7 @@ import { plainObjectSerializer } from "./plainObjectSerializer"
|
|
|
13
14
|
import { primitiveSerializer } from "./primitiveSerializer"
|
|
14
15
|
import { setSerializer } from "./setSerializer"
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
let serializersArray: ActionCallArgumentSerializer<any, any>[] = []
|
|
17
18
|
const serializersMap = new Map<string, ActionCallArgumentSerializer<any, any>>()
|
|
18
19
|
|
|
19
20
|
/**
|
|
@@ -32,19 +33,22 @@ export function registerActionCallArgumentSerializer(
|
|
|
32
33
|
if (serializersArray.includes(serializer)) {
|
|
33
34
|
throw failure("action call argument serializer already registered")
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
const id = serializer.id
|
|
37
|
+
if (serializersMap.has(id)) {
|
|
36
38
|
throw failure(`action call argument serializer with id '${serializer.id}' already registered`)
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
serializersArray
|
|
40
|
-
serializersMap.set(
|
|
41
|
+
serializersArray = [serializer, ...serializersArray]
|
|
42
|
+
serializersMap.set(id, serializer)
|
|
41
43
|
|
|
44
|
+
let disposed = false
|
|
42
45
|
return () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
serializersArray.splice(index, 1)
|
|
46
|
+
if (disposed) {
|
|
47
|
+
return
|
|
46
48
|
}
|
|
47
|
-
|
|
49
|
+
disposed = true
|
|
50
|
+
serializersArray = serializersArray.filter((entry) => entry !== serializer)
|
|
51
|
+
serializersMap.delete(id)
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -106,13 +110,12 @@ export function serializeActionCallArgument(
|
|
|
106
110
|
return argValue
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
const origValue = argValue
|
|
110
|
-
|
|
111
113
|
const serialize = (v: any) => serializeActionCallArgument(v, targetRoot)
|
|
112
114
|
|
|
113
115
|
// try serializers
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
const serializers = serializersArray
|
|
117
|
+
for (let i = 0; i < serializers.length; i++) {
|
|
118
|
+
const serializer = serializers[i]
|
|
116
119
|
const serializedValue = serializer.serialize(argValue, serialize, targetRoot)
|
|
117
120
|
if (serializedValue !== cannotSerialize) {
|
|
118
121
|
return {
|
|
@@ -122,7 +125,9 @@ export function serializeActionCallArgument(
|
|
|
122
125
|
}
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
throw failure(
|
|
128
|
+
throw failure(
|
|
129
|
+
`serializeActionCallArgument could not serialize the given value: ${getSafeErrorValuePreview(argValue)}`
|
|
130
|
+
)
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
/**
|
|
@@ -150,7 +155,7 @@ export function serializeActionCall(
|
|
|
150
155
|
return {
|
|
151
156
|
...actionCall,
|
|
152
157
|
serialized: true,
|
|
153
|
-
args: actionCall.args
|
|
158
|
+
args: Array.from(actionCall.args, serialize),
|
|
154
159
|
}
|
|
155
160
|
}
|
|
156
161
|
|