@tanstack/db 0.5.11 → 0.5.13
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/SortedMap.cjs +40 -26
- package/dist/cjs/SortedMap.cjs.map +1 -1
- package/dist/cjs/SortedMap.d.cts +10 -15
- package/dist/cjs/collection/change-events.cjs.map +1 -1
- package/dist/cjs/collection/changes.cjs +2 -0
- package/dist/cjs/collection/changes.cjs.map +1 -1
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/events.d.cts +12 -4
- package/dist/cjs/collection/index.cjs +2 -1
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/indexes.cjs.map +1 -1
- package/dist/cjs/collection/lifecycle.cjs.map +1 -1
- package/dist/cjs/collection/mutations.cjs +5 -2
- package/dist/cjs/collection/mutations.cjs.map +1 -1
- package/dist/cjs/collection/state.cjs +6 -5
- package/dist/cjs/collection/state.cjs.map +1 -1
- package/dist/cjs/collection/state.d.cts +4 -1
- package/dist/cjs/collection/subscription.cjs +91 -57
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +26 -4
- package/dist/cjs/collection/sync.cjs +11 -6
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/errors.cjs +9 -0
- package/dist/cjs/errors.cjs.map +1 -1
- package/dist/cjs/errors.d.cts +3 -0
- package/dist/cjs/event-emitter.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.cjs.map +1 -1
- package/dist/cjs/indexes/btree-index.cjs +8 -6
- package/dist/cjs/indexes/btree-index.cjs.map +1 -1
- package/dist/cjs/indexes/lazy-index.cjs.map +1 -1
- package/dist/cjs/indexes/reverse-index.cjs.map +1 -1
- package/dist/cjs/local-only.cjs.map +1 -1
- package/dist/cjs/local-storage.cjs.map +1 -1
- package/dist/cjs/optimistic-action.cjs.map +1 -1
- package/dist/cjs/paced-mutations.cjs.map +1 -1
- package/dist/cjs/proxy.cjs.map +1 -1
- package/dist/cjs/query/builder/functions.cjs.map +1 -1
- package/dist/cjs/query/builder/index.cjs.map +1 -1
- package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
- package/dist/cjs/query/compiler/expressions.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/index.cjs.map +1 -1
- package/dist/cjs/query/compiler/joins.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.cjs +91 -38
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +6 -2
- package/dist/cjs/query/compiler/select.cjs.map +1 -1
- package/dist/cjs/query/expression-helpers.cjs.map +1 -1
- package/dist/cjs/query/index.d.cts +1 -1
- package/dist/cjs/query/ir.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-registry.cjs.map +1 -1
- package/dist/cjs/query/live/collection-subscriber.cjs +30 -15
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/internal.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/optimizer.cjs.map +1 -1
- package/dist/cjs/query/predicate-utils.cjs +19 -2
- package/dist/cjs/query/predicate-utils.cjs.map +1 -1
- package/dist/cjs/query/predicate-utils.d.cts +32 -1
- package/dist/cjs/query/subset-dedupe.cjs.map +1 -1
- package/dist/cjs/scheduler.cjs.map +1 -1
- package/dist/cjs/strategies/debounceStrategy.cjs.map +1 -1
- package/dist/cjs/strategies/queueStrategy.cjs.map +1 -1
- package/dist/cjs/strategies/throttleStrategy.cjs.map +1 -1
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/types.d.cts +53 -8
- package/dist/cjs/utils/browser-polyfills.cjs.map +1 -1
- package/dist/cjs/utils/btree.cjs.map +1 -1
- package/dist/cjs/utils/comparison.cjs.map +1 -1
- package/dist/cjs/utils/cursor.cjs +39 -0
- package/dist/cjs/utils/cursor.cjs.map +1 -0
- package/dist/cjs/utils/cursor.d.cts +18 -0
- package/dist/cjs/utils/index-optimization.cjs.map +1 -1
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/esm/SortedMap.d.ts +10 -15
- package/dist/esm/SortedMap.js +40 -26
- package/dist/esm/SortedMap.js.map +1 -1
- package/dist/esm/collection/change-events.js.map +1 -1
- package/dist/esm/collection/changes.js +2 -0
- package/dist/esm/collection/changes.js.map +1 -1
- package/dist/esm/collection/events.d.ts +12 -4
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.js +2 -1
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/indexes.js.map +1 -1
- package/dist/esm/collection/lifecycle.js.map +1 -1
- package/dist/esm/collection/mutations.js +6 -3
- package/dist/esm/collection/mutations.js.map +1 -1
- package/dist/esm/collection/state.d.ts +4 -1
- package/dist/esm/collection/state.js +6 -5
- package/dist/esm/collection/state.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +26 -4
- package/dist/esm/collection/subscription.js +92 -58
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.js +11 -6
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/errors.d.ts +3 -0
- package/dist/esm/errors.js +9 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/event-emitter.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +4 -2
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/esm/indexes/base-index.js.map +1 -1
- package/dist/esm/indexes/btree-index.js +8 -6
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/lazy-index.js.map +1 -1
- package/dist/esm/indexes/reverse-index.js.map +1 -1
- package/dist/esm/local-only.js.map +1 -1
- package/dist/esm/local-storage.js.map +1 -1
- package/dist/esm/optimistic-action.js.map +1 -1
- package/dist/esm/paced-mutations.js.map +1 -1
- package/dist/esm/proxy.js.map +1 -1
- package/dist/esm/query/builder/functions.js.map +1 -1
- package/dist/esm/query/builder/index.js.map +1 -1
- package/dist/esm/query/builder/ref-proxy.js.map +1 -1
- package/dist/esm/query/compiler/evaluators.js.map +1 -1
- package/dist/esm/query/compiler/expressions.js.map +1 -1
- package/dist/esm/query/compiler/group-by.js.map +1 -1
- package/dist/esm/query/compiler/index.js.map +1 -1
- package/dist/esm/query/compiler/joins.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +6 -2
- package/dist/esm/query/compiler/order-by.js +91 -38
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/select.js.map +1 -1
- package/dist/esm/query/expression-helpers.js.map +1 -1
- package/dist/esm/query/index.d.ts +1 -1
- package/dist/esm/query/ir.js.map +1 -1
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-registry.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.js +30 -15
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live/internal.js.map +1 -1
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/query/optimizer.js.map +1 -1
- package/dist/esm/query/predicate-utils.d.ts +32 -1
- package/dist/esm/query/predicate-utils.js +19 -2
- package/dist/esm/query/predicate-utils.js.map +1 -1
- package/dist/esm/query/subset-dedupe.js.map +1 -1
- package/dist/esm/scheduler.js.map +1 -1
- package/dist/esm/strategies/debounceStrategy.js.map +1 -1
- package/dist/esm/strategies/queueStrategy.js.map +1 -1
- package/dist/esm/strategies/throttleStrategy.js.map +1 -1
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +53 -8
- package/dist/esm/utils/browser-polyfills.js.map +1 -1
- package/dist/esm/utils/btree.js.map +1 -1
- package/dist/esm/utils/comparison.js.map +1 -1
- package/dist/esm/utils/cursor.d.ts +18 -0
- package/dist/esm/utils/cursor.js +39 -0
- package/dist/esm/utils/cursor.js.map +1 -0
- package/dist/esm/utils/index-optimization.js.map +1 -1
- package/dist/esm/utils.js.map +1 -1
- package/package.json +30 -28
- package/src/SortedMap.ts +50 -31
- package/src/collection/change-events.ts +20 -20
- package/src/collection/changes.ts +16 -12
- package/src/collection/events.ts +20 -10
- package/src/collection/index.ts +47 -46
- package/src/collection/indexes.ts +14 -14
- package/src/collection/lifecycle.ts +16 -16
- package/src/collection/mutations.ts +25 -20
- package/src/collection/state.ts +43 -36
- package/src/collection/subscription.ts +171 -90
- package/src/collection/sync.ts +34 -22
- package/src/duplicate-instance-check.ts +1 -1
- package/src/errors.ts +49 -40
- package/src/event-emitter.ts +5 -5
- package/src/index.ts +21 -21
- package/src/indexes/auto-index.ts +11 -11
- package/src/indexes/base-index.ts +13 -13
- package/src/indexes/btree-index.ts +21 -17
- package/src/indexes/index-options.ts +3 -3
- package/src/indexes/lazy-index.ts +8 -8
- package/src/indexes/reverse-index.ts +5 -5
- package/src/local-only.ts +12 -12
- package/src/local-storage.ts +17 -17
- package/src/optimistic-action.ts +5 -5
- package/src/paced-mutations.ts +6 -6
- package/src/proxy.ts +43 -43
- package/src/query/builder/functions.ts +28 -28
- package/src/query/builder/index.ts +22 -22
- package/src/query/builder/ref-proxy.ts +4 -4
- package/src/query/builder/types.ts +8 -8
- package/src/query/compiler/evaluators.ts +9 -9
- package/src/query/compiler/expressions.ts +6 -6
- package/src/query/compiler/group-by.ts +24 -24
- package/src/query/compiler/index.ts +44 -44
- package/src/query/compiler/joins.ts +37 -37
- package/src/query/compiler/order-by.ts +170 -77
- package/src/query/compiler/select.ts +13 -13
- package/src/query/compiler/types.ts +2 -2
- package/src/query/expression-helpers.ts +16 -16
- package/src/query/index.ts +10 -9
- package/src/query/ir.ts +13 -13
- package/src/query/live/collection-config-builder.ts +53 -53
- package/src/query/live/collection-registry.ts +6 -6
- package/src/query/live/collection-subscriber.ts +87 -48
- package/src/query/live/internal.ts +1 -1
- package/src/query/live/types.ts +4 -4
- package/src/query/live-query-collection.ts +15 -15
- package/src/query/optimizer.ts +29 -29
- package/src/query/predicate-utils.ts +105 -50
- package/src/query/subset-dedupe.ts +6 -6
- package/src/scheduler.ts +3 -3
- package/src/strategies/debounceStrategy.ts +6 -6
- package/src/strategies/index.ts +4 -4
- package/src/strategies/queueStrategy.ts +5 -5
- package/src/strategies/throttleStrategy.ts +6 -6
- package/src/strategies/types.ts +2 -2
- package/src/transactions.ts +9 -9
- package/src/types.ts +76 -18
- package/src/utils/array-utils.ts +1 -1
- package/src/utils/browser-polyfills.ts +2 -2
- package/src/utils/btree.ts +22 -22
- package/src/utils/comparison.ts +3 -3
- package/src/utils/cursor.ts +78 -0
- package/src/utils/index-optimization.ts +14 -14
- package/src/utils.ts +4 -4
package/dist/esm/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","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\nimport { deepEquals, isTemporal } from \"./utils\"\n\n/**\n * Set of array methods that iterate with callbacks and may return elements.\n * Hoisted to module scope to avoid creating a new Set on every property access.\n */\nconst CALLBACK_ITERATION_METHODS = new Set([\n `find`,\n `findLast`,\n `findIndex`,\n `findLastIndex`,\n `filter`,\n `map`,\n `flatMap`,\n `forEach`,\n `some`,\n `every`,\n `reduce`,\n `reduceRight`,\n])\n\n/**\n * Set of array methods that modify the array in place.\n */\nconst ARRAY_MODIFYING_METHODS = new Set([\n `pop`,\n `push`,\n `shift`,\n `unshift`,\n `splice`,\n `sort`,\n `reverse`,\n `fill`,\n `copyWithin`,\n])\n\n/**\n * Set of Map/Set methods that modify the collection in place.\n */\nconst MAP_SET_MODIFYING_METHODS = new Set([`set`, `delete`, `clear`, `add`])\n\n/**\n * Set of Map/Set iterator methods.\n */\nconst MAP_SET_ITERATOR_METHODS = new Set([\n `entries`,\n `keys`,\n `values`,\n `forEach`,\n])\n\n/**\n * Check if a value is a proxiable object (not Date, RegExp, or Temporal)\n */\nfunction isProxiableObject(\n value: unknown\n): value is Record<string | symbol, unknown> {\n return (\n value !== null &&\n typeof value === `object` &&\n !((value as any) instanceof Date) &&\n !((value as any) instanceof RegExp) &&\n !isTemporal(value)\n )\n}\n\n/**\n * Creates a handler for array iteration methods that ensures proxied elements\n * are passed to callbacks and returned from methods like find/filter.\n */\nfunction createArrayIterationHandler<T extends object>(\n methodName: string,\n methodFn: (...args: Array<unknown>) => unknown,\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n ) => { proxy: Record<string | symbol, unknown> }\n): ((...args: Array<unknown>) => unknown) | undefined {\n if (!CALLBACK_ITERATION_METHODS.has(methodName)) {\n return undefined\n }\n\n return function (...args: Array<unknown>) {\n const callback = args[0]\n if (typeof callback !== `function`) {\n return methodFn.apply(changeTracker.copy_, args)\n }\n\n // Create a helper to get proxied version of an array element\n const getProxiedElement = (element: unknown, index: number): unknown => {\n if (isProxiableObject(element)) {\n const nestedParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: String(index),\n }\n const { proxy: elementProxy } = memoizedCreateChangeProxy(\n element,\n nestedParent\n )\n return elementProxy\n }\n return element\n }\n\n // Wrap the callback to pass proxied elements\n const wrappedCallback = function (\n this: unknown,\n element: unknown,\n index: number,\n array: unknown\n ) {\n const proxiedElement = getProxiedElement(element, index)\n return callback.call(this, proxiedElement, index, array)\n }\n\n // For reduce/reduceRight, the callback signature is different\n if (methodName === `reduce` || methodName === `reduceRight`) {\n const reduceCallback = function (\n this: unknown,\n accumulator: unknown,\n element: unknown,\n index: number,\n array: unknown\n ) {\n const proxiedElement = getProxiedElement(element, index)\n return callback.call(this, accumulator, proxiedElement, index, array)\n }\n return methodFn.apply(changeTracker.copy_, [\n reduceCallback,\n ...args.slice(1),\n ])\n }\n\n const result = methodFn.apply(changeTracker.copy_, [\n wrappedCallback,\n ...args.slice(1),\n ])\n\n // For find/findLast, proxy the returned element if it's an object\n if (\n (methodName === `find` || methodName === `findLast`) &&\n result &&\n typeof result === `object`\n ) {\n const foundIndex = (\n changeTracker.copy_ as unknown as Array<unknown>\n ).indexOf(result)\n if (foundIndex !== -1) {\n return getProxiedElement(result, foundIndex)\n }\n }\n\n // For filter, proxy each element in the result array\n if (methodName === `filter` && Array.isArray(result)) {\n return result.map((element) => {\n const originalIndex = (\n changeTracker.copy_ as unknown as Array<unknown>\n ).indexOf(element)\n if (originalIndex !== -1) {\n return getProxiedElement(element, originalIndex)\n }\n return element\n })\n }\n\n return result\n }\n}\n\n/**\n * Creates a Symbol.iterator handler for arrays that yields proxied elements.\n */\nfunction createArrayIteratorHandler<T extends object>(\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n ) => { proxy: Record<string | symbol, unknown> }\n): () => Iterator<unknown> {\n return function () {\n const array = changeTracker.copy_ as unknown as Array<unknown>\n let index = 0\n\n return {\n next() {\n if (index >= array.length) {\n return { done: true, value: undefined }\n }\n\n const element = array[index]\n let proxiedElement = element\n\n if (isProxiableObject(element)) {\n const nestedParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: String(index),\n }\n const { proxy: elementProxy } = memoizedCreateChangeProxy(\n element,\n nestedParent\n )\n proxiedElement = elementProxy\n }\n\n index++\n return { done: false, value: proxiedElement }\n },\n [Symbol.iterator]() {\n return this\n },\n }\n }\n}\n\n/**\n * Creates a wrapper for methods that modify a collection (array, Map, Set).\n * The wrapper calls the method and marks the change tracker as modified.\n */\nfunction createModifyingMethodHandler<T extends object>(\n methodFn: (...args: Array<unknown>) => unknown,\n changeTracker: ChangeTracker<T>,\n markChanged: (tracker: ChangeTracker<T>) => void\n): (...args: Array<unknown>) => unknown {\n return function (...args: Array<unknown>) {\n const result = methodFn.apply(changeTracker.copy_, args)\n markChanged(changeTracker)\n return result\n }\n}\n\n/**\n * Creates handlers for Map/Set iterator methods (entries, keys, values, forEach).\n * Returns proxied values for iteration to enable change tracking.\n */\nfunction createMapSetIteratorHandler<T extends object>(\n methodName: string,\n prop: string | symbol,\n methodFn: (...args: Array<unknown>) => unknown,\n target: Map<unknown, unknown> | Set<unknown>,\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n ) => { proxy: Record<string | symbol, unknown> },\n markChanged: (tracker: ChangeTracker<T>) => void\n): ((...args: Array<unknown>) => unknown) | undefined {\n const isIteratorMethod =\n MAP_SET_ITERATOR_METHODS.has(methodName) || prop === Symbol.iterator\n\n if (!isIteratorMethod) {\n return undefined\n }\n\n return function (this: unknown, ...args: Array<unknown>) {\n const result = methodFn.apply(changeTracker.copy_, args)\n\n // For forEach, wrap the callback to track changes\n if (methodName === `forEach`) {\n const callback = args[0]\n if (typeof callback === `function`) {\n const wrappedCallback = function (\n this: unknown,\n value: unknown,\n key: unknown,\n collection: unknown\n ) {\n const cbresult = callback.call(this, value, key, collection)\n markChanged(changeTracker)\n return cbresult\n }\n return methodFn.apply(target, [wrappedCallback, ...args.slice(1)])\n }\n }\n\n // For iterators (entries, keys, values, Symbol.iterator)\n const isValueIterator =\n methodName === `entries` ||\n methodName === `values` ||\n methodName === Symbol.iterator.toString() ||\n prop === Symbol.iterator\n\n if (isValueIterator) {\n const originalIterator = result as Iterator<unknown>\n\n // For values() iterator on Maps, create a value-to-key mapping\n const valueToKeyMap = new Map()\n if (methodName === `values` && target instanceof Map) {\n for (const [key, mapValue] of (\n changeTracker.copy_ as unknown as Map<unknown, unknown>\n ).entries()) {\n valueToKeyMap.set(mapValue, key)\n }\n }\n\n // For Set iterators, create an original-to-modified mapping\n const originalToModifiedMap = new Map()\n if (target instanceof Set) {\n for (const setValue of (\n changeTracker.copy_ as unknown as Set<unknown>\n ).values()) {\n originalToModifiedMap.set(setValue, setValue)\n }\n }\n\n // Return a wrapped iterator that proxies values\n return {\n next() {\n const nextResult = originalIterator.next()\n\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 if (\n nextResult.value[1] &&\n typeof nextResult.value[1] === `object`\n ) {\n const mapKey = nextResult.value[0]\n const mapParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: mapKey as string | symbol,\n updateMap: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Map) {\n ;(changeTracker.copy_ as Map<unknown, unknown>).set(\n mapKey,\n newValue\n )\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value[1] as Record<string | symbol, unknown>,\n mapParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\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 // For Map values(), use the key mapping\n if (methodName === `values` && target instanceof Map) {\n const mapKey = valueToKeyMap.get(nextResult.value)\n if (mapKey !== undefined) {\n const mapParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: mapKey as string | symbol,\n updateMap: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Map) {\n ;(changeTracker.copy_ as Map<unknown, unknown>).set(\n mapKey,\n newValue\n )\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n mapParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n )\n nextResult.value = valueProxy\n }\n } else if (target instanceof Set) {\n // For Set, track modifications\n const setOriginalValue = nextResult.value\n const setParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: setOriginalValue as unknown as string | symbol,\n updateSet: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Set) {\n ;(changeTracker.copy_ as Set<unknown>).delete(\n setOriginalValue\n )\n ;(changeTracker.copy_ as Set<unknown>).add(newValue)\n originalToModifiedMap.set(setOriginalValue, newValue)\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n setParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n )\n nextResult.value = valueProxy\n } else {\n // For other cases, use a symbol placeholder\n const tempKey = Symbol(`iterator-value`)\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\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/**\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 | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n updateMap: (newValue: unknown) => void\n }\n | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: unknown\n updateSet: (newValue: unknown) => void\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 // Handle Temporal objects\n if (isTemporal(obj)) {\n // Temporal objects are immutable, so we can return them directly\n // This preserves all their internal state correctly\n return obj\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\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 // Check if this is a special Map parent with updateMap function\n if (`updateMap` in state.parent) {\n // Use the special updateMap function for Maps\n state.parent.updateMap(state.copy_)\n } else if (`updateSet` in state.parent) {\n // Use the special updateSet function for Sets\n state.parent.updateSet(state.copy_)\n } else {\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\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 (!deepEquals(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 (!deepEquals(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 | unknown\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 Array methods that modify the array\n if (Array.isArray(ptarget)) {\n const methodName = prop.toString()\n\n if (ARRAY_MODIFYING_METHODS.has(methodName)) {\n return createModifyingMethodHandler(\n value,\n changeTracker,\n markChanged\n )\n }\n\n // Handle array iteration methods (find, filter, forEach, etc.)\n const iterationHandler = createArrayIterationHandler(\n methodName,\n value,\n changeTracker,\n memoizedCreateChangeProxy\n )\n if (iterationHandler) {\n return iterationHandler\n }\n\n // Handle array Symbol.iterator for for...of loops\n if (prop === Symbol.iterator) {\n return createArrayIteratorHandler(\n changeTracker,\n memoizedCreateChangeProxy\n )\n }\n }\n\n // For Map and Set methods that modify the collection\n if (ptarget instanceof Map || ptarget instanceof Set) {\n const methodName = prop.toString()\n\n if (MAP_SET_MODIFYING_METHODS.has(methodName)) {\n return createModifyingMethodHandler(\n value,\n changeTracker,\n markChanged\n )\n }\n\n // Handle iterator methods for Map and Set\n const iteratorHandler = createMapSetIteratorHandler(\n methodName,\n prop,\n value,\n ptarget,\n changeTracker,\n memoizedCreateChangeProxy,\n markChanged\n )\n if (iteratorHandler) {\n return iteratorHandler\n }\n }\n return value.bind(ptarget)\n }\n\n // If the value is an object (but not Date, RegExp, or Temporal), create a proxy for it\n if (isProxiableObject(value)) {\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 (!deepEquals(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 = deepEquals(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 // Forward the defineProperty to the target to maintain Proxy invariants\n // This allows Object.seal() and Object.freeze() to work on the proxy\n const result = Reflect.defineProperty(ptarget, prop, descriptor)\n if (result && `value` in descriptor) {\n changeTracker.copy_[prop as keyof T] = deepClone(descriptor.value)\n changeTracker.assigned_[prop.toString()] = true\n markChanged(changeTracker)\n }\n return result\n },\n\n getOwnPropertyDescriptor(ptarget, prop) {\n // Forward to target to maintain Proxy invariants for seal/freeze\n return Reflect.getOwnPropertyDescriptor(ptarget, prop)\n },\n\n preventExtensions(ptarget) {\n // Forward to target to allow Object.seal() and Object.preventExtensions()\n return Reflect.preventExtensions(ptarget)\n },\n\n isExtensible(ptarget) {\n // Forward to target to maintain consistency\n return Reflect.isExtensible(ptarget)\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 // Forward the delete to the target using Reflect\n // This respects Object.seal/preventExtensions constraints\n const result = Reflect.deleteProperty(dobj, prop)\n\n if (result) {\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.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 ===\n 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 markChanged(changeTracker)\n }\n }\n\n return result\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 // Use the unfrozen copy_ as the proxy target to avoid Proxy invariant violations\n // when the original target is frozen (e.g., from Immer)\n const proxy = createObjectProxy(changeTracker.copy_ as unknown as T)\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"proxy.js","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\nimport { deepEquals, isTemporal } from './utils'\n\n/**\n * Set of array methods that iterate with callbacks and may return elements.\n * Hoisted to module scope to avoid creating a new Set on every property access.\n */\nconst CALLBACK_ITERATION_METHODS = new Set([\n `find`,\n `findLast`,\n `findIndex`,\n `findLastIndex`,\n `filter`,\n `map`,\n `flatMap`,\n `forEach`,\n `some`,\n `every`,\n `reduce`,\n `reduceRight`,\n])\n\n/**\n * Set of array methods that modify the array in place.\n */\nconst ARRAY_MODIFYING_METHODS = new Set([\n `pop`,\n `push`,\n `shift`,\n `unshift`,\n `splice`,\n `sort`,\n `reverse`,\n `fill`,\n `copyWithin`,\n])\n\n/**\n * Set of Map/Set methods that modify the collection in place.\n */\nconst MAP_SET_MODIFYING_METHODS = new Set([`set`, `delete`, `clear`, `add`])\n\n/**\n * Set of Map/Set iterator methods.\n */\nconst MAP_SET_ITERATOR_METHODS = new Set([\n `entries`,\n `keys`,\n `values`,\n `forEach`,\n])\n\n/**\n * Check if a value is a proxiable object (not Date, RegExp, or Temporal)\n */\nfunction isProxiableObject(\n value: unknown,\n): value is Record<string | symbol, unknown> {\n return (\n value !== null &&\n typeof value === `object` &&\n !((value as any) instanceof Date) &&\n !((value as any) instanceof RegExp) &&\n !isTemporal(value)\n )\n}\n\n/**\n * Creates a handler for array iteration methods that ensures proxied elements\n * are passed to callbacks and returned from methods like find/filter.\n */\nfunction createArrayIterationHandler<T extends object>(\n methodName: string,\n methodFn: (...args: Array<unknown>) => unknown,\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n },\n ) => { proxy: Record<string | symbol, unknown> },\n): ((...args: Array<unknown>) => unknown) | undefined {\n if (!CALLBACK_ITERATION_METHODS.has(methodName)) {\n return undefined\n }\n\n return function (...args: Array<unknown>) {\n const callback = args[0]\n if (typeof callback !== `function`) {\n return methodFn.apply(changeTracker.copy_, args)\n }\n\n // Create a helper to get proxied version of an array element\n const getProxiedElement = (element: unknown, index: number): unknown => {\n if (isProxiableObject(element)) {\n const nestedParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: String(index),\n }\n const { proxy: elementProxy } = memoizedCreateChangeProxy(\n element,\n nestedParent,\n )\n return elementProxy\n }\n return element\n }\n\n // Wrap the callback to pass proxied elements\n const wrappedCallback = function (\n this: unknown,\n element: unknown,\n index: number,\n array: unknown,\n ) {\n const proxiedElement = getProxiedElement(element, index)\n return callback.call(this, proxiedElement, index, array)\n }\n\n // For reduce/reduceRight, the callback signature is different\n if (methodName === `reduce` || methodName === `reduceRight`) {\n const reduceCallback = function (\n this: unknown,\n accumulator: unknown,\n element: unknown,\n index: number,\n array: unknown,\n ) {\n const proxiedElement = getProxiedElement(element, index)\n return callback.call(this, accumulator, proxiedElement, index, array)\n }\n return methodFn.apply(changeTracker.copy_, [\n reduceCallback,\n ...args.slice(1),\n ])\n }\n\n const result = methodFn.apply(changeTracker.copy_, [\n wrappedCallback,\n ...args.slice(1),\n ])\n\n // For find/findLast, proxy the returned element if it's an object\n if (\n (methodName === `find` || methodName === `findLast`) &&\n result &&\n typeof result === `object`\n ) {\n const foundIndex = (\n changeTracker.copy_ as unknown as Array<unknown>\n ).indexOf(result)\n if (foundIndex !== -1) {\n return getProxiedElement(result, foundIndex)\n }\n }\n\n // For filter, proxy each element in the result array\n if (methodName === `filter` && Array.isArray(result)) {\n return result.map((element) => {\n const originalIndex = (\n changeTracker.copy_ as unknown as Array<unknown>\n ).indexOf(element)\n if (originalIndex !== -1) {\n return getProxiedElement(element, originalIndex)\n }\n return element\n })\n }\n\n return result\n }\n}\n\n/**\n * Creates a Symbol.iterator handler for arrays that yields proxied elements.\n */\nfunction createArrayIteratorHandler<T extends object>(\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n },\n ) => { proxy: Record<string | symbol, unknown> },\n): () => Iterator<unknown> {\n return function () {\n const array = changeTracker.copy_ as unknown as Array<unknown>\n let index = 0\n\n return {\n next() {\n if (index >= array.length) {\n return { done: true, value: undefined }\n }\n\n const element = array[index]\n let proxiedElement = element\n\n if (isProxiableObject(element)) {\n const nestedParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: String(index),\n }\n const { proxy: elementProxy } = memoizedCreateChangeProxy(\n element,\n nestedParent,\n )\n proxiedElement = elementProxy\n }\n\n index++\n return { done: false, value: proxiedElement }\n },\n [Symbol.iterator]() {\n return this\n },\n }\n }\n}\n\n/**\n * Creates a wrapper for methods that modify a collection (array, Map, Set).\n * The wrapper calls the method and marks the change tracker as modified.\n */\nfunction createModifyingMethodHandler<T extends object>(\n methodFn: (...args: Array<unknown>) => unknown,\n changeTracker: ChangeTracker<T>,\n markChanged: (tracker: ChangeTracker<T>) => void,\n): (...args: Array<unknown>) => unknown {\n return function (...args: Array<unknown>) {\n const result = methodFn.apply(changeTracker.copy_, args)\n markChanged(changeTracker)\n return result\n }\n}\n\n/**\n * Creates handlers for Map/Set iterator methods (entries, keys, values, forEach).\n * Returns proxied values for iteration to enable change tracking.\n */\nfunction createMapSetIteratorHandler<T extends object>(\n methodName: string,\n prop: string | symbol,\n methodFn: (...args: Array<unknown>) => unknown,\n target: Map<unknown, unknown> | Set<unknown>,\n changeTracker: ChangeTracker<T>,\n memoizedCreateChangeProxy: (\n obj: Record<string | symbol, unknown>,\n parent?: {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n },\n ) => { proxy: Record<string | symbol, unknown> },\n markChanged: (tracker: ChangeTracker<T>) => void,\n): ((...args: Array<unknown>) => unknown) | undefined {\n const isIteratorMethod =\n MAP_SET_ITERATOR_METHODS.has(methodName) || prop === Symbol.iterator\n\n if (!isIteratorMethod) {\n return undefined\n }\n\n return function (this: unknown, ...args: Array<unknown>) {\n const result = methodFn.apply(changeTracker.copy_, args)\n\n // For forEach, wrap the callback to track changes\n if (methodName === `forEach`) {\n const callback = args[0]\n if (typeof callback === `function`) {\n const wrappedCallback = function (\n this: unknown,\n value: unknown,\n key: unknown,\n collection: unknown,\n ) {\n const cbresult = callback.call(this, value, key, collection)\n markChanged(changeTracker)\n return cbresult\n }\n return methodFn.apply(target, [wrappedCallback, ...args.slice(1)])\n }\n }\n\n // For iterators (entries, keys, values, Symbol.iterator)\n const isValueIterator =\n methodName === `entries` ||\n methodName === `values` ||\n methodName === Symbol.iterator.toString() ||\n prop === Symbol.iterator\n\n if (isValueIterator) {\n const originalIterator = result as Iterator<unknown>\n\n // For values() iterator on Maps, create a value-to-key mapping\n const valueToKeyMap = new Map()\n if (methodName === `values` && target instanceof Map) {\n for (const [key, mapValue] of (\n changeTracker.copy_ as unknown as Map<unknown, unknown>\n ).entries()) {\n valueToKeyMap.set(mapValue, key)\n }\n }\n\n // For Set iterators, create an original-to-modified mapping\n const originalToModifiedMap = new Map()\n if (target instanceof Set) {\n for (const setValue of (\n changeTracker.copy_ as unknown as Set<unknown>\n ).values()) {\n originalToModifiedMap.set(setValue, setValue)\n }\n }\n\n // Return a wrapped iterator that proxies values\n return {\n next() {\n const nextResult = originalIterator.next()\n\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 if (\n nextResult.value[1] &&\n typeof nextResult.value[1] === `object`\n ) {\n const mapKey = nextResult.value[0]\n const mapParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: mapKey as string | symbol,\n updateMap: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Map) {\n ;(changeTracker.copy_ as Map<unknown, unknown>).set(\n mapKey,\n newValue,\n )\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value[1] as Record<string | symbol, unknown>,\n mapParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\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 // For Map values(), use the key mapping\n if (methodName === `values` && target instanceof Map) {\n const mapKey = valueToKeyMap.get(nextResult.value)\n if (mapKey !== undefined) {\n const mapParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: mapKey as string | symbol,\n updateMap: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Map) {\n ;(changeTracker.copy_ as Map<unknown, unknown>).set(\n mapKey,\n newValue,\n )\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n mapParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n },\n )\n nextResult.value = valueProxy\n }\n } else if (target instanceof Set) {\n // For Set, track modifications\n const setOriginalValue = nextResult.value\n const setParent = {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\n prop: setOriginalValue as unknown as string | symbol,\n updateSet: (newValue: unknown) => {\n if (changeTracker.copy_ instanceof Set) {\n ;(changeTracker.copy_ as Set<unknown>).delete(\n setOriginalValue,\n )\n ;(changeTracker.copy_ as Set<unknown>).add(newValue)\n originalToModifiedMap.set(setOriginalValue, newValue)\n }\n },\n }\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n setParent as unknown as {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n },\n )\n nextResult.value = valueProxy\n } else {\n // For other cases, use a symbol placeholder\n const tempKey = Symbol(`iterator-value`)\n const { proxy: valueProxy } = memoizedCreateChangeProxy(\n nextResult.value as Record<string | symbol, unknown>,\n {\n tracker: changeTracker as unknown as ChangeTracker<\n Record<string | symbol, unknown>\n >,\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/**\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 | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n }\n | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: string | symbol\n updateMap: (newValue: unknown) => void\n }\n | {\n tracker: ChangeTracker<Record<string | symbol, unknown>>\n prop: unknown\n updateSet: (newValue: unknown) => void\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 // Handle Temporal objects\n if (isTemporal(obj)) {\n // Temporal objects are immutable, so we can return them directly\n // This preserves all their internal state correctly\n return obj\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\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 // Check if this is a special Map parent with updateMap function\n if (`updateMap` in state.parent) {\n // Use the special updateMap function for Maps\n state.parent.updateMap(state.copy_)\n } else if (`updateSet` in state.parent) {\n // Use the special updateSet function for Sets\n state.parent.updateSet(state.copy_)\n } else {\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\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 (!deepEquals(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 (!deepEquals(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 | unknown,\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 Array methods that modify the array\n if (Array.isArray(ptarget)) {\n const methodName = prop.toString()\n\n if (ARRAY_MODIFYING_METHODS.has(methodName)) {\n return createModifyingMethodHandler(\n value,\n changeTracker,\n markChanged,\n )\n }\n\n // Handle array iteration methods (find, filter, forEach, etc.)\n const iterationHandler = createArrayIterationHandler(\n methodName,\n value,\n changeTracker,\n memoizedCreateChangeProxy,\n )\n if (iterationHandler) {\n return iterationHandler\n }\n\n // Handle array Symbol.iterator for for...of loops\n if (prop === Symbol.iterator) {\n return createArrayIteratorHandler(\n changeTracker,\n memoizedCreateChangeProxy,\n )\n }\n }\n\n // For Map and Set methods that modify the collection\n if (ptarget instanceof Map || ptarget instanceof Set) {\n const methodName = prop.toString()\n\n if (MAP_SET_MODIFYING_METHODS.has(methodName)) {\n return createModifyingMethodHandler(\n value,\n changeTracker,\n markChanged,\n )\n }\n\n // Handle iterator methods for Map and Set\n const iteratorHandler = createMapSetIteratorHandler(\n methodName,\n prop,\n value,\n ptarget,\n changeTracker,\n memoizedCreateChangeProxy,\n markChanged,\n )\n if (iteratorHandler) {\n return iteratorHandler\n }\n }\n return value.bind(ptarget)\n }\n\n // If the value is an object (but not Date, RegExp, or Temporal), create a proxy for it\n if (isProxiableObject(value)) {\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 (!deepEquals(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 = deepEquals(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 // Forward the defineProperty to the target to maintain Proxy invariants\n // This allows Object.seal() and Object.freeze() to work on the proxy\n const result = Reflect.defineProperty(ptarget, prop, descriptor)\n if (result && `value` in descriptor) {\n changeTracker.copy_[prop as keyof T] = deepClone(descriptor.value)\n changeTracker.assigned_[prop.toString()] = true\n markChanged(changeTracker)\n }\n return result\n },\n\n getOwnPropertyDescriptor(ptarget, prop) {\n // Forward to target to maintain Proxy invariants for seal/freeze\n return Reflect.getOwnPropertyDescriptor(ptarget, prop)\n },\n\n preventExtensions(ptarget) {\n // Forward to target to allow Object.seal() and Object.preventExtensions()\n return Reflect.preventExtensions(ptarget)\n },\n\n isExtensible(ptarget) {\n // Forward to target to maintain consistency\n return Reflect.isExtensible(ptarget)\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 // Forward the delete to the target using Reflect\n // This respects Object.seal/preventExtensions constraints\n const result = Reflect.deleteProperty(dobj, prop)\n\n if (result) {\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.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 ===\n 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 markChanged(changeTracker)\n }\n }\n\n return result\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 // Use the unfrozen copy_ as the proxy target to avoid Proxy invariant violations\n // when the original target is frozen (e.g., from Immer)\n const proxy = createObjectProxy(changeTracker.copy_ as unknown as T)\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"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.js","sources":["../../../../src/query/builder/functions.ts"],"sourcesContent":["import { Aggregate, Func } from \"../ir\"\nimport { toExpression } from \"./ref-proxy.js\"\nimport type { BasicExpression } from \"../ir\"\nimport type { RefProxy } from \"./ref-proxy.js\"\nimport type { RefLeaf } from \"./types.js\"\n\ntype StringRef =\n | RefLeaf<string>\n | RefLeaf<string | null>\n | RefLeaf<string | undefined>\ntype StringRefProxy =\n | RefProxy<string>\n | RefProxy<string | null>\n | RefProxy<string | undefined>\ntype StringBasicExpression =\n | BasicExpression<string>\n | BasicExpression<string | null>\n | BasicExpression<string | undefined>\ntype StringLike =\n | StringRef\n | StringRefProxy\n | StringBasicExpression\n | string\n | null\n | undefined\n\ntype ComparisonOperand<T> =\n | RefProxy<T>\n | RefLeaf<T>\n | T\n | BasicExpression<T>\n | undefined\n | null\ntype ComparisonOperandPrimitive<T extends string | number | boolean> =\n | T\n | BasicExpression<T>\n | undefined\n | null\n\n// Helper type for any expression-like value\ntype ExpressionLike = BasicExpression | RefProxy<any> | RefLeaf<any> | any\n\n// Helper type to extract the underlying type from various expression types\ntype ExtractType<T> =\n T extends RefProxy<infer U>\n ? U\n : T extends RefLeaf<infer U>\n ? U\n : T extends BasicExpression<infer U>\n ? U\n : T\n\n// Helper type to determine aggregate return type based on input nullability\ntype AggregateReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends number | undefined | null | Date | bigint\n ? Aggregate<U>\n : Aggregate<number | undefined | null | Date | bigint>\n : Aggregate<number | undefined | null | Date | bigint>\n\n// Helper type to determine string function return type based on input nullability\ntype StringFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | undefined | null\n ? BasicExpression<U>\n : BasicExpression<string | undefined | null>\n : BasicExpression<string | undefined | null>\n\n// Helper type to determine numeric function return type based on input nullability\n// This handles string, array, and number inputs for functions like length()\ntype NumericFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | Array<any> | undefined | null | number\n ? BasicExpression<MapToNumber<U>>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Transform string/array types to number while preserving nullability\ntype MapToNumber<T> = T extends string | Array<any>\n ? number\n : T extends undefined\n ? undefined\n : T extends null\n ? null\n : T\n\n// Helper type for binary numeric operations (combines nullability of both operands)\ntype BinaryNumericReturnType<T1, T2> =\n ExtractType<T1> extends infer U1\n ? ExtractType<T2> extends infer U2\n ? U1 extends number\n ? U2 extends number\n ? BasicExpression<number>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : U2 extends number | null\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : U1 extends number | undefined\n ? U2 extends number\n ? BasicExpression<number | undefined>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : BasicExpression<number | undefined | null>\n : U1 extends number | null\n ? U2 extends number\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Operators\n\nexport function eq<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function eq<T extends string | number | boolean>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function eq(left: any, right: any): BasicExpression<boolean> {\n return new Func(`eq`, [toExpression(left), toExpression(right)])\n}\n\nexport function gt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gt`, [toExpression(left), toExpression(right)])\n}\n\nexport function gte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function gte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gte`, [toExpression(left), toExpression(right)])\n}\n\nexport function lt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lt`, [toExpression(left), toExpression(right)])\n}\n\nexport function lte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>\n): BasicExpression<boolean>\nexport function lte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>\n): BasicExpression<boolean>\nexport function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lte`, [toExpression(left), toExpression(right)])\n}\n\n// Overloads for and() - support 2 or more arguments\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `and`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\n// Overloads for or() - support 2 or more arguments\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `or`,\n allArgs.map((arg) => toExpression(arg))\n )\n}\n\nexport function not(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`not`, [toExpression(value)])\n}\n\n// Null/undefined checking functions\nexport function isUndefined(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isUndefined`, [toExpression(value)])\n}\n\nexport function isNull(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isNull`, [toExpression(value)])\n}\n\nexport function inArray(\n value: ExpressionLike,\n array: ExpressionLike\n): BasicExpression<boolean> {\n return new Func(`in`, [toExpression(value), toExpression(array)])\n}\n\nexport function like(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean>\nexport function like(left: any, right: any): BasicExpression<boolean> {\n return new Func(`like`, [toExpression(left), toExpression(right)])\n}\n\nexport function ilike(\n left: StringLike,\n right: StringLike\n): BasicExpression<boolean> {\n return new Func(`ilike`, [toExpression(left), toExpression(right)])\n}\n\n// Functions\n\nexport function upper<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`upper`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function lower<T extends ExpressionLike>(\n arg: T\n): StringFunctionReturnType<T> {\n return new Func(`lower`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function length<T extends ExpressionLike>(\n arg: T\n): NumericFunctionReturnType<T> {\n return new Func(`length`, [toExpression(arg)]) as NumericFunctionReturnType<T>\n}\n\nexport function concat(\n ...args: Array<ExpressionLike>\n): BasicExpression<string> {\n return new Func(\n `concat`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function coalesce(...args: Array<ExpressionLike>): BasicExpression<any> {\n return new Func(\n `coalesce`,\n args.map((arg) => toExpression(arg))\n )\n}\n\nexport function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(\n left: T1,\n right: T2\n): BinaryNumericReturnType<T1, T2> {\n return new Func(`add`, [\n toExpression(left),\n toExpression(right),\n ]) as BinaryNumericReturnType<T1, T2>\n}\n\n// Aggregates\n\nexport function count(arg: ExpressionLike): Aggregate<number> {\n return new Aggregate(`count`, [toExpression(arg)])\n}\n\nexport function avg<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`avg`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function sum<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`sum`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function min<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`min`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function max<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`max`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\n/**\n * List of comparison function names that can be used with indexes\n */\nexport const comparisonFunctions = [\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n] as const\n\n/**\n * All supported operator names in TanStack DB expressions\n */\nexport const operators = [\n // Comparison operators\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n // Logical operators\n `and`,\n `or`,\n `not`,\n // Null checking\n `isNull`,\n `isUndefined`,\n // String functions\n `upper`,\n `lower`,\n `length`,\n `concat`,\n // Numeric functions\n `add`,\n // Utility functions\n `coalesce`,\n // Aggregate functions\n `count`,\n `avg`,\n `sum`,\n `min`,\n `max`,\n] as const\n\nexport type OperatorName = (typeof operators)[number]\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"functions.js","sources":["../../../../src/query/builder/functions.ts"],"sourcesContent":["import { Aggregate, Func } from '../ir'\nimport { toExpression } from './ref-proxy.js'\nimport type { BasicExpression } from '../ir'\nimport type { RefProxy } from './ref-proxy.js'\nimport type { RefLeaf } from './types.js'\n\ntype StringRef =\n | RefLeaf<string>\n | RefLeaf<string | null>\n | RefLeaf<string | undefined>\ntype StringRefProxy =\n | RefProxy<string>\n | RefProxy<string | null>\n | RefProxy<string | undefined>\ntype StringBasicExpression =\n | BasicExpression<string>\n | BasicExpression<string | null>\n | BasicExpression<string | undefined>\ntype StringLike =\n | StringRef\n | StringRefProxy\n | StringBasicExpression\n | string\n | null\n | undefined\n\ntype ComparisonOperand<T> =\n | RefProxy<T>\n | RefLeaf<T>\n | T\n | BasicExpression<T>\n | undefined\n | null\ntype ComparisonOperandPrimitive<T extends string | number | boolean> =\n | T\n | BasicExpression<T>\n | undefined\n | null\n\n// Helper type for any expression-like value\ntype ExpressionLike = BasicExpression | RefProxy<any> | RefLeaf<any> | any\n\n// Helper type to extract the underlying type from various expression types\ntype ExtractType<T> =\n T extends RefProxy<infer U>\n ? U\n : T extends RefLeaf<infer U>\n ? U\n : T extends BasicExpression<infer U>\n ? U\n : T\n\n// Helper type to determine aggregate return type based on input nullability\ntype AggregateReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends number | undefined | null | Date | bigint\n ? Aggregate<U>\n : Aggregate<number | undefined | null | Date | bigint>\n : Aggregate<number | undefined | null | Date | bigint>\n\n// Helper type to determine string function return type based on input nullability\ntype StringFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | undefined | null\n ? BasicExpression<U>\n : BasicExpression<string | undefined | null>\n : BasicExpression<string | undefined | null>\n\n// Helper type to determine numeric function return type based on input nullability\n// This handles string, array, and number inputs for functions like length()\ntype NumericFunctionReturnType<T> =\n ExtractType<T> extends infer U\n ? U extends string | Array<any> | undefined | null | number\n ? BasicExpression<MapToNumber<U>>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Transform string/array types to number while preserving nullability\ntype MapToNumber<T> = T extends string | Array<any>\n ? number\n : T extends undefined\n ? undefined\n : T extends null\n ? null\n : T\n\n// Helper type for binary numeric operations (combines nullability of both operands)\ntype BinaryNumericReturnType<T1, T2> =\n ExtractType<T1> extends infer U1\n ? ExtractType<T2> extends infer U2\n ? U1 extends number\n ? U2 extends number\n ? BasicExpression<number>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : U2 extends number | null\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : U1 extends number | undefined\n ? U2 extends number\n ? BasicExpression<number | undefined>\n : U2 extends number | undefined\n ? BasicExpression<number | undefined>\n : BasicExpression<number | undefined | null>\n : U1 extends number | null\n ? U2 extends number\n ? BasicExpression<number | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n : BasicExpression<number | undefined | null>\n\n// Operators\n\nexport function eq<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function eq<T extends string | number | boolean>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function eq<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function eq(left: any, right: any): BasicExpression<boolean> {\n return new Func(`eq`, [toExpression(left), toExpression(right)])\n}\n\nexport function gt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function gt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function gt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gt`, [toExpression(left), toExpression(right)])\n}\n\nexport function gte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function gte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function gte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function gte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`gte`, [toExpression(left), toExpression(right)])\n}\n\nexport function lt<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function lt<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function lt<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lt(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lt`, [toExpression(left), toExpression(right)])\n}\n\nexport function lte<T>(\n left: ComparisonOperand<T>,\n right: ComparisonOperand<T>,\n): BasicExpression<boolean>\nexport function lte<T extends string | number>(\n left: ComparisonOperandPrimitive<T>,\n right: ComparisonOperandPrimitive<T>,\n): BasicExpression<boolean>\nexport function lte<T>(left: Aggregate<T>, right: any): BasicExpression<boolean>\nexport function lte(left: any, right: any): BasicExpression<boolean> {\n return new Func(`lte`, [toExpression(left), toExpression(right)])\n}\n\n// Overloads for and() - support 2 or more arguments\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function and(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `and`,\n allArgs.map((arg) => toExpression(arg)),\n )\n}\n\n// Overloads for or() - support 2 or more arguments\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean>\nexport function or(\n left: ExpressionLike,\n right: ExpressionLike,\n ...rest: Array<ExpressionLike>\n): BasicExpression<boolean> {\n const allArgs = [left, right, ...rest]\n return new Func(\n `or`,\n allArgs.map((arg) => toExpression(arg)),\n )\n}\n\nexport function not(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`not`, [toExpression(value)])\n}\n\n// Null/undefined checking functions\nexport function isUndefined(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isUndefined`, [toExpression(value)])\n}\n\nexport function isNull(value: ExpressionLike): BasicExpression<boolean> {\n return new Func(`isNull`, [toExpression(value)])\n}\n\nexport function inArray(\n value: ExpressionLike,\n array: ExpressionLike,\n): BasicExpression<boolean> {\n return new Func(`in`, [toExpression(value), toExpression(array)])\n}\n\nexport function like(\n left: StringLike,\n right: StringLike,\n): BasicExpression<boolean>\nexport function like(left: any, right: any): BasicExpression<boolean> {\n return new Func(`like`, [toExpression(left), toExpression(right)])\n}\n\nexport function ilike(\n left: StringLike,\n right: StringLike,\n): BasicExpression<boolean> {\n return new Func(`ilike`, [toExpression(left), toExpression(right)])\n}\n\n// Functions\n\nexport function upper<T extends ExpressionLike>(\n arg: T,\n): StringFunctionReturnType<T> {\n return new Func(`upper`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function lower<T extends ExpressionLike>(\n arg: T,\n): StringFunctionReturnType<T> {\n return new Func(`lower`, [toExpression(arg)]) as StringFunctionReturnType<T>\n}\n\nexport function length<T extends ExpressionLike>(\n arg: T,\n): NumericFunctionReturnType<T> {\n return new Func(`length`, [toExpression(arg)]) as NumericFunctionReturnType<T>\n}\n\nexport function concat(\n ...args: Array<ExpressionLike>\n): BasicExpression<string> {\n return new Func(\n `concat`,\n args.map((arg) => toExpression(arg)),\n )\n}\n\nexport function coalesce(...args: Array<ExpressionLike>): BasicExpression<any> {\n return new Func(\n `coalesce`,\n args.map((arg) => toExpression(arg)),\n )\n}\n\nexport function add<T1 extends ExpressionLike, T2 extends ExpressionLike>(\n left: T1,\n right: T2,\n): BinaryNumericReturnType<T1, T2> {\n return new Func(`add`, [\n toExpression(left),\n toExpression(right),\n ]) as BinaryNumericReturnType<T1, T2>\n}\n\n// Aggregates\n\nexport function count(arg: ExpressionLike): Aggregate<number> {\n return new Aggregate(`count`, [toExpression(arg)])\n}\n\nexport function avg<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`avg`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function sum<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`sum`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function min<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`min`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\nexport function max<T extends ExpressionLike>(arg: T): AggregateReturnType<T> {\n return new Aggregate(`max`, [toExpression(arg)]) as AggregateReturnType<T>\n}\n\n/**\n * List of comparison function names that can be used with indexes\n */\nexport const comparisonFunctions = [\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n] as const\n\n/**\n * All supported operator names in TanStack DB expressions\n */\nexport const operators = [\n // Comparison operators\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n `like`,\n `ilike`,\n // Logical operators\n `and`,\n `or`,\n `not`,\n // Null checking\n `isNull`,\n `isUndefined`,\n // String functions\n `upper`,\n `lower`,\n `length`,\n `concat`,\n // Numeric functions\n `add`,\n // Utility functions\n `coalesce`,\n // Aggregate functions\n `count`,\n `avg`,\n `sum`,\n `min`,\n `max`,\n] as const\n\nexport type OperatorName = (typeof operators)[number]\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/query/builder/index.ts"],"sourcesContent":["import { CollectionImpl } from \"../../collection/index.js\"\nimport {\n Aggregate as AggregateExpr,\n CollectionRef,\n Func as FuncExpr,\n PropRef,\n QueryRef,\n Value as ValueExpr,\n isExpressionLike,\n} from \"../ir.js\"\nimport {\n InvalidSourceError,\n InvalidSourceTypeError,\n JoinConditionMustBeEqualityError,\n OnlyOneSourceAllowedError,\n QueryMustHaveFromClauseError,\n SubQueryMustHaveFromClauseError,\n} from \"../../errors.js\"\nimport { createRefProxy, toExpression } from \"./ref-proxy.js\"\nimport type { NamespacedRow, SingleResult } from \"../../types.js\"\nimport type {\n Aggregate,\n BasicExpression,\n JoinClause,\n OrderBy,\n OrderByDirection,\n QueryIR,\n} from \"../ir.js\"\nimport type {\n CompareOptions,\n Context,\n GroupByCallback,\n JoinOnCallback,\n MergeContextForJoinCallback,\n MergeContextWithJoinType,\n OrderByCallback,\n OrderByOptions,\n RefsForContext,\n ResultTypeFromSelect,\n SchemaFromSource,\n SelectObject,\n Source,\n WhereCallback,\n WithResult,\n} from \"./types.js\"\n\nexport class BaseQueryBuilder<TContext extends Context = Context> {\n private readonly query: Partial<QueryIR> = {}\n\n constructor(query: Partial<QueryIR> = {}) {\n this.query = { ...query }\n }\n\n /**\n * Creates a CollectionRef or QueryRef from a source object\n * @param source - An object with a single key-value pair\n * @param context - Context string for error messages (e.g., \"from clause\", \"join clause\")\n * @returns A tuple of [alias, ref] where alias is the source key and ref is the created reference\n */\n private _createRefForSource<TSource extends Source>(\n source: TSource,\n context: string\n ): [string, CollectionRef | QueryRef] {\n // Validate source is a plain object (not null, array, string, etc.)\n // We use try-catch to handle null/undefined gracefully\n let keys: Array<string>\n try {\n keys = Object.keys(source)\n } catch {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const type = source === null ? `null` : `undefined`\n throw new InvalidSourceTypeError(context, type)\n }\n\n // Check if it's an array (arrays pass Object.keys but aren't valid sources)\n if (Array.isArray(source)) {\n throw new InvalidSourceTypeError(context, `array`)\n }\n\n // Validate exactly one key\n if (keys.length !== 1) {\n if (keys.length === 0) {\n throw new InvalidSourceTypeError(context, `empty object`)\n }\n // Check if it looks like a string was passed (has numeric keys)\n if (keys.every((k) => !isNaN(Number(k)))) {\n throw new InvalidSourceTypeError(context, `string`)\n }\n throw new OnlyOneSourceAllowedError(context)\n }\n\n const alias = keys[0]!\n const sourceValue = source[alias]\n\n // Validate the value is a Collection or QueryBuilder\n let ref: CollectionRef | QueryRef\n\n if (sourceValue instanceof CollectionImpl) {\n ref = new CollectionRef(sourceValue, alias)\n } else if (sourceValue instanceof BaseQueryBuilder) {\n const subQuery = sourceValue._getQuery()\n if (!(subQuery as Partial<QueryIR>).from) {\n throw new SubQueryMustHaveFromClauseError(context)\n }\n ref = new QueryRef(subQuery, alias)\n } else {\n throw new InvalidSourceError(alias)\n }\n\n return [alias, ref]\n }\n\n /**\n * Specify the source table or subquery for the query\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @returns A QueryBuilder with the specified source\n *\n * @example\n * ```ts\n * // Query from a collection\n * query.from({ users: usersCollection })\n *\n * // Query from a subquery\n * const activeUsers = query.from({ u: usersCollection }).where(({u}) => u.active)\n * query.from({ activeUsers })\n * ```\n */\n from<TSource extends Source>(\n source: TSource\n ): QueryBuilder<{\n baseSchema: SchemaFromSource<TSource>\n schema: SchemaFromSource<TSource>\n fromSourceName: keyof TSource & string\n hasJoins: false\n }> {\n const [, from] = this._createRefForSource(source, `from clause`)\n\n return new BaseQueryBuilder({\n ...this.query,\n from,\n }) as any\n }\n\n /**\n * Join another table or subquery to the current query\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @param type - The type of join: 'inner', 'left', 'right', or 'full' (defaults to 'left')\n * @returns A QueryBuilder with the joined table available\n *\n * @example\n * ```ts\n * // Left join users with posts\n * query\n * .from({ users: usersCollection })\n * .join({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n *\n * // Inner join with explicit type\n * query\n * .from({ u: usersCollection })\n * .join({ p: postsCollection }, ({u, p}) => eq(u.id, p.userId), 'inner')\n * ```\n *\n * // Join with a subquery\n * const activeUsers = query.from({ u: usersCollection }).where(({u}) => u.active)\n * query\n * .from({ activeUsers })\n * .join({ p: postsCollection }, ({u, p}) => eq(u.id, p.userId))\n */\n join<\n TSource extends Source,\n TJoinType extends `inner` | `left` | `right` | `full` = `left`,\n >(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n type: TJoinType = `left` as TJoinType\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, TJoinType>\n > {\n const [alias, from] = this._createRefForSource(source, `join clause`)\n\n // Create a temporary context for the callback\n const currentAliases = this._getCurrentAliases()\n const newAliases = [...currentAliases, alias]\n const refProxy = createRefProxy(newAliases) as RefsForContext<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n\n // Get the join condition expression\n const onExpression = onCallback(refProxy)\n\n // Extract left and right from the expression\n // For now, we'll assume it's an eq function with two arguments\n let left: BasicExpression\n let right: BasicExpression\n\n if (\n onExpression.type === `func` &&\n onExpression.name === `eq` &&\n onExpression.args.length === 2\n ) {\n left = onExpression.args[0]!\n right = onExpression.args[1]!\n } else {\n throw new JoinConditionMustBeEqualityError()\n }\n\n const joinClause: JoinClause = {\n from,\n type,\n left,\n right,\n }\n\n const existingJoins = this.query.join || []\n\n return new BaseQueryBuilder({\n ...this.query,\n join: [...existingJoins, joinClause],\n }) as any\n }\n\n /**\n * Perform a LEFT JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the left joined table available\n *\n * @example\n * ```ts\n * // Left join users with posts\n * query\n * .from({ users: usersCollection })\n * .leftJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n leftJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `left`>\n > {\n return this.join(source, onCallback, `left`)\n }\n\n /**\n * Perform a RIGHT JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the right joined table available\n *\n * @example\n * ```ts\n * // Right join users with posts\n * query\n * .from({ users: usersCollection })\n * .rightJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n rightJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `right`>\n > {\n return this.join(source, onCallback, `right`)\n }\n\n /**\n * Perform an INNER JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the inner joined table available\n *\n * @example\n * ```ts\n * // Inner join users with posts\n * query\n * .from({ users: usersCollection })\n * .innerJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n innerJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `inner`>\n > {\n return this.join(source, onCallback, `inner`)\n }\n\n /**\n * Perform a FULL JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the full joined table available\n *\n * @example\n * ```ts\n * // Full join users with posts\n * query\n * .from({ users: usersCollection })\n * .fullJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n fullJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `full`>\n > {\n return this.join(source, onCallback, `full`)\n }\n\n /**\n * Filter rows based on a condition\n *\n * @param callback - A function that receives table references and returns an expression\n * @returns A QueryBuilder with the where condition applied\n *\n * @example\n * ```ts\n * // Simple condition\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => gt(users.age, 18))\n *\n * // Multiple conditions\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => and(\n * gt(users.age, 18),\n * eq(users.active, true)\n * ))\n *\n * // Multiple where calls are ANDed together\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => gt(users.age, 18))\n * .where(({users}) => eq(users.active, true))\n * ```\n */\n where(callback: WhereCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const expression = callback(refProxy)\n\n const existingWhere = this.query.where || []\n\n return new BaseQueryBuilder({\n ...this.query,\n where: [...existingWhere, expression],\n }) as any\n }\n\n /**\n * Filter grouped rows based on aggregate conditions\n *\n * @param callback - A function that receives table references and returns an expression\n * @returns A QueryBuilder with the having condition applied\n *\n * @example\n * ```ts\n * // Filter groups by count\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .having(({posts}) => gt(count(posts.id), 5))\n *\n * // Filter by average\n * query\n * .from({ orders: ordersCollection })\n * .groupBy(({orders}) => orders.customerId)\n * .having(({orders}) => gt(avg(orders.total), 100))\n *\n * // Multiple having calls are ANDed together\n * query\n * .from({ orders: ordersCollection })\n * .groupBy(({orders}) => orders.customerId)\n * .having(({orders}) => gt(count(orders.id), 5))\n * .having(({orders}) => gt(avg(orders.total), 100))\n * ```\n */\n having(callback: WhereCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const expression = callback(refProxy)\n\n const existingHaving = this.query.having || []\n\n return new BaseQueryBuilder({\n ...this.query,\n having: [...existingHaving, expression],\n }) as any\n }\n\n /**\n * Select specific columns or computed values from the query\n *\n * @param callback - A function that receives table references and returns an object with selected fields or expressions\n * @returns A QueryBuilder that returns only the selected fields\n *\n * @example\n * ```ts\n * // Select specific columns\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => ({\n * name: users.name,\n * email: users.email\n * }))\n *\n * // Select with computed values\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => ({\n * fullName: concat(users.firstName, ' ', users.lastName),\n * ageInMonths: mul(users.age, 12)\n * }))\n *\n * // Select with aggregates (requires GROUP BY)\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .select(({posts, count}) => ({\n * userId: posts.userId,\n * postCount: count(posts.id)\n * }))\n * ```\n */\n select<TSelectObject extends SelectObject>(\n callback: (refs: RefsForContext<TContext>) => TSelectObject\n ): QueryBuilder<WithResult<TContext, ResultTypeFromSelect<TSelectObject>>> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const selectObject = callback(refProxy)\n const select = buildNestedSelect(selectObject)\n\n return new BaseQueryBuilder({\n ...this.query,\n select: select,\n fnSelect: undefined, // remove the fnSelect clause if it exists\n }) as any\n }\n\n /**\n * Sort the query results by one or more columns\n *\n * @param callback - A function that receives table references and returns the field to sort by\n * @param direction - Sort direction: 'asc' for ascending, 'desc' for descending (defaults to 'asc')\n * @returns A QueryBuilder with the ordering applied\n *\n * @example\n * ```ts\n * // Sort by a single column\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.name)\n *\n * // Sort descending\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.createdAt, 'desc')\n *\n * // Multiple sorts (chain orderBy calls)\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.lastName)\n * .orderBy(({users}) => users.firstName)\n * ```\n */\n orderBy(\n callback: OrderByCallback<TContext>,\n options: OrderByDirection | OrderByOptions = `asc`\n ): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const result = callback(refProxy)\n\n const opts: CompareOptions =\n typeof options === `string`\n ? { direction: options, nulls: `first` }\n : {\n direction: options.direction ?? `asc`,\n nulls: options.nulls ?? `first`,\n stringSort: options.stringSort,\n locale:\n options.stringSort === `locale` ? options.locale : undefined,\n localeOptions:\n options.stringSort === `locale`\n ? options.localeOptions\n : undefined,\n }\n\n const makeOrderByClause = (res: any) => {\n return {\n expression: toExpression(res),\n compareOptions: opts,\n }\n }\n\n // Create the new OrderBy structure with expression and direction\n const orderByClauses = Array.isArray(result)\n ? result.map((r) => makeOrderByClause(r))\n : [makeOrderByClause(result)]\n\n const existingOrderBy: OrderBy = this.query.orderBy || []\n\n return new BaseQueryBuilder({\n ...this.query,\n orderBy: [...existingOrderBy, ...orderByClauses],\n }) as any\n }\n\n /**\n * Group rows by one or more columns for aggregation\n *\n * @param callback - A function that receives table references and returns the field(s) to group by\n * @returns A QueryBuilder with grouping applied (enables aggregate functions in SELECT and HAVING)\n *\n * @example\n * ```ts\n * // Group by a single column\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .select(({posts, count}) => ({\n * userId: posts.userId,\n * postCount: count()\n * }))\n *\n * // Group by multiple columns\n * query\n * .from({ sales: salesCollection })\n * .groupBy(({sales}) => [sales.region, sales.category])\n * .select(({sales, sum}) => ({\n * region: sales.region,\n * category: sales.category,\n * totalSales: sum(sales.amount)\n * }))\n * ```\n */\n groupBy(callback: GroupByCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const result = callback(refProxy)\n\n const newExpressions = Array.isArray(result)\n ? result.map((r) => toExpression(r))\n : [toExpression(result)]\n\n // Extend existing groupBy expressions (multiple groupBy calls should accumulate)\n const existingGroupBy = this.query.groupBy || []\n return new BaseQueryBuilder({\n ...this.query,\n groupBy: [...existingGroupBy, ...newExpressions],\n }) as any\n }\n\n /**\n * Limit the number of rows returned by the query\n * `orderBy` is required for `limit`\n *\n * @param count - Maximum number of rows to return\n * @returns A QueryBuilder with the limit applied\n *\n * @example\n * ```ts\n * // Get top 5 posts by likes\n * query\n * .from({ posts: postsCollection })\n * .orderBy(({posts}) => posts.likes, 'desc')\n * .limit(5)\n * ```\n */\n limit(count: number): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n limit: count,\n }) as any\n }\n\n /**\n * Skip a number of rows before returning results\n * `orderBy` is required for `offset`\n *\n * @param count - Number of rows to skip\n * @returns A QueryBuilder with the offset applied\n *\n * @example\n * ```ts\n * // Get second page of results\n * query\n * .from({ posts: postsCollection })\n * .orderBy(({posts}) => posts.createdAt, 'desc')\n * .offset(page * pageSize)\n * .limit(pageSize)\n * ```\n */\n offset(count: number): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n offset: count,\n }) as any\n }\n\n /**\n * Specify that the query should return distinct rows.\n * Deduplicates rows based on the selected columns.\n * @returns A QueryBuilder with distinct enabled\n *\n * @example\n * ```ts\n * // Get countries our users are from\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => users.country)\n * .distinct()\n * ```\n */\n distinct(): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n distinct: true,\n }) as any\n }\n\n /**\n * Specify that the query should return a single result\n * @returns A QueryBuilder that returns the first result\n *\n * @example\n * ```ts\n * // Get the user matching the query\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => eq(users.id, 1))\n * .findOne()\n *```\n */\n findOne(): QueryBuilder<TContext & SingleResult> {\n return new BaseQueryBuilder({\n ...this.query,\n // TODO: enforcing return only one result with also a default orderBy if none is specified\n // limit: 1,\n singleResult: true,\n })\n }\n\n // Helper methods\n private _getCurrentAliases(): Array<string> {\n const aliases: Array<string> = []\n\n // Add the from alias\n if (this.query.from) {\n aliases.push(this.query.from.alias)\n }\n\n // Add join aliases\n if (this.query.join) {\n for (const join of this.query.join) {\n aliases.push(join.from.alias)\n }\n }\n\n return aliases\n }\n\n /**\n * Functional variants of the query builder\n * These are imperative function that are called for ery row.\n * Warning: that these cannot be optimized by the query compiler, and may prevent\n * some type of optimizations being possible.\n * @example\n * ```ts\n * q.fn.select((row) => ({\n * name: row.user.name.toUpperCase(),\n * age: row.user.age + 1,\n * }))\n * ```\n */\n get fn() {\n const builder = this\n return {\n /**\n * Select fields using a function that operates on each row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives a row and returns the selected value\n * @returns A QueryBuilder with functional selection applied\n *\n * @example\n * ```ts\n * // Functional select (not optimized)\n * query\n * .from({ users: usersCollection })\n * .fn.select(row => ({\n * name: row.users.name.toUpperCase(),\n * age: row.users.age + 1,\n * }))\n * ```\n */\n select<TFuncSelectResult>(\n callback: (row: TContext[`schema`]) => TFuncSelectResult\n ): QueryBuilder<WithResult<TContext, TFuncSelectResult>> {\n return new BaseQueryBuilder({\n ...builder.query,\n select: undefined, // remove the select clause if it exists\n fnSelect: callback,\n })\n },\n /**\n * Filter rows using a function that operates on each row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives a row and returns a boolean\n * @returns A QueryBuilder with functional filtering applied\n *\n * @example\n * ```ts\n * // Functional where (not optimized)\n * query\n * .from({ users: usersCollection })\n * .fn.where(row => row.users.name.startsWith('A'))\n * ```\n */\n where(\n callback: (row: TContext[`schema`]) => any\n ): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...builder.query,\n fnWhere: [\n ...(builder.query.fnWhere || []),\n callback as (row: NamespacedRow) => any,\n ],\n })\n },\n /**\n * Filter grouped rows using a function that operates on each aggregated row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives an aggregated row and returns a boolean\n * @returns A QueryBuilder with functional having filter applied\n *\n * @example\n * ```ts\n * // Functional having (not optimized)\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .fn.having(row => row.count > 5)\n * ```\n */\n having(\n callback: (row: TContext[`schema`]) => any\n ): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...builder.query,\n fnHaving: [\n ...(builder.query.fnHaving || []),\n callback as (row: NamespacedRow) => any,\n ],\n })\n },\n }\n }\n\n _getQuery(): QueryIR {\n if (!this.query.from) {\n throw new QueryMustHaveFromClauseError()\n }\n return this.query as QueryIR\n }\n}\n\n// Helper to ensure we have a BasicExpression/Aggregate for a value\nfunction toExpr(value: any): BasicExpression | Aggregate {\n if (value === undefined) return toExpression(null)\n if (\n value instanceof AggregateExpr ||\n value instanceof FuncExpr ||\n value instanceof PropRef ||\n value instanceof ValueExpr\n ) {\n return value as BasicExpression | Aggregate\n }\n return toExpression(value)\n}\n\nfunction isPlainObject(value: any): value is Record<string, any> {\n return (\n value !== null &&\n typeof value === `object` &&\n !isExpressionLike(value) &&\n !value.__refProxy\n )\n}\n\nfunction buildNestedSelect(obj: any): any {\n if (!isPlainObject(obj)) return toExpr(obj)\n const out: Record<string, any> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (typeof k === `string` && k.startsWith(`__SPREAD_SENTINEL__`)) {\n // Preserve sentinel key and its value (value is unimportant at compile time)\n out[k] = v\n continue\n }\n out[k] = buildNestedSelect(v)\n }\n return out\n}\n\n// Internal function to build a query from a callback\n// used by liveQueryCollectionOptions.query\nexport function buildQuery<TContext extends Context>(\n fn: (builder: InitialQueryBuilder) => QueryBuilder<TContext>\n): QueryIR {\n const result = fn(new BaseQueryBuilder())\n return getQueryIR(result)\n}\n\n// Internal function to get the QueryIR from a builder\nexport function getQueryIR(\n builder: BaseQueryBuilder | QueryBuilder<any> | InitialQueryBuilder\n): QueryIR {\n return (builder as unknown as BaseQueryBuilder)._getQuery()\n}\n\n// Type-only exports for the query builder\nexport type InitialQueryBuilder = Pick<BaseQueryBuilder<Context>, `from`>\n\nexport type InitialQueryBuilderConstructor = new () => InitialQueryBuilder\n\nexport type QueryBuilder<TContext extends Context> = Omit<\n BaseQueryBuilder<TContext>,\n `from` | `_getQuery`\n>\n\n// Main query builder class alias with the constructor type modified to hide all\n// but the from method on the initial instance\nexport const Query: InitialQueryBuilderConstructor = BaseQueryBuilder\n\n// Helper type to extract context from a QueryBuilder\nexport type ExtractContext<T> =\n T extends BaseQueryBuilder<infer TContext>\n ? TContext\n : T extends QueryBuilder<infer TContext>\n ? TContext\n : never\n\n// Export the types from types.ts for convenience\nexport type {\n Context,\n Source,\n GetResult,\n RefLeaf as Ref,\n InferResultType,\n} from \"./types.js\"\n"],"names":["AggregateExpr","FuncExpr","ValueExpr"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/query/builder/index.ts"],"sourcesContent":["import { CollectionImpl } from '../../collection/index.js'\nimport {\n Aggregate as AggregateExpr,\n CollectionRef,\n Func as FuncExpr,\n PropRef,\n QueryRef,\n Value as ValueExpr,\n isExpressionLike,\n} from '../ir.js'\nimport {\n InvalidSourceError,\n InvalidSourceTypeError,\n JoinConditionMustBeEqualityError,\n OnlyOneSourceAllowedError,\n QueryMustHaveFromClauseError,\n SubQueryMustHaveFromClauseError,\n} from '../../errors.js'\nimport { createRefProxy, toExpression } from './ref-proxy.js'\nimport type { NamespacedRow, SingleResult } from '../../types.js'\nimport type {\n Aggregate,\n BasicExpression,\n JoinClause,\n OrderBy,\n OrderByDirection,\n QueryIR,\n} from '../ir.js'\nimport type {\n CompareOptions,\n Context,\n GroupByCallback,\n JoinOnCallback,\n MergeContextForJoinCallback,\n MergeContextWithJoinType,\n OrderByCallback,\n OrderByOptions,\n RefsForContext,\n ResultTypeFromSelect,\n SchemaFromSource,\n SelectObject,\n Source,\n WhereCallback,\n WithResult,\n} from './types.js'\n\nexport class BaseQueryBuilder<TContext extends Context = Context> {\n private readonly query: Partial<QueryIR> = {}\n\n constructor(query: Partial<QueryIR> = {}) {\n this.query = { ...query }\n }\n\n /**\n * Creates a CollectionRef or QueryRef from a source object\n * @param source - An object with a single key-value pair\n * @param context - Context string for error messages (e.g., \"from clause\", \"join clause\")\n * @returns A tuple of [alias, ref] where alias is the source key and ref is the created reference\n */\n private _createRefForSource<TSource extends Source>(\n source: TSource,\n context: string,\n ): [string, CollectionRef | QueryRef] {\n // Validate source is a plain object (not null, array, string, etc.)\n // We use try-catch to handle null/undefined gracefully\n let keys: Array<string>\n try {\n keys = Object.keys(source)\n } catch {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n const type = source === null ? `null` : `undefined`\n throw new InvalidSourceTypeError(context, type)\n }\n\n // Check if it's an array (arrays pass Object.keys but aren't valid sources)\n if (Array.isArray(source)) {\n throw new InvalidSourceTypeError(context, `array`)\n }\n\n // Validate exactly one key\n if (keys.length !== 1) {\n if (keys.length === 0) {\n throw new InvalidSourceTypeError(context, `empty object`)\n }\n // Check if it looks like a string was passed (has numeric keys)\n if (keys.every((k) => !isNaN(Number(k)))) {\n throw new InvalidSourceTypeError(context, `string`)\n }\n throw new OnlyOneSourceAllowedError(context)\n }\n\n const alias = keys[0]!\n const sourceValue = source[alias]\n\n // Validate the value is a Collection or QueryBuilder\n let ref: CollectionRef | QueryRef\n\n if (sourceValue instanceof CollectionImpl) {\n ref = new CollectionRef(sourceValue, alias)\n } else if (sourceValue instanceof BaseQueryBuilder) {\n const subQuery = sourceValue._getQuery()\n if (!(subQuery as Partial<QueryIR>).from) {\n throw new SubQueryMustHaveFromClauseError(context)\n }\n ref = new QueryRef(subQuery, alias)\n } else {\n throw new InvalidSourceError(alias)\n }\n\n return [alias, ref]\n }\n\n /**\n * Specify the source table or subquery for the query\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @returns A QueryBuilder with the specified source\n *\n * @example\n * ```ts\n * // Query from a collection\n * query.from({ users: usersCollection })\n *\n * // Query from a subquery\n * const activeUsers = query.from({ u: usersCollection }).where(({u}) => u.active)\n * query.from({ activeUsers })\n * ```\n */\n from<TSource extends Source>(\n source: TSource,\n ): QueryBuilder<{\n baseSchema: SchemaFromSource<TSource>\n schema: SchemaFromSource<TSource>\n fromSourceName: keyof TSource & string\n hasJoins: false\n }> {\n const [, from] = this._createRefForSource(source, `from clause`)\n\n return new BaseQueryBuilder({\n ...this.query,\n from,\n }) as any\n }\n\n /**\n * Join another table or subquery to the current query\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @param type - The type of join: 'inner', 'left', 'right', or 'full' (defaults to 'left')\n * @returns A QueryBuilder with the joined table available\n *\n * @example\n * ```ts\n * // Left join users with posts\n * query\n * .from({ users: usersCollection })\n * .join({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n *\n * // Inner join with explicit type\n * query\n * .from({ u: usersCollection })\n * .join({ p: postsCollection }, ({u, p}) => eq(u.id, p.userId), 'inner')\n * ```\n *\n * // Join with a subquery\n * const activeUsers = query.from({ u: usersCollection }).where(({u}) => u.active)\n * query\n * .from({ activeUsers })\n * .join({ p: postsCollection }, ({u, p}) => eq(u.id, p.userId))\n */\n join<\n TSource extends Source,\n TJoinType extends `inner` | `left` | `right` | `full` = `left`,\n >(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n type: TJoinType = `left` as TJoinType,\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, TJoinType>\n > {\n const [alias, from] = this._createRefForSource(source, `join clause`)\n\n // Create a temporary context for the callback\n const currentAliases = this._getCurrentAliases()\n const newAliases = [...currentAliases, alias]\n const refProxy = createRefProxy(newAliases) as RefsForContext<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >\n\n // Get the join condition expression\n const onExpression = onCallback(refProxy)\n\n // Extract left and right from the expression\n // For now, we'll assume it's an eq function with two arguments\n let left: BasicExpression\n let right: BasicExpression\n\n if (\n onExpression.type === `func` &&\n onExpression.name === `eq` &&\n onExpression.args.length === 2\n ) {\n left = onExpression.args[0]!\n right = onExpression.args[1]!\n } else {\n throw new JoinConditionMustBeEqualityError()\n }\n\n const joinClause: JoinClause = {\n from,\n type,\n left,\n right,\n }\n\n const existingJoins = this.query.join || []\n\n return new BaseQueryBuilder({\n ...this.query,\n join: [...existingJoins, joinClause],\n }) as any\n }\n\n /**\n * Perform a LEFT JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the left joined table available\n *\n * @example\n * ```ts\n * // Left join users with posts\n * query\n * .from({ users: usersCollection })\n * .leftJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n leftJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `left`>\n > {\n return this.join(source, onCallback, `left`)\n }\n\n /**\n * Perform a RIGHT JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the right joined table available\n *\n * @example\n * ```ts\n * // Right join users with posts\n * query\n * .from({ users: usersCollection })\n * .rightJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n rightJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `right`>\n > {\n return this.join(source, onCallback, `right`)\n }\n\n /**\n * Perform an INNER JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the inner joined table available\n *\n * @example\n * ```ts\n * // Inner join users with posts\n * query\n * .from({ users: usersCollection })\n * .innerJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n innerJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `inner`>\n > {\n return this.join(source, onCallback, `inner`)\n }\n\n /**\n * Perform a FULL JOIN with another table or subquery\n *\n * @param source - An object with a single key-value pair where the key is the table alias and the value is a Collection or subquery\n * @param onCallback - A function that receives table references and returns the join condition\n * @returns A QueryBuilder with the full joined table available\n *\n * @example\n * ```ts\n * // Full join users with posts\n * query\n * .from({ users: usersCollection })\n * .fullJoin({ posts: postsCollection }, ({users, posts}) => eq(users.id, posts.userId))\n * ```\n */\n fullJoin<TSource extends Source>(\n source: TSource,\n onCallback: JoinOnCallback<\n MergeContextForJoinCallback<TContext, SchemaFromSource<TSource>>\n >,\n ): QueryBuilder<\n MergeContextWithJoinType<TContext, SchemaFromSource<TSource>, `full`>\n > {\n return this.join(source, onCallback, `full`)\n }\n\n /**\n * Filter rows based on a condition\n *\n * @param callback - A function that receives table references and returns an expression\n * @returns A QueryBuilder with the where condition applied\n *\n * @example\n * ```ts\n * // Simple condition\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => gt(users.age, 18))\n *\n * // Multiple conditions\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => and(\n * gt(users.age, 18),\n * eq(users.active, true)\n * ))\n *\n * // Multiple where calls are ANDed together\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => gt(users.age, 18))\n * .where(({users}) => eq(users.active, true))\n * ```\n */\n where(callback: WhereCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const expression = callback(refProxy)\n\n const existingWhere = this.query.where || []\n\n return new BaseQueryBuilder({\n ...this.query,\n where: [...existingWhere, expression],\n }) as any\n }\n\n /**\n * Filter grouped rows based on aggregate conditions\n *\n * @param callback - A function that receives table references and returns an expression\n * @returns A QueryBuilder with the having condition applied\n *\n * @example\n * ```ts\n * // Filter groups by count\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .having(({posts}) => gt(count(posts.id), 5))\n *\n * // Filter by average\n * query\n * .from({ orders: ordersCollection })\n * .groupBy(({orders}) => orders.customerId)\n * .having(({orders}) => gt(avg(orders.total), 100))\n *\n * // Multiple having calls are ANDed together\n * query\n * .from({ orders: ordersCollection })\n * .groupBy(({orders}) => orders.customerId)\n * .having(({orders}) => gt(count(orders.id), 5))\n * .having(({orders}) => gt(avg(orders.total), 100))\n * ```\n */\n having(callback: WhereCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const expression = callback(refProxy)\n\n const existingHaving = this.query.having || []\n\n return new BaseQueryBuilder({\n ...this.query,\n having: [...existingHaving, expression],\n }) as any\n }\n\n /**\n * Select specific columns or computed values from the query\n *\n * @param callback - A function that receives table references and returns an object with selected fields or expressions\n * @returns A QueryBuilder that returns only the selected fields\n *\n * @example\n * ```ts\n * // Select specific columns\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => ({\n * name: users.name,\n * email: users.email\n * }))\n *\n * // Select with computed values\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => ({\n * fullName: concat(users.firstName, ' ', users.lastName),\n * ageInMonths: mul(users.age, 12)\n * }))\n *\n * // Select with aggregates (requires GROUP BY)\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .select(({posts, count}) => ({\n * userId: posts.userId,\n * postCount: count(posts.id)\n * }))\n * ```\n */\n select<TSelectObject extends SelectObject>(\n callback: (refs: RefsForContext<TContext>) => TSelectObject,\n ): QueryBuilder<WithResult<TContext, ResultTypeFromSelect<TSelectObject>>> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const selectObject = callback(refProxy)\n const select = buildNestedSelect(selectObject)\n\n return new BaseQueryBuilder({\n ...this.query,\n select: select,\n fnSelect: undefined, // remove the fnSelect clause if it exists\n }) as any\n }\n\n /**\n * Sort the query results by one or more columns\n *\n * @param callback - A function that receives table references and returns the field to sort by\n * @param direction - Sort direction: 'asc' for ascending, 'desc' for descending (defaults to 'asc')\n * @returns A QueryBuilder with the ordering applied\n *\n * @example\n * ```ts\n * // Sort by a single column\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.name)\n *\n * // Sort descending\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.createdAt, 'desc')\n *\n * // Multiple sorts (chain orderBy calls)\n * query\n * .from({ users: usersCollection })\n * .orderBy(({users}) => users.lastName)\n * .orderBy(({users}) => users.firstName)\n * ```\n */\n orderBy(\n callback: OrderByCallback<TContext>,\n options: OrderByDirection | OrderByOptions = `asc`,\n ): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const result = callback(refProxy)\n\n const opts: CompareOptions =\n typeof options === `string`\n ? { direction: options, nulls: `first` }\n : {\n direction: options.direction ?? `asc`,\n nulls: options.nulls ?? `first`,\n stringSort: options.stringSort,\n locale:\n options.stringSort === `locale` ? options.locale : undefined,\n localeOptions:\n options.stringSort === `locale`\n ? options.localeOptions\n : undefined,\n }\n\n const makeOrderByClause = (res: any) => {\n return {\n expression: toExpression(res),\n compareOptions: opts,\n }\n }\n\n // Create the new OrderBy structure with expression and direction\n const orderByClauses = Array.isArray(result)\n ? result.map((r) => makeOrderByClause(r))\n : [makeOrderByClause(result)]\n\n const existingOrderBy: OrderBy = this.query.orderBy || []\n\n return new BaseQueryBuilder({\n ...this.query,\n orderBy: [...existingOrderBy, ...orderByClauses],\n }) as any\n }\n\n /**\n * Group rows by one or more columns for aggregation\n *\n * @param callback - A function that receives table references and returns the field(s) to group by\n * @returns A QueryBuilder with grouping applied (enables aggregate functions in SELECT and HAVING)\n *\n * @example\n * ```ts\n * // Group by a single column\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .select(({posts, count}) => ({\n * userId: posts.userId,\n * postCount: count()\n * }))\n *\n * // Group by multiple columns\n * query\n * .from({ sales: salesCollection })\n * .groupBy(({sales}) => [sales.region, sales.category])\n * .select(({sales, sum}) => ({\n * region: sales.region,\n * category: sales.category,\n * totalSales: sum(sales.amount)\n * }))\n * ```\n */\n groupBy(callback: GroupByCallback<TContext>): QueryBuilder<TContext> {\n const aliases = this._getCurrentAliases()\n const refProxy = createRefProxy(aliases) as RefsForContext<TContext>\n const result = callback(refProxy)\n\n const newExpressions = Array.isArray(result)\n ? result.map((r) => toExpression(r))\n : [toExpression(result)]\n\n // Extend existing groupBy expressions (multiple groupBy calls should accumulate)\n const existingGroupBy = this.query.groupBy || []\n return new BaseQueryBuilder({\n ...this.query,\n groupBy: [...existingGroupBy, ...newExpressions],\n }) as any\n }\n\n /**\n * Limit the number of rows returned by the query\n * `orderBy` is required for `limit`\n *\n * @param count - Maximum number of rows to return\n * @returns A QueryBuilder with the limit applied\n *\n * @example\n * ```ts\n * // Get top 5 posts by likes\n * query\n * .from({ posts: postsCollection })\n * .orderBy(({posts}) => posts.likes, 'desc')\n * .limit(5)\n * ```\n */\n limit(count: number): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n limit: count,\n }) as any\n }\n\n /**\n * Skip a number of rows before returning results\n * `orderBy` is required for `offset`\n *\n * @param count - Number of rows to skip\n * @returns A QueryBuilder with the offset applied\n *\n * @example\n * ```ts\n * // Get second page of results\n * query\n * .from({ posts: postsCollection })\n * .orderBy(({posts}) => posts.createdAt, 'desc')\n * .offset(page * pageSize)\n * .limit(pageSize)\n * ```\n */\n offset(count: number): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n offset: count,\n }) as any\n }\n\n /**\n * Specify that the query should return distinct rows.\n * Deduplicates rows based on the selected columns.\n * @returns A QueryBuilder with distinct enabled\n *\n * @example\n * ```ts\n * // Get countries our users are from\n * query\n * .from({ users: usersCollection })\n * .select(({users}) => users.country)\n * .distinct()\n * ```\n */\n distinct(): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...this.query,\n distinct: true,\n }) as any\n }\n\n /**\n * Specify that the query should return a single result\n * @returns A QueryBuilder that returns the first result\n *\n * @example\n * ```ts\n * // Get the user matching the query\n * query\n * .from({ users: usersCollection })\n * .where(({users}) => eq(users.id, 1))\n * .findOne()\n *```\n */\n findOne(): QueryBuilder<TContext & SingleResult> {\n return new BaseQueryBuilder({\n ...this.query,\n // TODO: enforcing return only one result with also a default orderBy if none is specified\n // limit: 1,\n singleResult: true,\n })\n }\n\n // Helper methods\n private _getCurrentAliases(): Array<string> {\n const aliases: Array<string> = []\n\n // Add the from alias\n if (this.query.from) {\n aliases.push(this.query.from.alias)\n }\n\n // Add join aliases\n if (this.query.join) {\n for (const join of this.query.join) {\n aliases.push(join.from.alias)\n }\n }\n\n return aliases\n }\n\n /**\n * Functional variants of the query builder\n * These are imperative function that are called for ery row.\n * Warning: that these cannot be optimized by the query compiler, and may prevent\n * some type of optimizations being possible.\n * @example\n * ```ts\n * q.fn.select((row) => ({\n * name: row.user.name.toUpperCase(),\n * age: row.user.age + 1,\n * }))\n * ```\n */\n get fn() {\n const builder = this\n return {\n /**\n * Select fields using a function that operates on each row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives a row and returns the selected value\n * @returns A QueryBuilder with functional selection applied\n *\n * @example\n * ```ts\n * // Functional select (not optimized)\n * query\n * .from({ users: usersCollection })\n * .fn.select(row => ({\n * name: row.users.name.toUpperCase(),\n * age: row.users.age + 1,\n * }))\n * ```\n */\n select<TFuncSelectResult>(\n callback: (row: TContext[`schema`]) => TFuncSelectResult,\n ): QueryBuilder<WithResult<TContext, TFuncSelectResult>> {\n return new BaseQueryBuilder({\n ...builder.query,\n select: undefined, // remove the select clause if it exists\n fnSelect: callback,\n })\n },\n /**\n * Filter rows using a function that operates on each row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives a row and returns a boolean\n * @returns A QueryBuilder with functional filtering applied\n *\n * @example\n * ```ts\n * // Functional where (not optimized)\n * query\n * .from({ users: usersCollection })\n * .fn.where(row => row.users.name.startsWith('A'))\n * ```\n */\n where(\n callback: (row: TContext[`schema`]) => any,\n ): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...builder.query,\n fnWhere: [\n ...(builder.query.fnWhere || []),\n callback as (row: NamespacedRow) => any,\n ],\n })\n },\n /**\n * Filter grouped rows using a function that operates on each aggregated row\n * Warning: This cannot be optimized by the query compiler\n *\n * @param callback - A function that receives an aggregated row and returns a boolean\n * @returns A QueryBuilder with functional having filter applied\n *\n * @example\n * ```ts\n * // Functional having (not optimized)\n * query\n * .from({ posts: postsCollection })\n * .groupBy(({posts}) => posts.userId)\n * .fn.having(row => row.count > 5)\n * ```\n */\n having(\n callback: (row: TContext[`schema`]) => any,\n ): QueryBuilder<TContext> {\n return new BaseQueryBuilder({\n ...builder.query,\n fnHaving: [\n ...(builder.query.fnHaving || []),\n callback as (row: NamespacedRow) => any,\n ],\n })\n },\n }\n }\n\n _getQuery(): QueryIR {\n if (!this.query.from) {\n throw new QueryMustHaveFromClauseError()\n }\n return this.query as QueryIR\n }\n}\n\n// Helper to ensure we have a BasicExpression/Aggregate for a value\nfunction toExpr(value: any): BasicExpression | Aggregate {\n if (value === undefined) return toExpression(null)\n if (\n value instanceof AggregateExpr ||\n value instanceof FuncExpr ||\n value instanceof PropRef ||\n value instanceof ValueExpr\n ) {\n return value as BasicExpression | Aggregate\n }\n return toExpression(value)\n}\n\nfunction isPlainObject(value: any): value is Record<string, any> {\n return (\n value !== null &&\n typeof value === `object` &&\n !isExpressionLike(value) &&\n !value.__refProxy\n )\n}\n\nfunction buildNestedSelect(obj: any): any {\n if (!isPlainObject(obj)) return toExpr(obj)\n const out: Record<string, any> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (typeof k === `string` && k.startsWith(`__SPREAD_SENTINEL__`)) {\n // Preserve sentinel key and its value (value is unimportant at compile time)\n out[k] = v\n continue\n }\n out[k] = buildNestedSelect(v)\n }\n return out\n}\n\n// Internal function to build a query from a callback\n// used by liveQueryCollectionOptions.query\nexport function buildQuery<TContext extends Context>(\n fn: (builder: InitialQueryBuilder) => QueryBuilder<TContext>,\n): QueryIR {\n const result = fn(new BaseQueryBuilder())\n return getQueryIR(result)\n}\n\n// Internal function to get the QueryIR from a builder\nexport function getQueryIR(\n builder: BaseQueryBuilder | QueryBuilder<any> | InitialQueryBuilder,\n): QueryIR {\n return (builder as unknown as BaseQueryBuilder)._getQuery()\n}\n\n// Type-only exports for the query builder\nexport type InitialQueryBuilder = Pick<BaseQueryBuilder<Context>, `from`>\n\nexport type InitialQueryBuilderConstructor = new () => InitialQueryBuilder\n\nexport type QueryBuilder<TContext extends Context> = Omit<\n BaseQueryBuilder<TContext>,\n `from` | `_getQuery`\n>\n\n// Main query builder class alias with the constructor type modified to hide all\n// but the from method on the initial instance\nexport const Query: InitialQueryBuilderConstructor = BaseQueryBuilder\n\n// Helper type to extract context from a QueryBuilder\nexport type ExtractContext<T> =\n T extends BaseQueryBuilder<infer TContext>\n ? TContext\n : T extends QueryBuilder<infer TContext>\n ? TContext\n : never\n\n// Export the types from types.ts for convenience\nexport type {\n Context,\n Source,\n GetResult,\n RefLeaf as Ref,\n InferResultType,\n} from './types.js'\n"],"names":["AggregateExpr","FuncExpr","ValueExpr"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref-proxy.js","sources":["../../../../src/query/builder/ref-proxy.ts"],"sourcesContent":["import { PropRef, Value } from
|
|
1
|
+
{"version":3,"file":"ref-proxy.js","sources":["../../../../src/query/builder/ref-proxy.ts"],"sourcesContent":["import { PropRef, Value } from '../ir.js'\nimport type { BasicExpression } from '../ir.js'\nimport type { RefLeaf } from './types.js'\n\nexport interface RefProxy<T = any> {\n /** @internal */\n readonly __refProxy: true\n /** @internal */\n readonly __path: Array<string>\n /** @internal */\n readonly __type: T\n}\n\n/**\n * Type for creating a RefProxy for a single row/type without namespacing\n * Used in collection indexes and where clauses\n */\nexport type SingleRowRefProxy<T> =\n T extends Record<string, any>\n ? {\n [K in keyof T]: T[K] extends Record<string, any>\n ? SingleRowRefProxy<T[K]> & RefProxy<T[K]>\n : RefLeaf<T[K]>\n } & RefProxy<T>\n : RefProxy<T>\n\n/**\n * Creates a proxy object that records property access paths for a single row\n * Used in collection indexes and where clauses\n */\nexport function createSingleRowRefProxy<\n T extends Record<string, any>,\n>(): SingleRowRefProxy<T> {\n const cache = new Map<string, any>()\n\n function createProxy(path: Array<string>): any {\n const pathKey = path.join(`.`)\n if (cache.has(pathKey)) {\n return cache.get(pathKey)\n }\n\n const proxy = new Proxy({} as any, {\n get(target, prop, receiver) {\n if (prop === `__refProxy`) return true\n if (prop === `__path`) return path\n if (prop === `__type`) return undefined // Type is only for TypeScript inference\n if (typeof prop === `symbol`) return Reflect.get(target, prop, receiver)\n\n const newPath = [...path, String(prop)]\n return createProxy(newPath)\n },\n\n has(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`)\n return true\n return Reflect.has(target, prop)\n },\n\n ownKeys(target) {\n return Reflect.ownKeys(target)\n },\n\n getOwnPropertyDescriptor(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`) {\n return { enumerable: false, configurable: true }\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n })\n\n cache.set(pathKey, proxy)\n return proxy\n }\n\n // Return the root proxy that starts with an empty path\n return createProxy([]) as SingleRowRefProxy<T>\n}\n\n/**\n * Creates a proxy object that records property access paths\n * Used in callbacks like where, select, etc. to create type-safe references\n */\nexport function createRefProxy<T extends Record<string, any>>(\n aliases: Array<string>,\n): RefProxy<T> & T {\n const cache = new Map<string, any>()\n let accessId = 0 // Monotonic counter to record evaluation order\n\n function createProxy(path: Array<string>): any {\n const pathKey = path.join(`.`)\n if (cache.has(pathKey)) {\n return cache.get(pathKey)\n }\n\n const proxy = new Proxy({} as any, {\n get(target, prop, receiver) {\n if (prop === `__refProxy`) return true\n if (prop === `__path`) return path\n if (prop === `__type`) return undefined // Type is only for TypeScript inference\n if (typeof prop === `symbol`) return Reflect.get(target, prop, receiver)\n\n const newPath = [...path, String(prop)]\n return createProxy(newPath)\n },\n\n has(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`)\n return true\n return Reflect.has(target, prop)\n },\n\n ownKeys(target) {\n const id = ++accessId\n const sentinelKey = `__SPREAD_SENTINEL__${path.join(`.`)}__${id}`\n if (!Object.prototype.hasOwnProperty.call(target, sentinelKey)) {\n Object.defineProperty(target, sentinelKey, {\n enumerable: true,\n configurable: true,\n value: true,\n })\n }\n return Reflect.ownKeys(target)\n },\n\n getOwnPropertyDescriptor(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`) {\n return { enumerable: false, configurable: true }\n }\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n })\n\n cache.set(pathKey, proxy)\n return proxy\n }\n\n // Create the root proxy with all aliases as top-level properties\n const rootProxy = new Proxy({} as any, {\n get(target, prop, receiver) {\n if (prop === `__refProxy`) return true\n if (prop === `__path`) return []\n if (prop === `__type`) return undefined // Type is only for TypeScript inference\n if (typeof prop === `symbol`) return Reflect.get(target, prop, receiver)\n\n const propStr = String(prop)\n if (aliases.includes(propStr)) {\n return createProxy([propStr])\n }\n\n return undefined\n },\n\n has(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`)\n return true\n if (typeof prop === `string` && aliases.includes(prop)) return true\n return Reflect.has(target, prop)\n },\n\n ownKeys(_target) {\n return [...aliases, `__refProxy`, `__path`, `__type`]\n },\n\n getOwnPropertyDescriptor(target, prop) {\n if (prop === `__refProxy` || prop === `__path` || prop === `__type`) {\n return { enumerable: false, configurable: true }\n }\n if (typeof prop === `string` && aliases.includes(prop)) {\n return { enumerable: true, configurable: true }\n }\n return undefined\n },\n })\n\n return rootProxy\n}\n\n/**\n * Converts a value to an Expression\n * If it's a RefProxy, creates a Ref, otherwise creates a Value\n */\nexport function toExpression<T = any>(value: T): BasicExpression<T>\nexport function toExpression(value: RefProxy<any>): BasicExpression<any>\nexport function toExpression(value: any): BasicExpression<any> {\n if (isRefProxy(value)) {\n return new PropRef(value.__path)\n }\n // If it's already an Expression (Func, Ref, Value) or Agg, return it directly\n if (\n value &&\n typeof value === `object` &&\n `type` in value &&\n (value.type === `func` ||\n value.type === `ref` ||\n value.type === `val` ||\n value.type === `agg`)\n ) {\n return value\n }\n return new Value(value)\n}\n\n/**\n * Type guard to check if a value is a RefProxy\n */\nexport function isRefProxy(value: any): value is RefProxy {\n return value && typeof value === `object` && value.__refProxy === true\n}\n\n/**\n * Helper to create a Value expression from a literal\n */\nexport function val<T>(value: T): BasicExpression<T> {\n return new Value(value)\n}\n"],"names":[],"mappings":"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"}
|