@fluidframework/tree 2.10.0-305357 → 2.10.0-307060

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 (292) hide show
  1. package/.eslintrc.cjs +56 -25
  2. package/api-report/tree.alpha.api.md +14 -11
  3. package/api-report/tree.beta.api.md +5 -2
  4. package/api-report/tree.legacy.alpha.api.md +5 -2
  5. package/api-report/tree.legacy.public.api.md +5 -2
  6. package/api-report/tree.public.api.md +5 -2
  7. package/dist/core/forest/forest.d.ts +5 -1
  8. package/dist/core/forest/forest.d.ts.map +1 -1
  9. package/dist/core/forest/forest.js.map +1 -1
  10. package/dist/core/index.d.ts +1 -1
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/schema-stored/storedSchemaRepository.d.ts +7 -3
  14. package/dist/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  15. package/dist/core/schema-stored/storedSchemaRepository.js +4 -6
  16. package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
  17. package/dist/core/tree/anchorSet.d.ts +8 -5
  18. package/dist/core/tree/anchorSet.d.ts.map +1 -1
  19. package/dist/core/tree/anchorSet.js +12 -11
  20. package/dist/core/tree/anchorSet.js.map +1 -1
  21. package/dist/events/emitter.d.ts +21 -9
  22. package/dist/events/emitter.d.ts.map +1 -1
  23. package/dist/events/emitter.js +36 -21
  24. package/dist/events/emitter.js.map +1 -1
  25. package/dist/events/listeners.d.ts +16 -5
  26. package/dist/events/listeners.d.ts.map +1 -1
  27. package/dist/events/listeners.js.map +1 -1
  28. package/dist/feature-libraries/chunked-forest/basicChunk.d.ts +26 -5
  29. package/dist/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
  30. package/dist/feature-libraries/chunked-forest/basicChunk.js +15 -5
  31. package/dist/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
  32. package/dist/feature-libraries/chunked-forest/chunkTree.js +1 -1
  33. package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  34. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
  35. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  36. package/dist/feature-libraries/chunked-forest/chunkedForest.js +19 -9
  37. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  38. package/dist/feature-libraries/flex-tree/context.d.ts +3 -2
  39. package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
  40. package/dist/feature-libraries/flex-tree/context.js +3 -3
  41. package/dist/feature-libraries/flex-tree/context.js.map +1 -1
  42. package/dist/feature-libraries/flex-tree/lazyField.js +1 -1
  43. package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
  44. package/dist/feature-libraries/flex-tree/lazyNode.js +1 -1
  45. package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  46. package/dist/feature-libraries/flex-tree/utilities.js +1 -1
  47. package/dist/feature-libraries/flex-tree/utilities.js.map +1 -1
  48. package/dist/feature-libraries/index.d.ts +1 -1
  49. package/dist/feature-libraries/index.d.ts.map +1 -1
  50. package/dist/feature-libraries/index.js +2 -2
  51. package/dist/feature-libraries/index.js.map +1 -1
  52. package/dist/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
  53. package/dist/feature-libraries/modular-schema/comparison.js +3 -0
  54. package/dist/feature-libraries/modular-schema/comparison.js.map +1 -1
  55. package/dist/feature-libraries/modular-schema/discrepancies.d.ts +29 -29
  56. package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  57. package/dist/feature-libraries/modular-schema/discrepancies.js +121 -75
  58. package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  59. package/dist/feature-libraries/modular-schema/genericFieldKind.js +2 -2
  60. package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  61. package/dist/feature-libraries/modular-schema/index.d.ts +1 -1
  62. package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
  63. package/dist/feature-libraries/modular-schema/index.js +2 -2
  64. package/dist/feature-libraries/modular-schema/index.js.map +1 -1
  65. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
  66. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  67. package/dist/feature-libraries/object-forest/objectForest.d.ts +2 -2
  68. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  69. package/dist/feature-libraries/object-forest/objectForest.js +6 -8
  70. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  71. package/dist/feature-libraries/schema-index/schemaSummarizer.js +1 -1
  72. package/dist/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  73. package/dist/feature-libraries/sequence-field/compose.js +2 -2
  74. package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
  75. package/dist/feature-libraries/sequence-field/markListFactory.js +1 -1
  76. package/dist/feature-libraries/sequence-field/markListFactory.js.map +1 -1
  77. package/dist/packageVersion.d.ts +1 -1
  78. package/dist/packageVersion.js +1 -1
  79. package/dist/packageVersion.js.map +1 -1
  80. package/dist/shared-tree/schematizingTreeView.js +2 -2
  81. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  82. package/dist/shared-tree/treeApi.js +6 -3
  83. package/dist/shared-tree/treeApi.js.map +1 -1
  84. package/dist/shared-tree/treeCheckout.js +7 -7
  85. package/dist/shared-tree/treeCheckout.js.map +1 -1
  86. package/dist/shared-tree-core/branch.d.ts +7 -7
  87. package/dist/shared-tree-core/branch.d.ts.map +1 -1
  88. package/dist/shared-tree-core/branch.js +35 -25
  89. package/dist/shared-tree-core/branch.js.map +1 -1
  90. package/dist/shared-tree-core/editManager.js +4 -4
  91. package/dist/shared-tree-core/editManager.js.map +1 -1
  92. package/dist/shared-tree-core/sharedTreeCore.js +5 -5
  93. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  94. package/dist/simple-tree/api/schemaCreationUtilities.d.ts +12 -14
  95. package/dist/simple-tree/api/schemaCreationUtilities.d.ts.map +1 -1
  96. package/dist/simple-tree/api/schemaCreationUtilities.js +9 -7
  97. package/dist/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  98. package/dist/simple-tree/api/schemaFactory.d.ts +68 -10
  99. package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
  100. package/dist/simple-tree/api/schemaFactory.js +38 -10
  101. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  102. package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
  103. package/dist/simple-tree/api/treeNodeApi.js +4 -4
  104. package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
  105. package/dist/simple-tree/arrayNode.js +1 -1
  106. package/dist/simple-tree/arrayNode.js.map +1 -1
  107. package/dist/simple-tree/core/treeNodeKernel.d.ts +7 -8
  108. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  109. package/dist/simple-tree/core/treeNodeKernel.js +68 -73
  110. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  111. package/dist/simple-tree/objectNode.d.ts +1 -1
  112. package/dist/simple-tree/objectNode.js.map +1 -1
  113. package/dist/simple-tree/objectNodeTypes.d.ts +3 -0
  114. package/dist/simple-tree/objectNodeTypes.d.ts.map +1 -1
  115. package/dist/simple-tree/objectNodeTypes.js +3 -1
  116. package/dist/simple-tree/objectNodeTypes.js.map +1 -1
  117. package/dist/simple-tree/proxies.js +1 -1
  118. package/dist/simple-tree/proxies.js.map +1 -1
  119. package/dist/simple-tree/schemaTypes.d.ts +26 -1
  120. package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
  121. package/dist/simple-tree/schemaTypes.js.map +1 -1
  122. package/dist/simple-tree/treeNodeValid.js +2 -2
  123. package/dist/simple-tree/treeNodeValid.js.map +1 -1
  124. package/dist/util/nestedMap.d.ts.map +1 -1
  125. package/dist/util/nestedMap.js.map +1 -1
  126. package/docs/.attachments/object-merge-semantics.drawio +145 -0
  127. package/docs/user-facing/array-merge-semantics.md +344 -0
  128. package/docs/user-facing/map-merge-semantics.md +128 -0
  129. package/docs/user-facing/merge-semantics.md +7 -3
  130. package/docs/user-facing/object-merge-semantics.md +77 -0
  131. package/lib/core/forest/forest.d.ts +5 -1
  132. package/lib/core/forest/forest.d.ts.map +1 -1
  133. package/lib/core/forest/forest.js.map +1 -1
  134. package/lib/core/index.d.ts +1 -1
  135. package/lib/core/index.d.ts.map +1 -1
  136. package/lib/core/index.js.map +1 -1
  137. package/lib/core/schema-stored/storedSchemaRepository.d.ts +7 -3
  138. package/lib/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  139. package/lib/core/schema-stored/storedSchemaRepository.js +4 -6
  140. package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
  141. package/lib/core/tree/anchorSet.d.ts +8 -5
  142. package/lib/core/tree/anchorSet.d.ts.map +1 -1
  143. package/lib/core/tree/anchorSet.js +12 -11
  144. package/lib/core/tree/anchorSet.js.map +1 -1
  145. package/lib/events/emitter.d.ts +21 -9
  146. package/lib/events/emitter.d.ts.map +1 -1
  147. package/lib/events/emitter.js +37 -22
  148. package/lib/events/emitter.js.map +1 -1
  149. package/lib/events/listeners.d.ts +16 -5
  150. package/lib/events/listeners.d.ts.map +1 -1
  151. package/lib/events/listeners.js.map +1 -1
  152. package/lib/feature-libraries/chunked-forest/basicChunk.d.ts +26 -5
  153. package/lib/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
  154. package/lib/feature-libraries/chunked-forest/basicChunk.js +15 -5
  155. package/lib/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
  156. package/lib/feature-libraries/chunked-forest/chunkTree.js +1 -1
  157. package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  158. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
  159. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  160. package/lib/feature-libraries/chunked-forest/chunkedForest.js +19 -9
  161. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  162. package/lib/feature-libraries/flex-tree/context.d.ts +3 -2
  163. package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
  164. package/lib/feature-libraries/flex-tree/context.js +3 -3
  165. package/lib/feature-libraries/flex-tree/context.js.map +1 -1
  166. package/lib/feature-libraries/flex-tree/lazyField.js +1 -1
  167. package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
  168. package/lib/feature-libraries/flex-tree/lazyNode.js +1 -1
  169. package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  170. package/lib/feature-libraries/flex-tree/utilities.js +1 -1
  171. package/lib/feature-libraries/flex-tree/utilities.js.map +1 -1
  172. package/lib/feature-libraries/index.d.ts +1 -1
  173. package/lib/feature-libraries/index.d.ts.map +1 -1
  174. package/lib/feature-libraries/index.js +1 -1
  175. package/lib/feature-libraries/index.js.map +1 -1
  176. package/lib/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
  177. package/lib/feature-libraries/modular-schema/comparison.js +3 -0
  178. package/lib/feature-libraries/modular-schema/comparison.js.map +1 -1
  179. package/lib/feature-libraries/modular-schema/discrepancies.d.ts +29 -29
  180. package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  181. package/lib/feature-libraries/modular-schema/discrepancies.js +120 -74
  182. package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  183. package/lib/feature-libraries/modular-schema/genericFieldKind.js +2 -2
  184. package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  185. package/lib/feature-libraries/modular-schema/index.d.ts +1 -1
  186. package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
  187. package/lib/feature-libraries/modular-schema/index.js +1 -1
  188. package/lib/feature-libraries/modular-schema/index.js.map +1 -1
  189. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
  190. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  191. package/lib/feature-libraries/object-forest/objectForest.d.ts +2 -2
  192. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  193. package/lib/feature-libraries/object-forest/objectForest.js +6 -8
  194. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  195. package/lib/feature-libraries/schema-index/schemaSummarizer.js +1 -1
  196. package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  197. package/lib/feature-libraries/sequence-field/compose.js +2 -2
  198. package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
  199. package/lib/feature-libraries/sequence-field/markListFactory.js +1 -1
  200. package/lib/feature-libraries/sequence-field/markListFactory.js.map +1 -1
  201. package/lib/packageVersion.d.ts +1 -1
  202. package/lib/packageVersion.js +1 -1
  203. package/lib/packageVersion.js.map +1 -1
  204. package/lib/shared-tree/schematizingTreeView.js +2 -2
  205. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  206. package/lib/shared-tree/treeApi.js +7 -4
  207. package/lib/shared-tree/treeApi.js.map +1 -1
  208. package/lib/shared-tree/treeCheckout.js +7 -7
  209. package/lib/shared-tree/treeCheckout.js.map +1 -1
  210. package/lib/shared-tree-core/branch.d.ts +7 -7
  211. package/lib/shared-tree-core/branch.d.ts.map +1 -1
  212. package/lib/shared-tree-core/branch.js +36 -26
  213. package/lib/shared-tree-core/branch.js.map +1 -1
  214. package/lib/shared-tree-core/editManager.js +4 -4
  215. package/lib/shared-tree-core/editManager.js.map +1 -1
  216. package/lib/shared-tree-core/sharedTreeCore.js +5 -5
  217. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  218. package/lib/simple-tree/api/schemaCreationUtilities.d.ts +12 -14
  219. package/lib/simple-tree/api/schemaCreationUtilities.d.ts.map +1 -1
  220. package/lib/simple-tree/api/schemaCreationUtilities.js +9 -7
  221. package/lib/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  222. package/lib/simple-tree/api/schemaFactory.d.ts +68 -10
  223. package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
  224. package/lib/simple-tree/api/schemaFactory.js +38 -10
  225. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  226. package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
  227. package/lib/simple-tree/api/treeNodeApi.js +4 -4
  228. package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
  229. package/lib/simple-tree/arrayNode.js +1 -1
  230. package/lib/simple-tree/arrayNode.js.map +1 -1
  231. package/lib/simple-tree/core/treeNodeKernel.d.ts +7 -8
  232. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  233. package/lib/simple-tree/core/treeNodeKernel.js +69 -74
  234. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  235. package/lib/simple-tree/objectNode.d.ts +1 -1
  236. package/lib/simple-tree/objectNode.js.map +1 -1
  237. package/lib/simple-tree/objectNodeTypes.d.ts +3 -0
  238. package/lib/simple-tree/objectNodeTypes.d.ts.map +1 -1
  239. package/lib/simple-tree/objectNodeTypes.js +3 -1
  240. package/lib/simple-tree/objectNodeTypes.js.map +1 -1
  241. package/lib/simple-tree/proxies.js +1 -1
  242. package/lib/simple-tree/proxies.js.map +1 -1
  243. package/lib/simple-tree/schemaTypes.d.ts +26 -1
  244. package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
  245. package/lib/simple-tree/schemaTypes.js.map +1 -1
  246. package/lib/simple-tree/treeNodeValid.js +2 -2
  247. package/lib/simple-tree/treeNodeValid.js.map +1 -1
  248. package/lib/util/nestedMap.d.ts.map +1 -1
  249. package/lib/util/nestedMap.js.map +1 -1
  250. package/package.json +20 -20
  251. package/src/core/forest/forest.ts +6 -1
  252. package/src/core/index.ts +1 -1
  253. package/src/core/schema-stored/storedSchemaRepository.ts +10 -13
  254. package/src/core/tree/anchorSet.ts +13 -20
  255. package/src/events/emitter.ts +45 -24
  256. package/src/events/listeners.ts +17 -5
  257. package/src/feature-libraries/chunked-forest/basicChunk.ts +12 -4
  258. package/src/feature-libraries/chunked-forest/chunkTree.ts +1 -1
  259. package/src/feature-libraries/chunked-forest/chunkedForest.ts +13 -14
  260. package/src/feature-libraries/flex-tree/context.ts +5 -7
  261. package/src/feature-libraries/flex-tree/lazyField.ts +1 -1
  262. package/src/feature-libraries/flex-tree/lazyNode.ts +1 -1
  263. package/src/feature-libraries/flex-tree/utilities.ts +1 -1
  264. package/src/feature-libraries/index.ts +1 -1
  265. package/src/feature-libraries/modular-schema/comparison.ts +4 -0
  266. package/src/feature-libraries/modular-schema/discrepancies.ts +188 -124
  267. package/src/feature-libraries/modular-schema/genericFieldKind.ts +2 -2
  268. package/src/feature-libraries/modular-schema/index.ts +4 -1
  269. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1 -1
  270. package/src/feature-libraries/object-forest/objectForest.ts +5 -11
  271. package/src/feature-libraries/schema-index/schemaSummarizer.ts +1 -1
  272. package/src/feature-libraries/sequence-field/compose.ts +2 -2
  273. package/src/feature-libraries/sequence-field/markListFactory.ts +1 -1
  274. package/src/packageVersion.ts +1 -1
  275. package/src/shared-tree/schematizingTreeView.ts +2 -2
  276. package/src/shared-tree/treeApi.ts +9 -7
  277. package/src/shared-tree/treeCheckout.ts +7 -7
  278. package/src/shared-tree-core/branch.ts +30 -30
  279. package/src/shared-tree-core/editManager.ts +4 -4
  280. package/src/shared-tree-core/sharedTreeCore.ts +5 -5
  281. package/src/simple-tree/api/schemaCreationUtilities.ts +29 -17
  282. package/src/simple-tree/api/schemaFactory.ts +62 -29
  283. package/src/simple-tree/api/schemaFactoryRecursive.ts +1 -1
  284. package/src/simple-tree/api/treeNodeApi.ts +4 -4
  285. package/src/simple-tree/arrayNode.ts +1 -1
  286. package/src/simple-tree/core/treeNodeKernel.ts +68 -72
  287. package/src/simple-tree/objectNode.ts +1 -1
  288. package/src/simple-tree/objectNodeTypes.ts +3 -1
  289. package/src/simple-tree/proxies.ts +1 -1
  290. package/src/simple-tree/schemaTypes.ts +26 -1
  291. package/src/simple-tree/treeNodeValid.ts +2 -2
  292. package/src/util/nestedMap.ts +1 -0
@@ -11,12 +11,14 @@ import {
11
11
  LeafNodeStoredSchema,
12
12
  MapNodeStoredSchema,
13
13
  ObjectNodeStoredSchema,
14
+ storedEmptyFieldSchema,
14
15
  type TreeFieldStoredSchema,
15
16
  type TreeNodeSchemaIdentifier,
16
17
  type TreeStoredSchema,
17
18
  type TreeTypeSet,
18
19
  type ValueSchema,
19
20
  } from "../../core/index.js";
21
+ import { brand } from "../../util/index.js";
20
22
 
21
23
  // TODO:
22
24
  // The comparisons in this file seem redundant with those in comparison.ts.
@@ -25,45 +27,45 @@ import {
25
27
  /**
26
28
  * @remarks
27
29
  *
28
- * 1. FieldIncompatibility
30
+ * 1. FieldDiscrepancy
29
31
  *
30
- * `FieldIncompatibility` represents the differences between two `TreeFieldStoredSchema` objects. It consists of
32
+ * `FieldDiscrepancy` represents the differences between two `TreeFieldStoredSchema` objects. It consists of
31
33
  * three types of incompatibilities:
32
34
  *
33
- * - FieldKindIncompatibility: Indicates the differences in `FieldKindIdentifier` between two `TreeFieldStoredSchema`
35
+ * - FieldKindDiscrepancy: Indicates the differences in `FieldKindIdentifier` between two `TreeFieldStoredSchema`
34
36
  * objects (e.g., optional, required, sequence, etc.).
35
- * - AllowedTypesIncompatibility: Indicates the differences in the allowed child types between the two schemas.
36
- * - ValueSchemaIncompatibility: Specifically indicates the differences in the `ValueSchema` of two
37
+ * - AllowedTypesDiscrepancy: Indicates the differences in the allowed child types between the two schemas.
38
+ * - ValueSchemaDiscrepancy: Specifically indicates the differences in the `ValueSchema` of two
37
39
  * `LeafNodeStoredSchema` objects.
38
40
  *
39
- * 2. NodeIncompatibility
41
+ * 2. NodeDiscrepancy
40
42
  *
41
- * `NodeIncompatibility` represents the differences between two `TreeNodeStoredSchema` objects and includes:
43
+ * `NodeDiscrepancy` represents the differences between two `TreeNodeStoredSchema` objects and includes:
42
44
  *
43
- * - NodeKindIncompatibility: Indicates the differences in the types of `TreeNodeStoredSchema` (currently supports
45
+ * - NodeKindDiscrepancy: Indicates the differences in the types of `TreeNodeStoredSchema` (currently supports
44
46
  * `ObjectNodeStoredSchema`, `MapNodeStoredSchema`, and `LeafNodeStoredSchema`).
45
- * - NodeFieldsIncompatibility: Indicates the `FieldIncompatibility` of `TreeFieldStoredSchema` within two
46
- * `TreeNodeStoredSchema`. It includes an array of `FieldIncompatibility` instances in the `differences` field.
47
+ * - NodeFieldsDiscrepancy: Indicates the `FieldDiscrepancy` of `TreeFieldStoredSchema` within two
48
+ * `TreeNodeStoredSchema`. It includes an array of `FieldDiscrepancy` instances in the `differences` field.
47
49
  *
48
50
  * When comparing two nodes for compatibility, it only makes sense to compare their fields if the nodes are of
49
51
  * the same kind (map, object, leaf).
50
52
  *
51
- * 3. Incompatibility
53
+ * 3. Discrepancy
52
54
  *
53
- * Incompatibility consists of both `NodeIncompatibility` and `FieldIncompatibility`, representing any kind of
54
- * schema differences. See {@link getAllowedContentIncompatibilities} for more details about how we process it
55
+ * Discrepancy consists of both `NodeDiscrepancy` and `FieldDiscrepancy`, representing any kind of
56
+ * schema differences. See {@link getAllowedContentDiscrepancies} for more details about how we process it
55
57
  * and the ordering.
56
58
  */
57
- export type Incompatibility = FieldIncompatibility | NodeIncompatibility;
59
+ export type Discrepancy = FieldDiscrepancy | NodeDiscrepancy;
58
60
 
59
- export type NodeIncompatibility = NodeKindIncompatibility | NodeFieldsIncompatibility;
61
+ export type NodeDiscrepancy = NodeKindDiscrepancy | NodeFieldsDiscrepancy;
60
62
 
61
- export type FieldIncompatibility =
62
- | AllowedTypeIncompatibility
63
- | FieldKindIncompatibility
64
- | ValueSchemaIncompatibility;
63
+ export type FieldDiscrepancy =
64
+ | AllowedTypeDiscrepancy
65
+ | FieldKindDiscrepancy
66
+ | ValueSchemaDiscrepancy;
65
67
 
66
- export interface AllowedTypeIncompatibility {
68
+ export interface AllowedTypeDiscrepancy {
67
69
  identifier: string | undefined; // undefined indicates root field schema
68
70
  mismatch: "allowedTypes";
69
71
  /**
@@ -76,62 +78,60 @@ export interface AllowedTypeIncompatibility {
76
78
  stored: string[];
77
79
  }
78
80
 
79
- export interface FieldKindIncompatibility {
81
+ export interface FieldKindDiscrepancy {
80
82
  identifier: string | undefined; // undefined indicates root field schema
81
83
  mismatch: "fieldKind";
82
- view: FieldKindIdentifier | undefined;
83
- stored: FieldKindIdentifier | undefined;
84
+ view: FieldKindIdentifier;
85
+ stored: FieldKindIdentifier;
84
86
  }
85
87
 
86
- export interface ValueSchemaIncompatibility {
88
+ export interface ValueSchemaDiscrepancy {
87
89
  identifier: string;
88
90
  mismatch: "valueSchema";
89
91
  view: ValueSchema | undefined;
90
92
  stored: ValueSchema | undefined;
91
93
  }
92
94
 
93
- export interface NodeKindIncompatibility {
95
+ export interface NodeKindDiscrepancy {
94
96
  identifier: string;
95
97
  mismatch: "nodeKind";
96
98
  view: SchemaFactoryNodeKind | undefined;
97
99
  stored: SchemaFactoryNodeKind | undefined;
98
100
  }
99
101
 
100
- export interface NodeFieldsIncompatibility {
102
+ export interface NodeFieldsDiscrepancy {
101
103
  identifier: string;
102
104
  mismatch: "fields";
103
- differences: FieldIncompatibility[];
105
+ differences: FieldDiscrepancy[];
104
106
  }
105
107
 
106
108
  type SchemaFactoryNodeKind = "object" | "leaf" | "map";
107
109
 
108
110
  /**
109
- * @remarks
111
+ * Finds and reports discrepancies between a view schema and a stored schema.
110
112
  *
111
113
  * The workflow for finding schema incompatibilities:
112
- * 1. Compare the two root schemas to identify any `FieldIncompatibility`.
114
+ * 1. Compare the two root schemas to identify any `FieldDiscrepancy`.
113
115
  *
114
116
  * 2. For each node schema in the `view`:
115
117
  * - Verify if the node schema exists in the stored. If it does, ensure that the `SchemaFactoryNodeKind` are
116
- * consistent. Otherwise this difference is treated as `NodeKindIncompatibility`
118
+ * consistent. Otherwise this difference is treated as `NodeKindDiscrepancy`
117
119
  * - If a node schema with the same identifier exists in both view and stored, and their `SchemaFactoryNodeKind`
118
- * are consistent, perform a exhaustive validation to identify all `FieldIncompatibility`.
120
+ * are consistent, perform a exhaustive validation to identify all `FieldDiscrepancy`.
119
121
  *
120
122
  * 3. For each node schema in the stored, verify if it exists in the view. The overlapping parts were already
121
123
  * addressed in the previous step.
122
124
  *
123
125
  * @returns the discrepancies between two TreeStoredSchema objects
124
126
  */
125
- export function getAllowedContentIncompatibilities(
127
+ export function getAllowedContentDiscrepancies(
126
128
  view: TreeStoredSchema,
127
129
  stored: TreeStoredSchema,
128
- ): Incompatibility[] {
129
- const incompatibilities: Incompatibility[] = [];
130
+ ): Discrepancy[] {
131
+ const discrepancies: Discrepancy[] = [];
130
132
 
131
133
  // check root schema discrepancies
132
- incompatibilities.push(
133
- ...trackFieldDiscrepancies(view.rootFieldSchema, stored.rootFieldSchema),
134
- );
134
+ discrepancies.push(...trackFieldDiscrepancies(view.rootFieldSchema, stored.rootFieldSchema));
135
135
 
136
136
  // Verify the existence and type of a node schema given its identifier (key), then determine if
137
137
  // an exhaustive search is necessary.
@@ -141,7 +141,7 @@ export function getAllowedContentIncompatibilities(
141
141
 
142
142
  if (viewNodeSchema instanceof ObjectNodeStoredSchema) {
143
143
  if (!stored.nodeSchema.has(key)) {
144
- incompatibilities.push({
144
+ discrepancies.push({
145
145
  identifier: key,
146
146
  mismatch: "nodeKind",
147
147
  view: "object",
@@ -154,27 +154,27 @@ export function getAllowedContentIncompatibilities(
154
154
  0x9be /* The storedNodeSchema in stored.nodeSchema should not be undefined */,
155
155
  );
156
156
  if (storedNodeSchema instanceof MapNodeStoredSchema) {
157
- incompatibilities.push({
157
+ discrepancies.push({
158
158
  identifier: key,
159
159
  mismatch: "nodeKind",
160
160
  view: "object",
161
161
  stored: "map",
162
- } satisfies NodeKindIncompatibility);
162
+ } satisfies NodeKindDiscrepancy);
163
163
  } else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
164
- incompatibilities.push({
164
+ discrepancies.push({
165
165
  identifier: key,
166
166
  mismatch: "nodeKind",
167
167
  view: "object",
168
168
  stored: "leaf",
169
- } satisfies NodeKindIncompatibility);
169
+ } satisfies NodeKindDiscrepancy);
170
170
  } else if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
171
171
  const differences = trackObjectNodeDiscrepancies(viewNodeSchema, storedNodeSchema);
172
172
  if (differences.length > 0) {
173
- incompatibilities.push({
173
+ discrepancies.push({
174
174
  identifier: key,
175
175
  mismatch: "fields",
176
176
  differences,
177
- } satisfies NodeFieldsIncompatibility);
177
+ } satisfies NodeFieldsDiscrepancy);
178
178
  }
179
179
  } else {
180
180
  throwUnsupportedNodeType(storedNodeSchema.constructor.name);
@@ -182,12 +182,12 @@ export function getAllowedContentIncompatibilities(
182
182
  }
183
183
  } else if (viewNodeSchema instanceof MapNodeStoredSchema) {
184
184
  if (!stored.nodeSchema.has(key)) {
185
- incompatibilities.push({
185
+ discrepancies.push({
186
186
  identifier: key,
187
187
  mismatch: "nodeKind",
188
188
  view: "map",
189
189
  stored: undefined,
190
- } satisfies NodeKindIncompatibility);
190
+ } satisfies NodeKindDiscrepancy);
191
191
  } else {
192
192
  const storedNodeSchema = stored.nodeSchema.get(key);
193
193
  assert(
@@ -195,21 +195,21 @@ export function getAllowedContentIncompatibilities(
195
195
  0x9bf /* The storedNodeSchema in stored.nodeSchema should not be undefined */,
196
196
  );
197
197
  if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
198
- incompatibilities.push({
198
+ discrepancies.push({
199
199
  identifier: key,
200
200
  mismatch: "nodeKind",
201
201
  view: "map",
202
202
  stored: "object",
203
- } satisfies NodeKindIncompatibility);
203
+ } satisfies NodeKindDiscrepancy);
204
204
  } else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
205
- incompatibilities.push({
205
+ discrepancies.push({
206
206
  identifier: key,
207
207
  mismatch: "nodeKind",
208
208
  view: "map",
209
209
  stored: "leaf",
210
- } satisfies NodeKindIncompatibility);
210
+ } satisfies NodeKindDiscrepancy);
211
211
  } else if (storedNodeSchema instanceof MapNodeStoredSchema) {
212
- incompatibilities.push(
212
+ discrepancies.push(
213
213
  ...trackFieldDiscrepancies(
214
214
  viewNodeSchema.mapFields,
215
215
  storedNodeSchema.mapFields,
@@ -222,7 +222,7 @@ export function getAllowedContentIncompatibilities(
222
222
  }
223
223
  } else if (viewNodeSchema instanceof LeafNodeStoredSchema) {
224
224
  if (!stored.nodeSchema.has(key)) {
225
- incompatibilities.push({
225
+ discrepancies.push({
226
226
  identifier: key,
227
227
  mismatch: "nodeKind",
228
228
  view: "leaf",
@@ -235,27 +235,27 @@ export function getAllowedContentIncompatibilities(
235
235
  0x9c0 /* The storedNodeSchema in stored.nodeSchema should not be undefined */,
236
236
  );
237
237
  if (storedNodeSchema instanceof MapNodeStoredSchema) {
238
- incompatibilities.push({
238
+ discrepancies.push({
239
239
  identifier: key,
240
240
  mismatch: "nodeKind",
241
241
  view: "leaf",
242
242
  stored: "map",
243
- } satisfies NodeKindIncompatibility);
243
+ } satisfies NodeKindDiscrepancy);
244
244
  } else if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
245
- incompatibilities.push({
245
+ discrepancies.push({
246
246
  identifier: key,
247
247
  mismatch: "nodeKind",
248
248
  view: "leaf",
249
249
  stored: "object",
250
- } satisfies NodeKindIncompatibility);
250
+ } satisfies NodeKindDiscrepancy);
251
251
  } else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
252
252
  if (viewNodeSchema.leafValue !== storedNodeSchema.leafValue) {
253
- incompatibilities.push({
253
+ discrepancies.push({
254
254
  identifier: key,
255
255
  mismatch: "valueSchema",
256
256
  view: viewNodeSchema.leafValue,
257
257
  stored: storedNodeSchema.leafValue,
258
- } satisfies ValueSchemaIncompatibility);
258
+ } satisfies ValueSchemaDiscrepancy);
259
259
  }
260
260
  } else {
261
261
  throwUnsupportedNodeType(storedNodeSchema.constructor.name);
@@ -268,7 +268,7 @@ export function getAllowedContentIncompatibilities(
268
268
 
269
269
  for (const [key, storedNodeSchema] of stored.nodeSchema) {
270
270
  if (!viewNodeKeys.has(key)) {
271
- incompatibilities.push({
271
+ discrepancies.push({
272
272
  identifier: key,
273
273
  mismatch: "nodeKind",
274
274
  view: undefined,
@@ -278,11 +278,11 @@ export function getAllowedContentIncompatibilities(
278
278
  : storedNodeSchema instanceof ObjectNodeStoredSchema
279
279
  ? "object"
280
280
  : "leaf",
281
- } satisfies NodeKindIncompatibility);
281
+ } satisfies NodeKindDiscrepancy);
282
282
  }
283
283
  }
284
284
 
285
- return incompatibilities;
285
+ return discrepancies;
286
286
  }
287
287
 
288
288
  /**
@@ -294,8 +294,8 @@ function trackFieldDiscrepancies(
294
294
  view: TreeFieldStoredSchema,
295
295
  stored: TreeFieldStoredSchema,
296
296
  keyOrRoot?: string,
297
- ): FieldIncompatibility[] {
298
- const differences: FieldIncompatibility[] = [];
297
+ ): FieldDiscrepancy[] {
298
+ const differences: FieldDiscrepancy[] = [];
299
299
 
300
300
  // Only track the symmetric differences of two sets.
301
301
  const findSetDiscrepancies = (
@@ -314,7 +314,7 @@ function trackFieldDiscrepancies(
314
314
  mismatch: "allowedTypes",
315
315
  view: allowedTypesDiscrepancies[0],
316
316
  stored: allowedTypesDiscrepancies[1],
317
- } satisfies AllowedTypeIncompatibility);
317
+ } satisfies AllowedTypeDiscrepancy);
318
318
  }
319
319
 
320
320
  if (view.kind !== stored.kind) {
@@ -323,7 +323,7 @@ function trackFieldDiscrepancies(
323
323
  mismatch: "fieldKind",
324
324
  view: view.kind,
325
325
  stored: stored.kind,
326
- } satisfies FieldKindIncompatibility);
326
+ } satisfies FieldKindDiscrepancy);
327
327
  }
328
328
 
329
329
  return differences;
@@ -332,8 +332,8 @@ function trackFieldDiscrepancies(
332
332
  function trackObjectNodeDiscrepancies(
333
333
  view: ObjectNodeStoredSchema,
334
334
  stored: ObjectNodeStoredSchema,
335
- ): FieldIncompatibility[] {
336
- const differences: FieldIncompatibility[] = [];
335
+ ): FieldDiscrepancy[] {
336
+ const differences: FieldDiscrepancy[] = [];
337
337
  const viewFieldKeys = new Set<FieldKey>();
338
338
  /**
339
339
  * Similar to the logic used for tracking discrepancies between two node schemas, we will identify
@@ -348,13 +348,16 @@ function trackObjectNodeDiscrepancies(
348
348
 
349
349
  for (const [fieldKey, fieldStoredSchema] of view.objectNodeFields) {
350
350
  viewFieldKeys.add(fieldKey);
351
- if (!stored.objectNodeFields.has(fieldKey)) {
351
+ if (
352
+ !stored.objectNodeFields.has(fieldKey) &&
353
+ fieldStoredSchema.kind !== storedEmptyFieldSchema.kind
354
+ ) {
352
355
  differences.push({
353
356
  identifier: fieldKey,
354
357
  mismatch: "fieldKind",
355
358
  view: fieldStoredSchema.kind,
356
- stored: undefined,
357
- } satisfies FieldKindIncompatibility);
359
+ stored: storedEmptyFieldSchema.kind,
360
+ } satisfies FieldKindDiscrepancy);
358
361
  } else {
359
362
  differences.push(
360
363
  ...trackFieldDiscrepancies(
@@ -370,12 +373,15 @@ function trackObjectNodeDiscrepancies(
370
373
  if (viewFieldKeys.has(fieldKey)) {
371
374
  continue;
372
375
  }
373
- differences.push({
374
- identifier: fieldKey,
375
- mismatch: "fieldKind",
376
- view: undefined,
377
- stored: fieldStoredSchema.kind,
378
- } satisfies FieldKindIncompatibility);
376
+
377
+ if (fieldStoredSchema.kind !== storedEmptyFieldSchema.kind) {
378
+ differences.push({
379
+ identifier: fieldKey,
380
+ mismatch: "fieldKind",
381
+ view: storedEmptyFieldSchema.kind,
382
+ stored: fieldStoredSchema.kind,
383
+ } satisfies FieldKindDiscrepancy);
384
+ }
379
385
  }
380
386
 
381
387
  return differences;
@@ -399,24 +405,28 @@ function trackObjectNodeDiscrepancies(
399
405
  * validating internal fields.
400
406
  */
401
407
  export function isRepoSuperset(view: TreeStoredSchema, stored: TreeStoredSchema): boolean {
402
- const incompatibilities = getAllowedContentIncompatibilities(view, stored);
408
+ const discrepancies = getAllowedContentDiscrepancies(view, stored);
403
409
 
404
- for (const incompatibility of incompatibilities) {
405
- switch (incompatibility.mismatch) {
410
+ for (const discrepancy of discrepancies) {
411
+ switch (discrepancy.mismatch) {
406
412
  case "nodeKind": {
407
- return false;
413
+ if (discrepancy.stored !== undefined) {
414
+ // It's fine for the view schema to know of a node type that the stored schema doesn't know about.
415
+ return false;
416
+ }
417
+ break;
408
418
  }
409
419
  case "valueSchema":
410
420
  case "allowedTypes":
411
421
  case "fieldKind": {
412
- if (!validateFieldIncompatibility(incompatibility)) {
422
+ if (!validateFieldIncompatibility(discrepancy)) {
413
423
  return false;
414
424
  }
415
425
  break;
416
426
  }
417
427
  case "fields": {
418
428
  if (
419
- incompatibility.differences.some(
429
+ discrepancy.differences.some(
420
430
  (difference) => !validateFieldIncompatibility(difference),
421
431
  )
422
432
  ) {
@@ -430,26 +440,16 @@ export function isRepoSuperset(view: TreeStoredSchema, stored: TreeStoredSchema)
430
440
  return true;
431
441
  }
432
442
 
433
- function validateFieldIncompatibility(incompatibility: FieldIncompatibility): boolean {
434
- switch (incompatibility.mismatch) {
443
+ function validateFieldIncompatibility(discrepancy: FieldDiscrepancy): boolean {
444
+ switch (discrepancy.mismatch) {
435
445
  case "allowedTypes": {
436
446
  // Since we only track the symmetric difference between the allowed types in the view and
437
447
  // stored schemas, it's sufficient to check if any extra allowed types still exist in the
438
448
  // stored schema.
439
- return incompatibility.stored.length === 0;
449
+ return discrepancy.stored.length === 0;
440
450
  }
441
451
  case "fieldKind": {
442
- if (incompatibility.stored === undefined) {
443
- // Add an optional field
444
- if (incompatibility.view === "Optional") {
445
- return true;
446
- }
447
- } else {
448
- // Relax the field to make it more general
449
- return compareFieldKind(incompatibility.stored, incompatibility.view);
450
- }
451
-
452
- break;
452
+ return posetLte(discrepancy.stored, discrepancy.view, fieldRealizer);
453
453
  }
454
454
  case "valueSchema": {
455
455
  return false;
@@ -460,41 +460,105 @@ function validateFieldIncompatibility(incompatibility: FieldIncompatibility): bo
460
460
  }
461
461
 
462
462
  /**
463
- * A mapping that defines the order of field kinds for comparison purposes.
464
- * The numeric values indicate the hierarchy or "strength" of each field kind, where lower numbers are more restrictive.
465
- * This is used to determine if one field kind can be considered a superset of another.
463
+ * A linear extension of a partially-ordered set of `T`s. See:
464
+ * https://en.wikipedia.org/wiki/Linear_extension
466
465
  *
467
- * - "Forbidden": The most restrictive, represented by 1. Indicates a forbidden field.
468
- * - "Value": Represented by 2. Indicates a required field with a specific value.
469
- * - "Optional": Represented by 3. Indicates an optional field.
470
- *
471
- * Note:
472
- * - "Sequence": (Currently commented out) was intended to represent a sequence field kind with a value of 4.
473
- * Relaxing non-sequence fields to sequences is not currently supported but may be considered in the future.
474
- *
475
- * TODO: We may need more coverage in realm to prove the correctness of the Forbidden -\> Value transaction
466
+ * The linear extension is represented as a lookup from each poset element to its index in the linear extension.
467
+ */
468
+ type LinearExtension<T> = Map<T, number>;
469
+
470
+ /**
471
+ * A realizer for a partially-ordered set. See:
472
+ * https://en.wikipedia.org/wiki/Order_dimension
473
+ */
474
+ type Realizer<T> = LinearExtension<T>[];
475
+
476
+ /**
477
+ * @privateRemarks
478
+ * TODO: Knowledge of specific field kinds is not appropriate for modular schema.
479
+ * This bit of field comparison should be dependency injected by default-schema if this comparison logic remains in modular-schema
480
+ * (this is analogous to what is done in comparison.ts).
476
481
  */
477
- const fieldKindOrder: { [key: string]: number } = {
478
- "Forbidden": 1,
479
- "Value": 2,
480
- "Optional": 3,
481
- // "Sequence": 4, // Relaxing non-sequence fields to sequences is not currently supported, though we could consider doing so in the future.
482
+ const FieldKindIdentifiers = {
483
+ forbidden: brand<FieldKindIdentifier>("Forbidden"),
484
+ required: brand<FieldKindIdentifier>("Value"),
485
+ identifier: brand<FieldKindIdentifier>("Identifier"),
486
+ optional: brand<FieldKindIdentifier>("Optional"),
487
+ sequence: brand<FieldKindIdentifier>("Sequence"),
482
488
  };
483
489
 
484
- function compareFieldKind(
485
- aKind: FieldKindIdentifier | undefined,
486
- bKind: FieldKindIdentifier | undefined,
487
- ): boolean {
488
- if (aKind === undefined || bKind === undefined) {
489
- return false;
490
+ /**
491
+ * A realizer for the partial order of field kind relaxability.
492
+ *
493
+ * It seems extremely likely that this partial order will remain dimension 2 over time (i.e. the set of allowed relaxations can be visualized
494
+ * with a [dominance drawing](https://en.wikipedia.org/wiki/Dominance_drawing)), so this strategy allows efficient comarison between field kinds
495
+ * without excessive casework.
496
+ *
497
+ * Hasse diagram for the partial order is shown below (lower fields can be relaxed to higher fields):
498
+ * ```
499
+ * sequence
500
+ * |
501
+ * optional
502
+ * | \
503
+ * required forbidden
504
+ * |
505
+ * identifier
506
+ * ```
507
+ */
508
+ const fieldRealizer: Realizer<FieldKindIdentifier> = [
509
+ [
510
+ FieldKindIdentifiers.forbidden,
511
+ FieldKindIdentifiers.identifier,
512
+ FieldKindIdentifiers.required,
513
+ FieldKindIdentifiers.optional,
514
+ FieldKindIdentifiers.sequence,
515
+ ],
516
+ [
517
+ FieldKindIdentifiers.identifier,
518
+ FieldKindIdentifiers.required,
519
+ FieldKindIdentifiers.forbidden,
520
+ FieldKindIdentifiers.optional,
521
+ FieldKindIdentifiers.sequence,
522
+ ],
523
+ ].map((extension) => new Map(extension.map((identifier, index) => [identifier, index])));
524
+
525
+ const PosetComparisonResult = {
526
+ Less: "<",
527
+ Greater: ">",
528
+ Equal: "=",
529
+ Incomparable: "||",
530
+ } as const;
531
+ type PosetComparisonResult =
532
+ (typeof PosetComparisonResult)[keyof typeof PosetComparisonResult];
533
+
534
+ function comparePosetElements<T>(a: T, b: T, realizer: Realizer<T>): PosetComparisonResult {
535
+ let hasLessThanResult = false;
536
+ let hasGreaterThanResult = false;
537
+ for (const extension of realizer) {
538
+ const aIndex = extension.get(a);
539
+ const bIndex = extension.get(b);
540
+ assert(aIndex !== undefined && bIndex !== undefined, "Invalid realizer");
541
+ if (aIndex < bIndex) {
542
+ hasLessThanResult = true;
543
+ } else if (aIndex > bIndex) {
544
+ hasGreaterThanResult = true;
545
+ }
490
546
  }
491
547
 
492
- if (!(aKind in fieldKindOrder) || !(bKind in fieldKindOrder)) {
493
- return false;
494
- }
548
+ return hasLessThanResult
549
+ ? hasGreaterThanResult
550
+ ? PosetComparisonResult.Incomparable
551
+ : PosetComparisonResult.Less
552
+ : hasGreaterThanResult
553
+ ? PosetComparisonResult.Greater
554
+ : PosetComparisonResult.Equal;
555
+ }
495
556
 
496
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
497
- return fieldKindOrder[aKind]! <= fieldKindOrder[bKind]!;
557
+ function posetLte<T>(a: T, b: T, realizer: Realizer<T>): boolean {
558
+ const comparison = comparePosetElements(a, b, realizer);
559
+ return (
560
+ comparison === PosetComparisonResult.Less || comparison === PosetComparisonResult.Equal
561
+ );
498
562
  }
499
563
 
500
564
  function throwUnsupportedNodeType(type: string): never {
@@ -103,8 +103,8 @@ function rebaseGenericChange(
103
103
  break;
104
104
  }
105
105
 
106
- const newIndex = newEntry?.[0] ?? Infinity;
107
- const baseIndex = baseEntry?.[0] ?? Infinity;
106
+ const newIndex = newEntry?.[0] ?? Number.POSITIVE_INFINITY;
107
+ const baseIndex = baseEntry?.[0] ?? Number.POSITIVE_INFINITY;
108
108
  let newNodeChange: NodeId | undefined;
109
109
  let baseNodeChange: NodeId | undefined;
110
110
  let index: number;
@@ -74,4 +74,7 @@ export type {
74
74
  FieldKindConfiguration,
75
75
  FieldKindConfigurationEntry,
76
76
  } from "./fieldKindConfiguration.js";
77
- export { getAllowedContentIncompatibilities, isRepoSuperset } from "./discrepancies.js";
77
+ export {
78
+ getAllowedContentDiscrepancies,
79
+ isRepoSuperset,
80
+ } from "./discrepancies.js";
@@ -3016,7 +3016,7 @@ function getFirstIntersectingCrossFieldEntry(
3016
3016
  table: CrossFieldKeyTable,
3017
3017
  [target, revision, id, count]: CrossFieldKeyRange,
3018
3018
  ): [CrossFieldKeyRange, FieldId] | undefined {
3019
- const entry = table.nextLowerPair([target, revision, id, Infinity]);
3019
+ const entry = table.nextLowerPair([target, revision, id, Number.POSITIVE_INFINITY]);
3020
3020
  if (entry === undefined) {
3021
3021
  return undefined;
3022
3022
  }
@@ -33,7 +33,7 @@ import {
33
33
  aboveRootPlaceholder,
34
34
  deepCopyMapTree,
35
35
  } from "../../core/index.js";
36
- import { createEmitter } from "../../events/index.js";
36
+ import { createEmitter, type Listenable } from "../../events/index.js";
37
37
  import {
38
38
  assertNonNegativeSafeInteger,
39
39
  assertValidIndex,
@@ -73,7 +73,8 @@ export class ObjectForest implements IEditableForest {
73
73
  // All cursors that are in the "Current" state. Must be empty when editing.
74
74
  public readonly currentCursors: Set<Cursor> = new Set();
75
75
 
76
- private readonly events = createEmitter<ForestEvents>();
76
+ readonly #events = createEmitter<ForestEvents>();
77
+ public readonly events: Listenable<ForestEvents> = this.#events;
77
78
 
78
79
  readonly #roots: MutableMapTree;
79
80
  public get roots(): MapTree {
@@ -98,13 +99,6 @@ export class ObjectForest implements IEditableForest {
98
99
  return this.roots.fields.size === 0;
99
100
  }
100
101
 
101
- public on<K extends keyof ForestEvents>(
102
- eventName: K,
103
- listener: ForestEvents[K],
104
- ): () => void {
105
- return this.events.on(eventName, listener);
106
- }
107
-
108
102
  public clone(_: TreeStoredSchemaSubscription, anchors: AnchorSet): ObjectForest {
109
103
  return new ObjectForest(anchors, this.additionalAsserts, this.roots);
110
104
  }
@@ -133,7 +127,7 @@ export class ObjectForest implements IEditableForest {
133
127
  * This is required for each change since there may be app facing change event handlers which create cursors.
134
128
  */
135
129
  const preEdit = (): void => {
136
- this.events.emit("beforeChange");
130
+ this.#events.emit("beforeChange");
137
131
  assert(
138
132
  this.currentCursors.has(cursor),
139
133
  0x995 /* missing visitor cursor while editing */,
@@ -168,7 +162,7 @@ export class ObjectForest implements IEditableForest {
168
162
  public create(content: ProtoNodes, destination: FieldKey): void {
169
163
  preEdit();
170
164
  this.forest.add(content, destination);
171
- this.forest.events.emit("afterRootFieldCreated", destination);
165
+ this.forest.#events.emit("afterRootFieldCreated", destination);
172
166
  }
173
167
  public attach(source: FieldKey, count: number, destination: PlaceIndex): void {
174
168
  preEdit();