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/dist/patches.js CHANGED
@@ -1,74 +1,147 @@
1
1
  import { Operation } from './types.js';
2
2
  import { cloneIfNeeded, findGetItemIdFn } from './utils.js';
3
3
  /**
4
- * Generate a replace patch for property changes
4
+ * Generate a replace patch for property changes.
5
+ * Used for field modifications inside items (e.g., state.items[0].name = 'new')
6
+ *
7
+ * @param parentItem - Optional parent item when modifying a field inside an array item.
8
+ * Used to extract the item's ID for the patch.
9
+ * @param itemPathIndex - Optional index indicating where the item path ends in the full path.
10
+ * Used for pathIndex in the patch.
11
+ * @param isMapOrSet - Deprecated/unused - Maps nested in tracked items now include parent item ID.
5
12
  */
6
- export function generateSetPatch(state, path, oldValue, newValue) {
7
- const patch = {
8
- op: Operation.Replace,
9
- path,
10
- value: cloneIfNeeded(newValue),
11
- };
12
- // Add id if getItemId is configured for this path
13
- const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
14
- if (getItemIdFn && oldValue !== undefined) {
15
- const id = getItemIdFn(oldValue);
16
- if (id !== undefined && id !== null) {
17
- patch.id = id;
13
+ export function generateSetPatch(state, path, newValue, parentItem, itemPathIndex, isMapOrSet) {
14
+ // Try to extract item id if parent item is provided
15
+ // Note: The isMapOrSet flag is no longer checked here because:
16
+ // - When a Map is nested inside a tracked array item, we want the parent item's id
17
+ // - The parentItem passed in is the array item, not the Map entry
18
+ let id;
19
+ if (parentItem !== undefined) {
20
+ const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
21
+ if (getItemIdFn) {
22
+ const extractedId = getItemIdFn(parentItem);
23
+ if (extractedId !== undefined && extractedId !== null) {
24
+ id = extractedId;
25
+ }
18
26
  }
19
27
  }
28
+ // Construct patch with proper type based on whether id is present
29
+ const patch = id !== undefined && itemPathIndex !== undefined
30
+ ? {
31
+ op: Operation.Replace,
32
+ path,
33
+ value: cloneIfNeeded(newValue),
34
+ id,
35
+ pathIndex: itemPathIndex,
36
+ }
37
+ : {
38
+ op: Operation.Replace,
39
+ path,
40
+ value: cloneIfNeeded(newValue),
41
+ };
20
42
  state.patches.push(patch);
21
43
  }
22
44
  /**
23
- * Generate a remove patch for property deletions
45
+ * Generate a remove patch for property deletions.
46
+ *
47
+ * For ITEM removal (e.g., state.items.splice(1, 1)):
48
+ * - No id is included - the item is being removed, not modified.
49
+ *
50
+ * For FIELD removal from an item (e.g., delete state.items[0].optional):
51
+ * - The id of the parent item is included - the item is being modified.
52
+ *
53
+ * @param parentItem - Optional parent item when deleting a field from inside an array item.
54
+ * Used to extract the item's ID for the patch.
55
+ * @param itemPathIndex - Optional index indicating where the item path ends in the full path.
24
56
  */
25
- export function generateDeletePatch(state, path, oldValue) {
26
- const patch = {
27
- op: Operation.Remove,
28
- path: path,
29
- };
30
- // Add id if getItemId is configured for this path
31
- const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
32
- if (getItemIdFn && oldValue !== undefined) {
33
- const id = getItemIdFn(oldValue);
34
- if (id !== undefined && id !== null) {
35
- patch.id = id;
57
+ export function generateDeletePatch(state, path, _oldValue, parentItem, itemPathIndex) {
58
+ // Try to extract item id if parent item is provided
59
+ let id;
60
+ if (parentItem !== undefined) {
61
+ const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
62
+ if (getItemIdFn) {
63
+ const extractedId = getItemIdFn(parentItem);
64
+ if (extractedId !== undefined && extractedId !== null) {
65
+ id = extractedId;
66
+ }
36
67
  }
37
68
  }
69
+ // Construct patch with proper type based on whether id is present
70
+ const patch = id !== undefined && itemPathIndex !== undefined
71
+ ? {
72
+ op: Operation.Remove,
73
+ path,
74
+ id,
75
+ pathIndex: itemPathIndex,
76
+ }
77
+ : {
78
+ op: Operation.Remove,
79
+ path,
80
+ };
38
81
  state.patches.push(patch);
39
82
  }
40
83
  /**
41
- * Generate an add patch for new properties
84
+ * Generate an add patch for new properties.
85
+ *
86
+ * For adding a FIELD to an existing item (e.g., state.items[0].newField = 'value'):
87
+ * - The id of the parent item is included - the item is being modified.
88
+ *
89
+ * For adding a NEW ITEM to an array (e.g., state.items.push(newItem)):
90
+ * - No id is included - we're not modifying an existing item.
91
+ *
92
+ * @param parentItem - Optional parent item when adding a field to an array item.
93
+ * Used to extract the item's ID for the patch.
94
+ * @param itemPathIndex - Optional index indicating where the item path ends in the full path.
42
95
  */
43
- export function generateAddPatch(state, path, value) {
44
- const patch = {
45
- op: Operation.Add,
46
- path,
47
- value: cloneIfNeeded(value),
48
- };
96
+ export function generateAddPatch(state, path, value, parentItem, itemPathIndex) {
97
+ // Try to extract item id if parent item is provided
98
+ let id;
99
+ if (parentItem !== undefined) {
100
+ const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
101
+ if (getItemIdFn) {
102
+ const extractedId = getItemIdFn(parentItem);
103
+ if (extractedId !== undefined && extractedId !== null) {
104
+ id = extractedId;
105
+ }
106
+ }
107
+ }
108
+ // Construct patch with proper type based on whether id is present
109
+ const patch = id !== undefined && itemPathIndex !== undefined
110
+ ? {
111
+ op: Operation.Add,
112
+ path,
113
+ value: cloneIfNeeded(value),
114
+ id,
115
+ pathIndex: itemPathIndex,
116
+ }
117
+ : {
118
+ op: Operation.Add,
119
+ path,
120
+ value: cloneIfNeeded(value),
121
+ };
49
122
  state.patches.push(patch);
50
123
  }
51
124
  /**
52
- * Generate a replace patch for full object/array replacement
125
+ * Generate a replace patch for full item replacement or array length changes.
126
+ * Used for array length changes that need oldValue.
127
+ *
128
+ * Note: This function is used for array length changes only.
129
+ * For item replacements without id, use generateSetPatch instead.
53
130
  */
54
131
  export function generateReplacePatch(state, path, value, oldValue) {
55
- const patch = {
56
- op: Operation.Replace,
57
- path: path,
58
- value: cloneIfNeeded(value),
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
- }
64
- // Add id if getItemId is configured for this path
65
- const getItemIdFn = findGetItemIdFn(path, state.options.getItemId);
66
- if (getItemIdFn && oldValue !== undefined) {
67
- const id = getItemIdFn(oldValue);
68
- if (id !== undefined && id !== null) {
69
- patch.id = id;
132
+ // This function is now only used for array length changes
133
+ const patch = path.length > 0 && path[path.length - 1] === 'length' && oldValue !== undefined
134
+ ? {
135
+ op: Operation.Replace,
136
+ path,
137
+ value: cloneIfNeeded(value),
138
+ oldValue,
70
139
  }
71
- }
140
+ : {
141
+ op: Operation.Replace,
142
+ path,
143
+ value: cloneIfNeeded(value),
144
+ };
72
145
  state.patches.push(patch);
73
146
  }
74
147
  //# sourceMappingURL=patches.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"patches.js","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"patches.js","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"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"}
package/dist/proxy.d.ts CHANGED
@@ -1,3 +1,21 @@
1
1
  import type { PatchPath, RecorderState } from './types.js';
2
+ /**
3
+ * Find the array item context for getItemId extraction.
4
+ * Traverses the path and getItemId config in parallel to find the TRACKED array item,
5
+ * not just any array item. This ensures that nested arrays inside tracked items
6
+ * correctly return the tracked parent item.
7
+ *
8
+ * For path ['users', 0, 'posts', 0, 'title'] with config { users: (fn) => ... }:
9
+ * - Returns state.users[0] (the user), not state.users[0].posts[0] (the post)
10
+ * - pathIndex will be 2 (position after the user's numeric index)
11
+ *
12
+ * @param path - The full path to the property being modified
13
+ * @param state - The recorder state containing the root state object
14
+ * @returns Object with item and pathIndex, or undefined if not inside a tracked array item
15
+ */
16
+ export declare function findArrayItemContext(path: PatchPath, state: RecorderState<any>): {
17
+ item: unknown;
18
+ pathIndex: number;
19
+ } | undefined;
2
20
  export declare function createProxy<T extends object>(target: T, path: PatchPath, state: RecorderState<any>): T;
3
21
  //# sourceMappingURL=proxy.d.ts.map
@@ -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;AAOzD,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC3C,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,CAAC,CA2IH"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAY1E;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CACnC,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAC,GAAG,SAAS,CA8ChD;AA+BD,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC3C,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,CAAC,CAmNH"}
package/dist/proxy.js CHANGED
@@ -1,8 +1,91 @@
1
- import { generateSetPatch, generateDeletePatch, generateAddPatch, generateReplacePatch } 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';
5
5
  import { handleSetGet } from './sets.js';
6
+ /**
7
+ * Find the array item context for getItemId extraction.
8
+ * Traverses the path and getItemId config in parallel to find the TRACKED array item,
9
+ * not just any array item. This ensures that nested arrays inside tracked items
10
+ * correctly return the tracked parent item.
11
+ *
12
+ * For path ['users', 0, 'posts', 0, 'title'] with config { users: (fn) => ... }:
13
+ * - Returns state.users[0] (the user), not state.users[0].posts[0] (the post)
14
+ * - pathIndex will be 2 (position after the user's numeric index)
15
+ *
16
+ * @param path - The full path to the property being modified
17
+ * @param state - The recorder state containing the root state object
18
+ * @returns Object with item and pathIndex, or undefined if not inside a tracked array item
19
+ */
20
+ export function findArrayItemContext(path, state) {
21
+ const getItemIdConfig = state.options.getItemId;
22
+ // If no getItemId config, fall back to finding any numeric index from the end
23
+ // This maintains backward compatibility for cases without getItemId
24
+ if (!getItemIdConfig) {
25
+ return findDeepestArrayItem(path, state);
26
+ }
27
+ // Traverse path and config in parallel
28
+ // Skip numeric indices in the path when traversing the config
29
+ let currentConfig = getItemIdConfig;
30
+ for (let i = 0; i < path.length; i++) {
31
+ const pathKey = path[i];
32
+ // If we find a numeric index, check if we've found a getItemId function
33
+ if (typeof pathKey === 'number') {
34
+ // Check if the previous config level was a function
35
+ // This means this numeric index is for a tracked array
36
+ if (typeof currentConfig === 'function') {
37
+ // Found the tracked item! Navigate to it from root
38
+ let item = state.state;
39
+ for (let j = 0; j <= i; j++) {
40
+ const key = path[j];
41
+ item = item[key];
42
+ if (item === undefined || item === null)
43
+ return undefined;
44
+ }
45
+ // pathIndex is i + 1 (position after the numeric index)
46
+ return { item, pathIndex: i + 1 };
47
+ }
48
+ // Not a tracked array, continue to next path segment
49
+ continue;
50
+ }
51
+ // String key - traverse the config
52
+ if (typeof pathKey === 'string' && currentConfig && typeof currentConfig === 'object') {
53
+ currentConfig = currentConfig[pathKey];
54
+ }
55
+ else if (typeof pathKey === 'string') {
56
+ // No config at this level, but we still might have a numeric index ahead
57
+ // Continue without config
58
+ currentConfig = undefined;
59
+ }
60
+ }
61
+ return undefined;
62
+ }
63
+ /**
64
+ * Fallback function that finds the deepest array item (original behavior).
65
+ * Used when no getItemId config is provided.
66
+ */
67
+ function findDeepestArrayItem(path, state) {
68
+ for (let i = path.length - 1; i >= 1; i--) {
69
+ if (typeof path[i] === 'number') {
70
+ // Found a numeric index - the array item is the object at this position
71
+ // Navigate from the root state to get the array item
72
+ let current = state.state;
73
+ for (let j = 0; j <= i; j++) {
74
+ const pathKey = path[j];
75
+ current = current[pathKey];
76
+ if (current === undefined || current === null)
77
+ break;
78
+ }
79
+ if (current !== undefined && current !== null) {
80
+ // pathIndex is i + 1 (the position after the numeric index)
81
+ // This represents the length of the item path
82
+ return { item: current, pathIndex: i + 1 };
83
+ }
84
+ break;
85
+ }
86
+ }
87
+ return undefined;
88
+ }
6
89
  export function createProxy(target, path, state) {
7
90
  // Check cache first
8
91
  const cached = state.proxyCache.get(target);
@@ -58,18 +141,84 @@ export function createProxy(target, path, state) {
58
141
  if (Object.is(oldValue, value) && (value !== undefined || actuallyHasProperty)) {
59
142
  return true;
60
143
  }
144
+ // Special handling for array length with arrayLengthAssignment: false
145
+ // Must capture removed items BEFORE mutation
146
+ let removedItems = null;
147
+ if (isArrayType && prop === 'length' && state.options.arrayLengthAssignment === false) {
148
+ const arr = obj;
149
+ const newLength = value;
150
+ if (newLength < oldValue) {
151
+ // Capture items that will be removed before mutation
152
+ removedItems = [];
153
+ for (let i = newLength; i < oldValue; i++) {
154
+ removedItems.push(arr[i]);
155
+ }
156
+ }
157
+ }
61
158
  // Mutate original immediately
62
159
  obj[prop] = value;
160
+ // Find array item context for getItemId
161
+ const itemContext = findArrayItemContext(path, state);
63
162
  // Generate patch - use pre-mutation property existence check
64
163
  if (!hadProperty) {
65
- generateAddPatch(state, propPath, value);
164
+ // Check if we're adding a field to an array item (should include id)
165
+ // vs adding a new item to an array (should NOT include id)
166
+ if (itemContext) {
167
+ // Adding a field to an existing array item - include the item id
168
+ generateAddPatch(state, propPath, value, itemContext.item, itemContext.pathIndex);
169
+ }
170
+ else {
171
+ // Adding a new item to an array or a regular property - no id
172
+ generateAddPatch(state, propPath, value);
173
+ }
66
174
  }
67
175
  else if (isArrayType && prop === 'length') {
68
- // Use generateReplacePatch for array length to include oldValue
69
- generateReplacePatch(state, propPath, value, oldValue);
176
+ if (state.options.arrayLengthAssignment === false) {
177
+ // When arrayLengthAssignment is false, generate individual remove patches
178
+ // for each removed item (in reverse order)
179
+ const newLength = value;
180
+ if (removedItems) {
181
+ // Array was shrinking - generate remove patches for removed items
182
+ // Iterate in reverse to generate patches from end to start
183
+ for (let i = removedItems.length - 1; i >= 0; i--) {
184
+ const index = newLength + i;
185
+ generateDeletePatch(state, [...path, index], removedItems[i]);
186
+ }
187
+ }
188
+ else if (newLength > oldValue) {
189
+ // Array is growing - generate add patches for new undefined slots
190
+ for (let i = oldValue; i < newLength; i++) {
191
+ generateAddPatch(state, [...path, i], undefined);
192
+ }
193
+ }
194
+ }
195
+ else {
196
+ // Use generateReplacePatch for array length to include oldValue
197
+ generateReplacePatch(state, propPath, value, oldValue);
198
+ }
199
+ }
200
+ else if (isArrayType && typeof propForPath === 'number') {
201
+ // Array element replacement - could be:
202
+ // 1. Top-level tracked array item (state.items[0] = newItem) → NO id
203
+ // 2. Nested array inside tracked item (state.items[0].tags[1] = 'new') → INCLUDE parent item id
204
+ if (itemContext) {
205
+ // Nested array inside a tracked item - include the parent item's id
206
+ generateSetPatch(state, propPath, value, itemContext.item, itemContext.pathIndex);
207
+ }
208
+ else {
209
+ // Top-level tracked array item replacement - no id
210
+ generateSetPatch(state, propPath, value);
211
+ }
212
+ }
213
+ else if (itemContext) {
214
+ // Modifying a field inside an array item (e.g., state.items[0].name = 'new')
215
+ // or deeply nested (e.g., state.items[0].data.nested.value = 'new')
216
+ // Pass the array item for id extraction and itemPathIndex
217
+ generateSetPatch(state, propPath, value, itemContext.item, itemContext.pathIndex);
70
218
  }
71
219
  else {
72
- generateSetPatch(state, propPath, oldValue, value);
220
+ // Regular property modification
221
+ generateSetPatch(state, propPath, value);
73
222
  }
74
223
  return true;
75
224
  },
@@ -86,8 +235,10 @@ export function createProxy(target, path, state) {
86
235
  const propPath = [...path, prop];
87
236
  if (oldValue !== undefined || Object.prototype.hasOwnProperty.call(obj, prop)) {
88
237
  delete obj[prop];
89
- // Generate patch
90
- generateDeletePatch(state, propPath, oldValue);
238
+ // Find array item context for getItemId
239
+ const itemContext = findArrayItemContext(path, state);
240
+ // Generate patch with item context if we're inside an array item
241
+ generateDeletePatch(state, propPath, oldValue, itemContext?.item, itemContext?.pathIndex);
91
242
  }
92
243
  return true;
93
244
  },
package/dist/proxy.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sets.d.ts","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAIzD;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EACb,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,GAAG,CAkEL"}
1
+ {"version":3,"file":"sets.d.ts","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAKzD;;;GAGG;AACH,wBAAgB,YAAY,CAC3B,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,EACb,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,GAAG,CAyEL"}
package/dist/sets.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { findArrayItemContext } from './proxy.js';
1
2
  import { generateAddPatch, generateDeletePatch } from './patches.js';
2
3
  import { cloneIfNeeded } from './utils.js';
3
4
  /**
@@ -19,7 +20,9 @@ export function handleSetGet(obj, prop, path, state) {
19
20
  // Generate patch only if value didn't exist
20
21
  if (!existed) {
21
22
  const itemPath = [...path, value];
22
- generateAddPatch(state, itemPath, cloneIfNeeded(value));
23
+ // Find parent item context if this Set is inside a tracked array item
24
+ const itemContext = findArrayItemContext(path, state);
25
+ generateAddPatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex);
23
26
  }
24
27
  return result;
25
28
  };
@@ -31,7 +34,9 @@ export function handleSetGet(obj, prop, path, state) {
31
34
  // Generate patch only if value existed
32
35
  if (existed) {
33
36
  const itemPath = [...path, value];
34
- generateDeletePatch(state, itemPath, cloneIfNeeded(value));
37
+ // Find parent item context if this Set is inside a tracked array item
38
+ const itemContext = findArrayItemContext(path, state);
39
+ generateDeletePatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex);
35
40
  }
36
41
  return result;
37
42
  };
@@ -40,10 +45,12 @@ export function handleSetGet(obj, prop, path, state) {
40
45
  return () => {
41
46
  const values = Array.from(obj.values());
42
47
  obj.clear();
48
+ // Find parent item context if this Set is inside a tracked array item
49
+ const itemContext = findArrayItemContext(path, state);
43
50
  // Generate remove patches for all items
44
51
  values.forEach((value) => {
45
52
  const itemPath = [...path, value];
46
- generateDeletePatch(state, itemPath, cloneIfNeeded(value));
53
+ generateDeletePatch(state, itemPath, cloneIfNeeded(value), itemContext?.item, itemContext?.pathIndex);
47
54
  });
48
55
  };
49
56
  }
package/dist/sets.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"sets.js","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,gBAAgB,EAAE,mBAAmB,EAAC,MAAM,cAAc,CAAC;AACnE,OAAO,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC3B,GAAa,EACb,IAAqB,EACrB,IAAe,EACf,KAAyB;IAEzB,gEAAgE;IAChE,2DAA2D;IAC3D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,KAAU,EAAE,EAAE;YACrB,sEAAsE;YACtE,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAE9B,4CAA4C;YAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YACzD,CAAC;YAED,OAAO,MAAM,CAAC;QACf,CAAC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,CAAC,KAAU,EAAE,EAAE;YACrB,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEjC,uCAAuC;YACvC,IAAI,OAAO,EAAE,CAAC;gBACb,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5D,CAAC;YAED,OAAO,MAAM,CAAC;QACf,CAAC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,GAAG,EAAE;YACX,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACxC,GAAG,CAAC,KAAK,EAAE,CAAC;YAEZ,wCAAwC;YACxC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBACxB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;YAC5D,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAE3E,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB;IAChB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC;IACjB,CAAC;IAED,4BAA4B;IAC5B,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
1
+ {"version":3,"file":"sets.js","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,oBAAoB,EAAC,MAAM,YAAY,CAAC;AAChD,OAAO,EAAC,gBAAgB,EAAE,mBAAmB,EAAC,MAAM,cAAc,CAAC;AACnE,OAAO,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC3B,GAAa,EACb,IAAqB,EACrB,IAAe,EACf,KAAyB;IAEzB,gEAAgE;IAChE,2DAA2D;IAC3D,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACpB,OAAO,CAAC,KAAU,EAAE,EAAE;YACrB,sEAAsE;YACtE,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAE9B,4CAA4C;YAC5C,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,sEAAsE;gBACtE,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACtD,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;YACpG,CAAC;YAED,OAAO,MAAM,CAAC;QACf,CAAC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,CAAC,KAAU,EAAE,EAAE;YACrB,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAEjC,uCAAuC;YACvC,IAAI,OAAO,EAAE,CAAC;gBACb,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,sEAAsE;gBACtE,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACtD,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;YACvG,CAAC;YAED,OAAO,MAAM,CAAC;QACf,CAAC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,GAAG,EAAE;YACX,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;YACxC,GAAG,CAAC,KAAK,EAAE,CAAC;YAEZ,sEAAsE;YACtE,MAAM,WAAW,GAAG,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAEtD,wCAAwC;YACxC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBACxB,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAY,CAAC,CAAC;gBACzC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;YACvG,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC;IACH,CAAC;IAED,uBAAuB;IACvB,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAE3E,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB;IAChB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,GAAG,CAAC,IAAI,CAAC;IACjB,CAAC;IAED,4BAA4B;IAC5B,OAAQ,GAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
package/dist/types.d.ts CHANGED
@@ -15,36 +15,97 @@ export type GetItemIdConfig = {
15
15
  [key: string]: GetItemIdFunction | GetItemIdConfig;
16
16
  };
17
17
  export type PatchPath = (string | number | symbol | object)[];
18
- export type Patch = {
18
+ /**
19
+ * Item identity information.
20
+ * Always includes both id and pathIndex together when present.
21
+ * Use `patch.path.slice(0, patch.pathIndex)` to get the path to the item.
22
+ */
23
+ interface PatchWithItemId {
24
+ /**
25
+ * ID of the item being modified.
26
+ * Populated when getItemId option is configured and a field inside an array item is modified.
27
+ */
28
+ id: string | number;
29
+ /**
30
+ * Index indicating where in the path the item that `id` refers to ends.
31
+ *
32
+ * @example
33
+ * // For path ['items', 0, 'data', 'nested', 'value'] with pathIndex 2
34
+ * // The item path is ['items', 0]
35
+ */
36
+ pathIndex: number;
37
+ }
38
+ /**
39
+ * Patch without item identity information.
40
+ */
41
+ interface PatchWithoutItemId {
42
+ id?: undefined;
43
+ pathIndex?: undefined;
44
+ }
45
+ /**
46
+ * Base patch structure shared by all operations
47
+ */
48
+ interface BasePatch {
19
49
  path: PatchPath;
20
- op: PatchOp;
21
- value?: any;
50
+ }
51
+ /**
52
+ * Add operation - adding a new value.
53
+ * Includes item identity when adding a field TO an existing array item (the item is being modified).
54
+ * Does NOT include item identity when adding a new item to an array.
55
+ */
56
+ export type AddPatch = BasePatch & {
57
+ op: typeof Operation.Add;
58
+ value: any;
59
+ } & (PatchWithItemId | PatchWithoutItemId);
60
+ /**
61
+ * Remove operation - removing a value.
62
+ * Includes item identity when removing a field FROM an array item (not when removing the item itself).
63
+ */
64
+ export type RemovePatch = BasePatch & {
65
+ op: typeof Operation.Remove;
66
+ } & (PatchWithItemId | PatchWithoutItemId);
67
+ /**
68
+ * Replace operation - replacing a value.
69
+ * Includes oldValue for array length changes.
70
+ * Includes item identity when modifying a field inside an array item.
71
+ */
72
+ export type ReplacePatch = BasePatch & {
73
+ op: typeof Operation.Replace;
74
+ value: any;
22
75
  /**
23
- * Optional previous value for replace operations on array length.
76
+ * Previous value for replace operations on array length.
24
77
  * Enables consumers to detect how many elements were removed without pre-snapshotting state.
25
78
  */
26
79
  oldValue?: unknown;
27
- /**
28
- * Optional ID of the item being removed or replaced.
29
- * Populated when getItemId option is configured for the item's parent path.
30
- */
31
- id?: string | number;
32
- };
80
+ } & (PatchWithItemId | PatchWithoutItemId);
81
+ /**
82
+ * Union of all patch types.
83
+ * - AddPatch: Adding new values (no item identity)
84
+ * - RemovePatch: Removing values (has item identity when removing a field from an item)
85
+ * - ReplacePatch: Replacing values (has item identity when modifying a field inside an item)
86
+ */
87
+ export type Patch = AddPatch | RemovePatch | ReplacePatch;
33
88
  export type Patches = Patch[];
34
89
  export type NonPrimitive = object | Array<unknown>;
90
+ /**
91
+ * Configuration options for recordPatches.
92
+ */
35
93
  export interface RecordPatchesOptions {
36
- /**
37
- * Include array length in patches (default: true)
38
- */
39
- arrayLengthAssignment?: boolean;
40
94
  /**
41
95
  * Compress patches by merging redundant operations (default: true)
42
96
  */
43
97
  compressPatches?: boolean;
44
98
  /**
45
- * Configuration for extracting item IDs for remove/replace patches.
99
+ * Include array length in patches (default: true)
100
+ */
101
+ arrayLengthAssignment?: boolean;
102
+ /**
103
+ * Configuration for extracting item IDs for replace patches on individual items.
46
104
  * Maps paths to functions that extract IDs from item values.
47
105
  *
106
+ * Note: Item IDs are only included when an item itself is modified (replaced),
107
+ * not when items are removed or the array length changes.
108
+ *
48
109
  * @example
49
110
  * ```typescript
50
111
  * recordPatches(state, mutate, {
@@ -70,4 +131,5 @@ export interface RecorderState<T extends NonPrimitive> {
70
131
  */
71
132
  proxyCache: WeakMap<object, any>;
72
133
  }
134
+ export {};
73
135
  //# sourceMappingURL=types.d.ts.map