@fluidframework/tree 2.10.0-306579 → 2.10.0-307399
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/api-report/tree.alpha.api.md +11 -9
- package/api-report/tree.beta.api.md +2 -0
- package/api-report/tree.legacy.alpha.api.md +2 -0
- package/api-report/tree.legacy.public.api.md +2 -0
- package/api-report/tree.public.api.md +2 -0
- 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/chunkedForest.d.ts.map +1 -1
- package/dist/feature-libraries/chunked-forest/chunkedForest.js +5 -0
- package/dist/feature-libraries/chunked-forest/chunkedForest.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/discrepancies.d.ts +27 -27
- package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/discrepancies.js +152 -193
- package/dist/feature-libraries/modular-schema/discrepancies.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/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/treeApi.js +4 -1
- package/dist/shared-tree/treeApi.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 +2 -0
- package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactory.js +4 -1
- package/dist/simple-tree/api/schemaFactory.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +4 -5
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +63 -67
- 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/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/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/chunkedForest.d.ts.map +1 -1
- package/lib/feature-libraries/chunked-forest/chunkedForest.js +5 -0
- package/lib/feature-libraries/chunked-forest/chunkedForest.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/discrepancies.d.ts +27 -27
- package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/discrepancies.js +150 -191
- package/lib/feature-libraries/modular-schema/discrepancies.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/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/treeApi.js +5 -2
- package/lib/shared-tree/treeApi.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 +2 -0
- package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactory.js +4 -1
- package/lib/simple-tree/api/schemaFactory.js.map +1 -1
- package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +4 -5
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +64 -68
- 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/package.json +23 -31
- package/src/feature-libraries/chunked-forest/basicChunk.ts +12 -4
- package/src/feature-libraries/chunked-forest/chunkedForest.ts +5 -0
- package/src/feature-libraries/index.ts +1 -1
- package/src/feature-libraries/modular-schema/discrepancies.ts +202 -241
- package/src/feature-libraries/modular-schema/index.ts +4 -1
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/treeApi.ts +7 -5
- package/src/simple-tree/api/schemaCreationUtilities.ts +29 -17
- package/src/simple-tree/api/schemaFactory.ts +25 -18
- package/src/simple-tree/api/schemaFactoryRecursive.ts +1 -1
- package/src/simple-tree/core/treeNodeKernel.ts +62 -64
- package/src/simple-tree/objectNode.ts +1 -1
- package/src/simple-tree/objectNodeTypes.ts +3 -1
|
@@ -6,39 +6,39 @@ import { type FieldKindIdentifier, type TreeStoredSchema, type ValueSchema } fro
|
|
|
6
6
|
/**
|
|
7
7
|
* @remarks
|
|
8
8
|
*
|
|
9
|
-
* 1.
|
|
9
|
+
* 1. FieldDiscrepancy
|
|
10
10
|
*
|
|
11
|
-
* `
|
|
11
|
+
* `FieldDiscrepancy` represents the differences between two `TreeFieldStoredSchema` objects. It consists of
|
|
12
12
|
* three types of incompatibilities:
|
|
13
13
|
*
|
|
14
|
-
* -
|
|
14
|
+
* - FieldKindDiscrepancy: Indicates the differences in `FieldKindIdentifier` between two `TreeFieldStoredSchema`
|
|
15
15
|
* objects (e.g., optional, required, sequence, etc.).
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
16
|
+
* - AllowedTypesDiscrepancy: Indicates the differences in the allowed child types between the two schemas.
|
|
17
|
+
* - ValueSchemaDiscrepancy: Specifically indicates the differences in the `ValueSchema` of two
|
|
18
18
|
* `LeafNodeStoredSchema` objects.
|
|
19
19
|
*
|
|
20
|
-
* 2.
|
|
20
|
+
* 2. NodeDiscrepancy
|
|
21
21
|
*
|
|
22
|
-
* `
|
|
22
|
+
* `NodeDiscrepancy` represents the differences between two `TreeNodeStoredSchema` objects and includes:
|
|
23
23
|
*
|
|
24
|
-
* -
|
|
24
|
+
* - NodeKindDiscrepancy: Indicates the differences in the types of `TreeNodeStoredSchema` (currently supports
|
|
25
25
|
* `ObjectNodeStoredSchema`, `MapNodeStoredSchema`, and `LeafNodeStoredSchema`).
|
|
26
|
-
* -
|
|
27
|
-
* `TreeNodeStoredSchema`. It includes an array of `
|
|
26
|
+
* - NodeFieldsDiscrepancy: Indicates the `FieldDiscrepancy` of `TreeFieldStoredSchema` within two
|
|
27
|
+
* `TreeNodeStoredSchema`. It includes an array of `FieldDiscrepancy` instances in the `differences` field.
|
|
28
28
|
*
|
|
29
29
|
* When comparing two nodes for compatibility, it only makes sense to compare their fields if the nodes are of
|
|
30
30
|
* the same kind (map, object, leaf).
|
|
31
31
|
*
|
|
32
|
-
* 3.
|
|
32
|
+
* 3. Discrepancy
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
* schema differences. See {@link
|
|
34
|
+
* Discrepancy consists of both `NodeDiscrepancy` and `FieldDiscrepancy`, representing any kind of
|
|
35
|
+
* schema differences. See {@link getAllowedContentDiscrepancies} for more details about how we process it
|
|
36
36
|
* and the ordering.
|
|
37
37
|
*/
|
|
38
|
-
export type
|
|
39
|
-
export type
|
|
40
|
-
export type
|
|
41
|
-
export interface
|
|
38
|
+
export type Discrepancy = FieldDiscrepancy | NodeDiscrepancy;
|
|
39
|
+
export type NodeDiscrepancy = NodeKindDiscrepancy | NodeFieldsDiscrepancy;
|
|
40
|
+
export type FieldDiscrepancy = AllowedTypeDiscrepancy | FieldKindDiscrepancy | ValueSchemaDiscrepancy;
|
|
41
|
+
export interface AllowedTypeDiscrepancy {
|
|
42
42
|
identifier: string | undefined;
|
|
43
43
|
mismatch: "allowedTypes";
|
|
44
44
|
/**
|
|
@@ -50,48 +50,48 @@ export interface AllowedTypeIncompatibility {
|
|
|
50
50
|
*/
|
|
51
51
|
stored: string[];
|
|
52
52
|
}
|
|
53
|
-
export interface
|
|
53
|
+
export interface FieldKindDiscrepancy {
|
|
54
54
|
identifier: string | undefined;
|
|
55
55
|
mismatch: "fieldKind";
|
|
56
56
|
view: FieldKindIdentifier;
|
|
57
57
|
stored: FieldKindIdentifier;
|
|
58
58
|
}
|
|
59
|
-
export interface
|
|
59
|
+
export interface ValueSchemaDiscrepancy {
|
|
60
60
|
identifier: string;
|
|
61
61
|
mismatch: "valueSchema";
|
|
62
62
|
view: ValueSchema | undefined;
|
|
63
63
|
stored: ValueSchema | undefined;
|
|
64
64
|
}
|
|
65
|
-
export interface
|
|
65
|
+
export interface NodeKindDiscrepancy {
|
|
66
66
|
identifier: string;
|
|
67
67
|
mismatch: "nodeKind";
|
|
68
68
|
view: SchemaFactoryNodeKind | undefined;
|
|
69
69
|
stored: SchemaFactoryNodeKind | undefined;
|
|
70
70
|
}
|
|
71
|
-
export interface
|
|
71
|
+
export interface NodeFieldsDiscrepancy {
|
|
72
72
|
identifier: string;
|
|
73
73
|
mismatch: "fields";
|
|
74
|
-
differences:
|
|
74
|
+
differences: FieldDiscrepancy[];
|
|
75
75
|
}
|
|
76
76
|
type SchemaFactoryNodeKind = "object" | "leaf" | "map";
|
|
77
77
|
/**
|
|
78
|
-
*
|
|
78
|
+
* Finds and reports discrepancies between a view schema and a stored schema.
|
|
79
79
|
*
|
|
80
80
|
* The workflow for finding schema incompatibilities:
|
|
81
|
-
* 1. Compare the two root schemas to identify any `
|
|
81
|
+
* 1. Compare the two root schemas to identify any `FieldDiscrepancy`.
|
|
82
82
|
*
|
|
83
83
|
* 2. For each node schema in the `view`:
|
|
84
84
|
* - Verify if the node schema exists in the stored. If it does, ensure that the `SchemaFactoryNodeKind` are
|
|
85
|
-
* consistent. Otherwise this difference is treated as `
|
|
85
|
+
* consistent. Otherwise this difference is treated as `NodeKindDiscrepancy`
|
|
86
86
|
* - If a node schema with the same identifier exists in both view and stored, and their `SchemaFactoryNodeKind`
|
|
87
|
-
* are consistent, perform a exhaustive validation to identify all `
|
|
87
|
+
* are consistent, perform a exhaustive validation to identify all `FieldDiscrepancy`.
|
|
88
88
|
*
|
|
89
89
|
* 3. For each node schema in the stored, verify if it exists in the view. The overlapping parts were already
|
|
90
90
|
* addressed in the previous step.
|
|
91
91
|
*
|
|
92
92
|
* @returns the discrepancies between two TreeStoredSchema objects
|
|
93
93
|
*/
|
|
94
|
-
export declare function
|
|
94
|
+
export declare function getAllowedContentDiscrepancies(view: TreeStoredSchema, stored: TreeStoredSchema): Iterable<Discrepancy>;
|
|
95
95
|
/**
|
|
96
96
|
* @remarks
|
|
97
97
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discrepancies.d.ts","sourceRoot":"","sources":["../../../src/feature-libraries/modular-schema/discrepancies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,
|
|
1
|
+
{"version":3,"file":"discrepancies.d.ts","sourceRoot":"","sources":["../../../src/feature-libraries/modular-schema/discrepancies.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACN,KAAK,mBAAmB,EAQxB,KAAK,gBAAgB,EAErB,KAAK,WAAW,EAChB,MAAM,qBAAqB,CAAC;AAO7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE7D,MAAM,MAAM,eAAe,GAAG,mBAAmB,GAAG,qBAAqB,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GACzB,sBAAsB,GACtB,oBAAoB,GACpB,sBAAsB,CAAC;AAE1B,MAAM,WAAW,sBAAsB;IACtC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACpC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,WAAW,CAAC;IACtB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;IAC9B,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,UAAU,CAAC;IACrB,IAAI,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACxC,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,qBAAqB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,WAAW,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,KAAK,qBAAqB,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,CAAC;AAavD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAiB,8BAA8B,CAC9C,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,gBAAgB,GACtB,QAAQ,CAAC,WAAW,CAAC,CAkCvB;AAkLD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAkCxF"}
|
|
@@ -5,209 +5,144 @@
|
|
|
5
5
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
6
6
|
import { LeafNodeStoredSchema, MapNodeStoredSchema, ObjectNodeStoredSchema, storedEmptyFieldSchema, } from "../../core/index.js";
|
|
7
7
|
import { brand } from "../../util/index.js";
|
|
8
|
+
function getNodeSchemaType(nodeSchema) {
|
|
9
|
+
if (nodeSchema instanceof ObjectNodeStoredSchema) {
|
|
10
|
+
return "object";
|
|
11
|
+
}
|
|
12
|
+
else if (nodeSchema instanceof MapNodeStoredSchema) {
|
|
13
|
+
return "map";
|
|
14
|
+
}
|
|
15
|
+
else if (nodeSchema instanceof LeafNodeStoredSchema) {
|
|
16
|
+
return "leaf";
|
|
17
|
+
}
|
|
18
|
+
throwUnsupportedNodeType(nodeSchema.constructor.name);
|
|
19
|
+
}
|
|
8
20
|
/**
|
|
9
|
-
*
|
|
21
|
+
* Finds and reports discrepancies between a view schema and a stored schema.
|
|
10
22
|
*
|
|
11
23
|
* The workflow for finding schema incompatibilities:
|
|
12
|
-
* 1. Compare the two root schemas to identify any `
|
|
24
|
+
* 1. Compare the two root schemas to identify any `FieldDiscrepancy`.
|
|
13
25
|
*
|
|
14
26
|
* 2. For each node schema in the `view`:
|
|
15
27
|
* - Verify if the node schema exists in the stored. If it does, ensure that the `SchemaFactoryNodeKind` are
|
|
16
|
-
* consistent. Otherwise this difference is treated as `
|
|
28
|
+
* consistent. Otherwise this difference is treated as `NodeKindDiscrepancy`
|
|
17
29
|
* - If a node schema with the same identifier exists in both view and stored, and their `SchemaFactoryNodeKind`
|
|
18
|
-
* are consistent, perform a exhaustive validation to identify all `
|
|
30
|
+
* are consistent, perform a exhaustive validation to identify all `FieldDiscrepancy`.
|
|
19
31
|
*
|
|
20
32
|
* 3. For each node schema in the stored, verify if it exists in the view. The overlapping parts were already
|
|
21
33
|
* addressed in the previous step.
|
|
22
34
|
*
|
|
23
35
|
* @returns the discrepancies between two TreeStoredSchema objects
|
|
24
36
|
*/
|
|
25
|
-
export function
|
|
26
|
-
const incompatibilities = [];
|
|
37
|
+
export function* getAllowedContentDiscrepancies(view, stored) {
|
|
27
38
|
// check root schema discrepancies
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (!stored.nodeSchema.has(key)) {
|
|
36
|
-
incompatibilities.push({
|
|
37
|
-
identifier: key,
|
|
39
|
+
yield* getFieldDiscrepancies(view.rootFieldSchema, stored.rootFieldSchema);
|
|
40
|
+
for (const result of compareMaps(view.nodeSchema, stored.nodeSchema)) {
|
|
41
|
+
switch (result.type) {
|
|
42
|
+
case "aExtra": {
|
|
43
|
+
const viewType = getNodeSchemaType(result.value);
|
|
44
|
+
yield {
|
|
45
|
+
identifier: result.key,
|
|
38
46
|
mismatch: "nodeKind",
|
|
39
|
-
view:
|
|
47
|
+
view: viewType,
|
|
40
48
|
stored: undefined,
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
else {
|
|
44
|
-
const storedNodeSchema = stored.nodeSchema.get(key);
|
|
45
|
-
assert(storedNodeSchema !== undefined, 0x9be /* The storedNodeSchema in stored.nodeSchema should not be undefined */);
|
|
46
|
-
if (storedNodeSchema instanceof MapNodeStoredSchema) {
|
|
47
|
-
incompatibilities.push({
|
|
48
|
-
identifier: key,
|
|
49
|
-
mismatch: "nodeKind",
|
|
50
|
-
view: "object",
|
|
51
|
-
stored: "map",
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
55
|
-
incompatibilities.push({
|
|
56
|
-
identifier: key,
|
|
57
|
-
mismatch: "nodeKind",
|
|
58
|
-
view: "object",
|
|
59
|
-
stored: "leaf",
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
else if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
|
|
63
|
-
const differences = trackObjectNodeDiscrepancies(viewNodeSchema, storedNodeSchema);
|
|
64
|
-
if (differences.length > 0) {
|
|
65
|
-
incompatibilities.push({
|
|
66
|
-
identifier: key,
|
|
67
|
-
mismatch: "fields",
|
|
68
|
-
differences,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
throwUnsupportedNodeType(storedNodeSchema.constructor.name);
|
|
74
|
-
}
|
|
49
|
+
};
|
|
50
|
+
break;
|
|
75
51
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
identifier: key,
|
|
52
|
+
case "bExtra": {
|
|
53
|
+
const storedType = getNodeSchemaType(result.value);
|
|
54
|
+
yield {
|
|
55
|
+
identifier: result.key,
|
|
81
56
|
mismatch: "nodeKind",
|
|
82
|
-
view:
|
|
83
|
-
stored:
|
|
84
|
-
}
|
|
57
|
+
view: undefined,
|
|
58
|
+
stored: storedType,
|
|
59
|
+
};
|
|
60
|
+
break;
|
|
85
61
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (storedNodeSchema instanceof ObjectNodeStoredSchema) {
|
|
90
|
-
incompatibilities.push({
|
|
91
|
-
identifier: key,
|
|
92
|
-
mismatch: "nodeKind",
|
|
93
|
-
view: "map",
|
|
94
|
-
stored: "object",
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
98
|
-
incompatibilities.push({
|
|
99
|
-
identifier: key,
|
|
100
|
-
mismatch: "nodeKind",
|
|
101
|
-
view: "map",
|
|
102
|
-
stored: "leaf",
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
else if (storedNodeSchema instanceof MapNodeStoredSchema) {
|
|
106
|
-
incompatibilities.push(...trackFieldDiscrepancies(viewNodeSchema.mapFields, storedNodeSchema.mapFields, key));
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
throwUnsupportedNodeType(storedNodeSchema.constructor.name);
|
|
110
|
-
}
|
|
62
|
+
case "both": {
|
|
63
|
+
yield* getNodeDiscrepancies(result.key, result.valueA, result.valueB);
|
|
64
|
+
break;
|
|
111
65
|
}
|
|
66
|
+
default:
|
|
67
|
+
break;
|
|
112
68
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
mismatch: "nodeKind",
|
|
137
|
-
view: "leaf",
|
|
138
|
-
stored: "object",
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
else if (storedNodeSchema instanceof LeafNodeStoredSchema) {
|
|
142
|
-
if (viewNodeSchema.leafValue !== storedNodeSchema.leafValue) {
|
|
143
|
-
incompatibilities.push({
|
|
144
|
-
identifier: key,
|
|
145
|
-
mismatch: "valueSchema",
|
|
146
|
-
view: viewNodeSchema.leafValue,
|
|
147
|
-
stored: storedNodeSchema.leafValue,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
throwUnsupportedNodeType(storedNodeSchema.constructor.name);
|
|
153
|
-
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function* getNodeDiscrepancies(identifier, view, stored) {
|
|
72
|
+
const viewType = getNodeSchemaType(view);
|
|
73
|
+
const storedType = getNodeSchemaType(stored);
|
|
74
|
+
if (viewType !== storedType) {
|
|
75
|
+
yield {
|
|
76
|
+
identifier,
|
|
77
|
+
mismatch: "nodeKind",
|
|
78
|
+
view: viewType,
|
|
79
|
+
stored: storedType,
|
|
80
|
+
};
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
switch (viewType) {
|
|
84
|
+
case "object": {
|
|
85
|
+
const differences = Array.from(trackObjectNodeDiscrepancies(view, stored));
|
|
86
|
+
if (differences.length > 0) {
|
|
87
|
+
yield {
|
|
88
|
+
identifier,
|
|
89
|
+
mismatch: "fields",
|
|
90
|
+
differences,
|
|
91
|
+
};
|
|
154
92
|
}
|
|
93
|
+
break;
|
|
155
94
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
});
|
|
95
|
+
case "map":
|
|
96
|
+
yield* getFieldDiscrepancies(view.mapFields, stored.mapFields, identifier);
|
|
97
|
+
break;
|
|
98
|
+
case "leaf": {
|
|
99
|
+
const viewValue = view.leafValue;
|
|
100
|
+
const storedValue = stored.leafValue;
|
|
101
|
+
if (viewValue !== storedValue) {
|
|
102
|
+
yield {
|
|
103
|
+
identifier,
|
|
104
|
+
mismatch: "valueSchema",
|
|
105
|
+
view: viewValue,
|
|
106
|
+
stored: storedValue,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
break;
|
|
172
110
|
}
|
|
111
|
+
default:
|
|
112
|
+
break;
|
|
173
113
|
}
|
|
174
|
-
return incompatibilities;
|
|
175
114
|
}
|
|
176
115
|
/**
|
|
177
116
|
* The function to track the discrepancies between two field stored schemas.
|
|
178
117
|
*
|
|
179
118
|
* @param keyOrRoot - If the key is missing, it indicates that this is the root field schema.
|
|
180
119
|
*/
|
|
181
|
-
function
|
|
182
|
-
const differences = [];
|
|
120
|
+
function* getFieldDiscrepancies(view, stored, keyOrRoot) {
|
|
183
121
|
// Only track the symmetric differences of two sets.
|
|
184
122
|
const findSetDiscrepancies = (a, b) => {
|
|
185
123
|
const aDiff = [...a].filter((value) => !b.has(value));
|
|
186
124
|
const bDiff = [...b].filter((value) => !a.has(value));
|
|
187
125
|
return [aDiff, bDiff];
|
|
188
126
|
};
|
|
189
|
-
const
|
|
190
|
-
if (
|
|
191
|
-
|
|
127
|
+
const [viewExtra, storedExtra] = findSetDiscrepancies(view.types, stored.types);
|
|
128
|
+
if (viewExtra.length > 0 || storedExtra.length > 0) {
|
|
129
|
+
yield {
|
|
192
130
|
identifier: keyOrRoot,
|
|
193
131
|
mismatch: "allowedTypes",
|
|
194
|
-
view:
|
|
195
|
-
stored:
|
|
196
|
-
}
|
|
132
|
+
view: viewExtra,
|
|
133
|
+
stored: storedExtra,
|
|
134
|
+
};
|
|
197
135
|
}
|
|
198
136
|
if (view.kind !== stored.kind) {
|
|
199
|
-
|
|
137
|
+
yield {
|
|
200
138
|
identifier: keyOrRoot,
|
|
201
139
|
mismatch: "fieldKind",
|
|
202
140
|
view: view.kind,
|
|
203
141
|
stored: stored.kind,
|
|
204
|
-
}
|
|
142
|
+
};
|
|
205
143
|
}
|
|
206
|
-
return differences;
|
|
207
144
|
}
|
|
208
|
-
function trackObjectNodeDiscrepancies(view, stored) {
|
|
209
|
-
const differences = [];
|
|
210
|
-
const viewFieldKeys = new Set();
|
|
145
|
+
function* trackObjectNodeDiscrepancies(view, stored) {
|
|
211
146
|
/**
|
|
212
147
|
* Similar to the logic used for tracking discrepancies between two node schemas, we will identify
|
|
213
148
|
* three types of differences:
|
|
@@ -218,35 +153,59 @@ function trackObjectNodeDiscrepancies(view, stored) {
|
|
|
218
153
|
* First, the view schema is iterated to track the first two types of differences.
|
|
219
154
|
* Then, the stored schema is iterated to find the third type.
|
|
220
155
|
*/
|
|
221
|
-
for (const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
156
|
+
for (const result of compareMaps(view.objectNodeFields, stored.objectNodeFields)) {
|
|
157
|
+
const fieldKey = result.key;
|
|
158
|
+
switch (result.type) {
|
|
159
|
+
case "aExtra": {
|
|
160
|
+
if (result.value.kind === storedEmptyFieldSchema.kind) {
|
|
161
|
+
// In one of view/stored, this field is explicitly forbidden, but in the other it is implicitly forbidden
|
|
162
|
+
// (by way of omission). We treat these identically anyway.
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
yield {
|
|
166
|
+
identifier: fieldKey,
|
|
167
|
+
mismatch: "fieldKind",
|
|
168
|
+
view: result.value.kind,
|
|
169
|
+
stored: storedEmptyFieldSchema.kind,
|
|
170
|
+
};
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
case "bExtra": {
|
|
174
|
+
if (result.value.kind === storedEmptyFieldSchema.kind) {
|
|
175
|
+
// In one of view/stored, this field is explicitly forbidden, but in the other it is implicitly forbidden
|
|
176
|
+
// (by way of omission). We treat these identically anyway.
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
yield {
|
|
180
|
+
identifier: fieldKey,
|
|
181
|
+
mismatch: "fieldKind",
|
|
182
|
+
view: storedEmptyFieldSchema.kind,
|
|
183
|
+
stored: result.value.kind,
|
|
184
|
+
};
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case "both": {
|
|
188
|
+
yield* getFieldDiscrepancies(result.valueA, result.valueB, fieldKey);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
default: {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
234
194
|
}
|
|
235
195
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
196
|
+
}
|
|
197
|
+
function* compareMaps(a, b) {
|
|
198
|
+
for (const [key, valueA] of a) {
|
|
199
|
+
const valueB = b.get(key);
|
|
200
|
+
yield valueB === undefined
|
|
201
|
+
? { type: "aExtra", key, value: valueA }
|
|
202
|
+
: { type: "both", key, valueA, valueB };
|
|
203
|
+
}
|
|
204
|
+
for (const [key, valueB] of b) {
|
|
205
|
+
if (!a.has(key)) {
|
|
206
|
+
yield { type: "bExtra", key, value: valueB };
|
|
247
207
|
}
|
|
248
208
|
}
|
|
249
|
-
return differences;
|
|
250
209
|
}
|
|
251
210
|
/**
|
|
252
211
|
* @remarks
|
|
@@ -266,11 +225,11 @@ function trackObjectNodeDiscrepancies(view, stored) {
|
|
|
266
225
|
* validating internal fields.
|
|
267
226
|
*/
|
|
268
227
|
export function isRepoSuperset(view, stored) {
|
|
269
|
-
const
|
|
270
|
-
for (const
|
|
271
|
-
switch (
|
|
228
|
+
const discrepancies = getAllowedContentDiscrepancies(view, stored);
|
|
229
|
+
for (const discrepancy of discrepancies) {
|
|
230
|
+
switch (discrepancy.mismatch) {
|
|
272
231
|
case "nodeKind": {
|
|
273
|
-
if (
|
|
232
|
+
if (discrepancy.stored !== undefined) {
|
|
274
233
|
// It's fine for the view schema to know of a node type that the stored schema doesn't know about.
|
|
275
234
|
return false;
|
|
276
235
|
}
|
|
@@ -279,13 +238,13 @@ export function isRepoSuperset(view, stored) {
|
|
|
279
238
|
case "valueSchema":
|
|
280
239
|
case "allowedTypes":
|
|
281
240
|
case "fieldKind": {
|
|
282
|
-
if (!
|
|
241
|
+
if (!isFieldDiscrepancyCompatible(discrepancy)) {
|
|
283
242
|
return false;
|
|
284
243
|
}
|
|
285
244
|
break;
|
|
286
245
|
}
|
|
287
246
|
case "fields": {
|
|
288
|
-
if (
|
|
247
|
+
if (discrepancy.differences.some((difference) => !isFieldDiscrepancyCompatible(difference))) {
|
|
289
248
|
return false;
|
|
290
249
|
}
|
|
291
250
|
break;
|
|
@@ -295,16 +254,16 @@ export function isRepoSuperset(view, stored) {
|
|
|
295
254
|
}
|
|
296
255
|
return true;
|
|
297
256
|
}
|
|
298
|
-
function
|
|
299
|
-
switch (
|
|
257
|
+
function isFieldDiscrepancyCompatible(discrepancy) {
|
|
258
|
+
switch (discrepancy.mismatch) {
|
|
300
259
|
case "allowedTypes": {
|
|
301
260
|
// Since we only track the symmetric difference between the allowed types in the view and
|
|
302
261
|
// stored schemas, it's sufficient to check if any extra allowed types still exist in the
|
|
303
262
|
// stored schema.
|
|
304
|
-
return
|
|
263
|
+
return discrepancy.stored.length === 0;
|
|
305
264
|
}
|
|
306
265
|
case "fieldKind": {
|
|
307
|
-
return posetLte(
|
|
266
|
+
return posetLte(discrepancy.stored, discrepancy.view, fieldRealizer);
|
|
308
267
|
}
|
|
309
268
|
case "valueSchema": {
|
|
310
269
|
return false;
|