UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

87 lines (73 loc) 2.08 kB
/** * Generic utility functions */ /** * Deep equality function that compares two values recursively * * @param a - First value to compare * @param b - Second value to compare * @returns True if the values are deeply equal, false otherwise * * @example * ```typescript * deepEquals({ a: 1, b: 2 }, { b: 2, a: 1 }) // true (property order doesn't matter) * deepEquals([1, { x: 2 }], [1, { x: 2 }]) // true * deepEquals({ a: 1 }, { a: 2 }) // false * ``` */ export function deepEquals(a: any, b: any): boolean { return deepEqualsInternal(a, b, new Map()) } /** * Internal implementation with cycle detection to prevent infinite recursion */ function deepEqualsInternal( a: any, b: any, visited: Map<object, object> ): boolean { // Handle strict equality (primitives, same reference) if (a === b) return true // Handle null/undefined if (a == null || b == null) return false // Handle different types if (typeof a !== typeof b) return false // Handle arrays if (Array.isArray(a)) { if (!Array.isArray(b) || a.length !== b.length) return false // Check for circular references if (visited.has(a)) { return visited.get(a) === b } visited.set(a, b) const result = a.every((item, index) => deepEqualsInternal(item, b[index], visited) ) visited.delete(a) return result } // Handle objects if (typeof a === `object`) { // Check for circular references if (visited.has(a)) { return visited.get(a) === b } visited.set(a, b) // Get all keys from both objects const keysA = Object.keys(a) const keysB = Object.keys(b) // Check if they have the same number of keys if (keysA.length !== keysB.length) { visited.delete(a) return false } // Check if all keys exist in both objects and their values are equal const result = keysA.every( (key) => key in b && deepEqualsInternal(a[key], b[key], visited) ) visited.delete(a) return result } // For primitives that aren't strictly equal return false }