@jbrowse/mobx-state-tree 5.9.2 → 5.9.3

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.
@@ -2699,16 +2699,27 @@ function typecheck(type, value) {
2699
2699
  }
2700
2700
  }
2701
2701
  const MAX_ERRORS_REPORTED = 10;
2702
- function validationErrorsToString(type, value, errors) {
2703
- if (errors.length === 0) {
2704
- return undefined;
2705
- }
2702
+ /**
2703
+ * @internal
2704
+ * @hidden
2705
+ * Format a list of validation errors as bullet-style lines, capped at
2706
+ * MAX_ERRORS_REPORTED entries with an overflow suffix. Shared by typecheck()
2707
+ * and union's `noMatchMessage` so prod-build union failures can include
2708
+ * candidate validation errors using the same formatting.
2709
+ */
2710
+ function formatValidationErrorLines(errors) {
2706
2711
  const shown = errors.slice(0, MAX_ERRORS_REPORTED).map(toErrorString);
2707
2712
  const overflow = errors.length - shown.length;
2708
2713
  if (overflow > 0) {
2709
2714
  shown.push(`(… and ${overflow} more error${overflow === 1 ? "" : "s"})`);
2710
2715
  }
2711
- return (`Error while converting ${shortenPrintValue(prettyPrintValue(value))} to \`${type.name}\`:\n\n ` + shown.join("\n "));
2716
+ return shown;
2717
+ }
2718
+ function validationErrorsToString(type, value, errors) {
2719
+ if (errors.length === 0) {
2720
+ return undefined;
2721
+ }
2722
+ return (`Error while converting ${shortenPrintValue(prettyPrintValue(value))} to \`${type.name}\`:\n\n ` + formatValidationErrorLines(errors).join("\n "));
2712
2723
  }
2713
2724
 
2714
2725
  let identifierCacheId = 0;
@@ -5438,10 +5449,55 @@ class Union extends BaseType {
5438
5449
  return type.reconcile(current, newValue, parent, subpath);
5439
5450
  }
5440
5451
  noMatchMessage(value) {
5441
- const discriminator = isPlainObject(value) && typeof value.type === "string"
5442
- ? ` for snapshot with type "${value.type}"`
5443
- : "";
5444
- return `No matching type for union ${this.name}${discriminator}`;
5452
+ const base = `No matching type for union ${this.name}`;
5453
+ if (!isPlainObject(value)) {
5454
+ return base;
5455
+ }
5456
+ const discriminator = value.type;
5457
+ if (typeof discriminator !== "string") {
5458
+ return base;
5459
+ }
5460
+ const baseWithDiscriminator = `${base} for snapshot with type "${discriminator}"`;
5461
+ // If exactly one union member has a literal `type` property matching the
5462
+ // snapshot's discriminator, run its validate() so we can append the
5463
+ // property-level reasons it didn't match. This converts the bare prod-build
5464
+ // "no matching type" into something diagnosable (e.g. which field was the
5465
+ // wrong type, which required field was missing) without re-bloating the
5466
+ // message back to every-member's full describe() output.
5467
+ const candidate = this._findCandidateByTypeDiscriminator(discriminator);
5468
+ if (!candidate) {
5469
+ return baseWithDiscriminator;
5470
+ }
5471
+ const errors = candidate.validate(value, [
5472
+ { path: "", type: candidate }
5473
+ ]);
5474
+ if (errors.length === 0) {
5475
+ return baseWithDiscriminator;
5476
+ }
5477
+ return (`${baseWithDiscriminator}:\n ` +
5478
+ formatValidationErrorLines(errors).join("\n "));
5479
+ }
5480
+ _findCandidateByTypeDiscriminator(discriminator) {
5481
+ let found;
5482
+ for (const t of this._types) {
5483
+ if (!(t instanceof ModelType)) {
5484
+ continue;
5485
+ }
5486
+ const typeProp = t.properties
5487
+ .type;
5488
+ if (!typeProp ||
5489
+ !(typeProp.flags & TypeFlags.Literal) ||
5490
+ !typeProp.is(discriminator)) {
5491
+ continue;
5492
+ }
5493
+ if (found) {
5494
+ // Ambiguous (two members declare the same `type` literal). Fall back
5495
+ // to the short message rather than picking arbitrarily.
5496
+ return undefined;
5497
+ }
5498
+ found = t;
5499
+ }
5500
+ return found;
5445
5501
  }
5446
5502
  determineType(value, reconcileCurrentType) {
5447
5503
  // try the dispatcher, if defined