patch-recorder 0.2.1 → 0.3.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 +9 -2
- package/dist/arrays.js +10 -7
- package/dist/arrays.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/patches.d.ts.map +1 -1
- package/dist/patches.js +4 -0
- package/dist/patches.js.map +1 -1
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +40 -1
- package/dist/proxy.js.map +1 -1
- package/dist/types.d.ts +44 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/arrays.ts +9 -6
- package/src/index.ts +9 -3
- package/src/patches.ts +5 -0
- package/src/proxy.ts +44 -1
- package/src/types.ts +48 -6
package/README.md
CHANGED
|
@@ -90,9 +90,9 @@ Records JSON patches from mutations applied to the state.
|
|
|
90
90
|
#### Options
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
- **`arrayLengthAssignment`** (boolean, default: `true`) - When `true`, includes length patches when array shrinks (pop, shift, splice delete). When `false`, omits length patches entirely. Aligned with mutative's behavior.
|
|
93
|
+
- **`arrayLengthAssignment`** (boolean, default: `true`) - When `true`, includes length patches when array shrinks (pop, shift, splice delete). When `false`, omits length patches entirely. Must be `false` when using `getItemId`. Aligned with mutative's behavior.
|
|
94
94
|
- **`compressPatches`** (boolean, default: `true`) - Compress patches by merging redundant operations
|
|
95
|
-
- **`getItemId`** (object, optional) - Configuration for extracting item IDs (see [Item ID Tracking](#item-id-tracking))
|
|
95
|
+
- **`getItemId`** (object, optional) - Configuration for extracting item IDs. **Requires `arrayLengthAssignment: false`**. (see [Item ID Tracking](#item-id-tracking))
|
|
96
96
|
|
|
97
97
|
|
|
98
98
|
#### Returns
|
|
@@ -227,6 +227,10 @@ console.log(patches);
|
|
|
227
227
|
|
|
228
228
|
When working with arrays, the patch path only tells you the index, not which item was affected. The `getItemId` option allows you to include item IDs in `remove` and `replace` patches, making it easier to track which items changed.
|
|
229
229
|
|
|
230
|
+
**Important:** `getItemId` requires `arrayLengthAssignment: false` because length patches (e.g., `{ op: 'replace', path: ['arr', 'length'], value: 2 }`) cannot include individual item IDs. This is enforced at both compile time and runtime.
|
|
231
|
+
|
|
232
|
+
**Note:** When `arrayLengthAssignment: false`, direct array length assignment (`arr.length = N`) generates individual remove/add patches instead of a length patch, allowing proper item ID tracking.
|
|
233
|
+
|
|
230
234
|
```typescript
|
|
231
235
|
const state = {
|
|
232
236
|
users: [
|
|
@@ -239,6 +243,7 @@ const state = {
|
|
|
239
243
|
const patches = recordPatches(state, (state) => {
|
|
240
244
|
state.users.splice(1, 1); // Remove Bob
|
|
241
245
|
}, {
|
|
246
|
+
arrayLengthAssignment: false, // Required when using getItemId
|
|
242
247
|
getItemId: {
|
|
243
248
|
users: (user) => user.id // Extract ID from each user
|
|
244
249
|
}
|
|
@@ -255,6 +260,7 @@ The `getItemId` option is an object that mirrors your data structure:
|
|
|
255
260
|
|
|
256
261
|
```typescript
|
|
257
262
|
recordPatches(state, mutate, {
|
|
263
|
+
arrayLengthAssignment: false, // Required when using getItemId
|
|
258
264
|
getItemId: {
|
|
259
265
|
// Top-level arrays
|
|
260
266
|
items: (item) => item.id,
|
|
@@ -288,6 +294,7 @@ const state = {
|
|
|
288
294
|
const patches = recordPatches(state, (state) => {
|
|
289
295
|
state.entityMap.delete('key1');
|
|
290
296
|
}, {
|
|
297
|
+
arrayLengthAssignment: false, // Required when using getItemId
|
|
291
298
|
getItemId: {
|
|
292
299
|
entityMap: (entity) => entity.internalId
|
|
293
300
|
}
|
package/dist/arrays.js
CHANGED
|
@@ -77,13 +77,16 @@ function generateArrayPatches(state, array, method, args, result, path, oldArray
|
|
|
77
77
|
break;
|
|
78
78
|
}
|
|
79
79
|
case 'pop': {
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
// Only generate patch if length actually changed (pop on empty array does nothing)
|
|
81
|
+
if (array.length !== oldLength) {
|
|
82
|
+
if (state.options.arrayLengthAssignment !== false) {
|
|
83
|
+
// Generate length replace patch (mutative uses this instead of remove)
|
|
84
|
+
generateReplacePatch(state, [...path, 'length'], array.length, oldLength);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// When arrayLengthAssignment is false, generate remove patch for last element
|
|
88
|
+
generateDeletePatch(state, [...path, oldLength - 1], result);
|
|
89
|
+
}
|
|
87
90
|
}
|
|
88
91
|
break;
|
|
89
92
|
}
|
package/dist/arrays.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arrays.js","sourceRoot":"","sources":["../src/arrays.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"arrays.js","sourceRoot":"","sources":["../src/arrays.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAE,oBAAoB,EAAE,OAAO,EAAC,MAAM,YAAY,CAAC;AAE5E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC5B,CAAC,SAAS,YAAY,EACtB,aAAa,SAAS,oBAAoB,GAAG,EAAE,EAC9C,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAE,oBAAoB,EAAE,OAAO,EAAC,MAAM,YAAY,CAAC;AAE5E;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC5B,CAAC,SAAS,YAAY,EACtB,aAAa,SAAS,oBAAoB,GAAG,EAAE,EAC9C,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CA6BxE;AAGD,YAAY,EAAC,YAAY,EAAE,oBAAoB,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAC,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,13 +18,16 @@ import { compressPatches } from './optimizer.js';
|
|
|
18
18
|
* console.log(patches); // [{ op: 'replace', path: ['user', 'name'], value: 'Jane' }]
|
|
19
19
|
*/
|
|
20
20
|
export function recordPatches(state, mutate, options) {
|
|
21
|
+
// Runtime validation: getItemId requires arrayLengthAssignment: false
|
|
22
|
+
if (options?.getItemId && options?.arrayLengthAssignment !== false) {
|
|
23
|
+
throw new Error('getItemId requires arrayLengthAssignment: false. ' +
|
|
24
|
+
'Length patches cannot include individual item IDs.');
|
|
25
|
+
}
|
|
21
26
|
const recorderState = {
|
|
22
27
|
state,
|
|
23
28
|
patches: [],
|
|
24
29
|
basePath: [],
|
|
25
|
-
options: {
|
|
26
|
-
...options,
|
|
27
|
-
},
|
|
30
|
+
options: options ?? {},
|
|
28
31
|
proxyCache: new WeakMap(),
|
|
29
32
|
};
|
|
30
33
|
// Create proxy
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAG/C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAG3B,KAAQ,EAAE,MAA0B,EAAE,OAAuB;IAC9D,MAAM,aAAa,GAAG;QACrB,KAAK;QACL,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,YAAY,CAAC;AACvC,OAAO,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAG/C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,aAAa,CAG3B,KAAQ,EAAE,MAA0B,EAAE,OAAuB;IAC9D,sEAAsE;IACtE,IAAI,OAAO,EAAE,SAAS,IAAI,OAAO,EAAE,qBAAqB,KAAK,KAAK,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CACd,mDAAmD;YAClD,oDAAoD,CACrD,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG;QACrB,KAAK;QACL,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,OAAO,IAAI,EAAE;QACtB,UAAU,EAAE,IAAI,OAAO,EAAE;KACzB,CAAC;IAEF,eAAe;IACf,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,EAAE,aAAa,CAAM,CAAC;IAEzD,kBAAkB;IAClB,MAAM,CAAC,KAAK,CAAC,CAAC;IAEd,yCAAyC;IACzC,IAAI,OAAO,EAAE,eAAe,KAAK,KAAK,EAAE,CAAC;QACxC,OAAO,eAAe,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,aAAa,CAAC,OAAkB,CAAC;AACzC,CAAC"}
|
package/dist/patches.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAS,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAI9E;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,EAClC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,OAAO,QAkBjB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,EAClC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,OAAO,QAiBjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,QAOtF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAS,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAI9E;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,EAClC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,OAAO,QAkBjB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,EAClC,IAAI,EAAE,SAAS,EACf,QAAQ,EAAE,OAAO,QAiBjB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,QAOtF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,OAAO,EACd,QAAQ,CAAC,EAAE,OAAO,QAuBlB"}
|
package/dist/patches.js
CHANGED
|
@@ -57,6 +57,10 @@ export function generateReplacePatch(state, path, value, oldValue) {
|
|
|
57
57
|
path: path,
|
|
58
58
|
value: cloneIfNeeded(value),
|
|
59
59
|
};
|
|
60
|
+
// Include oldValue for array length changes to enable consumers to detect element removal
|
|
61
|
+
if (path.length > 0 && path[path.length - 1] === 'length' && oldValue !== undefined) {
|
|
62
|
+
patch.oldValue = oldValue;
|
|
63
|
+
}
|
|
60
64
|
// Add id if getItemId is configured for this path
|
|
61
65
|
const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
|
|
62
66
|
if (getItemIdFn && oldValue !== undefined) {
|
package/dist/patches.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"patches.js","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,EAAC,aAAa,EAAE,eAAe,EAAC,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAkC,EAClC,IAAe,EACf,QAAiB,EACjB,QAAiB;IAEjB,MAAM,KAAK,GAAQ;QAClB,EAAE,EAAE,SAAS,CAAC,OAAO;QACrB,IAAI;QACJ,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC;KAC9B,CAAC;IAEF,kDAAkD;IAClD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,WAAW,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACf,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAAkC,EAClC,IAAe,EACf,QAAiB;IAEjB,MAAM,KAAK,GAAU;QACpB,EAAE,EAAE,SAAS,CAAC,MAAM;QACpB,IAAI,EAAE,IAAI;KACV,CAAC;IAEF,kDAAkD;IAClD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,WAAW,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACf,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAyB,EAAE,IAAe,EAAE,KAAU;IACtF,MAAM,KAAK,GAAU;QACpB,EAAE,EAAE,SAAS,CAAC,GAAG;QACjB,IAAI;QACJ,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;KAC3B,CAAC;IACF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CACnC,KAAyB,EACzB,IAAe,EACf,KAAc,EACd,QAAkB;IAElB,MAAM,KAAK,GAAU;QACpB,EAAE,EAAE,SAAS,CAAC,OAAO;QACrB,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;KAC3B,CAAC;IAEF,kDAAkD;IAClD,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,IAAI,WAAW,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YACrC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACf,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
|
|
1
|
+
{"version":3,"file":"patches.js","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"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"}
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAYzD,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC3C,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,CAAC,CA8KH"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateSetPatch, generateDeletePatch, generateAddPatch } from './patches.js';
|
|
1
|
+
import { generateSetPatch, generateDeletePatch, generateAddPatch, generateReplacePatch, } from './patches.js';
|
|
2
2
|
import { isArray, isMap, isSet } from './utils.js';
|
|
3
3
|
import { handleArrayGet } from './arrays.js';
|
|
4
4
|
import { handleMapGet } from './maps.js';
|
|
@@ -58,12 +58,51 @@ export function createProxy(target, path, state) {
|
|
|
58
58
|
if (Object.is(oldValue, value) && (value !== undefined || actuallyHasProperty)) {
|
|
59
59
|
return true;
|
|
60
60
|
}
|
|
61
|
+
// Special handling for array length with arrayLengthAssignment: false
|
|
62
|
+
// Must capture removed items BEFORE mutation
|
|
63
|
+
let removedItems = null;
|
|
64
|
+
if (isArrayType && prop === 'length' && state.options.arrayLengthAssignment === false) {
|
|
65
|
+
const arr = obj;
|
|
66
|
+
const newLength = value;
|
|
67
|
+
if (newLength < oldValue) {
|
|
68
|
+
// Capture items that will be removed before mutation
|
|
69
|
+
removedItems = [];
|
|
70
|
+
for (let i = newLength; i < oldValue; i++) {
|
|
71
|
+
removedItems.push(arr[i]);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
61
75
|
// Mutate original immediately
|
|
62
76
|
obj[prop] = value;
|
|
63
77
|
// Generate patch - use pre-mutation property existence check
|
|
64
78
|
if (!hadProperty) {
|
|
65
79
|
generateAddPatch(state, propPath, value);
|
|
66
80
|
}
|
|
81
|
+
else if (isArrayType && prop === 'length') {
|
|
82
|
+
if (state.options.arrayLengthAssignment === false) {
|
|
83
|
+
// When arrayLengthAssignment is false, generate individual remove patches
|
|
84
|
+
// for each removed item (in reverse order)
|
|
85
|
+
const newLength = value;
|
|
86
|
+
if (removedItems) {
|
|
87
|
+
// Array was shrinking - generate remove patches for removed items
|
|
88
|
+
// Iterate in reverse to generate patches from end to start
|
|
89
|
+
for (let i = removedItems.length - 1; i >= 0; i--) {
|
|
90
|
+
const index = newLength + i;
|
|
91
|
+
generateDeletePatch(state, [...path, index], removedItems[i]);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else if (newLength > oldValue) {
|
|
95
|
+
// Array is growing - generate add patches for new undefined slots
|
|
96
|
+
for (let i = oldValue; i < newLength; i++) {
|
|
97
|
+
generateAddPatch(state, [...path, i], undefined);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Use generateReplacePatch for array length to include oldValue
|
|
103
|
+
generateReplacePatch(state, propPath, value, oldValue);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
67
106
|
else {
|
|
68
107
|
generateSetPatch(state, propPath, oldValue, value);
|
|
69
108
|
}
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ export type Patch = {
|
|
|
19
19
|
path: PatchPath;
|
|
20
20
|
op: PatchOp;
|
|
21
21
|
value?: any;
|
|
22
|
+
/**
|
|
23
|
+
* Optional previous value for replace operations on array length.
|
|
24
|
+
* Enables consumers to detect how many elements were removed without pre-snapshotting state.
|
|
25
|
+
*/
|
|
26
|
+
oldValue?: unknown;
|
|
22
27
|
/**
|
|
23
28
|
* Optional ID of the item being removed or replaced.
|
|
24
29
|
* Populated when getItemId option is configured for the item's parent path.
|
|
@@ -27,15 +32,25 @@ export type Patch = {
|
|
|
27
32
|
};
|
|
28
33
|
export type Patches = Patch[];
|
|
29
34
|
export type NonPrimitive = object | Array<unknown>;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
arrayLengthAssignment?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Base options shared by all configurations
|
|
37
|
+
*/
|
|
38
|
+
interface BaseRecordPatchesOptions {
|
|
35
39
|
/**
|
|
36
40
|
* Compress patches by merging redundant operations (default: true)
|
|
37
41
|
*/
|
|
38
42
|
compressPatches?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Options when using getItemId - requires arrayLengthAssignment to be false
|
|
46
|
+
* because length patches cannot include individual item IDs.
|
|
47
|
+
*/
|
|
48
|
+
interface RecordPatchesOptionsWithItemId extends BaseRecordPatchesOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Must be false when using getItemId.
|
|
51
|
+
* Length patches cannot include individual item IDs.
|
|
52
|
+
*/
|
|
53
|
+
arrayLengthAssignment: false;
|
|
39
54
|
/**
|
|
40
55
|
* Configuration for extracting item IDs for remove/replace patches.
|
|
41
56
|
* Maps paths to functions that extract IDs from item values.
|
|
@@ -43,6 +58,7 @@ export interface RecordPatchesOptions {
|
|
|
43
58
|
* @example
|
|
44
59
|
* ```typescript
|
|
45
60
|
* recordPatches(state, mutate, {
|
|
61
|
+
* arrayLengthAssignment: false,
|
|
46
62
|
* getItemId: {
|
|
47
63
|
* items: (item) => item.id,
|
|
48
64
|
* users: (user) => user.userId,
|
|
@@ -53,8 +69,29 @@ export interface RecordPatchesOptions {
|
|
|
53
69
|
* });
|
|
54
70
|
* ```
|
|
55
71
|
*/
|
|
56
|
-
getItemId
|
|
72
|
+
getItemId: GetItemIdConfig;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Options when not using getItemId - arrayLengthAssignment can be any value
|
|
76
|
+
*/
|
|
77
|
+
interface RecordPatchesOptionsWithoutItemId extends BaseRecordPatchesOptions {
|
|
78
|
+
/**
|
|
79
|
+
* Include array length in patches (default: true)
|
|
80
|
+
*/
|
|
81
|
+
arrayLengthAssignment?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Not available unless arrayLengthAssignment is false
|
|
84
|
+
*/
|
|
85
|
+
getItemId?: undefined;
|
|
57
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Configuration options for recordPatches.
|
|
89
|
+
*
|
|
90
|
+
* Note: getItemId requires arrayLengthAssignment: false because length patches
|
|
91
|
+
* (e.g., { op: 'replace', path: ['arr', 'length'], value: 2, oldValue: 3 })
|
|
92
|
+
* cannot include the IDs of individual items that were removed.
|
|
93
|
+
*/
|
|
94
|
+
export type RecordPatchesOptions = RecordPatchesOptionsWithItemId | RecordPatchesOptionsWithoutItemId;
|
|
58
95
|
export interface RecorderState<T extends NonPrimitive> {
|
|
59
96
|
state: T;
|
|
60
97
|
patches: Patches;
|
|
@@ -65,4 +102,5 @@ export interface RecorderState<T extends NonPrimitive> {
|
|
|
65
102
|
*/
|
|
66
103
|
proxyCache: WeakMap<object, any>;
|
|
67
104
|
}
|
|
105
|
+
export {};
|
|
68
106
|
//# sourceMappingURL=types.d.ts.map
|
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,KAAK,GAAG;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;AAE9B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;AAEnD,
|
|
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,KAAK,GAAG;IACnB,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;AAE9B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;AAEnD;;GAEG;AACH,UAAU,wBAAwB;IACjC;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,UAAU,8BAA+B,SAAQ,wBAAwB;IACxE;;;OAGG;IACH,qBAAqB,EAAE,KAAK,CAAC;IAC7B;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,EAAE,eAAe,CAAC;CAC3B;AAED;;GAEG;AACH,UAAU,iCAAkC,SAAQ,wBAAwB;IAC3E;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAC7B,8BAA8B,GAC9B,iCAAiC,CAAC;AAErC,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/package.json
CHANGED
package/src/arrays.ts
CHANGED
|
@@ -106,12 +106,15 @@ function generateArrayPatches(
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
case 'pop': {
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
109
|
+
// Only generate patch if length actually changed (pop on empty array does nothing)
|
|
110
|
+
if (array.length !== oldLength) {
|
|
111
|
+
if (state.options.arrayLengthAssignment !== false) {
|
|
112
|
+
// Generate length replace patch (mutative uses this instead of remove)
|
|
113
|
+
generateReplacePatch(state, [...path, 'length'], array.length, oldLength);
|
|
114
|
+
} else {
|
|
115
|
+
// When arrayLengthAssignment is false, generate remove patch for last element
|
|
116
|
+
generateDeletePatch(state, [...path, oldLength - 1], result);
|
|
117
|
+
}
|
|
115
118
|
}
|
|
116
119
|
break;
|
|
117
120
|
}
|
package/src/index.ts
CHANGED
|
@@ -23,13 +23,19 @@ export function recordPatches<
|
|
|
23
23
|
T extends NonPrimitive,
|
|
24
24
|
PatchesOption extends RecordPatchesOptions = {},
|
|
25
25
|
>(state: T, mutate: (state: T) => void, options?: PatchesOption): Patches {
|
|
26
|
+
// Runtime validation: getItemId requires arrayLengthAssignment: false
|
|
27
|
+
if (options?.getItemId && options?.arrayLengthAssignment !== false) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
'getItemId requires arrayLengthAssignment: false. ' +
|
|
30
|
+
'Length patches cannot include individual item IDs.',
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
const recorderState = {
|
|
27
35
|
state,
|
|
28
36
|
patches: [],
|
|
29
37
|
basePath: [],
|
|
30
|
-
options: {
|
|
31
|
-
...options,
|
|
32
|
-
},
|
|
38
|
+
options: options ?? {},
|
|
33
39
|
proxyCache: new WeakMap(),
|
|
34
40
|
};
|
|
35
41
|
|
package/src/patches.ts
CHANGED
|
@@ -81,6 +81,11 @@ export function generateReplacePatch(
|
|
|
81
81
|
value: cloneIfNeeded(value),
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
// Include oldValue for array length changes to enable consumers to detect element removal
|
|
85
|
+
if (path.length > 0 && path[path.length - 1] === 'length' && oldValue !== undefined) {
|
|
86
|
+
patch.oldValue = oldValue;
|
|
87
|
+
}
|
|
88
|
+
|
|
84
89
|
// Add id if getItemId is configured for this path
|
|
85
90
|
const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
|
|
86
91
|
if (getItemIdFn && oldValue !== undefined) {
|
package/src/proxy.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type {PatchPath, RecorderState} from './types.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
generateSetPatch,
|
|
4
|
+
generateDeletePatch,
|
|
5
|
+
generateAddPatch,
|
|
6
|
+
generateReplacePatch,
|
|
7
|
+
} from './patches.js';
|
|
3
8
|
import {isArray, isMap, isSet} from './utils.js';
|
|
4
9
|
import {handleArrayGet} from './arrays.js';
|
|
5
10
|
import {handleMapGet} from './maps.js';
|
|
@@ -78,12 +83,50 @@ export function createProxy<T extends object>(
|
|
|
78
83
|
return true;
|
|
79
84
|
}
|
|
80
85
|
|
|
86
|
+
// Special handling for array length with arrayLengthAssignment: false
|
|
87
|
+
// Must capture removed items BEFORE mutation
|
|
88
|
+
let removedItems: any[] | null = null;
|
|
89
|
+
if (isArrayType && prop === 'length' && state.options.arrayLengthAssignment === false) {
|
|
90
|
+
const arr = obj as any[];
|
|
91
|
+
const newLength = value as number;
|
|
92
|
+
if (newLength < oldValue) {
|
|
93
|
+
// Capture items that will be removed before mutation
|
|
94
|
+
removedItems = [];
|
|
95
|
+
for (let i = newLength; i < oldValue; i++) {
|
|
96
|
+
removedItems.push(arr[i]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
81
101
|
// Mutate original immediately
|
|
82
102
|
(obj as any)[prop] = value;
|
|
83
103
|
|
|
84
104
|
// Generate patch - use pre-mutation property existence check
|
|
85
105
|
if (!hadProperty) {
|
|
86
106
|
generateAddPatch(state, propPath, value);
|
|
107
|
+
} else if (isArrayType && prop === 'length') {
|
|
108
|
+
if (state.options.arrayLengthAssignment === false) {
|
|
109
|
+
// When arrayLengthAssignment is false, generate individual remove patches
|
|
110
|
+
// for each removed item (in reverse order)
|
|
111
|
+
const newLength = value as number;
|
|
112
|
+
|
|
113
|
+
if (removedItems) {
|
|
114
|
+
// Array was shrinking - generate remove patches for removed items
|
|
115
|
+
// Iterate in reverse to generate patches from end to start
|
|
116
|
+
for (let i = removedItems.length - 1; i >= 0; i--) {
|
|
117
|
+
const index = newLength + i;
|
|
118
|
+
generateDeletePatch(state, [...path, index], removedItems[i]);
|
|
119
|
+
}
|
|
120
|
+
} else if (newLength > oldValue) {
|
|
121
|
+
// Array is growing - generate add patches for new undefined slots
|
|
122
|
+
for (let i = oldValue; i < newLength; i++) {
|
|
123
|
+
generateAddPatch(state, [...path, i], undefined);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
// Use generateReplacePatch for array length to include oldValue
|
|
128
|
+
generateReplacePatch(state, propPath, value, oldValue);
|
|
129
|
+
}
|
|
87
130
|
} else {
|
|
88
131
|
generateSetPatch(state, propPath, oldValue, value);
|
|
89
132
|
}
|
package/src/types.ts
CHANGED
|
@@ -24,6 +24,11 @@ export type Patch = {
|
|
|
24
24
|
path: PatchPath;
|
|
25
25
|
op: PatchOp;
|
|
26
26
|
value?: any;
|
|
27
|
+
/**
|
|
28
|
+
* Optional previous value for replace operations on array length.
|
|
29
|
+
* Enables consumers to detect how many elements were removed without pre-snapshotting state.
|
|
30
|
+
*/
|
|
31
|
+
oldValue?: unknown;
|
|
27
32
|
/**
|
|
28
33
|
* Optional ID of the item being removed or replaced.
|
|
29
34
|
* Populated when getItemId option is configured for the item's parent path.
|
|
@@ -35,15 +40,26 @@ export type Patches = Patch[];
|
|
|
35
40
|
|
|
36
41
|
export type NonPrimitive = object | Array<unknown>;
|
|
37
42
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
arrayLengthAssignment?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Base options shared by all configurations
|
|
45
|
+
*/
|
|
46
|
+
interface BaseRecordPatchesOptions {
|
|
43
47
|
/**
|
|
44
48
|
* Compress patches by merging redundant operations (default: true)
|
|
45
49
|
*/
|
|
46
50
|
compressPatches?: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Options when using getItemId - requires arrayLengthAssignment to be false
|
|
55
|
+
* because length patches cannot include individual item IDs.
|
|
56
|
+
*/
|
|
57
|
+
interface RecordPatchesOptionsWithItemId extends BaseRecordPatchesOptions {
|
|
58
|
+
/**
|
|
59
|
+
* Must be false when using getItemId.
|
|
60
|
+
* Length patches cannot include individual item IDs.
|
|
61
|
+
*/
|
|
62
|
+
arrayLengthAssignment: false;
|
|
47
63
|
/**
|
|
48
64
|
* Configuration for extracting item IDs for remove/replace patches.
|
|
49
65
|
* Maps paths to functions that extract IDs from item values.
|
|
@@ -51,6 +67,7 @@ export interface RecordPatchesOptions {
|
|
|
51
67
|
* @example
|
|
52
68
|
* ```typescript
|
|
53
69
|
* recordPatches(state, mutate, {
|
|
70
|
+
* arrayLengthAssignment: false,
|
|
54
71
|
* getItemId: {
|
|
55
72
|
* items: (item) => item.id,
|
|
56
73
|
* users: (user) => user.userId,
|
|
@@ -61,9 +78,34 @@ export interface RecordPatchesOptions {
|
|
|
61
78
|
* });
|
|
62
79
|
* ```
|
|
63
80
|
*/
|
|
64
|
-
getItemId
|
|
81
|
+
getItemId: GetItemIdConfig;
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Options when not using getItemId - arrayLengthAssignment can be any value
|
|
86
|
+
*/
|
|
87
|
+
interface RecordPatchesOptionsWithoutItemId extends BaseRecordPatchesOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Include array length in patches (default: true)
|
|
90
|
+
*/
|
|
91
|
+
arrayLengthAssignment?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Not available unless arrayLengthAssignment is false
|
|
94
|
+
*/
|
|
95
|
+
getItemId?: undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Configuration options for recordPatches.
|
|
100
|
+
*
|
|
101
|
+
* Note: getItemId requires arrayLengthAssignment: false because length patches
|
|
102
|
+
* (e.g., { op: 'replace', path: ['arr', 'length'], value: 2, oldValue: 3 })
|
|
103
|
+
* cannot include the IDs of individual items that were removed.
|
|
104
|
+
*/
|
|
105
|
+
export type RecordPatchesOptions =
|
|
106
|
+
| RecordPatchesOptionsWithItemId
|
|
107
|
+
| RecordPatchesOptionsWithoutItemId;
|
|
108
|
+
|
|
67
109
|
export interface RecorderState<T extends NonPrimitive> {
|
|
68
110
|
state: T;
|
|
69
111
|
patches: Patches;
|