@tanstack/optimistic
Version:
Core optimistic updates library
1 lines • 51.7 kB
Source Map (JSON)
{"version":3,"file":"proxy.cjs","sources":["../../src/proxy.ts"],"sourcesContent":["/**\n * A utility for creating a proxy that captures changes to an object\n * and provides a way to retrieve those changes.\n */\n\n/**\n * Simple debug utility that only logs when debug mode is enabled\n * Set DEBUG to true in localStorage to enable debug logging\n */\nfunction debugLog(...args: Array<unknown>): void {\n // Check if we're in a browser environment\n const isBrowser =\n typeof window !== `undefined` && typeof localStorage !== `undefined`\n\n // In browser, check localStorage for debug flag\n if (isBrowser && localStorage.getItem(`DEBUG`) === `true`) {\n console.log(`[proxy]`, ...args)\n }\n // In Node.js environment, check for environment variable (though this is primarily for browser)\n else if (\n !isBrowser &&\n typeof process !== `undefined` &&\n process.env.DEBUG === `true`\n ) {\n console.log(`[proxy]`, ...args)\n }\n}\n\n// Add TypedArray interface with proper type\ninterface TypedArray {\n length: number\n [index: number]: number\n}\n\n// Update type for ChangeTracker\ninterface ChangeTracker<T extends object> {\n changes: Record<string | symbol, unknown>\n originalObject: T\n modified: boolean\n copy_?: T\n assigned_: Record<string | symbol, boolean>\n parent?: {\n tracker: ChangeTracker<object>\n prop: string | symbol\n }\n target: T\n}\n\n/**\n * Deep clones an object while preserving special types like Date and RegExp\n */\n\nfunction deepClone<T extends unknown>(\n obj: T,\n visited = new WeakMap<object, unknown>()\n): T {\n // Handle null and undefined\n if (obj === null || obj === undefined) {\n return obj\n }\n\n // Handle primitive types\n if (typeof obj !== `object`) {\n return obj\n }\n\n // If we've already cloned this object, return the cached clone\n if (visited.has(obj as object)) {\n return visited.get(obj as object) as T\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as unknown as T\n }\n\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as unknown as T\n }\n\n if (Array.isArray(obj)) {\n const arrayClone = [] as Array<unknown>\n visited.set(obj as object, arrayClone)\n obj.forEach((item, index) => {\n arrayClone[index] = deepClone(item, visited)\n })\n return arrayClone as unknown as T\n }\n\n // Handle TypedArrays\n if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {\n // Get the constructor to create a new instance of the same type\n const TypedArrayConstructor = Object.getPrototypeOf(obj).constructor\n const clone = new TypedArrayConstructor(\n (obj as unknown as TypedArray).length\n ) as unknown as TypedArray\n visited.set(obj as object, clone)\n\n // Copy the values\n for (let i = 0; i < (obj as unknown as TypedArray).length; i++) {\n clone[i] = (obj as unknown as TypedArray)[i]!\n }\n\n return clone as unknown as T\n }\n\n if (obj instanceof Map) {\n const clone = new Map() as Map<unknown, unknown>\n visited.set(obj as object, clone)\n obj.forEach((value, key) => {\n clone.set(key, deepClone(value, visited))\n })\n return clone as unknown as T\n }\n\n if (obj instanceof Set) {\n const clone = new Set()\n visited.set(obj as object, clone)\n obj.forEach((value) => {\n clone.add(deepClone(value, visited))\n })\n return clone as unknown as T\n }\n\n const clone = {} as Record<string | symbol, unknown>\n visited.set(obj as object, clone)\n\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n clone[key] = deepClone(\n (obj as Record<string | symbol, unknown>)[key],\n visited\n )\n }\n }\n\n const symbolProps = Object.getOwnPropertySymbols(obj)\n for (const sym of symbolProps) {\n clone[sym] = deepClone(\n (obj as Record<string | symbol, unknown>)[sym],\n visited\n )\n }\n\n return clone as T\n}\n\n/**\n * Deep equality check that handles special types like Date, RegExp, Map, and Set\n */\nfunction deepEqual<T>(a: T, b: T): boolean {\n // Handle primitive types\n if (a === b) return true\n\n // If either is null or not an object, they're not equal\n if (\n a === null ||\n b === null ||\n typeof a !== `object` ||\n typeof b !== `object`\n ) {\n return false\n }\n\n // Handle Date objects\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime()\n }\n\n // Handle RegExp objects\n if (a instanceof RegExp && b instanceof RegExp) {\n return a.source === b.source && a.flags === b.flags\n }\n\n // Handle Map objects\n if (a instanceof Map && b instanceof Map) {\n if (a.size !== b.size) return false\n\n const entries = Array.from(a.entries())\n for (const [key, val] of entries) {\n if (!b.has(key) || !deepEqual(val, b.get(key))) {\n return false\n }\n }\n\n return true\n }\n\n // Handle Set objects\n if (a instanceof Set && b instanceof Set) {\n if (a.size !== b.size) return false\n\n // Convert to arrays for comparison\n const aValues = Array.from(a)\n const bValues = Array.from(b)\n\n // Simple comparison for primitive values\n if (aValues.every((val) => typeof val !== `object`)) {\n return aValues.every((val) => b.has(val))\n }\n\n // For objects in sets, we need to do a more complex comparison\n // This is a simplified approach and may not work for all cases\n return aValues.length === bValues.length\n }\n\n // Handle arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) return false\n }\n\n return true\n }\n\n // Handle TypedArrays\n if (\n ArrayBuffer.isView(a) &&\n ArrayBuffer.isView(b) &&\n !(a instanceof DataView) &&\n !(b instanceof DataView)\n ) {\n const typedA = a as unknown as TypedArray\n const typedB = b as unknown as TypedArray\n if (typedA.length !== typedB.length) return false\n\n for (let i = 0; i < typedA.length; i++) {\n if (typedA[i] !== typedB[i]) return false\n }\n\n return true\n }\n\n // Handle plain objects\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n\n if (keysA.length !== keysB.length) return false\n\n return keysA.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(b, key) &&\n deepEqual((a as any)[key], (b as any)[key])\n )\n}\n\n/**\n * Creates a proxy that tracks changes to the target object\n *\n * @param target The object to proxy\n * @param parent Optional parent information\n * @returns An object containing the proxy and a function to get the changes\n */\nexport function createChangeProxy<T extends object>(\n target: T,\n parent?: { tracker: ChangeTracker<object>; prop: string | symbol }\n): {\n proxy: T\n\n getChanges: () => Record<string | symbol, any>\n} {\n // Create a WeakMap to cache proxies for nested objects\n // This prevents creating multiple proxies for the same object\n // and handles circular references\n const proxyCache = new WeakMap<object, object>()\n\n // Create a change tracker to track changes to the object\n const changeTracker: ChangeTracker<T> = {\n changes: {},\n originalObject: deepClone(target), // Create a deep clone to preserve the original state\n modified: false,\n assigned_: {},\n parent,\n target, // Store reference to the target object\n }\n\n // Mark this object and all its ancestors as modified\n function markChanged(state: ChangeTracker<object>) {\n if (!state.modified) {\n state.modified = true\n\n // Propagate the change up the parent chain\n if (state.parent) {\n markChanged(state.parent.tracker)\n }\n }\n }\n\n // Check if all properties in the current state have reverted to original values\n function checkIfReverted(state: ChangeTracker<object>): boolean {\n debugLog(\n `checkIfReverted called with assigned keys:`,\n Object.keys(state.assigned_)\n )\n\n // If there are no assigned properties, object is unchanged\n if (\n Object.keys(state.assigned_).length === 0 &&\n Object.getOwnPropertySymbols(state.assigned_).length === 0\n ) {\n debugLog(`No assigned properties, returning true`)\n return true\n }\n\n // Check each assigned regular property\n for (const prop in state.assigned_) {\n // If this property is marked as assigned\n if (state.assigned_[prop] === true) {\n const currentValue = state.copy_ ? (state.copy_ as any)[prop] : null\n const originalValue = (state.originalObject as any)[prop]\n\n debugLog(\n `Checking property ${String(prop)}, current:`,\n currentValue,\n `original:`,\n originalValue\n )\n\n // If the value is not equal to original, something is still changed\n if (!deepEqual(currentValue, originalValue)) {\n debugLog(`Property ${String(prop)} is different, returning false`)\n return false\n }\n } else if (state.assigned_[prop] === false) {\n // Property was deleted, so it's different from original\n debugLog(`Property ${String(prop)} was deleted, returning false`)\n return false\n }\n }\n\n // Check each assigned symbol property\n const symbolProps = Object.getOwnPropertySymbols(state.assigned_)\n for (const sym of symbolProps) {\n if (state.assigned_[sym.toString()] === true) {\n const currentValue = state.copy_ ? (state.copy_ as any)[sym] : null\n const originalValue = (state.originalObject as any)[sym]\n\n // If the value is not equal to original, something is still changed\n if (!deepEqual(currentValue, originalValue)) {\n debugLog(`Symbol property is different, returning false`)\n return false\n }\n } else if (state.assigned_[sym.toString()] === false) {\n // Property was deleted, so it's different from original\n debugLog(`Symbol property was deleted, returning false`)\n return false\n }\n }\n\n debugLog(`All properties match original values, returning true`)\n // All assigned properties match their original values\n return true\n }\n\n // Recursively check and update modified status based on child objects\n function updateModifiedStatus(state: ChangeTracker<object>): boolean {\n debugLog(\n `updateModifiedStatus called, assigned keys:`,\n Object.keys(state.assigned_)\n )\n\n // Only check for reverts if we actually have changes\n if (\n Object.keys(state.assigned_).length === 0 &&\n Object.getOwnPropertySymbols(state.assigned_).length === 0\n ) {\n debugLog(`No assigned properties, returning false`)\n return false\n }\n\n // If this object has direct changes that aren't reverted, it's modified\n const isReverted = checkIfReverted(state)\n debugLog(`checkIfReverted returned:`, isReverted)\n\n if (!isReverted) {\n debugLog(`Object has changes that aren't reverted, returning true`)\n return true\n }\n\n debugLog(`All changes reverted, clearing tracking`)\n // All changes have been reverted, clear the tracking\n state.modified = false\n state.changes = {}\n state.assigned_ = {}\n\n // If we have a parent, update its status too\n if (state.parent) {\n debugLog(`Checking parent status for prop:`, state.parent.prop)\n // Tell the parent this child has reverted\n checkParentStatus(state.parent.tracker, state.parent.prop)\n }\n\n return false\n }\n\n // Update parent status based on child changes\n function checkParentStatus(\n parentState: ChangeTracker<object>,\n childProp: string | symbol\n ) {\n debugLog(`checkParentStatus called for child prop:`, childProp)\n\n // Check if all properties of the parent are reverted\n const isReverted = checkIfReverted(parentState)\n debugLog(`Parent checkIfReverted returned:`, isReverted)\n\n if (isReverted) {\n debugLog(`Parent is fully reverted, clearing tracking`)\n // If everything is reverted, clear the tracking\n parentState.modified = false\n parentState.changes = {}\n parentState.assigned_ = {}\n\n // Continue up the chain\n if (parentState.parent) {\n debugLog(`Continuing up the parent chain`)\n checkParentStatus(parentState.parent.tracker, parentState.parent.prop)\n }\n }\n }\n\n // Create a proxy for the target object\n function createObjectProxy<TObj extends object>(obj: TObj): TObj {\n // If we've already created a proxy for this object, return it\n if (proxyCache.has(obj)) {\n return proxyCache.get(obj) as TObj\n }\n\n // Create a proxy for the object\n const proxy = new Proxy(obj, {\n get(ptarget, prop) {\n const value = ptarget[prop as keyof TObj]\n\n // If it's a getter, return the value directly\n const desc = Object.getOwnPropertyDescriptor(ptarget, prop)\n if (desc?.get) {\n return value\n }\n\n // If the value is a function, bind it to the ptarget\n if (typeof value === `function`) {\n // For Map and Set methods that modify the collection\n if (ptarget instanceof Map || ptarget instanceof Set) {\n const methodName = prop.toString()\n const modifyingMethods = new Set([\n `set`,\n `delete`,\n `clear`,\n `add`,\n `pop`,\n `push`,\n `shift`,\n `unshift`,\n `splice`,\n `sort`,\n `reverse`,\n ])\n\n if (modifyingMethods.has(methodName)) {\n return function (...args: Array<unknown>) {\n const result = value.apply(ptarget, args)\n markChanged(changeTracker)\n return result\n }\n }\n\n // Handle iterator methods for Map and Set\n const iteratorMethods = new Set([\n `entries`,\n `keys`,\n `values`,\n `forEach`,\n Symbol.iterator,\n ])\n\n if (iteratorMethods.has(methodName) || prop === Symbol.iterator) {\n return function (this: unknown, ...args: Array<unknown>) {\n const result = value.apply(ptarget, args)\n\n // For forEach, we need to wrap the callback to track changes\n if (methodName === `forEach`) {\n const callback = args[0]\n if (typeof callback === `function`) {\n // Replace the original callback with our wrapped version\n const wrappedCallback = function (\n // eslint-disable-next-line\n this: unknown,\n // eslint-disable-next-line\n value: unknown,\n key: unknown,\n collection: unknown\n ) {\n // Call the original callback\n const cbresult = callback.call(\n this,\n value,\n key,\n collection\n )\n // Mark as changed since the callback might have modified the value\n markChanged(changeTracker)\n return cbresult\n }\n // Call forEach with our wrapped callback\n return value.apply(ptarget, [\n wrappedCallback,\n ...args.slice(1),\n ])\n }\n }\n\n // For iterators (entries, keys, values, Symbol.iterator)\n if (\n methodName === `entries` ||\n methodName === `values` ||\n methodName === Symbol.iterator.toString() ||\n prop === Symbol.iterator\n ) {\n // If it's an iterator, we need to wrap the returned iterator\n // to track changes when the values are accessed and potentially modified\n const originalIterator = result\n\n // Create a proxy for the iterator that will mark changes when next() is called\n return {\n next() {\n const nextResult = originalIterator.next()\n\n // If we have a value and it's an object, we need to track it\n if (\n !nextResult.done &&\n nextResult.value &&\n typeof nextResult.value === `object`\n ) {\n // For entries, the value is a [key, value] pair\n if (\n methodName === `entries` &&\n Array.isArray(nextResult.value) &&\n nextResult.value.length === 2\n ) {\n // The value is at index 1 in the [key, value] pair\n if (\n nextResult.value[1] &&\n typeof nextResult.value[1] === `object`\n ) {\n // Create a proxy for the value and replace it in the result\n const { proxy: valueProxy } = createChangeProxy(\n nextResult.value[1],\n {\n tracker: changeTracker,\n prop:\n typeof nextResult.value[0] === `symbol`\n ? nextResult.value[0]\n : String(nextResult.value[0]),\n }\n )\n nextResult.value[1] = valueProxy\n }\n } else if (\n methodName === `values` ||\n methodName === Symbol.iterator.toString() ||\n prop === Symbol.iterator\n ) {\n // If the value is an object, create a proxy for it\n if (\n typeof nextResult.value === `object` &&\n nextResult.value !== null\n ) {\n // For Set, we need to track the whole object\n // For Map, we would need the key, but we don't have it here\n // So we'll use a symbol as a placeholder\n const tempKey = Symbol(`iterator-value`)\n const { proxy: valueProxy } = createChangeProxy(\n nextResult.value,\n {\n tracker: changeTracker,\n prop: tempKey,\n }\n )\n nextResult.value = valueProxy\n }\n }\n }\n\n return nextResult\n },\n [Symbol.iterator]() {\n return this\n },\n }\n }\n\n return result\n }\n }\n }\n return value.bind(ptarget)\n }\n\n // If the value is an object, create a proxy for it\n if (\n value &&\n typeof value === `object` &&\n !(value instanceof Date) &&\n !(value instanceof RegExp)\n ) {\n // Create a parent reference for the nested object\n const nestedParent = {\n tracker: changeTracker,\n prop: String(prop),\n }\n\n // Create a proxy for the nested object\n const { proxy: nestedProxy } = createChangeProxy(value, nestedParent)\n\n // Cache the proxy\n proxyCache.set(value, nestedProxy)\n\n return nestedProxy\n }\n\n return value\n },\n\n set(sobj, prop, value) {\n const currentValue = sobj[prop as keyof TObj]\n debugLog(\n `set called for property ${String(prop)}, current:`,\n currentValue,\n `new:`,\n value\n )\n\n // Special handling for array length changes\n if (Array.isArray(sobj) && prop === `length`) {\n const newLength = Number(value)\n const oldLength = sobj.length\n\n // Create a new array with the desired length\n const newArray = Array.from({ length: newLength }, (_, i) =>\n i < oldLength ? sobj[i] : undefined\n )\n\n // Track the change in the parent object since 'arr' is the property name\n if (parent) {\n parent.tracker.changes[parent.prop] = newArray\n parent.tracker.assigned_[parent.prop] = true\n markChanged(parent.tracker)\n }\n\n // Update the original array\n sobj.length = newLength\n return true\n }\n\n // Only track the change if the value is actually different\n if (!deepEqual(currentValue, value)) {\n // Check if the new value is equal to the original value\n // Important: Use the originalObject to get the true original value\n const originalValue = changeTracker.originalObject[prop as keyof T]\n const isRevertToOriginal = deepEqual(value, originalValue)\n debugLog(\n `Value different, original:`,\n originalValue,\n `isRevertToOriginal:`,\n isRevertToOriginal\n )\n\n if (isRevertToOriginal) {\n debugLog(`Reverting property ${String(prop)} to original value`)\n // If the value is reverted to its original state, remove it from changes\n delete changeTracker.changes[prop.toString()]\n delete changeTracker.assigned_[prop.toString()]\n\n // Make sure the copy is updated with the original value\n if (changeTracker.copy_) {\n debugLog(`Updating copy with original value for ${String(prop)}`)\n changeTracker.copy_[prop as keyof T] = deepClone(originalValue)\n }\n\n // Check if all properties in this object have been reverted\n debugLog(`Checking if all properties reverted`)\n const allReverted = checkIfReverted(changeTracker)\n debugLog(`All reverted:`, allReverted)\n\n if (allReverted) {\n debugLog(`All properties reverted, clearing tracking`)\n // If all have been reverted, clear tracking\n changeTracker.modified = false\n changeTracker.changes = {}\n changeTracker.assigned_ = {}\n\n // If we're a nested object, check if the parent needs updating\n if (parent) {\n debugLog(`Updating parent for property:`, parent.prop)\n checkParentStatus(parent.tracker, parent.prop)\n }\n } else {\n // Some properties are still changed\n debugLog(`Some properties still changed, keeping modified flag`)\n changeTracker.modified = true\n }\n } else {\n debugLog(`Setting new value for property ${String(prop)}`)\n // Create a copy of the object if it doesn't exist\n prepareCopy(changeTracker)\n\n // Set the value on the copy\n if (changeTracker.copy_) {\n changeTracker.copy_[prop as keyof T] = value\n }\n\n // Set the value on the original object\n obj[prop as keyof TObj] = value\n\n // Track that this property was assigned - store using the actual property (symbol or string)\n changeTracker.assigned_[prop.toString()] = true\n\n // Track the change directly with the property as the key\n changeTracker.changes[prop.toString()] = deepClone(value)\n\n // Mark this object and its ancestors as modified\n debugLog(`Marking object and ancestors as modified`)\n markChanged(changeTracker)\n }\n } else {\n debugLog(`Value unchanged, not tracking`)\n }\n\n return true\n },\n\n defineProperty(ptarget, prop, descriptor) {\n const result = Reflect.defineProperty(ptarget, prop, descriptor)\n if (result) {\n // Track the change if the property has a value\n if (`value` in descriptor) {\n changeTracker.changes[prop.toString()] = deepClone(descriptor.value)\n changeTracker.assigned_[prop.toString()] = true\n markChanged(changeTracker)\n }\n }\n return result\n },\n\n setPrototypeOf(ptarget, proto) {\n // Allow setting prototype but don't track it as a change\n return Object.setPrototypeOf(ptarget, proto)\n },\n\n deleteProperty(dobj, prop) {\n const stringProp = typeof prop === `symbol` ? prop.toString() : prop\n\n if (stringProp in dobj) {\n // Check if the property exists in the original object\n const hadPropertyInOriginal =\n stringProp in changeTracker.originalObject\n\n // Create a copy of the object if it doesn't exist\n prepareCopy(changeTracker)\n\n // Delete the property from the copy\n if (changeTracker.copy_) {\n // Use type assertion to tell TypeScript this is allowed\n delete (changeTracker.copy_ as Record<string | symbol, unknown>)[\n prop\n ]\n }\n\n // Delete the property from the original object\n // Use type assertion to tell TypeScript this is allowed\n delete (dobj as Record<string | symbol, unknown>)[prop]\n\n // If the property didn't exist in the original object, removing it\n // should revert to the original state\n if (!hadPropertyInOriginal) {\n delete changeTracker.changes[stringProp]\n delete changeTracker.assigned_[stringProp]\n\n // If this is the last change and we're not a nested object,\n // mark the object as unmodified\n if (\n Object.keys(changeTracker.assigned_).length === 0 &&\n Object.getOwnPropertySymbols(changeTracker.assigned_).length === 0\n ) {\n changeTracker.modified = false\n } else {\n // We still have changes, keep as modified\n changeTracker.modified = true\n }\n } else {\n // Mark this property as deleted\n changeTracker.assigned_[stringProp] = false\n changeTracker.changes[stringProp] = undefined\n markChanged(changeTracker)\n }\n }\n\n return true\n },\n })\n\n // Cache the proxy\n proxyCache.set(obj, proxy)\n\n return proxy\n }\n\n // Create a proxy for the target object\n const proxy = createObjectProxy(target)\n\n // Return the proxy and a function to get the changes\n return {\n proxy,\n getChanges: () => {\n debugLog(\n `getChanges called, modified:`,\n changeTracker.modified,\n `assigned keys:`,\n Object.keys(changeTracker.assigned_)\n )\n\n // First, check if the object is still considered modified\n if (!changeTracker.modified) {\n debugLog(`Object not modified, returning empty object`)\n return {}\n }\n\n // For deeply nested changes, we need to verify explicitly\n if (\n Object.keys(changeTracker.assigned_).length === 0 &&\n Object.getOwnPropertySymbols(changeTracker.assigned_).length === 0\n ) {\n debugLog(`No assigned properties, checking deep equality`)\n\n // If there are no assigned properties but the object is still marked as modified,\n // we should check deep equality with the original object\n if (changeTracker.copy_) {\n debugLog(`Comparing copy with original`)\n if (deepEqual(changeTracker.copy_, changeTracker.originalObject)) {\n debugLog(`Copy equals original, returning empty object`)\n changeTracker.modified = false\n return {}\n }\n } else if (deepEqual(target, changeTracker.originalObject)) {\n debugLog(`Target equals original, returning empty object`)\n changeTracker.modified = false\n changeTracker.changes = {}\n changeTracker.assigned_ = {}\n return {}\n }\n }\n\n debugLog(`Forcing full check for reverted state`)\n // Force a full check for reverted state, which will update the modified flag accordingly\n updateModifiedStatus(changeTracker)\n\n // If we're no longer modified after the check, return empty changes\n // eslint-disable-next-line\n if (!changeTracker.modified) {\n debugLog(`No longer modified after check, returning empty object`)\n return {}\n }\n\n // Handle optimization case - if the object is marked modified but actually is equal to original\n // eslint-disable-next-line\n if (changeTracker.modified) {\n const objToCheck = changeTracker.copy_ || target\n debugLog(\n `Checking if object is equal to original:`,\n objToCheck,\n changeTracker.originalObject\n )\n if (deepEqual(objToCheck, changeTracker.originalObject)) {\n debugLog(`Object equals original, returning empty object`)\n changeTracker.modified = false\n changeTracker.changes = {}\n changeTracker.assigned_ = {}\n return {}\n }\n }\n\n // If there are assigned properties, return the changes\n if (\n Object.keys(changeTracker.assigned_).length > 0 ||\n Object.getOwnPropertySymbols(changeTracker.assigned_).length > 0\n ) {\n // If we have a copy, use it to construct the changes\n if (changeTracker.copy_) {\n const changes: Record<string | symbol, unknown> = {}\n\n // Add all assigned properties\n for (const key in changeTracker.assigned_) {\n if (changeTracker.assigned_[key] === true) {\n // Property was assigned\n changes[key] = deepClone(changeTracker.copy_[key as keyof T])\n } else if (changeTracker.assigned_[key] === false) {\n // Property was deleted\n changes[key] = undefined\n }\n }\n\n // Handle symbol properties - this needs special handling\n const symbolProps = Object.getOwnPropertySymbols(\n changeTracker.assigned_\n )\n for (const sym of symbolProps) {\n if (changeTracker.assigned_[sym.toString()] === true) {\n // Use the symbol directly instead of its string representation\n\n const value = (changeTracker.copy_ as any)[sym]\n\n changes[sym.toString()] = deepClone(value)\n }\n }\n\n return changes\n }\n\n // Fall back to the existing changes object if no copy exists\n return changeTracker.changes\n }\n\n // If the object is modified but has no direct changes (nested changes),\n // but we're the root object, recursively check if unknown changes exist\n // eslint-disable-next-line\n if (changeTracker.modified && !parent) {\n debugLog(`Root object with nested changes, checking deep equality`)\n\n const currentState = changeTracker.copy_ || (target as any)\n\n debugLog(\n `Comparing current state with original:`,\n currentState,\n changeTracker.originalObject\n )\n if (deepEqual(currentState, changeTracker.originalObject)) {\n // The entire object has been reverted to its original state\n debugLog(`Current state equals original, returning empty object`)\n changeTracker.modified = false\n return {}\n }\n\n // One more deep check - compare the actual values\n // This is needed for the case where nested properties are modified and then reverted\n debugLog(\n `Comparing target with original:`,\n target,\n changeTracker.originalObject\n )\n if (deepEqual(target, changeTracker.originalObject)) {\n debugLog(`Target equals original, returning empty object`)\n changeTracker.modified = false\n changeTracker.changes = {}\n changeTracker.assigned_ = {}\n return {}\n }\n\n // Special case for nested object reverts\n // If we're here, we need to check if the nested objects have been reverted\n // even if the parent object still shows as modified\n // eslint-disable-next-line\n if (typeof target === `object` && target !== null) {\n let allNestedReverted = true\n\n // Check each property to see if it's been reverted to original\n for (const key in target) {\n if (Object.prototype.hasOwnProperty.call(target, key)) {\n const currentValue = target[key]\n const originalValue = changeTracker.originalObject[key as keyof T]\n\n // If this property is different from original, not all are reverted\n if (!deepEqual(currentValue, originalValue)) {\n allNestedReverted = false\n break\n }\n }\n }\n\n // If all nested properties match original values, return empty changes\n if (allNestedReverted) {\n debugLog(\n `All nested properties match original values, returning empty object`\n )\n changeTracker.modified = false\n changeTracker.changes = {}\n changeTracker.assigned_ = {}\n return {}\n }\n }\n\n debugLog(\n `Changes detected, returning full object:`,\n changeTracker.copy_ || target\n )\n // Convert the copy or target to a Record type before returning\n const result = changeTracker.copy_ || target\n return result as unknown as Record<string | symbol, unknown>\n }\n\n // No changes\n debugLog(`No changes detected, returning empty object`)\n return {}\n },\n }\n}\n\n/**\n * Creates proxies for an array of objects and tracks changes to each\n *\n * @param targets Array of objects to proxy\n * @returns An object containing the array of proxies and a function to get all changes\n */\nexport function createArrayChangeProxy<T extends object>(\n targets: Array<T>\n): {\n proxies: Array<T>\n getChanges: () => Array<Record<string | symbol, unknown>>\n} {\n const proxiesWithChanges = targets.map((target) => createChangeProxy(target))\n\n return {\n proxies: proxiesWithChanges.map((p) => p.proxy),\n getChanges: () => proxiesWithChanges.map((p) => p.getChanges()),\n }\n}\n\n/**\n * Creates a proxy for an object, passes it to a callback function,\n * and returns the changes made by the callback\n *\n * @param target The object to proxy\n * @param callback Function that receives the proxy and can make changes to it\n * @returns The changes made to the object\n */\nexport function withChangeTracking<T extends object>(\n target: T,\n callback: (proxy: T) => void\n): Record<string | symbol, unknown> {\n const { proxy, getChanges } = createChangeProxy(target)\n\n callback(proxy)\n\n return getChanges()\n}\n\n/**\n * Creates proxies for an array of objects, passes them to a callback function,\n * and returns the changes made by the callback for each object\n *\n * @param targets Array of objects to proxy\n * @param callback Function that receives the proxies and can make changes to them\n * @returns Array of changes made to each object\n */\nexport function withArrayChangeTracking<T extends object>(\n targets: Array<T>,\n callback: (proxies: Array<T>) => void\n): Array<Record<string | symbol, unknown>> {\n const { proxies, getChanges } = createArrayChangeProxy(targets)\n\n callback(proxies)\n\n return getChanges()\n}\n\n/**\n * Creates a shallow copy of the target object if it doesn't already exist\n */\nfunction prepareCopy<T extends object>(state: ChangeTracker<T>) {\n if (!state.copy_) {\n state.copy_ = shallowCopy(state.originalObject)\n }\n}\n\n/**\n * Creates a shallow copy of an object\n */\nfunction shallowCopy<T>(obj: T): T {\n if (Array.isArray(obj)) {\n return [...obj] as unknown as T\n }\n\n if (obj instanceof Map) {\n return new Map(obj) as unknown as T\n }\n\n if (obj instanceof Set) {\n return new Set(obj) as unknown as T\n }\n\n if (obj instanceof Date) {\n return new Date(obj.getTime()) as unknown as T\n }\n\n if (obj instanceof RegExp) {\n return new RegExp(obj.source, obj.flags) as unknown as T\n }\n\n if (obj !== null && typeof obj === `object`) {\n return { ...obj } as T\n }\n\n return obj\n}\n"],"names":["clone","proxy","value"],"mappings":"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