@tanstack/db 0.0.27 → 0.0.30

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.
Files changed (167) hide show
  1. package/dist/cjs/change-events.cjs +141 -0
  2. package/dist/cjs/change-events.cjs.map +1 -0
  3. package/dist/cjs/change-events.d.cts +49 -0
  4. package/dist/cjs/collection.cjs +234 -86
  5. package/dist/cjs/collection.cjs.map +1 -1
  6. package/dist/cjs/collection.d.cts +95 -20
  7. package/dist/cjs/errors.cjs +509 -1
  8. package/dist/cjs/errors.cjs.map +1 -1
  9. package/dist/cjs/errors.d.cts +225 -1
  10. package/dist/cjs/index.cjs +82 -3
  11. package/dist/cjs/index.cjs.map +1 -1
  12. package/dist/cjs/index.d.cts +5 -1
  13. package/dist/cjs/indexes/auto-index.cjs +64 -0
  14. package/dist/cjs/indexes/auto-index.cjs.map +1 -0
  15. package/dist/cjs/indexes/auto-index.d.cts +9 -0
  16. package/dist/cjs/indexes/base-index.cjs +46 -0
  17. package/dist/cjs/indexes/base-index.cjs.map +1 -0
  18. package/dist/cjs/indexes/base-index.d.cts +54 -0
  19. package/dist/cjs/indexes/btree-index.cjs +191 -0
  20. package/dist/cjs/indexes/btree-index.cjs.map +1 -0
  21. package/dist/cjs/indexes/btree-index.d.cts +74 -0
  22. package/dist/cjs/indexes/index-options.d.cts +13 -0
  23. package/dist/cjs/indexes/lazy-index.cjs +193 -0
  24. package/dist/cjs/indexes/lazy-index.cjs.map +1 -0
  25. package/dist/cjs/indexes/lazy-index.d.cts +96 -0
  26. package/dist/cjs/local-storage.cjs +9 -15
  27. package/dist/cjs/local-storage.cjs.map +1 -1
  28. package/dist/cjs/query/builder/functions.cjs +11 -0
  29. package/dist/cjs/query/builder/functions.cjs.map +1 -1
  30. package/dist/cjs/query/builder/functions.d.cts +4 -0
  31. package/dist/cjs/query/builder/index.cjs +6 -7
  32. package/dist/cjs/query/builder/index.cjs.map +1 -1
  33. package/dist/cjs/query/builder/ref-proxy.cjs +37 -0
  34. package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -1
  35. package/dist/cjs/query/builder/ref-proxy.d.cts +12 -0
  36. package/dist/cjs/query/compiler/evaluators.cjs +83 -58
  37. package/dist/cjs/query/compiler/evaluators.cjs.map +1 -1
  38. package/dist/cjs/query/compiler/evaluators.d.cts +8 -0
  39. package/dist/cjs/query/compiler/expressions.cjs +61 -0
  40. package/dist/cjs/query/compiler/expressions.cjs.map +1 -0
  41. package/dist/cjs/query/compiler/expressions.d.cts +25 -0
  42. package/dist/cjs/query/compiler/group-by.cjs +5 -10
  43. package/dist/cjs/query/compiler/group-by.cjs.map +1 -1
  44. package/dist/cjs/query/compiler/index.cjs +23 -17
  45. package/dist/cjs/query/compiler/index.cjs.map +1 -1
  46. package/dist/cjs/query/compiler/index.d.cts +12 -3
  47. package/dist/cjs/query/compiler/joins.cjs +61 -12
  48. package/dist/cjs/query/compiler/joins.cjs.map +1 -1
  49. package/dist/cjs/query/compiler/order-by.cjs +4 -34
  50. package/dist/cjs/query/compiler/order-by.cjs.map +1 -1
  51. package/dist/cjs/query/compiler/types.d.cts +2 -2
  52. package/dist/cjs/query/live-query-collection.cjs +54 -12
  53. package/dist/cjs/query/live-query-collection.cjs.map +1 -1
  54. package/dist/cjs/query/optimizer.cjs +45 -7
  55. package/dist/cjs/query/optimizer.cjs.map +1 -1
  56. package/dist/cjs/query/optimizer.d.cts +13 -3
  57. package/dist/cjs/transactions.cjs +5 -4
  58. package/dist/cjs/transactions.cjs.map +1 -1
  59. package/dist/cjs/types.d.cts +31 -0
  60. package/dist/cjs/utils/array-utils.d.cts +8 -0
  61. package/dist/cjs/utils/btree.cjs +677 -0
  62. package/dist/cjs/utils/btree.cjs.map +1 -0
  63. package/dist/cjs/utils/btree.d.cts +197 -0
  64. package/dist/cjs/utils/comparison.cjs +52 -0
  65. package/dist/cjs/utils/comparison.cjs.map +1 -0
  66. package/dist/cjs/utils/comparison.d.cts +11 -0
  67. package/dist/cjs/utils/index-optimization.cjs +270 -0
  68. package/dist/cjs/utils/index-optimization.cjs.map +1 -0
  69. package/dist/cjs/utils/index-optimization.d.cts +29 -0
  70. package/dist/esm/change-events.d.ts +49 -0
  71. package/dist/esm/change-events.js +141 -0
  72. package/dist/esm/change-events.js.map +1 -0
  73. package/dist/esm/collection.d.ts +95 -20
  74. package/dist/esm/collection.js +232 -84
  75. package/dist/esm/collection.js.map +1 -1
  76. package/dist/esm/errors.d.ts +225 -1
  77. package/dist/esm/errors.js +510 -2
  78. package/dist/esm/errors.js.map +1 -1
  79. package/dist/esm/index.d.ts +5 -1
  80. package/dist/esm/index.js +81 -2
  81. package/dist/esm/index.js.map +1 -1
  82. package/dist/esm/indexes/auto-index.d.ts +9 -0
  83. package/dist/esm/indexes/auto-index.js +64 -0
  84. package/dist/esm/indexes/auto-index.js.map +1 -0
  85. package/dist/esm/indexes/base-index.d.ts +54 -0
  86. package/dist/esm/indexes/base-index.js +46 -0
  87. package/dist/esm/indexes/base-index.js.map +1 -0
  88. package/dist/esm/indexes/btree-index.d.ts +74 -0
  89. package/dist/esm/indexes/btree-index.js +191 -0
  90. package/dist/esm/indexes/btree-index.js.map +1 -0
  91. package/dist/esm/indexes/index-options.d.ts +13 -0
  92. package/dist/esm/indexes/lazy-index.d.ts +96 -0
  93. package/dist/esm/indexes/lazy-index.js +193 -0
  94. package/dist/esm/indexes/lazy-index.js.map +1 -0
  95. package/dist/esm/local-storage.js +9 -15
  96. package/dist/esm/local-storage.js.map +1 -1
  97. package/dist/esm/query/builder/functions.d.ts +4 -0
  98. package/dist/esm/query/builder/functions.js +11 -0
  99. package/dist/esm/query/builder/functions.js.map +1 -1
  100. package/dist/esm/query/builder/index.js +6 -7
  101. package/dist/esm/query/builder/index.js.map +1 -1
  102. package/dist/esm/query/builder/ref-proxy.d.ts +12 -0
  103. package/dist/esm/query/builder/ref-proxy.js +37 -0
  104. package/dist/esm/query/builder/ref-proxy.js.map +1 -1
  105. package/dist/esm/query/compiler/evaluators.d.ts +8 -0
  106. package/dist/esm/query/compiler/evaluators.js +84 -59
  107. package/dist/esm/query/compiler/evaluators.js.map +1 -1
  108. package/dist/esm/query/compiler/expressions.d.ts +25 -0
  109. package/dist/esm/query/compiler/expressions.js +61 -0
  110. package/dist/esm/query/compiler/expressions.js.map +1 -0
  111. package/dist/esm/query/compiler/group-by.js +5 -10
  112. package/dist/esm/query/compiler/group-by.js.map +1 -1
  113. package/dist/esm/query/compiler/index.d.ts +12 -3
  114. package/dist/esm/query/compiler/index.js +23 -17
  115. package/dist/esm/query/compiler/index.js.map +1 -1
  116. package/dist/esm/query/compiler/joins.js +61 -12
  117. package/dist/esm/query/compiler/joins.js.map +1 -1
  118. package/dist/esm/query/compiler/order-by.js +1 -31
  119. package/dist/esm/query/compiler/order-by.js.map +1 -1
  120. package/dist/esm/query/compiler/types.d.ts +2 -2
  121. package/dist/esm/query/live-query-collection.js +54 -12
  122. package/dist/esm/query/live-query-collection.js.map +1 -1
  123. package/dist/esm/query/optimizer.d.ts +13 -3
  124. package/dist/esm/query/optimizer.js +40 -2
  125. package/dist/esm/query/optimizer.js.map +1 -1
  126. package/dist/esm/transactions.js +5 -4
  127. package/dist/esm/transactions.js.map +1 -1
  128. package/dist/esm/types.d.ts +31 -0
  129. package/dist/esm/utils/array-utils.d.ts +8 -0
  130. package/dist/esm/utils/btree.d.ts +197 -0
  131. package/dist/esm/utils/btree.js +677 -0
  132. package/dist/esm/utils/btree.js.map +1 -0
  133. package/dist/esm/utils/comparison.d.ts +11 -0
  134. package/dist/esm/utils/comparison.js +52 -0
  135. package/dist/esm/utils/comparison.js.map +1 -0
  136. package/dist/esm/utils/index-optimization.d.ts +29 -0
  137. package/dist/esm/utils/index-optimization.js +270 -0
  138. package/dist/esm/utils/index-optimization.js.map +1 -0
  139. package/package.json +1 -1
  140. package/src/change-events.ts +257 -0
  141. package/src/collection.ts +316 -105
  142. package/src/errors.ts +545 -1
  143. package/src/index.ts +7 -1
  144. package/src/indexes/auto-index.ts +108 -0
  145. package/src/indexes/base-index.ts +119 -0
  146. package/src/indexes/btree-index.ts +263 -0
  147. package/src/indexes/index-options.ts +42 -0
  148. package/src/indexes/lazy-index.ts +251 -0
  149. package/src/local-storage.ts +16 -17
  150. package/src/query/builder/functions.ts +14 -0
  151. package/src/query/builder/index.ts +12 -7
  152. package/src/query/builder/ref-proxy.ts +65 -0
  153. package/src/query/compiler/evaluators.ts +114 -62
  154. package/src/query/compiler/expressions.ts +92 -0
  155. package/src/query/compiler/group-by.ts +10 -10
  156. package/src/query/compiler/index.ts +52 -22
  157. package/src/query/compiler/joins.ts +114 -15
  158. package/src/query/compiler/order-by.ts +1 -45
  159. package/src/query/compiler/types.ts +2 -2
  160. package/src/query/live-query-collection.ts +95 -15
  161. package/src/query/optimizer.ts +94 -5
  162. package/src/transactions.ts +10 -4
  163. package/src/types.ts +38 -0
  164. package/src/utils/array-utils.ts +28 -0
  165. package/src/utils/btree.ts +1010 -0
  166. package/src/utils/comparison.ts +79 -0
  167. package/src/utils/index-optimization.ts +546 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
@@ -0,0 +1,9 @@
1
+ import { BasicExpression } from '../query/ir.js';
2
+ import { CollectionImpl } from '../collection.js';
3
+ export interface AutoIndexConfig {
4
+ autoIndex?: `off` | `eager`;
5
+ }
6
+ /**
7
+ * Analyzes a where expression and creates indexes for all simple operations on single fields
8
+ */
9
+ export declare function ensureIndexForExpression<T extends Record<string, any>, TKey extends string | number>(expression: BasicExpression, collection: CollectionImpl<T, TKey, any, any, any>): void;
@@ -0,0 +1,64 @@
1
+ import { BTreeIndex } from "./btree-index.js";
2
+ function ensureIndexForExpression(expression, collection) {
3
+ if (collection.config.autoIndex !== `eager`) {
4
+ return;
5
+ }
6
+ if (collection.status === `loading` || collection.status === `initialCommit`) {
7
+ return;
8
+ }
9
+ const indexableExpressions = extractIndexableExpressions(expression);
10
+ for (const { fieldName, fieldPath } of indexableExpressions) {
11
+ const existingIndex = Array.from(collection.indexes.values()).find(
12
+ (index) => index.matchesField(fieldPath)
13
+ );
14
+ if (existingIndex) {
15
+ continue;
16
+ }
17
+ try {
18
+ collection.createIndex((row) => row[fieldName], {
19
+ name: `auto_${fieldName}`,
20
+ indexType: BTreeIndex
21
+ });
22
+ } catch (error) {
23
+ console.warn(
24
+ `Failed to create auto-index for field "${fieldName}":`,
25
+ error
26
+ );
27
+ }
28
+ }
29
+ }
30
+ function extractIndexableExpressions(expression) {
31
+ const results = [];
32
+ function extractFromExpression(expr) {
33
+ if (expr.type !== `func`) {
34
+ return;
35
+ }
36
+ const func = expr;
37
+ if (func.name === `and`) {
38
+ for (const arg of func.args) {
39
+ extractFromExpression(arg);
40
+ }
41
+ return;
42
+ }
43
+ const supportedOperations = [`eq`, `gt`, `gte`, `lt`, `lte`, `in`];
44
+ if (!supportedOperations.includes(func.name)) {
45
+ return;
46
+ }
47
+ if (func.args.length < 1 || func.args[0].type !== `ref`) {
48
+ return;
49
+ }
50
+ const fieldRef = func.args[0];
51
+ const fieldPath = fieldRef.path;
52
+ if (fieldPath.length !== 1) {
53
+ return;
54
+ }
55
+ const fieldName = fieldPath[0];
56
+ results.push({ fieldName, fieldPath });
57
+ }
58
+ extractFromExpression(expression);
59
+ return results;
60
+ }
61
+ export {
62
+ ensureIndexForExpression
63
+ };
64
+ //# sourceMappingURL=auto-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-index.js","sources":["../../../src/indexes/auto-index.ts"],"sourcesContent":["import { BTreeIndex } from \"./btree-index\"\nimport type { BasicExpression } from \"../query/ir\"\nimport type { CollectionImpl } from \"../collection\"\n\nexport interface AutoIndexConfig {\n autoIndex?: `off` | `eager`\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 // Only proceed if auto-indexing is enabled\n if (collection.config.autoIndex !== `eager`) {\n return\n }\n\n // Don't auto-index during sync operations\n if (\n collection.status === `loading` ||\n collection.status === `initialCommit`\n ) {\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 // Check if we already have an index for this field\n const existingIndex = Array.from(collection.indexes.values()).find(\n (index) => index.matchesField(fieldPath)\n )\n\n if (existingIndex) {\n continue // 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 })\n } catch (error) {\n console.warn(\n `Failed to create auto-index for field \"${fieldName}\":`,\n error\n )\n }\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":[],"mappings":";AAWO,SAAS,yBAId,YACA,YACM;AAEN,MAAI,WAAW,OAAO,cAAc,SAAS;AAC3C;AAAA,EACF;AAGA,MACE,WAAW,WAAW,aACtB,WAAW,WAAW,iBACtB;AACA;AAAA,EACF;AAGA,QAAM,uBAAuB,4BAA4B,UAAU;AAEnE,aAAW,EAAE,WAAW,UAAA,KAAe,sBAAsB;AAE3D,UAAM,gBAAgB,MAAM,KAAK,WAAW,QAAQ,OAAA,CAAQ,EAAE;AAAA,MAC5D,CAAC,UAAU,MAAM,aAAa,SAAS;AAAA,IAAA;AAGzC,QAAI,eAAe;AACjB;AAAA,IACF;AAGA,QAAI;AACF,iBAAW,YAAY,CAAC,QAAS,IAAY,SAAS,GAAG;AAAA,QACvD,MAAM,QAAQ,SAAS;AAAA,QACvB,WAAW;AAAA,MAAA,CACZ;AAAA,IACH,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,0CAA0C,SAAS;AAAA,QACnD;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF;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;"}
@@ -0,0 +1,54 @@
1
+ import { comparisonFunctions } from '../query/builder/functions.js';
2
+ import { BasicExpression } from '../query/ir.js';
3
+ /**
4
+ * Operations that indexes can support, imported from available comparison functions
5
+ */
6
+ export declare const IndexOperation: readonly ["eq", "gt", "gte", "lt", "lte", "in", "like", "ilike"];
7
+ /**
8
+ * Type for index operation values
9
+ */
10
+ export type IndexOperation = (typeof comparisonFunctions)[number];
11
+ /**
12
+ * Statistics about index usage and performance
13
+ */
14
+ export interface IndexStats {
15
+ readonly entryCount: number;
16
+ readonly lookupCount: number;
17
+ readonly averageLookupTime: number;
18
+ readonly lastUpdated: Date;
19
+ }
20
+ /**
21
+ * Base abstract class that all index types extend
22
+ */
23
+ export declare abstract class BaseIndex<TKey extends string | number = string | number> {
24
+ readonly id: number;
25
+ readonly name?: string;
26
+ readonly expression: BasicExpression;
27
+ abstract readonly supportedOperations: Set<IndexOperation>;
28
+ protected lookupCount: number;
29
+ protected totalLookupTime: number;
30
+ protected lastUpdated: Date;
31
+ constructor(id: number, expression: BasicExpression, name?: string, options?: any);
32
+ abstract add(key: TKey, item: any): void;
33
+ abstract remove(key: TKey, item: any): void;
34
+ abstract update(key: TKey, oldItem: any, newItem: any): void;
35
+ abstract build(entries: Iterable<[TKey, any]>): void;
36
+ abstract clear(): void;
37
+ abstract lookup(operation: IndexOperation, value: any): Set<TKey>;
38
+ abstract get keyCount(): number;
39
+ supports(operation: IndexOperation): boolean;
40
+ matchesField(fieldPath: Array<string>): boolean;
41
+ getStats(): IndexStats;
42
+ protected abstract initialize(options?: any): void;
43
+ protected evaluateIndexExpression(item: any): any;
44
+ protected trackLookup(startTime: number): void;
45
+ protected updateTimestamp(): void;
46
+ }
47
+ /**
48
+ * Type for index constructor
49
+ */
50
+ export type IndexConstructor<TKey extends string | number = string | number> = new (id: number, expression: BasicExpression, name?: string, options?: any) => BaseIndex<TKey>;
51
+ /**
52
+ * Index resolver can be either a class constructor or async loader
53
+ */
54
+ export type IndexResolver<TKey extends string | number = string | number> = IndexConstructor<TKey> | (() => Promise<IndexConstructor<TKey>>);
@@ -0,0 +1,46 @@
1
+ import { compileSingleRowExpression } from "../query/compiler/evaluators.js";
2
+ import { comparisonFunctions } from "../query/builder/functions.js";
3
+ const IndexOperation = comparisonFunctions;
4
+ class BaseIndex {
5
+ constructor(id, expression, name, options) {
6
+ this.lookupCount = 0;
7
+ this.totalLookupTime = 0;
8
+ this.lastUpdated = /* @__PURE__ */ new Date();
9
+ this.id = id;
10
+ this.expression = expression;
11
+ this.name = name;
12
+ this.initialize(options);
13
+ }
14
+ // Common methods
15
+ supports(operation) {
16
+ return this.supportedOperations.has(operation);
17
+ }
18
+ matchesField(fieldPath) {
19
+ return this.expression.type === `ref` && this.expression.path.length === fieldPath.length && this.expression.path.every((part, i) => part === fieldPath[i]);
20
+ }
21
+ getStats() {
22
+ return {
23
+ entryCount: this.keyCount,
24
+ lookupCount: this.lookupCount,
25
+ averageLookupTime: this.lookupCount > 0 ? this.totalLookupTime / this.lookupCount : 0,
26
+ lastUpdated: this.lastUpdated
27
+ };
28
+ }
29
+ evaluateIndexExpression(item) {
30
+ const evaluator = compileSingleRowExpression(this.expression);
31
+ return evaluator(item);
32
+ }
33
+ trackLookup(startTime) {
34
+ const duration = performance.now() - startTime;
35
+ this.lookupCount++;
36
+ this.totalLookupTime += duration;
37
+ }
38
+ updateTimestamp() {
39
+ this.lastUpdated = /* @__PURE__ */ new Date();
40
+ }
41
+ }
42
+ export {
43
+ BaseIndex,
44
+ IndexOperation
45
+ };
46
+ //# sourceMappingURL=base-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-index.js","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<\n TKey extends string | number = string | number,\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\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.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 get keyCount(): number\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 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":[],"mappings":";;AAOO,MAAM,iBAAiB;AAoBvB,MAAe,UAEpB;AAAA,EAUA,YACE,IACA,YACA,MACA,SACA;AATF,SAAU,cAAc;AACxB,SAAU,kBAAkB;AAC5B,SAAU,kCAAkB,KAAA;AAQ1B,SAAK,KAAK;AACV,SAAK,aAAa;AAClB,SAAK,OAAO;AACZ,SAAK,WAAW,OAAO;AAAA,EACzB;AAAA;AAAA,EAYA,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,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,YAAY,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;"}
@@ -0,0 +1,74 @@
1
+ import { BaseIndex, IndexOperation } from './base-index.js';
2
+ import { BasicExpression } from '../query/ir.js';
3
+ /**
4
+ * Options for Ordered index
5
+ */
6
+ export interface BTreeIndexOptions {
7
+ compareFn?: (a: any, b: any) => number;
8
+ }
9
+ /**
10
+ * Options for range queries
11
+ */
12
+ export interface RangeQueryOptions {
13
+ from?: any;
14
+ to?: any;
15
+ fromInclusive?: boolean;
16
+ toInclusive?: boolean;
17
+ }
18
+ /**
19
+ * B+Tree index for sorted data with range queries
20
+ * This maintains items in sorted order and provides efficient range operations
21
+ */
22
+ export declare class BTreeIndex<TKey extends string | number = string | number> extends BaseIndex<TKey> {
23
+ readonly supportedOperations: Set<"eq" | "gt" | "gte" | "lt" | "lte" | "in" | "like" | "ilike">;
24
+ private orderedEntries;
25
+ private valueMap;
26
+ private indexedKeys;
27
+ private compareFn;
28
+ constructor(id: number, expression: BasicExpression, name?: string, options?: any);
29
+ protected initialize(_options?: BTreeIndexOptions): void;
30
+ /**
31
+ * Adds a value to the index
32
+ */
33
+ add(key: TKey, item: any): void;
34
+ /**
35
+ * Removes a value from the index
36
+ */
37
+ remove(key: TKey, item: any): void;
38
+ /**
39
+ * Updates a value in the index
40
+ */
41
+ update(key: TKey, oldItem: any, newItem: any): void;
42
+ /**
43
+ * Builds the index from a collection of entries
44
+ */
45
+ build(entries: Iterable<[TKey, any]>): void;
46
+ /**
47
+ * Clears all data from the index
48
+ */
49
+ clear(): void;
50
+ /**
51
+ * Performs a lookup operation
52
+ */
53
+ lookup(operation: IndexOperation, value: any): Set<TKey>;
54
+ /**
55
+ * Gets the number of indexed keys
56
+ */
57
+ get keyCount(): number;
58
+ /**
59
+ * Performs an equality lookup
60
+ */
61
+ equalityLookup(value: any): Set<TKey>;
62
+ /**
63
+ * Performs a range query with options
64
+ * This is more efficient for compound queries like "WHERE a > 5 AND a < 10"
65
+ */
66
+ rangeQuery(options?: RangeQueryOptions): Set<TKey>;
67
+ /**
68
+ * Performs an IN array lookup
69
+ */
70
+ inArrayLookup(values: Array<any>): Set<TKey>;
71
+ get indexedKeysSet(): Set<TKey>;
72
+ get orderedEntriesArray(): Array<[any, Set<TKey>]>;
73
+ get valueMapData(): Map<any, Set<TKey>>;
74
+ }
@@ -0,0 +1,191 @@
1
+ import { ascComparator } from "../utils/comparison.js";
2
+ import { BTree } from "../utils/btree.js";
3
+ import { BaseIndex } from "./base-index.js";
4
+ class BTreeIndex extends BaseIndex {
5
+ constructor(id, expression, name, options) {
6
+ super(id, expression, name, options);
7
+ this.supportedOperations = /* @__PURE__ */ new Set([
8
+ `eq`,
9
+ `gt`,
10
+ `gte`,
11
+ `lt`,
12
+ `lte`,
13
+ `in`
14
+ ]);
15
+ this.valueMap = /* @__PURE__ */ new Map();
16
+ this.indexedKeys = /* @__PURE__ */ new Set();
17
+ this.compareFn = ascComparator;
18
+ this.compareFn = (options == null ? void 0 : options.compareFn) ?? ascComparator;
19
+ this.orderedEntries = new BTree(this.compareFn);
20
+ }
21
+ initialize(_options) {
22
+ }
23
+ /**
24
+ * Adds a value to the index
25
+ */
26
+ add(key, item) {
27
+ let indexedValue;
28
+ try {
29
+ indexedValue = this.evaluateIndexExpression(item);
30
+ } catch (error) {
31
+ throw new Error(
32
+ `Failed to evaluate index expression for key ${key}: ${error}`
33
+ );
34
+ }
35
+ if (this.valueMap.has(indexedValue)) {
36
+ this.valueMap.get(indexedValue).add(key);
37
+ } else {
38
+ const keySet = /* @__PURE__ */ new Set([key]);
39
+ this.valueMap.set(indexedValue, keySet);
40
+ this.orderedEntries.set(indexedValue, void 0);
41
+ }
42
+ this.indexedKeys.add(key);
43
+ this.updateTimestamp();
44
+ }
45
+ /**
46
+ * Removes a value from the index
47
+ */
48
+ remove(key, item) {
49
+ let indexedValue;
50
+ try {
51
+ indexedValue = this.evaluateIndexExpression(item);
52
+ } catch (error) {
53
+ console.warn(
54
+ `Failed to evaluate index expression for key ${key} during removal:`,
55
+ error
56
+ );
57
+ return;
58
+ }
59
+ if (this.valueMap.has(indexedValue)) {
60
+ const keySet = this.valueMap.get(indexedValue);
61
+ keySet.delete(key);
62
+ if (keySet.size === 0) {
63
+ this.valueMap.delete(indexedValue);
64
+ this.orderedEntries.delete(indexedValue);
65
+ }
66
+ }
67
+ this.indexedKeys.delete(key);
68
+ this.updateTimestamp();
69
+ }
70
+ /**
71
+ * Updates a value in the index
72
+ */
73
+ update(key, oldItem, newItem) {
74
+ this.remove(key, oldItem);
75
+ this.add(key, newItem);
76
+ }
77
+ /**
78
+ * Builds the index from a collection of entries
79
+ */
80
+ build(entries) {
81
+ this.clear();
82
+ for (const [key, item] of entries) {
83
+ this.add(key, item);
84
+ }
85
+ }
86
+ /**
87
+ * Clears all data from the index
88
+ */
89
+ clear() {
90
+ this.orderedEntries.clear();
91
+ this.valueMap.clear();
92
+ this.indexedKeys.clear();
93
+ this.updateTimestamp();
94
+ }
95
+ /**
96
+ * Performs a lookup operation
97
+ */
98
+ lookup(operation, value) {
99
+ const startTime = performance.now();
100
+ let result;
101
+ switch (operation) {
102
+ case `eq`:
103
+ result = this.equalityLookup(value);
104
+ break;
105
+ case `gt`:
106
+ result = this.rangeQuery({ from: value, fromInclusive: false });
107
+ break;
108
+ case `gte`:
109
+ result = this.rangeQuery({ from: value, fromInclusive: true });
110
+ break;
111
+ case `lt`:
112
+ result = this.rangeQuery({ to: value, toInclusive: false });
113
+ break;
114
+ case `lte`:
115
+ result = this.rangeQuery({ to: value, toInclusive: true });
116
+ break;
117
+ case `in`:
118
+ result = this.inArrayLookup(value);
119
+ break;
120
+ default:
121
+ throw new Error(`Operation ${operation} not supported by BTreeIndex`);
122
+ }
123
+ this.trackLookup(startTime);
124
+ return result;
125
+ }
126
+ /**
127
+ * Gets the number of indexed keys
128
+ */
129
+ get keyCount() {
130
+ return this.indexedKeys.size;
131
+ }
132
+ // Public methods for backward compatibility (used by tests)
133
+ /**
134
+ * Performs an equality lookup
135
+ */
136
+ equalityLookup(value) {
137
+ return new Set(this.valueMap.get(value) ?? []);
138
+ }
139
+ /**
140
+ * Performs a range query with options
141
+ * This is more efficient for compound queries like "WHERE a > 5 AND a < 10"
142
+ */
143
+ rangeQuery(options = {}) {
144
+ const { from, to, fromInclusive = true, toInclusive = true } = options;
145
+ const result = /* @__PURE__ */ new Set();
146
+ const fromKey = from ?? this.orderedEntries.minKey();
147
+ const toKey = to ?? this.orderedEntries.maxKey();
148
+ this.orderedEntries.forRange(
149
+ fromKey,
150
+ toKey,
151
+ toInclusive,
152
+ (indexedValue, _) => {
153
+ if (!fromInclusive && this.compareFn(indexedValue, from) === 0) {
154
+ return;
155
+ }
156
+ const keys = this.valueMap.get(indexedValue);
157
+ if (keys) {
158
+ keys.forEach((key) => result.add(key));
159
+ }
160
+ }
161
+ );
162
+ return result;
163
+ }
164
+ /**
165
+ * Performs an IN array lookup
166
+ */
167
+ inArrayLookup(values) {
168
+ const result = /* @__PURE__ */ new Set();
169
+ for (const value of values) {
170
+ const keys = this.valueMap.get(value);
171
+ if (keys) {
172
+ keys.forEach((key) => result.add(key));
173
+ }
174
+ }
175
+ return result;
176
+ }
177
+ // Getter methods for testing compatibility
178
+ get indexedKeysSet() {
179
+ return this.indexedKeys;
180
+ }
181
+ get orderedEntriesArray() {
182
+ return this.orderedEntries.keysArray().map((key) => [key, this.valueMap.get(key) ?? /* @__PURE__ */ new Set()]);
183
+ }
184
+ get valueMapData() {
185
+ return this.valueMap;
186
+ }
187
+ }
188
+ export {
189
+ BTreeIndex
190
+ };
191
+ //# sourceMappingURL=btree-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"btree-index.js","sources":["../../../src/indexes/btree-index.ts"],"sourcesContent":["import { ascComparator } from \"../utils/comparison.js\"\nimport { BTree } from \"../utils/btree.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 = ascComparator\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 ?? ascComparator\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 // 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 this.orderedEntries.set(indexedValue, 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 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 // Remove from ordered entries\n this.orderedEntries.delete(indexedValue)\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 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 const fromKey = from ?? this.orderedEntries.minKey()\n const toKey = to ?? 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 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 .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":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { IndexConstructor, IndexResolver } from './base-index.js';
2
+ /**
3
+ * Enhanced index options that support both sync and async resolvers
4
+ */
5
+ export interface IndexOptions<TResolver extends IndexResolver = IndexResolver> {
6
+ name?: string;
7
+ indexType?: TResolver;
8
+ options?: TResolver extends IndexConstructor<any> ? TResolver extends new (id: string, expr: any, name?: string, options?: infer O) => any ? O : never : TResolver extends () => Promise<infer TCtor> ? TCtor extends new (id: string, expr: any, name?: string, options?: infer O) => any ? O : never : never;
9
+ }
10
+ /**
11
+ * Utility type to extract the constructed index type from a resolver
12
+ */
13
+ export type ResolvedIndexType<TResolver extends IndexResolver> = TResolver extends IndexConstructor<any> ? InstanceType<TResolver> : TResolver extends () => Promise<IndexConstructor<any>> ? TResolver extends () => Promise<infer TCtor> ? TCtor extends IndexConstructor<any> ? InstanceType<TCtor> : never : never : never;
@@ -0,0 +1,96 @@
1
+ import { BaseIndex, IndexResolver } from './base-index.js';
2
+ import { BasicExpression } from '../query/ir.js';
3
+ /**
4
+ * Wrapper that defers index creation until first sync
5
+ */
6
+ export declare class LazyIndexWrapper<TKey extends string | number = string | number> {
7
+ private id;
8
+ private expression;
9
+ private name;
10
+ private resolver;
11
+ private options;
12
+ private collectionEntries?;
13
+ private indexPromise;
14
+ private resolvedIndex;
15
+ constructor(id: number, expression: BasicExpression, name: string | undefined, resolver: IndexResolver<TKey>, options: any, collectionEntries?: Iterable<[TKey, any]> | undefined);
16
+ /**
17
+ * Resolve the actual index
18
+ */
19
+ resolve(): Promise<BaseIndex<TKey>>;
20
+ /**
21
+ * Check if already resolved
22
+ */
23
+ isResolved(): boolean;
24
+ /**
25
+ * Get resolved index (throws if not ready)
26
+ */
27
+ getResolved(): BaseIndex<TKey>;
28
+ /**
29
+ * Get the index ID
30
+ */
31
+ getId(): number;
32
+ /**
33
+ * Get the index name
34
+ */
35
+ getName(): string | undefined;
36
+ /**
37
+ * Get the index expression
38
+ */
39
+ getExpression(): BasicExpression;
40
+ private createIndex;
41
+ }
42
+ /**
43
+ * Proxy that provides synchronous interface while index loads asynchronously
44
+ */
45
+ export declare class IndexProxy<TKey extends string | number = string | number> {
46
+ private indexId;
47
+ private lazyIndex;
48
+ constructor(indexId: number, lazyIndex: LazyIndexWrapper<TKey>);
49
+ /**
50
+ * Get the resolved index (throws if not ready)
51
+ */
52
+ get index(): BaseIndex<TKey>;
53
+ /**
54
+ * Check if index is ready
55
+ */
56
+ get isReady(): boolean;
57
+ /**
58
+ * Wait for index to be ready
59
+ */
60
+ whenReady(): Promise<BaseIndex<TKey>>;
61
+ /**
62
+ * Get the index ID
63
+ */
64
+ get id(): number;
65
+ /**
66
+ * Get the index name (throws if not ready)
67
+ */
68
+ get name(): string | undefined;
69
+ /**
70
+ * Get the index expression (available immediately)
71
+ */
72
+ get expression(): BasicExpression;
73
+ /**
74
+ * Check if index supports an operation (throws if not ready)
75
+ */
76
+ supports(operation: any): boolean;
77
+ /**
78
+ * Get index statistics (throws if not ready)
79
+ */
80
+ getStats(): import('./base-index.js').IndexStats;
81
+ /**
82
+ * Check if index matches a field path (available immediately)
83
+ */
84
+ matchesField(fieldPath: Array<string>): boolean;
85
+ /**
86
+ * Get the key count (throws if not ready)
87
+ */
88
+ get keyCount(): number;
89
+ get indexedKeysSet(): Set<TKey>;
90
+ get orderedEntriesArray(): Array<[any, Set<TKey>]>;
91
+ get valueMapData(): Map<any, Set<TKey>>;
92
+ equalityLookup(value: any): Set<TKey>;
93
+ rangeQuery(options: any): Set<TKey>;
94
+ inArrayLookup(values: Array<any>): Set<TKey>;
95
+ _getLazyWrapper(): LazyIndexWrapper<TKey>;
96
+ }