UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

230 lines (229 loc) • 7.53 kB
import { UndefinedKeyError, InvalidKeyError } from "./errors.js"; const durationFields = [ `years`, `months`, `weeks`, `days`, `hours`, `minutes`, `seconds`, `milliseconds`, `microseconds`, `nanoseconds` ]; function deepEquals(a, b) { return deepEqualsInternal(a, b); } function sameRowValue(a, b) { return deepEqualsInternal(a, b, ROW); } function samePublishedValue(a, b) { return deepEqualsInternal(a, b, ROW | PUBLICATION); } function equalPersistedSnapshotValues(a, b) { return deepEqualsInternal(a, b, DRAFT | PERSISTED); } function isPlainPrototype(prototype) { return prototype === null || Object.getPrototypeOf(prototype) === null; } function enumerableOwnKeys(value) { const keys = Object.keys(value); for (const key of Object.getOwnPropertySymbols(value)) { if (Object.prototype.propertyIsEnumerable.call(value, key)) keys.push(key); } return keys; } const DRAFT = 1; const PERSISTED = 2; const ROW = 4; const PUBLICATION = 8; function deepEqualsInternal(a, b, mode = 0, visited) { const draft = mode & DRAFT; if (!(mode & ROW) && a === b || Object.is(a, b)) return true; if (a == null || b == null) return false; if (typeof a !== typeof b) return false; if (mode & PERSISTED && typeof a === `object` && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) { return false; } if (visited?.has(a)) return visited.get(a) === b; if (a instanceof Date) { if (!(b instanceof Date)) return false; return Object.is(a.getTime(), b.getTime()); } if (b instanceof Date) return false; if (a instanceof RegExp) { if (!(b instanceof RegExp)) return false; return a.source === b.source && a.flags === b.flags && (!draft || a.lastIndex === b.lastIndex); } if (b instanceof RegExp) return false; if (a instanceof Map) { if (!(b instanceof Map)) return false; if (a.size !== b.size) return false; (visited ??= /* @__PURE__ */ new Map()).set(a, b); const bEntries = draft && Array.from(b.entries()); const result = Array.from(a.entries()).every( ([key, val], index) => bEntries ? Object.is(key, bEntries[index][0]) && deepEqualsInternal(val, bEntries[index][1], mode, visited) : b.has(key) && deepEqualsInternal(val, b.get(key), mode, visited) ); visited.delete(a); return result; } if (b instanceof Map) return false; if (a instanceof Set) { if (!(b instanceof Set)) return false; if (a.size !== b.size) return false; (visited ??= /* @__PURE__ */ new Map()).set(a, b); const aValues = Array.from(a); const bValues = Array.from(b); if (draft) { const result2 = deepEqualsInternal(aValues, bValues, mode, visited); visited.delete(a); return result2; } if (aValues.every((val) => typeof val !== `object`)) { visited.delete(a); return aValues.every((val) => b.has(val)); } if (aValues.every( (value, index) => deepEqualsInternal(value, bValues[index], mode, visited) )) { visited.delete(a); return true; } const candidates = aValues.map( (value) => bValues.flatMap( (candidate, index) => deepEqualsInternal(value, candidate, mode, visited) ? [index] : [] ) ); const assigned = /* @__PURE__ */ new Map(); const match = (index, seen) => { const options = candidates[index]; const free = options.find((candidate) => !assigned.has(candidate)); if (free !== void 0) { assigned.set(free, index); return true; } return options.some((candidate) => { if (seen.has(candidate)) return false; seen.add(candidate); const previous = assigned.get(candidate); if (previous !== void 0 && !match(previous, seen)) return false; assigned.set(candidate, index); return true; }); }; const result = aValues.every((_, index) => match(index, /* @__PURE__ */ new Set())); visited.delete(a); return result; } if (b instanceof Set) return false; const typed = ArrayBuffer.isView(a) && !(a instanceof DataView); if (typed !== (ArrayBuffer.isView(b) && !(b instanceof DataView))) { return false; } if (typed) { const typedA = a; const typedB = b; return (!draft || Object.getPrototypeOf(a) === Object.getPrototypeOf(b)) && typedA.length === typedB.length && typedA.every((x, i) => deepEqualsInternal(x, typedB[i], mode)); } if (isTemporal(a) && isTemporal(b)) { const aTag = a[Symbol.toStringTag]; const bTag = b[Symbol.toStringTag]; if (aTag !== bTag) return false; if (aTag === `Temporal.Duration`) { const durationA = a; const durationB = b; return durationFields.every( (field) => durationA[field] === durationB[field] ); } if (typeof a.equals === `function`) { return a.equals(b); } return a.toString() === b.toString(); } if (isTemporal(b)) return false; if (Array.isArray(a) !== Array.isArray(b)) return false; if (Array.isArray(a) && a.length !== b.length) return false; if (Array.isArray(a) && !draft) { (visited ??= /* @__PURE__ */ new Map()).set(a, b); let result = true; for (let index = 0; index < a.length; index++) { if (!deepEqualsInternal(a[index], b[index], mode, visited)) { result = false; break; } } visited.delete(a); return result; } if (typeof a === `object`) { const prototype = Object.getPrototypeOf(a); const prototypeB = Object.getPrototypeOf(b); const plain = isPlainPrototype(prototype); const plainB = isPlainPrototype(prototypeB); if (prototype !== prototypeB && (mode & ROW && !draft || !plain && !plainB)) return false; if (mode & PUBLICATION && !(plain && plainB)) return false; const keysA = enumerableOwnKeys(a); const keysB = enumerableOwnKeys(b); if (keysA.length !== keysB.length) return false; if (keysA.length === 0 && !Array.isArray(a) && !(plain && plainB)) { return a instanceof URL && a.href === b.href; } let registered = false; let result = true; for (const key of keysA) { const value = a[key]; if (!registered && value !== null && typeof value === `object`) { (visited ??= /* @__PURE__ */ new Map()).set(a, b); registered = true; } if (!Object.prototype.propertyIsEnumerable.call(b, key) || !deepEqualsInternal(value, b[key], mode, visited)) { result = false; break; } } if (registered) visited.delete(a); return result; } return false; } const temporalTypes = /* @__PURE__ */ new Set([ `Temporal.Duration`, `Temporal.Instant`, `Temporal.PlainDate`, `Temporal.PlainDateTime`, `Temporal.PlainMonthDay`, `Temporal.PlainTime`, `Temporal.PlainYearMonth`, `Temporal.ZonedDateTime` ]); function isTemporal(a) { if (a == null || typeof a !== `object`) return false; const tag = a[Symbol.toStringTag]; return typeof tag === `string` && temporalTypes.has(tag); } const DEFAULT_COMPARE_OPTIONS = { direction: `asc`, nulls: `first`, stringSort: `locale` }; function assertCollectionKey(key, item) { if (typeof key !== `string` && typeof key !== `number`) { throw key === void 0 ? new UndefinedKeyError(item) : new InvalidKeyError(key, item); } } export { DEFAULT_COMPARE_OPTIONS, DRAFT, ROW, assertCollectionKey, deepEquals, deepEqualsInternal, durationFields, equalPersistedSnapshotValues, isTemporal, samePublishedValue, sameRowValue }; //# sourceMappingURL=utils.js.map