patch-recorder 0.2.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -27
- package/dist/arrays.js +22 -10
- package/dist/arrays.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/maps.d.ts.map +1 -1
- package/dist/maps.js +15 -7
- package/dist/maps.js.map +1 -1
- package/dist/optimizer.js +18 -5
- package/dist/optimizer.js.map +1 -1
- package/dist/patches.d.ts +38 -7
- package/dist/patches.d.ts.map +1 -1
- package/dist/patches.js +122 -49
- package/dist/patches.js.map +1 -1
- package/dist/proxy.d.ts +18 -0
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +158 -7
- package/dist/proxy.js.map +1 -1
- package/dist/sets.d.ts.map +1 -1
- package/dist/sets.js +10 -3
- package/dist/sets.js.map +1 -1
- package/dist/types.d.ts +77 -15
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +6 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/arrays.ts +22 -10
- package/src/index.ts +1 -3
- package/src/maps.ts +17 -7
- package/src/optimizer.ts +20 -6
- package/src/patches.ts +142 -55
- package/src/proxy.ts +179 -8
- package/src/sets.ts +11 -3
- package/src/types.ts +82 -15
- package/src/utils.ts +7 -0
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAE9D,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;CAIZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,eAAe,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AAE9D;;;;GAIG;AACH,UAAU,eAAe;IACxB;;;OAGG;IACH,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,SAAS,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,UAAU,kBAAkB;IAC3B,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,UAAU,SAAS;IAClB,IAAI,EAAE,SAAS,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG;IAClC,EAAE,EAAE,OAAO,SAAS,CAAC,GAAG,CAAC;IACzB,KAAK,EAAE,GAAG,CAAC;CACX,GAAG,CAAC,eAAe,GAAG,kBAAkB,CAAC,CAAC;AAE3C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG;IACrC,EAAE,EAAE,OAAO,SAAS,CAAC,MAAM,CAAC;CAC5B,GAAG,CAAC,eAAe,GAAG,kBAAkB,CAAC,CAAC;AAE3C;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG;IACtC,EAAE,EAAE,OAAO,SAAS,CAAC,OAAO,CAAC;IAC7B,KAAK,EAAE,GAAG,CAAC;IACX;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,CAAC,eAAe,GAAG,kBAAkB,CAAC,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,CAAC;AAE1D,MAAM,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;AAE9B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,YAAY;IACpD,KAAK,EAAE,CAAC,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACjC"}
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAC,MAAM,YAAY,CAAC;AAE9E;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,EAAE,CAE1D;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAEpE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAE3D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CA2CvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAmC5C;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,SAAS,EACf,eAAe,EAAE,eAAe,GAAG,SAAS,GAC1C,iBAAiB,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAC,MAAM,YAAY,CAAC;AAE9E;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQzE;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,EAAE,CAE1D;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAEpE;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAE3D;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAMlD;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CA2CvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAmC5C;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE,SAAS,EACf,eAAe,EAAE,eAAe,GAAG,SAAS,GAC1C,iBAAiB,GAAG,SAAS,CAoD/B;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CA8BjD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAc1D"}
|
package/dist/utils.js
CHANGED
|
@@ -150,6 +150,12 @@ export function findGetItemIdFn(path, getItemIdConfig) {
|
|
|
150
150
|
if (typeof key === 'number') {
|
|
151
151
|
continue;
|
|
152
152
|
}
|
|
153
|
+
// If we already found a function, return it immediately
|
|
154
|
+
// This handles nested paths like ['items', 0, 'data', 'nested', 'value']
|
|
155
|
+
// where the config is { items: (item) => item.id }
|
|
156
|
+
if (typeof current === 'function') {
|
|
157
|
+
return current;
|
|
158
|
+
}
|
|
153
159
|
if (current === undefined || typeof current !== 'object') {
|
|
154
160
|
return undefined;
|
|
155
161
|
}
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/arrays.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {NonPrimitive, PatchPath, RecorderState} from './types.js';
|
|
2
|
-
import {generateAddPatch, generateDeletePatch, generateReplacePatch} from './patches.js';
|
|
3
|
-
import {createProxy} from './proxy.js';
|
|
2
|
+
import {generateAddPatch, generateDeletePatch, generateReplacePatch, generateSetPatch} from './patches.js';
|
|
3
|
+
import {createProxy, findArrayItemContext} from './proxy.js';
|
|
4
4
|
|
|
5
5
|
// Module-level Sets for O(1) lookup instead of O(n) array includes
|
|
6
6
|
const MUTATING_METHODS = new Set(['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']);
|
|
@@ -93,13 +93,19 @@ function generateArrayPatches(
|
|
|
93
93
|
oldArray: unknown[] | null,
|
|
94
94
|
oldLength: number,
|
|
95
95
|
) {
|
|
96
|
+
// Check if this array is nested inside a tracked item
|
|
97
|
+
// If so, all patches should include the parent item's id
|
|
98
|
+
const itemContext = findArrayItemContext(path, state);
|
|
99
|
+
const parentItem = itemContext?.item;
|
|
100
|
+
const itemPathIndex = itemContext?.pathIndex;
|
|
101
|
+
|
|
96
102
|
switch (method) {
|
|
97
103
|
case 'push': {
|
|
98
104
|
// Generate add patches for each new element
|
|
99
105
|
// oldLength is the starting index before push
|
|
100
106
|
args.forEach((value, i) => {
|
|
101
107
|
const index = oldLength + i;
|
|
102
|
-
generateAddPatch(state, [...path, index], value);
|
|
108
|
+
generateAddPatch(state, [...path, index], value, parentItem, itemPathIndex);
|
|
103
109
|
});
|
|
104
110
|
// No length patch when array grows (aligned with mutative)
|
|
105
111
|
break;
|
|
@@ -113,7 +119,7 @@ function generateArrayPatches(
|
|
|
113
119
|
generateReplacePatch(state, [...path, 'length'], array.length, oldLength);
|
|
114
120
|
} else {
|
|
115
121
|
// When arrayLengthAssignment is false, generate remove patch for last element
|
|
116
|
-
generateDeletePatch(state, [...path, oldLength - 1], result);
|
|
122
|
+
generateDeletePatch(state, [...path, oldLength - 1], result, parentItem, itemPathIndex);
|
|
117
123
|
}
|
|
118
124
|
}
|
|
119
125
|
break;
|
|
@@ -122,14 +128,14 @@ function generateArrayPatches(
|
|
|
122
128
|
case 'shift': {
|
|
123
129
|
// Remove first element (shifted elements are handled automatically by JSON Patch spec)
|
|
124
130
|
// We don't have oldValue here, but the result of shift() is the removed element
|
|
125
|
-
generateDeletePatch(state, [...path, 0], result);
|
|
131
|
+
generateDeletePatch(state, [...path, 0], result, parentItem, itemPathIndex);
|
|
126
132
|
break;
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
case 'unshift': {
|
|
130
136
|
// Add new elements at the beginning (shifted elements are handled automatically by JSON Patch spec)
|
|
131
137
|
args.forEach((value, i) => {
|
|
132
|
-
generateAddPatch(state, [...path, i], value);
|
|
138
|
+
generateAddPatch(state, [...path, i], value, parentItem, itemPathIndex);
|
|
133
139
|
});
|
|
134
140
|
break;
|
|
135
141
|
}
|
|
@@ -146,18 +152,19 @@ function generateArrayPatches(
|
|
|
146
152
|
const deletedElements = result as any[];
|
|
147
153
|
|
|
148
154
|
// First minCount elements: replace (overlap between add and delete)
|
|
155
|
+
// These are element replacements in a nested array - include parent item context
|
|
149
156
|
for (let i = 0; i < minCount; i++) {
|
|
150
|
-
|
|
157
|
+
generateSetPatch(state, [...path, actualStart + i], addItems[i], parentItem, itemPathIndex);
|
|
151
158
|
}
|
|
152
159
|
|
|
153
160
|
// Remaining add items: add
|
|
154
161
|
for (let i = minCount; i < addItems.length; i++) {
|
|
155
|
-
generateAddPatch(state, [...path, actualStart + i], addItems[i]);
|
|
162
|
+
generateAddPatch(state, [...path, actualStart + i], addItems[i], parentItem, itemPathIndex);
|
|
156
163
|
}
|
|
157
164
|
|
|
158
165
|
// Remaining delete items: remove (generate in reverse order)
|
|
159
166
|
for (let i = actualDeleteCount - 1; i >= minCount; i--) {
|
|
160
|
-
generateDeletePatch(state, [...path, actualStart + i], deletedElements[i]);
|
|
167
|
+
generateDeletePatch(state, [...path, actualStart + i], deletedElements[i], parentItem, itemPathIndex);
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
break;
|
|
@@ -167,7 +174,12 @@ function generateArrayPatches(
|
|
|
167
174
|
case 'reverse': {
|
|
168
175
|
// These reorder the entire array - generate full replace
|
|
169
176
|
// oldValue contains the array before the mutation
|
|
170
|
-
|
|
177
|
+
// For nested arrays, include parent item context
|
|
178
|
+
if (itemContext) {
|
|
179
|
+
generateSetPatch(state, path, array, parentItem, itemPathIndex);
|
|
180
|
+
} else {
|
|
181
|
+
generateReplacePatch(state, path, array, oldArray);
|
|
182
|
+
}
|
|
171
183
|
break;
|
|
172
184
|
}
|
|
173
185
|
}
|
package/src/index.ts
CHANGED
package/src/maps.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type {PatchPath, RecorderState} from './types.js';
|
|
2
|
-
import {createProxy} from './proxy.js';
|
|
3
|
-
import {generateAddPatch, generateDeletePatch,
|
|
2
|
+
import {createProxy, findArrayItemContext} from './proxy.js';
|
|
3
|
+
import {generateAddPatch, generateDeletePatch, generateSetPatch} from './patches.js';
|
|
4
4
|
import {cloneIfNeeded} from './utils.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -29,13 +29,18 @@ export function handleMapGet(
|
|
|
29
29
|
|
|
30
30
|
// Generate patch
|
|
31
31
|
const itemPath = [...path, key as any];
|
|
32
|
+
|
|
33
|
+
// Find parent item context if this Map is inside a tracked array item
|
|
34
|
+
const itemContext = findArrayItemContext(path, state);
|
|
32
35
|
|
|
33
36
|
if (existed) {
|
|
34
|
-
// Key exists - replace
|
|
35
|
-
|
|
37
|
+
// Key exists - replace
|
|
38
|
+
// Pass 'map' to skip getItemId for the Map's own keys
|
|
39
|
+
// but still include parent item id if nested inside a tracked array item
|
|
40
|
+
generateSetPatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex, 'map');
|
|
36
41
|
} else {
|
|
37
42
|
// Key doesn't exist - add
|
|
38
|
-
generateAddPatch(state, itemPath, cloneIfNeeded(value));
|
|
43
|
+
generateAddPatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex);
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
return result;
|
|
@@ -49,7 +54,9 @@ export function handleMapGet(
|
|
|
49
54
|
|
|
50
55
|
if (result) {
|
|
51
56
|
const itemPath = [...path, key as any];
|
|
52
|
-
|
|
57
|
+
// Find parent item context if this Map is inside a tracked array item
|
|
58
|
+
const itemContext = findArrayItemContext(path, state);
|
|
59
|
+
generateDeletePatch(state, itemPath, cloneIfNeeded(oldValue), itemContext?.item, itemContext?.pathIndex);
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
return result;
|
|
@@ -61,10 +68,13 @@ export function handleMapGet(
|
|
|
61
68
|
const entries = Array.from(obj.entries());
|
|
62
69
|
obj.clear();
|
|
63
70
|
|
|
71
|
+
// Find parent item context if this Map is inside a tracked array item
|
|
72
|
+
const itemContext = findArrayItemContext(path, state);
|
|
73
|
+
|
|
64
74
|
// Generate remove patches for all items
|
|
65
75
|
entries.forEach(([key, value]) => {
|
|
66
76
|
const itemPath = [...path, key as any];
|
|
67
|
-
generateDeletePatch(state, itemPath, cloneIfNeeded(value));
|
|
77
|
+
generateDeletePatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex);
|
|
68
78
|
});
|
|
69
79
|
};
|
|
70
80
|
}
|
package/src/optimizer.ts
CHANGED
|
@@ -203,9 +203,9 @@ function cancelArrayPushPop(patches: Patches): Patches {
|
|
|
203
203
|
(a, b) => (b.path[b.path.length - 1] as number) - (a.path[a.path.length - 1] as number),
|
|
204
204
|
);
|
|
205
205
|
|
|
206
|
-
// Find pop patches (length reduction)
|
|
206
|
+
// Find pop patches (length reduction) - these are replace patches with a value
|
|
207
207
|
const popPatches = groupPatches.filter(
|
|
208
|
-
(p) => p.op === 'replace' && p.path[p.path.length - 1] === 'length',
|
|
208
|
+
(p) => p.op === 'replace' && p.path[p.path.length - 1] === 'length' && 'value' in p,
|
|
209
209
|
);
|
|
210
210
|
|
|
211
211
|
// Cancel pushes and pops that match (push at highest index, pop reduces length)
|
|
@@ -216,7 +216,7 @@ function cancelArrayPushPop(patches: Patches): Patches {
|
|
|
216
216
|
|
|
217
217
|
// Check if the push index matches the pop target
|
|
218
218
|
const pushIndex = pushPatch.path[pushPatch.path.length - 1] as number;
|
|
219
|
-
const popLength = popPatch
|
|
219
|
+
const popLength = (popPatch as {value: number}).value;
|
|
220
220
|
|
|
221
221
|
// If push added at index pushIndex and pop reduced to popLength, they cancel
|
|
222
222
|
// This is a heuristic: push adds at end, pop removes from end
|
|
@@ -241,7 +241,8 @@ function cancelOutOfBoundsPatches(patches: Patches): Patches {
|
|
|
241
241
|
if (
|
|
242
242
|
Array.isArray(patch.path) &&
|
|
243
243
|
patch.path.length >= 2 &&
|
|
244
|
-
patch.path[patch.path.length - 1] === 'length'
|
|
244
|
+
patch.path[patch.path.length - 1] === 'length' &&
|
|
245
|
+
'value' in patch
|
|
245
246
|
) {
|
|
246
247
|
const parentPath = pathToKey(patch.path.slice(0, -1));
|
|
247
248
|
arrayLengths.set(parentPath, patch.value as number);
|
|
@@ -284,7 +285,7 @@ function mergePatches(patch1: Patch, patch2: Patch): Patch | null | undefined {
|
|
|
284
285
|
// Same operations - keep the latest one
|
|
285
286
|
if (op1 === op2) {
|
|
286
287
|
// For replace operations, keep the latest value
|
|
287
|
-
if (op1 === 'replace') {
|
|
288
|
+
if (op1 === 'replace' && 'value' in patch1 && 'value' in patch2) {
|
|
288
289
|
// Skip if same reference (no-op)
|
|
289
290
|
if (patch1.value === patch2.value) {
|
|
290
291
|
return patch1;
|
|
@@ -292,7 +293,7 @@ function mergePatches(patch1: Patch, patch2: Patch): Patch | null | undefined {
|
|
|
292
293
|
return patch2;
|
|
293
294
|
}
|
|
294
295
|
// For add operations, if adding same reference, it's a no-op
|
|
295
|
-
if (op1 === 'add' && patch1.value === patch2.value) {
|
|
296
|
+
if (op1 === 'add' && 'value' in patch1 && 'value' in patch2 && patch1.value === patch2.value) {
|
|
296
297
|
return patch1;
|
|
297
298
|
}
|
|
298
299
|
// For remove operations, don't merge (sequential removes should never be merged)
|
|
@@ -324,6 +325,19 @@ function mergePatches(patch1: Patch, patch2: Patch): Patch | null | undefined {
|
|
|
324
325
|
|
|
325
326
|
if (op1 === 'remove' && op2 === 'add') {
|
|
326
327
|
// Remove then add - this is a replace operation
|
|
328
|
+
// Preserve id and pathIndex from either patch (they should be the same if present)
|
|
329
|
+
const id = patch1.id ?? patch2.id;
|
|
330
|
+
const pathIndex = patch1.pathIndex ?? patch2.pathIndex;
|
|
331
|
+
|
|
332
|
+
if (id !== undefined && pathIndex !== undefined) {
|
|
333
|
+
return {
|
|
334
|
+
op: 'replace',
|
|
335
|
+
path: patch1.path,
|
|
336
|
+
value: patch2.value,
|
|
337
|
+
id,
|
|
338
|
+
pathIndex,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
327
341
|
return {
|
|
328
342
|
op: 'replace',
|
|
329
343
|
path: patch1.path,
|
package/src/patches.ts
CHANGED
|
@@ -1,73 +1,165 @@
|
|
|
1
|
-
import type {NonPrimitive,
|
|
1
|
+
import type {NonPrimitive, PatchPath, RecorderState, ReplacePatch, RemovePatch, AddPatch} from './types.js';
|
|
2
2
|
import {Operation} from './types.js';
|
|
3
3
|
import {cloneIfNeeded, findGetItemIdFn} from './utils.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Generate a replace patch for property changes
|
|
6
|
+
* Generate a replace patch for property changes.
|
|
7
|
+
* Used for field modifications inside items (e.g., state.items[0].name = 'new')
|
|
8
|
+
*
|
|
9
|
+
* @param parentItem - Optional parent item when modifying a field inside an array item.
|
|
10
|
+
* Used to extract the item's ID for the patch.
|
|
11
|
+
* @param itemPathIndex - Optional index indicating where the item path ends in the full path.
|
|
12
|
+
* Used for pathIndex in the patch.
|
|
13
|
+
* @param isMapOrSet - Deprecated/unused - Maps nested in tracked items now include parent item ID.
|
|
7
14
|
*/
|
|
8
15
|
export function generateSetPatch(
|
|
9
16
|
state: RecorderState<NonPrimitive>,
|
|
10
17
|
path: PatchPath,
|
|
11
|
-
oldValue: unknown,
|
|
12
18
|
newValue: unknown,
|
|
19
|
+
parentItem?: unknown,
|
|
20
|
+
itemPathIndex?: number,
|
|
21
|
+
isMapOrSet?: 'map' | 'set',
|
|
13
22
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
// Try to extract item id if parent item is provided
|
|
24
|
+
// Note: The isMapOrSet flag is no longer checked here because:
|
|
25
|
+
// - When a Map is nested inside a tracked array item, we want the parent item's id
|
|
26
|
+
// - The parentItem passed in is the array item, not the Map entry
|
|
27
|
+
let id: string | number | undefined;
|
|
28
|
+
if (parentItem !== undefined) {
|
|
29
|
+
const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
|
|
30
|
+
if (getItemIdFn) {
|
|
31
|
+
const extractedId = getItemIdFn(parentItem);
|
|
32
|
+
if (extractedId !== undefined && extractedId !== null) {
|
|
33
|
+
id = extractedId;
|
|
34
|
+
}
|
|
26
35
|
}
|
|
27
36
|
}
|
|
28
37
|
|
|
38
|
+
// Construct patch with proper type based on whether id is present
|
|
39
|
+
const patch: ReplacePatch =
|
|
40
|
+
id !== undefined && itemPathIndex !== undefined
|
|
41
|
+
? {
|
|
42
|
+
op: Operation.Replace,
|
|
43
|
+
path,
|
|
44
|
+
value: cloneIfNeeded(newValue),
|
|
45
|
+
id,
|
|
46
|
+
pathIndex: itemPathIndex,
|
|
47
|
+
}
|
|
48
|
+
: {
|
|
49
|
+
op: Operation.Replace,
|
|
50
|
+
path,
|
|
51
|
+
value: cloneIfNeeded(newValue),
|
|
52
|
+
};
|
|
53
|
+
|
|
29
54
|
state.patches.push(patch);
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
/**
|
|
33
|
-
* Generate a remove patch for property deletions
|
|
58
|
+
* Generate a remove patch for property deletions.
|
|
59
|
+
*
|
|
60
|
+
* For ITEM removal (e.g., state.items.splice(1, 1)):
|
|
61
|
+
* - No id is included - the item is being removed, not modified.
|
|
62
|
+
*
|
|
63
|
+
* For FIELD removal from an item (e.g., delete state.items[0].optional):
|
|
64
|
+
* - The id of the parent item is included - the item is being modified.
|
|
65
|
+
*
|
|
66
|
+
* @param parentItem - Optional parent item when deleting a field from inside an array item.
|
|
67
|
+
* Used to extract the item's ID for the patch.
|
|
68
|
+
* @param itemPathIndex - Optional index indicating where the item path ends in the full path.
|
|
34
69
|
*/
|
|
35
70
|
export function generateDeletePatch(
|
|
36
71
|
state: RecorderState<NonPrimitive>,
|
|
37
72
|
path: PatchPath,
|
|
38
|
-
|
|
73
|
+
_oldValue: unknown,
|
|
74
|
+
parentItem?: unknown,
|
|
75
|
+
itemPathIndex?: number,
|
|
39
76
|
) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (id !== undefined && id !== null) {
|
|
50
|
-
patch.id = id;
|
|
77
|
+
// Try to extract item id if parent item is provided
|
|
78
|
+
let id: string | number | undefined;
|
|
79
|
+
if (parentItem !== undefined) {
|
|
80
|
+
const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
|
|
81
|
+
if (getItemIdFn) {
|
|
82
|
+
const extractedId = getItemIdFn(parentItem);
|
|
83
|
+
if (extractedId !== undefined && extractedId !== null) {
|
|
84
|
+
id = extractedId;
|
|
85
|
+
}
|
|
51
86
|
}
|
|
52
87
|
}
|
|
53
88
|
|
|
89
|
+
// Construct patch with proper type based on whether id is present
|
|
90
|
+
const patch: RemovePatch =
|
|
91
|
+
id !== undefined && itemPathIndex !== undefined
|
|
92
|
+
? {
|
|
93
|
+
op: Operation.Remove,
|
|
94
|
+
path,
|
|
95
|
+
id,
|
|
96
|
+
pathIndex: itemPathIndex,
|
|
97
|
+
}
|
|
98
|
+
: {
|
|
99
|
+
op: Operation.Remove,
|
|
100
|
+
path,
|
|
101
|
+
};
|
|
102
|
+
|
|
54
103
|
state.patches.push(patch);
|
|
55
104
|
}
|
|
56
105
|
|
|
57
106
|
/**
|
|
58
|
-
* Generate an add patch for new properties
|
|
107
|
+
* Generate an add patch for new properties.
|
|
108
|
+
*
|
|
109
|
+
* For adding a FIELD to an existing item (e.g., state.items[0].newField = 'value'):
|
|
110
|
+
* - The id of the parent item is included - the item is being modified.
|
|
111
|
+
*
|
|
112
|
+
* For adding a NEW ITEM to an array (e.g., state.items.push(newItem)):
|
|
113
|
+
* - No id is included - we're not modifying an existing item.
|
|
114
|
+
*
|
|
115
|
+
* @param parentItem - Optional parent item when adding a field to an array item.
|
|
116
|
+
* Used to extract the item's ID for the patch.
|
|
117
|
+
* @param itemPathIndex - Optional index indicating where the item path ends in the full path.
|
|
59
118
|
*/
|
|
60
|
-
export function generateAddPatch(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
119
|
+
export function generateAddPatch(
|
|
120
|
+
state: RecorderState<any>,
|
|
121
|
+
path: PatchPath,
|
|
122
|
+
value: any,
|
|
123
|
+
parentItem?: unknown,
|
|
124
|
+
itemPathIndex?: number,
|
|
125
|
+
) {
|
|
126
|
+
// Try to extract item id if parent item is provided
|
|
127
|
+
let id: string | number | undefined;
|
|
128
|
+
if (parentItem !== undefined) {
|
|
129
|
+
const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
|
|
130
|
+
if (getItemIdFn) {
|
|
131
|
+
const extractedId = getItemIdFn(parentItem);
|
|
132
|
+
if (extractedId !== undefined && extractedId !== null) {
|
|
133
|
+
id = extractedId;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Construct patch with proper type based on whether id is present
|
|
139
|
+
const patch: AddPatch =
|
|
140
|
+
id !== undefined && itemPathIndex !== undefined
|
|
141
|
+
? {
|
|
142
|
+
op: Operation.Add,
|
|
143
|
+
path,
|
|
144
|
+
value: cloneIfNeeded(value),
|
|
145
|
+
id,
|
|
146
|
+
pathIndex: itemPathIndex,
|
|
147
|
+
}
|
|
148
|
+
: {
|
|
149
|
+
op: Operation.Add,
|
|
150
|
+
path,
|
|
151
|
+
value: cloneIfNeeded(value),
|
|
152
|
+
};
|
|
153
|
+
|
|
66
154
|
state.patches.push(patch);
|
|
67
155
|
}
|
|
68
156
|
|
|
69
157
|
/**
|
|
70
|
-
* Generate a replace patch for full
|
|
158
|
+
* Generate a replace patch for full item replacement or array length changes.
|
|
159
|
+
* Used for array length changes that need oldValue.
|
|
160
|
+
*
|
|
161
|
+
* Note: This function is used for array length changes only.
|
|
162
|
+
* For item replacements without id, use generateSetPatch instead.
|
|
71
163
|
*/
|
|
72
164
|
export function generateReplacePatch(
|
|
73
165
|
state: RecorderState<any>,
|
|
@@ -75,25 +167,20 @@ export function generateReplacePatch(
|
|
|
75
167
|
value: unknown,
|
|
76
168
|
oldValue?: unknown,
|
|
77
169
|
) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
path
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const id = getItemIdFn(oldValue);
|
|
93
|
-
if (id !== undefined && id !== null) {
|
|
94
|
-
patch.id = id;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
170
|
+
// This function is now only used for array length changes
|
|
171
|
+
const patch: ReplacePatch =
|
|
172
|
+
path.length > 0 && path[path.length - 1] === 'length' && oldValue !== undefined
|
|
173
|
+
? {
|
|
174
|
+
op: Operation.Replace,
|
|
175
|
+
path,
|
|
176
|
+
value: cloneIfNeeded(value),
|
|
177
|
+
oldValue,
|
|
178
|
+
}
|
|
179
|
+
: {
|
|
180
|
+
op: Operation.Replace,
|
|
181
|
+
path,
|
|
182
|
+
value: cloneIfNeeded(value),
|
|
183
|
+
};
|
|
97
184
|
|
|
98
185
|
state.patches.push(patch);
|
|
99
186
|
}
|