@tanstack/db 0.0.4 → 0.0.6
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/cjs/collection.cjs +182 -113
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +43 -15
- package/dist/cjs/index.cjs +1 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/proxy.cjs +87 -248
- package/dist/cjs/proxy.cjs.map +1 -1
- package/dist/cjs/proxy.d.cts +5 -5
- package/dist/cjs/query/compiled-query.cjs +23 -14
- package/dist/cjs/query/compiled-query.cjs.map +1 -1
- package/dist/cjs/query/compiled-query.d.cts +3 -1
- package/dist/cjs/query/evaluators.cjs +35 -20
- package/dist/cjs/query/evaluators.cjs.map +1 -1
- package/dist/cjs/query/evaluators.d.cts +8 -3
- package/dist/cjs/query/extractors.cjs +20 -20
- package/dist/cjs/query/extractors.cjs.map +1 -1
- package/dist/cjs/query/extractors.d.cts +3 -3
- package/dist/cjs/query/group-by.cjs +12 -15
- package/dist/cjs/query/group-by.cjs.map +1 -1
- package/dist/cjs/query/group-by.d.cts +7 -7
- package/dist/cjs/query/joins.cjs +41 -55
- package/dist/cjs/query/joins.cjs.map +1 -1
- package/dist/cjs/query/joins.d.cts +3 -3
- package/dist/cjs/query/order-by.cjs +37 -84
- package/dist/cjs/query/order-by.cjs.map +1 -1
- package/dist/cjs/query/order-by.d.cts +2 -2
- package/dist/cjs/query/pipeline-compiler.cjs +13 -18
- package/dist/cjs/query/pipeline-compiler.cjs.map +1 -1
- package/dist/cjs/query/pipeline-compiler.d.cts +2 -1
- package/dist/cjs/query/query-builder.cjs +22 -29
- package/dist/cjs/query/query-builder.cjs.map +1 -1
- package/dist/cjs/query/query-builder.d.cts +16 -10
- package/dist/cjs/query/schema.d.cts +12 -11
- package/dist/cjs/query/select.cjs +47 -24
- package/dist/cjs/query/select.cjs.map +1 -1
- package/dist/cjs/query/select.d.cts +2 -2
- package/dist/cjs/query/types.d.cts +1 -0
- package/dist/cjs/transactions.cjs +20 -9
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/types.d.cts +66 -7
- package/dist/esm/collection.d.ts +43 -15
- package/dist/esm/collection.js +183 -114
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/proxy.d.ts +5 -5
- package/dist/esm/proxy.js +87 -248
- package/dist/esm/proxy.js.map +1 -1
- package/dist/esm/query/compiled-query.d.ts +3 -1
- package/dist/esm/query/compiled-query.js +23 -14
- package/dist/esm/query/compiled-query.js.map +1 -1
- package/dist/esm/query/evaluators.d.ts +8 -3
- package/dist/esm/query/evaluators.js +36 -21
- package/dist/esm/query/evaluators.js.map +1 -1
- package/dist/esm/query/extractors.d.ts +3 -3
- package/dist/esm/query/extractors.js +20 -20
- package/dist/esm/query/extractors.js.map +1 -1
- package/dist/esm/query/group-by.d.ts +7 -7
- package/dist/esm/query/group-by.js +14 -17
- package/dist/esm/query/group-by.js.map +1 -1
- package/dist/esm/query/joins.d.ts +3 -3
- package/dist/esm/query/joins.js +42 -56
- package/dist/esm/query/joins.js.map +1 -1
- package/dist/esm/query/order-by.d.ts +2 -2
- package/dist/esm/query/order-by.js +39 -86
- package/dist/esm/query/order-by.js.map +1 -1
- package/dist/esm/query/pipeline-compiler.d.ts +2 -1
- package/dist/esm/query/pipeline-compiler.js +14 -19
- package/dist/esm/query/pipeline-compiler.js.map +1 -1
- package/dist/esm/query/query-builder.d.ts +16 -10
- package/dist/esm/query/query-builder.js +22 -29
- package/dist/esm/query/query-builder.js.map +1 -1
- package/dist/esm/query/schema.d.ts +12 -11
- package/dist/esm/query/select.d.ts +2 -2
- package/dist/esm/query/select.js +48 -25
- package/dist/esm/query/select.js.map +1 -1
- package/dist/esm/query/types.d.ts +1 -0
- package/dist/esm/transactions.js +20 -9
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +66 -7
- package/package.json +2 -2
- package/src/collection.ts +286 -146
- package/src/proxy.ts +141 -358
- package/src/query/compiled-query.ts +30 -15
- package/src/query/evaluators.ts +49 -21
- package/src/query/extractors.ts +24 -21
- package/src/query/group-by.ts +24 -22
- package/src/query/joins.ts +88 -75
- package/src/query/order-by.ts +56 -106
- package/src/query/pipeline-compiler.ts +34 -37
- package/src/query/query-builder.ts +49 -46
- package/src/query/schema.ts +18 -15
- package/src/query/select.ts +68 -33
- package/src/query/types.ts +1 -0
- package/src/transactions.ts +30 -14
- package/src/types.ts +76 -7
- package/dist/cjs/query/key-by.cjs +0 -43
- package/dist/cjs/query/key-by.cjs.map +0 -1
- package/dist/cjs/query/key-by.d.cts +0 -3
- package/dist/esm/query/key-by.d.ts +0 -3
- package/dist/esm/query/key-by.js +0 -43
- package/dist/esm/query/key-by.js.map +0 -1
- package/src/query/key-by.ts +0 -61
package/dist/cjs/proxy.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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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"}
|
|
1
|
+
{"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 // true\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 originalObject: T\n modified: boolean\n copy_: T\n proxyCount: number\n assigned_: Record<string | symbol, boolean>\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\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\nlet count = 0\nfunction getProxyCount() {\n count += 1\n return count\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<\n T extends Record<string | symbol, any | undefined>,\n>(\n target: T,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n): {\n proxy: T\n\n getChanges: () => Record<string | symbol, any>\n} {\n const changeProxyCache = new Map<object, object>()\n\n function memoizedCreateChangeProxy<\n TInner extends Record<string | symbol, any | undefined>,\n >(\n innerTarget: TInner,\n innerParent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n ): {\n proxy: TInner\n getChanges: () => Record<string | symbol, any>\n } {\n debugLog(`Object ID:`, innerTarget.constructor.name)\n if (changeProxyCache.has(innerTarget)) {\n return changeProxyCache.get(innerTarget) as {\n proxy: TInner\n getChanges: () => Record<string | symbol, any>\n }\n } else {\n const changeProxy = createChangeProxy(innerTarget, innerParent)\n changeProxyCache.set(innerTarget, changeProxy)\n return changeProxy\n }\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 Map<object, object>()\n\n // Create a change tracker to track changes to the object\n const changeTracker: ChangeTracker<T> = {\n copy_: deepClone(target),\n originalObject: deepClone(target),\n proxyCount: getProxyCount(),\n modified: false,\n assigned_: {},\n parent,\n target, // Store reference to the target object\n }\n\n debugLog(\n `createChangeProxy called for target`,\n target,\n changeTracker.proxyCount\n )\n // Mark this object and all its ancestors as modified\n // Also propagate the actual changes up the chain\n function markChanged(state: ChangeTracker<object>) {\n if (!state.modified) {\n state.modified = true\n }\n\n // Propagate the change up the parent chain\n if (state.parent) {\n debugLog(`propagating change to parent`)\n\n // Update parent's copy with this object's current state\n state.parent.tracker.copy_[state.parent.prop] = state.copy_\n state.parent.tracker.assigned_[state.parent.prop] = true\n\n // Mark parent as changed\n markChanged(state.parent.tracker)\n }\n }\n\n // Check if all properties in the current state have reverted to original values\n function checkIfReverted(\n state: ChangeTracker<Record<string | symbol, unknown>>\n ): 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_[prop]\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] === true) {\n const currentValue = (state.copy_ as any)[sym]\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] === 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 // Update parent status based on child changes\n function checkParentStatus(\n parentState: ChangeTracker<Record<string | symbol, unknown>>,\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.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 debugLog(`createObjectProxy`, obj)\n // If we've already created a proxy for this object, return it\n if (proxyCache.has(obj)) {\n debugLog(`proxyCache found match`)\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 debugLog(`get`, ptarget, prop)\n const value =\n changeTracker.copy_[prop as keyof T] ??\n changeTracker.originalObject[prop as keyof T]\n\n const originalValue = changeTracker.originalObject[prop as keyof T]\n\n debugLog(`value (at top of proxy get)`, value)\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(changeTracker.copy_, 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(changeTracker.copy_, 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 } =\n memoizedCreateChangeProxy(nextResult.value[1], {\n tracker: changeTracker,\n prop:\n typeof nextResult.value[0] === `symbol`\n ? nextResult.value[0]\n : String(nextResult.value[0]),\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 } =\n memoizedCreateChangeProxy(nextResult.value, {\n tracker: changeTracker,\n prop: tempKey,\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 as any) instanceof Date) &&\n !((value as any) 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 } = memoizedCreateChangeProxy(\n originalValue,\n nestedParent\n )\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 = changeTracker.copy_[prop as keyof T]\n debugLog(\n `set called for property ${String(prop)}, current:`,\n currentValue,\n `new:`,\n value\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:`,\n value,\n `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.assigned_[prop.toString()]\n\n // Make sure the copy is updated with the original value\n debugLog(`Updating copy with original value for ${String(prop)}`)\n changeTracker.copy_[prop as keyof T] = deepClone(originalValue)\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.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\n // Set the value on the copy\n changeTracker.copy_[prop as keyof T] = 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 // Mark this object and its ancestors as modified\n debugLog(`Marking object and ancestors as modified`, changeTracker)\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(\n // changeTracker.copy_,\n // prop,\n // descriptor\n // )\n // if (result) {\n if (`value` in descriptor) {\n changeTracker.copy_[prop as keyof T] = deepClone(descriptor.value)\n changeTracker.assigned_[prop.toString()] = true\n markChanged(changeTracker)\n }\n // }\n // return result\n return true\n },\n\n deleteProperty(dobj, prop) {\n debugLog(`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 // Delete the property from the copy\n // Use type assertion to tell TypeScript this is allowed\n delete (changeTracker.copy_ 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.copy_[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.copy_[stringProp as keyof T] = undefined as T[keyof T]\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(`getChanges called, modified:`, changeTracker.modified)\n debugLog(changeTracker)\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 // If we have a copy, return it directly\n // Check if valueObj is actually an object\n if (\n typeof changeTracker.copy_ !== `object` ||\n Array.isArray(changeTracker.copy_)\n ) {\n return changeTracker.copy_\n }\n\n if (Object.keys(changeTracker.assigned_).length === 0) {\n return changeTracker.copy_\n }\n\n const result: Record<string, any | undefined> = {}\n\n // Iterate through keys in keyObj\n for (const key in changeTracker.copy_) {\n // If the key's value is true and the key exists in valueObj\n if (\n changeTracker.assigned_[key] === true &&\n key in changeTracker.copy_\n ) {\n result[key] = changeTracker.copy_[key]\n }\n }\n debugLog(`Returning copy:`, result)\n return result as unknown as Record<string | symbol, unknown>\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"],"names":["clone","proxy","value"],"mappings":"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"}
|
package/dist/cjs/proxy.d.cts
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* and provides a way to retrieve those changes.
|
|
4
4
|
*/
|
|
5
5
|
interface ChangeTracker<T extends object> {
|
|
6
|
-
changes: Record<string | symbol, unknown>;
|
|
7
6
|
originalObject: T;
|
|
8
7
|
modified: boolean;
|
|
9
|
-
copy_
|
|
8
|
+
copy_: T;
|
|
9
|
+
proxyCount: number;
|
|
10
10
|
assigned_: Record<string | symbol, boolean>;
|
|
11
11
|
parent?: {
|
|
12
|
-
tracker: ChangeTracker<
|
|
12
|
+
tracker: ChangeTracker<Record<string | symbol, unknown>>;
|
|
13
13
|
prop: string | symbol;
|
|
14
14
|
};
|
|
15
15
|
target: T;
|
|
@@ -21,8 +21,8 @@ interface ChangeTracker<T extends object> {
|
|
|
21
21
|
* @param parent Optional parent information
|
|
22
22
|
* @returns An object containing the proxy and a function to get the changes
|
|
23
23
|
*/
|
|
24
|
-
export declare function createChangeProxy<T extends
|
|
25
|
-
tracker: ChangeTracker<
|
|
24
|
+
export declare function createChangeProxy<T extends Record<string | symbol, any | undefined>>(target: T, parent?: {
|
|
25
|
+
tracker: ChangeTracker<Record<string | symbol, unknown>>;
|
|
26
26
|
prop: string | symbol;
|
|
27
27
|
}): {
|
|
28
28
|
proxy: T;
|
|
@@ -44,24 +44,21 @@ class CompiledQuery {
|
|
|
44
44
|
acc.set(key, changes);
|
|
45
45
|
return acc;
|
|
46
46
|
}, /* @__PURE__ */ new Map()).forEach((changes, rawKey) => {
|
|
47
|
-
const key = rawKey.toString();
|
|
48
47
|
const { deletes, inserts, value } = changes;
|
|
48
|
+
const valueWithKey = { ...value, _key: rawKey };
|
|
49
49
|
if (inserts && !deletes) {
|
|
50
50
|
write({
|
|
51
|
-
|
|
52
|
-
value,
|
|
51
|
+
value: valueWithKey,
|
|
53
52
|
type: `insert`
|
|
54
53
|
});
|
|
55
54
|
} else if (inserts >= deletes) {
|
|
56
55
|
write({
|
|
57
|
-
|
|
58
|
-
value,
|
|
56
|
+
value: valueWithKey,
|
|
59
57
|
type: `update`
|
|
60
58
|
});
|
|
61
59
|
} else if (deletes > 0) {
|
|
62
60
|
write({
|
|
63
|
-
|
|
64
|
-
value,
|
|
61
|
+
value: valueWithKey,
|
|
65
62
|
type: `delete`
|
|
66
63
|
});
|
|
67
64
|
}
|
|
@@ -77,6 +74,9 @@ class CompiledQuery {
|
|
|
77
74
|
this.resultCollection = new collection.Collection({
|
|
78
75
|
id: crypto.randomUUID(),
|
|
79
76
|
// TODO: remove when we don't require any more
|
|
77
|
+
getId: (val) => {
|
|
78
|
+
return val._key;
|
|
79
|
+
},
|
|
80
80
|
sync: {
|
|
81
81
|
sync
|
|
82
82
|
}
|
|
@@ -85,17 +85,18 @@ class CompiledQuery {
|
|
|
85
85
|
get results() {
|
|
86
86
|
return this.resultCollection;
|
|
87
87
|
}
|
|
88
|
-
sendChangesToInput(inputKey, changes) {
|
|
88
|
+
sendChangesToInput(inputKey, changes, getId) {
|
|
89
89
|
const input = this.inputs[inputKey];
|
|
90
90
|
const multiSetArray = [];
|
|
91
91
|
for (const change of changes) {
|
|
92
|
+
const key = getId(change.value);
|
|
92
93
|
if (change.type === `insert`) {
|
|
93
|
-
multiSetArray.push([change.value, 1]);
|
|
94
|
+
multiSetArray.push([[key, change.value], 1]);
|
|
94
95
|
} else if (change.type === `update`) {
|
|
95
|
-
multiSetArray.push([change.previousValue, -1]);
|
|
96
|
-
multiSetArray.push([change.value, 1]);
|
|
96
|
+
multiSetArray.push([[key, change.previousValue], -1]);
|
|
97
|
+
multiSetArray.push([[key, change.value], 1]);
|
|
97
98
|
} else {
|
|
98
|
-
multiSetArray.push([change.value, -1]);
|
|
99
|
+
multiSetArray.push([[key, change.value], -1]);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
input.sendData(this.version, new d2ts.MultiSet(multiSetArray));
|
|
@@ -123,7 +124,11 @@ class CompiledQuery {
|
|
|
123
124
|
}
|
|
124
125
|
store.batch(() => {
|
|
125
126
|
Object.entries(this.inputCollections).forEach(([key, collection2]) => {
|
|
126
|
-
this.sendChangesToInput(
|
|
127
|
+
this.sendChangesToInput(
|
|
128
|
+
key,
|
|
129
|
+
collection2.currentStateAsChanges(),
|
|
130
|
+
collection2.config.getId
|
|
131
|
+
);
|
|
127
132
|
});
|
|
128
133
|
this.incrementVersion();
|
|
129
134
|
this.sendFrontierToAllInputs();
|
|
@@ -133,7 +138,11 @@ class CompiledQuery {
|
|
|
133
138
|
fn: () => {
|
|
134
139
|
store.batch(() => {
|
|
135
140
|
Object.entries(this.inputCollections).forEach(([key, collection2]) => {
|
|
136
|
-
this.sendChangesToInput(
|
|
141
|
+
this.sendChangesToInput(
|
|
142
|
+
key,
|
|
143
|
+
collection2.derivedChanges.state,
|
|
144
|
+
collection2.config.getId
|
|
145
|
+
);
|
|
137
146
|
});
|
|
138
147
|
this.incrementVersion();
|
|
139
148
|
this.sendFrontierToAllInputs();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiled-query.cjs","sources":["../../../src/query/compiled-query.ts"],"sourcesContent":["import { D2, MessageType, MultiSet, output } from \"@electric-sql/d2ts\"\nimport { Effect, batch } from \"@tanstack/store\"\nimport { Collection } from \"../collection.js\"\nimport { compileQueryPipeline } from \"./pipeline-compiler.js\"\nimport type { ChangeMessage, SyncConfig } from \"../types.js\"\nimport type {\n IStreamBuilder,\n MultiSetArray,\n RootStreamBuilder,\n} from \"@electric-sql/d2ts\"\nimport type { QueryBuilder, ResultsFromContext } from \"./query-builder.js\"\nimport type { Context, Schema } from \"./types.js\"\n\nexport function compileQuery<TContext extends Context<Schema>>(\n queryBuilder: QueryBuilder<TContext>\n) {\n return new CompiledQuery<ResultsFromContext<TContext>>(queryBuilder)\n}\n\nexport class CompiledQuery<TResults extends object = Record<string, unknown>> {\n private graph: D2\n private inputs: Record<string, RootStreamBuilder<any>>\n private inputCollections: Record<string, Collection<any>>\n private resultCollection: Collection<TResults>\n public state: `compiled` | `running` | `stopped` = `compiled`\n private version = 0\n private unsubscribeEffect?: () => void\n\n constructor(queryBuilder: QueryBuilder<Context<Schema>>) {\n const query = queryBuilder._query\n const collections = query.collections\n\n if (!collections) {\n throw new Error(`No collections provided`)\n }\n\n this.inputCollections = collections\n\n const graph = new D2({ initialFrontier: this.version })\n const inputs = Object.fromEntries(\n Object.entries(collections).map(([key]) => [key, graph.newInput<any>()])\n )\n\n const sync: SyncConfig<TResults>[`sync`] = ({ begin, write, commit }) => {\n compileQueryPipeline<IStreamBuilder<[unknown, TResults]>>(\n query,\n inputs\n ).pipe(\n output(({ type, data }) => {\n if (type === MessageType.DATA) {\n begin()\n data.collection\n .getInner()\n .reduce((acc, [[key, value], multiplicity]) => {\n const changes = acc.get(key) || {\n deletes: 0,\n inserts: 0,\n value,\n }\n if (multiplicity < 0) {\n changes.deletes += Math.abs(multiplicity)\n } else if (multiplicity > 0) {\n changes.inserts += multiplicity\n changes.value = value\n }\n acc.set(key, changes)\n return acc\n }, new Map<unknown, { deletes: number; inserts: number; value: TResults }>())\n .forEach((changes, rawKey) => {\n const key = (rawKey as any).toString()\n const { deletes, inserts, value } = changes\n if (inserts && !deletes) {\n write({\n key,\n value: value,\n type: `insert`,\n })\n } else if (inserts >= deletes) {\n write({\n key,\n value: value,\n type: `update`,\n })\n } else if (deletes > 0) {\n write({\n key,\n value: value,\n type: `delete`,\n })\n }\n })\n commit()\n }\n })\n )\n graph.finalize()\n }\n\n this.graph = graph\n this.inputs = inputs\n this.resultCollection = new Collection<TResults>({\n id: crypto.randomUUID(), // TODO: remove when we don't require any more\n sync: {\n sync,\n },\n })\n }\n\n get results() {\n return this.resultCollection\n }\n\n private sendChangesToInput(inputKey: string, changes: Array<ChangeMessage>) {\n const input = this.inputs[inputKey]!\n const multiSetArray: MultiSetArray<unknown> = []\n for (const change of changes) {\n if (change.type === `insert`) {\n multiSetArray.push([change.value, 1])\n } else if (change.type === `update`) {\n multiSetArray.push([change.previousValue, -1])\n multiSetArray.push([change.value, 1])\n } else {\n // change.type === `delete`\n multiSetArray.push([change.value, -1])\n }\n }\n input.sendData(this.version, new MultiSet(multiSetArray))\n }\n\n private sendFrontierToInput(inputKey: string) {\n const input = this.inputs[inputKey]!\n input.sendFrontier(this.version)\n }\n\n private sendFrontierToAllInputs() {\n Object.entries(this.inputs).forEach(([key]) => {\n this.sendFrontierToInput(key)\n })\n }\n\n private incrementVersion() {\n this.version++\n }\n\n private runGraph() {\n this.graph.run()\n }\n\n start() {\n if (this.state === `running`) {\n throw new Error(`Query is already running`)\n } else if (this.state === `stopped`) {\n throw new Error(`Query is stopped`)\n }\n\n batch(() => {\n Object.entries(this.inputCollections).forEach(([key, collection]) => {\n this.sendChangesToInput(key, collection.currentStateAsChanges())\n })\n this.incrementVersion()\n this.sendFrontierToAllInputs()\n this.runGraph()\n })\n\n const changeEffect = new Effect({\n fn: () => {\n batch(() => {\n Object.entries(this.inputCollections).forEach(([key, collection]) => {\n this.sendChangesToInput(key, collection.derivedChanges.state)\n })\n this.incrementVersion()\n this.sendFrontierToAllInputs()\n this.runGraph()\n })\n },\n deps: Object.values(this.inputCollections).map(\n (collection) => collection.derivedChanges\n ),\n })\n this.unsubscribeEffect = changeEffect.mount()\n\n this.state = `running`\n return () => {\n this.stop()\n }\n }\n\n stop() {\n this.unsubscribeEffect?.()\n this.unsubscribeEffect = undefined\n this.state = `stopped`\n }\n}\n"],"names":["D2","compileQueryPipeline","output","MessageType","Collection","MultiSet","batch","collection","Effect"],"mappings":";;;;;;AAaO,SAAS,aACd,cACA;AACO,SAAA,IAAI,cAA4C,YAAY;AACrE;AAEO,MAAM,cAAiE;AAAA,EAS5E,YAAY,cAA6C;AAJzD,SAAO,QAA4C;AACnD,SAAQ,UAAU;AAIhB,UAAM,QAAQ,aAAa;AAC3B,UAAM,cAAc,MAAM;AAE1B,QAAI,CAAC,aAAa;AACV,YAAA,IAAI,MAAM,yBAAyB;AAAA,IAAA;AAG3C,SAAK,mBAAmB;AAExB,UAAM,QAAQ,IAAIA,KAAA,GAAG,EAAE,iBAAiB,KAAK,SAAS;AACtD,UAAM,SAAS,OAAO;AAAA,MACpB,OAAO,QAAQ,WAAW,EAAE,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,MAAM,SAAA,CAAe,CAAC;AAAA,IACzE;AAEA,UAAM,OAAqC,CAAC,EAAE,OAAO,OAAO,aAAa;AACvEC,uBAAA;AAAA,QACE;AAAA,QACA;AAAA,MAAA,EACA;AAAA,QACAC,KAAAA,OAAO,CAAC,EAAE,MAAM,WAAW;AACrB,cAAA,SAASC,iBAAY,MAAM;AACvB,kBAAA;AACN,iBAAK,WACF,SACA,EAAA,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,GAAG,YAAY,MAAM;AAC7C,oBAAM,UAAU,IAAI,IAAI,GAAG,KAAK;AAAA,gBAC9B,SAAS;AAAA,gBACT,SAAS;AAAA,gBACT;AAAA,cACF;AACA,kBAAI,eAAe,GAAG;AACZ,wBAAA,WAAW,KAAK,IAAI,YAAY;AAAA,cAAA,WAC/B,eAAe,GAAG;AAC3B,wBAAQ,WAAW;AACnB,wBAAQ,QAAQ;AAAA,cAAA;AAEd,kBAAA,IAAI,KAAK,OAAO;AACb,qBAAA;AAAA,YAAA,uBACF,IAAoE,CAAC,EAC3E,QAAQ,CAAC,SAAS,WAAW;AACtB,oBAAA,MAAO,OAAe,SAAS;AACrC,oBAAM,EAAE,SAAS,SAAS,MAAU,IAAA;AAChC,kBAAA,WAAW,CAAC,SAAS;AACjB,sBAAA;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,MAAM;AAAA,gBAAA,CACP;AAAA,cAAA,WACQ,WAAW,SAAS;AACvB,sBAAA;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,MAAM;AAAA,gBAAA,CACP;AAAA,cAAA,WACQ,UAAU,GAAG;AAChB,sBAAA;AAAA,kBACJ;AAAA,kBACA;AAAA,kBACA,MAAM;AAAA,gBAAA,CACP;AAAA,cAAA;AAAA,YACH,CACD;AACI,mBAAA;AAAA,UAAA;AAAA,QAEV,CAAA;AAAA,MACH;AACA,YAAM,SAAS;AAAA,IACjB;AAEA,SAAK,QAAQ;AACb,SAAK,SAAS;AACT,SAAA,mBAAmB,IAAIC,sBAAqB;AAAA,MAC/C,IAAI,OAAO,WAAW;AAAA;AAAA,MACtB,MAAM;AAAA,QACJ;AAAA,MAAA;AAAA,IACF,CACD;AAAA,EAAA;AAAA,EAGH,IAAI,UAAU;AACZ,WAAO,KAAK;AAAA,EAAA;AAAA,EAGN,mBAAmB,UAAkB,SAA+B;AACpE,UAAA,QAAQ,KAAK,OAAO,QAAQ;AAClC,UAAM,gBAAwC,CAAC;AAC/C,eAAW,UAAU,SAAS;AACxB,UAAA,OAAO,SAAS,UAAU;AAC5B,sBAAc,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAAA,MACtC,WAAW,OAAO,SAAS,UAAU;AACnC,sBAAc,KAAK,CAAC,OAAO,eAAe,EAAE,CAAC;AAC7C,sBAAc,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAAA,MAAA,OAC/B;AAEL,sBAAc,KAAK,CAAC,OAAO,OAAO,EAAE,CAAC;AAAA,MAAA;AAAA,IACvC;AAEF,UAAM,SAAS,KAAK,SAAS,IAAIC,KAAAA,SAAS,aAAa,CAAC;AAAA,EAAA;AAAA,EAGlD,oBAAoB,UAAkB;AACtC,UAAA,QAAQ,KAAK,OAAO,QAAQ;AAC5B,UAAA,aAAa,KAAK,OAAO;AAAA,EAAA;AAAA,EAGzB,0BAA0B;AACzB,WAAA,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAAC,CAAC,GAAG,MAAM;AAC7C,WAAK,oBAAoB,GAAG;AAAA,IAAA,CAC7B;AAAA,EAAA;AAAA,EAGK,mBAAmB;AACpB,SAAA;AAAA,EAAA;AAAA,EAGC,WAAW;AACjB,SAAK,MAAM,IAAI;AAAA,EAAA;AAAA,EAGjB,QAAQ;AACF,QAAA,KAAK,UAAU,WAAW;AACtB,YAAA,IAAI,MAAM,0BAA0B;AAAA,IAC5C,WAAW,KAAK,UAAU,WAAW;AAC7B,YAAA,IAAI,MAAM,kBAAkB;AAAA,IAAA;AAGpCC,UAAAA,MAAM,MAAM;AACH,aAAA,QAAQ,KAAK,gBAAgB,EAAE,QAAQ,CAAC,CAAC,KAAKC,WAAU,MAAM;AACnE,aAAK,mBAAmB,KAAKA,YAAW,sBAAA,CAAuB;AAAA,MAAA,CAChE;AACD,WAAK,iBAAiB;AACtB,WAAK,wBAAwB;AAC7B,WAAK,SAAS;AAAA,IAAA,CACf;AAEK,UAAA,eAAe,IAAIC,aAAO;AAAA,MAC9B,IAAI,MAAM;AACRF,cAAAA,MAAM,MAAM;AACH,iBAAA,QAAQ,KAAK,gBAAgB,EAAE,QAAQ,CAAC,CAAC,KAAKC,WAAU,MAAM;AACnE,iBAAK,mBAAmB,KAAKA,YAAW,eAAe,KAAK;AAAA,UAAA,CAC7D;AACD,eAAK,iBAAiB;AACtB,eAAK,wBAAwB;AAC7B,eAAK,SAAS;AAAA,QAAA,CACf;AAAA,MACH;AAAA,MACA,MAAM,OAAO,OAAO,KAAK,gBAAgB,EAAE;AAAA,QACzC,CAACA,gBAAeA,YAAW;AAAA,MAAA;AAAA,IAC7B,CACD;AACI,SAAA,oBAAoB,aAAa,MAAM;AAE5C,SAAK,QAAQ;AACb,WAAO,MAAM;AACX,WAAK,KAAK;AAAA,IACZ;AAAA,EAAA;AAAA,EAGF,OAAO;;AACL,eAAK,sBAAL;AACA,SAAK,oBAAoB;AACzB,SAAK,QAAQ;AAAA,EAAA;AAEjB;;;"}
|
|
1
|
+
{"version":3,"file":"compiled-query.cjs","sources":["../../../src/query/compiled-query.ts"],"sourcesContent":["import { D2, MessageType, MultiSet, output } from \"@electric-sql/d2ts\"\nimport { Effect, batch } from \"@tanstack/store\"\nimport { Collection } from \"../collection.js\"\nimport { compileQueryPipeline } from \"./pipeline-compiler.js\"\nimport type { ChangeMessage, SyncConfig } from \"../types.js\"\nimport type {\n IStreamBuilder,\n MultiSetArray,\n RootStreamBuilder,\n} from \"@electric-sql/d2ts\"\nimport type { QueryBuilder, ResultsFromContext } from \"./query-builder.js\"\nimport type { Context, Schema } from \"./types.js\"\n\nexport function compileQuery<TContext extends Context<Schema>>(\n queryBuilder: QueryBuilder<TContext>\n) {\n return new CompiledQuery<\n ResultsFromContext<TContext> & { _key?: string | number }\n >(queryBuilder)\n}\n\nexport class CompiledQuery<TResults extends object = Record<string, unknown>> {\n private graph: D2\n private inputs: Record<string, RootStreamBuilder<any>>\n private inputCollections: Record<string, Collection<any>>\n private resultCollection: Collection<TResults>\n public state: `compiled` | `running` | `stopped` = `compiled`\n private version = 0\n private unsubscribeEffect?: () => void\n\n constructor(queryBuilder: QueryBuilder<Context<Schema>>) {\n const query = queryBuilder._query\n const collections = query.collections\n\n if (!collections) {\n throw new Error(`No collections provided`)\n }\n\n this.inputCollections = collections\n\n const graph = new D2({ initialFrontier: this.version })\n const inputs = Object.fromEntries(\n Object.entries(collections).map(([key]) => [key, graph.newInput<any>()])\n )\n\n const sync: SyncConfig<TResults>[`sync`] = ({ begin, write, commit }) => {\n compileQueryPipeline<IStreamBuilder<[unknown, TResults]>>(\n query,\n inputs\n ).pipe(\n output(({ type, data }) => {\n if (type === MessageType.DATA) {\n begin()\n data.collection\n .getInner()\n .reduce((acc, [[key, value], multiplicity]) => {\n const changes = acc.get(key) || {\n deletes: 0,\n inserts: 0,\n value,\n }\n if (multiplicity < 0) {\n changes.deletes += Math.abs(multiplicity)\n } else if (multiplicity > 0) {\n changes.inserts += multiplicity\n changes.value = value\n }\n acc.set(key, changes)\n return acc\n }, new Map<unknown, { deletes: number; inserts: number; value: TResults }>())\n .forEach((changes, rawKey) => {\n const { deletes, inserts, value } = changes\n const valueWithKey = { ...value, _key: rawKey }\n if (inserts && !deletes) {\n write({\n value: valueWithKey,\n type: `insert`,\n })\n } else if (inserts >= deletes) {\n write({\n value: valueWithKey,\n type: `update`,\n })\n } else if (deletes > 0) {\n write({\n value: valueWithKey,\n type: `delete`,\n })\n }\n })\n commit()\n }\n })\n )\n graph.finalize()\n }\n\n this.graph = graph\n this.inputs = inputs\n this.resultCollection = new Collection<TResults>({\n id: crypto.randomUUID(), // TODO: remove when we don't require any more\n getId: (val) => {\n return (val as any)._key\n },\n sync: {\n sync,\n },\n })\n }\n\n get results() {\n return this.resultCollection\n }\n\n private sendChangesToInput(\n inputKey: string,\n changes: Array<ChangeMessage>,\n getId: (item: ChangeMessage[`value`]) => any\n ) {\n const input = this.inputs[inputKey]!\n const multiSetArray: MultiSetArray<unknown> = []\n for (const change of changes) {\n const key = getId(change.value)\n if (change.type === `insert`) {\n multiSetArray.push([[key, change.value], 1])\n } else if (change.type === `update`) {\n multiSetArray.push([[key, change.previousValue], -1])\n multiSetArray.push([[key, change.value], 1])\n } else {\n // change.type === `delete`\n multiSetArray.push([[key, change.value], -1])\n }\n }\n input.sendData(this.version, new MultiSet(multiSetArray))\n }\n\n private sendFrontierToInput(inputKey: string) {\n const input = this.inputs[inputKey]!\n input.sendFrontier(this.version)\n }\n\n private sendFrontierToAllInputs() {\n Object.entries(this.inputs).forEach(([key]) => {\n this.sendFrontierToInput(key)\n })\n }\n\n private incrementVersion() {\n this.version++\n }\n\n private runGraph() {\n this.graph.run()\n }\n\n start() {\n if (this.state === `running`) {\n throw new Error(`Query is already running`)\n } else if (this.state === `stopped`) {\n throw new Error(`Query is stopped`)\n }\n\n batch(() => {\n Object.entries(this.inputCollections).forEach(([key, collection]) => {\n this.sendChangesToInput(\n key,\n collection.currentStateAsChanges(),\n collection.config.getId\n )\n })\n this.incrementVersion()\n this.sendFrontierToAllInputs()\n this.runGraph()\n })\n\n const changeEffect = new Effect({\n fn: () => {\n batch(() => {\n Object.entries(this.inputCollections).forEach(([key, collection]) => {\n this.sendChangesToInput(\n key,\n collection.derivedChanges.state,\n collection.config.getId\n )\n })\n this.incrementVersion()\n this.sendFrontierToAllInputs()\n this.runGraph()\n })\n },\n deps: Object.values(this.inputCollections).map(\n (collection) => collection.derivedChanges\n ),\n })\n this.unsubscribeEffect = changeEffect.mount()\n\n this.state = `running`\n return () => {\n this.stop()\n }\n }\n\n stop() {\n this.unsubscribeEffect?.()\n this.unsubscribeEffect = undefined\n this.state = `stopped`\n }\n}\n"],"names":["D2","compileQueryPipeline","output","MessageType","Collection","MultiSet","batch","collection","Effect"],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Collection } from '../collection.js';
|
|
2
2
|
import { QueryBuilder } from './query-builder.js';
|
|
3
3
|
import { Context, Schema } from './types.js';
|
|
4
|
-
export declare function compileQuery<TContext extends Context<Schema>>(queryBuilder: QueryBuilder<TContext>): CompiledQuery<(TContext["result"] extends object ? TContext["result"] : TContext["
|
|
4
|
+
export declare function compileQuery<TContext extends Context<Schema>>(queryBuilder: QueryBuilder<TContext>): CompiledQuery<((TContext["result"] extends object ? TContext["result"] : TContext["hasJoin"] extends true ? TContext["schema"] : TContext["default"] extends keyof TContext["schema"] ? TContext["schema"][TContext["default"]] : never) extends infer T ? { [K in keyof T]: (TContext["result"] extends object ? TContext["result"] : TContext["hasJoin"] extends true ? TContext["schema"] : TContext["default"] extends keyof TContext["schema"] ? TContext["schema"][TContext["default"]] : never)[K]; } : never) & {
|
|
5
|
+
_key?: string | number;
|
|
6
|
+
}>;
|
|
5
7
|
export declare class CompiledQuery<TResults extends object = Record<string, unknown>> {
|
|
6
8
|
private graph;
|
|
7
9
|
private inputs;
|
|
@@ -2,11 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const extractors = require("./extractors.cjs");
|
|
4
4
|
const utils = require("./utils.cjs");
|
|
5
|
-
function
|
|
5
|
+
function evaluateWhereOnNamespacedRow(namespacedRow, where, mainTableAlias, joinedTableAlias) {
|
|
6
|
+
return where.every((item) => {
|
|
7
|
+
if (typeof item === `function`) {
|
|
8
|
+
return item(namespacedRow);
|
|
9
|
+
} else {
|
|
10
|
+
return evaluateConditionOnNamespacedRow(
|
|
11
|
+
namespacedRow,
|
|
12
|
+
item,
|
|
13
|
+
mainTableAlias,
|
|
14
|
+
joinedTableAlias
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function evaluateConditionOnNamespacedRow(namespacedRow, condition, mainTableAlias, joinedTableAlias) {
|
|
6
20
|
if (condition.length === 3 && !Array.isArray(condition[0])) {
|
|
7
21
|
const [left, comparator, right] = condition;
|
|
8
|
-
return
|
|
9
|
-
|
|
22
|
+
return evaluateSimpleConditionOnNamespacedRow(
|
|
23
|
+
namespacedRow,
|
|
10
24
|
left,
|
|
11
25
|
comparator,
|
|
12
26
|
right,
|
|
@@ -15,8 +29,8 @@ function evaluateConditionOnNestedRow(nestedRow, condition, mainTableAlias, join
|
|
|
15
29
|
);
|
|
16
30
|
}
|
|
17
31
|
if (condition.length > 3 && !Array.isArray(condition[0]) && typeof condition[1] === `string` && ![`and`, `or`].includes(condition[1])) {
|
|
18
|
-
let result =
|
|
19
|
-
|
|
32
|
+
let result = evaluateSimpleConditionOnNamespacedRow(
|
|
33
|
+
namespacedRow,
|
|
20
34
|
condition[0],
|
|
21
35
|
condition[1],
|
|
22
36
|
condition[2],
|
|
@@ -26,8 +40,8 @@ function evaluateConditionOnNestedRow(nestedRow, condition, mainTableAlias, join
|
|
|
26
40
|
for (let i = 3; i < condition.length; i += 4) {
|
|
27
41
|
const logicalOp = condition[i];
|
|
28
42
|
if (i + 3 <= condition.length) {
|
|
29
|
-
const nextResult =
|
|
30
|
-
|
|
43
|
+
const nextResult = evaluateSimpleConditionOnNamespacedRow(
|
|
44
|
+
namespacedRow,
|
|
31
45
|
condition[i + 1],
|
|
32
46
|
condition[i + 2],
|
|
33
47
|
condition[i + 3],
|
|
@@ -44,8 +58,8 @@ function evaluateConditionOnNestedRow(nestedRow, condition, mainTableAlias, join
|
|
|
44
58
|
return result;
|
|
45
59
|
}
|
|
46
60
|
if (condition.length > 0 && Array.isArray(condition[0])) {
|
|
47
|
-
let result =
|
|
48
|
-
|
|
61
|
+
let result = evaluateConditionOnNamespacedRow(
|
|
62
|
+
namespacedRow,
|
|
49
63
|
condition[0],
|
|
50
64
|
mainTableAlias,
|
|
51
65
|
joinedTableAlias
|
|
@@ -55,15 +69,15 @@ function evaluateConditionOnNestedRow(nestedRow, condition, mainTableAlias, join
|
|
|
55
69
|
const operator = condition[i];
|
|
56
70
|
const nextCondition = condition[i + 1];
|
|
57
71
|
if (operator === `and`) {
|
|
58
|
-
result = result &&
|
|
59
|
-
|
|
72
|
+
result = result && evaluateConditionOnNamespacedRow(
|
|
73
|
+
namespacedRow,
|
|
60
74
|
nextCondition,
|
|
61
75
|
mainTableAlias,
|
|
62
76
|
joinedTableAlias
|
|
63
77
|
);
|
|
64
78
|
} else {
|
|
65
|
-
result = result ||
|
|
66
|
-
|
|
79
|
+
result = result || evaluateConditionOnNamespacedRow(
|
|
80
|
+
namespacedRow,
|
|
67
81
|
nextCondition,
|
|
68
82
|
mainTableAlias,
|
|
69
83
|
joinedTableAlias
|
|
@@ -74,15 +88,15 @@ function evaluateConditionOnNestedRow(nestedRow, condition, mainTableAlias, join
|
|
|
74
88
|
}
|
|
75
89
|
return true;
|
|
76
90
|
}
|
|
77
|
-
function
|
|
78
|
-
const leftValue = extractors.
|
|
79
|
-
|
|
91
|
+
function evaluateSimpleConditionOnNamespacedRow(namespacedRow, left, comparator, right, mainTableAlias, joinedTableAlias) {
|
|
92
|
+
const leftValue = extractors.evaluateOperandOnNamespacedRow(
|
|
93
|
+
namespacedRow,
|
|
80
94
|
left,
|
|
81
95
|
mainTableAlias,
|
|
82
96
|
joinedTableAlias
|
|
83
97
|
);
|
|
84
|
-
const rightValue = extractors.
|
|
85
|
-
|
|
98
|
+
const rightValue = extractors.evaluateOperandOnNamespacedRow(
|
|
99
|
+
namespacedRow,
|
|
86
100
|
right,
|
|
87
101
|
mainTableAlias,
|
|
88
102
|
joinedTableAlias
|
|
@@ -141,6 +155,7 @@ function evaluateSimpleConditionOnNestedRow(nestedRow, left, comparator, right,
|
|
|
141
155
|
return false;
|
|
142
156
|
}
|
|
143
157
|
}
|
|
144
|
-
exports.
|
|
145
|
-
exports.
|
|
158
|
+
exports.evaluateConditionOnNamespacedRow = evaluateConditionOnNamespacedRow;
|
|
159
|
+
exports.evaluateSimpleConditionOnNamespacedRow = evaluateSimpleConditionOnNamespacedRow;
|
|
160
|
+
exports.evaluateWhereOnNamespacedRow = evaluateWhereOnNamespacedRow;
|
|
146
161
|
//# sourceMappingURL=evaluators.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluators.cjs","sources":["../../../src/query/evaluators.ts"],"sourcesContent":["import { evaluateOperandOnNestedRow } from \"./extractors.js\"\nimport { compareValues, convertLikeToRegex, isValueInArray } from \"./utils.js\"\nimport type {\n Comparator,\n Condition,\n ConditionOperand,\n LogicalOperator,\n SimpleCondition,\n} from \"./schema.js\"\n\n/**\n * Evaluates a condition against a nested row structure\n */\nexport function evaluateConditionOnNestedRow(\n nestedRow: Record<string, unknown>,\n condition: Condition,\n mainTableAlias?: string,\n joinedTableAlias?: string\n): boolean {\n // Handle simple conditions with exactly 3 elements\n if (condition.length === 3 && !Array.isArray(condition[0])) {\n const [left, comparator, right] = condition as SimpleCondition\n return evaluateSimpleConditionOnNestedRow(\n nestedRow,\n left,\n comparator,\n right,\n mainTableAlias,\n joinedTableAlias\n )\n }\n\n // Handle flat composite conditions (multiple conditions in a single array)\n if (\n condition.length > 3 &&\n !Array.isArray(condition[0]) &&\n typeof condition[1] === `string` &&\n ![`and`, `or`].includes(condition[1] as string)\n ) {\n // Start with the first condition (first 3 elements)\n let result = evaluateSimpleConditionOnNestedRow(\n nestedRow,\n condition[0],\n condition[1] as Comparator,\n condition[2],\n mainTableAlias,\n joinedTableAlias\n )\n\n // Process the rest in groups: logical operator, then 3 elements for each condition\n for (let i = 3; i < condition.length; i += 4) {\n const logicalOp = condition[i] as LogicalOperator\n\n // Make sure we have a complete condition to evaluate\n if (i + 3 <= condition.length) {\n const nextResult = evaluateSimpleConditionOnNestedRow(\n nestedRow,\n condition[i + 1],\n condition[i + 2] as Comparator,\n condition[i + 3],\n mainTableAlias,\n joinedTableAlias\n )\n\n // Apply the logical operator\n if (logicalOp === `and`) {\n result = result && nextResult\n } else {\n // logicalOp === `or`\n result = result || nextResult\n }\n }\n }\n\n return result\n }\n\n // Handle nested composite conditions where the first element is an array\n if (condition.length > 0 && Array.isArray(condition[0])) {\n // Start with the first condition\n let result = evaluateConditionOnNestedRow(\n nestedRow,\n condition[0] as Condition,\n mainTableAlias,\n joinedTableAlias\n )\n\n // Process the rest of the conditions and logical operators in pairs\n for (let i = 1; i < condition.length; i += 2) {\n if (i + 1 >= condition.length) break // Make sure we have a pair\n\n const operator = condition[i] as LogicalOperator\n const nextCondition = condition[i + 1] as Condition\n\n // Apply the logical operator\n if (operator === `and`) {\n result =\n result &&\n evaluateConditionOnNestedRow(\n nestedRow,\n nextCondition,\n mainTableAlias,\n joinedTableAlias\n )\n } else {\n // logicalOp === `or`\n result =\n result ||\n evaluateConditionOnNestedRow(\n nestedRow,\n nextCondition,\n mainTableAlias,\n joinedTableAlias\n )\n }\n }\n\n return result\n }\n\n // Fallback - this should not happen with valid conditions\n return true\n}\n\n/**\n * Evaluates a simple condition against a nested row structure\n */\nexport function evaluateSimpleConditionOnNestedRow(\n nestedRow: Record<string, unknown>,\n left: ConditionOperand,\n comparator: Comparator,\n right: ConditionOperand,\n mainTableAlias?: string,\n joinedTableAlias?: string\n): boolean {\n const leftValue = evaluateOperandOnNestedRow(\n nestedRow,\n left,\n mainTableAlias,\n joinedTableAlias\n )\n\n const rightValue = evaluateOperandOnNestedRow(\n nestedRow,\n right,\n mainTableAlias,\n joinedTableAlias\n )\n\n // The rest of the function remains the same as evaluateSimpleCondition\n switch (comparator) {\n case `=`:\n return leftValue === rightValue\n case `!=`:\n return leftValue !== rightValue\n case `<`:\n return compareValues(leftValue, rightValue, `<`)\n case `<=`:\n return compareValues(leftValue, rightValue, `<=`)\n case `>`:\n return compareValues(leftValue, rightValue, `>`)\n case `>=`:\n return compareValues(leftValue, rightValue, `>=`)\n case `like`:\n case `not like`:\n if (typeof leftValue === `string` && typeof rightValue === `string`) {\n // Convert SQL LIKE pattern to proper regex pattern\n const pattern = convertLikeToRegex(rightValue)\n const matches = new RegExp(`^${pattern}$`, `i`).test(leftValue)\n return comparator === `like` ? matches : !matches\n }\n return comparator === `like` ? false : true\n case `in`:\n // If right value is not an array, we can't do an IN operation\n if (!Array.isArray(rightValue)) {\n return false\n }\n\n // For empty arrays, nothing is contained in them\n if (rightValue.length === 0) {\n return false\n }\n\n // Handle array-to-array comparison (check if any element in leftValue exists in rightValue)\n if (Array.isArray(leftValue)) {\n return leftValue.some((item) => isValueInArray(item, rightValue))\n }\n\n // Handle single value comparison\n return isValueInArray(leftValue, rightValue)\n\n case `not in`:\n // If right value is not an array, everything is \"not in\" it\n if (!Array.isArray(rightValue)) {\n return true\n }\n\n // For empty arrays, everything is \"not in\" them\n if (rightValue.length === 0) {\n return true\n }\n\n // Handle array-to-array comparison (check if no element in leftValue exists in rightValue)\n if (Array.isArray(leftValue)) {\n return !leftValue.some((item) => isValueInArray(item, rightValue))\n }\n\n // Handle single value comparison\n return !isValueInArray(leftValue, rightValue)\n\n case `is`:\n return leftValue === rightValue\n case `is not`:\n // Properly handle null/undefined checks\n if (rightValue === null) {\n return leftValue !== null && leftValue !== undefined\n }\n return leftValue !== rightValue\n default:\n return false\n }\n}\n"],"names":["evaluateOperandOnNestedRow","compareValues","convertLikeToRegex","isValueInArray"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"evaluators.cjs","sources":["../../../src/query/evaluators.ts"],"sourcesContent":["import { evaluateOperandOnNamespacedRow } from \"./extractors.js\"\nimport { compareValues, convertLikeToRegex, isValueInArray } from \"./utils.js\"\nimport type {\n Comparator,\n Condition,\n ConditionOperand,\n LogicalOperator,\n SimpleCondition,\n Where,\n WhereCallback,\n} from \"./schema.js\"\nimport type { NamespacedRow } from \"../types.js\"\n\n/**\n * Evaluates a Where clause (which is always an array of conditions and/or callbacks) against a nested row structure\n */\nexport function evaluateWhereOnNamespacedRow(\n namespacedRow: NamespacedRow,\n where: Where,\n mainTableAlias?: string,\n joinedTableAlias?: string\n): boolean {\n // Where is always an array of conditions and/or callbacks\n // Evaluate all items and combine with AND logic\n return where.every((item) => {\n if (typeof item === `function`) {\n return (item as WhereCallback)(namespacedRow)\n } else {\n return evaluateConditionOnNamespacedRow(\n namespacedRow,\n item as Condition,\n mainTableAlias,\n joinedTableAlias\n )\n }\n })\n}\n\n/**\n * Evaluates a condition against a nested row structure\n */\nexport function evaluateConditionOnNamespacedRow(\n namespacedRow: NamespacedRow,\n condition: Condition,\n mainTableAlias?: string,\n joinedTableAlias?: string\n): boolean {\n // Handle simple conditions with exactly 3 elements\n if (condition.length === 3 && !Array.isArray(condition[0])) {\n const [left, comparator, right] = condition as SimpleCondition\n return evaluateSimpleConditionOnNamespacedRow(\n namespacedRow,\n left,\n comparator,\n right,\n mainTableAlias,\n joinedTableAlias\n )\n }\n\n // Handle flat composite conditions (multiple conditions in a single array)\n if (\n condition.length > 3 &&\n !Array.isArray(condition[0]) &&\n typeof condition[1] === `string` &&\n ![`and`, `or`].includes(condition[1] as string)\n ) {\n // Start with the first condition (first 3 elements)\n let result = evaluateSimpleConditionOnNamespacedRow(\n namespacedRow,\n condition[0],\n condition[1] as Comparator,\n condition[2],\n mainTableAlias,\n joinedTableAlias\n )\n\n // Process the rest in groups: logical operator, then 3 elements for each condition\n for (let i = 3; i < condition.length; i += 4) {\n const logicalOp = condition[i] as LogicalOperator\n\n // Make sure we have a complete condition to evaluate\n if (i + 3 <= condition.length) {\n const nextResult = evaluateSimpleConditionOnNamespacedRow(\n namespacedRow,\n condition[i + 1],\n condition[i + 2] as Comparator,\n condition[i + 3],\n mainTableAlias,\n joinedTableAlias\n )\n\n // Apply the logical operator\n if (logicalOp === `and`) {\n result = result && nextResult\n } else {\n // logicalOp === `or`\n result = result || nextResult\n }\n }\n }\n\n return result\n }\n\n // Handle nested composite conditions where the first element is an array\n if (condition.length > 0 && Array.isArray(condition[0])) {\n // Start with the first condition\n let result = evaluateConditionOnNamespacedRow(\n namespacedRow,\n condition[0] as Condition,\n mainTableAlias,\n joinedTableAlias\n )\n\n // Process the rest of the conditions and logical operators in pairs\n for (let i = 1; i < condition.length; i += 2) {\n if (i + 1 >= condition.length) break // Make sure we have a pair\n\n const operator = condition[i] as LogicalOperator\n const nextCondition = condition[i + 1] as Condition\n\n // Apply the logical operator\n if (operator === `and`) {\n result =\n result &&\n evaluateConditionOnNamespacedRow(\n namespacedRow,\n nextCondition,\n mainTableAlias,\n joinedTableAlias\n )\n } else {\n // logicalOp === `or`\n result =\n result ||\n evaluateConditionOnNamespacedRow(\n namespacedRow,\n nextCondition,\n mainTableAlias,\n joinedTableAlias\n )\n }\n }\n\n return result\n }\n\n // Fallback - this should not happen with valid conditions\n return true\n}\n\n/**\n * Evaluates a simple condition against a nested row structure\n */\nexport function evaluateSimpleConditionOnNamespacedRow(\n namespacedRow: Record<string, unknown>,\n left: ConditionOperand,\n comparator: Comparator,\n right: ConditionOperand,\n mainTableAlias?: string,\n joinedTableAlias?: string\n): boolean {\n const leftValue = evaluateOperandOnNamespacedRow(\n namespacedRow,\n left,\n mainTableAlias,\n joinedTableAlias\n )\n\n const rightValue = evaluateOperandOnNamespacedRow(\n namespacedRow,\n right,\n mainTableAlias,\n joinedTableAlias\n )\n\n // The rest of the function remains the same as evaluateSimpleCondition\n switch (comparator) {\n case `=`:\n return leftValue === rightValue\n case `!=`:\n return leftValue !== rightValue\n case `<`:\n return compareValues(leftValue, rightValue, `<`)\n case `<=`:\n return compareValues(leftValue, rightValue, `<=`)\n case `>`:\n return compareValues(leftValue, rightValue, `>`)\n case `>=`:\n return compareValues(leftValue, rightValue, `>=`)\n case `like`:\n case `not like`:\n if (typeof leftValue === `string` && typeof rightValue === `string`) {\n // Convert SQL LIKE pattern to proper regex pattern\n const pattern = convertLikeToRegex(rightValue)\n const matches = new RegExp(`^${pattern}$`, `i`).test(leftValue)\n return comparator === `like` ? matches : !matches\n }\n return comparator === `like` ? false : true\n case `in`:\n // If right value is not an array, we can't do an IN operation\n if (!Array.isArray(rightValue)) {\n return false\n }\n\n // For empty arrays, nothing is contained in them\n if (rightValue.length === 0) {\n return false\n }\n\n // Handle array-to-array comparison (check if any element in leftValue exists in rightValue)\n if (Array.isArray(leftValue)) {\n return leftValue.some((item) => isValueInArray(item, rightValue))\n }\n\n // Handle single value comparison\n return isValueInArray(leftValue, rightValue)\n\n case `not in`:\n // If right value is not an array, everything is \"not in\" it\n if (!Array.isArray(rightValue)) {\n return true\n }\n\n // For empty arrays, everything is \"not in\" them\n if (rightValue.length === 0) {\n return true\n }\n\n // Handle array-to-array comparison (check if no element in leftValue exists in rightValue)\n if (Array.isArray(leftValue)) {\n return !leftValue.some((item) => isValueInArray(item, rightValue))\n }\n\n // Handle single value comparison\n return !isValueInArray(leftValue, rightValue)\n\n case `is`:\n return leftValue === rightValue\n case `is not`:\n // Properly handle null/undefined checks\n if (rightValue === null) {\n return leftValue !== null && leftValue !== undefined\n }\n return leftValue !== rightValue\n default:\n return false\n }\n}\n"],"names":["evaluateOperandOnNamespacedRow","compareValues","convertLikeToRegex","isValueInArray"],"mappings":"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"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { Comparator, Condition, ConditionOperand } from './schema.js';
|
|
1
|
+
import { Comparator, Condition, ConditionOperand, Where } from './schema.js';
|
|
2
|
+
import { NamespacedRow } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Evaluates a Where clause (which is always an array of conditions and/or callbacks) against a nested row structure
|
|
5
|
+
*/
|
|
6
|
+
export declare function evaluateWhereOnNamespacedRow(namespacedRow: NamespacedRow, where: Where, mainTableAlias?: string, joinedTableAlias?: string): boolean;
|
|
2
7
|
/**
|
|
3
8
|
* Evaluates a condition against a nested row structure
|
|
4
9
|
*/
|
|
5
|
-
export declare function
|
|
10
|
+
export declare function evaluateConditionOnNamespacedRow(namespacedRow: NamespacedRow, condition: Condition, mainTableAlias?: string, joinedTableAlias?: string): boolean;
|
|
6
11
|
/**
|
|
7
12
|
* Evaluates a simple condition against a nested row structure
|
|
8
13
|
*/
|
|
9
|
-
export declare function
|
|
14
|
+
export declare function evaluateSimpleConditionOnNamespacedRow(namespacedRow: Record<string, unknown>, left: ConditionOperand, comparator: Comparator, right: ConditionOperand, mainTableAlias?: string, joinedTableAlias?: string): boolean;
|