@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,515 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { NodeKind } from "@fluidframework/tree";
6
+ import { isTreeMapNode, sharedTreeTraverse } from "./utils.js";
7
+ const richTypes = { Date: true, RegExp: true, String: true, Number: true };
8
+ /**
9
+ * By default, Object Diff supports cyclical references, but if you are sure that the object has no cycles like parsed JSON
10
+ * you can disable cycles by setting the cyclesFix option to false
11
+ */
12
+ const DEFAULT_OPTIONS = { cyclesFix: true };
13
+ /**
14
+ * Compares two objects and returns an array of differences between them.
15
+ *
16
+ * @alpha
17
+ */
18
+ export function sharedTreeDiff(obj, newObj, options = DEFAULT_OPTIONS, _stack = []) {
19
+ const diffs = [];
20
+ const isObjArray = isArrayOrTreeArrayNode(obj);
21
+ const isNewObjArray = isArrayOrTreeArrayNode(newObj);
22
+ // If useObjectIds is set, we'll create a map of object ids to their index in the array.
23
+ const oldObjArrayItemIdsToIndex = isObjArray === false || options.useObjectIds === undefined
24
+ ? new Map()
25
+ : createObjectArrayItemIdsToIndexMap(obj, options.useObjectIds.idAttributeName);
26
+ const newObjArrayItemIdsToIndex = isNewObjArray === false || options.useObjectIds === undefined
27
+ ? new Map()
28
+ : createObjectArrayItemIdsToIndexMap(newObj, options.useObjectIds.idAttributeName);
29
+ const objectKeys = isTreeMapNode(obj) ? obj.keys() : Object.keys(obj);
30
+ // We compare existence and values of all attributes within the old against new object, looking for removals or changes.
31
+ for (const key of objectKeys) {
32
+ const objValue = isTreeMapNode(obj) ? obj.get(key) : obj[key];
33
+ const path = isObjArray ? +key : key;
34
+ // 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.
35
+ if (!(key in newObj)) {
36
+ if (options.useObjectIds === undefined) {
37
+ diffs.push({
38
+ type: "REMOVE",
39
+ path: [path],
40
+ objectId: undefined,
41
+ oldValue: objValue,
42
+ });
43
+ continue;
44
+ }
45
+ // 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.
46
+ else if (isNewObjArray === true &&
47
+ isObjArray &&
48
+ typeof objValue === "object" &&
49
+ objValue !== null) {
50
+ const objectId = objValue[options.useObjectIds.idAttributeName];
51
+ if (objectId !== undefined && newObjArrayItemIdsToIndex.has(objectId)) {
52
+ // 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.
53
+ // Therefore, this node was moved to a new index.
54
+ diffs.push({
55
+ type: "MOVE",
56
+ path: [path],
57
+ newIndex: newObjArrayItemIdsToIndex.get(objectId),
58
+ value: objValue,
59
+ objectId,
60
+ });
61
+ continue;
62
+ }
63
+ // The object with the given id cannot be found within the new array, therefore it was removed.
64
+ else {
65
+ diffs.push({
66
+ type: "REMOVE",
67
+ path: [path],
68
+ objectId,
69
+ oldValue: objValue,
70
+ });
71
+ continue;
72
+ }
73
+ }
74
+ // If we're not dealing with an object in an array, we can't use id's to check for a move.
75
+ // We'll assume that a missing key in the new object means that the cooresponding value was removed.
76
+ else {
77
+ diffs.push({
78
+ type: "REMOVE",
79
+ path: [path],
80
+ objectId: undefined,
81
+ oldValue: objValue,
82
+ });
83
+ continue;
84
+ }
85
+ }
86
+ const newObjValue = newObj[key];
87
+ const areCompatibleObjects = typeof objValue === "object" &&
88
+ typeof newObjValue === "object" &&
89
+ isArrayOrTreeArrayNode(objValue) === isArrayOrTreeArrayNode(newObjValue);
90
+ // 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.
91
+ if (objValue !== null &&
92
+ newObjValue !== null &&
93
+ areCompatibleObjects &&
94
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/no-unsafe-member-access
95
+ !richTypes[Object.getPrototypeOf(objValue)?.constructor?.name] &&
96
+ (!options.cyclesFix || !_stack.includes(objValue))) {
97
+ if (options.useObjectIds === undefined) {
98
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
99
+ ? [..._stack, objValue]
100
+ : []);
101
+ // eslint-disable-next-line prefer-spread
102
+ diffs.push.apply(diffs, nestedDiffs.map((difference) => {
103
+ difference.path.unshift(path);
104
+ return difference;
105
+ }));
106
+ }
107
+ // Use Object Id strategy to determine if the objects should be compared for changes
108
+ else {
109
+ const oldObjectId = objValue[options.useObjectIds.idAttributeName];
110
+ const newObjectId = newObjValue[options.useObjectIds.idAttributeName];
111
+ if (oldObjectId !== undefined && newObjectId !== undefined) {
112
+ // 2a.1 if the object id's are the same, we can continue a comparison between the two objects.
113
+ if (oldObjectId === newObjectId) {
114
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
115
+ ? [..._stack, objValue]
116
+ : []);
117
+ diffs.push(...nestedDiffs.map((difference) => {
118
+ difference.path.unshift(path);
119
+ return difference;
120
+ }));
121
+ }
122
+ // 2a.2 The object id's are different, their attributes cannot be compared.
123
+ // We need to find the new index of the object, if it exists in the new array and do a diff comparison.
124
+ else {
125
+ const newIndexOfOldObject = newObjArrayItemIdsToIndex.get(oldObjectId);
126
+ // The object no longer exists in the new array, therefore it was removed.
127
+ if (newIndexOfOldObject === undefined) {
128
+ diffs.push({
129
+ type: "REMOVE",
130
+ path: [path],
131
+ oldValue: objValue,
132
+ objectId: oldObjectId,
133
+ });
134
+ }
135
+ // This object still exists but at a new index within the new array therefore it was moved.
136
+ // At this point we can determine whether a new move is necessary or there is one that will place it at the desired index.
137
+ else {
138
+ diffs.push({
139
+ type: "MOVE",
140
+ path: [path],
141
+ newIndex: newIndexOfOldObject,
142
+ value: objValue,
143
+ objectId: oldObjectId,
144
+ });
145
+ // An object could have been moved AND changed. We need to check for this.
146
+ const nestedDiffs = sharedTreeDiff(obj[path], newObj[newIndexOfOldObject], options, options.cyclesFix === true
147
+ ? [..._stack, objValue]
148
+ : []);
149
+ diffs.push(...nestedDiffs.map((difference) => {
150
+ difference.path.unshift(path);
151
+ return difference;
152
+ }));
153
+ }
154
+ }
155
+ }
156
+ else {
157
+ const nestedDiffs = sharedTreeDiff(objValue, newObjValue, options, options.cyclesFix === true
158
+ ? [..._stack, objValue]
159
+ : []);
160
+ diffs.push(...nestedDiffs.map((difference) => {
161
+ difference.path.unshift(path);
162
+ return difference;
163
+ }));
164
+ }
165
+ }
166
+ }
167
+ // 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.
168
+ else if (objValue !== newObjValue &&
169
+ // treat NaN values as equivalent
170
+ !(Number.isNaN(objValue) && Number.isNaN(newObjValue)) &&
171
+ !(areCompatibleObjects &&
172
+ (Number.isNaN(objValue)
173
+ ? // eslint-disable-next-line prefer-template
174
+ objValue + "" === newObjValue + ""
175
+ : // eslint-disable-next-line @typescript-eslint/ban-ts-comment
176
+ // @ts-ignore
177
+ +objValue === +newObjValue))) {
178
+ diffs.push({
179
+ path: [path],
180
+ type: "CHANGE",
181
+ value: newObjValue,
182
+ oldValue: objValue,
183
+ objectId: options.useObjectIds?.idAttributeName === undefined
184
+ ? undefined
185
+ : newObj[options.useObjectIds.idAttributeName],
186
+ });
187
+ }
188
+ }
189
+ // 3. Finally, we check for new keys in the new object that did not exist in the old object.
190
+ // The existence of new keys may signal new values or moved values.
191
+ const newObjKeys = isTreeMapNode(newObj) ? newObj.keys() : Object.keys(newObj);
192
+ for (const key of newObjKeys) {
193
+ const newObjValue = isTreeMapNode(newObj)
194
+ ? newObj.get(key)
195
+ : newObj[key];
196
+ const path = isNewObjArray ? +key : key;
197
+ const isKeyInOldObject = isTreeMapNode(obj)
198
+ ? obj.has(key)
199
+ : Object.keys(obj).includes(key);
200
+ if (!isKeyInOldObject) {
201
+ if (options.useObjectIds === undefined) {
202
+ diffs.push({
203
+ type: "CREATE",
204
+ path: [path],
205
+ value: newObjValue,
206
+ });
207
+ }
208
+ // If we're dealing with an object in an array, we can use the object's id to check if this new index actually
209
+ // contains a prexisting object that was moved from an old index.
210
+ else if (isObjArray === true &&
211
+ isNewObjArray === true &&
212
+ typeof newObjValue === "object" &&
213
+ newObjValue !== null) {
214
+ const objectId = newObjValue[options.useObjectIds.idAttributeName];
215
+ if (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId)) {
216
+ // The new root object array contains a new index, however the object that lives at this new index previously existed at an old index.
217
+ // Therefore, this object was moved to a new index.
218
+ diffs.push({
219
+ type: "MOVE",
220
+ path: [path],
221
+ newIndex: newObjArrayItemIdsToIndex.get(objectId),
222
+ value: newObjValue,
223
+ objectId,
224
+ });
225
+ continue;
226
+ }
227
+ // If either the object's id attribute does not exist or the original array does not contain an object with the given id
228
+ // Then we assume this was a newly created object.
229
+ else {
230
+ diffs.push({
231
+ type: "CREATE",
232
+ path: [path],
233
+ value: newObjValue,
234
+ });
235
+ }
236
+ }
237
+ // If we're not dealing with an object in an array, we can't use id's to check for a move.
238
+ // We'll assume that a brand new key and value pair in the new object means that a new value was created.
239
+ else {
240
+ diffs.push({
241
+ type: "CREATE",
242
+ path: [path],
243
+ value: newObjValue,
244
+ });
245
+ }
246
+ }
247
+ else if (options.useObjectIds !== undefined) {
248
+ // If we're dealing with an object in an array, we can use the object's id to check if this EXISTING index
249
+ // houses a new object based on a newly encountered id.
250
+ if (isObjArray === true &&
251
+ isNewObjArray === true &&
252
+ typeof newObjValue === "object" &&
253
+ newObjValue !== null) {
254
+ const objectId = newObjValue[options.useObjectIds.idAttributeName];
255
+ // If this object has an id and it does not exist in the old array, then it was created.
256
+ if (objectId !== undefined && oldObjArrayItemIdsToIndex.has(objectId) === false) {
257
+ diffs.push({
258
+ type: "CREATE",
259
+ path: [path],
260
+ value: newObjValue,
261
+ });
262
+ }
263
+ }
264
+ else {
265
+ continue;
266
+ }
267
+ }
268
+ }
269
+ return diffs;
270
+ }
271
+ /**
272
+ * Type Guard that determines if a given object is an array of type unknown[] or {@link TreeArrayNode}.
273
+ */
274
+ function isArrayOrTreeArrayNode(obj) {
275
+ if (typeof obj === "object" && obj !== null) {
276
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
277
+ const maybeNodeKind = Object.getPrototypeOf(obj)?.constructor?.kind;
278
+ const isTreeArrayNode = maybeNodeKind === NodeKind.Array;
279
+ return Array.isArray(obj) || isTreeArrayNode;
280
+ }
281
+ return false;
282
+ }
283
+ /**
284
+ * Helper that creates a map of object ids to their index in an array of objects.
285
+ */
286
+ function createObjectArrayItemIdsToIndexMap(obj, idAttributeName) {
287
+ const objArrayItemIdsToIndex = new Map();
288
+ for (let i = 0; i < obj.length; i++) {
289
+ const objArrayItem = obj[i];
290
+ if (typeof objArrayItem === "object" && objArrayItem !== null) {
291
+ const id = objArrayItem[idAttributeName];
292
+ if (objArrayItemIdsToIndex.has(id)) {
293
+ throw new TypeError(`Duplicate object id found: ${id}`);
294
+ }
295
+ else if (id !== undefined) {
296
+ objArrayItemIdsToIndex.set(id, i);
297
+ }
298
+ }
299
+ }
300
+ return objArrayItemIdsToIndex;
301
+ }
302
+ /**
303
+ * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}
304
+ * that are using the object ID strategy. These diffs don't need any modifications to be applied to the old object.
305
+ *
306
+ * @alpha
307
+ */
308
+ export function createMergableIdDiffSeries(oldObject, diffs, idAttributeName) {
309
+ // the final series of diffs that will be returned.
310
+ const finalDiffSeries = [];
311
+ // Diffs that aren't of type 'CHANGE'
312
+ const nonChangeDiffs = [];
313
+ for (const diff of diffs) {
314
+ if (diff.type === "CHANGE") {
315
+ // Changes must be applied before any other diff, ao so they are ordered first.
316
+ finalDiffSeries.push({ ...diff });
317
+ }
318
+ else {
319
+ nonChangeDiffs.push({ ...diff });
320
+ }
321
+ }
322
+ // Create sets of array diffs grouped by the array they are applying changes to.
323
+ const diffsByArrayUuid = new Map();
324
+ for (const diff of nonChangeDiffs) {
325
+ if (!isDiffOnArray(diff)) {
326
+ continue;
327
+ }
328
+ const arrayUuid = arrayUuidFromPath(diff.path);
329
+ if (diffsByArrayUuid.has(arrayUuid) === false) {
330
+ diffsByArrayUuid.set(arrayUuid, []);
331
+ }
332
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
333
+ diffsByArrayUuid.get(arrayUuid).push(diff);
334
+ }
335
+ const shiftIndexesFromMove = (diff, targetArray, diffAdjustedObjectIndexes, objectId) => {
336
+ const sourceIndex = diff.path[diff.path.length - 1];
337
+ if (diff.newIndex > sourceIndex) {
338
+ // This move diff shifts objects it moved over to the left.
339
+ // |----| |----|
340
+ // e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{2}, {3}, {1}, {4}]
341
+ const minIndex = sourceIndex;
342
+ const maxIndex = diff.newIndex;
343
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
344
+ const shouldIndexBeShifted = id !== objectId && index <= maxIndex && index >= minIndex && index - 1 >= 0;
345
+ if (shouldIndexBeShifted) {
346
+ diffAdjustedObjectIndexes.set(id, index - 1);
347
+ }
348
+ }
349
+ }
350
+ else if (diff.newIndex < sourceIndex) {
351
+ // This move diff shifts objects it moved over to the right.
352
+ // |----| |----|
353
+ // e.g. - shift with no length change: [{1}, {2}, {3}, {4}] -> [{3}, {1}, {2}, {4}]
354
+ const minIndex = diff.newIndex;
355
+ const maxIndex = sourceIndex;
356
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
357
+ const shouldIndexBeShifted = id !== objectId &&
358
+ index <= maxIndex &&
359
+ index >= minIndex &&
360
+ index + 1 <= targetArray.length;
361
+ if (shouldIndexBeShifted) {
362
+ diffAdjustedObjectIndexes.set(id, index + 1);
363
+ }
364
+ }
365
+ }
366
+ };
367
+ const shiftIndexesFromRemove = (diff, diffAdjustedObjectIndexes, objectId) => {
368
+ const removalIndex = diff.path[diff.path.length - 1];
369
+ for (const [id, index] of diffAdjustedObjectIndexes.entries()) {
370
+ const shouldIndexBeShifted = id !== objectId && index > removalIndex && index - 1 >= 0;
371
+ if (shouldIndexBeShifted) {
372
+ diffAdjustedObjectIndexes.set(id, index - 1);
373
+ }
374
+ }
375
+ };
376
+ const diffsMarkedForRemoval = new Set();
377
+ const arrayDiffsMarkedForEndReorder = new Map();
378
+ for (const [arrayUuid, arrayDiffs] of diffsByArrayUuid.entries()) {
379
+ // The prior grouping code ensures that each map value will have atleast 1 diff.
380
+ const targetArray = getTargetObjectFromPath(
381
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
382
+ arrayDiffs[0].path, oldObject);
383
+ const diffAdjustedObjectIndexes = createObjectArrayItemIdsToIndexMap(targetArray, idAttributeName);
384
+ for (const diff of arrayDiffs) {
385
+ if (diff.type === "MOVE") {
386
+ const objectId = diff.value[idAttributeName];
387
+ const sourceIndex = diff.path[diff.path.length - 1];
388
+ // 1. Prior moves may render the next move redundant.
389
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
390
+ const currentAdjustedIndex = diffAdjustedObjectIndexes.get(objectId);
391
+ if (currentAdjustedIndex === diff.newIndex) {
392
+ diffsMarkedForRemoval.add(diff);
393
+ continue;
394
+ }
395
+ if (currentAdjustedIndex !== sourceIndex) {
396
+ // 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.
397
+ diff.path[diff.path.length - 1] = currentAdjustedIndex;
398
+ }
399
+ // Handle index shifts
400
+ diffAdjustedObjectIndexes.set(objectId, diff.newIndex);
401
+ // edge case: this MOVE should be applied after some series of creates that we haven't seen.
402
+ if (diff.newIndex > targetArray.length - 1) {
403
+ // It also wont shift any indexes since its moved to the total end of the array,
404
+ // after creations that produce the necessary indexes.
405
+ if (arrayDiffsMarkedForEndReorder.has(arrayUuid) === false) {
406
+ arrayDiffsMarkedForEndReorder.set(arrayUuid, []);
407
+ }
408
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
409
+ arrayDiffsMarkedForEndReorder.get(arrayUuid).push(diff);
410
+ }
411
+ else {
412
+ shiftIndexesFromMove(diff, targetArray, diffAdjustedObjectIndexes, objectId);
413
+ }
414
+ }
415
+ if (diff.type === "REMOVE") {
416
+ const objectId = diff.oldValue[idAttributeName];
417
+ const targetIndex = diff.path[diff.path.length - 1];
418
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
419
+ const currentDiffAdjustedIndex = diffAdjustedObjectIndexes.get(objectId);
420
+ if (targetIndex !== diffAdjustedObjectIndexes.get(objectId)) {
421
+ // 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.
422
+ diff.path[diff.path.length - 1] = currentDiffAdjustedIndex;
423
+ }
424
+ shiftIndexesFromRemove(diff, diffAdjustedObjectIndexes, objectId);
425
+ }
426
+ // Ignoring 'CREATE' for now.
427
+ }
428
+ }
429
+ for (let i = 0; i < nonChangeDiffs.length; i++) {
430
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
431
+ const diff = nonChangeDiffs[i];
432
+ if (diffsMarkedForRemoval.has(diff)) {
433
+ continue;
434
+ }
435
+ const isLastDiffInArraySeries = (currentIndex) => {
436
+ if (currentIndex === nonChangeDiffs.length - 1) {
437
+ return true;
438
+ }
439
+ const nextIndex = currentIndex + 1;
440
+ if (nextIndex <= nonChangeDiffs.length - 1) {
441
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
442
+ const diffAfter = nonChangeDiffs[nextIndex];
443
+ if (diffsMarkedForRemoval.has(diffAfter)) {
444
+ return isLastDiffInArraySeries(nextIndex + 1);
445
+ }
446
+ const arrayUuidAfter = arrayUuidFromPath(diffAfter.path);
447
+ const arrayUuid = arrayUuidFromPath(diff.path);
448
+ if (arrayUuidAfter === arrayUuid) {
449
+ return false;
450
+ }
451
+ }
452
+ return true;
453
+ };
454
+ if (isDiffOnArray(diff)) {
455
+ const arrayUuid = arrayUuidFromPath(diff.path);
456
+ const endReorderDiffs = arrayDiffsMarkedForEndReorder.get(arrayUuid);
457
+ const isDiffMarkedForReorder = endReorderDiffs?.includes(diff) ?? false;
458
+ if (isDiffMarkedForReorder === false) {
459
+ finalDiffSeries.push(diff);
460
+ }
461
+ if (isLastDiffInArraySeries(i) && endReorderDiffs !== undefined) {
462
+ finalDiffSeries.push(...endReorderDiffs);
463
+ }
464
+ continue;
465
+ }
466
+ finalDiffSeries.push(diff);
467
+ }
468
+ return finalDiffSeries;
469
+ }
470
+ /**
471
+ * Creates a set of mergeable diffs from a series of diffs produced by {@link sharedTreeDiff}
472
+ * that AREN'T using the object ID strategy. These diffs don't need any modifications to be applied to the old object.
473
+ *
474
+ * @alpha
475
+ */
476
+ export function createMergableDiffSeries(diffs) {
477
+ // the final series of diffs that will be returned.
478
+ const finalDiffSeries = [];
479
+ // Diffs that aren't of type 'CHANGE'
480
+ const nonChangeDiffs = [];
481
+ for (const diff of diffs) {
482
+ if (diff.type === "CHANGE") {
483
+ // Changes must be applied before any other diff, ao so they are ordered first.
484
+ finalDiffSeries.push({ ...diff });
485
+ }
486
+ else {
487
+ nonChangeDiffs.push({ ...diff });
488
+ }
489
+ }
490
+ finalDiffSeries.push(...nonChangeDiffs);
491
+ return finalDiffSeries;
492
+ }
493
+ /**
494
+ * Creates a UUID for the target array from a {@link Difference}'s ${@link ObjectPath}
495
+ */
496
+ function arrayUuidFromPath(path) {
497
+ return path.length === 1 ? "" : path.slice(0, -1).join("");
498
+ }
499
+ /**
500
+ * Determines if a given difference is on an array.
501
+ */
502
+ export function isDiffOnArray(diff) {
503
+ return typeof diff.path[diff.path.length - 1] === "number";
504
+ }
505
+ /**
506
+ * Returns the target object that the given diff should be applied to.
507
+ */
508
+ function getTargetObjectFromPath(path, object) {
509
+ let targetObject = object;
510
+ if (path.length > 1) {
511
+ targetObject = sharedTreeTraverse(object, path.slice(0, -1));
512
+ }
513
+ return targetObject;
514
+ }
515
+ //# sourceMappingURL=sharedTreeDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sharedTreeDiff.js","sourceRoot":"","sources":["../../src/implicit-strategy/sharedTreeDiff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAsB,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAwF/D,MAAM,SAAS,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAE3E;;;GAGG;AACH,MAAM,eAAe,GAAY,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAErD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC7B,GAAwC,EACxC,MAA2C,EAC3C,UAAmB,eAAe,EAClC,SAAkD,EAAE;IAEpD,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,aAAa,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAErD,wFAAwF;IACxF,MAAM,yBAAyB,GAC9B,UAAU,KAAK,KAAK,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;QACzD,CAAC,CAAC,IAAI,GAAG,EAA2B;QACpC,CAAC,CAAC,kCAAkC,CAAC,GAAG,EAAE,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAElF,MAAM,yBAAyB,GAC9B,aAAa,KAAK,KAAK,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;QAC5D,CAAC,CAAC,IAAI,GAAG,EAA2B;QACpC,CAAC,CAAC,kCAAkC,CAAC,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAErF,MAAM,UAAU,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtE,wHAAwH;IACxH,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAY,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACrC,0IAA0I;QAC1I,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;YACtB,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,QAAQ;iBAClB,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;YACD,mHAAmH;iBAC9G,IACJ,aAAa,KAAK,IAAI;gBACtB,UAAU;gBACV,OAAO,QAAQ,KAAK,QAAQ;gBAC5B,QAAQ,KAAK,IAAI,EAChB,CAAC;gBACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAGlD,CAAC;gBACb,IAAI,QAAQ,KAAK,SAAS,IAAI,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvE,6IAA6I;oBAC7I,iDAAiD;oBACjD,KAAK,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,CAAC,IAAI,CAAC;wBACZ,QAAQ,EAAE,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAW;wBAC3D,KAAK,EAAE,QAAQ;wBACf,QAAQ;qBACR,CAAC,CAAC;oBACH,SAAS;gBACV,CAAC;gBACD,+FAA+F;qBAC1F,CAAC;oBACL,KAAK,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,CAAC,IAAI,CAAC;wBACZ,QAAQ;wBACR,QAAQ,EAAE,QAAQ;qBAClB,CAAC,CAAC;oBACH,SAAS;gBACV,CAAC;YACF,CAAC;YACD,0FAA0F;YAC1F,oGAAoG;iBAC/F,CAAC;gBACL,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,QAAQ;iBAClB,CAAC,CAAC;gBACH,SAAS;YACV,CAAC;QACF,CAAC;QAED,MAAM,WAAW,GAAY,MAAM,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,oBAAoB,GACzB,OAAO,QAAQ,KAAK,QAAQ;YAC5B,OAAO,WAAW,KAAK,QAAQ;YAC/B,sBAAsB,CAAC,QAAQ,CAAC,KAAK,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAE1E,+KAA+K;QAC/K,IACC,QAAQ,KAAK,IAAI;YACjB,WAAW,KAAK,IAAI;YACpB,oBAAoB;YACpB,qHAAqH;YACrH,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC;YAC9D,CAAC,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAmC,CAAC,CAAC,EAC5E,CAAC;YACF,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACxC,MAAM,WAAW,GAAG,cAAc,CACjC,QAA+C,EAC/C,WAAkD,EAClD,OAAO,EACP,OAAO,CAAC,SAAS,KAAK,IAAI;oBACzB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,QAA+C,CAAC;oBAC9D,CAAC,CAAC,EAAE,CACL,CAAC;gBACF,yCAAyC;gBACzC,KAAK,CAAC,IAAI,CAAC,KAAK,CACf,KAAK,EACL,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;oBAC9B,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAC9B,OAAO,UAAU,CAAC;gBACnB,CAAC,CAAC,CACF,CAAC;YACH,CAAC;YACD,oFAAoF;iBAC/E,CAAC;gBACL,MAAM,WAAW,GAAI,QAAoC,CACxD,OAAO,CAAC,YAAY,CAAC,eAAe,CACL,CAAC;gBACjC,MAAM,WAAW,GAAI,WAAuC,CAC3D,OAAO,CAAC,YAAY,CAAC,eAAe,CACL,CAAC;gBAEjC,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBAC5D,8FAA8F;oBAC9F,IAAI,WAAW,KAAK,WAAW,EAAE,CAAC;wBACjC,MAAM,WAAW,GAAG,cAAc,CACjC,QAA+C,EAC/C,WAAkD,EAClD,OAAO,EACP,OAAO,CAAC,SAAS,KAAK,IAAI;4BACzB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,QAA+C,CAAC;4BAC9D,CAAC,CAAC,EAAE,CACL,CAAC;wBACF,KAAK,CAAC,IAAI,CACT,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;4BACjC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;4BAC9B,OAAO,UAAU,CAAC;wBACnB,CAAC,CAAC,CACF,CAAC;oBACH,CAAC;oBACD,2EAA2E;oBAC3E,uGAAuG;yBAClG,CAAC;wBACL,MAAM,mBAAmB,GAAG,yBAAyB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;wBACvE,0EAA0E;wBAC1E,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;4BACvC,KAAK,CAAC,IAAI,CAAC;gCACV,IAAI,EAAE,QAAQ;gCACd,IAAI,EAAE,CAAC,IAAI,CAAC;gCACZ,QAAQ,EAAE,QAAQ;gCAClB,QAAQ,EAAE,WAAW;6BACrB,CAAC,CAAC;wBACJ,CAAC;wBACD,2FAA2F;wBAC3F,0HAA0H;6BACrH,CAAC;4BACL,KAAK,CAAC,IAAI,CAAC;gCACV,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,CAAC,IAAI,CAAC;gCACZ,QAAQ,EAAE,mBAAmB;gCAC7B,KAAK,EAAE,QAAQ;gCACf,QAAQ,EAAE,WAAW;6BACrB,CAAC,CAAC;4BAEH,0EAA0E;4BAC1E,MAAM,WAAW,GAAG,cAAc,CACjC,GAAG,CAAC,IAAI,CAAwC,EAChD,MAAM,CAAC,mBAAmB,CAAwC,EAClE,OAAO,EACP,OAAO,CAAC,SAAS,KAAK,IAAI;gCACzB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,QAA+C,CAAC;gCAC9D,CAAC,CAAC,EAAE,CACL,CAAC;4BACF,KAAK,CAAC,IAAI,CACT,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;gCACjC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gCAC9B,OAAO,UAAU,CAAC;4BACnB,CAAC,CAAC,CACF,CAAC;wBACH,CAAC;oBACF,CAAC;gBACF,CAAC;qBAAM,CAAC;oBACP,MAAM,WAAW,GAAG,cAAc,CACjC,QAA+C,EAC/C,WAAkD,EAClD,OAAO,EACP,OAAO,CAAC,SAAS,KAAK,IAAI;wBACzB,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,QAA+C,CAAC;wBAC9D,CAAC,CAAC,EAAE,CACL,CAAC;oBACF,KAAK,CAAC,IAAI,CACT,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;wBACjC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;wBAC9B,OAAO,UAAU,CAAC;oBACnB,CAAC,CAAC,CACF,CAAC;gBACH,CAAC;YACF,CAAC;QACF,CAAC;QACD,iLAAiL;aAC5K,IACJ,QAAQ,KAAK,WAAW;YACxB,iCAAiC;YACjC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACtD,CAAC,CACA,oBAAoB;gBACpB,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;oBACtB,CAAC,CAAC,2CAA2C;wBAC5C,QAAQ,GAAG,EAAE,KAAK,WAAW,GAAG,EAAE;oBACnC,CAAC,CAAC,6DAA6D;wBAC9D,aAAa;wBACb,CAAC,QAAQ,KAAK,CAAC,WAAW,CAAC,CAC7B,EACA,CAAC;YACF,KAAK,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,QAAQ;gBAClB,QAAQ,EACP,OAAO,CAAC,YAAY,EAAE,eAAe,KAAK,SAAS;oBAClD,CAAC,CAAC,SAAS;oBACX,CAAC,CAAE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAAiC;aACjF,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IAED,4FAA4F;IAC5F,mEAAmE;IACnE,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC/E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,WAAW,GAAY,aAAa,CAAC,MAAM,CAAC;YACjD,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAa,CAAC;YAC3B,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACf,MAAM,IAAI,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAExC,MAAM,gBAAgB,GAAG,aAAa,CAAC,GAAG,CAAC;YAC1C,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAa,CAAC;YACxB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,GAAa,CAAC,CAAC;QAC5C,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvB,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,IAAI,CAAC;oBACZ,KAAK,EAAE,WAAW;iBAClB,CAAC,CAAC;YACJ,CAAC;YACD,8GAA8G;YAC9G,iEAAiE;iBAC5D,IACJ,UAAU,KAAK,IAAI;gBACnB,aAAa,KAAK,IAAI;gBACtB,OAAO,WAAW,KAAK,QAAQ;gBAC/B,WAAW,KAAK,IAAI,EACnB,CAAC;gBACF,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAGrD,CAAC;gBACb,IAAI,QAAQ,KAAK,SAAS,IAAI,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvE,sIAAsI;oBACtI,mDAAmD;oBACnD,KAAK,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,CAAC,IAAI,CAAC;wBACZ,QAAQ,EAAE,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAW;wBAC3D,KAAK,EAAE,WAAW;wBAClB,QAAQ;qBACR,CAAC,CAAC;oBACH,SAAS;gBACV,CAAC;gBACD,wHAAwH;gBACxH,kDAAkD;qBAC7C,CAAC;oBACL,KAAK,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,CAAC,IAAI,CAAC;wBACZ,KAAK,EAAE,WAAW;qBAClB,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YACD,0FAA0F;YAC1F,yGAAyG;iBACpG,CAAC;gBACL,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,IAAI,CAAC;oBACZ,KAAK,EAAE,WAAW;iBAClB,CAAC,CAAC;YACJ,CAAC;QACF,CAAC;aAAM,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/C,0GAA0G;YAC1G,uDAAuD;YACvD,IACC,UAAU,KAAK,IAAI;gBACnB,aAAa,KAAK,IAAI;gBACtB,OAAO,WAAW,KAAK,QAAQ;gBAC/B,WAAW,KAAK,IAAI,EACnB,CAAC;gBACF,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,eAAe,CAGrD,CAAC;gBACb,wFAAwF;gBACxF,IAAI,QAAQ,KAAK,SAAS,IAAI,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;oBACjF,KAAK,CAAC,IAAI,CAAC;wBACV,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,CAAC,IAAI,CAAC;wBACZ,KAAK,EAAE,WAAW;qBAClB,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,SAAS;YACV,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,sBAAsB,CAAC,GAAY;IAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QAC7C,sEAAsE;QACtE,MAAM,aAAa,GAAY,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC;QAC7E,MAAM,eAAe,GAAG,aAAa,KAAK,QAAQ,CAAC,KAAK,CAAC;QACzD,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,kCAAkC,CAC1C,GAAc,EACd,eAAgC;IAEhC,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA2B,CAAC;IAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/D,MAAM,EAAE,GAAI,YAAwC,CAAC,eAAe,CAAoB,CAAC;YACzF,IAAI,sBAAsB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,SAAS,CAAC,8BAA8B,EAAE,EAAE,CAAC,CAAC;YACzD,CAAC;iBAAM,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC7B,sBAAsB,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACnC,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,sBAAsB,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACzC,SAAkB,EAClB,KAAmB,EACnB,eAAgC;IAEhC,mDAAmD;IACnD,MAAM,eAAe,GAAiB,EAAE,CAAC;IACzC,qCAAqC;IACrC,MAAM,cAAc,GAAiB,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,+EAA+E;YAC/E,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACP,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;IACF,CAAC;IAED,gFAAgF;IAChF,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAwB,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,SAAS;QACV,CAAC;QAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,IAAI,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,EAAE,CAAC;YAC/C,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACrC,CAAC;QAED,oEAAoE;QACpE,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,oBAAoB,GAAG,CAC5B,IAAoB,EACpB,WAAsB,EACtB,yBAAuD,EACvD,QAAyB,EAClB,EAAE;QACT,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;QAE9D,IAAI,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,CAAC;YACjC,2DAA2D;YAC3D,uEAAuE;YACvE,mFAAmF;YACnF,MAAM,QAAQ,GAAG,WAAW,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC/B,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,yBAAyB,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC/D,MAAM,oBAAoB,GACzB,EAAE,KAAK,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC7E,IAAI,oBAAoB,EAAE,CAAC;oBAC1B,yBAAyB,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACF,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,GAAG,WAAW,EAAE,CAAC;YACxC,4DAA4D;YAC5D,4EAA4E;YAC5E,mFAAmF;YACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC;YAC7B,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,yBAAyB,CAAC,OAAO,EAAE,EAAE,CAAC;gBAC/D,MAAM,oBAAoB,GACzB,EAAE,KAAK,QAAQ;oBACf,KAAK,IAAI,QAAQ;oBACjB,KAAK,IAAI,QAAQ;oBACjB,KAAK,GAAG,CAAC,IAAI,WAAW,CAAC,MAAM,CAAC;gBACjC,IAAI,oBAAoB,EAAE,CAAC;oBAC1B,yBAAyB,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;gBAC9C,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,CAC9B,IAAsB,EACtB,yBAAuD,EACvD,QAAyB,EAClB,EAAE;QACT,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;QAC/D,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,yBAAyB,CAAC,OAAO,EAAE,EAAE,CAAC;YAC/D,MAAM,oBAAoB,GAAG,EAAE,KAAK,QAAQ,IAAI,KAAK,GAAG,YAAY,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;YACvF,IAAI,oBAAoB,EAAE,CAAC;gBAC1B,yBAAyB,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YAC9C,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAc,CAAC;IACpD,MAAM,6BAA6B,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEtE,KAAK,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,gBAAgB,CAAC,OAAO,EAAE,EAAE,CAAC;QAClE,gFAAgF;QAChF,MAAM,WAAW,GAAG,uBAAuB;QAC1C,oEAAoE;QACpE,UAAU,CAAC,CAAC,CAAE,CAAC,IAAI,EACnB,SAA0B,CACb,CAAC;QACf,MAAM,yBAAyB,GAC9B,kCAAkC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAElE,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAI,IAAI,CAAC,KAAiC,CAAC,eAAe,CAE/D,CAAC;gBACV,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;gBAE9D,qDAAqD;gBACrD,oEAAoE;gBACpE,MAAM,oBAAoB,GAAG,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;gBACtE,IAAI,oBAAoB,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAC5C,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBAChC,SAAS;gBACV,CAAC;gBACD,IAAI,oBAAoB,KAAK,WAAW,EAAE,CAAC;oBAC1C,0HAA0H;oBAC1H,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,oBAAoB,CAAC;gBACxD,CAAC;gBAED,sBAAsB;gBACtB,yBAAyB,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEvD,4FAA4F;gBAC5F,IAAI,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC5C,gFAAgF;oBAChF,sDAAsD;oBACtD,IAAI,6BAA6B,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,EAAE,CAAC;wBAC5D,6BAA6B,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;oBAClD,CAAC;oBACD,oEAAoE;oBACpE,6BAA6B,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1D,CAAC;qBAAM,CAAC;oBACP,oBAAoB,CAAC,IAAI,EAAE,WAAW,EAAE,yBAAyB,EAAE,QAAQ,CAAC,CAAC;gBAC9E,CAAC;YACF,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAI,IAAI,CAAC,QAAoC,CAAC,eAAe,CAElE,CAAC;gBACV,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;gBAC9D,oEAAoE;gBACpE,MAAM,wBAAwB,GAAG,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;gBAC1E,IAAI,WAAW,KAAK,yBAAyB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC7D,0HAA0H;oBAC1H,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,wBAAwB,CAAC;gBAC5D,CAAC;gBAED,sBAAsB,CAAC,IAAI,EAAE,yBAAyB,EAAE,QAAQ,CAAC,CAAC;YACnE,CAAC;YAED,6BAA6B;QAC9B,CAAC;IACF,CAAC;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChD,oEAAoE;QACpE,MAAM,IAAI,GAAG,cAAc,CAAC,CAAC,CAAE,CAAC;QAEhC,IAAI,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,SAAS;QACV,CAAC;QAED,MAAM,uBAAuB,GAAG,CAAC,YAAoB,EAAW,EAAE;YACjE,IAAI,YAAY,KAAK,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChD,OAAO,IAAI,CAAC;YACb,CAAC;YACD,MAAM,SAAS,GAAG,YAAY,GAAG,CAAC,CAAC;YACnC,IAAI,SAAS,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,oEAAoE;gBACpE,MAAM,SAAS,GAAG,cAAc,CAAC,SAAS,CAAE,CAAC;gBAE7C,IAAI,qBAAqB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC1C,OAAO,uBAAuB,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;gBAC/C,CAAC;gBAED,MAAM,cAAc,GAAG,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBACzD,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC/C,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;oBAClC,OAAO,KAAK,CAAC;gBACd,CAAC;YACF,CAAC;YACD,OAAO,IAAI,CAAC;QACb,CAAC,CAAC;QAEF,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/C,MAAM,eAAe,GAAG,6BAA6B,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACrE,MAAM,sBAAsB,GAAG,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;YAExE,IAAI,sBAAsB,KAAK,KAAK,EAAE,CAAC;gBACtC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;YAED,IAAI,uBAAuB,CAAC,CAAC,CAAC,IAAI,eAAe,KAAK,SAAS,EAAE,CAAC;gBACjE,eAAe,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC;YAC1C,CAAC;YAED,SAAS;QACV,CAAC;QAED,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,eAAe,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAmB;IAC3D,mDAAmD;IACnD,MAAM,eAAe,GAAiB,EAAE,CAAC;IACzC,qCAAqC;IACrC,MAAM,cAAc,GAAiB,EAAE,CAAC;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC5B,+EAA+E;YAC/E,eAAe,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACP,cAAc,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;IACF,CAAC;IAED,eAAe,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAC;IAExC,OAAO,eAAe,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,IAAgB;IAC1C,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAgB;IAC7C,OAAO,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC/B,IAAgB,EAChB,MAA+C;IAE/C,IAAI,YAAY,GAAY,MAAM,CAAC;IACnC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,YAAY,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,YAAY,CAAC;AACrB,CAAC","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"}