@jbrowse/mobx-state-tree 5.9.1 → 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.
package/README.md CHANGED
@@ -7,12 +7,11 @@ Fork of mobx-state-tree v5.4.2 for use in jbrowse
7
7
  - updated typescript
8
8
  - updated to import actual filepaths instead of node module resolution
9
9
  - reduced rollup config
10
- - tried tsdown but builds were very slow for some reason
11
10
  - removed process.env.NODE_ENV from code, instead exporting a setDevMode function
12
11
  - converted tests to vitest
13
12
  - remove unused dependencies
14
13
  - updated tslint to eslint and typescript-eslint
15
- - attempted to make it a dual CJS/'pure ESM' package but did not work quite yet, using main (CJS) and module (ESM-ish) fields for now since dual build causes trouble with both being imported in vite
14
+ - dual CJS/ESM build using main and module fields (pure ESM causes trouble when both are imported in vite)
16
15
  - added `types.resilient` - wraps a type so that instantiation errors are caught
17
16
  and a fallback type is used instead of crashing the entire state tree. This is
18
17
  useful for arrays or maps that may contain unknown or invalid entries (e.g.
@@ -22,3 +21,6 @@ Fork of mobx-state-tree v5.4.2 for use in jbrowse
22
21
  meaning any value is considered a valid snapshot. Validation is deferred to
23
22
  instantiation time, where failures are caught and routed to the fallback
24
23
  - removed NonEmptyObject annotation (also at upstream in post v5 versions)
24
+ - replaced `unique symbol` phantom properties (`$emptyObject`, `$stateTreeNodeType`) with
25
+ exported string-keyed brand interfaces (`$EmptyObjectBrand`, `$__mstStateTreeNodeType__`),
26
+ fixing tsgo TS4058/TS4023 errors when MST types propagate into exported function return types
@@ -2701,16 +2701,27 @@ function typecheck(type, value) {
2701
2701
  }
2702
2702
  }
2703
2703
  const MAX_ERRORS_REPORTED = 10;
2704
- function validationErrorsToString(type, value, errors) {
2705
- if (errors.length === 0) {
2706
- return undefined;
2707
- }
2704
+ /**
2705
+ * @internal
2706
+ * @hidden
2707
+ * Format a list of validation errors as bullet-style lines, capped at
2708
+ * MAX_ERRORS_REPORTED entries with an overflow suffix. Shared by typecheck()
2709
+ * and union's `noMatchMessage` so prod-build union failures can include
2710
+ * candidate validation errors using the same formatting.
2711
+ */
2712
+ function formatValidationErrorLines(errors) {
2708
2713
  const shown = errors.slice(0, MAX_ERRORS_REPORTED).map(toErrorString);
2709
2714
  const overflow = errors.length - shown.length;
2710
2715
  if (overflow > 0) {
2711
2716
  shown.push(`(… and ${overflow} more error${overflow === 1 ? "" : "s"})`);
2712
2717
  }
2713
- return (`Error while converting ${shortenPrintValue(prettyPrintValue(value))} to \`${type.name}\`:\n\n ` + shown.join("\n "));
2718
+ return shown;
2719
+ }
2720
+ function validationErrorsToString(type, value, errors) {
2721
+ if (errors.length === 0) {
2722
+ return undefined;
2723
+ }
2724
+ return (`Error while converting ${shortenPrintValue(prettyPrintValue(value))} to \`${type.name}\`:\n\n ` + formatValidationErrorLines(errors).join("\n "));
2714
2725
  }
2715
2726
 
2716
2727
  let identifierCacheId = 0;
@@ -5440,10 +5451,55 @@ class Union extends BaseType {
5440
5451
  return type.reconcile(current, newValue, parent, subpath);
5441
5452
  }
5442
5453
  noMatchMessage(value) {
5443
- const discriminator = isPlainObject(value) && typeof value.type === "string"
5444
- ? ` for snapshot with type "${value.type}"`
5445
- : "";
5446
- return `No matching type for union ${this.name}${discriminator}`;
5454
+ const base = `No matching type for union ${this.name}`;
5455
+ if (!isPlainObject(value)) {
5456
+ return base;
5457
+ }
5458
+ const discriminator = value.type;
5459
+ if (typeof discriminator !== "string") {
5460
+ return base;
5461
+ }
5462
+ const baseWithDiscriminator = `${base} for snapshot with type "${discriminator}"`;
5463
+ // If exactly one union member has a literal `type` property matching the
5464
+ // snapshot's discriminator, run its validate() so we can append the
5465
+ // property-level reasons it didn't match. This converts the bare prod-build
5466
+ // "no matching type" into something diagnosable (e.g. which field was the
5467
+ // wrong type, which required field was missing) without re-bloating the
5468
+ // message back to every-member's full describe() output.
5469
+ const candidate = this._findCandidateByTypeDiscriminator(discriminator);
5470
+ if (!candidate) {
5471
+ return baseWithDiscriminator;
5472
+ }
5473
+ const errors = candidate.validate(value, [
5474
+ { path: "", type: candidate }
5475
+ ]);
5476
+ if (errors.length === 0) {
5477
+ return baseWithDiscriminator;
5478
+ }
5479
+ return (`${baseWithDiscriminator}:\n ` +
5480
+ formatValidationErrorLines(errors).join("\n "));
5481
+ }
5482
+ _findCandidateByTypeDiscriminator(discriminator) {
5483
+ let found;
5484
+ for (const t of this._types) {
5485
+ if (!(t instanceof ModelType)) {
5486
+ continue;
5487
+ }
5488
+ const typeProp = t.properties
5489
+ .type;
5490
+ if (!typeProp ||
5491
+ !(typeProp.flags & TypeFlags.Literal) ||
5492
+ !typeProp.is(discriminator)) {
5493
+ continue;
5494
+ }
5495
+ if (found) {
5496
+ // Ambiguous (two members declare the same `type` literal). Fall back
5497
+ // to the short message rather than picking arbitrarily.
5498
+ return undefined;
5499
+ }
5500
+ found = t;
5501
+ }
5502
+ return found;
5447
5503
  }
5448
5504
  determineType(value, reconcileCurrentType) {
5449
5505
  // try the dispatcher, if defined