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