patch-recorder 0.0.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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/dist/arrays.d.ts +6 -0
  4. package/dist/arrays.d.ts.map +1 -0
  5. package/dist/arrays.js +143 -0
  6. package/dist/arrays.js.map +1 -0
  7. package/dist/index.d.ts +21 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +44 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/maps.d.ts +7 -0
  12. package/dist/maps.d.ts.map +1 -0
  13. package/dist/maps.js +96 -0
  14. package/dist/maps.js.map +1 -0
  15. package/dist/optimizer.d.ts +7 -0
  16. package/dist/optimizer.d.ts.map +1 -0
  17. package/dist/optimizer.js +123 -0
  18. package/dist/optimizer.js.map +1 -0
  19. package/dist/patches.d.ts +18 -0
  20. package/dist/patches.d.ts.map +1 -0
  21. package/dist/patches.js +46 -0
  22. package/dist/patches.js.map +1 -0
  23. package/dist/proxy.d.ts +3 -0
  24. package/dist/proxy.d.ts.map +1 -0
  25. package/dist/proxy.js +127 -0
  26. package/dist/proxy.js.map +1 -0
  27. package/dist/sets.d.ts +7 -0
  28. package/dist/sets.d.ts.map +1 -0
  29. package/dist/sets.js +78 -0
  30. package/dist/sets.js.map +1 -0
  31. package/dist/types.d.ts +55 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +6 -0
  34. package/dist/types.js.map +1 -0
  35. package/dist/utils.d.ts +33 -0
  36. package/dist/utils.d.ts.map +1 -0
  37. package/dist/utils.js +132 -0
  38. package/dist/utils.js.map +1 -0
  39. package/package.json +60 -0
  40. package/src/arrays.ts +191 -0
  41. package/src/index.ts +71 -0
  42. package/src/maps.ts +120 -0
  43. package/src/optimizer.ts +136 -0
  44. package/src/patches.ts +67 -0
  45. package/src/proxy.ts +163 -0
  46. package/src/sets.ts +100 -0
  47. package/src/types.ts +67 -0
  48. package/src/utils.ts +150 -0
package/dist/maps.js ADDED
@@ -0,0 +1,96 @@
1
+ import { createProxy } from './proxy.js';
2
+ import { generateAddPatch, generateDeletePatch, generateReplacePatch } from './patches.js';
3
+ import { cloneIfNeeded, isMap, isArray } from './utils.js';
4
+ /**
5
+ * Handle property access on Map objects
6
+ * Wraps mutating methods (set, delete, clear) to generate patches
7
+ */
8
+ export function handleMapGet(obj, prop, path, state) {
9
+ // Skip symbol properties
10
+ if (typeof prop === 'symbol') {
11
+ return obj[prop];
12
+ }
13
+ // Mutating methods
14
+ if (prop === 'set') {
15
+ return (key, value) => {
16
+ // Check if key existed BEFORE mutation
17
+ const existed = keyExistsInOriginal(state.original, path, key);
18
+ const oldValue = obj.get(key);
19
+ const result = obj.set(key, value);
20
+ // Generate patch
21
+ const itemPath = [...path, key];
22
+ if (existed) {
23
+ // Key exists - replace
24
+ generateReplacePatch(state, itemPath, cloneIfNeeded(value));
25
+ }
26
+ else {
27
+ // Key doesn't exist - add
28
+ generateAddPatch(state, itemPath, cloneIfNeeded(value));
29
+ }
30
+ return result;
31
+ };
32
+ }
33
+ if (prop === 'delete') {
34
+ return (key) => {
35
+ const oldValue = obj.get(key);
36
+ const result = obj.delete(key);
37
+ if (result) {
38
+ const itemPath = [...path, key];
39
+ generateDeletePatch(state, itemPath, cloneIfNeeded(oldValue));
40
+ }
41
+ return result;
42
+ };
43
+ }
44
+ if (prop === 'clear') {
45
+ return () => {
46
+ const entries = Array.from(obj.entries());
47
+ obj.clear();
48
+ // Generate remove patches for all items
49
+ entries.forEach(([key, value]) => {
50
+ const itemPath = [...path, key];
51
+ generateDeletePatch(state, itemPath, cloneIfNeeded(value));
52
+ });
53
+ };
54
+ }
55
+ // Non-mutating methods
56
+ if (prop === 'get') {
57
+ return (key) => {
58
+ const value = obj.get(key);
59
+ // If the value is a Map, Array, or object, return a proxy
60
+ if (value != null && typeof value === 'object') {
61
+ if (isMap(value) || isArray(value)) {
62
+ return createProxy(value, [...path, key], state);
63
+ }
64
+ }
65
+ return value;
66
+ };
67
+ }
68
+ const nonMutatingMethods = ['has', 'keys', 'values', 'entries', 'forEach'];
69
+ if (nonMutatingMethods.includes(prop)) {
70
+ return obj[prop].bind(obj);
71
+ }
72
+ // Size property
73
+ if (prop === 'size') {
74
+ return obj.size;
75
+ }
76
+ // Return any other property
77
+ return obj[prop];
78
+ }
79
+ /**
80
+ * Navigate to the original Map at the given path and check if a key exists
81
+ * This is needed to check if a key existed before mutations
82
+ */
83
+ function keyExistsInOriginal(original, path, key) {
84
+ let current = original;
85
+ for (const part of path) {
86
+ if (current == null)
87
+ return false;
88
+ current = current[part];
89
+ }
90
+ // If we reached a Map, check if the key exists
91
+ if (current instanceof Map) {
92
+ return current.has(key);
93
+ }
94
+ return false;
95
+ }
96
+ //# sourceMappingURL=maps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maps.js","sourceRoot":"","sources":["../src/maps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Patches } from './types.js';
2
+ /**
3
+ * Compress patches by merging redundant operations
4
+ * This handles both consecutive and interleaved operations on the same path
5
+ */
6
+ export declare function compressPatches(patches: Patches<true>): Patches<true>;
7
+ //# sourceMappingURL=optimizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.d.ts","sourceRoot":"","sources":["../src/optimizer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AAExC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCrE"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Compress patches by merging redundant operations
3
+ * This handles both consecutive and interleaved operations on the same path
4
+ */
5
+ export function compressPatches(patches) {
6
+ if (patches.length === 0) {
7
+ return patches;
8
+ }
9
+ // Use a Map to track the latest operation for each path
10
+ // Key: JSON stringified path, Value: the latest patch for that path
11
+ const pathMap = new Map();
12
+ for (const patch of patches) {
13
+ const pathKey = JSON.stringify(patch.path);
14
+ const existing = pathMap.get(pathKey);
15
+ if (!existing) {
16
+ // First operation on this path
17
+ pathMap.set(pathKey, patch);
18
+ continue;
19
+ }
20
+ // Merge with existing operation based on operation types
21
+ const merged = mergePatches(existing, patch);
22
+ if (merged) {
23
+ // Update with merged result (or null if they cancel out)
24
+ if (merged !== null) {
25
+ pathMap.set(pathKey, merged);
26
+ }
27
+ else {
28
+ // Operations canceled each other out
29
+ pathMap.delete(pathKey);
30
+ }
31
+ }
32
+ else {
33
+ // Can't merge, keep the new operation
34
+ pathMap.set(pathKey, patch);
35
+ }
36
+ }
37
+ // Convert Map back to array
38
+ return Array.from(pathMap.values());
39
+ }
40
+ /**
41
+ * Merge two patches on the same path
42
+ * Returns the merged patch, or null if they cancel out, or undefined if they can't be merged
43
+ */
44
+ function mergePatches(patch1, patch2) {
45
+ const op1 = patch1.op;
46
+ const op2 = patch2.op;
47
+ // Same operations - keep the latest one
48
+ if (op1 === op2) {
49
+ // For replace operations, keep the latest value
50
+ if (op1 === 'replace') {
51
+ // Skip if same value (no-op)
52
+ if (valuesEqual(patch1.value, patch2.value)) {
53
+ return patch1;
54
+ }
55
+ return patch2;
56
+ }
57
+ // For add operations, if adding the same value, it's a no-op
58
+ if (op1 === 'add' && valuesEqual(patch1.value, patch2.value)) {
59
+ return patch1;
60
+ }
61
+ // For remove operations, keep the latest
62
+ if (op1 === 'remove') {
63
+ return patch2;
64
+ }
65
+ }
66
+ // Different operations
67
+ if (op1 === 'add' && op2 === 'replace') {
68
+ // Add then replace - just keep the replace
69
+ return patch2;
70
+ }
71
+ if (op1 === 'replace' && op2 === 'replace') {
72
+ // Replace then replace - keep the latest
73
+ return patch2;
74
+ }
75
+ if (op1 === 'replace' && op2 === 'remove') {
76
+ // Replace then delete - just keep the delete
77
+ return patch2;
78
+ }
79
+ if (op1 === 'add' && op2 === 'remove') {
80
+ // Add then remove - they cancel out
81
+ return null;
82
+ }
83
+ if (op1 === 'remove' && op2 === 'add') {
84
+ // Remove then add - keep the add
85
+ return patch2;
86
+ }
87
+ // Can't merge these operations
88
+ return undefined;
89
+ }
90
+ /**
91
+ * Check if two values are equal (deep comparison)
92
+ */
93
+ function valuesEqual(val1, val2) {
94
+ if (val1 === val2)
95
+ return true;
96
+ // Handle null/undefined
97
+ if (val1 == null || val2 == null)
98
+ return val1 === val2;
99
+ // Handle arrays
100
+ if (Array.isArray(val1) && Array.isArray(val2)) {
101
+ if (val1.length !== val2.length)
102
+ return false;
103
+ for (let i = 0; i < val1.length; i++) {
104
+ if (!valuesEqual(val1[i], val2[i]))
105
+ return false;
106
+ }
107
+ return true;
108
+ }
109
+ // Handle objects
110
+ if (typeof val1 === 'object' && typeof val2 === 'object') {
111
+ const keys1 = Object.keys(val1);
112
+ const keys2 = Object.keys(val2);
113
+ if (keys1.length !== keys2.length)
114
+ return false;
115
+ for (const key of keys1) {
116
+ if (!valuesEqual(val1[key], val2[key]))
117
+ return false;
118
+ }
119
+ return true;
120
+ }
121
+ return false;
122
+ }
123
+ //# sourceMappingURL=optimizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optimizer.js","sourceRoot":"","sources":["../src/optimizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { RecorderState } from './types.js';
2
+ /**
3
+ * Generate a replace patch for property changes
4
+ */
5
+ export declare function generateSetPatch(state: RecorderState<any>, path: (string | number)[], oldValue: any, newValue: any): void;
6
+ /**
7
+ * Generate a remove patch for property deletions
8
+ */
9
+ export declare function generateDeletePatch(state: RecorderState<any>, path: (string | number)[], oldValue: any): void;
10
+ /**
11
+ * Generate an add patch for new properties
12
+ */
13
+ export declare function generateAddPatch(state: RecorderState<any>, path: (string | number)[], value: any): void;
14
+ /**
15
+ * Generate a replace patch for full object/array replacement
16
+ */
17
+ export declare function generateReplacePatch(state: RecorderState<any>, path: (string | number)[], value: any): void;
18
+ //# sourceMappingURL=patches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patches.d.ts","sourceRoot":"","sources":["../src/patches.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAI9C;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,QAAQ,EAAE,GAAG,EACb,QAAQ,EAAE,GAAG,QASb;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,QAAQ,EAAE,GAAG,QAQb;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,QAQhG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,EACzB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,KAAK,EAAE,GAAG,QASV"}
@@ -0,0 +1,46 @@
1
+ import { Operation } from './types.js';
2
+ import { formatPath, cloneIfNeeded } from './utils.js';
3
+ /**
4
+ * Generate a replace patch for property changes
5
+ */
6
+ export function generateSetPatch(state, path, oldValue, newValue) {
7
+ const patch = {
8
+ op: Operation.Replace,
9
+ path: formatPath(path, state.options),
10
+ value: cloneIfNeeded(newValue),
11
+ };
12
+ state.patches.push(patch);
13
+ }
14
+ /**
15
+ * Generate a remove patch for property deletions
16
+ */
17
+ export function generateDeletePatch(state, path, oldValue) {
18
+ const patch = {
19
+ op: Operation.Remove,
20
+ path: formatPath(path, state.options),
21
+ };
22
+ state.patches.push(patch);
23
+ }
24
+ /**
25
+ * Generate an add patch for new properties
26
+ */
27
+ export function generateAddPatch(state, path, value) {
28
+ const patch = {
29
+ op: Operation.Add,
30
+ path: formatPath(path, state.options),
31
+ value: cloneIfNeeded(value),
32
+ };
33
+ state.patches.push(patch);
34
+ }
35
+ /**
36
+ * Generate a replace patch for full object/array replacement
37
+ */
38
+ export function generateReplacePatch(state, path, value) {
39
+ const patch = {
40
+ op: Operation.Replace,
41
+ path: formatPath(path, state.options),
42
+ value: cloneIfNeeded(value),
43
+ };
44
+ state.patches.push(patch);
45
+ }
46
+ //# sourceMappingURL=patches.js.map
@@ -0,0 +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,UAAU,EAAE,aAAa,EAAC,MAAM,YAAY,CAAC;AAErD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC/B,KAAyB,EACzB,IAAyB,EACzB,QAAa,EACb,QAAa;IAEb,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,SAAS,CAAC,OAAO;QACrB,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;QACrC,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC;KAC9B,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAClC,KAAyB,EACzB,IAAyB,EACzB,QAAa;IAEb,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,SAAS,CAAC,MAAM;QACpB,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;KACrC,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAyB,EAAE,IAAyB,EAAE,KAAU;IAChG,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,SAAS,CAAC,GAAG;QACjB,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;QACrC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;KAC3B,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CACnC,KAAyB,EACzB,IAAyB,EACzB,KAAU;IAEV,MAAM,KAAK,GAAG;QACb,EAAE,EAAE,SAAS,CAAC,OAAO;QACrB,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;QACrC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC;KAC3B,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RecorderState } from './types.js';
2
+ export declare function createProxy<T extends object>(target: T, path: (string | number)[], state: RecorderState<any>): T;
3
+ //# sourceMappingURL=proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAO9C,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAC3C,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,CAAC,CAuJH"}
package/dist/proxy.js ADDED
@@ -0,0 +1,127 @@
1
+ import { generateSetPatch, generateDeletePatch, generateAddPatch } from './patches.js';
2
+ import { isArray, isMap, isSet } from './utils.js';
3
+ import { handleArrayGet } from './arrays.js';
4
+ import { handleMapGet } from './maps.js';
5
+ import { handleSetGet } from './sets.js';
6
+ export function createProxy(target, path, state) {
7
+ const isArrayType = isArray(target);
8
+ const isMapType = isMap(target);
9
+ const isSetType = isSet(target);
10
+ const handler = {
11
+ get(obj, prop) {
12
+ // Handle array methods
13
+ if (isArrayType && typeof prop === 'string') {
14
+ return handleArrayGet(obj, prop, path, state);
15
+ }
16
+ // Handle Map methods
17
+ if (isMapType) {
18
+ return handleMapGet(obj, prop, path, state);
19
+ }
20
+ // Handle Set methods
21
+ if (isSetType) {
22
+ return handleSetGet(obj, prop, path, state);
23
+ }
24
+ // Handle property access
25
+ const value = obj[prop];
26
+ // Skip creating proxies for primitive values and special cases
27
+ if (typeof value !== 'object' || value === null) {
28
+ return value;
29
+ }
30
+ // Create nested proxy for draftable values
31
+ // Only include string | number in path, skip symbols
32
+ if (typeof prop === 'string' || typeof prop === 'number') {
33
+ return createProxy(value, [...path, prop], state);
34
+ }
35
+ return value;
36
+ },
37
+ set(obj, prop, value) {
38
+ // Map and Set don't support direct property assignment
39
+ if (isMapType || isSetType) {
40
+ throw new Error('Map/Set draft does not support any property assignment.');
41
+ }
42
+ const oldValue = obj[prop];
43
+ // Only create path for string | number props, skip symbols
44
+ if (typeof prop !== 'string' && typeof prop !== 'number') {
45
+ obj[prop] = value;
46
+ return true;
47
+ }
48
+ // Convert numeric string props to numbers for array indices
49
+ const propForPath = typeof prop === 'string' && !isNaN(Number(prop)) ? Number(prop) : prop;
50
+ const propPath = [...path, propForPath];
51
+ // Skip if no actual change (handle undefined as a valid value)
52
+ if (oldValue === value &&
53
+ (value !== undefined || Object.prototype.hasOwnProperty.call(obj, prop))) {
54
+ return true;
55
+ }
56
+ // Determine if this is an add or replace operation by checking the original state
57
+ let originalHasProperty = false;
58
+ let originalValue = undefined;
59
+ // Navigate to the original object at this path
60
+ let currentOriginal = state.original;
61
+ for (let i = 0; i < path.length; i++) {
62
+ currentOriginal = currentOriginal[path[i]];
63
+ if (currentOriginal === undefined || currentOriginal === null) {
64
+ break;
65
+ }
66
+ }
67
+ if (currentOriginal && currentOriginal !== undefined && currentOriginal !== null) {
68
+ originalHasProperty = Object.prototype.hasOwnProperty.call(currentOriginal, prop);
69
+ originalValue = currentOriginal[prop];
70
+ }
71
+ // Mutate original immediately
72
+ obj[prop] = value;
73
+ // Generate patch
74
+ if (!originalHasProperty) {
75
+ generateAddPatch(state, propPath, value);
76
+ }
77
+ else {
78
+ generateSetPatch(state, propPath, originalValue, value);
79
+ }
80
+ return true;
81
+ },
82
+ deleteProperty(obj, prop) {
83
+ if (isArrayType) {
84
+ // For arrays, delete is equivalent to setting to undefined
85
+ return handler.set(obj, prop, undefined, obj);
86
+ }
87
+ // Map and Set don't support deleteProperty
88
+ if (isMapType || isSetType) {
89
+ throw new Error('Map/Set draft does not support deleteProperty.');
90
+ }
91
+ const oldValue = obj[prop];
92
+ // Only create path for string | number props, skip symbols
93
+ if (typeof prop !== 'string' && typeof prop !== 'number') {
94
+ delete obj[prop];
95
+ return true;
96
+ }
97
+ const propPath = [...path, prop];
98
+ if (oldValue !== undefined || Object.prototype.hasOwnProperty.call(obj, prop)) {
99
+ delete obj[prop];
100
+ // Generate patch
101
+ generateDeletePatch(state, propPath, oldValue);
102
+ }
103
+ return true;
104
+ },
105
+ has(obj, prop) {
106
+ return prop in obj;
107
+ },
108
+ ownKeys(obj) {
109
+ return Reflect.ownKeys(obj);
110
+ },
111
+ getOwnPropertyDescriptor(obj, prop) {
112
+ const descriptor = Reflect.getOwnPropertyDescriptor(obj, prop);
113
+ if (!descriptor)
114
+ return descriptor;
115
+ return {
116
+ ...descriptor,
117
+ writable: true,
118
+ configurable: true,
119
+ };
120
+ },
121
+ getPrototypeOf(obj) {
122
+ return Reflect.getPrototypeOf(obj);
123
+ },
124
+ };
125
+ return new Proxy(target, handler);
126
+ }
127
+ //# sourceMappingURL=proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
package/dist/sets.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { RecorderState } from './types.js';
2
+ /**
3
+ * Handle property access on Set objects
4
+ * Wraps mutating methods (add, delete, clear) to generate patches
5
+ */
6
+ export declare function handleSetGet<T = any>(obj: Set<T>, prop: string | symbol, path: (string | number)[], state: RecorderState<any>): any;
7
+ //# sourceMappingURL=sets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sets.d.ts","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,YAAY,CAAC;AAM9C;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,GAAG,EACnC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EACX,IAAI,EAAE,MAAM,GAAG,MAAM,EACrB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,EACzB,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,GACvB,GAAG,CAiEL"}
package/dist/sets.js ADDED
@@ -0,0 +1,78 @@
1
+ import { generateAddPatch, generateDeletePatch } from './patches.js';
2
+ import { cloneIfNeeded } from './utils.js';
3
+ /**
4
+ * Handle property access on Set objects
5
+ * Wraps mutating methods (add, delete, clear) to generate patches
6
+ */
7
+ export function handleSetGet(obj, prop, path, state) {
8
+ // Skip symbol properties
9
+ if (typeof prop === 'symbol') {
10
+ return obj[prop];
11
+ }
12
+ // Mutating methods
13
+ if (prop === 'add') {
14
+ return (value) => {
15
+ // Check if value existed BEFORE mutation
16
+ const existed = valueExistsInOriginal(state.original, path, value);
17
+ const result = obj.add(value);
18
+ // Generate patch only if value didn't exist
19
+ if (!existed) {
20
+ const itemPath = [...path, value];
21
+ generateAddPatch(state, itemPath, cloneIfNeeded(value));
22
+ }
23
+ return result;
24
+ };
25
+ }
26
+ if (prop === 'delete') {
27
+ return (value) => {
28
+ const existed = obj.has(value);
29
+ const result = obj.delete(value);
30
+ // Generate patch only if value existed
31
+ if (existed) {
32
+ const itemPath = [...path, value];
33
+ generateDeletePatch(state, itemPath, cloneIfNeeded(value));
34
+ }
35
+ return result;
36
+ };
37
+ }
38
+ if (prop === 'clear') {
39
+ return () => {
40
+ const values = Array.from(obj.values());
41
+ obj.clear();
42
+ // Generate remove patches for all items
43
+ values.forEach((value) => {
44
+ const itemPath = [...path, value];
45
+ generateDeletePatch(state, itemPath, cloneIfNeeded(value));
46
+ });
47
+ };
48
+ }
49
+ // Non-mutating methods
50
+ const nonMutatingMethods = ['has', 'keys', 'values', 'entries', 'forEach'];
51
+ if (nonMutatingMethods.includes(prop)) {
52
+ return obj[prop].bind(obj);
53
+ }
54
+ // Size property
55
+ if (prop === 'size') {
56
+ return obj.size;
57
+ }
58
+ // Return any other property
59
+ return obj[prop];
60
+ }
61
+ /**
62
+ * Navigate to the original Set at the given path and check if a value exists
63
+ * This is needed to check if a value existed before mutations
64
+ */
65
+ function valueExistsInOriginal(original, path, value) {
66
+ let current = original;
67
+ for (const part of path) {
68
+ if (current == null)
69
+ return false;
70
+ current = current[part];
71
+ }
72
+ // If we reached a Set, check if the value exists
73
+ if (current instanceof Set) {
74
+ return current.has(value);
75
+ }
76
+ return false;
77
+ }
78
+ //# sourceMappingURL=sets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sets.js","sourceRoot":"","sources":["../src/sets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ export declare const Operation: {
2
+ readonly Remove: "remove";
3
+ readonly Replace: "replace";
4
+ readonly Add: "add";
5
+ };
6
+ export type PatchOp = (typeof Operation)[keyof typeof Operation];
7
+ export type PatchesOptions = boolean | {
8
+ /**
9
+ * The default value is `true`. If it's `true`, the path will be an array, otherwise it is a string.
10
+ */
11
+ pathAsArray?: boolean;
12
+ /**
13
+ * The default value is `true`. If it's `true`, the array length will be included in the patches, otherwise no include array length.
14
+ */
15
+ arrayLengthAssignment?: boolean;
16
+ };
17
+ export interface IPatch {
18
+ op: PatchOp;
19
+ value?: any;
20
+ }
21
+ export type Patch<P extends PatchesOptions = any> = P extends {
22
+ pathAsArray: false;
23
+ } ? IPatch & {
24
+ path: string;
25
+ } : P extends true | object ? IPatch & {
26
+ path: (string | number)[];
27
+ } : IPatch & {
28
+ path: string | (string | number)[];
29
+ };
30
+ export type Patches<P extends PatchesOptions = any> = Patch<P>[];
31
+ export type NonPrimitive = object | Array<unknown>;
32
+ export interface RecordPatchesOptions {
33
+ /**
34
+ * Return paths as arrays (default: true) or strings
35
+ */
36
+ pathAsArray?: boolean;
37
+ /**
38
+ * Include array length in patches (default: true)
39
+ */
40
+ arrayLengthAssignment?: boolean;
41
+ /**
42
+ * Optimize patches by merging redundant operations (default: false)
43
+ */
44
+ optimize?: boolean;
45
+ }
46
+ export type Draft<T> = T;
47
+ export interface RecorderState<T> {
48
+ original: T;
49
+ patches: Patches<any>;
50
+ basePath: (string | number)[];
51
+ options: RecordPatchesOptions & {
52
+ internalPatchesOptions: PatchesOptions;
53
+ };
54
+ }
55
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +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,MAAM,MAAM,cAAc,GACvB,OAAO,GACP;IACA;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEL,MAAM,WAAW,MAAM;IACtB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,IAAI,CAAC,SAAS;IAC7D,WAAW,EAAE,KAAK,CAAC;CACnB,GACE,MAAM,GAAG;IACT,IAAI,EAAE,MAAM,CAAC;CACb,GACA,CAAC,SAAS,IAAI,GAAG,MAAM,GACtB,MAAM,GAAG;IACT,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CAC1B,GACA,MAAM,GAAG;IACT,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;CACnC,CAAC;AAEL,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,cAAc,GAAG,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAEjE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;AAEnD,MAAM,WAAW,oBAAoB;IACpC;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC;AAEzB,MAAM,WAAW,aAAa,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACtB,QAAQ,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC9B,OAAO,EAAE,oBAAoB,GAAG;QAAC,sBAAsB,EAAE,cAAc,CAAA;KAAC,CAAC;CACzE"}
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ export const Operation = {
2
+ Remove: 'remove',
3
+ Replace: 'replace',
4
+ Add: 'add',
5
+ };
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;IACxB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,GAAG,EAAE,KAAK;CACD,CAAC"}