@jbrowse/mobx-state-tree 5.9.3 → 5.10.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/mobx-state-tree.cjs
CHANGED
|
@@ -5402,6 +5402,25 @@ function enumeration(name, options) {
|
|
|
5402
5402
|
return type;
|
|
5403
5403
|
}
|
|
5404
5404
|
|
|
5405
|
+
// Drill through single-subtype wrappers — optional(), refinement(),
|
|
5406
|
+
// snapshotProcessor(), late() — to the underlying ModelType. Discriminated-
|
|
5407
|
+
// union scoping keys on a member's literal `type` property, but real-world
|
|
5408
|
+
// members are rarely bare models (jbrowse config schemas, for instance, are
|
|
5409
|
+
// always optional(model) or optional(snapshotProcessor(model))). Without this
|
|
5410
|
+
// the scoping never engages and every failure prints every member's full
|
|
5411
|
+
// structure. Wrappers expose their child as `_subtype` (optional/refinement/
|
|
5412
|
+
// snapshotProcessor) or via `getSubType()` (late); bounded to avoid cycles.
|
|
5413
|
+
function resolveModelType(type) {
|
|
5414
|
+
let current = type;
|
|
5415
|
+
for (let depth = 0; current && depth < 20; depth++) {
|
|
5416
|
+
if (current instanceof ModelType) {
|
|
5417
|
+
return current;
|
|
5418
|
+
}
|
|
5419
|
+
const wrapper = current;
|
|
5420
|
+
current = wrapper._subtype ?? wrapper.getSubType?.(false);
|
|
5421
|
+
}
|
|
5422
|
+
return undefined;
|
|
5423
|
+
}
|
|
5405
5424
|
/**
|
|
5406
5425
|
* @internal
|
|
5407
5426
|
* @hidden
|
|
@@ -5482,11 +5501,11 @@ class Union extends BaseType {
|
|
|
5482
5501
|
_findCandidateByTypeDiscriminator(discriminator) {
|
|
5483
5502
|
let found;
|
|
5484
5503
|
for (const t of this._types) {
|
|
5485
|
-
|
|
5504
|
+
const model = resolveModelType(t);
|
|
5505
|
+
if (!model) {
|
|
5486
5506
|
continue;
|
|
5487
5507
|
}
|
|
5488
|
-
const typeProp =
|
|
5489
|
-
.type;
|
|
5508
|
+
const typeProp = model.properties.type;
|
|
5490
5509
|
if (!typeProp ||
|
|
5491
5510
|
!(typeProp.flags & TypeFlags.Literal) ||
|
|
5492
5511
|
!typeProp.is(discriminator)) {
|
|
@@ -5497,10 +5516,29 @@ class Union extends BaseType {
|
|
|
5497
5516
|
// to the short message rather than picking arbitrarily.
|
|
5498
5517
|
return undefined;
|
|
5499
5518
|
}
|
|
5519
|
+
// Return the original (possibly wrapped) member, not the unwrapped
|
|
5520
|
+
// model, so validate()/is() still apply optional defaults and any
|
|
5521
|
+
// snapshotProcessor pre-processing.
|
|
5500
5522
|
found = t;
|
|
5501
5523
|
}
|
|
5502
5524
|
return found;
|
|
5503
5525
|
}
|
|
5526
|
+
// True when every member resolves to a model carrying a literal `type`
|
|
5527
|
+
// discriminator — i.e. a fully discriminated union, where a snapshot's `type`
|
|
5528
|
+
// uniquely identifies the intended member and no untagged catch-all member
|
|
5529
|
+
// could also accept it. Cached: membership is fixed at construction.
|
|
5530
|
+
_allMembersDiscriminated;
|
|
5531
|
+
allMembersDiscriminated() {
|
|
5532
|
+
if (this._allMembersDiscriminated === undefined) {
|
|
5533
|
+
this._allMembersDiscriminated = this._types.every(t => {
|
|
5534
|
+
const model = resolveModelType(t);
|
|
5535
|
+
const typeProp = model &&
|
|
5536
|
+
model.properties.type;
|
|
5537
|
+
return !!typeProp && (typeProp.flags & TypeFlags.Literal) !== 0;
|
|
5538
|
+
});
|
|
5539
|
+
}
|
|
5540
|
+
return this._allMembersDiscriminated;
|
|
5541
|
+
}
|
|
5504
5542
|
determineType(value, reconcileCurrentType) {
|
|
5505
5543
|
// try the dispatcher, if defined
|
|
5506
5544
|
if (this._dispatcher) {
|
|
@@ -5588,11 +5626,14 @@ class Union extends BaseType {
|
|
|
5588
5626
|
}
|
|
5589
5627
|
snapshotLooksLikeType(value, type) {
|
|
5590
5628
|
// for model types, check if snapshot has all the required property keys
|
|
5591
|
-
// and that any literal-typed properties match exactly
|
|
5592
|
-
|
|
5593
|
-
|
|
5629
|
+
// and that any literal-typed properties match exactly. Unwrap optional() /
|
|
5630
|
+
// snapshotProcessor() / refinement() / late() so wrapped members (e.g.
|
|
5631
|
+
// jbrowse config schemas, which are always optional(model)) still match.
|
|
5632
|
+
const model = resolveModelType(type);
|
|
5633
|
+
if (model) {
|
|
5634
|
+
const props = model.properties;
|
|
5594
5635
|
// use cached propertyNames from ModelType instead of Object.keys()
|
|
5595
|
-
for (const key of
|
|
5636
|
+
for (const key of model.propertyNames) {
|
|
5596
5637
|
const propType = props[key];
|
|
5597
5638
|
const isOptional = propType.flags & TypeFlags.Optional;
|
|
5598
5639
|
const propValue = value[key];
|
|
@@ -5619,6 +5660,28 @@ class Union extends BaseType {
|
|
|
5619
5660
|
if (this._dispatcher) {
|
|
5620
5661
|
return this._dispatcher(value).validate(value, context);
|
|
5621
5662
|
}
|
|
5663
|
+
// For plain-object snapshots carrying a `type` discriminator, validate only
|
|
5664
|
+
// the single member whose literal `type` matches.
|
|
5665
|
+
// - Clean validation short-circuits to success only when it is sound to skip
|
|
5666
|
+
// the other members: an eager union (first match wins) or a fully
|
|
5667
|
+
// discriminated one (no untagged catch-all could also match). A non-eager
|
|
5668
|
+
// union with a catch-all must still fall through so ambiguity is counted.
|
|
5669
|
+
// - A failure is the definitive, scoped error only when every member is
|
|
5670
|
+
// discriminated; otherwise a catch-all could still accept the value, so
|
|
5671
|
+
// fall through to full validation.
|
|
5672
|
+
if (isPlainObject(value) && !isStateTreeNode(value)) {
|
|
5673
|
+
const discriminator = value.type;
|
|
5674
|
+
if (typeof discriminator === "string") {
|
|
5675
|
+
const candidate = this._findCandidateByTypeDiscriminator(discriminator);
|
|
5676
|
+
if (candidate) {
|
|
5677
|
+
const errors = candidate.validate(value, context);
|
|
5678
|
+
const cleanAndUnique = errors.length === 0 && this._eager;
|
|
5679
|
+
if (cleanAndUnique || this.allMembersDiscriminated()) {
|
|
5680
|
+
return errors;
|
|
5681
|
+
}
|
|
5682
|
+
}
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5622
5685
|
// for plain-object snapshots, prefer union members whose literal-typed
|
|
5623
5686
|
// discriminator properties match the value (e.g. {type: "MsaView"})
|
|
5624
5687
|
// so error output is scoped to the intended branch instead of every member
|