@fluidframework/tree 2.10.0-307060 → 2.10.0

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 (29) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/dist/feature-libraries/modular-schema/discrepancies.d.ts +1 -1
  3. package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  4. package/dist/feature-libraries/modular-schema/discrepancies.js +141 -182
  5. package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  6. package/dist/packageVersion.d.ts +1 -1
  7. package/dist/packageVersion.d.ts.map +1 -1
  8. package/dist/packageVersion.js +1 -1
  9. package/dist/packageVersion.js.map +1 -1
  10. package/dist/shared-tree/treeCheckout.d.ts +4 -0
  11. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  12. package/dist/shared-tree/treeCheckout.js +14 -1
  13. package/dist/shared-tree/treeCheckout.js.map +1 -1
  14. package/lib/feature-libraries/modular-schema/discrepancies.d.ts +1 -1
  15. package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  16. package/lib/feature-libraries/modular-schema/discrepancies.js +140 -181
  17. package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  18. package/lib/packageVersion.d.ts +1 -1
  19. package/lib/packageVersion.d.ts.map +1 -1
  20. package/lib/packageVersion.js +1 -1
  21. package/lib/packageVersion.js.map +1 -1
  22. package/lib/shared-tree/treeCheckout.d.ts +4 -0
  23. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  24. package/lib/shared-tree/treeCheckout.js +15 -2
  25. package/lib/shared-tree/treeCheckout.js.map +1 -1
  26. package/package.json +24 -32
  27. package/src/feature-libraries/modular-schema/discrepancies.ts +166 -203
  28. package/src/packageVersion.ts +1 -1
  29. package/src/shared-tree/treeCheckout.ts +21 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,83 @@
1
1
  # @fluidframework/tree
2
2
 
3
+ ## 2.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Fix typing bug in `adaptEnum` and `enumFromStrings` ([#23077](https://github.com/microsoft/FluidFramework/pull/23077)) [cfb68388cb](https://github.com/microsoft/FluidFramework/commit/cfb68388cb6b88a0ef670633b3afa46a82c99972)
8
+
9
+ When using the return value from [`adaptEnum`](https://fluidframework.com/docs/api/v2/tree#adaptenum-function) as a function, passing in a value who's type is a union no longer produced an incorrectly typed return value. This has been fixed.
10
+
11
+ Additionally [`enumFromStrings`](https://fluidframework.com/docs/api/v2/tree#enumfromstrings-function) has improved the typing of its schema, ensuring the returned object's members have sufficiently specific types.
12
+ Part of this improvement was fixing the `.schema` property to be a tuple over each of the schema where it was previously a tuple of a single combined schema due to a bug.
13
+
14
+ One side-effect of these fixes is that narrowing of the `value` field of a node typed from the `.schema` behaves slightly different, such that the node type is now a union instead of it being a single type with a `.value` that is a union.
15
+ This means that narrowing based on `.value` property narrows which node type you have, not just the value property.
16
+ This mainly matters when matching all cases like the switch statement below:
17
+
18
+ ```typescript
19
+ const Mode = enumFromStrings(schema, ["Fun", "Bonus"]);
20
+ type Mode = TreeNodeFromImplicitAllowedTypes<typeof Mode.schema>;
21
+ const node = new Mode.Bonus() as Mode;
22
+
23
+ switch (node.value) {
24
+ case "Fun": {
25
+ assert.fail();
26
+ }
27
+ case "Bonus": {
28
+ // This one runs
29
+ break;
30
+ }
31
+ default:
32
+ // Before this change, "node.value" was never here, now "node" is never.
33
+ unreachableCase(node);
34
+ }
35
+ ```
36
+
37
+ - SharedTree event listeners that implement `Listenable` now allow deregistration of event listeners via an `off()` function. ([#23046](https://github.com/microsoft/FluidFramework/pull/23046)) [c59225db03](https://github.com/microsoft/FluidFramework/commit/c59225db033a516ee20e459ae31567d97ce8776c)
38
+
39
+ The ability to deregister events via a callback returned by `on()` remains the same.
40
+ Both strategies will remain supported and consumers of SharedTree events may choose which method of deregistration they prefer in a given instance.
41
+
42
+ ```typescript
43
+ // The new behavior
44
+ function deregisterViaOff(view: TreeView<MySchema>): {
45
+ const listener = () => { /* ... */ };
46
+ view.events.on("commitApplied", listener); // Register
47
+ view.events.off("commitApplied", listener); // Deregister
48
+ }
49
+
50
+ // The existing behavior (still supported)
51
+ function deregisterViaCallback(view: TreeView<MySchema>): {
52
+ const off = view.events.on("commitApplied", () => { /* ... */ }); // Register
53
+ off(); // Deregister
54
+ }
55
+ ```
56
+
57
+ - Allow constructing recursive maps from objects ([#23070](https://github.com/microsoft/FluidFramework/pull/23070)) [0185a08c6f](https://github.com/microsoft/FluidFramework/commit/0185a08c6f8bf6e922a6467f11da049503c4d215)
58
+
59
+ Previously only non-recursive maps could be constructed from objects.
60
+ Now all maps nodes can constructed from objects:
61
+
62
+ ```typescript
63
+ class MapRecursive extends sf.mapRecursive("Map", [() => MapRecursive]) {}
64
+ {
65
+ type _check = ValidateRecursiveSchema<typeof MapRecursive>;
66
+ }
67
+ // New:
68
+ const fromObject = new MapRecursive({ x: new MapRecursive() });
69
+ // Existing:
70
+ const fromIterator = new MapRecursive([["x", new MapRecursive()]]);
71
+ const fromMap = new MapRecursive(new Map([["x", new MapRecursive()]]));
72
+ const fromNothing = new MapRecursive();
73
+ const fromUndefined = new MapRecursive(undefined);
74
+ ```
75
+
76
+ - Provide more comprehensive replacement to the `commitApplied` event ([#22977](https://github.com/microsoft/FluidFramework/pull/22977)) [e51c94da32](https://github.com/microsoft/FluidFramework/commit/e51c94da3248868de3c0c7fdce568cc425204155)
77
+
78
+ Adds a new `changed` event to the (currently alpha) `TreeBranchEvents` that replaces the `commitApplied` event on `TreeViewEvents`.
79
+ This new event is fired for both local and remote changes and maintains the existing functionality of `commitApplied` that is used for obtaining `Revertibles`.
80
+
3
81
  ## 2.5.0
4
82
 
5
83
  ### Minor Changes
@@ -91,7 +91,7 @@ type SchemaFactoryNodeKind = "object" | "leaf" | "map";
91
91
  *
92
92
  * @returns the discrepancies between two TreeStoredSchema objects
93
93
  */
94
- export declare function getAllowedContentDiscrepancies(view: TreeStoredSchema, stored: TreeStoredSchema): Discrepancy[];
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,EAEN,KAAK,mBAAmB,EAOxB,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;AAEvD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,8BAA8B,CAC7C,IAAI,EAAE,gBAAgB,EACtB,MAAM,EAAE,gBAAgB,GACtB,WAAW,EAAE,CA4Jf;AAwGD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAkCxF"}
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"}
@@ -8,6 +8,18 @@ exports.isRepoSuperset = exports.getAllowedContentDiscrepancies = void 0;
8
8
  const internal_1 = require("@fluidframework/core-utils/internal");
9
9
  const index_js_1 = require("../../core/index.js");
10
10
  const index_js_2 = require("../../util/index.js");
11
+ function getNodeSchemaType(nodeSchema) {
12
+ if (nodeSchema instanceof index_js_1.ObjectNodeStoredSchema) {
13
+ return "object";
14
+ }
15
+ else if (nodeSchema instanceof index_js_1.MapNodeStoredSchema) {
16
+ return "map";
17
+ }
18
+ else if (nodeSchema instanceof index_js_1.LeafNodeStoredSchema) {
19
+ return "leaf";
20
+ }
21
+ throwUnsupportedNodeType(nodeSchema.constructor.name);
22
+ }
11
23
  /**
12
24
  * Finds and reports discrepancies between a view schema and a stored schema.
13
25
  *
@@ -25,193 +37,116 @@ const index_js_2 = require("../../util/index.js");
25
37
  *
26
38
  * @returns the discrepancies between two TreeStoredSchema objects
27
39
  */
28
- function getAllowedContentDiscrepancies(view, stored) {
29
- const discrepancies = [];
40
+ function* getAllowedContentDiscrepancies(view, stored) {
30
41
  // check root schema discrepancies
31
- discrepancies.push(...trackFieldDiscrepancies(view.rootFieldSchema, stored.rootFieldSchema));
32
- // Verify the existence and type of a node schema given its identifier (key), then determine if
33
- // an exhaustive search is necessary.
34
- const viewNodeKeys = new Set();
35
- for (const [key, viewNodeSchema] of view.nodeSchema) {
36
- viewNodeKeys.add(key);
37
- if (viewNodeSchema instanceof index_js_1.ObjectNodeStoredSchema) {
38
- if (!stored.nodeSchema.has(key)) {
39
- discrepancies.push({
40
- identifier: key,
42
+ yield* getFieldDiscrepancies(view.rootFieldSchema, stored.rootFieldSchema);
43
+ for (const result of compareMaps(view.nodeSchema, stored.nodeSchema)) {
44
+ switch (result.type) {
45
+ case "aExtra": {
46
+ const viewType = getNodeSchemaType(result.value);
47
+ yield {
48
+ identifier: result.key,
41
49
  mismatch: "nodeKind",
42
- view: "object",
50
+ view: viewType,
43
51
  stored: undefined,
44
- });
45
- }
46
- else {
47
- const storedNodeSchema = stored.nodeSchema.get(key);
48
- (0, internal_1.assert)(storedNodeSchema !== undefined, 0x9be /* The storedNodeSchema in stored.nodeSchema should not be undefined */);
49
- if (storedNodeSchema instanceof index_js_1.MapNodeStoredSchema) {
50
- discrepancies.push({
51
- identifier: key,
52
- mismatch: "nodeKind",
53
- view: "object",
54
- stored: "map",
55
- });
56
- }
57
- else if (storedNodeSchema instanceof index_js_1.LeafNodeStoredSchema) {
58
- discrepancies.push({
59
- identifier: key,
60
- mismatch: "nodeKind",
61
- view: "object",
62
- stored: "leaf",
63
- });
64
- }
65
- else if (storedNodeSchema instanceof index_js_1.ObjectNodeStoredSchema) {
66
- const differences = trackObjectNodeDiscrepancies(viewNodeSchema, storedNodeSchema);
67
- if (differences.length > 0) {
68
- discrepancies.push({
69
- identifier: key,
70
- mismatch: "fields",
71
- differences,
72
- });
73
- }
74
- }
75
- else {
76
- throwUnsupportedNodeType(storedNodeSchema.constructor.name);
77
- }
52
+ };
53
+ break;
78
54
  }
79
- }
80
- else if (viewNodeSchema instanceof index_js_1.MapNodeStoredSchema) {
81
- if (!stored.nodeSchema.has(key)) {
82
- discrepancies.push({
83
- identifier: key,
55
+ case "bExtra": {
56
+ const storedType = getNodeSchemaType(result.value);
57
+ yield {
58
+ identifier: result.key,
84
59
  mismatch: "nodeKind",
85
- view: "map",
86
- stored: undefined,
87
- });
60
+ view: undefined,
61
+ stored: storedType,
62
+ };
63
+ break;
88
64
  }
89
- else {
90
- const storedNodeSchema = stored.nodeSchema.get(key);
91
- (0, internal_1.assert)(storedNodeSchema !== undefined, 0x9bf /* The storedNodeSchema in stored.nodeSchema should not be undefined */);
92
- if (storedNodeSchema instanceof index_js_1.ObjectNodeStoredSchema) {
93
- discrepancies.push({
94
- identifier: key,
95
- mismatch: "nodeKind",
96
- view: "map",
97
- stored: "object",
98
- });
99
- }
100
- else if (storedNodeSchema instanceof index_js_1.LeafNodeStoredSchema) {
101
- discrepancies.push({
102
- identifier: key,
103
- mismatch: "nodeKind",
104
- view: "map",
105
- stored: "leaf",
106
- });
107
- }
108
- else if (storedNodeSchema instanceof index_js_1.MapNodeStoredSchema) {
109
- discrepancies.push(...trackFieldDiscrepancies(viewNodeSchema.mapFields, storedNodeSchema.mapFields, key));
110
- }
111
- else {
112
- throwUnsupportedNodeType(storedNodeSchema.constructor.name);
113
- }
65
+ case "both": {
66
+ yield* getNodeDiscrepancies(result.key, result.valueA, result.valueB);
67
+ break;
114
68
  }
69
+ default:
70
+ break;
115
71
  }
116
- else if (viewNodeSchema instanceof index_js_1.LeafNodeStoredSchema) {
117
- if (!stored.nodeSchema.has(key)) {
118
- discrepancies.push({
119
- identifier: key,
120
- mismatch: "nodeKind",
121
- view: "leaf",
122
- stored: undefined,
123
- });
124
- }
125
- else {
126
- const storedNodeSchema = stored.nodeSchema.get(key);
127
- (0, internal_1.assert)(storedNodeSchema !== undefined, 0x9c0 /* The storedNodeSchema in stored.nodeSchema should not be undefined */);
128
- if (storedNodeSchema instanceof index_js_1.MapNodeStoredSchema) {
129
- discrepancies.push({
130
- identifier: key,
131
- mismatch: "nodeKind",
132
- view: "leaf",
133
- stored: "map",
134
- });
135
- }
136
- else if (storedNodeSchema instanceof index_js_1.ObjectNodeStoredSchema) {
137
- discrepancies.push({
138
- identifier: key,
139
- mismatch: "nodeKind",
140
- view: "leaf",
141
- stored: "object",
142
- });
143
- }
144
- else if (storedNodeSchema instanceof index_js_1.LeafNodeStoredSchema) {
145
- if (viewNodeSchema.leafValue !== storedNodeSchema.leafValue) {
146
- discrepancies.push({
147
- identifier: key,
148
- mismatch: "valueSchema",
149
- view: viewNodeSchema.leafValue,
150
- stored: storedNodeSchema.leafValue,
151
- });
152
- }
153
- }
154
- else {
155
- throwUnsupportedNodeType(storedNodeSchema.constructor.name);
156
- }
72
+ }
73
+ }
74
+ exports.getAllowedContentDiscrepancies = getAllowedContentDiscrepancies;
75
+ function* getNodeDiscrepancies(identifier, view, stored) {
76
+ const viewType = getNodeSchemaType(view);
77
+ const storedType = getNodeSchemaType(stored);
78
+ if (viewType !== storedType) {
79
+ yield {
80
+ identifier,
81
+ mismatch: "nodeKind",
82
+ view: viewType,
83
+ stored: storedType,
84
+ };
85
+ return;
86
+ }
87
+ switch (viewType) {
88
+ case "object": {
89
+ const differences = Array.from(trackObjectNodeDiscrepancies(view, stored));
90
+ if (differences.length > 0) {
91
+ yield {
92
+ identifier,
93
+ mismatch: "fields",
94
+ differences,
95
+ };
157
96
  }
97
+ break;
158
98
  }
159
- else {
160
- throwUnsupportedNodeType(viewNodeSchema.constructor.name);
161
- }
162
- }
163
- for (const [key, storedNodeSchema] of stored.nodeSchema) {
164
- if (!viewNodeKeys.has(key)) {
165
- discrepancies.push({
166
- identifier: key,
167
- mismatch: "nodeKind",
168
- view: undefined,
169
- stored: storedNodeSchema instanceof index_js_1.MapNodeStoredSchema
170
- ? "map"
171
- : storedNodeSchema instanceof index_js_1.ObjectNodeStoredSchema
172
- ? "object"
173
- : "leaf",
174
- });
99
+ case "map":
100
+ yield* getFieldDiscrepancies(view.mapFields, stored.mapFields, identifier);
101
+ break;
102
+ case "leaf": {
103
+ const viewValue = view.leafValue;
104
+ const storedValue = stored.leafValue;
105
+ if (viewValue !== storedValue) {
106
+ yield {
107
+ identifier,
108
+ mismatch: "valueSchema",
109
+ view: viewValue,
110
+ stored: storedValue,
111
+ };
112
+ }
113
+ break;
175
114
  }
115
+ default:
116
+ break;
176
117
  }
177
- return discrepancies;
178
118
  }
179
- exports.getAllowedContentDiscrepancies = getAllowedContentDiscrepancies;
180
119
  /**
181
120
  * The function to track the discrepancies between two field stored schemas.
182
121
  *
183
122
  * @param keyOrRoot - If the key is missing, it indicates that this is the root field schema.
184
123
  */
185
- function trackFieldDiscrepancies(view, stored, keyOrRoot) {
186
- const differences = [];
124
+ function* getFieldDiscrepancies(view, stored, keyOrRoot) {
187
125
  // Only track the symmetric differences of two sets.
188
126
  const findSetDiscrepancies = (a, b) => {
189
127
  const aDiff = [...a].filter((value) => !b.has(value));
190
128
  const bDiff = [...b].filter((value) => !a.has(value));
191
129
  return [aDiff, bDiff];
192
130
  };
193
- const allowedTypesDiscrepancies = findSetDiscrepancies(view.types, stored.types);
194
- if (allowedTypesDiscrepancies[0].length > 0 || allowedTypesDiscrepancies[1].length > 0) {
195
- differences.push({
131
+ const [viewExtra, storedExtra] = findSetDiscrepancies(view.types, stored.types);
132
+ if (viewExtra.length > 0 || storedExtra.length > 0) {
133
+ yield {
196
134
  identifier: keyOrRoot,
197
135
  mismatch: "allowedTypes",
198
- view: allowedTypesDiscrepancies[0],
199
- stored: allowedTypesDiscrepancies[1],
200
- });
136
+ view: viewExtra,
137
+ stored: storedExtra,
138
+ };
201
139
  }
202
140
  if (view.kind !== stored.kind) {
203
- differences.push({
141
+ yield {
204
142
  identifier: keyOrRoot,
205
143
  mismatch: "fieldKind",
206
144
  view: view.kind,
207
145
  stored: stored.kind,
208
- });
146
+ };
209
147
  }
210
- return differences;
211
148
  }
212
- function trackObjectNodeDiscrepancies(view, stored) {
213
- const differences = [];
214
- const viewFieldKeys = new Set();
149
+ function* trackObjectNodeDiscrepancies(view, stored) {
215
150
  /**
216
151
  * Similar to the logic used for tracking discrepancies between two node schemas, we will identify
217
152
  * three types of differences:
@@ -222,35 +157,59 @@ function trackObjectNodeDiscrepancies(view, stored) {
222
157
  * First, the view schema is iterated to track the first two types of differences.
223
158
  * Then, the stored schema is iterated to find the third type.
224
159
  */
225
- for (const [fieldKey, fieldStoredSchema] of view.objectNodeFields) {
226
- viewFieldKeys.add(fieldKey);
227
- if (!stored.objectNodeFields.has(fieldKey) &&
228
- fieldStoredSchema.kind !== index_js_1.storedEmptyFieldSchema.kind) {
229
- differences.push({
230
- identifier: fieldKey,
231
- mismatch: "fieldKind",
232
- view: fieldStoredSchema.kind,
233
- stored: index_js_1.storedEmptyFieldSchema.kind,
234
- });
235
- }
236
- else {
237
- differences.push(...trackFieldDiscrepancies(view.objectNodeFields.get(fieldKey), stored.objectNodeFields.get(fieldKey), fieldKey));
160
+ for (const result of compareMaps(view.objectNodeFields, stored.objectNodeFields)) {
161
+ const fieldKey = result.key;
162
+ switch (result.type) {
163
+ case "aExtra": {
164
+ if (result.value.kind === index_js_1.storedEmptyFieldSchema.kind) {
165
+ // In one of view/stored, this field is explicitly forbidden, but in the other it is implicitly forbidden
166
+ // (by way of omission). We treat these identically anyway.
167
+ break;
168
+ }
169
+ yield {
170
+ identifier: fieldKey,
171
+ mismatch: "fieldKind",
172
+ view: result.value.kind,
173
+ stored: index_js_1.storedEmptyFieldSchema.kind,
174
+ };
175
+ break;
176
+ }
177
+ case "bExtra": {
178
+ if (result.value.kind === index_js_1.storedEmptyFieldSchema.kind) {
179
+ // In one of view/stored, this field is explicitly forbidden, but in the other it is implicitly forbidden
180
+ // (by way of omission). We treat these identically anyway.
181
+ break;
182
+ }
183
+ yield {
184
+ identifier: fieldKey,
185
+ mismatch: "fieldKind",
186
+ view: index_js_1.storedEmptyFieldSchema.kind,
187
+ stored: result.value.kind,
188
+ };
189
+ break;
190
+ }
191
+ case "both": {
192
+ yield* getFieldDiscrepancies(result.valueA, result.valueB, fieldKey);
193
+ break;
194
+ }
195
+ default: {
196
+ break;
197
+ }
238
198
  }
239
199
  }
240
- for (const [fieldKey, fieldStoredSchema] of stored.objectNodeFields) {
241
- if (viewFieldKeys.has(fieldKey)) {
242
- continue;
243
- }
244
- if (fieldStoredSchema.kind !== index_js_1.storedEmptyFieldSchema.kind) {
245
- differences.push({
246
- identifier: fieldKey,
247
- mismatch: "fieldKind",
248
- view: index_js_1.storedEmptyFieldSchema.kind,
249
- stored: fieldStoredSchema.kind,
250
- });
200
+ }
201
+ function* compareMaps(a, b) {
202
+ for (const [key, valueA] of a) {
203
+ const valueB = b.get(key);
204
+ yield valueB === undefined
205
+ ? { type: "aExtra", key, value: valueA }
206
+ : { type: "both", key, valueA, valueB };
207
+ }
208
+ for (const [key, valueB] of b) {
209
+ if (!a.has(key)) {
210
+ yield { type: "bExtra", key, value: valueB };
251
211
  }
252
212
  }
253
- return differences;
254
213
  }
255
214
  /**
256
215
  * @remarks
@@ -283,13 +242,13 @@ function isRepoSuperset(view, stored) {
283
242
  case "valueSchema":
284
243
  case "allowedTypes":
285
244
  case "fieldKind": {
286
- if (!validateFieldIncompatibility(discrepancy)) {
245
+ if (!isFieldDiscrepancyCompatible(discrepancy)) {
287
246
  return false;
288
247
  }
289
248
  break;
290
249
  }
291
250
  case "fields": {
292
- if (discrepancy.differences.some((difference) => !validateFieldIncompatibility(difference))) {
251
+ if (discrepancy.differences.some((difference) => !isFieldDiscrepancyCompatible(difference))) {
293
252
  return false;
294
253
  }
295
254
  break;
@@ -300,7 +259,7 @@ function isRepoSuperset(view, stored) {
300
259
  return true;
301
260
  }
302
261
  exports.isRepoSuperset = isRepoSuperset;
303
- function validateFieldIncompatibility(discrepancy) {
262
+ function isFieldDiscrepancyCompatible(discrepancy) {
304
263
  switch (discrepancy.mismatch) {
305
264
  case "allowedTypes": {
306
265
  // Since we only track the symmetric difference between the allowed types in the view and
@@ -377,7 +336,7 @@ function comparePosetElements(a, b, realizer) {
377
336
  for (const extension of realizer) {
378
337
  const aIndex = extension.get(a);
379
338
  const bIndex = extension.get(b);
380
- (0, internal_1.assert)(aIndex !== undefined && bIndex !== undefined, "Invalid realizer");
339
+ (0, internal_1.assert)(aIndex !== undefined && bIndex !== undefined, 0xa72 /* Invalid realizer */);
381
340
  if (aIndex < bIndex) {
382
341
  hasLessThanResult = true;
383
342
  }