@jbrowse/mobx-state-tree 6.4.0 → 6.5.1
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 +407 -0
- package/dist/index.d.ts +14 -5
- package/dist/mobx-state-tree.cjs +106 -20
- package/dist/mobx-state-tree.cjs.map +1 -1
- package/dist/mobx-state-tree.mjs +106 -20
- package/dist/mobx-state-tree.mjs.map +1 -1
- package/package.json +9 -3
package/dist/mobx-state-tree.cjs
CHANGED
|
@@ -5725,7 +5725,7 @@ class Union extends BaseType {
|
|
|
5725
5725
|
return cached;
|
|
5726
5726
|
}
|
|
5727
5727
|
let result = TypeFlags.Union;
|
|
5728
|
-
for (const type of this.
|
|
5728
|
+
for (const type of this.members()) {
|
|
5729
5729
|
result |= type.flags;
|
|
5730
5730
|
}
|
|
5731
5731
|
if (!(result & TypeFlags.Late)) {
|
|
@@ -5734,12 +5734,14 @@ class Union extends BaseType {
|
|
|
5734
5734
|
return result;
|
|
5735
5735
|
}
|
|
5736
5736
|
computeName() {
|
|
5737
|
-
return `(${this.
|
|
5737
|
+
return `(${this.members()
|
|
5738
|
+
.map(type => type.name)
|
|
5739
|
+
.join(" | ")})`;
|
|
5738
5740
|
}
|
|
5739
5741
|
constructor(_types, options) {
|
|
5740
5742
|
super();
|
|
5741
5743
|
this._types = _types;
|
|
5742
|
-
// read the
|
|
5744
|
+
// read the options directly rather than spreading defaults into a fresh
|
|
5743
5745
|
// object: this constructor runs once per config slot in jbrowse, and the
|
|
5744
5746
|
// merged object was allocated only to be read twice and dropped
|
|
5745
5747
|
if (options !== undefined) {
|
|
@@ -5749,13 +5751,23 @@ class Union extends BaseType {
|
|
|
5749
5751
|
if (options.eager === false) {
|
|
5750
5752
|
this._eager = false;
|
|
5751
5753
|
}
|
|
5754
|
+
if (options.name !== undefined) {
|
|
5755
|
+
this.name = options.name;
|
|
5756
|
+
}
|
|
5752
5757
|
}
|
|
5753
5758
|
}
|
|
5759
|
+
// The one point membership is read through, so DynamicUnion can substitute
|
|
5760
|
+
// its thunk without duplicating any of the scanning logic below.
|
|
5761
|
+
members() {
|
|
5762
|
+
return this._types;
|
|
5763
|
+
}
|
|
5754
5764
|
isAssignableFrom(type) {
|
|
5755
|
-
return this.
|
|
5765
|
+
return this.members().some(subType => subType.isAssignableFrom(type));
|
|
5756
5766
|
}
|
|
5757
5767
|
describe() {
|
|
5758
|
-
return `(${this.
|
|
5768
|
+
return `(${this.members()
|
|
5769
|
+
.map(factory => factory.describe())
|
|
5770
|
+
.join(" | ")})`;
|
|
5759
5771
|
}
|
|
5760
5772
|
instantiate(parent, subpath, environment, initialValue) {
|
|
5761
5773
|
const type = this.determineType(initialValue, undefined);
|
|
@@ -5810,7 +5822,7 @@ class Union extends BaseType {
|
|
|
5810
5822
|
}
|
|
5811
5823
|
_scanForTypeDiscriminator(discriminator) {
|
|
5812
5824
|
let found;
|
|
5813
|
-
for (const t of this.
|
|
5825
|
+
for (const t of this.members()) {
|
|
5814
5826
|
const model = resolveModelType(t);
|
|
5815
5827
|
if (!model) {
|
|
5816
5828
|
continue;
|
|
@@ -5835,15 +5847,18 @@ class Union extends BaseType {
|
|
|
5835
5847
|
}
|
|
5836
5848
|
allMembersDiscriminated() {
|
|
5837
5849
|
if (this._allMembersDiscriminated === undefined) {
|
|
5838
|
-
this._allMembersDiscriminated = this.
|
|
5839
|
-
const model = resolveModelType(t);
|
|
5840
|
-
const typeProp = model &&
|
|
5841
|
-
model.properties["type"];
|
|
5842
|
-
return !!typeProp && (typeProp.flags & TypeFlags.Literal) !== 0;
|
|
5843
|
-
});
|
|
5850
|
+
this._allMembersDiscriminated = this.computeAllMembersDiscriminated();
|
|
5844
5851
|
}
|
|
5845
5852
|
return this._allMembersDiscriminated;
|
|
5846
5853
|
}
|
|
5854
|
+
computeAllMembersDiscriminated() {
|
|
5855
|
+
return this.members().every(t => {
|
|
5856
|
+
const model = resolveModelType(t);
|
|
5857
|
+
const typeProp = model &&
|
|
5858
|
+
model.properties["type"];
|
|
5859
|
+
return !!typeProp && (typeProp.flags & TypeFlags.Literal) !== 0;
|
|
5860
|
+
});
|
|
5861
|
+
}
|
|
5847
5862
|
determineType(value, reconcileCurrentType) {
|
|
5848
5863
|
// try the dispatcher, if defined
|
|
5849
5864
|
if (this._dispatcher) {
|
|
@@ -5864,9 +5879,9 @@ class Union extends BaseType {
|
|
|
5864
5879
|
if (reconcileCurrentType.is(value)) {
|
|
5865
5880
|
return reconcileCurrentType;
|
|
5866
5881
|
}
|
|
5867
|
-
return this.
|
|
5882
|
+
return this.members().find(type => type !== reconcileCurrentType && type.is(value));
|
|
5868
5883
|
}
|
|
5869
|
-
return this.
|
|
5884
|
+
return this.members().find(type => type.is(value));
|
|
5870
5885
|
}
|
|
5871
5886
|
tryQuickMatch(value, reconcileCurrentType) {
|
|
5872
5887
|
// state tree nodes need full type compatibility checking
|
|
@@ -5886,7 +5901,7 @@ class Union extends BaseType {
|
|
|
5886
5901
|
this.snapshotLooksLikeType(value, reconcileCurrentType)) {
|
|
5887
5902
|
return reconcileCurrentType;
|
|
5888
5903
|
}
|
|
5889
|
-
for (const type of this.
|
|
5904
|
+
for (const type of this.members()) {
|
|
5890
5905
|
if (type !== reconcileCurrentType &&
|
|
5891
5906
|
this.snapshotLooksLikeType(value, type)) {
|
|
5892
5907
|
return type;
|
|
@@ -5896,7 +5911,7 @@ class Union extends BaseType {
|
|
|
5896
5911
|
}
|
|
5897
5912
|
tryMatchPrimitive(value) {
|
|
5898
5913
|
const valueType = typeof value;
|
|
5899
|
-
for (const type of this.
|
|
5914
|
+
for (const type of this.members()) {
|
|
5900
5915
|
const flags = type.flags;
|
|
5901
5916
|
if ((valueType === "string" && flags & TypeFlags.String) ||
|
|
5902
5917
|
(valueType === "number" &&
|
|
@@ -5983,10 +5998,11 @@ class Union extends BaseType {
|
|
|
5983
5998
|
// for plain-object snapshots, prefer union members whose literal-typed
|
|
5984
5999
|
// discriminator properties match the value (e.g. {type: "MsaView"})
|
|
5985
6000
|
// so error output is scoped to the intended branch instead of every member
|
|
6001
|
+
const members = this.members();
|
|
5986
6002
|
const candidates = isSnapshotObject
|
|
5987
|
-
?
|
|
6003
|
+
? members.filter(t => this.snapshotLooksLikeType(value, t))
|
|
5988
6004
|
: [];
|
|
5989
|
-
const typesToValidate = candidates.length > 0 ? candidates :
|
|
6005
|
+
const typesToValidate = candidates.length > 0 ? candidates : members;
|
|
5990
6006
|
const allErrors = [];
|
|
5991
6007
|
let applicableTypes = 0;
|
|
5992
6008
|
for (const type of typesToValidate) {
|
|
@@ -6009,7 +6025,7 @@ class Union extends BaseType {
|
|
|
6009
6025
|
return typeCheckFailure(context, value, "No type is applicable for the union").concat(allErrors.flat());
|
|
6010
6026
|
}
|
|
6011
6027
|
getSubTypes() {
|
|
6012
|
-
return this.
|
|
6028
|
+
return this.members();
|
|
6013
6029
|
}
|
|
6014
6030
|
}
|
|
6015
6031
|
// Defaults shared by every union; see the field declarations at the top of the
|
|
@@ -6020,6 +6036,56 @@ Object.assign(Union.prototype, {
|
|
|
6020
6036
|
_discriminatorCache: undefined,
|
|
6021
6037
|
_allMembersDiscriminated: undefined
|
|
6022
6038
|
});
|
|
6039
|
+
/**
|
|
6040
|
+
* @internal
|
|
6041
|
+
* @hidden
|
|
6042
|
+
*
|
|
6043
|
+
* A union whose membership is read fresh from a thunk on every operation, so
|
|
6044
|
+
* members that come into existence after the union was built — a registry of
|
|
6045
|
+
* pluggable types whose modules load on demand — still dispatch, validate, and
|
|
6046
|
+
* satisfy references. That last one is the reason this exists: reference
|
|
6047
|
+
* resolution asks the target type `isAssignableFrom(node.type)` through the
|
|
6048
|
+
* identifier cache, and a membership list frozen at construction would reject
|
|
6049
|
+
* every late-loaded member's instances.
|
|
6050
|
+
*
|
|
6051
|
+
* Every membership-derived cache the base class keeps is bypassed here: flags
|
|
6052
|
+
* and the folded name are recomputed per read, and the discriminator scan is
|
|
6053
|
+
* uncached so a miss stays retryable once the missing member registers. A hit
|
|
6054
|
+
* for a given discriminator is assumed stable — registering two members with
|
|
6055
|
+
* the same `type` literal at different times can leave a stale unambiguous
|
|
6056
|
+
* answer where the base class would have reported ambiguity.
|
|
6057
|
+
*/
|
|
6058
|
+
class DynamicUnion extends Union {
|
|
6059
|
+
_members;
|
|
6060
|
+
constructor(members, options) {
|
|
6061
|
+
super([], options);
|
|
6062
|
+
this._members = members;
|
|
6063
|
+
}
|
|
6064
|
+
members() {
|
|
6065
|
+
return this._members();
|
|
6066
|
+
}
|
|
6067
|
+
get flags() {
|
|
6068
|
+
let result = TypeFlags.Union;
|
|
6069
|
+
for (const type of this.members()) {
|
|
6070
|
+
result |= type.flags;
|
|
6071
|
+
}
|
|
6072
|
+
return result;
|
|
6073
|
+
}
|
|
6074
|
+
get name() {
|
|
6075
|
+
return this._explicitName !== undefined
|
|
6076
|
+
? this._explicitName
|
|
6077
|
+
: this.computeName();
|
|
6078
|
+
}
|
|
6079
|
+
set name(value) {
|
|
6080
|
+
this._explicitName = value;
|
|
6081
|
+
}
|
|
6082
|
+
_findCandidateByTypeDiscriminator(discriminator) {
|
|
6083
|
+
return this._scanForTypeDiscriminator(discriminator);
|
|
6084
|
+
}
|
|
6085
|
+
allMembersDiscriminated() {
|
|
6086
|
+
return this.computeAllMembersDiscriminated();
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6023
6089
|
const unionInternRoot = {};
|
|
6024
6090
|
function internUnion(types) {
|
|
6025
6091
|
let node = unionInternRoot;
|
|
@@ -6039,6 +6105,13 @@ function internUnion(types) {
|
|
|
6039
6105
|
/**
|
|
6040
6106
|
* `types.union` - Create a union of multiple types. If the correct type cannot be inferred unambiguously from a snapshot, provide a dispatcher function of the form `(snapshot) => Type`.
|
|
6041
6107
|
*
|
|
6108
|
+
* Passing `members: () => Type[]` in the options (with no positional member
|
|
6109
|
+
* types) creates a union whose membership is re-read from the thunk on every
|
|
6110
|
+
* operation, so types registered after construction — e.g. from a lazily
|
|
6111
|
+
* loaded module — participate in dispatch, validation and reference
|
|
6112
|
+
* resolution. Pair it with a `dispatcher` for snapshot dispatch and a `name`
|
|
6113
|
+
* for stable error messages.
|
|
6114
|
+
*
|
|
6042
6115
|
* @param optionsOrType
|
|
6043
6116
|
* @param otherTypes
|
|
6044
6117
|
* @returns
|
|
@@ -6058,12 +6131,18 @@ function union(...args) {
|
|
|
6058
6131
|
// check all options
|
|
6059
6132
|
if (devMode()) {
|
|
6060
6133
|
if (options) {
|
|
6061
|
-
assertArg(options, o => isPlainObject(o), "object { eager?: boolean, dispatcher?: Function }", 1);
|
|
6134
|
+
assertArg(options, o => isPlainObject(o), "object { eager?: boolean, dispatcher?: Function, members?: Function, name?: string }", 1);
|
|
6062
6135
|
}
|
|
6063
6136
|
types.forEach((type, i) => {
|
|
6064
6137
|
assertIsType(type, options ? i + 2 : i + 1);
|
|
6065
6138
|
});
|
|
6066
6139
|
}
|
|
6140
|
+
if (options?.members !== undefined) {
|
|
6141
|
+
if (types.length > 0) {
|
|
6142
|
+
throw fail("union(): the members option cannot be combined with positional member types");
|
|
6143
|
+
}
|
|
6144
|
+
return new DynamicUnion(options.members, options);
|
|
6145
|
+
}
|
|
6067
6146
|
return options === undefined ? internUnion(types) : new Union(types, options);
|
|
6068
6147
|
}
|
|
6069
6148
|
/**
|
|
@@ -6648,6 +6727,13 @@ class Lazy extends SimpleType {
|
|
|
6648
6727
|
}
|
|
6649
6728
|
reconcile(current, value, parent, subpath) {
|
|
6650
6729
|
if (this.loadedType) {
|
|
6730
|
+
// a node created after load carries the loaded type: let it reconcile so
|
|
6731
|
+
// the instance survives applySnapshot instead of dying on every write
|
|
6732
|
+
const loaded = this.loadedType;
|
|
6733
|
+
const currentType = current.type;
|
|
6734
|
+
if (currentType === loaded) {
|
|
6735
|
+
return this.loadedType.reconcile(current, value, parent, subpath);
|
|
6736
|
+
}
|
|
6651
6737
|
current.die();
|
|
6652
6738
|
return this.loadedType.instantiate(parent, subpath, parent.environment, value);
|
|
6653
6739
|
}
|