@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.
- package/.eslintrc.cjs +56 -25
- package/api-report/tree.alpha.api.md +14 -11
- package/api-report/tree.beta.api.md +5 -2
- package/api-report/tree.legacy.alpha.api.md +5 -2
- package/api-report/tree.legacy.public.api.md +5 -2
- package/api-report/tree.public.api.md +5 -2
- package/dist/core/forest/forest.d.ts +5 -1
- package/dist/core/forest/forest.d.ts.map +1 -1
- package/dist/core/forest/forest.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/schema-stored/storedSchemaRepository.d.ts +7 -3
- package/dist/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
- package/dist/core/schema-stored/storedSchemaRepository.js +4 -6
- package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/dist/core/tree/anchorSet.d.ts +8 -5
- package/dist/core/tree/anchorSet.d.ts.map +1 -1
- package/dist/core/tree/anchorSet.js +12 -11
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/events/emitter.d.ts +21 -9
- package/dist/events/emitter.d.ts.map +1 -1
- package/dist/events/emitter.js +36 -21
- package/dist/events/emitter.js.map +1 -1
- package/dist/events/listeners.d.ts +16 -5
- package/dist/events/listeners.d.ts.map +1 -1
- package/dist/events/listeners.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/basicChunk.d.ts +26 -5
- package/dist/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/basicChunk.js +15 -5
- package/dist/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkTree.js +1 -1
- package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
- package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.js +19 -9
- package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/dist/feature-libraries/flex-tree/context.d.ts +3 -2
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +3 -3
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/dist/feature-libraries/flex-tree/utilities.js +1 -1
- package/dist/feature-libraries/flex-tree/utilities.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +2 -2
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/comparison.js +3 -0
- package/dist/feature-libraries/modular-schema/comparison.js.map +1 -1
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts +29 -29
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/discrepancies.js +121 -75
- package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js +2 -2
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +2 -2
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.d.ts +2 -2
- package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/dist/feature-libraries/object-forest/objectForest.js +6 -8
- package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/dist/feature-libraries/schema-index/schemaSummarizer.js +1 -1
- package/dist/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
- package/dist/feature-libraries/sequence-field/compose.js +2 -2
- package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
- package/dist/feature-libraries/sequence-field/markListFactory.js +1 -1
- package/dist/feature-libraries/sequence-field/markListFactory.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +2 -2
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/treeApi.js +6 -3
- package/dist/shared-tree/treeApi.js.map +1 -1
- package/dist/shared-tree/treeCheckout.js +7 -7
- package/dist/shared-tree/treeCheckout.js.map +1 -1
- package/dist/shared-tree-core/branch.d.ts +7 -7
- package/dist/shared-tree-core/branch.d.ts.map +1 -1
- package/dist/shared-tree-core/branch.js +35 -25
- package/dist/shared-tree-core/branch.js.map +1 -1
- package/dist/shared-tree-core/editManager.js +4 -4
- package/dist/shared-tree-core/editManager.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +5 -5
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/schemaCreationUtilities.d.ts +12 -14
- package/dist/simple-tree/api/schemaCreationUtilities.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaCreationUtilities.js +9 -7
- package/dist/simple-tree/api/schemaCreationUtilities.js.map +1 -1
- package/dist/simple-tree/api/schemaFactory.d.ts +68 -10
- package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactory.js +38 -10
- package/dist/simple-tree/api/schemaFactory.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/dist/simple-tree/api/treeNodeApi.js +4 -4
- package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
- package/dist/simple-tree/arrayNode.js +1 -1
- package/dist/simple-tree/arrayNode.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +7 -8
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +68 -73
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts +1 -1
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/objectNodeTypes.d.ts +3 -0
- package/dist/simple-tree/objectNodeTypes.d.ts.map +1 -1
- package/dist/simple-tree/objectNodeTypes.js +3 -1
- package/dist/simple-tree/objectNodeTypes.js.map +1 -1
- package/dist/simple-tree/proxies.js +1 -1
- package/dist/simple-tree/proxies.js.map +1 -1
- package/dist/simple-tree/schemaTypes.d.ts +26 -1
- package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
- package/dist/simple-tree/schemaTypes.js.map +1 -1
- package/dist/simple-tree/treeNodeValid.js +2 -2
- package/dist/simple-tree/treeNodeValid.js.map +1 -1
- package/dist/util/nestedMap.d.ts.map +1 -1
- package/dist/util/nestedMap.js.map +1 -1
- package/docs/.attachments/object-merge-semantics.drawio +145 -0
- package/docs/user-facing/array-merge-semantics.md +344 -0
- package/docs/user-facing/map-merge-semantics.md +128 -0
- package/docs/user-facing/merge-semantics.md +7 -3
- package/docs/user-facing/object-merge-semantics.md +77 -0
- package/lib/core/forest/forest.d.ts +5 -1
- package/lib/core/forest/forest.d.ts.map +1 -1
- package/lib/core/forest/forest.js.map +1 -1
- package/lib/core/index.d.ts +1 -1
- package/lib/core/index.d.ts.map +1 -1
- package/lib/core/index.js.map +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.d.ts +7 -3
- package/lib/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
- package/lib/core/schema-stored/storedSchemaRepository.js +4 -6
- package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
- package/lib/core/tree/anchorSet.d.ts +8 -5
- package/lib/core/tree/anchorSet.d.ts.map +1 -1
- package/lib/core/tree/anchorSet.js +12 -11
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/events/emitter.d.ts +21 -9
- package/lib/events/emitter.d.ts.map +1 -1
- package/lib/events/emitter.js +37 -22
- package/lib/events/emitter.js.map +1 -1
- package/lib/events/listeners.d.ts +16 -5
- package/lib/events/listeners.d.ts.map +1 -1
- package/lib/events/listeners.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/basicChunk.d.ts +26 -5
- package/lib/feature-libraries/chunked-forest/basicChunk.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/basicChunk.js +15 -5
- package/lib/feature-libraries/chunked-forest/basicChunk.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkTree.js +1 -1
- package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
- package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.js +19 -9
- package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
- package/lib/feature-libraries/flex-tree/context.d.ts +3 -2
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +3 -3
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/lib/feature-libraries/flex-tree/utilities.js +1 -1
- package/lib/feature-libraries/flex-tree/utilities.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/comparison.js +3 -0
- package/lib/feature-libraries/modular-schema/comparison.js.map +1 -1
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts +29 -29
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/discrepancies.js +120 -74
- package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js +2 -2
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +1 -1
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.d.ts +2 -2
- package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
- package/lib/feature-libraries/object-forest/objectForest.js +6 -8
- package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
- package/lib/feature-libraries/schema-index/schemaSummarizer.js +1 -1
- package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
- package/lib/feature-libraries/sequence-field/compose.js +2 -2
- package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
- package/lib/feature-libraries/sequence-field/markListFactory.js +1 -1
- package/lib/feature-libraries/sequence-field/markListFactory.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +2 -2
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/treeApi.js +7 -4
- package/lib/shared-tree/treeApi.js.map +1 -1
- package/lib/shared-tree/treeCheckout.js +7 -7
- package/lib/shared-tree/treeCheckout.js.map +1 -1
- package/lib/shared-tree-core/branch.d.ts +7 -7
- package/lib/shared-tree-core/branch.d.ts.map +1 -1
- package/lib/shared-tree-core/branch.js +36 -26
- package/lib/shared-tree-core/branch.js.map +1 -1
- package/lib/shared-tree-core/editManager.js +4 -4
- package/lib/shared-tree-core/editManager.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +5 -5
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/schemaCreationUtilities.d.ts +12 -14
- package/lib/simple-tree/api/schemaCreationUtilities.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaCreationUtilities.js +9 -7
- package/lib/simple-tree/api/schemaCreationUtilities.js.map +1 -1
- package/lib/simple-tree/api/schemaFactory.d.ts +68 -10
- package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactory.js +38 -10
- package/lib/simple-tree/api/schemaFactory.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/lib/simple-tree/api/treeNodeApi.js +4 -4
- package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
- package/lib/simple-tree/arrayNode.js +1 -1
- package/lib/simple-tree/arrayNode.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +7 -8
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +69 -74
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/objectNode.d.ts +1 -1
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/objectNodeTypes.d.ts +3 -0
- package/lib/simple-tree/objectNodeTypes.d.ts.map +1 -1
- package/lib/simple-tree/objectNodeTypes.js +3 -1
- package/lib/simple-tree/objectNodeTypes.js.map +1 -1
- package/lib/simple-tree/proxies.js +1 -1
- package/lib/simple-tree/proxies.js.map +1 -1
- package/lib/simple-tree/schemaTypes.d.ts +26 -1
- package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
- package/lib/simple-tree/schemaTypes.js.map +1 -1
- package/lib/simple-tree/treeNodeValid.js +2 -2
- package/lib/simple-tree/treeNodeValid.js.map +1 -1
- package/lib/util/nestedMap.d.ts.map +1 -1
- package/lib/util/nestedMap.js.map +1 -1
- package/package.json +20 -20
- package/src/core/forest/forest.ts +6 -1
- package/src/core/index.ts +1 -1
- package/src/core/schema-stored/storedSchemaRepository.ts +10 -13
- package/src/core/tree/anchorSet.ts +13 -20
- package/src/events/emitter.ts +45 -24
- package/src/events/listeners.ts +17 -5
- package/src/feature-libraries/chunked-forest/basicChunk.ts +12 -4
- package/src/feature-libraries/chunked-forest/chunkTree.ts +1 -1
- package/src/feature-libraries/chunked-forest/chunkedForest.ts +13 -14
- package/src/feature-libraries/flex-tree/context.ts +5 -7
- package/src/feature-libraries/flex-tree/lazyField.ts +1 -1
- package/src/feature-libraries/flex-tree/lazyNode.ts +1 -1
- package/src/feature-libraries/flex-tree/utilities.ts +1 -1
- package/src/feature-libraries/index.ts +1 -1
- package/src/feature-libraries/modular-schema/comparison.ts +4 -0
- package/src/feature-libraries/modular-schema/discrepancies.ts +188 -124
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +2 -2
- package/src/feature-libraries/modular-schema/index.ts +4 -1
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1 -1
- package/src/feature-libraries/object-forest/objectForest.ts +5 -11
- package/src/feature-libraries/schema-index/schemaSummarizer.ts +1 -1
- package/src/feature-libraries/sequence-field/compose.ts +2 -2
- package/src/feature-libraries/sequence-field/markListFactory.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +2 -2
- package/src/shared-tree/treeApi.ts +9 -7
- package/src/shared-tree/treeCheckout.ts +7 -7
- package/src/shared-tree-core/branch.ts +30 -30
- package/src/shared-tree-core/editManager.ts +4 -4
- package/src/shared-tree-core/sharedTreeCore.ts +5 -5
- package/src/simple-tree/api/schemaCreationUtilities.ts +29 -17
- package/src/simple-tree/api/schemaFactory.ts +62 -29
- package/src/simple-tree/api/schemaFactoryRecursive.ts +1 -1
- package/src/simple-tree/api/treeNodeApi.ts +4 -4
- package/src/simple-tree/arrayNode.ts +1 -1
- package/src/simple-tree/core/treeNodeKernel.ts +68 -72
- package/src/simple-tree/objectNode.ts +1 -1
- package/src/simple-tree/objectNodeTypes.ts +3 -1
- package/src/simple-tree/proxies.ts +1 -1
- package/src/simple-tree/schemaTypes.ts +26 -1
- package/src/simple-tree/treeNodeValid.ts +2 -2
- 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.
|
|
30
|
+
* 1. FieldDiscrepancy
|
|
29
31
|
*
|
|
30
|
-
* `
|
|
32
|
+
* `FieldDiscrepancy` represents the differences between two `TreeFieldStoredSchema` objects. It consists of
|
|
31
33
|
* three types of incompatibilities:
|
|
32
34
|
*
|
|
33
|
-
* -
|
|
35
|
+
* - FieldKindDiscrepancy: Indicates the differences in `FieldKindIdentifier` between two `TreeFieldStoredSchema`
|
|
34
36
|
* objects (e.g., optional, required, sequence, etc.).
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
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.
|
|
41
|
+
* 2. NodeDiscrepancy
|
|
40
42
|
*
|
|
41
|
-
* `
|
|
43
|
+
* `NodeDiscrepancy` represents the differences between two `TreeNodeStoredSchema` objects and includes:
|
|
42
44
|
*
|
|
43
|
-
* -
|
|
45
|
+
* - NodeKindDiscrepancy: Indicates the differences in the types of `TreeNodeStoredSchema` (currently supports
|
|
44
46
|
* `ObjectNodeStoredSchema`, `MapNodeStoredSchema`, and `LeafNodeStoredSchema`).
|
|
45
|
-
* -
|
|
46
|
-
* `TreeNodeStoredSchema`. It includes an array of `
|
|
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.
|
|
53
|
+
* 3. Discrepancy
|
|
52
54
|
*
|
|
53
|
-
*
|
|
54
|
-
* schema differences. See {@link
|
|
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
|
|
59
|
+
export type Discrepancy = FieldDiscrepancy | NodeDiscrepancy;
|
|
58
60
|
|
|
59
|
-
export type
|
|
61
|
+
export type NodeDiscrepancy = NodeKindDiscrepancy | NodeFieldsDiscrepancy;
|
|
60
62
|
|
|
61
|
-
export type
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
|
63
|
+
export type FieldDiscrepancy =
|
|
64
|
+
| AllowedTypeDiscrepancy
|
|
65
|
+
| FieldKindDiscrepancy
|
|
66
|
+
| ValueSchemaDiscrepancy;
|
|
65
67
|
|
|
66
|
-
export interface
|
|
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
|
|
81
|
+
export interface FieldKindDiscrepancy {
|
|
80
82
|
identifier: string | undefined; // undefined indicates root field schema
|
|
81
83
|
mismatch: "fieldKind";
|
|
82
|
-
view: FieldKindIdentifier
|
|
83
|
-
stored: FieldKindIdentifier
|
|
84
|
+
view: FieldKindIdentifier;
|
|
85
|
+
stored: FieldKindIdentifier;
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
export interface
|
|
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
|
|
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
|
|
102
|
+
export interface NodeFieldsDiscrepancy {
|
|
101
103
|
identifier: string;
|
|
102
104
|
mismatch: "fields";
|
|
103
|
-
differences:
|
|
105
|
+
differences: FieldDiscrepancy[];
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
type SchemaFactoryNodeKind = "object" | "leaf" | "map";
|
|
107
109
|
|
|
108
110
|
/**
|
|
109
|
-
*
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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
|
|
127
|
+
export function getAllowedContentDiscrepancies(
|
|
126
128
|
view: TreeStoredSchema,
|
|
127
129
|
stored: TreeStoredSchema,
|
|
128
|
-
):
|
|
129
|
-
const
|
|
130
|
+
): Discrepancy[] {
|
|
131
|
+
const discrepancies: Discrepancy[] = [];
|
|
130
132
|
|
|
131
133
|
// check root schema discrepancies
|
|
132
|
-
|
|
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
|
-
|
|
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
|
-
|
|
157
|
+
discrepancies.push({
|
|
158
158
|
identifier: key,
|
|
159
159
|
mismatch: "nodeKind",
|
|
160
160
|
view: "object",
|
|
161
161
|
stored: "map",
|
|
162
|
-
} satisfies
|
|
162
|
+
} satisfies NodeKindDiscrepancy);
|
|
163
163
|
} else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
164
|
-
|
|
164
|
+
discrepancies.push({
|
|
165
165
|
identifier: key,
|
|
166
166
|
mismatch: "nodeKind",
|
|
167
167
|
view: "object",
|
|
168
168
|
stored: "leaf",
|
|
169
|
-
} satisfies
|
|
169
|
+
} satisfies NodeKindDiscrepancy);
|
|
170
170
|
} else if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
|
|
171
171
|
const differences = trackObjectNodeDiscrepancies(viewNodeSchema, storedNodeSchema);
|
|
172
172
|
if (differences.length > 0) {
|
|
173
|
-
|
|
173
|
+
discrepancies.push({
|
|
174
174
|
identifier: key,
|
|
175
175
|
mismatch: "fields",
|
|
176
176
|
differences,
|
|
177
|
-
} satisfies
|
|
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
|
-
|
|
185
|
+
discrepancies.push({
|
|
186
186
|
identifier: key,
|
|
187
187
|
mismatch: "nodeKind",
|
|
188
188
|
view: "map",
|
|
189
189
|
stored: undefined,
|
|
190
|
-
} satisfies
|
|
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
|
-
|
|
198
|
+
discrepancies.push({
|
|
199
199
|
identifier: key,
|
|
200
200
|
mismatch: "nodeKind",
|
|
201
201
|
view: "map",
|
|
202
202
|
stored: "object",
|
|
203
|
-
} satisfies
|
|
203
|
+
} satisfies NodeKindDiscrepancy);
|
|
204
204
|
} else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
205
|
-
|
|
205
|
+
discrepancies.push({
|
|
206
206
|
identifier: key,
|
|
207
207
|
mismatch: "nodeKind",
|
|
208
208
|
view: "map",
|
|
209
209
|
stored: "leaf",
|
|
210
|
-
} satisfies
|
|
210
|
+
} satisfies NodeKindDiscrepancy);
|
|
211
211
|
} else if (storedNodeSchema instanceof MapNodeStoredSchema) {
|
|
212
|
-
|
|
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
|
-
|
|
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
|
-
|
|
238
|
+
discrepancies.push({
|
|
239
239
|
identifier: key,
|
|
240
240
|
mismatch: "nodeKind",
|
|
241
241
|
view: "leaf",
|
|
242
242
|
stored: "map",
|
|
243
|
-
} satisfies
|
|
243
|
+
} satisfies NodeKindDiscrepancy);
|
|
244
244
|
} else if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
|
|
245
|
-
|
|
245
|
+
discrepancies.push({
|
|
246
246
|
identifier: key,
|
|
247
247
|
mismatch: "nodeKind",
|
|
248
248
|
view: "leaf",
|
|
249
249
|
stored: "object",
|
|
250
|
-
} satisfies
|
|
250
|
+
} satisfies NodeKindDiscrepancy);
|
|
251
251
|
} else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
252
252
|
if (viewNodeSchema.leafValue !== storedNodeSchema.leafValue) {
|
|
253
|
-
|
|
253
|
+
discrepancies.push({
|
|
254
254
|
identifier: key,
|
|
255
255
|
mismatch: "valueSchema",
|
|
256
256
|
view: viewNodeSchema.leafValue,
|
|
257
257
|
stored: storedNodeSchema.leafValue,
|
|
258
|
-
} satisfies
|
|
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
|
-
|
|
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
|
|
281
|
+
} satisfies NodeKindDiscrepancy);
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
return
|
|
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
|
-
):
|
|
298
|
-
const differences:
|
|
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
|
|
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
|
|
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
|
-
):
|
|
336
|
-
const differences:
|
|
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 (
|
|
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:
|
|
357
|
-
} satisfies
|
|
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
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
|
408
|
+
const discrepancies = getAllowedContentDiscrepancies(view, stored);
|
|
403
409
|
|
|
404
|
-
for (const
|
|
405
|
-
switch (
|
|
410
|
+
for (const discrepancy of discrepancies) {
|
|
411
|
+
switch (discrepancy.mismatch) {
|
|
406
412
|
case "nodeKind": {
|
|
407
|
-
|
|
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(
|
|
422
|
+
if (!validateFieldIncompatibility(discrepancy)) {
|
|
413
423
|
return false;
|
|
414
424
|
}
|
|
415
425
|
break;
|
|
416
426
|
}
|
|
417
427
|
case "fields": {
|
|
418
428
|
if (
|
|
419
|
-
|
|
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(
|
|
434
|
-
switch (
|
|
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
|
|
449
|
+
return discrepancy.stored.length === 0;
|
|
440
450
|
}
|
|
441
451
|
case "fieldKind": {
|
|
442
|
-
|
|
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
|
|
464
|
-
*
|
|
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
|
-
*
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
|
|
475
|
-
|
|
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
|
|
478
|
-
"Forbidden"
|
|
479
|
-
"Value"
|
|
480
|
-
"
|
|
481
|
-
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
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
|
-
|
|
493
|
-
|
|
494
|
-
|
|
548
|
+
return hasLessThanResult
|
|
549
|
+
? hasGreaterThanResult
|
|
550
|
+
? PosetComparisonResult.Incomparable
|
|
551
|
+
: PosetComparisonResult.Less
|
|
552
|
+
: hasGreaterThanResult
|
|
553
|
+
? PosetComparisonResult.Greater
|
|
554
|
+
: PosetComparisonResult.Equal;
|
|
555
|
+
}
|
|
495
556
|
|
|
496
|
-
|
|
497
|
-
|
|
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] ??
|
|
107
|
-
const baseIndex = baseEntry?.[0] ??
|
|
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 {
|
|
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,
|
|
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
|
-
|
|
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
|
|
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
|
|
165
|
+
this.forest.#events.emit("afterRootFieldCreated", destination);
|
|
172
166
|
}
|
|
173
167
|
public attach(source: FieldKey, count: number, destination: PlaceIndex): void {
|
|
174
168
|
preEdit();
|