@fluidframework/ai-collab 2.10.0-306579

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/.eslintrc.cjs +26 -0
  2. package/CHANGELOG.md +9 -0
  3. package/LICENSE +21 -0
  4. package/README.md +280 -0
  5. package/alpha.d.ts +11 -0
  6. package/api-extractor/api-extractor-lint-alpha.cjs.json +5 -0
  7. package/api-extractor/api-extractor-lint-alpha.esm.json +5 -0
  8. package/api-extractor/api-extractor-lint-bundle.json +5 -0
  9. package/api-extractor/api-extractor-lint-index.cjs.json +5 -0
  10. package/api-extractor/api-extractor-lint-index.esm.json +5 -0
  11. package/api-extractor/api-extractor-lint-public.cjs.json +5 -0
  12. package/api-extractor/api-extractor-lint-public.esm.json +5 -0
  13. package/api-extractor-lint.json +4 -0
  14. package/api-extractor.json +4 -0
  15. package/api-report/ai-collab.alpha.api.md +164 -0
  16. package/api-report/ai-collab.beta.api.md +7 -0
  17. package/api-report/ai-collab.public.api.md +7 -0
  18. package/biome.jsonc +4 -0
  19. package/dist/aiCollab.d.ts +65 -0
  20. package/dist/aiCollab.d.ts.map +1 -0
  21. package/dist/aiCollab.js +81 -0
  22. package/dist/aiCollab.js.map +1 -0
  23. package/dist/aiCollabApi.d.ts +173 -0
  24. package/dist/aiCollabApi.d.ts.map +1 -0
  25. package/dist/aiCollabApi.js +7 -0
  26. package/dist/aiCollabApi.js.map +1 -0
  27. package/dist/alpha.d.ts +41 -0
  28. package/dist/explicit-strategy/agentEditReducer.d.ts +12 -0
  29. package/dist/explicit-strategy/agentEditReducer.d.ts.map +1 -0
  30. package/dist/explicit-strategy/agentEditReducer.js +394 -0
  31. package/dist/explicit-strategy/agentEditReducer.js.map +1 -0
  32. package/dist/explicit-strategy/agentEditTypes.d.ts +158 -0
  33. package/dist/explicit-strategy/agentEditTypes.d.ts.map +1 -0
  34. package/dist/explicit-strategy/agentEditTypes.js +50 -0
  35. package/dist/explicit-strategy/agentEditTypes.js.map +1 -0
  36. package/dist/explicit-strategy/idGenerator.d.ts +22 -0
  37. package/dist/explicit-strategy/idGenerator.d.ts.map +1 -0
  38. package/dist/explicit-strategy/idGenerator.js +74 -0
  39. package/dist/explicit-strategy/idGenerator.js.map +1 -0
  40. package/dist/explicit-strategy/index.d.ts +51 -0
  41. package/dist/explicit-strategy/index.d.ts.map +1 -0
  42. package/dist/explicit-strategy/index.js +223 -0
  43. package/dist/explicit-strategy/index.js.map +1 -0
  44. package/dist/explicit-strategy/jsonTypes.d.ts +23 -0
  45. package/dist/explicit-strategy/jsonTypes.d.ts.map +1 -0
  46. package/dist/explicit-strategy/jsonTypes.js +7 -0
  47. package/dist/explicit-strategy/jsonTypes.js.map +1 -0
  48. package/dist/explicit-strategy/promptGeneration.d.ts +51 -0
  49. package/dist/explicit-strategy/promptGeneration.d.ts.map +1 -0
  50. package/dist/explicit-strategy/promptGeneration.js +218 -0
  51. package/dist/explicit-strategy/promptGeneration.js.map +1 -0
  52. package/dist/explicit-strategy/typeGeneration.d.ts +15 -0
  53. package/dist/explicit-strategy/typeGeneration.d.ts.map +1 -0
  54. package/dist/explicit-strategy/typeGeneration.js +264 -0
  55. package/dist/explicit-strategy/typeGeneration.js.map +1 -0
  56. package/dist/explicit-strategy/utils.d.ts +37 -0
  57. package/dist/explicit-strategy/utils.d.ts.map +1 -0
  58. package/dist/explicit-strategy/utils.js +47 -0
  59. package/dist/explicit-strategy/utils.js.map +1 -0
  60. package/dist/implicit-strategy/index.d.ts +8 -0
  61. package/dist/implicit-strategy/index.d.ts.map +1 -0
  62. package/dist/implicit-strategy/index.js +18 -0
  63. package/dist/implicit-strategy/index.js.map +1 -0
  64. package/dist/implicit-strategy/sharedTreeBranchManager.d.ts +63 -0
  65. package/dist/implicit-strategy/sharedTreeBranchManager.d.ts.map +1 -0
  66. package/dist/implicit-strategy/sharedTreeBranchManager.js +212 -0
  67. package/dist/implicit-strategy/sharedTreeBranchManager.js.map +1 -0
  68. package/dist/implicit-strategy/sharedTreeDiff.d.ts +102 -0
  69. package/dist/implicit-strategy/sharedTreeDiff.d.ts.map +1 -0
  70. package/dist/implicit-strategy/sharedTreeDiff.js +522 -0
  71. package/dist/implicit-strategy/sharedTreeDiff.js.map +1 -0
  72. package/dist/implicit-strategy/utils.d.ts +21 -0
  73. package/dist/implicit-strategy/utils.d.ts.map +1 -0
  74. package/dist/implicit-strategy/utils.js +49 -0
  75. package/dist/implicit-strategy/utils.js.map +1 -0
  76. package/dist/index.d.ts +16 -0
  77. package/dist/index.d.ts.map +1 -0
  78. package/dist/index.js +24 -0
  79. package/dist/index.js.map +1 -0
  80. package/dist/package.json +3 -0
  81. package/dist/public.d.ts +19 -0
  82. package/eslintrc.cjs +11 -0
  83. package/internal.d.ts +11 -0
  84. package/lib/aiCollab.d.ts +65 -0
  85. package/lib/aiCollab.d.ts.map +1 -0
  86. package/lib/aiCollab.js +77 -0
  87. package/lib/aiCollab.js.map +1 -0
  88. package/lib/aiCollabApi.d.ts +173 -0
  89. package/lib/aiCollabApi.d.ts.map +1 -0
  90. package/lib/aiCollabApi.js +6 -0
  91. package/lib/aiCollabApi.js.map +1 -0
  92. package/lib/alpha.d.ts +41 -0
  93. package/lib/explicit-strategy/agentEditReducer.d.ts +12 -0
  94. package/lib/explicit-strategy/agentEditReducer.d.ts.map +1 -0
  95. package/lib/explicit-strategy/agentEditReducer.js +390 -0
  96. package/lib/explicit-strategy/agentEditReducer.js.map +1 -0
  97. package/lib/explicit-strategy/agentEditTypes.d.ts +158 -0
  98. package/lib/explicit-strategy/agentEditTypes.d.ts.map +1 -0
  99. package/lib/explicit-strategy/agentEditTypes.js +47 -0
  100. package/lib/explicit-strategy/agentEditTypes.js.map +1 -0
  101. package/lib/explicit-strategy/idGenerator.d.ts +22 -0
  102. package/lib/explicit-strategy/idGenerator.d.ts.map +1 -0
  103. package/lib/explicit-strategy/idGenerator.js +70 -0
  104. package/lib/explicit-strategy/idGenerator.js.map +1 -0
  105. package/lib/explicit-strategy/index.d.ts +51 -0
  106. package/lib/explicit-strategy/index.d.ts.map +1 -0
  107. package/lib/explicit-strategy/index.js +219 -0
  108. package/lib/explicit-strategy/index.js.map +1 -0
  109. package/lib/explicit-strategy/jsonTypes.d.ts +23 -0
  110. package/lib/explicit-strategy/jsonTypes.d.ts.map +1 -0
  111. package/lib/explicit-strategy/jsonTypes.js +6 -0
  112. package/lib/explicit-strategy/jsonTypes.js.map +1 -0
  113. package/lib/explicit-strategy/promptGeneration.d.ts +51 -0
  114. package/lib/explicit-strategy/promptGeneration.d.ts.map +1 -0
  115. package/lib/explicit-strategy/promptGeneration.js +208 -0
  116. package/lib/explicit-strategy/promptGeneration.js.map +1 -0
  117. package/lib/explicit-strategy/typeGeneration.d.ts +15 -0
  118. package/lib/explicit-strategy/typeGeneration.d.ts.map +1 -0
  119. package/lib/explicit-strategy/typeGeneration.js +260 -0
  120. package/lib/explicit-strategy/typeGeneration.js.map +1 -0
  121. package/lib/explicit-strategy/utils.d.ts +37 -0
  122. package/lib/explicit-strategy/utils.d.ts.map +1 -0
  123. package/lib/explicit-strategy/utils.js +41 -0
  124. package/lib/explicit-strategy/utils.js.map +1 -0
  125. package/lib/implicit-strategy/index.d.ts +8 -0
  126. package/lib/implicit-strategy/index.d.ts.map +1 -0
  127. package/lib/implicit-strategy/index.js +8 -0
  128. package/lib/implicit-strategy/index.js.map +1 -0
  129. package/lib/implicit-strategy/sharedTreeBranchManager.d.ts +63 -0
  130. package/lib/implicit-strategy/sharedTreeBranchManager.d.ts.map +1 -0
  131. package/lib/implicit-strategy/sharedTreeBranchManager.js +213 -0
  132. package/lib/implicit-strategy/sharedTreeBranchManager.js.map +1 -0
  133. package/lib/implicit-strategy/sharedTreeDiff.d.ts +102 -0
  134. package/lib/implicit-strategy/sharedTreeDiff.d.ts.map +1 -0
  135. package/lib/implicit-strategy/sharedTreeDiff.js +515 -0
  136. package/lib/implicit-strategy/sharedTreeDiff.js.map +1 -0
  137. package/lib/implicit-strategy/utils.d.ts +21 -0
  138. package/lib/implicit-strategy/utils.d.ts.map +1 -0
  139. package/lib/implicit-strategy/utils.js +43 -0
  140. package/lib/implicit-strategy/utils.js.map +1 -0
  141. package/lib/index.d.ts +16 -0
  142. package/lib/index.d.ts.map +1 -0
  143. package/lib/index.js +15 -0
  144. package/lib/index.js.map +1 -0
  145. package/lib/public.d.ts +19 -0
  146. package/lib/tsdoc-metadata.json +11 -0
  147. package/mocharc.cjs +14 -0
  148. package/package.json +165 -0
  149. package/prettier.config.cjs +8 -0
  150. package/src/aiCollab.ts +86 -0
  151. package/src/aiCollabApi.ts +184 -0
  152. package/src/explicit-strategy/agentEditReducer.ts +498 -0
  153. package/src/explicit-strategy/agentEditTypes.ts +177 -0
  154. package/src/explicit-strategy/idGenerator.ts +90 -0
  155. package/src/explicit-strategy/index.ts +364 -0
  156. package/src/explicit-strategy/jsonTypes.ts +27 -0
  157. package/src/explicit-strategy/promptGeneration.ts +294 -0
  158. package/src/explicit-strategy/typeGeneration.ts +374 -0
  159. package/src/explicit-strategy/utils.ts +60 -0
  160. package/src/implicit-strategy/README.md +4 -0
  161. package/src/implicit-strategy/index.ts +21 -0
  162. package/src/implicit-strategy/sharedTreeBranchManager.ts +294 -0
  163. package/src/implicit-strategy/sharedTreeDiff.ts +735 -0
  164. package/src/implicit-strategy/utils.ts +54 -0
  165. package/src/index.ts +39 -0
  166. package/tsconfig.cjs.json +7 -0
  167. package/tsconfig.json +12 -0
  168. package/tsdoc.json +4 -0
@@ -0,0 +1,522 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
+ * Licensed under the MIT License.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.isDiffOnArray = exports.createMergableDiffSeries = exports.createMergableIdDiffSeries = exports.sharedTreeDiff = void 0;
8
+ const tree_1 = require("@fluidframework/tree");
9
+ const utils_js_1 = require("./utils.js");
10
+ const richTypes = { Date: true, RegExp: true, String: true, Number: true };
11
+ /**
12
+ * By default, Object Diff supports cyclical references, but if you are sure that the object has no cycles like parsed JSON
13
+ * you can disable cycles by setting the cyclesFix option to false
14
+ */
15
+ const DEFAULT_OPTIONS = { cyclesFix: true };
16
+ /**
17
+ * Compares two objects and returns an array of differences between them.
18
+ *
19
+ * @alpha
20
+ */
21
+ function sharedTreeDiff(obj, newObj, options = DEFAULT_OPTIONS, _stack = []) {
22
+ const diffs = [];
23
+ const isObjArray = isArrayOrTreeArrayNode(obj);
24
+ const isNewObjArray = isArrayOrTreeArrayNode(newObj);
25
+ // If useObjectIds is set, we'll create a map of object ids to their index in the array.
26
+ const oldObjArrayItemIdsToIndex = isObjArray === false || options.useObjectIds === undefined
27
+ ? new Map()
28
+ : createObjectArrayItemIdsToIndexMap(obj, options.useObjectIds.idAttributeName);
29
+ const newObjArrayItemIdsToIndex = isNewObjArray === false || options.useObjectIds === undefined
30
+ ? new Map()
31
+ : createObjectArrayItemIdsToIndexMap(newObj, options.useObjectIds.idAttributeName);
32
+ const objectKeys = (0, utils_js_1.isTreeMapNode)(obj) ? obj.keys() : Object.keys(obj);
33
+ // We compare existence and values of all attributes within the old against new object, looking for removals or changes.
34
+ for (const key of objectKeys) {
35
+ const objValue = (0, utils_js_1.isTreeMapNode)(obj) ? obj.get(key) : obj[key];
36
+ const path = isObjArray ? +key : key;
37
+ // 1. First, check if the key within the old object, exists within the new object. If it doesn't exist this would be an attribute removal.
38
+ if (!(key in newObj)) {
39
+ if (options.useObjectIds === undefined) {
40
+ diffs.push({
41
+ type: "REMOVE",
42
+ path: [path],
43
+ objectId: undefined,
44
+ oldValue: objValue,
45
+ });
46
+ continue;
47
+ }
48
+ // If we're dealing with an object in an array, we can use the object's id to check if it was moved to a new index.
49
+ else if (isNewObjArray === true &&
50
+ isObjArray &&
51
+ typeof objValue === "object" &&
52
+ objValue !== null) {
53
+ const objectId = objValue[options.useObjectIds.idAttributeName];
54
+ if (objectId !== undefined && newObjArrayItemIdsToIndex.has(objectId)) {
55
+ // The index no longer exists in the new root object array, however the object that lived at this index actually still exists at a new index.
56
+ // Therefore, this node was moved to a new index.
57
+ diffs.push({
58
+ type: "MOVE",
59
+ path: [path],
60
+ newIndex: newObjArrayItemIdsToIndex.get(objectId),
61
+ value: objValue,
62
+ objectId,
63
+ });
64
+ continue;
65
+ }
66
+ // The object with the given id cannot be found within the new array, therefore it was removed.
67
+ else {
68
+ diffs.push({
69
+ type: "REMOVE",
70
+ path: [path],
71
+ objectId,
72
+ oldValue: objValue,
73
+ });
74
+ continue;
75
+ }
76
+ }
77
+ // If we're not dealing with an object in an array, we can't use id's to check for a move.
78
+ // We'll assume that a missing key in the new object means that the cooresponding value was removed.
79
+ else {
80
+ diffs.push({
81
+ type: "REMOVE",
82
+ path: [path],
83
+ objectId: undefined,
84
+ oldValue: objValue,
85
+ });
86
+ continue;
87
+ }
88
+ }
89
+ const newObjValue = newObj[key];
90
+ const areCompatibleObjects = typeof objValue === "object" &&
91
+ typeof newObjValue === "object" &&
92
+ isArrayOrTreeArrayNode(objValue) === isArrayOrTreeArrayNode(newObjValue);
93
+ // 2a. If the given old object key exists in the new object, and the value of said key in both objects is ANOTHER nested object, we need to run a recursive diff check on them.
94
+ if (objValue !== null &&
95
+ newObjValue !== null &&
96
+ areCompatibleObjects &&
97
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/no-unsafe-member-access
98
+ !richTypes[Object.getPrototypeOf(objValue)?.constructor?.name] &&
99
+ (!options.cyclesFix || !_stack.includes(objValue))) {
100
+ if (options.useObjectIds === undefined) {
101
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
102
+ ? [..._stack, objValue]
103
+ : []);
104
+ // eslint-disable-next-line prefer-spread
105
+ diffs.push.apply(diffs, nestedDiffs.map((difference) => {
106
+ difference.path.unshift(path);
107
+ return difference;
108
+ }));
109
+ }
110
+ // Use Object Id strategy to determine if the objects should be compared for changes
111
+ else {
112
+ const oldObjectId = objValue[options.useObjectIds.idAttributeName];
113
+ const newObjectId = newObjValue[options.useObjectIds.idAttributeName];
114
+ if (oldObjectId !== undefined && newObjectId !== undefined) {
115
+ // 2a.1 if the object id's are the same, we can continue a comparison between the two objects.
116
+ if (oldObjectId === newObjectId) {
117
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
118
+ ? [..._stack, objValue]
119
+ : []);
120
+ diffs.push(...nestedDiffs.map((difference) => {
121
+ difference.path.unshift(path);
122
+ return difference;
123
+ }));
124
+ }
125
+ // 2a.2 The object id's are different, their attributes cannot be compared.
126
+ // We need to find the new index of the object, if it exists in the new array and do a diff comparison.
127
+ else {
128
+ const newIndexOfOldObject = newObjArrayItemIdsToIndex.get(oldObjectId);
129
+ // The object no longer exists in the new array, therefore it was removed.
130
+ if (newIndexOfOldObject === undefined) {
131
+ diffs.push({
132
+ type: "REMOVE",
133
+ path: [path],
134
+ oldValue: objValue,
135
+ objectId: oldObjectId,
136
+ });
137
+ }
138
+ // This object still exists but at a new index within the new array therefore it was moved.
139
+ // At this point we can determine whether a new move is necessary or there is one that will place it at the desired index.
140
+ else {
141
+ diffs.push({
142
+ type: "MOVE",
143
+ path: [path],
144
+ newIndex: newIndexOfOldObject,
145
+ value: objValue,
146
+ objectId: oldObjectId,
147
+ });
148
+ // An object could have been moved AND changed. We need to check for this.
149
+ const nestedDiffs = sharedTreeDiff(obj[path], newObj[newIndexOfOldObject], options, options.cyclesFix === true
150
+ ? [..._stack, objValue]
151
+ : []);
152
+ diffs.push(...nestedDiffs.map((difference) => {
153
+ difference.path.unshift(path);
154
+ return difference;
155
+ }));
156
+ }
157
+ }
158
+ }
159
+ else {
160
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
161
+ ? [..._stack, objValue]
162
+ : []);
163
+ diffs.push(...nestedDiffs.map((difference) => {
164
+ difference.path.unshift(path);
165
+ return difference;
166
+ }));
167
+ }
168
+ }
169
+ }
170
+ // 2b. If the given old object key exists in the new object, and the value of said key in both objects is NOT another nested object, we need to check if the values are the same.
171
+ else if (objValue !== newObjValue &&
172
+ // treat NaN values as equivalent
173
+ !(Number.isNaN(objValue) && Number.isNaN(newObjValue)) &&
174
+ !(areCompatibleObjects &&
175
+ (Number.isNaN(objValue)
176
+ ? // eslint-disable-next-line prefer-template
177
+ objValue + "" === newObjValue + ""
178
+ : // eslint-disable-next-line @typescript-eslint/ban-ts-comment
179
+ // @ts-ignore
180
+ +objValue === +newObjValue))) {
181
+ diffs.push({
182
+ path: [path],
183
+ type: "CHANGE",
184
+ value: newObjValue,
185
+ oldValue: objValue,
186
+ objectId: options.useObjectIds?.idAttributeName === undefined
187
+ ? undefined
188
+ : newObj[options.useObjectIds.idAttributeName],
189
+ });
190
+ }
191
+ }
192
+ // 3. Finally, we check for new keys in the new object that did not exist in the old object.
193
+ // The existence of new keys may signal new values or moved values.
194
+ const newObjKeys = (0, utils_js_1.isTreeMapNode)(newObj) ? newObj.keys() : Object.keys(newObj);
195
+ for (const key of newObjKeys) {
196
+ const newObjValue = (0, utils_js_1.isTreeMapNode)(newObj)
197
+ ? newObj.get(key)
198
+ : newObj[key];
199
+ const path = isNewObjArray ? +key : key;
200
+ const isKeyInOldObject = (0, utils_js_1.isTreeMapNode)(obj)
201
+ ? obj.has(key)
202
+ : Object.keys(obj).includes(key);
203
+ if (!isKeyInOldObject) {
204
+ if (options.useObjectIds === undefined) {
205
+ diffs.push({
206
+ type: "CREATE",
207
+ path: [path],
208
+ value: newObjValue,
209
+ });
210
+ }
211
+ // If we're dealing with an object in an array, we can use the object's id to check if this new index actually
212
+ // contains a prexisting object that was moved from an old index.
213
+ else if (isObjArray === true &&
214
+ isNewObjArray === true &&
215
+ typeof newObjValue === "object" &&
216
+ newObjValue !== null) {
217
+ const objectId = newObjValue[options.useObjectIds.idAttributeName];
218
+ if (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId)) {
219
+ // The new root object array contains a new index, however the object that lives at this new index previously existed at an old index.
220
+ // Therefore, this object was moved to a new index.
221
+ diffs.push({
222
+ type: "MOVE",
223
+ path: [path],
224
+ newIndex: newObjArrayItemIdsToIndex.get(objectId),
225
+ value: newObjValue,
226
+ objectId,
227
+ });
228
+ continue;
229
+ }
230
+ // If either the object's id attribute does not exist or the original array does not contain an object with the given id
231
+ // Then we assume this was a newly created object.
232
+ else {
233
+ diffs.push({
234
+ type: "CREATE",
235
+ path: [path],
236
+ value: newObjValue,
237
+ });
238
+ }
239
+ }
240
+ // If we're not dealing with an object in an array, we can't use id's to check for a move.
241
+ // We'll assume that a brand new key and value pair in the new object means that a new value was created.
242
+ else {
243
+ diffs.push({
244
+ type: "CREATE",
245
+ path: [path],
246
+ value: newObjValue,
247
+ });
248
+ }
249
+ }
250
+ else if (options.useObjectIds !== undefined) {
251
+ // If we're dealing with an object in an array, we can use the object's id to check if this EXISTING index
252
+ // houses a new object based on a newly encountered id.
253
+ if (isObjArray === true &&
254
+ isNewObjArray === true &&
255
+ typeof newObjValue === "object" &&
256
+ newObjValue !== null) {
257
+ const objectId = newObjValue[options.useObjectIds.idAttributeName];
258
+ // If this object has an id and it does not exist in the old array, then it was created.
259
+ if (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId) === false) {
260
+ diffs.push({
261
+ type: "CREATE",
262
+ path: [path],
263
+ value: newObjValue,
264
+ });
265
+ }
266
+ }
267
+ else {
268
+ continue;
269
+ }
270
+ }
271
+ }
272
+ return diffs;
273
+ }
274
+ exports.sharedTreeDiff = sharedTreeDiff;
275
+ /**
276
+ * Type Guard that determines if a given object is an array of type unknown[] or {@link TreeArrayNode}.
277
+ */
278
+ function isArrayOrTreeArrayNode(obj) {
279
+ if (typeof obj === "object" && obj !== null) {
280
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
281
+ const maybeNodeKind = Object.getPrototypeOf(obj)?.constructor?.kind;
282
+ const isTreeArrayNode = maybeNodeKind === tree_1.NodeKind.Array;
283
+ return Array.isArray(obj) || isTreeArrayNode;
284
+ }
285
+ return false;
286
+ }
287
+ /**
288
+ * Helper that creates a map of object ids to their index in an array of objects.
289
+ */
290
+ function createObjectArrayItemIdsToIndexMap(obj, idAttributeName) {
291
+ const objArrayItemIdsToIndex = new Map();
292
+ for (let i = 0; i < obj.length; i++) {
293
+ const objArrayItem = obj[i];
294
+ if (typeof objArrayItem === "object" && objArrayItem !== null) {
295
+ const id = objArrayItem[idAttributeName];
296
+ if (objArrayItemIdsToIndex.has(id)) {
297
+ throw new TypeError(`Duplicate object id found: ${id}`);
298
+ }
299
+ else if (id !== undefined) {
300
+ objArrayItemIdsToIndex.set(id, i);
301
+ }
302
+ }
303
+ }
304
+ return objArrayItemIdsToIndex;
305
+ }
306
+ /**
307
+ * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}
308
+ * that are using the object ID strategy. These diffs don't need any modifications to be applied to the old object.
309
+ *
310
+ * @alpha
311
+ */
312
+ function createMergableIdDiffSeries(oldObject, diffs, idAttributeName) {
313
+ // the final series of diffs that will be returned.
314
+ const finalDiffSeries = [];
315
+ // Diffs that aren't of type 'CHANGE'
316
+ const nonChangeDiffs = [];
317
+ for (const diff of diffs) {
318
+ if (diff.type === "CHANGE") {
319
+ // Changes must be applied before any other diff, ao so they are ordered first.
320
+ finalDiffSeries.push({ ...diff });
321
+ }
322
+ else {
323
+ nonChangeDiffs.push({ ...diff });
324
+ }
325
+ }
326
+ // Create sets of array diffs grouped by the array they are applying changes to.
327
+ const diffsByArrayUuid = new Map();
328
+ for (const diff of nonChangeDiffs) {
329
+ if (!isDiffOnArray(diff)) {
330
+ continue;
331
+ }
332
+ const arrayUuid = arrayUuidFromPath(diff.path);
333
+ if (diffsByArrayUuid.has(arrayUuid) === false) {
334
+ diffsByArrayUuid.set(arrayUuid, []);
335
+ }
336
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
337
+ diffsByArrayUuid.get(arrayUuid).push(diff);
338
+ }
339
+ const shiftIndexesFromMove = (diff, targetArray, diffAdjustedObjectIndexes, objectId) => {
340
+ const sourceIndex = diff.path[diff.path.length - 1];
341
+ if (diff.newIndex > sourceIndex) {
342
+ // This move diff shifts objects it moved over to the left.
343
+ // |----| |----|
344
+ // e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{2}, {3}, {1}, {4}]
345
+ const minIndex = sourceIndex;
346
+ const maxIndex = diff.newIndex;
347
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
348
+ const shouldIndexBeShifted = id !== objectId && index <= maxIndex && index >= minIndex && index - 1 >= 0;
349
+ if (shouldIndexBeShifted) {
350
+ diffAdjustedObjectIndexes.set(id, index - 1);
351
+ }
352
+ }
353
+ }
354
+ else if (diff.newIndex < sourceIndex) {
355
+ // This move diff shifts objects it moved over to the right.
356
+ // |----| |----|
357
+ // e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{3}, {1}, {2}, {4}]
358
+ const minIndex = diff.newIndex;
359
+ const maxIndex = sourceIndex;
360
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
361
+ const shouldIndexBeShifted = id !== objectId &&
362
+ index <= maxIndex &&
363
+ index >= minIndex &&
364
+ index + 1 <= targetArray.length;
365
+ if (shouldIndexBeShifted) {
366
+ diffAdjustedObjectIndexes.set(id, index + 1);
367
+ }
368
+ }
369
+ }
370
+ };
371
+ const shiftIndexesFromRemove = (diff, diffAdjustedObjectIndexes, objectId) => {
372
+ const removalIndex = diff.path[diff.path.length - 1];
373
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
374
+ const shouldIndexBeShifted = id !== objectId && index > removalIndex && index - 1 >= 0;
375
+ if (shouldIndexBeShifted) {
376
+ diffAdjustedObjectIndexes.set(id, index - 1);
377
+ }
378
+ }
379
+ };
380
+ const diffsMarkedForRemoval = new Set();
381
+ const arrayDiffsMarkedForEndReorder = new Map();
382
+ for (const [arrayUuid, arrayDiffs] of diffsByArrayUuid.entries()) {
383
+ // The prior grouping code ensures that each map value will have atleast 1 diff.
384
+ const targetArray = getTargetObjectFromPath(
385
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
386
+ arrayDiffs[0].path, oldObject);
387
+ const diffAdjustedObjectIndexes = createObjectArrayItemIdsToIndexMap(targetArray, idAttributeName);
388
+ for (const diff of arrayDiffs) {
389
+ if (diff.type === "MOVE") {
390
+ const objectId = diff.value[idAttributeName];
391
+ const sourceIndex = diff.path[diff.path.length - 1];
392
+ // 1. Prior moves may render the next move redundant.
393
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
394
+ const currentAdjustedIndex = diffAdjustedObjectIndexes.get(objectId);
395
+ if (currentAdjustedIndex === diff.newIndex) {
396
+ diffsMarkedForRemoval.add(diff);
397
+ continue;
398
+ }
399
+ if (currentAdjustedIndex !== sourceIndex) {
400
+ // A Prior Remove or Move Diff moved the object to a new index, so update the diff source index to point to the new index.
401
+ diff.path[diff.path.length - 1] = currentAdjustedIndex;
402
+ }
403
+ // Handle index shifts
404
+ diffAdjustedObjectIndexes.set(objectId, diff.newIndex);
405
+ // edge case: this MOVE should be applied after some series of creates that we haven't seen.
406
+ if (diff.newIndex > targetArray.length - 1) {
407
+ // It also wont shift any indexes since its moved to the total end of the array,
408
+ // after creations that produce the necessary indexes.
409
+ if (arrayDiffsMarkedForEndReorder.has(arrayUuid) === false) {
410
+ arrayDiffsMarkedForEndReorder.set(arrayUuid, []);
411
+ }
412
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
413
+ arrayDiffsMarkedForEndReorder.get(arrayUuid).push(diff);
414
+ }
415
+ else {
416
+ shiftIndexesFromMove(diff, targetArray, diffAdjustedObjectIndexes, objectId);
417
+ }
418
+ }
419
+ if (diff.type === "REMOVE") {
420
+ const objectId = diff.oldValue[idAttributeName];
421
+ const targetIndex = diff.path[diff.path.length - 1];
422
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
423
+ const currentDiffAdjustedIndex = diffAdjustedObjectIndexes.get(objectId);
424
+ if (targetIndex !== diffAdjustedObjectIndexes.get(objectId)) {
425
+ // A Prior Remove or Move Diff moved the object to a new index, so update the diff source index to point to the new index.
426
+ diff.path[diff.path.length - 1] = currentDiffAdjustedIndex;
427
+ }
428
+ shiftIndexesFromRemove(diff, diffAdjustedObjectIndexes, objectId);
429
+ }
430
+ // Ignoring 'CREATE' for now.
431
+ }
432
+ }
433
+ for (let i = 0; i < nonChangeDiffs.length; i++) {
434
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
435
+ const diff = nonChangeDiffs[i];
436
+ if (diffsMarkedForRemoval.has(diff)) {
437
+ continue;
438
+ }
439
+ const isLastDiffInArraySeries = (currentIndex) => {
440
+ if (currentIndex === nonChangeDiffs.length - 1) {
441
+ return true;
442
+ }
443
+ const nextIndex = currentIndex + 1;
444
+ if (nextIndex <= nonChangeDiffs.length - 1) {
445
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
446
+ const diffAfter = nonChangeDiffs[nextIndex];
447
+ if (diffsMarkedForRemoval.has(diffAfter)) {
448
+ return isLastDiffInArraySeries(nextIndex + 1);
449
+ }
450
+ const arrayUuidAfter = arrayUuidFromPath(diffAfter.path);
451
+ const arrayUuid = arrayUuidFromPath(diff.path);
452
+ if (arrayUuidAfter === arrayUuid) {
453
+ return false;
454
+ }
455
+ }
456
+ return true;
457
+ };
458
+ if (isDiffOnArray(diff)) {
459
+ const arrayUuid = arrayUuidFromPath(diff.path);
460
+ const endReorderDiffs = arrayDiffsMarkedForEndReorder.get(arrayUuid);
461
+ const isDiffMarkedForReorder = endReorderDiffs?.includes(diff) ?? false;
462
+ if (isDiffMarkedForReorder === false) {
463
+ finalDiffSeries.push(diff);
464
+ }
465
+ if (isLastDiffInArraySeries(i) && endReorderDiffs !== undefined) {
466
+ finalDiffSeries.push(...endReorderDiffs);
467
+ }
468
+ continue;
469
+ }
470
+ finalDiffSeries.push(diff);
471
+ }
472
+ return finalDiffSeries;
473
+ }
474
+ exports.createMergableIdDiffSeries = createMergableIdDiffSeries;
475
+ /**
476
+ * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}
477
+ * that AREN'T using the object ID strategy. These diffs don't need any modifications to be applied to the old object.
478
+ *
479
+ * @alpha
480
+ */
481
+ function createMergableDiffSeries(diffs) {
482
+ // the final series of diffs that will be returned.
483
+ const finalDiffSeries = [];
484
+ // Diffs that aren't of type 'CHANGE'
485
+ const nonChangeDiffs = [];
486
+ for (const diff of diffs) {
487
+ if (diff.type === "CHANGE") {
488
+ // Changes must be applied before any other diff, ao so they are ordered first.
489
+ finalDiffSeries.push({ ...diff });
490
+ }
491
+ else {
492
+ nonChangeDiffs.push({ ...diff });
493
+ }
494
+ }
495
+ finalDiffSeries.push(...nonChangeDiffs);
496
+ return finalDiffSeries;
497
+ }
498
+ exports.createMergableDiffSeries = createMergableDiffSeries;
499
+ /**
500
+ * Creates a UUID for the target array from a {@link Difference}'s ${@link ObjectPath}
501
+ */
502
+ function arrayUuidFromPath(path) {
503
+ return path.length === 1 ? "" : path.slice(0, -1).join("");
504
+ }
505
+ /**
506
+ * Determines if a given difference is on an array.
507
+ */
508
+ function isDiffOnArray(diff) {
509
+ return typeof diff.path[diff.path.length - 1] === "number";
510
+ }
511
+ exports.isDiffOnArray = isDiffOnArray;
512
+ /**
513
+ * Returns the target object that the given diff should be applied to.
514
+ */
515
+ function getTargetObjectFromPath(path, object) {
516
+ let targetObject = object;
517
+ if (path.length > 1) {
518
+ targetObject = (0, utils_js_1.sharedTreeTraverse)(object, path.slice(0, -1));
519
+ }
520
+ return targetObject;
521
+ }
522
+ //# sourceMappingURL=sharedTreeDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sharedTreeDiff.js","sourceRoot":"","sources":["../../src/implicit-strategy/sharedTreeDiff.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { type TreeArrayNode, NodeKind } from \"@fluidframework/tree\";\n\nimport { isTreeMapNode, sharedTreeTraverse } from \"./utils.js\";\n\n/**\n * Represents a path through a tree of objects.\n * number values represent array indices whereas string values represent object keys.\n *\n * @alpha\n */\nexport type ObjectPath = (string | number)[];\n\n/**\n * Represents a create operation between two branches of a tree.\n * Meaning that an attribute (a shared tree node) was identified as being created.\n *\n * @alpha\n */\nexport interface DifferenceCreate {\n\ttype: \"CREATE\";\n\tpath: ObjectPath;\n\tvalue: unknown;\n}\n\n/**\n * Represents a remove operation between two branches of a tree.\n * Meaning that an attribute (a shared tree node) was identified as being deleted.\n * When using object ids, removes are idenitified by an object with a given id no longer existing.\n *\n * @alpha\n */\nexport interface DifferenceRemove {\n\ttype: \"REMOVE\";\n\tpath: ObjectPath;\n\toldValue: unknown;\n\tobjectId?: string | number | undefined;\n}\n\n/**\n * Represents a change operation between two branches of a tree.\n * Meaning that an attribute (a shared tree node) was identified as being changed from one value to another.\n *\n * @alpha\n */\nexport interface DifferenceChange {\n\ttype: \"CHANGE\";\n\tpath: ObjectPath;\n\tvalue: unknown;\n\toldValue: unknown;\n\tobjectId?: string | number | undefined;\n}\n\n/**\n * Represents a move operation between two branches of a tree.\n * Meaning that an object (shared tree node) was identified as being moved from one index to another based on its unique id.\n *\n * @alpha\n */\nexport interface DifferenceMove {\n\ttype: \"MOVE\";\n\tpath: ObjectPath;\n\tnewIndex: number;\n\tvalue: unknown;\n\tobjectId?: string | number | undefined;\n}\n\n/**\n * Union for all possible difference types.\n *\n * @alpha\n */\nexport type Difference =\n\t| DifferenceCreate\n\t| DifferenceRemove\n\t| DifferenceChange\n\t| DifferenceMove;\n\n/**\n * Options for tree diffing.\n * @alpha\n */\nexport interface Options {\n\tcyclesFix: boolean;\n\tuseObjectIds?:\n\t\t| {\n\t\t\t\tidAttributeName: string;\n\t\t }\n\t\t| undefined;\n}\n\nconst richTypes = { Date: true, RegExp: true, String: true, Number: true };\n\n/**\n * By default, Object Diff supports cyclical references, but if you are sure that the object has no cycles like parsed JSON\n * you can disable cycles by setting the cyclesFix option to false\n */\nconst DEFAULT_OPTIONS: Options = { cyclesFix: true };\n\n/**\n * Compares two objects and returns an array of differences between them.\n *\n * @alpha\n */\nexport function sharedTreeDiff(\n\tobj: Record<string, unknown> | unknown[],\n\tnewObj: Record<string, unknown> | unknown[],\n\toptions: Options = DEFAULT_OPTIONS,\n\t_stack: (Record<string, unknown> | unknown[])[] = [],\n): Difference[] {\n\tconst diffs: Difference[] = [];\n\tconst isObjArray = isArrayOrTreeArrayNode(obj);\n\tconst isNewObjArray = isArrayOrTreeArrayNode(newObj);\n\n\t// If useObjectIds is set, we'll create a map of object ids to their index in the array.\n\tconst oldObjArrayItemIdsToIndex =\n\t\tisObjArray === false || options.useObjectIds === undefined\n\t\t\t? new Map<string | number, number>()\n\t\t\t: createObjectArrayItemIdsToIndexMap(obj, options.useObjectIds.idAttributeName);\n\n\tconst newObjArrayItemIdsToIndex =\n\t\tisNewObjArray === false || options.useObjectIds === undefined\n\t\t\t? new Map<string | number, number>()\n\t\t\t: createObjectArrayItemIdsToIndexMap(newObj, options.useObjectIds.idAttributeName);\n\n\tconst objectKeys = isTreeMapNode(obj) ? obj.keys() : Object.keys(obj);\n\t// We compare existence and values of all attributes within the old against new object, looking for removals or changes.\n\tfor (const key of objectKeys) {\n\t\tconst objValue: unknown = isTreeMapNode(obj) ? obj.get(key as string) : obj[key];\n\t\tconst path = isObjArray ? +key : key;\n\t\t// 1. First, check if the key within the old object, exists within the new object. If it doesn't exist this would be an attribute removal.\n\t\tif (!(key in newObj)) {\n\t\t\tif (options.useObjectIds === undefined) {\n\t\t\t\tdiffs.push({\n\t\t\t\t\ttype: \"REMOVE\",\n\t\t\t\t\tpath: [path],\n\t\t\t\t\tobjectId: undefined,\n\t\t\t\t\toldValue: objValue,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// If we're dealing with an object in an array, we can use the object's id to check if it was moved to a new index.\n\t\t\telse if (\n\t\t\t\tisNewObjArray === true &&\n\t\t\t\tisObjArray &&\n\t\t\t\ttypeof objValue === \"object\" &&\n\t\t\t\tobjValue !== null\n\t\t\t) {\n\t\t\t\tconst objectId = objValue[options.useObjectIds.idAttributeName] as\n\t\t\t\t\t| string\n\t\t\t\t\t| number\n\t\t\t\t\t| undefined;\n\t\t\t\tif (objectId !== undefined && newObjArrayItemIdsToIndex.has(objectId)) {\n\t\t\t\t\t// The index no longer exists in the new root object array, however the object that lived at this index actually still exists at a new index.\n\t\t\t\t\t// Therefore, this node was moved to a new index.\n\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\ttype: \"MOVE\",\n\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\tnewIndex: newObjArrayItemIdsToIndex.get(objectId) as number,\n\t\t\t\t\t\tvalue: objValue,\n\t\t\t\t\t\tobjectId,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// The object with the given id cannot be found within the new array, therefore it was removed.\n\t\t\t\telse {\n\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\ttype: \"REMOVE\",\n\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\tobjectId,\n\t\t\t\t\t\toldValue: objValue,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we're not dealing with an object in an array, we can't use id's to check for a move.\n\t\t\t// We'll assume that a missing key in the new object means that the cooresponding value was removed.\n\t\t\telse {\n\t\t\t\tdiffs.push({\n\t\t\t\t\ttype: \"REMOVE\",\n\t\t\t\t\tpath: [path],\n\t\t\t\t\tobjectId: undefined,\n\t\t\t\t\toldValue: objValue,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\n\t\tconst newObjValue: unknown = newObj[key];\n\t\tconst areCompatibleObjects =\n\t\t\ttypeof objValue === \"object\" &&\n\t\t\ttypeof newObjValue === \"object\" &&\n\t\t\tisArrayOrTreeArrayNode(objValue) === isArrayOrTreeArrayNode(newObjValue);\n\n\t\t// 2a. If the given old object key exists in the new object, and the value of said key in both objects is ANOTHER nested object, we need to run a recursive diff check on them.\n\t\tif (\n\t\t\tobjValue !== null &&\n\t\t\tnewObjValue !== null &&\n\t\t\tareCompatibleObjects &&\n\t\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/no-unsafe-member-access\n\t\t\t!richTypes[Object.getPrototypeOf(objValue)?.constructor?.name] &&\n\t\t\t(!options.cyclesFix || !_stack.includes(objValue as Record<string, unknown>))\n\t\t) {\n\t\t\tif (options.useObjectIds === undefined) {\n\t\t\t\tconst nestedDiffs = sharedTreeDiff(\n\t\t\t\t\tobjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\tnewObjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\toptions,\n\t\t\t\t\toptions.cyclesFix === true\n\t\t\t\t\t\t? [..._stack, objValue as Record<string, unknown> | unknown[]]\n\t\t\t\t\t\t: [],\n\t\t\t\t);\n\t\t\t\t// eslint-disable-next-line prefer-spread\n\t\t\t\tdiffs.push.apply(\n\t\t\t\t\tdiffs,\n\t\t\t\t\tnestedDiffs.map((difference) => {\n\t\t\t\t\t\tdifference.path.unshift(path);\n\t\t\t\t\t\treturn difference;\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Use Object Id strategy to determine if the objects should be compared for changes\n\t\t\telse {\n\t\t\t\tconst oldObjectId = (objValue as Record<string, unknown>)[\n\t\t\t\t\toptions.useObjectIds.idAttributeName\n\t\t\t\t] as string | number | undefined;\n\t\t\t\tconst newObjectId = (newObjValue as Record<string, unknown>)[\n\t\t\t\t\toptions.useObjectIds.idAttributeName\n\t\t\t\t] as string | number | undefined;\n\n\t\t\t\tif (oldObjectId !== undefined && newObjectId !== undefined) {\n\t\t\t\t\t// 2a.1 if the object id's are the same, we can continue a comparison between the two objects.\n\t\t\t\t\tif (oldObjectId === newObjectId) {\n\t\t\t\t\t\tconst nestedDiffs = sharedTreeDiff(\n\t\t\t\t\t\t\tobjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\t\t\tnewObjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\t\t\toptions,\n\t\t\t\t\t\t\toptions.cyclesFix === true\n\t\t\t\t\t\t\t\t? [..._stack, objValue as Record<string, unknown> | unknown[]]\n\t\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\t);\n\t\t\t\t\t\tdiffs.push(\n\t\t\t\t\t\t\t...nestedDiffs.map((difference) => {\n\t\t\t\t\t\t\t\tdifference.path.unshift(path);\n\t\t\t\t\t\t\t\treturn difference;\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// 2a.2 The object id's are different, their attributes cannot be compared.\n\t\t\t\t\t// We need to find the new index of the object, if it exists in the new array and do a diff comparison.\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst newIndexOfOldObject = newObjArrayItemIdsToIndex.get(oldObjectId);\n\t\t\t\t\t\t// The object no longer exists in the new array, therefore it was removed.\n\t\t\t\t\t\tif (newIndexOfOldObject === undefined) {\n\t\t\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\t\t\ttype: \"REMOVE\",\n\t\t\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\t\t\toldValue: objValue,\n\t\t\t\t\t\t\t\tobjectId: oldObjectId,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// This object still exists but at a new index within the new array therefore it was moved.\n\t\t\t\t\t\t// At this point we can determine whether a new move is necessary or there is one that will place it at the desired index.\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\t\t\ttype: \"MOVE\",\n\t\t\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\t\t\tnewIndex: newIndexOfOldObject,\n\t\t\t\t\t\t\t\tvalue: objValue,\n\t\t\t\t\t\t\t\tobjectId: oldObjectId,\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t// An object could have been moved AND changed. We need to check for this.\n\t\t\t\t\t\t\tconst nestedDiffs = sharedTreeDiff(\n\t\t\t\t\t\t\t\tobj[path] as Record<string, unknown> | unknown[],\n\t\t\t\t\t\t\t\tnewObj[newIndexOfOldObject] as Record<string, unknown> | unknown[],\n\t\t\t\t\t\t\t\toptions,\n\t\t\t\t\t\t\t\toptions.cyclesFix === true\n\t\t\t\t\t\t\t\t\t? [..._stack, objValue as Record<string, unknown> | unknown[]]\n\t\t\t\t\t\t\t\t\t: [],\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tdiffs.push(\n\t\t\t\t\t\t\t\t...nestedDiffs.map((difference) => {\n\t\t\t\t\t\t\t\t\tdifference.path.unshift(path);\n\t\t\t\t\t\t\t\t\treturn difference;\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconst nestedDiffs = sharedTreeDiff(\n\t\t\t\t\t\tobjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\t\tnewObjValue as Record<string, unknown> | unknown[],\n\t\t\t\t\t\toptions,\n\t\t\t\t\t\toptions.cyclesFix === true\n\t\t\t\t\t\t\t? [..._stack, objValue as Record<string, unknown> | unknown[]]\n\t\t\t\t\t\t\t: [],\n\t\t\t\t\t);\n\t\t\t\t\tdiffs.push(\n\t\t\t\t\t\t...nestedDiffs.map((difference) => {\n\t\t\t\t\t\t\tdifference.path.unshift(path);\n\t\t\t\t\t\t\treturn difference;\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// 2b. If the given old object key exists in the new object, and the value of said key in both objects is NOT another nested object, we need to check if the values are the same.\n\t\telse if (\n\t\t\tobjValue !== newObjValue &&\n\t\t\t// treat NaN values as equivalent\n\t\t\t!(Number.isNaN(objValue) && Number.isNaN(newObjValue)) &&\n\t\t\t!(\n\t\t\t\tareCompatibleObjects &&\n\t\t\t\t(Number.isNaN(objValue)\n\t\t\t\t\t? // eslint-disable-next-line prefer-template\n\t\t\t\t\t\tobjValue + \"\" === newObjValue + \"\"\n\t\t\t\t\t: // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n\t\t\t\t\t\t// @ts-ignore\n\t\t\t\t\t\t+objValue === +newObjValue)\n\t\t\t)\n\t\t) {\n\t\t\tdiffs.push({\n\t\t\t\tpath: [path],\n\t\t\t\ttype: \"CHANGE\",\n\t\t\t\tvalue: newObjValue,\n\t\t\t\toldValue: objValue,\n\t\t\t\tobjectId:\n\t\t\t\t\toptions.useObjectIds?.idAttributeName === undefined\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (newObj[options.useObjectIds.idAttributeName] as string | number | undefined),\n\t\t\t});\n\t\t}\n\t}\n\n\t// 3. Finally, we check for new keys in the new object that did not exist in the old object.\n\t// The existence of new keys may signal new values or moved values.\n\tconst newObjKeys = isTreeMapNode(newObj) ? newObj.keys() : Object.keys(newObj);\n\tfor (const key of newObjKeys) {\n\t\tconst newObjValue: unknown = isTreeMapNode(newObj)\n\t\t\t? newObj.get(key as string)\n\t\t\t: newObj[key];\n\t\tconst path = isNewObjArray ? +key : key;\n\n\t\tconst isKeyInOldObject = isTreeMapNode(obj)\n\t\t\t? obj.has(key as string)\n\t\t\t: Object.keys(obj).includes(key as string);\n\t\tif (!isKeyInOldObject) {\n\t\t\tif (options.useObjectIds === undefined) {\n\t\t\t\tdiffs.push({\n\t\t\t\t\ttype: \"CREATE\",\n\t\t\t\t\tpath: [path],\n\t\t\t\t\tvalue: newObjValue,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// If we're dealing with an object in an array, we can use the object's id to check if this new index actually\n\t\t\t// contains a prexisting object that was moved from an old index.\n\t\t\telse if (\n\t\t\t\tisObjArray === true &&\n\t\t\t\tisNewObjArray === true &&\n\t\t\t\ttypeof newObjValue === \"object\" &&\n\t\t\t\tnewObjValue !== null\n\t\t\t) {\n\t\t\t\tconst objectId = newObjValue[options.useObjectIds.idAttributeName] as\n\t\t\t\t\t| string\n\t\t\t\t\t| number\n\t\t\t\t\t| undefined;\n\t\t\t\tif (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId)) {\n\t\t\t\t\t// The new root object array contains a new index, however the object that lives at this new index previously existed at an old index.\n\t\t\t\t\t// Therefore, this object was moved to a new index.\n\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\ttype: \"MOVE\",\n\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\tnewIndex: newObjArrayItemIdsToIndex.get(objectId) as number,\n\t\t\t\t\t\tvalue: newObjValue,\n\t\t\t\t\t\tobjectId,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// If either the object's id attribute does not exist or the original array does not contain an object with the given id\n\t\t\t\t// Then we assume this was a newly created object.\n\t\t\t\telse {\n\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\ttype: \"CREATE\",\n\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\tvalue: newObjValue,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If we're not dealing with an object in an array, we can't use id's to check for a move.\n\t\t\t// We'll assume that a brand new key and value pair in the new object means that a new value was created.\n\t\t\telse {\n\t\t\t\tdiffs.push({\n\t\t\t\t\ttype: \"CREATE\",\n\t\t\t\t\tpath: [path],\n\t\t\t\t\tvalue: newObjValue,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (options.useObjectIds !== undefined) {\n\t\t\t// If we're dealing with an object in an array, we can use the object's id to check if this EXISTING index\n\t\t\t// houses a new object based on a newly encountered id.\n\t\t\tif (\n\t\t\t\tisObjArray === true &&\n\t\t\t\tisNewObjArray === true &&\n\t\t\t\ttypeof newObjValue === \"object\" &&\n\t\t\t\tnewObjValue !== null\n\t\t\t) {\n\t\t\t\tconst objectId = newObjValue[options.useObjectIds.idAttributeName] as\n\t\t\t\t\t| string\n\t\t\t\t\t| number\n\t\t\t\t\t| undefined;\n\t\t\t\t// If this object has an id and it does not exist in the old array, then it was created.\n\t\t\t\tif (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId) === false) {\n\t\t\t\t\tdiffs.push({\n\t\t\t\t\t\ttype: \"CREATE\",\n\t\t\t\t\t\tpath: [path],\n\t\t\t\t\t\tvalue: newObjValue,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t}\n\treturn diffs;\n}\n\n/**\n * Type Guard that determines if a given object is an array of type unknown[] or {@link TreeArrayNode}.\n */\nfunction isArrayOrTreeArrayNode(obj: unknown): obj is unknown[] | TreeArrayNode {\n\tif (typeof obj === \"object\" && obj !== null) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n\t\tconst maybeNodeKind: unknown = Object.getPrototypeOf(obj)?.constructor?.kind;\n\t\tconst isTreeArrayNode = maybeNodeKind === NodeKind.Array;\n\t\treturn Array.isArray(obj) || isTreeArrayNode;\n\t}\n\treturn false;\n}\n\n/**\n * Helper that creates a map of object ids to their index in an array of objects.\n */\nfunction createObjectArrayItemIdsToIndexMap(\n\tobj: unknown[],\n\tidAttributeName: string | number,\n): Map<string | number, number> {\n\tconst objArrayItemIdsToIndex = new Map<string | number, number>();\n\tfor (let i = 0; i < obj.length; i++) {\n\t\tconst objArrayItem = obj[i];\n\t\tif (typeof objArrayItem === \"object\" && objArrayItem !== null) {\n\t\t\tconst id = (objArrayItem as Record<string, unknown>)[idAttributeName] as string | number;\n\t\t\tif (objArrayItemIdsToIndex.has(id)) {\n\t\t\t\tthrow new TypeError(`Duplicate object id found: ${id}`);\n\t\t\t} else if (id !== undefined) {\n\t\t\t\tobjArrayItemIdsToIndex.set(id, i);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn objArrayItemIdsToIndex;\n}\n\n/**\n * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}\n * that are using the object ID strategy. These diffs don't need any modifications to be applied to the old object.\n *\n * @alpha\n */\nexport function createMergableIdDiffSeries(\n\toldObject: unknown,\n\tdiffs: Difference[],\n\tidAttributeName: string | number,\n): Difference[] {\n\t// the final series of diffs that will be returned.\n\tconst finalDiffSeries: Difference[] = [];\n\t// Diffs that aren't of type 'CHANGE'\n\tconst nonChangeDiffs: Difference[] = [];\n\n\tfor (const diff of diffs) {\n\t\tif (diff.type === \"CHANGE\") {\n\t\t\t// Changes must be applied before any other diff, ao so they are ordered first.\n\t\t\tfinalDiffSeries.push({ ...diff });\n\t\t} else {\n\t\t\tnonChangeDiffs.push({ ...diff });\n\t\t}\n\t}\n\n\t// Create sets of array diffs grouped by the array they are applying changes to.\n\tconst diffsByArrayUuid = new Map<string, Difference[]>();\n\tfor (const diff of nonChangeDiffs) {\n\t\tif (!isDiffOnArray(diff)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst arrayUuid = arrayUuidFromPath(diff.path);\n\n\t\tif (diffsByArrayUuid.has(arrayUuid) === false) {\n\t\t\tdiffsByArrayUuid.set(arrayUuid, []);\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tdiffsByArrayUuid.get(arrayUuid)!.push(diff);\n\t}\n\n\tconst shiftIndexesFromMove = (\n\t\tdiff: DifferenceMove,\n\t\ttargetArray: unknown[],\n\t\tdiffAdjustedObjectIndexes: Map<string | number, number>,\n\t\tobjectId: string | number,\n\t): void => {\n\t\tconst sourceIndex = diff.path[diff.path.length - 1] as number;\n\n\t\tif (diff.newIndex > sourceIndex) {\n\t\t\t// This move diff shifts objects it moved over to the left.\n\t\t\t// |----| |----|\n\t\t\t// e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{2}, {3}, {1}, {4}]\n\t\t\tconst minIndex = sourceIndex;\n\t\t\tconst maxIndex = diff.newIndex;\n\t\t\tfor (const [id, index] of diffAdjustedObjectIndexes.entries()) {\n\t\t\t\tconst shouldIndexBeShifted =\n\t\t\t\t\tid !== objectId && index <= maxIndex && index >= minIndex && index - 1 >= 0;\n\t\t\t\tif (shouldIndexBeShifted) {\n\t\t\t\t\tdiffAdjustedObjectIndexes.set(id, index - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (diff.newIndex < sourceIndex) {\n\t\t\t// This move diff shifts objects it moved over to the right.\n\t\t\t// |----| |----|\n\t\t\t// e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{3}, {1}, {2}, {4}]\n\t\t\tconst minIndex = diff.newIndex;\n\t\t\tconst maxIndex = sourceIndex;\n\t\t\tfor (const [id, index] of diffAdjustedObjectIndexes.entries()) {\n\t\t\t\tconst shouldIndexBeShifted =\n\t\t\t\t\tid !== objectId &&\n\t\t\t\t\tindex <= maxIndex &&\n\t\t\t\t\tindex >= minIndex &&\n\t\t\t\t\tindex + 1 <= targetArray.length;\n\t\t\t\tif (shouldIndexBeShifted) {\n\t\t\t\t\tdiffAdjustedObjectIndexes.set(id, index + 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tconst shiftIndexesFromRemove = (\n\t\tdiff: DifferenceRemove,\n\t\tdiffAdjustedObjectIndexes: Map<string | number, number>,\n\t\tobjectId: string | number,\n\t): void => {\n\t\tconst removalIndex = diff.path[diff.path.length - 1] as number;\n\t\tfor (const [id, index] of diffAdjustedObjectIndexes.entries()) {\n\t\t\tconst shouldIndexBeShifted = id !== objectId && index > removalIndex && index - 1 >= 0;\n\t\t\tif (shouldIndexBeShifted) {\n\t\t\t\tdiffAdjustedObjectIndexes.set(id, index - 1);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst diffsMarkedForRemoval = new Set<Difference>();\n\tconst arrayDiffsMarkedForEndReorder = new Map<string, Difference[]>();\n\n\tfor (const [arrayUuid, arrayDiffs] of diffsByArrayUuid.entries()) {\n\t\t// The prior grouping code ensures that each map value will have atleast 1 diff.\n\t\tconst targetArray = getTargetObjectFromPath(\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tarrayDiffs[0]!.path,\n\t\t\toldObject as TreeArrayNode,\n\t\t) as unknown[];\n\t\tconst diffAdjustedObjectIndexes: Map<string | number, number> =\n\t\t\tcreateObjectArrayItemIdsToIndexMap(targetArray, idAttributeName);\n\n\t\tfor (const diff of arrayDiffs) {\n\t\t\tif (diff.type === \"MOVE\") {\n\t\t\t\tconst objectId = (diff.value as Record<string, unknown>)[idAttributeName] as\n\t\t\t\t\t| string\n\t\t\t\t\t| number;\n\t\t\t\tconst sourceIndex = diff.path[diff.path.length - 1] as number;\n\n\t\t\t\t// 1. Prior moves may render the next move redundant.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst currentAdjustedIndex = diffAdjustedObjectIndexes.get(objectId)!;\n\t\t\t\tif (currentAdjustedIndex === diff.newIndex) {\n\t\t\t\t\tdiffsMarkedForRemoval.add(diff);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (currentAdjustedIndex !== sourceIndex) {\n\t\t\t\t\t// A Prior Remove or Move Diff moved the object to a new index, so update the diff source index to point to the new index.\n\t\t\t\t\tdiff.path[diff.path.length - 1] = currentAdjustedIndex;\n\t\t\t\t}\n\n\t\t\t\t// Handle index shifts\n\t\t\t\tdiffAdjustedObjectIndexes.set(objectId, diff.newIndex);\n\n\t\t\t\t// edge case: this MOVE should be applied after some series of creates that we haven't seen.\n\t\t\t\tif (diff.newIndex > targetArray.length - 1) {\n\t\t\t\t\t// It also wont shift any indexes since its moved to the total end of the array,\n\t\t\t\t\t// after creations that produce the necessary indexes.\n\t\t\t\t\tif (arrayDiffsMarkedForEndReorder.has(arrayUuid) === false) {\n\t\t\t\t\t\tarrayDiffsMarkedForEndReorder.set(arrayUuid, []);\n\t\t\t\t\t}\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tarrayDiffsMarkedForEndReorder.get(arrayUuid)!.push(diff);\n\t\t\t\t} else {\n\t\t\t\t\tshiftIndexesFromMove(diff, targetArray, diffAdjustedObjectIndexes, objectId);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (diff.type === \"REMOVE\") {\n\t\t\t\tconst objectId = (diff.oldValue as Record<string, unknown>)[idAttributeName] as\n\t\t\t\t\t| string\n\t\t\t\t\t| number;\n\t\t\t\tconst targetIndex = diff.path[diff.path.length - 1] as number;\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst currentDiffAdjustedIndex = diffAdjustedObjectIndexes.get(objectId)!;\n\t\t\t\tif (targetIndex !== diffAdjustedObjectIndexes.get(objectId)) {\n\t\t\t\t\t// A Prior Remove or Move Diff moved the object to a new index, so update the diff source index to point to the new index.\n\t\t\t\t\tdiff.path[diff.path.length - 1] = currentDiffAdjustedIndex;\n\t\t\t\t}\n\n\t\t\t\tshiftIndexesFromRemove(diff, diffAdjustedObjectIndexes, objectId);\n\t\t\t}\n\n\t\t\t// Ignoring 'CREATE' for now.\n\t\t}\n\t}\n\n\tfor (let i = 0; i < nonChangeDiffs.length; i++) {\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst diff = nonChangeDiffs[i]!;\n\n\t\tif (diffsMarkedForRemoval.has(diff)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst isLastDiffInArraySeries = (currentIndex: number): boolean => {\n\t\t\tif (currentIndex === nonChangeDiffs.length - 1) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tconst nextIndex = currentIndex + 1;\n\t\t\tif (nextIndex <= nonChangeDiffs.length - 1) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tconst diffAfter = nonChangeDiffs[nextIndex]!;\n\n\t\t\t\tif (diffsMarkedForRemoval.has(diffAfter)) {\n\t\t\t\t\treturn isLastDiffInArraySeries(nextIndex + 1);\n\t\t\t\t}\n\n\t\t\t\tconst arrayUuidAfter = arrayUuidFromPath(diffAfter.path);\n\t\t\t\tconst arrayUuid = arrayUuidFromPath(diff.path);\n\t\t\t\tif (arrayUuidAfter === arrayUuid) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tif (isDiffOnArray(diff)) {\n\t\t\tconst arrayUuid = arrayUuidFromPath(diff.path);\n\t\t\tconst endReorderDiffs = arrayDiffsMarkedForEndReorder.get(arrayUuid);\n\t\t\tconst isDiffMarkedForReorder = endReorderDiffs?.includes(diff) ?? false;\n\n\t\t\tif (isDiffMarkedForReorder === false) {\n\t\t\t\tfinalDiffSeries.push(diff);\n\t\t\t}\n\n\t\t\tif (isLastDiffInArraySeries(i) && endReorderDiffs !== undefined) {\n\t\t\t\tfinalDiffSeries.push(...endReorderDiffs);\n\t\t\t}\n\n\t\t\tcontinue;\n\t\t}\n\n\t\tfinalDiffSeries.push(diff);\n\t}\n\n\treturn finalDiffSeries;\n}\n\n/**\n * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}\n * that AREN'T using the object ID strategy. These diffs don't need any modifications to be applied to the old object.\n *\n * @alpha\n */\nexport function createMergableDiffSeries(diffs: Difference[]): Difference[] {\n\t// the final series of diffs that will be returned.\n\tconst finalDiffSeries: Difference[] = [];\n\t// Diffs that aren't of type 'CHANGE'\n\tconst nonChangeDiffs: Difference[] = [];\n\n\tfor (const diff of diffs) {\n\t\tif (diff.type === \"CHANGE\") {\n\t\t\t// Changes must be applied before any other diff, ao so they are ordered first.\n\t\t\tfinalDiffSeries.push({ ...diff });\n\t\t} else {\n\t\t\tnonChangeDiffs.push({ ...diff });\n\t\t}\n\t}\n\n\tfinalDiffSeries.push(...nonChangeDiffs);\n\n\treturn finalDiffSeries;\n}\n\n/**\n * Creates a UUID for the target array from a {@link Difference}'s ${@link ObjectPath}\n */\nfunction arrayUuidFromPath(path: ObjectPath): string {\n\treturn path.length === 1 ? \"\" : path.slice(0, -1).join(\"\");\n}\n\n/**\n * Determines if a given difference is on an array.\n */\nexport function isDiffOnArray(diff: Difference): boolean {\n\treturn typeof diff.path[diff.path.length - 1] === \"number\";\n}\n\n/**\n * Returns the target object that the given diff should be applied to.\n */\nfunction getTargetObjectFromPath(\n\tpath: ObjectPath,\n\tobject: Record<string, unknown> | TreeArrayNode,\n): unknown {\n\tlet targetObject: unknown = object;\n\tif (path.length > 1) {\n\t\ttargetObject = sharedTreeTraverse(object, path.slice(0, -1));\n\t}\n\treturn targetObject;\n}\n"]}
@@ -0,0 +1,21 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { type TreeMapNode, type TreeArrayNode } from "@fluidframework/tree";
6
+ import type { ObjectPath } from "./sharedTreeDiff.js";
7
+ /**
8
+ * Checks if the given object is an {@link TreeMapNode}.
9
+ */
10
+ export declare function isTreeMapNode(obj: unknown): obj is TreeMapNode;
11
+ /**
12
+ * Checks if the given object is an {@link TreeArrayNode}.
13
+ */
14
+ export declare function isTreeArrayNode(obj: unknown): obj is TreeArrayNode;
15
+ /**
16
+ * Traverses the provided {@link ObjectPath} on the provided Shared Tree or JSON object and returns the value at the end of the path.
17
+ *
18
+ * @alpha
19
+ */
20
+ export declare function sharedTreeTraverse<T = unknown>(jsonObject: TreeMapNode | TreeArrayNode | Record<string, unknown>, path: ObjectPath): T | undefined;
21
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/implicit-strategy/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,aAAa,EAAY,MAAM,sBAAsB,CAAC;AAEtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,WAAW,CAO9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,aAAa,CAOlE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAC7C,UAAU,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,IAAI,EAAE,UAAU,GACd,CAAC,GAAG,SAAS,CAYf"}