@tanstack/db 0.4.3 → 0.4.5
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/change-events.cjs +1 -1
- package/dist/cjs/collection/change-events.cjs.map +1 -1
- package/dist/cjs/collection/changes.cjs +7 -3
- package/dist/cjs/collection/changes.cjs.map +1 -1
- package/dist/cjs/collection/events.cjs +3 -6
- package/dist/cjs/collection/events.cjs.map +1 -1
- package/dist/cjs/collection/index.cjs +4 -1
- package/dist/cjs/collection/index.cjs.map +1 -1
- package/dist/cjs/collection/index.d.cts +16 -4
- package/dist/cjs/collection/mutations.cjs +13 -20
- package/dist/cjs/collection/mutations.cjs.map +1 -1
- package/dist/cjs/collection/state.cjs +14 -6
- package/dist/cjs/collection/state.cjs.map +1 -1
- package/dist/cjs/collection/subscription.cjs +3 -4
- package/dist/cjs/collection/subscription.cjs.map +1 -1
- package/dist/cjs/collection/subscription.d.cts +2 -2
- package/dist/cjs/collection/sync.cjs +10 -2
- package/dist/cjs/collection/sync.cjs.map +1 -1
- package/dist/cjs/indexes/auto-index.cjs +4 -3
- package/dist/cjs/indexes/auto-index.cjs.map +1 -1
- package/dist/cjs/indexes/auto-index.d.cts +2 -1
- package/dist/cjs/indexes/base-index.cjs +26 -0
- package/dist/cjs/indexes/base-index.cjs.map +1 -1
- package/dist/cjs/indexes/base-index.d.cts +47 -2
- package/dist/cjs/indexes/btree-index.cjs +45 -9
- package/dist/cjs/indexes/btree-index.cjs.map +1 -1
- package/dist/cjs/indexes/btree-index.d.cts +15 -0
- package/dist/cjs/indexes/lazy-index.cjs +3 -6
- package/dist/cjs/indexes/lazy-index.cjs.map +1 -1
- package/dist/cjs/indexes/reverse-index.cjs +78 -0
- package/dist/cjs/indexes/reverse-index.cjs.map +1 -0
- package/dist/cjs/indexes/reverse-index.d.cts +30 -0
- package/dist/cjs/proxy.cjs +1 -1
- package/dist/cjs/proxy.cjs.map +1 -1
- package/dist/cjs/query/builder/index.cjs +21 -0
- package/dist/cjs/query/builder/index.cjs.map +1 -1
- package/dist/cjs/query/builder/index.d.cts +16 -1
- package/dist/cjs/query/builder/types.d.cts +7 -0
- package/dist/cjs/query/compiler/evaluators.cjs +1 -1
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
- package/dist/cjs/query/compiler/group-by.cjs +2 -10
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/joins.cjs +6 -6
- package/dist/cjs/query/compiler/joins.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.cjs +4 -5
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
- package/dist/cjs/query/compiler/order-by.d.cts +2 -2
- package/dist/cjs/query/compiler/select.cjs +1 -1
- package/dist/cjs/query/compiler/select.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/ir.d.cts +1 -0
- package/dist/cjs/query/live/collection-config-builder.cjs +3 -2
- package/dist/cjs/query/live/collection-config-builder.cjs.map +1 -1
- package/dist/cjs/query/live/collection-config-builder.d.cts +2 -2
- package/dist/cjs/query/live/collection-subscriber.cjs +2 -3
- package/dist/cjs/query/live/collection-subscriber.cjs.map +1 -1
- package/dist/cjs/query/live/types.d.cts +4 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -1
- package/dist/cjs/query/live-query-collection.d.cts +7 -4
- package/dist/cjs/query/optimizer.cjs +2 -4
- package/dist/cjs/query/optimizer.cjs.map +1 -1
- package/dist/cjs/transactions.cjs +2 -3
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/types.d.cts +13 -0
- package/dist/cjs/utils/btree.cjs +1 -1
- package/dist/cjs/utils/btree.cjs.map +1 -1
- package/dist/cjs/utils/index-optimization.cjs +7 -2
- package/dist/cjs/utils/index-optimization.cjs.map +1 -1
- package/dist/cjs/utils/index-optimization.d.cts +3 -2
- package/dist/cjs/utils.cjs +6 -0
- package/dist/cjs/utils.cjs.map +1 -1
- package/dist/cjs/utils.d.cts +2 -3
- package/dist/esm/collection/change-events.js +1 -1
- package/dist/esm/collection/change-events.js.map +1 -1
- package/dist/esm/collection/changes.js +7 -3
- package/dist/esm/collection/changes.js.map +1 -1
- package/dist/esm/collection/events.js +3 -6
- package/dist/esm/collection/events.js.map +1 -1
- package/dist/esm/collection/index.d.ts +16 -4
- package/dist/esm/collection/index.js +4 -1
- package/dist/esm/collection/index.js.map +1 -1
- package/dist/esm/collection/mutations.js +13 -20
- package/dist/esm/collection/mutations.js.map +1 -1
- package/dist/esm/collection/state.js +14 -6
- package/dist/esm/collection/state.js.map +1 -1
- package/dist/esm/collection/subscription.d.ts +2 -2
- package/dist/esm/collection/subscription.js +3 -4
- package/dist/esm/collection/subscription.js.map +1 -1
- package/dist/esm/collection/sync.js +10 -2
- package/dist/esm/collection/sync.js.map +1 -1
- package/dist/esm/indexes/auto-index.d.ts +2 -1
- package/dist/esm/indexes/auto-index.js +4 -3
- package/dist/esm/indexes/auto-index.js.map +1 -1
- package/dist/esm/indexes/base-index.d.ts +47 -2
- package/dist/esm/indexes/base-index.js +26 -0
- package/dist/esm/indexes/base-index.js.map +1 -1
- package/dist/esm/indexes/btree-index.d.ts +15 -0
- package/dist/esm/indexes/btree-index.js +45 -9
- package/dist/esm/indexes/btree-index.js.map +1 -1
- package/dist/esm/indexes/lazy-index.js +3 -6
- package/dist/esm/indexes/lazy-index.js.map +1 -1
- package/dist/esm/indexes/reverse-index.d.ts +30 -0
- package/dist/esm/indexes/reverse-index.js +78 -0
- package/dist/esm/indexes/reverse-index.js.map +1 -0
- package/dist/esm/proxy.js +1 -1
- package/dist/esm/proxy.js.map +1 -1
- package/dist/esm/query/builder/index.d.ts +16 -1
- package/dist/esm/query/builder/index.js +21 -0
- package/dist/esm/query/builder/index.js.map +1 -1
- package/dist/esm/query/builder/types.d.ts +7 -0
- package/dist/esm/query/compiler/evaluators.js +1 -1
- package/dist/esm/query/compiler/evaluators.js.map +1 -1
- package/dist/esm/query/compiler/group-by.js +3 -11
- package/dist/esm/query/compiler/group-by.js.map +1 -1
- package/dist/esm/query/compiler/joins.js +6 -6
- package/dist/esm/query/compiler/joins.js.map +1 -1
- package/dist/esm/query/compiler/order-by.d.ts +2 -2
- package/dist/esm/query/compiler/order-by.js +4 -5
- package/dist/esm/query/compiler/order-by.js.map +1 -1
- package/dist/esm/query/compiler/select.js +1 -1
- package/dist/esm/query/compiler/select.js.map +1 -1
- package/dist/esm/query/index.d.ts +1 -1
- package/dist/esm/query/ir.d.ts +1 -0
- package/dist/esm/query/ir.js.map +1 -1
- package/dist/esm/query/live/collection-config-builder.d.ts +2 -2
- package/dist/esm/query/live/collection-config-builder.js +3 -2
- package/dist/esm/query/live/collection-config-builder.js.map +1 -1
- package/dist/esm/query/live/collection-subscriber.js +2 -3
- package/dist/esm/query/live/collection-subscriber.js.map +1 -1
- package/dist/esm/query/live/types.d.ts +4 -0
- package/dist/esm/query/live-query-collection.d.ts +7 -4
- package/dist/esm/query/live-query-collection.js.map +1 -1
- package/dist/esm/query/optimizer.js +2 -4
- package/dist/esm/query/optimizer.js.map +1 -1
- package/dist/esm/transactions.js +2 -3
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +13 -0
- package/dist/esm/utils/btree.js +1 -1
- package/dist/esm/utils/btree.js.map +1 -1
- package/dist/esm/utils/index-optimization.d.ts +3 -2
- package/dist/esm/utils/index-optimization.js +7 -2
- package/dist/esm/utils/index-optimization.js.map +1 -1
- package/dist/esm/utils.d.ts +2 -3
- package/dist/esm/utils.js +6 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/collection/changes.ts +10 -4
- package/src/collection/index.ts +38 -5
- package/src/collection/state.ts +28 -11
- package/src/collection/subscription.ts +3 -3
- package/src/collection/sync.ts +17 -2
- package/src/indexes/auto-index.ts +8 -3
- package/src/indexes/base-index.ts +94 -4
- package/src/indexes/btree-index.ts +58 -7
- package/src/indexes/reverse-index.ts +120 -0
- package/src/query/builder/index.ts +30 -2
- package/src/query/builder/types.ts +12 -0
- package/src/query/compiler/group-by.ts +1 -10
- package/src/query/compiler/order-by.ts +15 -18
- package/src/query/index.ts +1 -0
- package/src/query/ir.ts +1 -0
- package/src/query/live/collection-config-builder.ts +3 -2
- package/src/query/live/types.ts +5 -0
- package/src/query/live-query-collection.ts +34 -8
- package/src/types.ts +22 -0
- package/src/utils/index-optimization.ts +19 -5
- package/src/utils.ts +8 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const utils = require("../utils.cjs");
|
|
3
4
|
const btreeIndex = require("./btree-index.cjs");
|
|
4
5
|
function shouldAutoIndex(collection) {
|
|
5
6
|
if (collection.config.autoIndex !== `eager`) {
|
|
@@ -10,12 +11,12 @@ function shouldAutoIndex(collection) {
|
|
|
10
11
|
}
|
|
11
12
|
return true;
|
|
12
13
|
}
|
|
13
|
-
function ensureIndexForField(fieldName, fieldPath, collection, compareFn) {
|
|
14
|
+
function ensureIndexForField(fieldName, fieldPath, collection, compareOptions = utils.DEFAULT_COMPARE_OPTIONS, compareFn) {
|
|
14
15
|
if (!shouldAutoIndex(collection)) {
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
18
|
const existingIndex = Array.from(collection.indexes.values()).find(
|
|
18
|
-
(index) => index.matchesField(fieldPath)
|
|
19
|
+
(index) => index.matchesField(fieldPath) && index.matchesCompareOptions(compareOptions)
|
|
19
20
|
);
|
|
20
21
|
if (existingIndex) {
|
|
21
22
|
return;
|
|
@@ -24,7 +25,7 @@ function ensureIndexForField(fieldName, fieldPath, collection, compareFn) {
|
|
|
24
25
|
collection.createIndex((row) => row[fieldName], {
|
|
25
26
|
name: `auto_${fieldName}`,
|
|
26
27
|
indexType: btreeIndex.BTreeIndex,
|
|
27
|
-
options: compareFn ? { compareFn } : {}
|
|
28
|
+
options: compareFn ? { compareFn, compareOptions } : {}
|
|
28
29
|
});
|
|
29
30
|
} catch (error) {
|
|
30
31
|
console.warn(`Failed to create auto-index for field "${fieldName}":`, error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-index.cjs","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { BTreeIndex } from \"./btree-index\"\nimport type { BasicExpression } from \"../query/ir\"\nimport type { CollectionImpl } from \"../collection/index.js\"\n\nexport interface AutoIndexConfig {\n autoIndex?: `off` | `eager`\n}\n\nfunction shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {\n // Only proceed if auto-indexing is enabled\n if (collection.config.autoIndex !== `eager`) {\n return false\n }\n\n // Don't auto-index during sync operations\n if (\n collection.status === `loading` ||\n collection.status === `initialCommit`\n ) {\n return false\n }\n\n return true\n}\n\nexport function ensureIndexForField<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n fieldName: string,\n fieldPath: Array<string>,\n collection: CollectionImpl<T, TKey, any, any, any>,\n compareFn?: (a: any, b: any) => number\n) {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Check if we already have an index for this field\n const existingIndex = Array.from(collection.indexes.values()).find((index) =>\n
|
|
1
|
+
{"version":3,"file":"auto-index.cjs","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { DEFAULT_COMPARE_OPTIONS } from \"../utils\"\nimport { BTreeIndex } from \"./btree-index\"\nimport type { CompareOptions } from \"../query/builder/types\"\nimport type { BasicExpression } from \"../query/ir\"\nimport type { CollectionImpl } from \"../collection/index.js\"\n\nexport interface AutoIndexConfig {\n autoIndex?: `off` | `eager`\n}\n\nfunction shouldAutoIndex(collection: CollectionImpl<any, any, any, any, any>) {\n // Only proceed if auto-indexing is enabled\n if (collection.config.autoIndex !== `eager`) {\n return false\n }\n\n // Don't auto-index during sync operations\n if (\n collection.status === `loading` ||\n collection.status === `initialCommit`\n ) {\n return false\n }\n\n return true\n}\n\nexport function ensureIndexForField<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n fieldName: string,\n fieldPath: Array<string>,\n collection: CollectionImpl<T, TKey, any, any, any>,\n compareOptions: CompareOptions = DEFAULT_COMPARE_OPTIONS,\n compareFn?: (a: any, b: any) => number\n) {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Check if we already have an index for this field\n const existingIndex = Array.from(collection.indexes.values()).find(\n (index) =>\n index.matchesField(fieldPath) &&\n index.matchesCompareOptions(compareOptions)\n )\n\n if (existingIndex) {\n return // Index already exists\n }\n\n // Create a new index for this field using the collection's createIndex method\n try {\n collection.createIndex((row) => (row as any)[fieldName], {\n name: `auto_${fieldName}`,\n indexType: BTreeIndex,\n options: compareFn ? { compareFn, compareOptions } : {},\n })\n } catch (error) {\n console.warn(`Failed to create auto-index for field \"${fieldName}\":`, error)\n }\n}\n\n/**\n * Analyzes a where expression and creates indexes for all simple operations on single fields\n */\nexport function ensureIndexForExpression<\n T extends Record<string, any>,\n TKey extends string | number,\n>(\n expression: BasicExpression,\n collection: CollectionImpl<T, TKey, any, any, any>\n): void {\n if (!shouldAutoIndex(collection)) {\n return\n }\n\n // Extract all indexable expressions and create indexes for them\n const indexableExpressions = extractIndexableExpressions(expression)\n\n for (const { fieldName, fieldPath } of indexableExpressions) {\n ensureIndexForField(fieldName, fieldPath, collection)\n }\n}\n\n/**\n * Extracts all indexable expressions from a where expression\n */\nfunction extractIndexableExpressions(\n expression: BasicExpression\n): Array<{ fieldName: string; fieldPath: Array<string> }> {\n const results: Array<{ fieldName: string; fieldPath: Array<string> }> = []\n\n function extractFromExpression(expr: BasicExpression): void {\n if (expr.type !== `func`) {\n return\n }\n\n const func = expr as any\n\n // Handle 'and' expressions by recursively processing all arguments\n if (func.name === `and`) {\n for (const arg of func.args) {\n extractFromExpression(arg)\n }\n return\n }\n\n // Check if this is a supported operation\n const supportedOperations = [`eq`, `gt`, `gte`, `lt`, `lte`, `in`]\n if (!supportedOperations.includes(func.name)) {\n return\n }\n\n // Check if the first argument is a property reference (single field)\n if (func.args.length < 1 || func.args[0].type !== `ref`) {\n return\n }\n\n const fieldRef = func.args[0]\n const fieldPath = fieldRef.path\n\n // Skip if it's not a simple field (e.g., nested properties or array access)\n if (fieldPath.length !== 1) {\n return\n }\n\n const fieldName = fieldPath[0]\n results.push({ fieldName, fieldPath })\n }\n\n extractFromExpression(expression)\n return results\n}\n"],"names":["DEFAULT_COMPARE_OPTIONS","BTreeIndex"],"mappings":";;;;AAUA,SAAS,gBAAgB,YAAqD;AAE5E,MAAI,WAAW,OAAO,cAAc,SAAS;AAC3C,WAAO;AAAA,EACT;AAGA,MACE,WAAW,WAAW,aACtB,WAAW,WAAW,iBACtB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,oBAId,WACA,WACA,YACA,iBAAiCA,MAAAA,yBACjC,WACA;AACA,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,gBAAgB,MAAM,KAAK,WAAW,QAAQ,OAAA,CAAQ,EAAE;AAAA,IAC5D,CAAC,UACC,MAAM,aAAa,SAAS,KAC5B,MAAM,sBAAsB,cAAc;AAAA,EAAA;AAG9C,MAAI,eAAe;AACjB;AAAA,EACF;AAGA,MAAI;AACF,eAAW,YAAY,CAAC,QAAS,IAAY,SAAS,GAAG;AAAA,MACvD,MAAM,QAAQ,SAAS;AAAA,MACvB,WAAWC,WAAAA;AAAAA,MACX,SAAS,YAAY,EAAE,WAAW,eAAA,IAAmB,CAAA;AAAA,IAAC,CACvD;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,KAAK,0CAA0C,SAAS,MAAM,KAAK;AAAA,EAC7E;AACF;AAKO,SAAS,yBAId,YACA,YACM;AACN,MAAI,CAAC,gBAAgB,UAAU,GAAG;AAChC;AAAA,EACF;AAGA,QAAM,uBAAuB,4BAA4B,UAAU;AAEnE,aAAW,EAAE,WAAW,UAAA,KAAe,sBAAsB;AAC3D,wBAAoB,WAAW,WAAW,UAAU;AAAA,EACtD;AACF;AAKA,SAAS,4BACP,YACwD;AACxD,QAAM,UAAkE,CAAA;AAExE,WAAS,sBAAsB,MAA6B;AAC1D,QAAI,KAAK,SAAS,QAAQ;AACxB;AAAA,IACF;AAEA,UAAM,OAAO;AAGb,QAAI,KAAK,SAAS,OAAO;AACvB,iBAAW,OAAO,KAAK,MAAM;AAC3B,8BAAsB,GAAG;AAAA,MAC3B;AACA;AAAA,IACF;AAGA,UAAM,sBAAsB,CAAC,MAAM,MAAM,OAAO,MAAM,OAAO,IAAI;AACjE,QAAI,CAAC,oBAAoB,SAAS,KAAK,IAAI,GAAG;AAC5C;AAAA,IACF;AAGA,QAAI,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,EAAE,SAAS,OAAO;AACvD;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,KAAK,CAAC;AAC5B,UAAM,YAAY,SAAS;AAG3B,QAAI,UAAU,WAAW,GAAG;AAC1B;AAAA,IACF;AAEA,UAAM,YAAY,UAAU,CAAC;AAC7B,YAAQ,KAAK,EAAE,WAAW,UAAA,CAAW;AAAA,EACvC;AAEA,wBAAsB,UAAU;AAChC,SAAO;AACT;;;"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { CompareOptions } from '../query/builder/types.cjs';
|
|
1
2
|
import { BasicExpression } from '../query/ir.cjs';
|
|
2
3
|
import { CollectionImpl } from '../collection/index.js';
|
|
3
4
|
export interface AutoIndexConfig {
|
|
4
5
|
autoIndex?: `off` | `eager`;
|
|
5
6
|
}
|
|
6
|
-
export declare function ensureIndexForField<T extends Record<string, any>, TKey extends string | number>(fieldName: string, fieldPath: Array<string>, collection: CollectionImpl<T, TKey, any, any, any>, compareFn?: (a: any, b: any) => number): void;
|
|
7
|
+
export declare function ensureIndexForField<T extends Record<string, any>, TKey extends string | number>(fieldName: string, fieldPath: Array<string>, collection: CollectionImpl<T, TKey, any, any, any>, compareOptions?: CompareOptions, compareFn?: (a: any, b: any) => number): void;
|
|
7
8
|
/**
|
|
8
9
|
* Analyzes a where expression and creates indexes for all simple operations on single fields
|
|
9
10
|
*/
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const evaluators = require("../query/compiler/evaluators.cjs");
|
|
4
4
|
const functions = require("../query/builder/functions.cjs");
|
|
5
|
+
const utils = require("../utils.cjs");
|
|
5
6
|
const IndexOperation = functions.comparisonFunctions;
|
|
6
7
|
class BaseIndex {
|
|
7
8
|
constructor(id, expression, name, options) {
|
|
@@ -10,6 +11,7 @@ class BaseIndex {
|
|
|
10
11
|
this.lastUpdated = /* @__PURE__ */ new Date();
|
|
11
12
|
this.id = id;
|
|
12
13
|
this.expression = expression;
|
|
14
|
+
this.compareOptions = utils.DEFAULT_COMPARE_OPTIONS;
|
|
13
15
|
this.name = name;
|
|
14
16
|
this.initialize(options);
|
|
15
17
|
}
|
|
@@ -20,6 +22,30 @@ class BaseIndex {
|
|
|
20
22
|
matchesField(fieldPath) {
|
|
21
23
|
return this.expression.type === `ref` && this.expression.path.length === fieldPath.length && this.expression.path.every((part, i) => part === fieldPath[i]);
|
|
22
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks if the compare options match the index's compare options.
|
|
27
|
+
* The direction is ignored because the index can be reversed if the direction is different.
|
|
28
|
+
*/
|
|
29
|
+
matchesCompareOptions(compareOptions) {
|
|
30
|
+
const thisCompareOptionsWithoutDirection = {
|
|
31
|
+
...this.compareOptions,
|
|
32
|
+
direction: void 0
|
|
33
|
+
};
|
|
34
|
+
const compareOptionsWithoutDirection = {
|
|
35
|
+
...compareOptions,
|
|
36
|
+
direction: void 0
|
|
37
|
+
};
|
|
38
|
+
return utils.deepEquals(
|
|
39
|
+
thisCompareOptionsWithoutDirection,
|
|
40
|
+
compareOptionsWithoutDirection
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Checks if the index matches the provided direction.
|
|
45
|
+
*/
|
|
46
|
+
matchesDirection(direction) {
|
|
47
|
+
return this.compareOptions.direction === direction;
|
|
48
|
+
}
|
|
23
49
|
getStats() {
|
|
24
50
|
return {
|
|
25
51
|
entryCount: this.keyCount,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-index.cjs","sources":["../../../src/indexes/base-index.ts"],"sourcesContent":["import { compileSingleRowExpression } from \"../query/compiler/evaluators.js\"\nimport { comparisonFunctions } from \"../query/builder/functions.js\"\nimport type { BasicExpression } from \"../query/ir.js\"\n\n/**\n * Operations that indexes can support, imported from available comparison functions\n */\nexport const IndexOperation = comparisonFunctions\n\n/**\n * Type for index operation values\n */\nexport type IndexOperation = (typeof comparisonFunctions)[number]\n\n/**\n * Statistics about index usage and performance\n */\nexport interface IndexStats {\n readonly entryCount: number\n readonly lookupCount: number\n readonly averageLookupTime: number\n readonly lastUpdated: Date\n}\n\n/**\n * Base abstract class that all index types extend\n */\nexport abstract class BaseIndex
|
|
1
|
+
{"version":3,"file":"base-index.cjs","sources":["../../../src/indexes/base-index.ts"],"sourcesContent":["import { compileSingleRowExpression } from \"../query/compiler/evaluators.js\"\nimport { comparisonFunctions } from \"../query/builder/functions.js\"\nimport { DEFAULT_COMPARE_OPTIONS, deepEquals } from \"../utils.js\"\nimport type { RangeQueryOptions } from \"./btree-index.js\"\nimport type { CompareOptions } from \"../query/builder/types.js\"\nimport type { BasicExpression, OrderByDirection } from \"../query/ir.js\"\n\n/**\n * Operations that indexes can support, imported from available comparison functions\n */\nexport const IndexOperation = comparisonFunctions\n\n/**\n * Type for index operation values\n */\nexport type IndexOperation = (typeof comparisonFunctions)[number]\n\n/**\n * Statistics about index usage and performance\n */\nexport interface IndexStats {\n readonly entryCount: number\n readonly lookupCount: number\n readonly averageLookupTime: number\n readonly lastUpdated: Date\n}\n\nexport interface IndexInterface<\n TKey extends string | number = string | number,\n> {\n add: (key: TKey, item: any) => void\n remove: (key: TKey, item: any) => void\n update: (key: TKey, oldItem: any, newItem: any) => void\n\n build: (entries: Iterable<[TKey, any]>) => void\n clear: () => void\n\n lookup: (operation: IndexOperation, value: any) => Set<TKey>\n\n equalityLookup: (value: any) => Set<TKey>\n inArrayLookup: (values: Array<any>) => Set<TKey>\n\n rangeQuery: (options: RangeQueryOptions) => Set<TKey>\n rangeQueryReversed: (options: RangeQueryOptions) => Set<TKey>\n\n take: (\n n: number,\n from?: TKey,\n filterFn?: (key: TKey) => boolean\n ) => Array<TKey>\n takeReversed: (\n n: number,\n from?: TKey,\n filterFn?: (key: TKey) => boolean\n ) => Array<TKey>\n\n get keyCount(): number\n get orderedEntriesArray(): Array<[any, Set<TKey>]>\n get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>\n\n get indexedKeysSet(): Set<TKey>\n get valueMapData(): Map<any, Set<TKey>>\n\n supports: (operation: IndexOperation) => boolean\n\n matchesField: (fieldPath: Array<string>) => boolean\n matchesCompareOptions: (compareOptions: CompareOptions) => boolean\n matchesDirection: (direction: OrderByDirection) => boolean\n\n getStats: () => IndexStats\n}\n\n/**\n * Base abstract class that all index types extend\n */\nexport abstract class BaseIndex<TKey extends string | number = string | number>\n implements IndexInterface<TKey>\n{\n public readonly id: number\n public readonly name?: string\n public readonly expression: BasicExpression\n public abstract readonly supportedOperations: Set<IndexOperation>\n\n protected lookupCount = 0\n protected totalLookupTime = 0\n protected lastUpdated = new Date()\n protected compareOptions: CompareOptions\n\n constructor(\n id: number,\n expression: BasicExpression,\n name?: string,\n options?: any\n ) {\n this.id = id\n this.expression = expression\n this.compareOptions = DEFAULT_COMPARE_OPTIONS\n this.name = name\n this.initialize(options)\n }\n\n // Abstract methods that each index type must implement\n abstract add(key: TKey, item: any): void\n abstract remove(key: TKey, item: any): void\n abstract update(key: TKey, oldItem: any, newItem: any): void\n abstract build(entries: Iterable<[TKey, any]>): void\n abstract clear(): void\n abstract lookup(operation: IndexOperation, value: any): Set<TKey>\n abstract take(\n n: number,\n from?: TKey,\n filterFn?: (key: TKey) => boolean\n ): Array<TKey>\n abstract takeReversed(\n n: number,\n from?: TKey,\n filterFn?: (key: TKey) => boolean\n ): Array<TKey>\n abstract get keyCount(): number\n abstract equalityLookup(value: any): Set<TKey>\n abstract inArrayLookup(values: Array<any>): Set<TKey>\n abstract rangeQuery(options: RangeQueryOptions): Set<TKey>\n abstract rangeQueryReversed(options: RangeQueryOptions): Set<TKey>\n abstract get orderedEntriesArray(): Array<[any, Set<TKey>]>\n abstract get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>\n abstract get indexedKeysSet(): Set<TKey>\n abstract get valueMapData(): Map<any, Set<TKey>>\n\n // Common methods\n supports(operation: IndexOperation): boolean {\n return this.supportedOperations.has(operation)\n }\n\n matchesField(fieldPath: Array<string>): boolean {\n return (\n this.expression.type === `ref` &&\n this.expression.path.length === fieldPath.length &&\n this.expression.path.every((part, i) => part === fieldPath[i])\n )\n }\n\n /**\n * Checks if the compare options match the index's compare options.\n * The direction is ignored because the index can be reversed if the direction is different.\n */\n matchesCompareOptions(compareOptions: CompareOptions): boolean {\n const thisCompareOptionsWithoutDirection = {\n ...this.compareOptions,\n direction: undefined,\n }\n const compareOptionsWithoutDirection = {\n ...compareOptions,\n direction: undefined,\n }\n\n return deepEquals(\n thisCompareOptionsWithoutDirection,\n compareOptionsWithoutDirection\n )\n }\n\n /**\n * Checks if the index matches the provided direction.\n */\n matchesDirection(direction: OrderByDirection): boolean {\n return this.compareOptions.direction === direction\n }\n\n getStats(): IndexStats {\n return {\n entryCount: this.keyCount,\n lookupCount: this.lookupCount,\n averageLookupTime:\n this.lookupCount > 0 ? this.totalLookupTime / this.lookupCount : 0,\n lastUpdated: this.lastUpdated,\n }\n }\n\n // Protected methods for subclasses\n protected abstract initialize(options?: any): void\n\n protected evaluateIndexExpression(item: any): any {\n const evaluator = compileSingleRowExpression(this.expression)\n return evaluator(item as Record<string, unknown>)\n }\n\n protected trackLookup(startTime: number): void {\n const duration = performance.now() - startTime\n this.lookupCount++\n this.totalLookupTime += duration\n }\n\n protected updateTimestamp(): void {\n this.lastUpdated = new Date()\n }\n}\n\n/**\n * Type for index constructor\n */\nexport type IndexConstructor<TKey extends string | number = string | number> =\n new (\n id: number,\n expression: BasicExpression,\n name?: string,\n options?: any\n ) => BaseIndex<TKey>\n\n/**\n * Index resolver can be either a class constructor or async loader\n */\nexport type IndexResolver<TKey extends string | number = string | number> =\n | IndexConstructor<TKey>\n | (() => Promise<IndexConstructor<TKey>>)\n"],"names":["comparisonFunctions","DEFAULT_COMPARE_OPTIONS","deepEquals","compileSingleRowExpression"],"mappings":";;;;;AAUO,MAAM,iBAAiBA,UAAAA;AAiEvB,MAAe,UAEtB;AAAA,EAWE,YACE,IACA,YACA,MACA,SACA;AAVF,SAAU,cAAc;AACxB,SAAU,kBAAkB;AAC5B,SAAU,kCAAkB,KAAA;AAS1B,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,iBAAiBC,MAAAA;AACtB,SAAK,OAAO;AACZ,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA;AAAA,EA8BA,SAAS,WAAoC;AAC3C,WAAO,KAAK,oBAAoB,IAAI,SAAS;AAAA,EAC/C;AAAA,EAEA,aAAa,WAAmC;AAC9C,WACE,KAAK,WAAW,SAAS,SACzB,KAAK,WAAW,KAAK,WAAW,UAAU,UAC1C,KAAK,WAAW,KAAK,MAAM,CAAC,MAAM,MAAM,SAAS,UAAU,CAAC,CAAC;AAAA,EAEjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,gBAAyC;AAC7D,UAAM,qCAAqC;AAAA,MACzC,GAAG,KAAK;AAAA,MACR,WAAW;AAAA,IAAA;AAEb,UAAM,iCAAiC;AAAA,MACrC,GAAG;AAAA,MACH,WAAW;AAAA,IAAA;AAGb,WAAOC,MAAAA;AAAAA,MACL;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,WAAsC;AACrD,WAAO,KAAK,eAAe,cAAc;AAAA,EAC3C;AAAA,EAEA,WAAuB;AACrB,WAAO;AAAA,MACL,YAAY,KAAK;AAAA,MACjB,aAAa,KAAK;AAAA,MAClB,mBACE,KAAK,cAAc,IAAI,KAAK,kBAAkB,KAAK,cAAc;AAAA,MACnE,aAAa,KAAK;AAAA,IAAA;AAAA,EAEtB;AAAA,EAKU,wBAAwB,MAAgB;AAChD,UAAM,YAAYC,WAAAA,2BAA2B,KAAK,UAAU;AAC5D,WAAO,UAAU,IAA+B;AAAA,EAClD;AAAA,EAEU,YAAY,WAAyB;AAC7C,UAAM,WAAW,YAAY,IAAA,IAAQ;AACrC,SAAK;AACL,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEU,kBAAwB;AAChC,SAAK,kCAAkB,KAAA;AAAA,EACzB;AACF;;;"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { comparisonFunctions } from '../query/builder/functions.js';
|
|
2
|
-
import {
|
|
2
|
+
import { RangeQueryOptions } from './btree-index.js';
|
|
3
|
+
import { CompareOptions } from '../query/builder/types.js';
|
|
4
|
+
import { BasicExpression, OrderByDirection } from '../query/ir.js';
|
|
3
5
|
/**
|
|
4
6
|
* Operations that indexes can support, imported from available comparison functions
|
|
5
7
|
*/
|
|
@@ -17,10 +19,34 @@ export interface IndexStats {
|
|
|
17
19
|
readonly averageLookupTime: number;
|
|
18
20
|
readonly lastUpdated: Date;
|
|
19
21
|
}
|
|
22
|
+
export interface IndexInterface<TKey extends string | number = string | number> {
|
|
23
|
+
add: (key: TKey, item: any) => void;
|
|
24
|
+
remove: (key: TKey, item: any) => void;
|
|
25
|
+
update: (key: TKey, oldItem: any, newItem: any) => void;
|
|
26
|
+
build: (entries: Iterable<[TKey, any]>) => void;
|
|
27
|
+
clear: () => void;
|
|
28
|
+
lookup: (operation: IndexOperation, value: any) => Set<TKey>;
|
|
29
|
+
equalityLookup: (value: any) => Set<TKey>;
|
|
30
|
+
inArrayLookup: (values: Array<any>) => Set<TKey>;
|
|
31
|
+
rangeQuery: (options: RangeQueryOptions) => Set<TKey>;
|
|
32
|
+
rangeQueryReversed: (options: RangeQueryOptions) => Set<TKey>;
|
|
33
|
+
take: (n: number, from?: TKey, filterFn?: (key: TKey) => boolean) => Array<TKey>;
|
|
34
|
+
takeReversed: (n: number, from?: TKey, filterFn?: (key: TKey) => boolean) => Array<TKey>;
|
|
35
|
+
get keyCount(): number;
|
|
36
|
+
get orderedEntriesArray(): Array<[any, Set<TKey>]>;
|
|
37
|
+
get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>;
|
|
38
|
+
get indexedKeysSet(): Set<TKey>;
|
|
39
|
+
get valueMapData(): Map<any, Set<TKey>>;
|
|
40
|
+
supports: (operation: IndexOperation) => boolean;
|
|
41
|
+
matchesField: (fieldPath: Array<string>) => boolean;
|
|
42
|
+
matchesCompareOptions: (compareOptions: CompareOptions) => boolean;
|
|
43
|
+
matchesDirection: (direction: OrderByDirection) => boolean;
|
|
44
|
+
getStats: () => IndexStats;
|
|
45
|
+
}
|
|
20
46
|
/**
|
|
21
47
|
* Base abstract class that all index types extend
|
|
22
48
|
*/
|
|
23
|
-
export declare abstract class BaseIndex<TKey extends string | number = string | number> {
|
|
49
|
+
export declare abstract class BaseIndex<TKey extends string | number = string | number> implements IndexInterface<TKey> {
|
|
24
50
|
readonly id: number;
|
|
25
51
|
readonly name?: string;
|
|
26
52
|
readonly expression: BasicExpression;
|
|
@@ -28,6 +54,7 @@ export declare abstract class BaseIndex<TKey extends string | number = string |
|
|
|
28
54
|
protected lookupCount: number;
|
|
29
55
|
protected totalLookupTime: number;
|
|
30
56
|
protected lastUpdated: Date;
|
|
57
|
+
protected compareOptions: CompareOptions;
|
|
31
58
|
constructor(id: number, expression: BasicExpression, name?: string, options?: any);
|
|
32
59
|
abstract add(key: TKey, item: any): void;
|
|
33
60
|
abstract remove(key: TKey, item: any): void;
|
|
@@ -36,9 +63,27 @@ export declare abstract class BaseIndex<TKey extends string | number = string |
|
|
|
36
63
|
abstract clear(): void;
|
|
37
64
|
abstract lookup(operation: IndexOperation, value: any): Set<TKey>;
|
|
38
65
|
abstract take(n: number, from?: TKey, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
66
|
+
abstract takeReversed(n: number, from?: TKey, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
39
67
|
abstract get keyCount(): number;
|
|
68
|
+
abstract equalityLookup(value: any): Set<TKey>;
|
|
69
|
+
abstract inArrayLookup(values: Array<any>): Set<TKey>;
|
|
70
|
+
abstract rangeQuery(options: RangeQueryOptions): Set<TKey>;
|
|
71
|
+
abstract rangeQueryReversed(options: RangeQueryOptions): Set<TKey>;
|
|
72
|
+
abstract get orderedEntriesArray(): Array<[any, Set<TKey>]>;
|
|
73
|
+
abstract get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>;
|
|
74
|
+
abstract get indexedKeysSet(): Set<TKey>;
|
|
75
|
+
abstract get valueMapData(): Map<any, Set<TKey>>;
|
|
40
76
|
supports(operation: IndexOperation): boolean;
|
|
41
77
|
matchesField(fieldPath: Array<string>): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Checks if the compare options match the index's compare options.
|
|
80
|
+
* The direction is ignored because the index can be reversed if the direction is different.
|
|
81
|
+
*/
|
|
82
|
+
matchesCompareOptions(compareOptions: CompareOptions): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Checks if the index matches the provided direction.
|
|
85
|
+
*/
|
|
86
|
+
matchesDirection(direction: OrderByDirection): boolean;
|
|
42
87
|
getStats(): IndexStats;
|
|
43
88
|
protected abstract initialize(options?: any): void;
|
|
44
89
|
protected evaluateIndexExpression(item: any): any;
|
|
@@ -17,7 +17,10 @@ class BTreeIndex extends baseIndex.BaseIndex {
|
|
|
17
17
|
this.valueMap = /* @__PURE__ */ new Map();
|
|
18
18
|
this.indexedKeys = /* @__PURE__ */ new Set();
|
|
19
19
|
this.compareFn = comparison.defaultComparator;
|
|
20
|
-
this.compareFn =
|
|
20
|
+
this.compareFn = options?.compareFn ?? comparison.defaultComparator;
|
|
21
|
+
if (options?.compareOptions) {
|
|
22
|
+
this.compareOptions = options.compareOptions;
|
|
23
|
+
}
|
|
21
24
|
this.orderedEntries = new btree.BTree(this.compareFn);
|
|
22
25
|
}
|
|
23
26
|
initialize(_options) {
|
|
@@ -169,23 +172,30 @@ class BTreeIndex extends baseIndex.BaseIndex {
|
|
|
169
172
|
return result;
|
|
170
173
|
}
|
|
171
174
|
/**
|
|
172
|
-
*
|
|
173
|
-
* @param n - The number of items to return
|
|
174
|
-
* @param from - The item to start from (exclusive). Starts from the smallest item (inclusive) if not provided.
|
|
175
|
-
* @returns The next n items after the provided key. Returns the first n items if no from item is provided.
|
|
175
|
+
* Performs a reversed range query
|
|
176
176
|
*/
|
|
177
|
-
|
|
177
|
+
rangeQueryReversed(options = {}) {
|
|
178
|
+
const { from, to, fromInclusive = true, toInclusive = true } = options;
|
|
179
|
+
return this.rangeQuery({
|
|
180
|
+
from: to ?? this.orderedEntries.maxKey(),
|
|
181
|
+
to: from ?? this.orderedEntries.minKey(),
|
|
182
|
+
fromInclusive: toInclusive,
|
|
183
|
+
toInclusive: fromInclusive
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
takeInternal(n, nextPair, from, filterFn) {
|
|
178
187
|
const keysInResult = /* @__PURE__ */ new Set();
|
|
179
188
|
const result = [];
|
|
180
|
-
|
|
189
|
+
let pair;
|
|
181
190
|
let key = comparison.normalizeValue(from);
|
|
182
|
-
while ((
|
|
191
|
+
while ((pair = nextPair(key)) !== void 0 && result.length < n) {
|
|
192
|
+
key = pair[0];
|
|
183
193
|
const keys = this.valueMap.get(key);
|
|
184
194
|
if (keys) {
|
|
185
195
|
const it = keys.values();
|
|
186
196
|
let ks;
|
|
187
197
|
while (result.length < n && (ks = it.next().value)) {
|
|
188
|
-
if (!keysInResult.has(ks) && (
|
|
198
|
+
if (!keysInResult.has(ks) && (filterFn?.(ks) ?? true)) {
|
|
189
199
|
result.push(ks);
|
|
190
200
|
keysInResult.add(ks);
|
|
191
201
|
}
|
|
@@ -194,6 +204,26 @@ class BTreeIndex extends baseIndex.BaseIndex {
|
|
|
194
204
|
}
|
|
195
205
|
return result;
|
|
196
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Returns the next n items after the provided item or the first n items if no from item is provided.
|
|
209
|
+
* @param n - The number of items to return
|
|
210
|
+
* @param from - The item to start from (exclusive). Starts from the smallest item (inclusive) if not provided.
|
|
211
|
+
* @returns The next n items after the provided key. Returns the first n items if no from item is provided.
|
|
212
|
+
*/
|
|
213
|
+
take(n, from, filterFn) {
|
|
214
|
+
const nextPair = (k) => this.orderedEntries.nextHigherPair(k);
|
|
215
|
+
return this.takeInternal(n, nextPair, from, filterFn);
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Returns the next n items **before** the provided item (in descending order) or the last n items if no from item is provided.
|
|
219
|
+
* @param n - The number of items to return
|
|
220
|
+
* @param from - The item to start from (exclusive). Starts from the largest item (inclusive) if not provided.
|
|
221
|
+
* @returns The next n items **before** the provided key. Returns the last n items if no from item is provided.
|
|
222
|
+
*/
|
|
223
|
+
takeReversed(n, from, filterFn) {
|
|
224
|
+
const nextPair = (k) => this.orderedEntries.nextLowerPair(k);
|
|
225
|
+
return this.takeInternal(n, nextPair, from, filterFn);
|
|
226
|
+
}
|
|
197
227
|
/**
|
|
198
228
|
* Performs an IN array lookup
|
|
199
229
|
*/
|
|
@@ -215,6 +245,12 @@ class BTreeIndex extends baseIndex.BaseIndex {
|
|
|
215
245
|
get orderedEntriesArray() {
|
|
216
246
|
return this.orderedEntries.keysArray().map((key) => [key, this.valueMap.get(key) ?? /* @__PURE__ */ new Set()]);
|
|
217
247
|
}
|
|
248
|
+
get orderedEntriesArrayReversed() {
|
|
249
|
+
return this.takeReversed(this.orderedEntries.size).map((key) => [
|
|
250
|
+
key,
|
|
251
|
+
this.valueMap.get(key) ?? /* @__PURE__ */ new Set()
|
|
252
|
+
]);
|
|
253
|
+
}
|
|
218
254
|
get valueMapData() {
|
|
219
255
|
return this.valueMap;
|
|
220
256
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"btree-index.cjs","sources":["../../../src/indexes/btree-index.ts"],"sourcesContent":["import { BTree } from \"../utils/btree.js\"\nimport { defaultComparator, normalizeValue } from \"../utils/comparison.js\"\nimport { BaseIndex } from \"./base-index.js\"\nimport type { BasicExpression } from \"../query/ir.js\"\nimport type { IndexOperation } from \"./base-index.js\"\n\n/**\n * Options for Ordered index\n */\nexport interface BTreeIndexOptions {\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 * B+Tree index for sorted data with range queries\n * This maintains items in sorted order and provides efficient range operations\n */\nexport class BTreeIndex<\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 // The `orderedEntries` B+ tree is used for efficient range queries\n // The `valueMap` is used for O(1) lookups of PKs by indexed value\n private orderedEntries: BTree<any, undefined> // we don't associate values with the keys of the B+ tree (the keys are indexed values)\n private valueMap = new Map<any, Set<TKey>>() // instead we store a mapping of indexed values to a set of PKs\n private indexedKeys = new Set<TKey>()\n private compareFn: (a: any, b: any) => number = defaultComparator\n\n constructor(\n id: number,\n expression: BasicExpression,\n name?: string,\n options?: any\n ) {\n super(id, expression, name, options)\n this.compareFn = options?.compareFn ?? defaultComparator\n this.orderedEntries = new BTree(this.compareFn)\n }\n\n protected initialize(_options?: BTreeIndexOptions): void {}\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 // Normalize the value for Map key usage\n const normalizedValue = normalizeValue(indexedValue)\n\n // Check if this value already exists\n if (this.valueMap.has(normalizedValue)) {\n // Add to existing set\n this.valueMap.get(normalizedValue)!.add(key)\n } else {\n // Create new set for this value\n const keySet = new Set<TKey>([key])\n this.valueMap.set(normalizedValue, keySet)\n this.orderedEntries.set(normalizedValue, undefined)\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 // Normalize the value for Map key usage\n const normalizedValue = normalizeValue(indexedValue)\n\n if (this.valueMap.has(normalizedValue)) {\n const keySet = this.valueMap.get(normalizedValue)!\n keySet.delete(key)\n\n // If set is now empty, remove the entry entirely\n if (keySet.size === 0) {\n this.valueMap.delete(normalizedValue)\n\n // Remove from ordered entries\n this.orderedEntries.delete(normalizedValue)\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.clear()\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 BTreeIndex`)\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 const normalizedValue = normalizeValue(value)\n return new Set(this.valueMap.get(normalizedValue) ?? [])\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 const normalizedFrom = normalizeValue(from)\n const normalizedTo = normalizeValue(to)\n const fromKey = normalizedFrom ?? this.orderedEntries.minKey()\n const toKey = normalizedTo ?? this.orderedEntries.maxKey()\n\n this.orderedEntries.forRange(\n fromKey,\n toKey,\n toInclusive,\n (indexedValue, _) => {\n if (!fromInclusive && this.compareFn(indexedValue, from) === 0) {\n // the B+ tree `forRange` method does not support exclusive lower bounds\n // so we need to exclude it manually\n return\n }\n\n const keys = this.valueMap.get(indexedValue)\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n )\n\n return result\n }\n\n /**\n * Returns the next n items after the provided item or the first n items if no from item is provided.\n * @param n - The number of items to return\n * @param from - The item to start from (exclusive). Starts from the smallest item (inclusive) if not provided.\n * @returns The next n items after the provided key. Returns the first n items if no from item is provided.\n */\n take(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey> {\n const keysInResult: Set<TKey> = new Set()\n const result: Array<TKey> = []\n const nextKey = (k?: any) => this.orderedEntries.nextHigherKey(k)\n let key = normalizeValue(from)\n\n while ((key = nextKey(key)) && result.length < n) {\n const keys = this.valueMap.get(key)\n if (keys) {\n const it = keys.values()\n let ks: TKey | undefined\n while (result.length < n && (ks = it.next().value)) {\n if (!keysInResult.has(ks) && (filterFn?.(ks) ?? true)) {\n result.push(ks)\n keysInResult.add(ks)\n }\n }\n }\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 normalizedValue = normalizeValue(value)\n const keys = this.valueMap.get(normalizedValue)\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 .keysArray()\n .map((key) => [key, this.valueMap.get(key) ?? new Set()])\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n return this.valueMap\n }\n}\n"],"names":["BaseIndex","defaultComparator","BTree","normalizeValue"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"btree-index.cjs","sources":["../../../src/indexes/btree-index.ts"],"sourcesContent":["import { BTree } from \"../utils/btree.js\"\nimport { defaultComparator, normalizeValue } from \"../utils/comparison.js\"\nimport { BaseIndex } from \"./base-index.js\"\nimport type { CompareOptions } from \"../query/builder/types.js\"\nimport type { BasicExpression } from \"../query/ir.js\"\nimport type { IndexOperation } from \"./base-index.js\"\n\n/**\n * Options for Ordered index\n */\nexport interface BTreeIndexOptions {\n compareFn?: (a: any, b: any) => number\n compareOptions?: CompareOptions\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 * B+Tree index for sorted data with range queries\n * This maintains items in sorted order and provides efficient range operations\n */\nexport class BTreeIndex<\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 // The `orderedEntries` B+ tree is used for efficient range queries\n // The `valueMap` is used for O(1) lookups of PKs by indexed value\n private orderedEntries: BTree<any, undefined> // we don't associate values with the keys of the B+ tree (the keys are indexed values)\n private valueMap = new Map<any, Set<TKey>>() // instead we store a mapping of indexed values to a set of PKs\n private indexedKeys = new Set<TKey>()\n private compareFn: (a: any, b: any) => number = defaultComparator\n\n constructor(\n id: number,\n expression: BasicExpression,\n name?: string,\n options?: any\n ) {\n super(id, expression, name, options)\n this.compareFn = options?.compareFn ?? defaultComparator\n if (options?.compareOptions) {\n this.compareOptions = options!.compareOptions\n }\n this.orderedEntries = new BTree(this.compareFn)\n }\n\n protected initialize(_options?: BTreeIndexOptions): void {}\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 // Normalize the value for Map key usage\n const normalizedValue = normalizeValue(indexedValue)\n\n // Check if this value already exists\n if (this.valueMap.has(normalizedValue)) {\n // Add to existing set\n this.valueMap.get(normalizedValue)!.add(key)\n } else {\n // Create new set for this value\n const keySet = new Set<TKey>([key])\n this.valueMap.set(normalizedValue, keySet)\n this.orderedEntries.set(normalizedValue, undefined)\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 // Normalize the value for Map key usage\n const normalizedValue = normalizeValue(indexedValue)\n\n if (this.valueMap.has(normalizedValue)) {\n const keySet = this.valueMap.get(normalizedValue)!\n keySet.delete(key)\n\n // If set is now empty, remove the entry entirely\n if (keySet.size === 0) {\n this.valueMap.delete(normalizedValue)\n\n // Remove from ordered entries\n this.orderedEntries.delete(normalizedValue)\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.clear()\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 BTreeIndex`)\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 const normalizedValue = normalizeValue(value)\n return new Set(this.valueMap.get(normalizedValue) ?? [])\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 const normalizedFrom = normalizeValue(from)\n const normalizedTo = normalizeValue(to)\n const fromKey = normalizedFrom ?? this.orderedEntries.minKey()\n const toKey = normalizedTo ?? this.orderedEntries.maxKey()\n\n this.orderedEntries.forRange(\n fromKey,\n toKey,\n toInclusive,\n (indexedValue, _) => {\n if (!fromInclusive && this.compareFn(indexedValue, from) === 0) {\n // the B+ tree `forRange` method does not support exclusive lower bounds\n // so we need to exclude it manually\n return\n }\n\n const keys = this.valueMap.get(indexedValue)\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n )\n\n return result\n }\n\n /**\n * Performs a reversed range query\n */\n rangeQueryReversed(options: RangeQueryOptions = {}): Set<TKey> {\n const { from, to, fromInclusive = true, toInclusive = true } = options\n return this.rangeQuery({\n from: to ?? this.orderedEntries.maxKey(),\n to: from ?? this.orderedEntries.minKey(),\n fromInclusive: toInclusive,\n toInclusive: fromInclusive,\n })\n }\n\n private takeInternal(\n n: number,\n nextPair: (k?: any) => [any, any] | undefined,\n from?: any,\n filterFn?: (key: TKey) => boolean\n ): Array<TKey> {\n const keysInResult: Set<TKey> = new Set()\n const result: Array<TKey> = []\n let pair: [any, any] | undefined\n let key = normalizeValue(from)\n\n while ((pair = nextPair(key)) !== undefined && result.length < n) {\n key = pair[0]\n const keys = this.valueMap.get(key)\n if (keys) {\n const it = keys.values()\n let ks: TKey | undefined\n while (result.length < n && (ks = it.next().value)) {\n if (!keysInResult.has(ks) && (filterFn?.(ks) ?? true)) {\n result.push(ks)\n keysInResult.add(ks)\n }\n }\n }\n }\n\n return result\n }\n\n /**\n * Returns the next n items after the provided item or the first n items if no from item is provided.\n * @param n - The number of items to return\n * @param from - The item to start from (exclusive). Starts from the smallest item (inclusive) if not provided.\n * @returns The next n items after the provided key. Returns the first n items if no from item is provided.\n */\n take(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey> {\n const nextPair = (k?: any) => this.orderedEntries.nextHigherPair(k)\n return this.takeInternal(n, nextPair, from, filterFn)\n }\n\n /**\n * Returns the next n items **before** the provided item (in descending order) or the last n items if no from item is provided.\n * @param n - The number of items to return\n * @param from - The item to start from (exclusive). Starts from the largest item (inclusive) if not provided.\n * @returns The next n items **before** the provided key. Returns the last n items if no from item is provided.\n */\n takeReversed(\n n: number,\n from?: any,\n filterFn?: (key: TKey) => boolean\n ): Array<TKey> {\n const nextPair = (k?: any) => this.orderedEntries.nextLowerPair(k)\n return this.takeInternal(n, nextPair, from, filterFn)\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 normalizedValue = normalizeValue(value)\n const keys = this.valueMap.get(normalizedValue)\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 .keysArray()\n .map((key) => [key, this.valueMap.get(key) ?? new Set()])\n }\n\n get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]> {\n return this.takeReversed(this.orderedEntries.size).map((key) => [\n key,\n this.valueMap.get(key) ?? new Set(),\n ])\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n return this.valueMap\n }\n}\n"],"names":["BaseIndex","defaultComparator","BTree","normalizeValue"],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { BaseIndex, IndexOperation } from './base-index.js';
|
|
2
|
+
import { CompareOptions } from '../query/builder/types.js';
|
|
2
3
|
import { BasicExpression } from '../query/ir.js';
|
|
3
4
|
/**
|
|
4
5
|
* Options for Ordered index
|
|
5
6
|
*/
|
|
6
7
|
export interface BTreeIndexOptions {
|
|
7
8
|
compareFn?: (a: any, b: any) => number;
|
|
9
|
+
compareOptions?: CompareOptions;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
10
12
|
* Options for range queries
|
|
@@ -64,6 +66,11 @@ export declare class BTreeIndex<TKey extends string | number = string | number>
|
|
|
64
66
|
* This is more efficient for compound queries like "WHERE a > 5 AND a < 10"
|
|
65
67
|
*/
|
|
66
68
|
rangeQuery(options?: RangeQueryOptions): Set<TKey>;
|
|
69
|
+
/**
|
|
70
|
+
* Performs a reversed range query
|
|
71
|
+
*/
|
|
72
|
+
rangeQueryReversed(options?: RangeQueryOptions): Set<TKey>;
|
|
73
|
+
private takeInternal;
|
|
67
74
|
/**
|
|
68
75
|
* Returns the next n items after the provided item or the first n items if no from item is provided.
|
|
69
76
|
* @param n - The number of items to return
|
|
@@ -71,11 +78,19 @@ export declare class BTreeIndex<TKey extends string | number = string | number>
|
|
|
71
78
|
* @returns The next n items after the provided key. Returns the first n items if no from item is provided.
|
|
72
79
|
*/
|
|
73
80
|
take(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
81
|
+
/**
|
|
82
|
+
* Returns the next n items **before** the provided item (in descending order) or the last n items if no from item is provided.
|
|
83
|
+
* @param n - The number of items to return
|
|
84
|
+
* @param from - The item to start from (exclusive). Starts from the largest item (inclusive) if not provided.
|
|
85
|
+
* @returns The next n items **before** the provided key. Returns the last n items if no from item is provided.
|
|
86
|
+
*/
|
|
87
|
+
takeReversed(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
74
88
|
/**
|
|
75
89
|
* Performs an IN array lookup
|
|
76
90
|
*/
|
|
77
91
|
inArrayLookup(values: Array<any>): Set<TKey>;
|
|
78
92
|
get indexedKeysSet(): Set<TKey>;
|
|
79
93
|
get orderedEntriesArray(): Array<[any, Set<TKey>]>;
|
|
94
|
+
get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>;
|
|
80
95
|
get valueMapData(): Map<any, Set<TKey>>;
|
|
81
96
|
}
|
|
@@ -169,19 +169,16 @@ class IndexProxy {
|
|
|
169
169
|
}
|
|
170
170
|
// BTreeIndex compatibility methods
|
|
171
171
|
equalityLookup(value) {
|
|
172
|
-
var _a;
|
|
173
172
|
const resolved = this.index;
|
|
174
|
-
return
|
|
173
|
+
return resolved.equalityLookup?.(value) ?? /* @__PURE__ */ new Set();
|
|
175
174
|
}
|
|
176
175
|
rangeQuery(options) {
|
|
177
|
-
var _a;
|
|
178
176
|
const resolved = this.index;
|
|
179
|
-
return
|
|
177
|
+
return resolved.rangeQuery?.(options) ?? /* @__PURE__ */ new Set();
|
|
180
178
|
}
|
|
181
179
|
inArrayLookup(values) {
|
|
182
|
-
var _a;
|
|
183
180
|
const resolved = this.index;
|
|
184
|
-
return
|
|
181
|
+
return resolved.inArrayLookup?.(values) ?? /* @__PURE__ */ new Set();
|
|
185
182
|
}
|
|
186
183
|
// Internal method for the collection to get the lazy wrapper
|
|
187
184
|
_getLazyWrapper() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy-index.cjs","sources":["../../../src/indexes/lazy-index.ts"],"sourcesContent":["import type {\n BaseIndex,\n IndexConstructor,\n IndexResolver,\n} from \"./base-index.js\"\nimport type { BasicExpression } from \"../query/ir.js\"\n\n/**\n * Utility to determine if a resolver is a constructor or async loader\n */\nfunction isConstructor<TKey extends string | number>(\n resolver: IndexResolver<TKey>\n): resolver is IndexConstructor<TKey> {\n // Check if it's a function with a prototype (constructor)\n return (\n typeof resolver === `function` &&\n resolver.prototype !== undefined &&\n resolver.prototype.constructor === resolver\n )\n}\n\n/**\n * Resolve index constructor from resolver\n */\nasync function resolveIndexConstructor<TKey extends string | number>(\n resolver: IndexResolver<TKey>\n): Promise<IndexConstructor<TKey>> {\n if (isConstructor(resolver)) {\n return resolver\n } else {\n // It's an async loader function\n return await resolver()\n }\n}\n\n/**\n * Wrapper that defers index creation until first sync\n */\nexport class LazyIndexWrapper<TKey extends string | number = string | number> {\n private indexPromise: Promise<BaseIndex<TKey>> | null = null\n private resolvedIndex: BaseIndex<TKey> | null = null\n\n constructor(\n private id: number,\n private expression: BasicExpression,\n private name: string | undefined,\n private resolver: IndexResolver<TKey>,\n private options: any,\n private collectionEntries?: Iterable<[TKey, any]>\n ) {\n // For synchronous constructors, resolve immediately\n if (isConstructor(this.resolver)) {\n this.resolvedIndex = new this.resolver(\n this.id,\n this.expression,\n this.name,\n this.options\n )\n // Build with initial data if provided\n if (this.collectionEntries) {\n this.resolvedIndex.build(this.collectionEntries)\n }\n }\n }\n\n /**\n * Resolve the actual index\n */\n async resolve(): Promise<BaseIndex<TKey>> {\n if (this.resolvedIndex) {\n return this.resolvedIndex\n }\n\n if (!this.indexPromise) {\n this.indexPromise = this.createIndex()\n }\n\n this.resolvedIndex = await this.indexPromise\n return this.resolvedIndex\n }\n\n /**\n * Check if already resolved\n */\n isResolved(): boolean {\n return this.resolvedIndex !== null\n }\n\n /**\n * Get resolved index (throws if not ready)\n */\n getResolved(): BaseIndex<TKey> {\n if (!this.resolvedIndex) {\n throw new Error(\n `Index ${this.id} has not been resolved yet. Ensure collection is synced.`\n )\n }\n return this.resolvedIndex\n }\n\n /**\n * Get the index ID\n */\n getId(): number {\n return this.id\n }\n\n /**\n * Get the index name\n */\n getName(): string | undefined {\n return this.name\n }\n\n /**\n * Get the index expression\n */\n getExpression(): BasicExpression {\n return this.expression\n }\n\n private async createIndex(): Promise<BaseIndex<TKey>> {\n const IndexClass = await resolveIndexConstructor(this.resolver)\n return new IndexClass(this.id, this.expression, this.name, this.options)\n }\n}\n\n/**\n * Proxy that provides synchronous interface while index loads asynchronously\n */\nexport class IndexProxy<TKey extends string | number = string | number> {\n constructor(\n private indexId: number,\n private lazyIndex: LazyIndexWrapper<TKey>\n ) {}\n\n /**\n * Get the resolved index (throws if not ready)\n */\n get index(): BaseIndex<TKey> {\n return this.lazyIndex.getResolved()\n }\n\n /**\n * Check if index is ready\n */\n get isReady(): boolean {\n return this.lazyIndex.isResolved()\n }\n\n /**\n * Wait for index to be ready\n */\n async whenReady(): Promise<BaseIndex<TKey>> {\n return await this.lazyIndex.resolve()\n }\n\n /**\n * Get the index ID\n */\n get id(): number {\n return this.indexId\n }\n\n /**\n * Get the index name (throws if not ready)\n */\n get name(): string | undefined {\n if (this.isReady) {\n return this.index.name\n }\n return this.lazyIndex.getName()\n }\n\n /**\n * Get the index expression (available immediately)\n */\n get expression(): BasicExpression {\n return this.lazyIndex.getExpression()\n }\n\n /**\n * Check if index supports an operation (throws if not ready)\n */\n supports(operation: any): boolean {\n return this.index.supports(operation)\n }\n\n /**\n * Get index statistics (throws if not ready)\n */\n getStats() {\n return this.index.getStats()\n }\n\n /**\n * Check if index matches a field path (available immediately)\n */\n matchesField(fieldPath: Array<string>): boolean {\n const expr = this.expression\n return (\n expr.type === `ref` &&\n expr.path.length === fieldPath.length &&\n expr.path.every((part, i) => part === fieldPath[i])\n )\n }\n\n /**\n * Get the key count (throws if not ready)\n */\n get keyCount(): number {\n return this.index.keyCount\n }\n\n // Test compatibility properties - delegate to resolved index\n get indexedKeysSet(): Set<TKey> {\n const resolved = this.index as any\n return resolved.indexedKeysSet\n }\n\n get orderedEntriesArray(): Array<[any, Set<TKey>]> {\n const resolved = this.index as any\n return resolved.orderedEntriesArray\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n const resolved = this.index as any\n return resolved.valueMapData\n }\n\n // BTreeIndex compatibility methods\n equalityLookup(value: any): Set<TKey> {\n const resolved = this.index as any\n return resolved.equalityLookup?.(value) ?? new Set()\n }\n\n rangeQuery(options: any): Set<TKey> {\n const resolved = this.index as any\n return resolved.rangeQuery?.(options) ?? new Set()\n }\n\n inArrayLookup(values: Array<any>): Set<TKey> {\n const resolved = this.index as any\n return resolved.inArrayLookup?.(values) ?? new Set()\n }\n\n // Internal method for the collection to get the lazy wrapper\n _getLazyWrapper(): LazyIndexWrapper<TKey> {\n return this.lazyIndex\n }\n}\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"lazy-index.cjs","sources":["../../../src/indexes/lazy-index.ts"],"sourcesContent":["import type {\n BaseIndex,\n IndexConstructor,\n IndexResolver,\n} from \"./base-index.js\"\nimport type { BasicExpression } from \"../query/ir.js\"\n\n/**\n * Utility to determine if a resolver is a constructor or async loader\n */\nfunction isConstructor<TKey extends string | number>(\n resolver: IndexResolver<TKey>\n): resolver is IndexConstructor<TKey> {\n // Check if it's a function with a prototype (constructor)\n return (\n typeof resolver === `function` &&\n resolver.prototype !== undefined &&\n resolver.prototype.constructor === resolver\n )\n}\n\n/**\n * Resolve index constructor from resolver\n */\nasync function resolveIndexConstructor<TKey extends string | number>(\n resolver: IndexResolver<TKey>\n): Promise<IndexConstructor<TKey>> {\n if (isConstructor(resolver)) {\n return resolver\n } else {\n // It's an async loader function\n return await resolver()\n }\n}\n\n/**\n * Wrapper that defers index creation until first sync\n */\nexport class LazyIndexWrapper<TKey extends string | number = string | number> {\n private indexPromise: Promise<BaseIndex<TKey>> | null = null\n private resolvedIndex: BaseIndex<TKey> | null = null\n\n constructor(\n private id: number,\n private expression: BasicExpression,\n private name: string | undefined,\n private resolver: IndexResolver<TKey>,\n private options: any,\n private collectionEntries?: Iterable<[TKey, any]>\n ) {\n // For synchronous constructors, resolve immediately\n if (isConstructor(this.resolver)) {\n this.resolvedIndex = new this.resolver(\n this.id,\n this.expression,\n this.name,\n this.options\n )\n // Build with initial data if provided\n if (this.collectionEntries) {\n this.resolvedIndex.build(this.collectionEntries)\n }\n }\n }\n\n /**\n * Resolve the actual index\n */\n async resolve(): Promise<BaseIndex<TKey>> {\n if (this.resolvedIndex) {\n return this.resolvedIndex\n }\n\n if (!this.indexPromise) {\n this.indexPromise = this.createIndex()\n }\n\n this.resolvedIndex = await this.indexPromise\n return this.resolvedIndex\n }\n\n /**\n * Check if already resolved\n */\n isResolved(): boolean {\n return this.resolvedIndex !== null\n }\n\n /**\n * Get resolved index (throws if not ready)\n */\n getResolved(): BaseIndex<TKey> {\n if (!this.resolvedIndex) {\n throw new Error(\n `Index ${this.id} has not been resolved yet. Ensure collection is synced.`\n )\n }\n return this.resolvedIndex\n }\n\n /**\n * Get the index ID\n */\n getId(): number {\n return this.id\n }\n\n /**\n * Get the index name\n */\n getName(): string | undefined {\n return this.name\n }\n\n /**\n * Get the index expression\n */\n getExpression(): BasicExpression {\n return this.expression\n }\n\n private async createIndex(): Promise<BaseIndex<TKey>> {\n const IndexClass = await resolveIndexConstructor(this.resolver)\n return new IndexClass(this.id, this.expression, this.name, this.options)\n }\n}\n\n/**\n * Proxy that provides synchronous interface while index loads asynchronously\n */\nexport class IndexProxy<TKey extends string | number = string | number> {\n constructor(\n private indexId: number,\n private lazyIndex: LazyIndexWrapper<TKey>\n ) {}\n\n /**\n * Get the resolved index (throws if not ready)\n */\n get index(): BaseIndex<TKey> {\n return this.lazyIndex.getResolved()\n }\n\n /**\n * Check if index is ready\n */\n get isReady(): boolean {\n return this.lazyIndex.isResolved()\n }\n\n /**\n * Wait for index to be ready\n */\n async whenReady(): Promise<BaseIndex<TKey>> {\n return await this.lazyIndex.resolve()\n }\n\n /**\n * Get the index ID\n */\n get id(): number {\n return this.indexId\n }\n\n /**\n * Get the index name (throws if not ready)\n */\n get name(): string | undefined {\n if (this.isReady) {\n return this.index.name\n }\n return this.lazyIndex.getName()\n }\n\n /**\n * Get the index expression (available immediately)\n */\n get expression(): BasicExpression {\n return this.lazyIndex.getExpression()\n }\n\n /**\n * Check if index supports an operation (throws if not ready)\n */\n supports(operation: any): boolean {\n return this.index.supports(operation)\n }\n\n /**\n * Get index statistics (throws if not ready)\n */\n getStats() {\n return this.index.getStats()\n }\n\n /**\n * Check if index matches a field path (available immediately)\n */\n matchesField(fieldPath: Array<string>): boolean {\n const expr = this.expression\n return (\n expr.type === `ref` &&\n expr.path.length === fieldPath.length &&\n expr.path.every((part, i) => part === fieldPath[i])\n )\n }\n\n /**\n * Get the key count (throws if not ready)\n */\n get keyCount(): number {\n return this.index.keyCount\n }\n\n // Test compatibility properties - delegate to resolved index\n get indexedKeysSet(): Set<TKey> {\n const resolved = this.index as any\n return resolved.indexedKeysSet\n }\n\n get orderedEntriesArray(): Array<[any, Set<TKey>]> {\n const resolved = this.index as any\n return resolved.orderedEntriesArray\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n const resolved = this.index as any\n return resolved.valueMapData\n }\n\n // BTreeIndex compatibility methods\n equalityLookup(value: any): Set<TKey> {\n const resolved = this.index as any\n return resolved.equalityLookup?.(value) ?? new Set()\n }\n\n rangeQuery(options: any): Set<TKey> {\n const resolved = this.index as any\n return resolved.rangeQuery?.(options) ?? new Set()\n }\n\n inArrayLookup(values: Array<any>): Set<TKey> {\n const resolved = this.index as any\n return resolved.inArrayLookup?.(values) ?? new Set()\n }\n\n // Internal method for the collection to get the lazy wrapper\n _getLazyWrapper(): LazyIndexWrapper<TKey> {\n return this.lazyIndex\n }\n}\n"],"names":[],"mappings":";;AAUA,SAAS,cACP,UACoC;AAEpC,SACE,OAAO,aAAa,cACpB,SAAS,cAAc,UACvB,SAAS,UAAU,gBAAgB;AAEvC;AAKA,eAAe,wBACb,UACiC;AACjC,MAAI,cAAc,QAAQ,GAAG;AAC3B,WAAO;AAAA,EACT,OAAO;AAEL,WAAO,MAAM,SAAA;AAAA,EACf;AACF;AAKO,MAAM,iBAAiE;AAAA,EAI5E,YACU,IACA,YACA,MACA,UACA,SACA,mBACR;AANQ,SAAA,KAAA;AACA,SAAA,aAAA;AACA,SAAA,OAAA;AACA,SAAA,WAAA;AACA,SAAA,UAAA;AACA,SAAA,oBAAA;AATV,SAAQ,eAAgD;AACxD,SAAQ,gBAAwC;AAW9C,QAAI,cAAc,KAAK,QAAQ,GAAG;AAChC,WAAK,gBAAgB,IAAI,KAAK;AAAA,QAC5B,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,MAAA;AAGP,UAAI,KAAK,mBAAmB;AAC1B,aAAK,cAAc,MAAM,KAAK,iBAAiB;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAoC;AACxC,QAAI,KAAK,eAAe;AACtB,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe,KAAK,YAAA;AAAA,IAC3B;AAEA,SAAK,gBAAgB,MAAM,KAAK;AAChC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,cAA+B;AAC7B,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,IAAI;AAAA,QACR,SAAS,KAAK,EAAE;AAAA,MAAA;AAAA,IAEpB;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,QAAgB;AACd,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAiC;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,cAAwC;AACpD,UAAM,aAAa,MAAM,wBAAwB,KAAK,QAAQ;AAC9D,WAAO,IAAI,WAAW,KAAK,IAAI,KAAK,YAAY,KAAK,MAAM,KAAK,OAAO;AAAA,EACzE;AACF;AAKO,MAAM,WAA2D;AAAA,EACtE,YACU,SACA,WACR;AAFQ,SAAA,UAAA;AACA,SAAA,YAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKH,IAAI,QAAyB;AAC3B,WAAO,KAAK,UAAU,YAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAmB;AACrB,WAAO,KAAK,UAAU,WAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAsC;AAC1C,WAAO,MAAM,KAAK,UAAU,QAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAa;AACf,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAA2B;AAC7B,QAAI,KAAK,SAAS;AAChB,aAAO,KAAK,MAAM;AAAA,IACpB;AACA,WAAO,KAAK,UAAU,QAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAA8B;AAChC,WAAO,KAAK,UAAU,cAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,WAAyB;AAChC,WAAO,KAAK,MAAM,SAAS,SAAS;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW;AACT,WAAO,KAAK,MAAM,SAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,WAAmC;AAC9C,UAAM,OAAO,KAAK;AAClB,WACE,KAAK,SAAS,SACd,KAAK,KAAK,WAAW,UAAU,UAC/B,KAAK,KAAK,MAAM,CAAC,MAAM,MAAM,SAAS,UAAU,CAAC,CAAC;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAmB;AACrB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA;AAAA,EAGA,IAAI,iBAA4B;AAC9B,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,IAAI,sBAA+C;AACjD,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS;AAAA,EAClB;AAAA,EAEA,IAAI,eAAoC;AACtC,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA,EAGA,eAAe,OAAuB;AACpC,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS,iBAAiB,KAAK,yBAAS,IAAA;AAAA,EACjD;AAAA,EAEA,WAAW,SAAyB;AAClC,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS,aAAa,OAAO,yBAAS,IAAA;AAAA,EAC/C;AAAA,EAEA,cAAc,QAA+B;AAC3C,UAAM,WAAW,KAAK;AACtB,WAAO,SAAS,gBAAgB,MAAM,yBAAS,IAAA;AAAA,EACjD;AAAA;AAAA,EAGA,kBAA0C;AACxC,WAAO,KAAK;AAAA,EACd;AACF;;;"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
class ReverseIndex {
|
|
4
|
+
constructor(index) {
|
|
5
|
+
this.originalIndex = index;
|
|
6
|
+
}
|
|
7
|
+
// Define the reversed operations
|
|
8
|
+
lookup(operation, value) {
|
|
9
|
+
const reverseOperation = operation === `gt` ? `lt` : operation === `gte` ? `lte` : operation === `lt` ? `gt` : operation === `lte` ? `gte` : operation;
|
|
10
|
+
return this.originalIndex.lookup(reverseOperation, value);
|
|
11
|
+
}
|
|
12
|
+
rangeQuery(options = {}) {
|
|
13
|
+
return this.originalIndex.rangeQueryReversed(options);
|
|
14
|
+
}
|
|
15
|
+
rangeQueryReversed(options = {}) {
|
|
16
|
+
return this.originalIndex.rangeQuery(options);
|
|
17
|
+
}
|
|
18
|
+
take(n, from, filterFn) {
|
|
19
|
+
return this.originalIndex.takeReversed(n, from, filterFn);
|
|
20
|
+
}
|
|
21
|
+
takeReversed(n, from, filterFn) {
|
|
22
|
+
return this.originalIndex.take(n, from, filterFn);
|
|
23
|
+
}
|
|
24
|
+
get orderedEntriesArray() {
|
|
25
|
+
return this.originalIndex.orderedEntriesArrayReversed;
|
|
26
|
+
}
|
|
27
|
+
get orderedEntriesArrayReversed() {
|
|
28
|
+
return this.originalIndex.orderedEntriesArray;
|
|
29
|
+
}
|
|
30
|
+
// All operations below delegate to the original index
|
|
31
|
+
supports(operation) {
|
|
32
|
+
return this.originalIndex.supports(operation);
|
|
33
|
+
}
|
|
34
|
+
matchesField(fieldPath) {
|
|
35
|
+
return this.originalIndex.matchesField(fieldPath);
|
|
36
|
+
}
|
|
37
|
+
matchesCompareOptions(compareOptions) {
|
|
38
|
+
return this.originalIndex.matchesCompareOptions(compareOptions);
|
|
39
|
+
}
|
|
40
|
+
matchesDirection(direction) {
|
|
41
|
+
return this.originalIndex.matchesDirection(direction);
|
|
42
|
+
}
|
|
43
|
+
getStats() {
|
|
44
|
+
return this.originalIndex.getStats();
|
|
45
|
+
}
|
|
46
|
+
add(key, item) {
|
|
47
|
+
this.originalIndex.add(key, item);
|
|
48
|
+
}
|
|
49
|
+
remove(key, item) {
|
|
50
|
+
this.originalIndex.remove(key, item);
|
|
51
|
+
}
|
|
52
|
+
update(key, oldItem, newItem) {
|
|
53
|
+
this.originalIndex.update(key, oldItem, newItem);
|
|
54
|
+
}
|
|
55
|
+
build(entries) {
|
|
56
|
+
this.originalIndex.build(entries);
|
|
57
|
+
}
|
|
58
|
+
clear() {
|
|
59
|
+
this.originalIndex.clear();
|
|
60
|
+
}
|
|
61
|
+
get keyCount() {
|
|
62
|
+
return this.originalIndex.keyCount;
|
|
63
|
+
}
|
|
64
|
+
equalityLookup(value) {
|
|
65
|
+
return this.originalIndex.equalityLookup(value);
|
|
66
|
+
}
|
|
67
|
+
inArrayLookup(values) {
|
|
68
|
+
return this.originalIndex.inArrayLookup(values);
|
|
69
|
+
}
|
|
70
|
+
get indexedKeysSet() {
|
|
71
|
+
return this.originalIndex.indexedKeysSet;
|
|
72
|
+
}
|
|
73
|
+
get valueMapData() {
|
|
74
|
+
return this.originalIndex.valueMapData;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.ReverseIndex = ReverseIndex;
|
|
78
|
+
//# sourceMappingURL=reverse-index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reverse-index.cjs","sources":["../../../src/indexes/reverse-index.ts"],"sourcesContent":["import type { CompareOptions } from \"../query/builder/types\"\nimport type { OrderByDirection } from \"../query/ir\"\nimport type { IndexInterface, IndexOperation, IndexStats } from \"./base-index\"\nimport type { RangeQueryOptions } from \"./btree-index\"\n\nexport class ReverseIndex<TKey extends string | number>\n implements IndexInterface<TKey>\n{\n private originalIndex: IndexInterface<TKey>\n\n constructor(index: IndexInterface<TKey>) {\n this.originalIndex = index\n }\n\n // Define the reversed operations\n\n lookup(operation: IndexOperation, value: any): Set<TKey> {\n const reverseOperation =\n operation === `gt`\n ? `lt`\n : operation === `gte`\n ? `lte`\n : operation === `lt`\n ? `gt`\n : operation === `lte`\n ? `gte`\n : operation\n return this.originalIndex.lookup(reverseOperation, value)\n }\n\n rangeQuery(options: RangeQueryOptions = {}): Set<TKey> {\n return this.originalIndex.rangeQueryReversed(options)\n }\n\n rangeQueryReversed(options: RangeQueryOptions = {}): Set<TKey> {\n return this.originalIndex.rangeQuery(options)\n }\n\n take(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey> {\n return this.originalIndex.takeReversed(n, from, filterFn)\n }\n\n takeReversed(\n n: number,\n from?: any,\n filterFn?: (key: TKey) => boolean\n ): Array<TKey> {\n return this.originalIndex.take(n, from, filterFn)\n }\n\n get orderedEntriesArray(): Array<[any, Set<TKey>]> {\n return this.originalIndex.orderedEntriesArrayReversed\n }\n\n get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]> {\n return this.originalIndex.orderedEntriesArray\n }\n\n // All operations below delegate to the original index\n\n supports(operation: IndexOperation): boolean {\n return this.originalIndex.supports(operation)\n }\n\n matchesField(fieldPath: Array<string>): boolean {\n return this.originalIndex.matchesField(fieldPath)\n }\n\n matchesCompareOptions(compareOptions: CompareOptions): boolean {\n return this.originalIndex.matchesCompareOptions(compareOptions)\n }\n\n matchesDirection(direction: OrderByDirection): boolean {\n return this.originalIndex.matchesDirection(direction)\n }\n\n getStats(): IndexStats {\n return this.originalIndex.getStats()\n }\n\n add(key: TKey, item: any): void {\n this.originalIndex.add(key, item)\n }\n\n remove(key: TKey, item: any): void {\n this.originalIndex.remove(key, item)\n }\n\n update(key: TKey, oldItem: any, newItem: any): void {\n this.originalIndex.update(key, oldItem, newItem)\n }\n\n build(entries: Iterable<[TKey, any]>): void {\n this.originalIndex.build(entries)\n }\n\n clear(): void {\n this.originalIndex.clear()\n }\n\n get keyCount(): number {\n return this.originalIndex.keyCount\n }\n\n equalityLookup(value: any): Set<TKey> {\n return this.originalIndex.equalityLookup(value)\n }\n\n inArrayLookup(values: Array<any>): Set<TKey> {\n return this.originalIndex.inArrayLookup(values)\n }\n\n get indexedKeysSet(): Set<TKey> {\n return this.originalIndex.indexedKeysSet\n }\n\n get valueMapData(): Map<any, Set<TKey>> {\n return this.originalIndex.valueMapData\n }\n}\n"],"names":[],"mappings":";;AAKO,MAAM,aAEb;AAAA,EAGE,YAAY,OAA6B;AACvC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA,EAIA,OAAO,WAA2B,OAAuB;AACvD,UAAM,mBACJ,cAAc,OACV,OACA,cAAc,QACZ,QACA,cAAc,OACZ,OACA,cAAc,QACZ,QACA;AACZ,WAAO,KAAK,cAAc,OAAO,kBAAkB,KAAK;AAAA,EAC1D;AAAA,EAEA,WAAW,UAA6B,IAAe;AACrD,WAAO,KAAK,cAAc,mBAAmB,OAAO;AAAA,EACtD;AAAA,EAEA,mBAAmB,UAA6B,IAAe;AAC7D,WAAO,KAAK,cAAc,WAAW,OAAO;AAAA,EAC9C;AAAA,EAEA,KAAK,GAAW,MAAY,UAAgD;AAC1E,WAAO,KAAK,cAAc,aAAa,GAAG,MAAM,QAAQ;AAAA,EAC1D;AAAA,EAEA,aACE,GACA,MACA,UACa;AACb,WAAO,KAAK,cAAc,KAAK,GAAG,MAAM,QAAQ;AAAA,EAClD;AAAA,EAEA,IAAI,sBAA+C;AACjD,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,IAAI,8BAAuD;AACzD,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA,EAIA,SAAS,WAAoC;AAC3C,WAAO,KAAK,cAAc,SAAS,SAAS;AAAA,EAC9C;AAAA,EAEA,aAAa,WAAmC;AAC9C,WAAO,KAAK,cAAc,aAAa,SAAS;AAAA,EAClD;AAAA,EAEA,sBAAsB,gBAAyC;AAC7D,WAAO,KAAK,cAAc,sBAAsB,cAAc;AAAA,EAChE;AAAA,EAEA,iBAAiB,WAAsC;AACrD,WAAO,KAAK,cAAc,iBAAiB,SAAS;AAAA,EACtD;AAAA,EAEA,WAAuB;AACrB,WAAO,KAAK,cAAc,SAAA;AAAA,EAC5B;AAAA,EAEA,IAAI,KAAW,MAAiB;AAC9B,SAAK,cAAc,IAAI,KAAK,IAAI;AAAA,EAClC;AAAA,EAEA,OAAO,KAAW,MAAiB;AACjC,SAAK,cAAc,OAAO,KAAK,IAAI;AAAA,EACrC;AAAA,EAEA,OAAO,KAAW,SAAc,SAAoB;AAClD,SAAK,cAAc,OAAO,KAAK,SAAS,OAAO;AAAA,EACjD;AAAA,EAEA,MAAM,SAAsC;AAC1C,SAAK,cAAc,MAAM,OAAO;AAAA,EAClC;AAAA,EAEA,QAAc;AACZ,SAAK,cAAc,MAAA;AAAA,EACrB;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,eAAe,OAAuB;AACpC,WAAO,KAAK,cAAc,eAAe,KAAK;AAAA,EAChD;AAAA,EAEA,cAAc,QAA+B;AAC3C,WAAO,KAAK,cAAc,cAAc,MAAM;AAAA,EAChD;AAAA,EAEA,IAAI,iBAA4B;AAC9B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,IAAI,eAAoC;AACtC,WAAO,KAAK,cAAc;AAAA,EAC5B;AACF;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CompareOptions } from '../query/builder/types.cjs';
|
|
2
|
+
import { OrderByDirection } from '../query/ir.cjs';
|
|
3
|
+
import { IndexInterface, IndexOperation, IndexStats } from './base-index.cjs';
|
|
4
|
+
import { RangeQueryOptions } from './btree-index.cjs';
|
|
5
|
+
export declare class ReverseIndex<TKey extends string | number> implements IndexInterface<TKey> {
|
|
6
|
+
private originalIndex;
|
|
7
|
+
constructor(index: IndexInterface<TKey>);
|
|
8
|
+
lookup(operation: IndexOperation, value: any): Set<TKey>;
|
|
9
|
+
rangeQuery(options?: RangeQueryOptions): Set<TKey>;
|
|
10
|
+
rangeQueryReversed(options?: RangeQueryOptions): Set<TKey>;
|
|
11
|
+
take(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
12
|
+
takeReversed(n: number, from?: any, filterFn?: (key: TKey) => boolean): Array<TKey>;
|
|
13
|
+
get orderedEntriesArray(): Array<[any, Set<TKey>]>;
|
|
14
|
+
get orderedEntriesArrayReversed(): Array<[any, Set<TKey>]>;
|
|
15
|
+
supports(operation: IndexOperation): boolean;
|
|
16
|
+
matchesField(fieldPath: Array<string>): boolean;
|
|
17
|
+
matchesCompareOptions(compareOptions: CompareOptions): boolean;
|
|
18
|
+
matchesDirection(direction: OrderByDirection): boolean;
|
|
19
|
+
getStats(): IndexStats;
|
|
20
|
+
add(key: TKey, item: any): void;
|
|
21
|
+
remove(key: TKey, item: any): void;
|
|
22
|
+
update(key: TKey, oldItem: any, newItem: any): void;
|
|
23
|
+
build(entries: Iterable<[TKey, any]>): void;
|
|
24
|
+
clear(): void;
|
|
25
|
+
get keyCount(): number;
|
|
26
|
+
equalityLookup(value: any): Set<TKey>;
|
|
27
|
+
inArrayLookup(values: Array<any>): Set<TKey>;
|
|
28
|
+
get indexedKeysSet(): Set<TKey>;
|
|
29
|
+
get valueMapData(): Map<any, Set<TKey>>;
|
|
30
|
+
}
|