@jbrowse/mobx-state-tree 5.10.7 → 5.11.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/dist/index.d.ts +20 -1
- package/dist/mobx-state-tree.cjs +179 -132
- package/dist/mobx-state-tree.cjs.map +1 -1
- package/dist/mobx-state-tree.mjs +179 -133
- package/dist/mobx-state-tree.mjs.map +1 -1
- package/package.json +1 -1
package/dist/mobx-state-tree.cjs
CHANGED
|
@@ -980,7 +980,7 @@ class BaseNode {
|
|
|
980
980
|
if (this._escapedSubpath === undefined) {
|
|
981
981
|
this._escapedSubpath = !this._subpath ? "" : escapeJsonPath(this._subpath);
|
|
982
982
|
}
|
|
983
|
-
return
|
|
983
|
+
return `${this.parent.getEscapedPath(reportObserved)}/${this._escapedSubpath}`;
|
|
984
984
|
}
|
|
985
985
|
get isRoot() {
|
|
986
986
|
return this.parent === null;
|
|
@@ -1214,9 +1214,8 @@ class ObjectNode extends BaseNode {
|
|
|
1214
1214
|
// uninitialized parent
|
|
1215
1215
|
// this is done to avoid traversing the whole tree to the root when using
|
|
1216
1216
|
// the same reference again
|
|
1217
|
-
while (parent
|
|
1218
|
-
|
|
1219
|
-
0 /* ObservableInstanceLifecycle.UNINITIALIZED */) {
|
|
1217
|
+
while (parent?._observableInstanceState ===
|
|
1218
|
+
0 /* ObservableInstanceLifecycle.UNINITIALIZED */) {
|
|
1220
1219
|
parentChain.unshift(parent);
|
|
1221
1220
|
parent = parent.parent;
|
|
1222
1221
|
}
|
|
@@ -1404,12 +1403,9 @@ class ObjectNode extends BaseNode {
|
|
|
1404
1403
|
actionContext = actionContext.parentActionEvent;
|
|
1405
1404
|
}
|
|
1406
1405
|
let actionFullPath = "";
|
|
1407
|
-
if (actionContext
|
|
1406
|
+
if (actionContext?.name != null) {
|
|
1408
1407
|
// try to use the context, and if it not available use the node one
|
|
1409
|
-
const actionPath = (actionContext &&
|
|
1410
|
-
actionContext.context &&
|
|
1411
|
-
getPath(actionContext.context)) ||
|
|
1412
|
-
escapedPath;
|
|
1408
|
+
const actionPath = (actionContext.context && getPath(actionContext.context)) || escapedPath;
|
|
1413
1409
|
actionFullPath = `${actionPath}.${actionContext.name}()`;
|
|
1414
1410
|
}
|
|
1415
1411
|
return `You are trying to read or write to an object that is no longer part of a state tree. (Object type: '${this.type.name}', Path upon death: '${escapedPath}', Subpath: '${subpath}', Action: '${actionFullPath}'). Either detach nodes first, or don't use objects after removing / replacing them in the tree.`;
|
|
@@ -1556,9 +1552,10 @@ class ObjectNode extends BaseNode {
|
|
|
1556
1552
|
}
|
|
1557
1553
|
emitPatch(basePatch, source) {
|
|
1558
1554
|
if (this._internalEventsHasSubscribers("patch" /* InternalEvents.Patch */)) {
|
|
1559
|
-
const localizedPatch =
|
|
1560
|
-
|
|
1561
|
-
|
|
1555
|
+
const localizedPatch = {
|
|
1556
|
+
...basePatch,
|
|
1557
|
+
path: `${source.path.substr(this.path.length)}/${basePatch.path}` // calculate the relative path of the patch
|
|
1558
|
+
};
|
|
1562
1559
|
const [patch, reversePatch] = splitPatch(localizedPatch);
|
|
1563
1560
|
this._internalEventsEmit("patch" /* InternalEvents.Patch */, patch, reversePatch);
|
|
1564
1561
|
}
|
|
@@ -1887,7 +1884,7 @@ class SimpleType extends BaseType {
|
|
|
1887
1884
|
* @returns `true` if the value is a type.
|
|
1888
1885
|
*/
|
|
1889
1886
|
function isType(value) {
|
|
1890
|
-
return typeof value === "object" && value
|
|
1887
|
+
return typeof value === "object" && value?.isType === true;
|
|
1891
1888
|
}
|
|
1892
1889
|
/**
|
|
1893
1890
|
* @internal
|
|
@@ -2039,8 +2036,8 @@ function createActionTrackingMiddleware2(middlewareHooks) {
|
|
|
2039
2036
|
const newCall = {
|
|
2040
2037
|
...call,
|
|
2041
2038
|
// make a shallow copy of the parent action env
|
|
2042
|
-
env: parentRunningAction
|
|
2043
|
-
parentCall: parentRunningAction
|
|
2039
|
+
env: parentRunningAction?.call.env,
|
|
2040
|
+
parentCall: parentRunningAction?.call
|
|
2044
2041
|
};
|
|
2045
2042
|
const passesFilter = !middlewareHooks.filter || middlewareHooks.filter(newCall);
|
|
2046
2043
|
const hooks = passesFilter ? middlewareHooks : undefined;
|
|
@@ -2121,8 +2118,7 @@ function serializeArgument(node, actionName, index, arg) {
|
|
|
2121
2118
|
return serializeTheUnserializable(`[function]`);
|
|
2122
2119
|
}
|
|
2123
2120
|
if (typeof arg === "object" && !isPlainObject(arg) && !isArray(arg)) {
|
|
2124
|
-
return serializeTheUnserializable(`[object ${
|
|
2125
|
-
"Complex Object"}]`);
|
|
2121
|
+
return serializeTheUnserializable(`[object ${arg?.constructor?.name || "Complex Object"}]`);
|
|
2126
2122
|
}
|
|
2127
2123
|
try {
|
|
2128
2124
|
// Check if serializable, cycle free etc...
|
|
@@ -2131,7 +2127,7 @@ function serializeArgument(node, actionName, index, arg) {
|
|
|
2131
2127
|
return arg;
|
|
2132
2128
|
}
|
|
2133
2129
|
catch (e) {
|
|
2134
|
-
return serializeTheUnserializable(
|
|
2130
|
+
return serializeTheUnserializable(`${e}`);
|
|
2135
2131
|
}
|
|
2136
2132
|
}
|
|
2137
2133
|
function deserializeArgument(adm, value) {
|
|
@@ -2491,7 +2487,7 @@ function runMiddleWares(node, baseCall, originalFn) {
|
|
|
2491
2487
|
let result = null;
|
|
2492
2488
|
function runNextMiddleware(call) {
|
|
2493
2489
|
const middleware = middlewares.getNextMiddleware();
|
|
2494
|
-
const handler = middleware
|
|
2490
|
+
const handler = middleware?.handler;
|
|
2495
2491
|
if (!handler) {
|
|
2496
2492
|
return mobx.action(originalFn)(...call.args);
|
|
2497
2493
|
}
|
|
@@ -2599,7 +2595,7 @@ function safeStringify(value) {
|
|
|
2599
2595
|
*/
|
|
2600
2596
|
function prettyPrintValue(value) {
|
|
2601
2597
|
return typeof value === "function"
|
|
2602
|
-
? `<function${value.name ?
|
|
2598
|
+
? `<function${value.name ? ` ${value.name}` : ""}>`
|
|
2603
2599
|
: isStateTreeNode(value)
|
|
2604
2600
|
? `<${value}>`
|
|
2605
2601
|
: `\`${safeStringify(value)}\``;
|
|
@@ -2623,16 +2619,13 @@ function toErrorString(error) {
|
|
|
2623
2619
|
? "value"
|
|
2624
2620
|
: "snapshot";
|
|
2625
2621
|
const isSnapshotCompatible = type && isStateTreeNode(value) && type.is(getStateTreeNode(value).snapshot);
|
|
2626
|
-
return
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
?
|
|
2631
|
-
:
|
|
2632
|
-
|
|
2633
|
-
? " (Note that a snapshot of the provided value is compatible with the targeted type)"
|
|
2634
|
-
: "")
|
|
2635
|
-
: `.`));
|
|
2622
|
+
return `${pathPrefix}${currentTypename} ${shortenPrintValue(prettyPrintValue(value))} is not assignable ${type ? `to type: \`${type.name}\`` : ``}${error.message ? ` (${error.message})` : ""}${type
|
|
2623
|
+
? isPrimitiveType(type) || isPrimitive(value)
|
|
2624
|
+
? `.`
|
|
2625
|
+
: `, expected an instance of \`${type.name}\` or a snapshot like \`${shortenPrintValue(type.describe())}\` instead.${isSnapshotCompatible
|
|
2626
|
+
? " (Note that a snapshot of the provided value is compatible with the targeted type)"
|
|
2627
|
+
: ""}`
|
|
2628
|
+
: `.`}`;
|
|
2636
2629
|
}
|
|
2637
2630
|
/**
|
|
2638
2631
|
* @internal
|
|
@@ -2721,7 +2714,7 @@ function validationErrorsToString(type, value, errors) {
|
|
|
2721
2714
|
if (errors.length === 0) {
|
|
2722
2715
|
return undefined;
|
|
2723
2716
|
}
|
|
2724
|
-
return
|
|
2717
|
+
return `Error while converting ${shortenPrintValue(prettyPrintValue(value))} to \`${type.name}\`:\n\n ${formatValidationErrorLines(errors).join("\n ")}`;
|
|
2725
2718
|
}
|
|
2726
2719
|
|
|
2727
2720
|
let identifierCacheId = 0;
|
|
@@ -2753,7 +2746,7 @@ class IdentifierCache {
|
|
|
2753
2746
|
this.cache.set(identifier, mobx.observable.array([], mobxShallow));
|
|
2754
2747
|
}
|
|
2755
2748
|
const set = this.cache.get(identifier);
|
|
2756
|
-
if (set.
|
|
2749
|
+
if (set.includes(node)) {
|
|
2757
2750
|
throw fail(`Already registered`);
|
|
2758
2751
|
}
|
|
2759
2752
|
set.push(node);
|
|
@@ -2786,12 +2779,12 @@ class IdentifierCache {
|
|
|
2786
2779
|
// The slash is added here so we only match children of the splitNode. In version 5.1.8 and
|
|
2787
2780
|
// earlier there was no trailing slash, so non children that started with the same path string
|
|
2788
2781
|
// were being matched incorrectly.
|
|
2789
|
-
const basePath = splitNode.path
|
|
2782
|
+
const basePath = `${splitNode.path}/`;
|
|
2790
2783
|
mobx.entries(this.cache).forEach(([id, nodes]) => {
|
|
2791
2784
|
let modified = false;
|
|
2792
2785
|
for (let i = nodes.length - 1; i >= 0; i--) {
|
|
2793
2786
|
const node = nodes[i];
|
|
2794
|
-
if (node === splitNode || node.path.
|
|
2787
|
+
if (node === splitNode || node.path.startsWith(basePath)) {
|
|
2795
2788
|
newCache.addNodeToCache(node, false); // no need to update lastUpdated since it is a whole new cache
|
|
2796
2789
|
nodes.splice(i, 1);
|
|
2797
2790
|
// remove empty sets from cache
|
|
@@ -2889,7 +2882,7 @@ var NodeLifeCycle;
|
|
|
2889
2882
|
* @returns true if the value is a state tree node.
|
|
2890
2883
|
*/
|
|
2891
2884
|
function isStateTreeNode(value) {
|
|
2892
|
-
return !!
|
|
2885
|
+
return !!value?.$treenode;
|
|
2893
2886
|
}
|
|
2894
2887
|
/**
|
|
2895
2888
|
* @internal
|
|
@@ -2914,7 +2907,7 @@ function getStateTreeNode(value) {
|
|
|
2914
2907
|
* @hidden
|
|
2915
2908
|
*/
|
|
2916
2909
|
function getStateTreeNodeSafe(value) {
|
|
2917
|
-
return
|
|
2910
|
+
return value?.$treenode || null;
|
|
2918
2911
|
}
|
|
2919
2912
|
/**
|
|
2920
2913
|
* @internal
|
|
@@ -3041,7 +3034,7 @@ const DEPRECATION_MESSAGE = "See https://github.com/mobxjs/mobx-state-tree/issue
|
|
|
3041
3034
|
* @returns {Promise}
|
|
3042
3035
|
*/
|
|
3043
3036
|
function process$1(asyncAction) {
|
|
3044
|
-
deprecated("process",
|
|
3037
|
+
deprecated("process", `\`process()\` has been renamed to \`flow()\`. ${DEPRECATION_MESSAGE}`);
|
|
3045
3038
|
return flow(asyncAction);
|
|
3046
3039
|
}
|
|
3047
3040
|
|
|
@@ -3069,7 +3062,7 @@ Object.freeze(mobxShallow);
|
|
|
3069
3062
|
* @hidden
|
|
3070
3063
|
*/
|
|
3071
3064
|
function fail(message = "Illegal state") {
|
|
3072
|
-
return new Error(
|
|
3065
|
+
return new Error(`[mobx-state-tree] ${message}`);
|
|
3073
3066
|
}
|
|
3074
3067
|
/**
|
|
3075
3068
|
* @internal
|
|
@@ -3117,19 +3110,6 @@ function asArray(val) {
|
|
|
3117
3110
|
}
|
|
3118
3111
|
return [val];
|
|
3119
3112
|
}
|
|
3120
|
-
/**
|
|
3121
|
-
* @internal
|
|
3122
|
-
* @hidden
|
|
3123
|
-
*/
|
|
3124
|
-
function extend(a, ...b) {
|
|
3125
|
-
for (let i = 0; i < b.length; i++) {
|
|
3126
|
-
const current = b[i];
|
|
3127
|
-
for (const key in current) {
|
|
3128
|
-
a[key] = current[key];
|
|
3129
|
-
}
|
|
3130
|
-
}
|
|
3131
|
-
return a;
|
|
3132
|
-
}
|
|
3133
3113
|
/**
|
|
3134
3114
|
* @internal
|
|
3135
3115
|
* @hidden
|
|
@@ -3263,7 +3243,7 @@ class EventHandler {
|
|
|
3263
3243
|
};
|
|
3264
3244
|
}
|
|
3265
3245
|
has(fn) {
|
|
3266
|
-
return this.handlers.
|
|
3246
|
+
return this.handlers.includes(fn);
|
|
3267
3247
|
}
|
|
3268
3248
|
unregister(fn) {
|
|
3269
3249
|
if (this.emitting) {
|
|
@@ -3312,8 +3292,7 @@ class EventHandler {
|
|
|
3312
3292
|
class EventHandlers {
|
|
3313
3293
|
eventHandlers;
|
|
3314
3294
|
hasSubscribers(event) {
|
|
3315
|
-
|
|
3316
|
-
return !!handler && handler.hasSubscribers;
|
|
3295
|
+
return this.eventHandlers?.[event]?.hasSubscribers ?? false;
|
|
3317
3296
|
}
|
|
3318
3297
|
register(event, fn, atTheBeginning = false) {
|
|
3319
3298
|
if (!this.eventHandlers) {
|
|
@@ -3326,11 +3305,10 @@ class EventHandlers {
|
|
|
3326
3305
|
return handler.register(fn, atTheBeginning);
|
|
3327
3306
|
}
|
|
3328
3307
|
has(event, fn) {
|
|
3329
|
-
|
|
3330
|
-
return !!handler && handler.has(fn);
|
|
3308
|
+
return this.eventHandlers?.[event]?.has(fn) ?? false;
|
|
3331
3309
|
}
|
|
3332
3310
|
unregister(event, fn) {
|
|
3333
|
-
const handler = this.eventHandlers
|
|
3311
|
+
const handler = this.eventHandlers?.[event];
|
|
3334
3312
|
if (handler) {
|
|
3335
3313
|
handler.unregister(fn);
|
|
3336
3314
|
}
|
|
@@ -3344,19 +3322,12 @@ class EventHandlers {
|
|
|
3344
3322
|
this.eventHandlers = undefined;
|
|
3345
3323
|
}
|
|
3346
3324
|
emit(event, ...args) {
|
|
3347
|
-
const handler = this.eventHandlers
|
|
3325
|
+
const handler = this.eventHandlers?.[event];
|
|
3348
3326
|
if (handler) {
|
|
3349
3327
|
handler.emit(...args);
|
|
3350
3328
|
}
|
|
3351
3329
|
}
|
|
3352
3330
|
}
|
|
3353
|
-
/**
|
|
3354
|
-
* @internal
|
|
3355
|
-
* @hidden
|
|
3356
|
-
*/
|
|
3357
|
-
function stringStartsWith(str, beginning) {
|
|
3358
|
-
return str.indexOf(beginning) === 0;
|
|
3359
|
-
}
|
|
3360
3331
|
/**
|
|
3361
3332
|
* @internal
|
|
3362
3333
|
* @hidden
|
|
@@ -3368,7 +3339,7 @@ const deprecated = function (id, message) {
|
|
|
3368
3339
|
}
|
|
3369
3340
|
// warn if hasn't been warned before
|
|
3370
3341
|
if (deprecated.ids && !deprecated.ids.hasOwnProperty(id)) {
|
|
3371
|
-
warnError(
|
|
3342
|
+
warnError(`Deprecation warning: ${message}`);
|
|
3372
3343
|
}
|
|
3373
3344
|
// mark as warned to avoid duplicate warn message
|
|
3374
3345
|
if (deprecated.ids) {
|
|
@@ -3383,15 +3354,27 @@ deprecated.ids = {};
|
|
|
3383
3354
|
function warnError(msg) {
|
|
3384
3355
|
console.warn(new Error(`[mobx-state-tree] ${msg}`));
|
|
3385
3356
|
}
|
|
3357
|
+
let _typeChecking;
|
|
3358
|
+
/**
|
|
3359
|
+
* Forces full run-time type-checking on or off, overriding the dev-mode and
|
|
3360
|
+
* `ENABLE_TYPE_CHECK` env-var defaults. Pass `true` to get better error messages
|
|
3361
|
+
* in production builds without relying on an environment variable, `false` to
|
|
3362
|
+
* force it off, or `undefined` to restore the default behavior.
|
|
3363
|
+
*/
|
|
3364
|
+
function setTypeChecking(enabled) {
|
|
3365
|
+
_typeChecking = enabled;
|
|
3366
|
+
}
|
|
3386
3367
|
/**
|
|
3387
3368
|
* @internal
|
|
3388
3369
|
* @hidden
|
|
3389
3370
|
*/
|
|
3390
3371
|
function isTypeCheckingEnabled() {
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3372
|
+
// an explicit setTypeChecking() override (incl. `false`) wins over the
|
|
3373
|
+
// dev-mode / env-var default, hence ?? rather than ||
|
|
3374
|
+
return (_typeChecking ??
|
|
3375
|
+
(devMode() ||
|
|
3376
|
+
(typeof process !== "undefined" &&
|
|
3377
|
+
process.env?.ENABLE_TYPE_CHECK === "true")));
|
|
3395
3378
|
}
|
|
3396
3379
|
let _devMode = process.env.NODE_ENV !== "production";
|
|
3397
3380
|
/**
|
|
@@ -3625,7 +3608,7 @@ function createFlowSpawner(name, generator) {
|
|
|
3625
3608
|
// TODO: support more type of values? See https://github.com/tj/co/blob/249bbdc72da24ae44076afd716349d2089b31c4c/index.js#L100
|
|
3626
3609
|
if (!ret.value || typeof ret.value.then !== "function") {
|
|
3627
3610
|
// istanbul ignore next
|
|
3628
|
-
throw fail(
|
|
3611
|
+
throw fail(`Only promises can be yielded to \`async\`, got: ${ret}`);
|
|
3629
3612
|
}
|
|
3630
3613
|
return ret.value.then(onFulfilled, onRejected);
|
|
3631
3614
|
}
|
|
@@ -3682,22 +3665,13 @@ function invertPatch(patch) {
|
|
|
3682
3665
|
};
|
|
3683
3666
|
}
|
|
3684
3667
|
}
|
|
3685
|
-
/**
|
|
3686
|
-
* Simple simple check to check it is a number.
|
|
3687
|
-
*/
|
|
3688
|
-
function isNumber(x) {
|
|
3689
|
-
return typeof x === "number";
|
|
3690
|
-
}
|
|
3691
3668
|
/**
|
|
3692
3669
|
* Escape slashes and backslashes.
|
|
3693
3670
|
*
|
|
3694
3671
|
* http://tools.ietf.org/html/rfc6901
|
|
3695
3672
|
*/
|
|
3696
3673
|
function escapeJsonPath(path) {
|
|
3697
|
-
if (
|
|
3698
|
-
return "" + path;
|
|
3699
|
-
}
|
|
3700
|
-
if (path.indexOf("/") === -1 && path.indexOf("~") === -1) {
|
|
3674
|
+
if (!path.includes("/") && !path.includes("~")) {
|
|
3701
3675
|
return path;
|
|
3702
3676
|
}
|
|
3703
3677
|
return path.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
@@ -3726,7 +3700,7 @@ function joinJsonPath(path) {
|
|
|
3726
3700
|
}
|
|
3727
3701
|
else {
|
|
3728
3702
|
// absolute
|
|
3729
|
-
return
|
|
3703
|
+
return `/${getPathStr(path)}`;
|
|
3730
3704
|
}
|
|
3731
3705
|
}
|
|
3732
3706
|
/**
|
|
@@ -3741,9 +3715,9 @@ function splitJsonPath(path) {
|
|
|
3741
3715
|
const valid = path === "" ||
|
|
3742
3716
|
path === "." ||
|
|
3743
3717
|
path === ".." ||
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3718
|
+
path.startsWith("/") ||
|
|
3719
|
+
path.startsWith("./") ||
|
|
3720
|
+
path.startsWith("../");
|
|
3747
3721
|
if (!valid) {
|
|
3748
3722
|
throw fail(`a json path must be either rooted, empty or relative, but got '${path}'`);
|
|
3749
3723
|
}
|
|
@@ -3951,16 +3925,16 @@ class MSTMap extends mobx.ObservableMap {
|
|
|
3951
3925
|
}
|
|
3952
3926
|
get(key) {
|
|
3953
3927
|
// maybe this is over-enthousiastic? normalize numeric keys to strings
|
|
3954
|
-
return super.get(
|
|
3928
|
+
return super.get(`${key}`);
|
|
3955
3929
|
}
|
|
3956
3930
|
has(key) {
|
|
3957
|
-
return super.has(
|
|
3931
|
+
return super.has(`${key}`);
|
|
3958
3932
|
}
|
|
3959
3933
|
delete(key) {
|
|
3960
|
-
return super.delete(
|
|
3934
|
+
return super.delete(`${key}`);
|
|
3961
3935
|
}
|
|
3962
3936
|
set(key, value) {
|
|
3963
|
-
return super.set(
|
|
3937
|
+
return super.set(`${key}`, value);
|
|
3964
3938
|
}
|
|
3965
3939
|
put(value) {
|
|
3966
3940
|
if (!value) {
|
|
@@ -4085,9 +4059,9 @@ class MapType extends ComplexType {
|
|
|
4085
4059
|
return mobx.values(node.storedValue);
|
|
4086
4060
|
}
|
|
4087
4061
|
getChildNode(node, key) {
|
|
4088
|
-
const childNode = node.storedValue.get(
|
|
4062
|
+
const childNode = node.storedValue.get(`${key}`);
|
|
4089
4063
|
if (!childNode) {
|
|
4090
|
-
throw fail(
|
|
4064
|
+
throw fail(`Not a child ${key}`);
|
|
4091
4065
|
}
|
|
4092
4066
|
return childNode;
|
|
4093
4067
|
}
|
|
@@ -4195,7 +4169,7 @@ class MapType extends ComplexType {
|
|
|
4195
4169
|
// Don't use target.replace, as it will throw away all existing items first
|
|
4196
4170
|
for (const key in snapshot) {
|
|
4197
4171
|
target.set(key, snapshot[key]);
|
|
4198
|
-
currentKeys[
|
|
4172
|
+
currentKeys[`${key}`] = true;
|
|
4199
4173
|
}
|
|
4200
4174
|
}
|
|
4201
4175
|
Object.keys(currentKeys).forEach(key => {
|
|
@@ -4295,7 +4269,7 @@ class ArrayType extends ComplexType {
|
|
|
4295
4269
|
const subType = objNode.type._subType;
|
|
4296
4270
|
const result = {};
|
|
4297
4271
|
snapshot.forEach((item, index) => {
|
|
4298
|
-
const subpath =
|
|
4272
|
+
const subpath = `${index}`;
|
|
4299
4273
|
result[subpath] = subType.instantiate(objNode, subpath, undefined, item);
|
|
4300
4274
|
});
|
|
4301
4275
|
return result;
|
|
@@ -4329,11 +4303,11 @@ class ArrayType extends ComplexType {
|
|
|
4329
4303
|
if (index < node.storedValue.length) {
|
|
4330
4304
|
return node.storedValue[index];
|
|
4331
4305
|
}
|
|
4332
|
-
throw fail(
|
|
4306
|
+
throw fail(`Not a child: ${key}`);
|
|
4333
4307
|
}
|
|
4334
4308
|
willChange(change) {
|
|
4335
4309
|
const node = getStateTreeNode(change.object);
|
|
4336
|
-
node.assertWritable({ subpath:
|
|
4310
|
+
node.assertWritable({ subpath: `${change.index}` });
|
|
4337
4311
|
const subType = node.type._subType;
|
|
4338
4312
|
const childNodes = node.getChildren();
|
|
4339
4313
|
switch (change.type) {
|
|
@@ -4359,7 +4333,7 @@ class ArrayType extends ComplexType {
|
|
|
4359
4333
|
change.added = addedNodes;
|
|
4360
4334
|
// update paths of remaining items
|
|
4361
4335
|
for (let i = index + removedCount; i < childNodes.length; i++) {
|
|
4362
|
-
childNodes[i].setParent(node,
|
|
4336
|
+
childNodes[i].setParent(node, `${i + added.length - removedCount}`);
|
|
4363
4337
|
}
|
|
4364
4338
|
}
|
|
4365
4339
|
break;
|
|
@@ -4382,7 +4356,7 @@ class ArrayType extends ComplexType {
|
|
|
4382
4356
|
case "update":
|
|
4383
4357
|
return void node.emitPatch({
|
|
4384
4358
|
op: "replace",
|
|
4385
|
-
path:
|
|
4359
|
+
path: `${change.index}`,
|
|
4386
4360
|
value: change.newValue.snapshot,
|
|
4387
4361
|
oldValue: change.oldValue ? change.oldValue.snapshot : undefined
|
|
4388
4362
|
}, node);
|
|
@@ -4390,15 +4364,15 @@ class ArrayType extends ComplexType {
|
|
|
4390
4364
|
for (let i = change.removedCount - 1; i >= 0; i--) {
|
|
4391
4365
|
node.emitPatch({
|
|
4392
4366
|
op: "remove",
|
|
4393
|
-
path:
|
|
4367
|
+
path: `${change.index + i}`,
|
|
4394
4368
|
oldValue: change.removed[i].snapshot
|
|
4395
4369
|
}, node);
|
|
4396
4370
|
}
|
|
4397
4371
|
for (let i = 0; i < change.addedCount; i++) {
|
|
4398
4372
|
node.emitPatch({
|
|
4399
4373
|
op: "add",
|
|
4400
|
-
path:
|
|
4401
|
-
value: node.getChildNode(
|
|
4374
|
+
path: `${change.index + i}`,
|
|
4375
|
+
value: node.getChildNode(`${change.index + i}`).snapshot,
|
|
4402
4376
|
oldValue: undefined
|
|
4403
4377
|
}, node);
|
|
4404
4378
|
}
|
|
@@ -4433,7 +4407,7 @@ class ArrayType extends ComplexType {
|
|
|
4433
4407
|
return typeCheckFailure(context, value, "Value is not an array");
|
|
4434
4408
|
}
|
|
4435
4409
|
for (let i = 0; i < value.length; i++) {
|
|
4436
|
-
getContextForPath(context,
|
|
4410
|
+
getContextForPath(context, `${i}`, this._subType);
|
|
4437
4411
|
const errors = this._subType.validate(value[i], context);
|
|
4438
4412
|
popContext(context);
|
|
4439
4413
|
if (errors.length > 0) {
|
|
@@ -4484,7 +4458,7 @@ function reconcileArrayChildren(parent, childType, oldNodes, newValues, newPaths
|
|
|
4484
4458
|
const hasNewNode = i <= newValues.length - 1;
|
|
4485
4459
|
const oldNode = oldNodes[i];
|
|
4486
4460
|
let newValue = hasNewNode ? newValues[i] : undefined;
|
|
4487
|
-
const newPath =
|
|
4461
|
+
const newPath = `${newPaths[i]}`;
|
|
4488
4462
|
// for some reason, instead of newValue we got a node, fallback to the storedValue
|
|
4489
4463
|
// TODO: https://github.com/mobxjs/mobx-state-tree/issues/340#issuecomment-325581681
|
|
4490
4464
|
if (isNode(newValue)) {
|
|
@@ -4920,18 +4894,18 @@ class ModelType extends ComplexType {
|
|
|
4920
4894
|
}
|
|
4921
4895
|
getChildNode(node, key) {
|
|
4922
4896
|
if (!(key in this.properties)) {
|
|
4923
|
-
throw fail(
|
|
4897
|
+
throw fail(`Not a value property: ${key}`);
|
|
4924
4898
|
}
|
|
4925
4899
|
const adm = mobx._getAdministration(node.storedValue, key);
|
|
4926
4900
|
const childNode = adm.raw?.();
|
|
4927
4901
|
if (!childNode) {
|
|
4928
|
-
throw fail(
|
|
4902
|
+
throw fail(`Node not available for property ${key}`);
|
|
4929
4903
|
}
|
|
4930
4904
|
return childNode;
|
|
4931
4905
|
}
|
|
4932
4906
|
getSnapshot(node, applyPostProcess = true) {
|
|
4933
4907
|
const res = {};
|
|
4934
|
-
this.forAllProps((name,
|
|
4908
|
+
this.forAllProps((name, type) => {
|
|
4935
4909
|
try {
|
|
4936
4910
|
// TODO: FIXME, make sure the observable ref is used!
|
|
4937
4911
|
const atom = mobx.getAtom(node.storedValue, name);
|
|
@@ -4940,7 +4914,11 @@ class ModelType extends ComplexType {
|
|
|
4940
4914
|
catch (_e) {
|
|
4941
4915
|
throw fail(`${name} property is declared twice`);
|
|
4942
4916
|
}
|
|
4943
|
-
|
|
4917
|
+
const snapshot = this.getChildNode(node, name).snapshot;
|
|
4918
|
+
// strip-default optionals omit their key when equal to the default
|
|
4919
|
+
if (!shouldStripChildFromSnapshot(type, snapshot)) {
|
|
4920
|
+
res[name] = snapshot;
|
|
4921
|
+
}
|
|
4944
4922
|
});
|
|
4945
4923
|
if (applyPostProcess) {
|
|
4946
4924
|
return this.applySnapshotPostProcessor(res);
|
|
@@ -4950,7 +4928,13 @@ class ModelType extends ComplexType {
|
|
|
4950
4928
|
processInitialSnapshot(childNodes) {
|
|
4951
4929
|
const processed = {};
|
|
4952
4930
|
Object.keys(childNodes).forEach(key => {
|
|
4953
|
-
|
|
4931
|
+
const snapshot = childNodes[key].getSnapshot();
|
|
4932
|
+
// strip-default optionals omit their key when equal to the default; this
|
|
4933
|
+
// mirrors getSnapshot for nodes serialized before they become observable
|
|
4934
|
+
// instances (e.g. array/map children that were never accessed)
|
|
4935
|
+
if (!shouldStripChildFromSnapshot(this.properties[key], snapshot)) {
|
|
4936
|
+
processed[key] = snapshot;
|
|
4937
|
+
}
|
|
4954
4938
|
});
|
|
4955
4939
|
return this.applySnapshotPostProcessor(processed);
|
|
4956
4940
|
}
|
|
@@ -5003,11 +4987,9 @@ class ModelType extends ComplexType {
|
|
|
5003
4987
|
}
|
|
5004
4988
|
describe() {
|
|
5005
4989
|
// optimization: cache
|
|
5006
|
-
return
|
|
5007
|
-
this.
|
|
5008
|
-
|
|
5009
|
-
.join("; ") +
|
|
5010
|
-
" }");
|
|
4990
|
+
return `{ ${this.propertyNames
|
|
4991
|
+
.map(key => `${key}: ${this.properties[key].describe()}`)
|
|
4992
|
+
.join("; ")} }`;
|
|
5011
4993
|
}
|
|
5012
4994
|
getDefaultSnapshot() {
|
|
5013
4995
|
return EMPTY_OBJECT;
|
|
@@ -5052,7 +5034,7 @@ function compose(...args) {
|
|
|
5052
5034
|
}
|
|
5053
5035
|
return args
|
|
5054
5036
|
.reduce((prev, cur) => prev.cloneAndEnhance({
|
|
5055
|
-
name: prev.name
|
|
5037
|
+
name: `${prev.name}_${cur.name}`,
|
|
5056
5038
|
properties: cur.properties,
|
|
5057
5039
|
initializers: cur.initializers,
|
|
5058
5040
|
preProcessor: (snapshot) => cur.applySnapshotPreProcessor(prev.applySnapshotPreProcessor(snapshot)),
|
|
@@ -5219,7 +5201,7 @@ function getPrimitiveFactoryFromValue(value) {
|
|
|
5219
5201
|
return DatePrimitive;
|
|
5220
5202
|
}
|
|
5221
5203
|
}
|
|
5222
|
-
throw fail(
|
|
5204
|
+
throw fail(`Cannot determine primitive type from value ${value}`);
|
|
5223
5205
|
}
|
|
5224
5206
|
/**
|
|
5225
5207
|
* Returns if a given value represents a primitive type.
|
|
@@ -5395,7 +5377,7 @@ function enumeration(name, options) {
|
|
|
5395
5377
|
assertIsString(option, i + 1);
|
|
5396
5378
|
});
|
|
5397
5379
|
}
|
|
5398
|
-
const type = union(...realOptions.map(option => literal(
|
|
5380
|
+
const type = union(...realOptions.map(option => literal(`${option}`)));
|
|
5399
5381
|
if (typeof name === "string") {
|
|
5400
5382
|
type.name = name;
|
|
5401
5383
|
}
|
|
@@ -5453,7 +5435,7 @@ class Union extends BaseType {
|
|
|
5453
5435
|
return this._types.some(subType => subType.isAssignableFrom(type));
|
|
5454
5436
|
}
|
|
5455
5437
|
describe() {
|
|
5456
|
-
return (
|
|
5438
|
+
return `(${this._types.map(factory => factory.describe()).join(" | ")})`;
|
|
5457
5439
|
}
|
|
5458
5440
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5459
5441
|
const type = this.determineType(initialValue, undefined);
|
|
@@ -5495,8 +5477,7 @@ class Union extends BaseType {
|
|
|
5495
5477
|
if (errors.length === 0) {
|
|
5496
5478
|
return baseWithDiscriminator;
|
|
5497
5479
|
}
|
|
5498
|
-
return
|
|
5499
|
-
formatValidationErrorLines(errors).join("\n "));
|
|
5480
|
+
return `${baseWithDiscriminator}:\n ${formatValidationErrorLines(errors).join("\n ")}`;
|
|
5500
5481
|
}
|
|
5501
5482
|
_findCandidateByTypeDiscriminator(discriminator) {
|
|
5502
5483
|
let found;
|
|
@@ -5726,7 +5707,7 @@ function union(optionsOrType, ...otherTypes) {
|
|
|
5726
5707
|
const types = isType(optionsOrType)
|
|
5727
5708
|
? [optionsOrType, ...otherTypes]
|
|
5728
5709
|
: otherTypes;
|
|
5729
|
-
const name =
|
|
5710
|
+
const name = `(${types.map(type => type.name).join(" | ")})`;
|
|
5730
5711
|
// check all options
|
|
5731
5712
|
if (devMode()) {
|
|
5732
5713
|
if (options) {
|
|
@@ -5793,17 +5774,17 @@ class OptionalValue extends BaseType {
|
|
|
5793
5774
|
this.optionalValues = optionalValues;
|
|
5794
5775
|
}
|
|
5795
5776
|
describe() {
|
|
5796
|
-
return this._subtype.describe()
|
|
5777
|
+
return `${this._subtype.describe()}?`;
|
|
5797
5778
|
}
|
|
5798
5779
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5799
|
-
if (this.optionalValues.
|
|
5780
|
+
if (this.optionalValues.includes(initialValue)) {
|
|
5800
5781
|
const defaultInstanceOrSnapshot = this.getDefaultInstanceOrSnapshot();
|
|
5801
5782
|
return this._subtype.instantiate(parent, subpath, environment, defaultInstanceOrSnapshot);
|
|
5802
5783
|
}
|
|
5803
5784
|
return this._subtype.instantiate(parent, subpath, environment, initialValue);
|
|
5804
5785
|
}
|
|
5805
5786
|
reconcile(current, newValue, parent, subpath) {
|
|
5806
|
-
return this._subtype.reconcile(current, this.optionalValues.
|
|
5787
|
+
return this._subtype.reconcile(current, !this.optionalValues.includes(newValue) && this._subtype.is(newValue)
|
|
5807
5788
|
? newValue
|
|
5808
5789
|
: this.getDefaultInstanceOrSnapshot(), parent, subpath);
|
|
5809
5790
|
}
|
|
@@ -5820,7 +5801,7 @@ class OptionalValue extends BaseType {
|
|
|
5820
5801
|
}
|
|
5821
5802
|
isValidSnapshot(value, context) {
|
|
5822
5803
|
// defaulted values can be skipped
|
|
5823
|
-
if (this.optionalValues.
|
|
5804
|
+
if (this.optionalValues.includes(value)) {
|
|
5824
5805
|
return typeCheckSuccess();
|
|
5825
5806
|
}
|
|
5826
5807
|
// bounce validation to the sub-type
|
|
@@ -5907,6 +5888,72 @@ const undefinedAsOptionalValues = [undefined];
|
|
|
5907
5888
|
function isOptionalType(type) {
|
|
5908
5889
|
return isType(type) && (type.flags & TypeFlags.Optional) > 0;
|
|
5909
5890
|
}
|
|
5891
|
+
/**
|
|
5892
|
+
* Compare a child snapshot to a stripped-default's reference snapshot. Mirrors
|
|
5893
|
+
* the legacy hand-rolled comparison: identity for primitives, structural for
|
|
5894
|
+
* objects/arrays.
|
|
5895
|
+
*/
|
|
5896
|
+
function defaultSnapshotEquals(a, b) {
|
|
5897
|
+
if (a === b) {
|
|
5898
|
+
return true;
|
|
5899
|
+
}
|
|
5900
|
+
if (typeof a === "object" &&
|
|
5901
|
+
a !== null &&
|
|
5902
|
+
typeof b === "object" &&
|
|
5903
|
+
b !== null) {
|
|
5904
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
5905
|
+
}
|
|
5906
|
+
return false;
|
|
5907
|
+
}
|
|
5908
|
+
/**
|
|
5909
|
+
* An optional type that additionally omits its key from a parent model's
|
|
5910
|
+
* snapshot when the value equals the (snapshotted) default. The comparison is
|
|
5911
|
+
* against the default *snapshot* — i.e. the subtype is instantiated with the
|
|
5912
|
+
* default once and its post-processed snapshot is cached — so a default whose
|
|
5913
|
+
* normalized form gains fields (e.g. a fileLocation gaining `locationType`)
|
|
5914
|
+
* still strips correctly.
|
|
5915
|
+
*
|
|
5916
|
+
* @hidden
|
|
5917
|
+
* @internal
|
|
5918
|
+
*/
|
|
5919
|
+
class StripDefaultValue extends OptionalValue {
|
|
5920
|
+
_defaultSnapshot;
|
|
5921
|
+
shouldStripFromSnapshot(snapshot) {
|
|
5922
|
+
if (!this._defaultSnapshot) {
|
|
5923
|
+
// instantiate the subtype detached with the default and read the node's
|
|
5924
|
+
// snapshot, which normalizes (fills model defaults, applies the subtype's
|
|
5925
|
+
// own postProcess). Cached on the (singleton) type after first use.
|
|
5926
|
+
const node = this.getSubTypes().instantiate(null, "", undefined, this.getDefaultInstanceOrSnapshot());
|
|
5927
|
+
this._defaultSnapshot = { value: node.snapshot };
|
|
5928
|
+
}
|
|
5929
|
+
return defaultSnapshotEquals(snapshot, this._defaultSnapshot.value);
|
|
5930
|
+
}
|
|
5931
|
+
}
|
|
5932
|
+
/**
|
|
5933
|
+
* Whether `type` is a strip-default optional whose current child `snapshot`
|
|
5934
|
+
* equals its default and should therefore be omitted from the parent model's
|
|
5935
|
+
* snapshot. Used by `ModelType.getSnapshot`.
|
|
5936
|
+
*
|
|
5937
|
+
* @hidden
|
|
5938
|
+
* @internal
|
|
5939
|
+
*/
|
|
5940
|
+
function shouldStripChildFromSnapshot(type, snapshot) {
|
|
5941
|
+
return (type instanceof StripDefaultValue && type.shouldStripFromSnapshot(snapshot));
|
|
5942
|
+
}
|
|
5943
|
+
/**
|
|
5944
|
+
* `types.stripDefault` - Like `types.optional`, but the property is omitted from
|
|
5945
|
+
* a parent model's snapshot entirely when its value equals the default (instead
|
|
5946
|
+
* of being serialized with the default value). Lets a model produce minimal
|
|
5947
|
+
* snapshots without a bespoke `postProcessSnapshot`.
|
|
5948
|
+
*
|
|
5949
|
+
* @param type
|
|
5950
|
+
* @param defaultValueOrFunction
|
|
5951
|
+
* @returns
|
|
5952
|
+
*/
|
|
5953
|
+
function stripDefault(type, defaultValueOrFunction) {
|
|
5954
|
+
checkOptionalPreconditions(type, defaultValueOrFunction);
|
|
5955
|
+
return new StripDefaultValue(type, defaultValueOrFunction, undefinedAsOptionalValues);
|
|
5956
|
+
}
|
|
5910
5957
|
|
|
5911
5958
|
const optionalUndefinedType = optional(undefinedType, undefined);
|
|
5912
5959
|
const optionalNullType = optional(nullType, null);
|
|
@@ -6021,8 +6068,7 @@ function late(nameOrType, maybeType) {
|
|
|
6021
6068
|
// checks that the type is actually a late type
|
|
6022
6069
|
if (devMode()) {
|
|
6023
6070
|
if (!(typeof type === "function" && type.length === 0)) {
|
|
6024
|
-
throw fail(
|
|
6025
|
-
type);
|
|
6071
|
+
throw fail(`Invalid late type, expected a function with zero arguments that returns a type, got: ${type}`);
|
|
6026
6072
|
}
|
|
6027
6073
|
}
|
|
6028
6074
|
return new Late(name, type);
|
|
@@ -6235,8 +6281,7 @@ class StoredReference {
|
|
|
6235
6281
|
const normalizedId = normalizeIdentifier(this.identifier);
|
|
6236
6282
|
const root = node.root;
|
|
6237
6283
|
const lastCacheModification = root.identifierCache.getLastCacheModificationPerId(normalizedId);
|
|
6238
|
-
if (
|
|
6239
|
-
this.resolvedReference.lastCacheModification !== lastCacheModification) {
|
|
6284
|
+
if (this.resolvedReference?.lastCacheModification !== lastCacheModification) {
|
|
6240
6285
|
const { targetType } = this;
|
|
6241
6286
|
// reference was initialized with the identifier of the target
|
|
6242
6287
|
const target = root.identifierCache.resolve(targetType, normalizedId);
|
|
@@ -6245,7 +6290,7 @@ class StoredReference {
|
|
|
6245
6290
|
}
|
|
6246
6291
|
this.resolvedReference = {
|
|
6247
6292
|
node: target,
|
|
6248
|
-
lastCacheModification
|
|
6293
|
+
lastCacheModification
|
|
6249
6294
|
};
|
|
6250
6295
|
}
|
|
6251
6296
|
}
|
|
@@ -6293,7 +6338,7 @@ class BaseReferenceType extends SimpleType {
|
|
|
6293
6338
|
// since it is a scalar value (immutable-ish) and we need to change it
|
|
6294
6339
|
// from the parent
|
|
6295
6340
|
const storedRefParentNode = storedRefNode.parent;
|
|
6296
|
-
if (!storedRefParentNode
|
|
6341
|
+
if (!storedRefParentNode?.isAlive) {
|
|
6297
6342
|
return;
|
|
6298
6343
|
}
|
|
6299
6344
|
const storedRefParentValue = storedRefParentNode.storedValue;
|
|
@@ -6365,7 +6410,7 @@ class BaseReferenceType extends SimpleType {
|
|
|
6365
6410
|
}
|
|
6366
6411
|
// make sure the target node is actually there and initialized
|
|
6367
6412
|
const storedRefParentNode = storedRefNode.parent;
|
|
6368
|
-
const storedRefParentValue = storedRefParentNode
|
|
6413
|
+
const storedRefParentValue = storedRefParentNode?.storedValue;
|
|
6369
6414
|
if (storedRefParentNode &&
|
|
6370
6415
|
storedRefParentNode.isAlive &&
|
|
6371
6416
|
storedRefParentValue) {
|
|
@@ -6679,7 +6724,7 @@ function isIdentifierType(type) {
|
|
|
6679
6724
|
* @hidden
|
|
6680
6725
|
*/
|
|
6681
6726
|
function normalizeIdentifier(id) {
|
|
6682
|
-
return
|
|
6727
|
+
return `${id}`;
|
|
6683
6728
|
}
|
|
6684
6729
|
/**
|
|
6685
6730
|
* @internal
|
|
@@ -6775,7 +6820,7 @@ class CustomType extends SimpleType {
|
|
|
6775
6820
|
instantiate(parent, subpath, environment, initialValue) {
|
|
6776
6821
|
const valueToStore = this.options.isTargetType(initialValue)
|
|
6777
6822
|
? initialValue
|
|
6778
|
-
: this.options.fromSnapshot(initialValue, parent
|
|
6823
|
+
: this.options.fromSnapshot(initialValue, parent?.root.environment);
|
|
6779
6824
|
return createScalarNode(this, parent, subpath, environment, valueToStore);
|
|
6780
6825
|
}
|
|
6781
6826
|
reconcile(current, value, parent, subpath) {
|
|
@@ -6926,6 +6971,7 @@ const types = {
|
|
|
6926
6971
|
safeReference,
|
|
6927
6972
|
union,
|
|
6928
6973
|
optional,
|
|
6974
|
+
stripDefault,
|
|
6929
6975
|
literal,
|
|
6930
6976
|
maybe,
|
|
6931
6977
|
maybeNull,
|
|
@@ -7019,6 +7065,7 @@ exports.resolvePath = resolvePath;
|
|
|
7019
7065
|
exports.setDevMode = setDevMode;
|
|
7020
7066
|
exports.setLivelinessChecking = setLivelinessChecking;
|
|
7021
7067
|
exports.setLivelynessChecking = setLivelynessChecking;
|
|
7068
|
+
exports.setTypeChecking = setTypeChecking;
|
|
7022
7069
|
exports.splitJsonPath = splitJsonPath;
|
|
7023
7070
|
exports.t = types;
|
|
7024
7071
|
exports.toGenerator = toGenerator;
|