mobx-keystone 2.2.0 → 2.3.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.
Files changed (168) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/mobx-keystone.esm.js +426 -334
  3. package/dist/mobx-keystone.esm.mjs +426 -334
  4. package/dist/mobx-keystone.umd.js +429 -333
  5. package/dist/types/action/applyAction.d.ts +1 -1
  6. package/dist/types/action/applyMethodCall.d.ts +1 -1
  7. package/dist/types/action/index.d.ts +12 -12
  8. package/dist/types/action/isModelAction.d.ts +1 -1
  9. package/dist/types/action/middleware.d.ts +1 -1
  10. package/dist/types/actionMiddlewares/actionSerialization/actionSerialization.d.ts +3 -3
  11. package/dist/types/actionMiddlewares/actionSerialization/applySerializedAction.d.ts +2 -2
  12. package/dist/types/actionMiddlewares/actionSerialization/arraySerializer.d.ts +2 -2
  13. package/dist/types/actionMiddlewares/actionSerialization/dateSerializer.d.ts +1 -1
  14. package/dist/types/actionMiddlewares/actionSerialization/index.d.ts +3 -3
  15. package/dist/types/actionMiddlewares/actionSerialization/mapSerializer.d.ts +2 -2
  16. package/dist/types/actionMiddlewares/actionSerialization/objectPathSerializer.d.ts +2 -2
  17. package/dist/types/actionMiddlewares/actionSerialization/objectSnapshotSerializer.d.ts +1 -1
  18. package/dist/types/actionMiddlewares/actionSerialization/plainObjectSerializer.d.ts +1 -1
  19. package/dist/types/actionMiddlewares/actionSerialization/primitiveSerializer.d.ts +1 -1
  20. package/dist/types/actionMiddlewares/actionSerialization/setSerializer.d.ts +2 -2
  21. package/dist/types/actionMiddlewares/actionTrackingMiddleware.d.ts +3 -3
  22. package/dist/types/actionMiddlewares/index.d.ts +6 -6
  23. package/dist/types/actionMiddlewares/onActionMiddleware.d.ts +3 -3
  24. package/dist/types/actionMiddlewares/readonlyMiddleware.d.ts +1 -1
  25. package/dist/types/actionMiddlewares/transactionMiddleware.d.ts +2 -2
  26. package/dist/types/actionMiddlewares/undoMiddleware.d.ts +8 -8
  27. package/dist/types/computedTree/index.d.ts +1 -1
  28. package/dist/types/context/index.d.ts +1 -1
  29. package/dist/types/dataModel/BaseDataModel.d.ts +3 -3
  30. package/dist/types/dataModel/DataModel.d.ts +3 -3
  31. package/dist/types/dataModel/getDataModelMetadata.d.ts +3 -3
  32. package/dist/types/dataModel/index.d.ts +4 -4
  33. package/dist/types/dataModel/utils.d.ts +1 -1
  34. package/dist/types/deepChange/index.d.ts +1 -1
  35. package/dist/types/deepChange/onDeepChange.d.ts +1 -1
  36. package/dist/types/frozen/Frozen.d.ts +1 -1
  37. package/dist/types/frozen/index.d.ts +1 -1
  38. package/dist/types/globalConfig/index.d.ts +1 -1
  39. package/dist/types/index.d.ts +24 -24
  40. package/dist/types/model/BaseModel.d.ts +5 -5
  41. package/dist/types/model/Model.d.ts +3 -3
  42. package/dist/types/model/getModelMetadata.d.ts +3 -3
  43. package/dist/types/model/index.d.ts +6 -6
  44. package/dist/types/model/mixins.d.ts +4 -4
  45. package/dist/types/model/utils.d.ts +4 -4
  46. package/dist/types/modelShared/BaseModelShared.d.ts +5 -5
  47. package/dist/types/modelShared/index.d.ts +4 -4
  48. package/dist/types/modelShared/modelDecorator.d.ts +3 -3
  49. package/dist/types/modelShared/modelInfo.d.ts +3 -3
  50. package/dist/types/modelShared/newModel.d.ts +3 -3
  51. package/dist/types/modelShared/prop.d.ts +3 -3
  52. package/dist/types/modelShared/sharedInternalModel.d.ts +4 -4
  53. package/dist/types/parent/findParent.d.ts +1 -1
  54. package/dist/types/parent/index.d.ts +9 -9
  55. package/dist/types/parent/path.d.ts +1 -1
  56. package/dist/types/patch/Patch.d.ts +1 -1
  57. package/dist/types/patch/applyPatches.d.ts +1 -1
  58. package/dist/types/patch/emitPatch.d.ts +1 -1
  59. package/dist/types/patch/index.d.ts +5 -5
  60. package/dist/types/patch/jsonPatch.d.ts +2 -2
  61. package/dist/types/patch/patchRecorder.d.ts +2 -2
  62. package/dist/types/redux/index.d.ts +2 -2
  63. package/dist/types/redux/redux.d.ts +3 -3
  64. package/dist/types/ref/Ref.d.ts +3 -3
  65. package/dist/types/ref/core.d.ts +2 -2
  66. package/dist/types/ref/customRef.d.ts +2 -2
  67. package/dist/types/ref/index.d.ts +4 -4
  68. package/dist/types/ref/rootRef.d.ts +2 -2
  69. package/dist/types/rootStore/index.d.ts +1 -1
  70. package/dist/types/snapshot/SnapshotOf.d.ts +5 -5
  71. package/dist/types/snapshot/SnapshotProcessingError.d.ts +2 -2
  72. package/dist/types/snapshot/applySnapshot.d.ts +1 -1
  73. package/dist/types/snapshot/cloneTreeValue.d.ts +1 -1
  74. package/dist/types/snapshot/fromSnapshot.d.ts +2 -2
  75. package/dist/types/snapshot/getSnapshot.d.ts +2 -2
  76. package/dist/types/snapshot/index.d.ts +8 -8
  77. package/dist/types/snapshot/onSnapshot.d.ts +1 -1
  78. package/dist/types/standardActions/index.d.ts +3 -3
  79. package/dist/types/standardActions/objectActions.d.ts +1 -1
  80. package/dist/types/transforms/asMap.d.ts +1 -1
  81. package/dist/types/transforms/asSet.d.ts +2 -2
  82. package/dist/types/transforms/bigint.d.ts +1 -1
  83. package/dist/types/transforms/date.d.ts +1 -1
  84. package/dist/types/transforms/index.d.ts +4 -4
  85. package/dist/types/treeUtils/draft.d.ts +1 -1
  86. package/dist/types/treeUtils/index.d.ts +3 -3
  87. package/dist/types/tweaker/index.d.ts +2 -2
  88. package/dist/types/tweaker/tweak.d.ts +1 -1
  89. package/dist/types/types/SnapshotTypeMismatchError.d.ts +5 -3
  90. package/dist/types/types/TypeCheckError.d.ts +2 -2
  91. package/dist/types/types/TypeChecker.d.ts +3 -3
  92. package/dist/types/types/arrayBased/typesArray.d.ts +2 -2
  93. package/dist/types/types/arrayBased/typesTuple.d.ts +2 -2
  94. package/dist/types/types/getTypeInfo.d.ts +2 -2
  95. package/dist/types/types/index.d.ts +7 -7
  96. package/dist/types/types/modelTypeMatching.d.ts +1 -0
  97. package/dist/types/types/objectBased/typesArraySet.d.ts +3 -3
  98. package/dist/types/types/objectBased/typesDataModelData.d.ts +4 -4
  99. package/dist/types/types/objectBased/typesModel.d.ts +4 -4
  100. package/dist/types/types/objectBased/typesObject.d.ts +3 -3
  101. package/dist/types/types/objectBased/typesObjectMap.d.ts +3 -3
  102. package/dist/types/types/objectBased/typesRecord.d.ts +2 -2
  103. package/dist/types/types/objectBased/typesRef.d.ts +3 -3
  104. package/dist/types/types/primitiveBased/typesEnum.d.ts +1 -1
  105. package/dist/types/types/primitiveBased/typesPrimitive.d.ts +3 -3
  106. package/dist/types/types/primitiveBased/typesRefinedPrimitive.d.ts +2 -2
  107. package/dist/types/types/schemas.d.ts +5 -5
  108. package/dist/types/types/tProp.d.ts +4 -4
  109. package/dist/types/types/typeCheck.d.ts +2 -2
  110. package/dist/types/types/types.d.ts +39 -39
  111. package/dist/types/types/utility/typeToStoredData.d.ts +2 -2
  112. package/dist/types/types/utility/typesBigInt.d.ts +1 -1
  113. package/dist/types/types/utility/typesCodec.d.ts +6 -6
  114. package/dist/types/types/utility/typesCodecCore.d.ts +4 -4
  115. package/dist/types/types/utility/typesCodecSupport.d.ts +4 -4
  116. package/dist/types/types/utility/typesDate.d.ts +2 -2
  117. package/dist/types/types/utility/typesMap.d.ts +2 -2
  118. package/dist/types/types/utility/typesMaybe.d.ts +1 -1
  119. package/dist/types/types/utility/typesOr.d.ts +2 -2
  120. package/dist/types/types/utility/typesRefinement.d.ts +3 -3
  121. package/dist/types/types/utility/typesSet.d.ts +3 -3
  122. package/dist/types/types/utility/typesSkipCheck.d.ts +2 -2
  123. package/dist/types/types/utility/typesTag.d.ts +2 -2
  124. package/dist/types/types/utility/typesUnchecked.d.ts +2 -2
  125. package/dist/types/utils/ModelPool.d.ts +1 -1
  126. package/dist/types/wrappers/ArraySet.d.ts +1 -1
  127. package/dist/types/wrappers/ObjectMap.d.ts +1 -1
  128. package/dist/types/wrappers/asMap.d.ts +1 -1
  129. package/dist/types/wrappers/asSet.d.ts +1 -1
  130. package/dist/types/wrappers/index.d.ts +4 -4
  131. package/package.json +10 -23
  132. package/src/action/modelAction.ts +1 -1
  133. package/src/action/modelFlow.ts +1 -1
  134. package/src/dataModel/BaseDataModel.ts +5 -5
  135. package/src/model/BaseModel.ts +7 -6
  136. package/src/model/mixins.ts +1 -1
  137. package/src/model/newModel.ts +1 -1
  138. package/src/modelShared/modelDecorator.ts +6 -11
  139. package/src/modelShared/modelInfo.ts +76 -0
  140. package/src/modelShared/sharedInternalModel.ts +1 -1
  141. package/src/ref/Ref.ts +1 -1
  142. package/src/snapshot/SnapshotterAndReconcilerPriority.ts +2 -1
  143. package/src/snapshot/fromModelSnapshot.ts +1 -1
  144. package/src/snapshot/fromSnapshot.ts +1 -1
  145. package/src/transforms/ImmutableDate.ts +19 -19
  146. package/src/tweaker/tweakArray.ts +1 -1
  147. package/src/tweaker/tweakFrozen.ts +1 -1
  148. package/src/tweaker/tweakModel.ts +1 -1
  149. package/src/tweaker/tweakPlainObject.ts +1 -1
  150. package/src/types/SnapshotTypeMismatchError.ts +3 -1
  151. package/src/types/arrayBased/typesArray.ts +1 -1
  152. package/src/types/arrayBased/typesTuple.ts +1 -1
  153. package/src/types/modelTypeMatching.ts +276 -0
  154. package/src/types/objectBased/typesArraySet.ts +1 -1
  155. package/src/types/objectBased/typesModel.ts +24 -7
  156. package/src/types/objectBased/typesObject.ts +1 -1
  157. package/src/types/objectBased/typesObjectMap.ts +1 -1
  158. package/src/types/objectBased/typesRecord.ts +1 -1
  159. package/src/types/objectBased/typesRef.ts +24 -5
  160. package/src/types/primitiveBased/typesPrimitive.ts +1 -1
  161. package/src/types/schemas.ts +1 -1
  162. package/src/types/utility/typesCodecCore.ts +4 -2
  163. package/src/types/utility/typesCodecSupport.ts +15 -7
  164. package/src/types/utility/typesOr.ts +40 -10
  165. package/src/types/utility/typesRefinement.ts +1 -1
  166. package/src/utils/index.ts +20 -13
  167. package/src/wrappers/ArraySet.ts +3 -5
  168. package/src/wrappers/ObjectMap.ts +3 -5
@@ -6,7 +6,6 @@ import { ObjectMap } from "../../wrappers/ObjectMap"
6
6
  import { getTypeInfo } from "../getTypeInfo"
7
7
  import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
8
8
  import type { AnyStandardType, AnyType, ModelType, TypeToData } from "../schemas"
9
- import { TypeCheckError } from "../TypeCheckError"
10
9
  import {
11
10
  lateTypeChecker,
12
11
  snapshotProcessorPlan,
@@ -15,6 +14,7 @@ import {
15
14
  TypeInfo,
16
15
  type TypeInfoGen,
17
16
  } from "../TypeChecker"
17
+ import { TypeCheckError } from "../TypeCheckError"
18
18
  import { resolveCodecSupport } from "../utility/typesCodec"
19
19
  import { typesObject } from "./typesObject"
20
20
  import { typesRecord } from "./typesRecord"
@@ -6,7 +6,6 @@ import { createChunkedRecordCachedCheck } from "../createCachedTypeCheck"
6
6
  import { getTypeInfo } from "../getTypeInfo"
7
7
  import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
8
8
  import type { AnyStandardType, AnyType, RecordType } from "../schemas"
9
- import { TypeCheckError } from "../TypeCheckError"
10
9
  import {
11
10
  lateTypeChecker,
12
11
  snapshotProcessorPlan,
@@ -15,6 +14,7 @@ import {
15
14
  TypeInfo,
16
15
  type TypeInfoGen,
17
16
  } from "../TypeChecker"
17
+ import { TypeCheckError } from "../TypeCheckError"
18
18
  import { prependPathElementToTypeCheckError } from "../typeCheckErrorUtils"
19
19
 
20
20
  /**
@@ -1,12 +1,19 @@
1
1
  import { modelTypeKey } from "../../model/metadata"
2
+ import { isModel } from "../../model/utils"
2
3
  import { modelInfoByClass } from "../../modelShared/modelInfo"
3
4
  import type { Ref, RefConstructor } from "../../ref/Ref"
4
5
  import { isObject } from "../../utils"
6
+ import {
7
+ isModelInstanceOfModelName,
8
+ isUnrelatedSnapshotModelType,
9
+ snapshotModelTypeMatches,
10
+ } from "../modelTypeMatching"
5
11
  import { typesString } from "../primitiveBased/typesPrimitive"
6
12
  import { resolveTypeChecker } from "../resolveTypeChecker"
7
13
  import type { ModelType } from "../schemas"
8
- import { TypeCheckError } from "../TypeCheckError"
14
+ import { SnapshotTypeMismatchError } from "../SnapshotTypeMismatchError"
9
15
  import { TypeChecker, TypeCheckerBaseType, TypeInfo } from "../TypeChecker"
16
+ import { TypeCheckError } from "../TypeCheckError"
10
17
  import { typesObject } from "./typesObject"
11
18
 
12
19
  /**
@@ -36,7 +43,10 @@ export function typesRef<O extends object>(refConstructor: RefConstructor<O>): M
36
43
  TypeCheckerBaseType.Object,
37
44
 
38
45
  (value, path, typeCheckedValue) => {
39
- if (!(value instanceof refConstructor.refClass)) {
46
+ if (
47
+ !(value instanceof refConstructor.refClass) &&
48
+ !(isModel(value) && isModelInstanceOfModelName(value, modelInfo.name))
49
+ ) {
40
50
  return new TypeCheckError({
41
51
  path,
42
52
  expectedTypeName: typeName,
@@ -56,16 +66,25 @@ export function typesRef<O extends object>(refConstructor: RefConstructor<O>): M
56
66
  return null
57
67
  }
58
68
 
59
- if (obj[modelTypeKey] !== undefined) {
69
+ const snModelType = obj[modelTypeKey]
70
+ if (snModelType !== undefined) {
60
71
  // fast check
61
- return obj[modelTypeKey] === modelInfo.name ? thisTc : null
72
+ return snapshotModelTypeMatches(snModelType, modelInfo.name) ? thisTc : null
62
73
  }
63
74
 
64
75
  return refDataTypeChecker.snapshotType(obj) ? thisTc : null
65
76
  },
66
77
 
67
78
  (sn: Record<string, unknown>) => {
68
- if (sn[modelTypeKey]) {
79
+ const snModelType = sn[modelTypeKey]
80
+ if (typeof snModelType === "string") {
81
+ // the snapshot names its own model; make sure it is this ref or a subclass of it
82
+ if (isUnrelatedSnapshotModelType(snModelType, modelInfo.name)) {
83
+ throw new SnapshotTypeMismatchError({
84
+ expectedTypeName: typeName,
85
+ actualValue: sn,
86
+ })
87
+ }
69
88
  return sn
70
89
  } else {
71
90
  return {
@@ -2,8 +2,8 @@ import { assertIsPrimitive, isEqualOrBothNaN } from "../../utils"
2
2
  import type { PrimitiveValue } from "../../utils/types"
3
3
  import { registerStandardTypeResolver, type StandardTypeResolverFn } from "../resolveTypeChecker"
4
4
  import type { AnyStandardType, IdentityType } from "../schemas"
5
- import { TypeCheckError } from "../TypeCheckError"
6
5
  import { TypeChecker, TypeCheckerBaseType, TypeInfo, type TypeInfoGen } from "../TypeChecker"
6
+ import { TypeCheckError } from "../TypeCheckError"
7
7
 
8
8
  const standardTypeResolvers: StandardTypeResolverFn[] = []
9
9
 
@@ -96,7 +96,7 @@ type ObjectSnapshotOutData<S, OK = ObjectOptionalKeys<S>> = SimplifyObject<
96
96
  export interface ObjectType<S> extends Type<"object", ObjectData<S>> {}
97
97
 
98
98
  export interface ObjectTypeFunction {
99
- // biome-ignore lint/style/useShorthandFunctionType: make the type recursive
99
+ // oxlint-disable-next-line typescript/prefer-function-type -- make the type recursive
100
100
  (): ObjectOfTypes
101
101
  }
102
102
 
@@ -1,6 +1,7 @@
1
1
  import type { ModelPropTransform } from "../../modelShared/prop"
2
2
  import { lazy } from "../../utils"
3
3
  import { getTypeInfo } from "../getTypeInfo"
4
+ import { runInModelTypeMatchingPass } from "../modelTypeMatching"
4
5
  import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
5
6
  import type {
6
7
  AnyStandardType,
@@ -10,7 +11,6 @@ import type {
10
11
  TypeToSnapshotIn,
11
12
  TypeToSnapshotOut,
12
13
  } from "../schemas"
13
- import { TypeCheckError } from "../TypeCheckError"
14
14
  import {
15
15
  lateTypeChecker,
16
16
  TypeChecker,
@@ -18,6 +18,7 @@ import {
18
18
  TypeInfo,
19
19
  type TypeInfoGen,
20
20
  } from "../TypeChecker"
21
+ import { TypeCheckError } from "../TypeCheckError"
21
22
  import type { TypeToStoredData } from "./typeToStoredData"
22
23
 
23
24
  export interface RuntimeAdapter<Stored, Runtime> {
@@ -145,7 +146,8 @@ export function createCodecType<TEncodedType extends AnyType, TRuntime>(
145
146
  () => typeName,
146
147
  typeInfoGen,
147
148
 
148
- (value) => (is(value) ? thisTc : null),
149
+ // user code, so it must not see the model type matching pass of an outer union
150
+ (value) => (runInModelTypeMatchingPass("none", is, value, undefined) ? thisTc : null),
149
151
 
150
152
  (snapshot) => {
151
153
  const processedSnapshot = encodedTypeChecker.fromSnapshotProcessor(snapshot)
@@ -5,6 +5,7 @@ import { setIfDifferent } from "../../utils/setIfDifferent"
5
5
  import { ArrayTypeInfo, typesArray } from "../arrayBased/typesArray"
6
6
  import { TupleTypeInfo, typesTuple } from "../arrayBased/typesTuple"
7
7
  import { getTypeInfo } from "../getTypeInfo"
8
+ import { findClosestModelTypeMatch, findFirstMatch } from "../modelTypeMatching"
8
9
  import { isDataModelDataStandardType } from "../objectBased/typesDataModelData"
9
10
  import { isModelStandardType } from "../objectBased/typesModel"
10
11
  import { ObjectTypeInfo, typesObject } from "../objectBased/typesObject"
@@ -274,6 +275,7 @@ function createArrayLikeRuntimeAdapter(
274
275
  target.length = storedValues.length
275
276
  for (let i = 0; i < storedValues.length; i++) {
276
277
  if (i in storedValues) target[i] = storedValues[i]
278
+ // oxlint-disable-next-line typescript/no-array-delete -- keep the holes of sparse arrays
277
279
  else delete target[i]
278
280
  }
279
281
  }
@@ -512,6 +514,7 @@ function createCodecLeafRuntimeAdapter(
512
514
 
513
515
  // Declared up front (rather than initialized from the call) so that a setter invoked
514
516
  // while decoding can read it without hitting the temporal dead zone.
517
+ // oxlint-disable-next-line eslint/prefer-const -- see above
515
518
  let runtime: unknown
516
519
  let storedChanged = false
517
520
  runtime = transform.transform({
@@ -577,6 +580,13 @@ function createCodecLeafRuntimeAdapter(
577
580
  }
578
581
  }
579
582
 
583
+ function matchCodecSupport(
584
+ support: ResolvedCodecSupport,
585
+ value: unknown
586
+ ): ResolvedCodecSupport | undefined {
587
+ return resolveTypeChecker(support.storedType).snapshotType(value) ? support : undefined
588
+ }
589
+
580
590
  function createOrRuntimeAdapter(
581
591
  childTypes: ReadonlyArray<AnyStandardType>,
582
592
  getChildSupports: () => ReadonlyArray<ResolvedCodecSupport>,
@@ -607,14 +617,12 @@ function createOrRuntimeAdapter(
607
617
  }
608
618
 
609
619
  const supports = getChildSupports()
610
- for (let i = 0; i < supports.length; i++) {
611
- const storedTypeChecker = resolveTypeChecker(supports[i].storedType)
612
- if (storedTypeChecker.snapshotType(value)) {
613
- return supports[i]
614
- }
615
- }
620
+ // prefer branches whose (possibly nested) models are the closest to the snapshot ones
621
+ const matchingSupport = isObject(value)
622
+ ? findClosestModelTypeMatch(supports, matchCodecSupport, value)
623
+ : findFirstMatch(supports, matchCodecSupport, value)
616
624
 
617
- return supports[0]
625
+ return matchingSupport ?? supports[0]
618
626
  }
619
627
 
620
628
  return {
@@ -1,13 +1,21 @@
1
+ import { modelTypeKey } from "../../model/metadata"
2
+ import { getModelInfoForName } from "../../modelShared/modelInfo"
1
3
  import { failure, lazy } from "../../utils"
2
4
  import { getTypeInfo } from "../getTypeInfo"
5
+ import {
6
+ findClosestModelTypeMatch,
7
+ findFirstMatch,
8
+ getModelTypeMatchingPass,
9
+ hasSnapshotModelType,
10
+ matchUnlessModelSnapshotRejected,
11
+ } from "../modelTypeMatching"
3
12
  import {
4
13
  resolveStandardType,
5
14
  resolveStandardTypeNoThrow,
6
15
  resolveTypeChecker,
7
16
  } from "../resolveTypeChecker"
8
- import { SnapshotTypeMismatchError } from "../SnapshotTypeMismatchError"
9
17
  import type { AnyStandardType, AnyType } from "../schemas"
10
- import { TypeCheckError } from "../TypeCheckError"
18
+ import { SnapshotTypeMismatchError } from "../SnapshotTypeMismatchError"
11
19
  import {
12
20
  getTypeCheckerBaseTypeFromValue,
13
21
  lateTypeChecker,
@@ -17,6 +25,7 @@ import {
17
25
  TypeInfo,
18
26
  type TypeInfoGen,
19
27
  } from "../TypeChecker"
28
+ import { TypeCheckError } from "../TypeCheckError"
20
29
  import { typesUnchecked } from "./typesUnchecked"
21
30
 
22
31
  /**
@@ -195,17 +204,34 @@ export function typesOr(
195
204
  // this is done because:
196
205
  // 1) performance (avoid checking structure if not needed)
197
206
  // 2) so we can accept untyped models when paired with undefined | null
198
- return checkerForBaseType[0]
199
- }
200
-
201
- for (let i = 0; i < checkerForBaseType.length; i++) {
202
- const matchingType = checkerForBaseType[i].snapshotType(value)
203
- if (matchingType) {
204
- return matchingType
207
+ const candidate = checkerForBaseType[0]
208
+ if (
209
+ getModelTypeMatchingPass() !== "none" &&
210
+ valueBaseType !== TypeCheckerBaseType.Primitive
211
+ ) {
212
+ // an outer union is matching its branches, so let it know whether this one matches
213
+ // the (possibly nested) snapshot models; if it does not because a (possibly nested)
214
+ // model type rejected a model snapshot (in the exact pass, also one of a subclass),
215
+ // or because the snapshot names a registered model this branch does not accept, the
216
+ // outer union has to try other branches first, else it might pick a farther branch
217
+ // or one that rejects the snapshot
218
+ const matched = matchUnlessModelSnapshotRejected(matchSnapshotType, candidate, value)
219
+ if (
220
+ matched === undefined ||
221
+ (!matched &&
222
+ hasSnapshotModelType(value) &&
223
+ getModelInfoForName((value as any)[modelTypeKey]))
224
+ ) {
225
+ return null
226
+ }
205
227
  }
228
+ return candidate
206
229
  }
207
230
 
208
- return null
231
+ // prefer branches whose (possibly nested) models are the closest to the snapshot ones
232
+ return valueBaseType === TypeCheckerBaseType.Primitive
233
+ ? (findFirstMatch(checkerForBaseType, matchSnapshotType, value) ?? null)
234
+ : (findClosestModelTypeMatch(checkerForBaseType, matchSnapshotType, value) ?? null)
209
235
  },
210
236
 
211
237
  snapshotProcessorPlan(
@@ -272,3 +298,7 @@ export class OrTypeInfo extends TypeInfo {
272
298
  this.dispatcher = dispatcher
273
299
  }
274
300
  }
301
+
302
+ function matchSnapshotType(checker: TypeChecker, value: unknown): TypeChecker | null {
303
+ return checker.snapshotType(value)
304
+ }
@@ -1,7 +1,6 @@
1
1
  import { getTypeInfo } from "../getTypeInfo"
2
2
  import { resolveStandardType, resolveTypeChecker } from "../resolveTypeChecker"
3
3
  import type { AnyStandardType, AnyType, TypeToData } from "../schemas"
4
- import { TypeCheckError } from "../TypeCheckError"
5
4
  import {
6
5
  lateTypeChecker,
7
6
  snapshotProcessorPlan,
@@ -9,6 +8,7 @@ import {
9
8
  TypeInfo,
10
9
  type TypeInfoGen,
11
10
  } from "../TypeChecker"
11
+ import { TypeCheckError } from "../TypeCheckError"
12
12
 
13
13
  /**
14
14
  * A refinement over a given type. This allows you to do extra checks
@@ -117,7 +117,7 @@ export let hasOwnProp: (object: object, propName: PropertyKey) => boolean = (
117
117
  typeof Object.hasOwn === "function"
118
118
  ? Object.hasOwn
119
119
  : (object, propName) => {
120
- // biome-ignore lint/suspicious/noPrototypeBuiltins: legacy fallback for runtimes without Object.hasOwn.
120
+ // oxlint-disable-next-line eslint/no-prototype-builtins -- legacy fallback for runtimes without Object.hasOwn.
121
121
  return Object.prototype.hasOwnProperty.call(object, propName)
122
122
  }
123
123
 
@@ -133,7 +133,7 @@ export let hasOwnProp: (object: object, propName: PropertyKey) => boolean = (
133
133
  * @internal
134
134
  */
135
135
  export function isEqualOrBothNaN(a: unknown, b: unknown): boolean {
136
- // biome-ignore lint/suspicious/noSelfCompare: NaN check
136
+ // oxlint-disable-next-line eslint/no-self-compare -- NaN check
137
137
  return a === b || (a !== a && b !== b)
138
138
  }
139
139
 
@@ -244,19 +244,26 @@ export function isArray(val: unknown): val is any[] | IObservableArray {
244
244
  return Array.isArray(val) || isObservableArray(val)
245
245
  }
246
246
 
247
- declare const process:
248
- | {
249
- env?: Record<string, string | undefined>
250
- }
251
- | undefined
247
+ declare const process: {
248
+ env: Record<string, string | undefined>
249
+ }
250
+
251
+ function readInDevMode(): boolean {
252
+ // Bundlers replace the literal expression `process.env.NODE_ENV` with a string, so it must stay
253
+ // spelled out in full (no optional chaining, destructuring or `typeof process` guard) for dev
254
+ // mode to work in browser bundles. The try/catch keeps the library loadable where there is
255
+ // neither a bundler replacement nor a global `process`.
256
+ try {
257
+ return process.env.NODE_ENV !== undefined && process.env.NODE_ENV !== "production"
258
+ } catch {
259
+ return false
260
+ }
261
+ }
252
262
 
253
263
  /**
254
264
  * @internal
255
265
  */
256
- export const inDevMode =
257
- typeof process !== "undefined" &&
258
- process?.env?.NODE_ENV !== undefined &&
259
- process.env.NODE_ENV !== "production"
266
+ export const inDevMode = readInDevMode()
260
267
 
261
268
  /**
262
269
  * @internal
@@ -390,11 +397,11 @@ export function logWarning(type: "warn" | "error", msg: string, uniqueKey?: stri
390
397
  msg = "[mobx-keystone] " + msg
391
398
  switch (type) {
392
399
  case "warn":
393
- // biome-ignore lint/suspicious/noConsole: this internal helper intentionally emits user-facing warnings.
400
+ // oxlint-disable-next-line eslint/no-console -- this internal helper intentionally emits user-facing warnings.
394
401
  console.warn(msg)
395
402
  break
396
403
  case "error":
397
- // biome-ignore lint/suspicious/noConsole: this internal helper intentionally emits user-facing errors.
404
+ // oxlint-disable-next-line eslint/no-console -- this internal helper intentionally emits user-facing errors.
398
405
  console.error(msg)
399
406
  break
400
407
  default:
@@ -1,7 +1,7 @@
1
1
  import { modelAction } from "../action/modelAction"
2
2
  import type { AnyModel } from "../model/BaseModel"
3
- import { Model } from "../model/Model"
4
3
  import { modelIdKey } from "../model/metadata"
4
+ import { Model } from "../model/Model"
5
5
  import { model } from "../modelShared/modelDecorator"
6
6
  import { idProp } from "../modelShared/prop"
7
7
  import { typesArray } from "../types/arrayBased/typesArray"
@@ -21,9 +21,7 @@ import {
21
21
  const arraySetBase = Model({
22
22
  [modelIdKey]: idProp,
23
23
  items: tProp(typesArray(typesUnchecked<any>()), () => []), // will be properly checked by types.arraySet(subType)
24
- }) as abstract new (
25
- data: any
26
- ) => AnyModel & {
24
+ }) as abstract new (data: any) => AnyModel & {
27
25
  readonly $: {
28
26
  items: any[]
29
27
  }
@@ -35,7 +33,7 @@ const arraySetBase = Model({
35
33
  * Use `arraySet` to create it.
36
34
  */
37
35
  @model(`${namespace}/ArraySet`)
38
- // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
36
+ // oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- model base defines these properties at runtime.
39
37
  export class ArraySet<V> extends arraySetBase implements Set<V> {
40
38
  @modelAction
41
39
  add(value: V): this {
@@ -1,8 +1,8 @@
1
1
  import { entries, get, has, keys, remove, values } from "mobx"
2
2
  import { modelAction } from "../action/modelAction"
3
3
  import type { AnyModel } from "../model/BaseModel"
4
- import { Model } from "../model/Model"
5
4
  import { modelIdKey } from "../model/metadata"
5
+ import { Model } from "../model/Model"
6
6
  import { model } from "../modelShared/modelDecorator"
7
7
  import { idProp } from "../modelShared/prop"
8
8
  import { typesRecord } from "../types/objectBased/typesRecord"
@@ -14,9 +14,7 @@ import { setIfDifferent } from "../utils/setIfDifferent"
14
14
  const objectMapBase = Model({
15
15
  [modelIdKey]: idProp,
16
16
  items: tProp(typesRecord(typesUnchecked<any>()), () => ({})), // will be properly checked by types.objectMap(subType)
17
- }) as abstract new (
18
- data: any
19
- ) => AnyModel & {
17
+ }) as abstract new (data: any) => AnyModel & {
20
18
  readonly $: {
21
19
  items: Record<string, any>
22
20
  }
@@ -28,7 +26,7 @@ const objectMapBase = Model({
28
26
  * Use `objectMap` to create it.
29
27
  */
30
28
  @model(`${namespace}/ObjectMap`)
31
- // biome-ignore lint/suspicious/noUnsafeDeclarationMerging: model base defines these properties at runtime.
29
+ // oxlint-disable-next-line typescript/no-unsafe-declaration-merging -- model base defines these properties at runtime.
32
30
  export class ObjectMap<V> extends objectMapBase implements Map<string, V> {
33
31
  @modelAction
34
32
  clear(): void {