@tanstack/db 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/collection.cjs +30 -26
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +4 -4
- package/dist/cjs/index.cjs +2 -2
- package/dist/cjs/index.d.cts +1 -1
- package/dist/cjs/indexes/auto-index.cjs +2 -2
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/{ordered-index.cjs → btree-index.cjs} +27 -63
- package/dist/cjs/indexes/btree-index.cjs.map +1 -0
- package/dist/{esm/indexes/ordered-index.d.ts → cjs/indexes/btree-index.d.cts} +6 -4
- package/dist/cjs/utils/btree.cjs +677 -0
- package/dist/cjs/utils/btree.cjs.map +1 -0
- package/dist/cjs/utils/btree.d.cts +197 -0
- package/dist/esm/collection.d.ts +4 -4
- package/dist/esm/collection.js +30 -26
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/indexes/auto-index.js +2 -2
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/{cjs/indexes/ordered-index.d.cts → esm/indexes/btree-index.d.ts} +6 -4
- package/dist/esm/indexes/{ordered-index.js → btree-index.js} +27 -63
- package/dist/esm/indexes/btree-index.js.map +1 -0
- package/dist/esm/utils/btree.d.ts +197 -0
- package/dist/esm/utils/btree.js +677 -0
- package/dist/esm/utils/btree.js.map +1 -0
- package/package.json +1 -1
- package/src/collection.ts +45 -33
- package/src/index.ts +1 -1
- package/src/indexes/auto-index.ts +2 -2
- package/src/indexes/{ordered-index.ts → btree-index.ts} +42 -84
- package/src/utils/btree.ts +1010 -0
- package/dist/cjs/indexes/ordered-index.cjs.map +0 -1
- package/dist/cjs/utils/array-utils.cjs +0 -18
- package/dist/cjs/utils/array-utils.cjs.map +0 -1
- package/dist/esm/indexes/ordered-index.js.map +0 -1
- package/dist/esm/utils/array-utils.js +0 -18
- package/dist/esm/utils/array-utils.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ordered-index.cjs","sources":["../../../src/indexes/ordered-index.ts"],"sourcesContent":["import { ascComparator } from \"../utils/comparison.js\"\nimport { findInsertPosition } from \"../utils/array-utils.js\"\nimport { BaseIndex } from \"./base-index.js\"\nimport type { IndexOperation } from \"./base-index.js\"\n\n/**\n * Options for Ordered index\n */\nexport interface OrderedIndexOptions {\n compareFn?: (a: any, b: any) => number\n}\n\n/**\n * Options for range queries\n */\nexport interface RangeQueryOptions {\n from?: any\n to?: any\n fromInclusive?: boolean\n toInclusive?: boolean\n}\n\n/**\n * Ordered index for sorted data with range queries\n * This maintains items in sorted order and provides efficient range operations\n */\nexport class OrderedIndex<\n TKey extends string | number = string | number,\n> extends BaseIndex<TKey> {\n public readonly supportedOperations = new Set<IndexOperation>([\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n ])\n\n // Internal data structures - private to hide implementation details\n private orderedEntries: Array<[any, Set<TKey>]> = []\n private valueMap = new Map<any, Set<TKey>>()\n private indexedKeys = new Set<TKey>()\n private compareFn: (a: any, b: any) => number = ascComparator\n\n protected initialize(options?: OrderedIndexOptions): void {\n this.compareFn = options?.compareFn ?? ascComparator\n }\n\n /**\n * Adds a value to the index\n */\n add(key: TKey, item: any): void {\n let indexedValue: any\n try {\n indexedValue = this.evaluateIndexExpression(item)\n } catch (error) {\n throw new Error(\n `Failed to evaluate index expression for key ${key}: ${error}`\n )\n }\n\n // Check if this value already exists\n if (this.valueMap.has(indexedValue)) {\n // Add to existing set\n this.valueMap.get(indexedValue)!.add(key)\n } else {\n // Create new set for this value\n const keySet = new Set<TKey>([key])\n this.valueMap.set(indexedValue, keySet)\n\n // Find correct position in ordered entries using binary search\n const insertIndex = findInsertPosition(\n this.orderedEntries,\n indexedValue,\n this.compareFn\n )\n this.orderedEntries.splice(insertIndex, 0, [indexedValue, keySet])\n }\n\n this.indexedKeys.add(key)\n this.updateTimestamp()\n }\n\n /**\n * Removes a value from the index\n */\n remove(key: TKey, item: any): void {\n let indexedValue: any\n try {\n indexedValue = this.evaluateIndexExpression(item)\n } catch (error) {\n console.warn(\n `Failed to evaluate index expression for key ${key} during removal:`,\n error\n )\n return\n }\n\n if (this.valueMap.has(indexedValue)) {\n const keySet = this.valueMap.get(indexedValue)!\n keySet.delete(key)\n\n // If set is now empty, remove the entry entirely\n if (keySet.size === 0) {\n this.valueMap.delete(indexedValue)\n\n // Find and remove from ordered entries\n const index = this.orderedEntries.findIndex(\n ([value]) => this.compareFn(value, indexedValue) === 0\n )\n if (index !== -1) {\n this.orderedEntries.splice(index, 1)\n }\n }\n }\n\n this.indexedKeys.delete(key)\n this.updateTimestamp()\n }\n\n /**\n * Updates a value in the index\n */\n update(key: TKey, oldItem: any, newItem: any): void {\n this.remove(key, oldItem)\n this.add(key, newItem)\n }\n\n /**\n * Builds the index from a collection of entries\n */\n build(entries: Iterable<[TKey, any]>): void {\n this.clear()\n\n for (const [key, item] of entries) {\n this.add(key, item)\n }\n }\n\n /**\n * Clears all data from the index\n */\n clear(): void {\n this.orderedEntries = []\n this.valueMap.clear()\n this.indexedKeys.clear()\n this.updateTimestamp()\n }\n\n /**\n * Performs a lookup operation\n */\n lookup(operation: IndexOperation, value: any): Set<TKey> {\n const startTime = performance.now()\n\n let result: Set<TKey>\n\n switch (operation) {\n case `eq`:\n result = this.equalityLookup(value)\n break\n case `gt`:\n result = this.rangeQuery({ from: value, fromInclusive: false })\n break\n case `gte`:\n result = this.rangeQuery({ from: value, fromInclusive: true })\n break\n case `lt`:\n result = this.rangeQuery({ to: value, toInclusive: false })\n break\n case `lte`:\n result = this.rangeQuery({ to: value, toInclusive: true })\n break\n case `in`:\n result = this.inArrayLookup(value)\n break\n default:\n throw new Error(`Operation ${operation} not supported by OrderedIndex`)\n }\n\n this.trackLookup(startTime)\n return result\n }\n\n /**\n * Gets the number of indexed keys\n */\n get keyCount(): number {\n return this.indexedKeys.size\n }\n\n // Public methods for backward compatibility (used by tests)\n\n /**\n * Performs an equality lookup\n */\n equalityLookup(value: any): Set<TKey> {\n return new Set(this.valueMap.get(value) ?? [])\n }\n\n /**\n * Performs a range query with options\n * This is more efficient for compound queries like \"WHERE a > 5 AND a < 10\"\n */\n rangeQuery(options: RangeQueryOptions = {}): Set<TKey> {\n const { from, to, fromInclusive = true, toInclusive = true } = options\n const result = new Set<TKey>()\n\n if (this.orderedEntries.length === 0) {\n return result\n }\n\n // Find start position\n let startIndex = 0\n if (from !== undefined) {\n const fromInsertIndex = findInsertPosition(\n this.orderedEntries,\n from,\n this.compareFn\n )\n\n if (fromInclusive) {\n // Include values equal to 'from'\n startIndex = fromInsertIndex\n } else {\n // Exclude values equal to 'from'\n startIndex = fromInsertIndex\n // Skip the value if it exists at this position\n if (\n startIndex < this.orderedEntries.length &&\n this.compareFn(this.orderedEntries[startIndex]![0], from) === 0\n ) {\n startIndex++\n }\n }\n }\n\n // Find end position\n let endIndex = this.orderedEntries.length\n if (to !== undefined) {\n const toInsertIndex = findInsertPosition(\n this.orderedEntries,\n to,\n this.compareFn\n )\n\n if (toInclusive) {\n // Include values equal to 'to'\n endIndex = toInsertIndex\n // Include the value if it exists at this position\n if (\n toInsertIndex < this.orderedEntries.length &&\n this.compareFn(this.orderedEntries[toInsertIndex]![0], to) === 0\n ) {\n endIndex = toInsertIndex + 1\n }\n } else {\n // Exclude values equal to 'to'\n endIndex = toInsertIndex\n }\n }\n\n // Ensure startIndex doesn't exceed endIndex\n if (startIndex >= endIndex) {\n return result\n }\n\n // Collect keys from the range\n for (let i = startIndex; i < endIndex; i++) {\n const keys = this.orderedEntries[i]![1]\n keys.forEach((key) => result.add(key))\n }\n\n return result\n }\n\n /**\n * Performs an IN array lookup\n */\n inArrayLookup(values: Array<any>): Set<TKey> {\n const result = new Set<TKey>()\n\n for (const value of values) {\n const keys = this.valueMap.get(value)\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n\n return result\n }\n\n // Getter methods for testing compatibility\n get indexedKeysSet(): Set<TKey> {\n return this.indexedKeys\n }\n\n get orderedEntriesArray(): Array<[any, Set<TKey>]> {\n return this.orderedEntries\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n return this.valueMap\n }\n}\n"],"names":["BaseIndex","ascComparator","findInsertPosition"],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
function findInsertPosition(sortedArray, value, compareFn) {
|
|
4
|
-
let left = 0;
|
|
5
|
-
let right = sortedArray.length;
|
|
6
|
-
while (left < right) {
|
|
7
|
-
const mid = Math.floor((left + right) / 2);
|
|
8
|
-
const comparison = compareFn(sortedArray[mid][0], value);
|
|
9
|
-
if (comparison < 0) {
|
|
10
|
-
left = mid + 1;
|
|
11
|
-
} else {
|
|
12
|
-
right = mid;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return left;
|
|
16
|
-
}
|
|
17
|
-
exports.findInsertPosition = findInsertPosition;
|
|
18
|
-
//# sourceMappingURL=array-utils.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"array-utils.cjs","sources":["../../../src/utils/array-utils.ts"],"sourcesContent":["/**\n * Finds the correct insert position for a value in a sorted array using binary search\n * @param sortedArray The sorted array to search in\n * @param value The value to find the position for\n * @param compareFn Comparison function to use for ordering\n * @returns The index where the value should be inserted to maintain order\n */\nexport function findInsertPosition<T>(\n sortedArray: Array<[T, any]>,\n value: T,\n compareFn: (a: T, b: T) => number\n): number {\n let left = 0\n let right = sortedArray.length\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2)\n const comparison = compareFn(sortedArray[mid]![0], value)\n\n if (comparison < 0) {\n left = mid + 1\n } else {\n right = mid\n }\n }\n\n return left\n}\n"],"names":[],"mappings":";;AAOO,SAAS,mBACd,aACA,OACA,WACQ;AACR,MAAI,OAAO;AACX,MAAI,QAAQ,YAAY;AAExB,SAAO,OAAO,OAAO;AACnB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,UAAM,aAAa,UAAU,YAAY,GAAG,EAAG,CAAC,GAAG,KAAK;AAExD,QAAI,aAAa,GAAG;AAClB,aAAO,MAAM;AAAA,IACf,OAAO;AACL,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ordered-index.js","sources":["../../../src/indexes/ordered-index.ts"],"sourcesContent":["import { ascComparator } from \"../utils/comparison.js\"\nimport { findInsertPosition } from \"../utils/array-utils.js\"\nimport { BaseIndex } from \"./base-index.js\"\nimport type { IndexOperation } from \"./base-index.js\"\n\n/**\n * Options for Ordered index\n */\nexport interface OrderedIndexOptions {\n compareFn?: (a: any, b: any) => number\n}\n\n/**\n * Options for range queries\n */\nexport interface RangeQueryOptions {\n from?: any\n to?: any\n fromInclusive?: boolean\n toInclusive?: boolean\n}\n\n/**\n * Ordered index for sorted data with range queries\n * This maintains items in sorted order and provides efficient range operations\n */\nexport class OrderedIndex<\n TKey extends string | number = string | number,\n> extends BaseIndex<TKey> {\n public readonly supportedOperations = new Set<IndexOperation>([\n `eq`,\n `gt`,\n `gte`,\n `lt`,\n `lte`,\n `in`,\n ])\n\n // Internal data structures - private to hide implementation details\n private orderedEntries: Array<[any, Set<TKey>]> = []\n private valueMap = new Map<any, Set<TKey>>()\n private indexedKeys = new Set<TKey>()\n private compareFn: (a: any, b: any) => number = ascComparator\n\n protected initialize(options?: OrderedIndexOptions): void {\n this.compareFn = options?.compareFn ?? ascComparator\n }\n\n /**\n * Adds a value to the index\n */\n add(key: TKey, item: any): void {\n let indexedValue: any\n try {\n indexedValue = this.evaluateIndexExpression(item)\n } catch (error) {\n throw new Error(\n `Failed to evaluate index expression for key ${key}: ${error}`\n )\n }\n\n // Check if this value already exists\n if (this.valueMap.has(indexedValue)) {\n // Add to existing set\n this.valueMap.get(indexedValue)!.add(key)\n } else {\n // Create new set for this value\n const keySet = new Set<TKey>([key])\n this.valueMap.set(indexedValue, keySet)\n\n // Find correct position in ordered entries using binary search\n const insertIndex = findInsertPosition(\n this.orderedEntries,\n indexedValue,\n this.compareFn\n )\n this.orderedEntries.splice(insertIndex, 0, [indexedValue, keySet])\n }\n\n this.indexedKeys.add(key)\n this.updateTimestamp()\n }\n\n /**\n * Removes a value from the index\n */\n remove(key: TKey, item: any): void {\n let indexedValue: any\n try {\n indexedValue = this.evaluateIndexExpression(item)\n } catch (error) {\n console.warn(\n `Failed to evaluate index expression for key ${key} during removal:`,\n error\n )\n return\n }\n\n if (this.valueMap.has(indexedValue)) {\n const keySet = this.valueMap.get(indexedValue)!\n keySet.delete(key)\n\n // If set is now empty, remove the entry entirely\n if (keySet.size === 0) {\n this.valueMap.delete(indexedValue)\n\n // Find and remove from ordered entries\n const index = this.orderedEntries.findIndex(\n ([value]) => this.compareFn(value, indexedValue) === 0\n )\n if (index !== -1) {\n this.orderedEntries.splice(index, 1)\n }\n }\n }\n\n this.indexedKeys.delete(key)\n this.updateTimestamp()\n }\n\n /**\n * Updates a value in the index\n */\n update(key: TKey, oldItem: any, newItem: any): void {\n this.remove(key, oldItem)\n this.add(key, newItem)\n }\n\n /**\n * Builds the index from a collection of entries\n */\n build(entries: Iterable<[TKey, any]>): void {\n this.clear()\n\n for (const [key, item] of entries) {\n this.add(key, item)\n }\n }\n\n /**\n * Clears all data from the index\n */\n clear(): void {\n this.orderedEntries = []\n this.valueMap.clear()\n this.indexedKeys.clear()\n this.updateTimestamp()\n }\n\n /**\n * Performs a lookup operation\n */\n lookup(operation: IndexOperation, value: any): Set<TKey> {\n const startTime = performance.now()\n\n let result: Set<TKey>\n\n switch (operation) {\n case `eq`:\n result = this.equalityLookup(value)\n break\n case `gt`:\n result = this.rangeQuery({ from: value, fromInclusive: false })\n break\n case `gte`:\n result = this.rangeQuery({ from: value, fromInclusive: true })\n break\n case `lt`:\n result = this.rangeQuery({ to: value, toInclusive: false })\n break\n case `lte`:\n result = this.rangeQuery({ to: value, toInclusive: true })\n break\n case `in`:\n result = this.inArrayLookup(value)\n break\n default:\n throw new Error(`Operation ${operation} not supported by OrderedIndex`)\n }\n\n this.trackLookup(startTime)\n return result\n }\n\n /**\n * Gets the number of indexed keys\n */\n get keyCount(): number {\n return this.indexedKeys.size\n }\n\n // Public methods for backward compatibility (used by tests)\n\n /**\n * Performs an equality lookup\n */\n equalityLookup(value: any): Set<TKey> {\n return new Set(this.valueMap.get(value) ?? [])\n }\n\n /**\n * Performs a range query with options\n * This is more efficient for compound queries like \"WHERE a > 5 AND a < 10\"\n */\n rangeQuery(options: RangeQueryOptions = {}): Set<TKey> {\n const { from, to, fromInclusive = true, toInclusive = true } = options\n const result = new Set<TKey>()\n\n if (this.orderedEntries.length === 0) {\n return result\n }\n\n // Find start position\n let startIndex = 0\n if (from !== undefined) {\n const fromInsertIndex = findInsertPosition(\n this.orderedEntries,\n from,\n this.compareFn\n )\n\n if (fromInclusive) {\n // Include values equal to 'from'\n startIndex = fromInsertIndex\n } else {\n // Exclude values equal to 'from'\n startIndex = fromInsertIndex\n // Skip the value if it exists at this position\n if (\n startIndex < this.orderedEntries.length &&\n this.compareFn(this.orderedEntries[startIndex]![0], from) === 0\n ) {\n startIndex++\n }\n }\n }\n\n // Find end position\n let endIndex = this.orderedEntries.length\n if (to !== undefined) {\n const toInsertIndex = findInsertPosition(\n this.orderedEntries,\n to,\n this.compareFn\n )\n\n if (toInclusive) {\n // Include values equal to 'to'\n endIndex = toInsertIndex\n // Include the value if it exists at this position\n if (\n toInsertIndex < this.orderedEntries.length &&\n this.compareFn(this.orderedEntries[toInsertIndex]![0], to) === 0\n ) {\n endIndex = toInsertIndex + 1\n }\n } else {\n // Exclude values equal to 'to'\n endIndex = toInsertIndex\n }\n }\n\n // Ensure startIndex doesn't exceed endIndex\n if (startIndex >= endIndex) {\n return result\n }\n\n // Collect keys from the range\n for (let i = startIndex; i < endIndex; i++) {\n const keys = this.orderedEntries[i]![1]\n keys.forEach((key) => result.add(key))\n }\n\n return result\n }\n\n /**\n * Performs an IN array lookup\n */\n inArrayLookup(values: Array<any>): Set<TKey> {\n const result = new Set<TKey>()\n\n for (const value of values) {\n const keys = this.valueMap.get(value)\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n\n return result\n }\n\n // Getter methods for testing compatibility\n get indexedKeysSet(): Set<TKey> {\n return this.indexedKeys\n }\n\n get orderedEntriesArray(): Array<[any, Set<TKey>]> {\n return this.orderedEntries\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n return this.valueMap\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
function findInsertPosition(sortedArray, value, compareFn) {
|
|
2
|
-
let left = 0;
|
|
3
|
-
let right = sortedArray.length;
|
|
4
|
-
while (left < right) {
|
|
5
|
-
const mid = Math.floor((left + right) / 2);
|
|
6
|
-
const comparison = compareFn(sortedArray[mid][0], value);
|
|
7
|
-
if (comparison < 0) {
|
|
8
|
-
left = mid + 1;
|
|
9
|
-
} else {
|
|
10
|
-
right = mid;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
return left;
|
|
14
|
-
}
|
|
15
|
-
export {
|
|
16
|
-
findInsertPosition
|
|
17
|
-
};
|
|
18
|
-
//# sourceMappingURL=array-utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"array-utils.js","sources":["../../../src/utils/array-utils.ts"],"sourcesContent":["/**\n * Finds the correct insert position for a value in a sorted array using binary search\n * @param sortedArray The sorted array to search in\n * @param value The value to find the position for\n * @param compareFn Comparison function to use for ordering\n * @returns The index where the value should be inserted to maintain order\n */\nexport function findInsertPosition<T>(\n sortedArray: Array<[T, any]>,\n value: T,\n compareFn: (a: T, b: T) => number\n): number {\n let left = 0\n let right = sortedArray.length\n\n while (left < right) {\n const mid = Math.floor((left + right) / 2)\n const comparison = compareFn(sortedArray[mid]![0], value)\n\n if (comparison < 0) {\n left = mid + 1\n } else {\n right = mid\n }\n }\n\n return left\n}\n"],"names":[],"mappings":"AAOO,SAAS,mBACd,aACA,OACA,WACQ;AACR,MAAI,OAAO;AACX,MAAI,QAAQ,YAAY;AAExB,SAAO,OAAO,OAAO;AACnB,UAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,UAAM,aAAa,UAAU,YAAY,GAAG,EAAG,CAAC,GAAG,KAAK;AAExD,QAAI,aAAa,GAAG;AAClB,aAAO,MAAM;AAAA,IACf,OAAO;AACL,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;"}
|