@topgunbuild/core 0.5.0 → 0.7.0

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/index.d.mts CHANGED
@@ -3330,10 +3330,10 @@ interface Index<K, V, A = unknown> {
3330
3330
  */
3331
3331
  interface IndexQuery<A> {
3332
3332
  /** Query type */
3333
- type: 'equal' | 'in' | 'has' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'contains' | 'containsAll' | 'containsAny';
3333
+ type: 'equal' | 'in' | 'has' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'contains' | 'containsAll' | 'containsAny' | 'compound';
3334
3334
  /** Value for equality queries */
3335
3335
  value?: A;
3336
- /** Values for 'in' queries */
3336
+ /** Values for 'in' queries or compound queries */
3337
3337
  values?: A[];
3338
3338
  /** Lower bound for range queries */
3339
3339
  from?: A;
@@ -4164,6 +4164,571 @@ declare class InvertedIndex<K, V, A extends string = string> implements Index<K,
4164
4164
  private valuesEqual;
4165
4165
  }
4166
4166
 
4167
+ /**
4168
+ * CompoundIndex Implementation (Phase 9.03)
4169
+ *
4170
+ * Multi-attribute index for optimizing AND queries.
4171
+ * Creates a composite key from multiple attribute values for O(1) lookup.
4172
+ *
4173
+ * Benefits:
4174
+ * - 100-1000× speedup for compound AND queries
4175
+ * - Eliminates ResultSet intersection overhead
4176
+ * - Single lookup instead of multiple index scans
4177
+ *
4178
+ * @module query/indexes/CompoundIndex
4179
+ */
4180
+
4181
+ /**
4182
+ * Options for compound index creation.
4183
+ */
4184
+ interface CompoundIndexOptions {
4185
+ /**
4186
+ * Separator for composite key generation.
4187
+ * Default: '|'
4188
+ * Choose a separator that won't appear in attribute values.
4189
+ */
4190
+ separator?: string;
4191
+ }
4192
+ /**
4193
+ * Compound index for O(1) multi-attribute queries.
4194
+ * Indexes multiple attributes as a single composite key.
4195
+ *
4196
+ * K = record key type, V = record value type
4197
+ */
4198
+ declare class CompoundIndex<K, V> implements Index<K, V, unknown> {
4199
+ readonly type: "compound";
4200
+ /** Attributes that make up this compound index (in order) */
4201
+ private readonly _attributes;
4202
+ /** Map from composite key to set of record keys */
4203
+ private data;
4204
+ /** Set of all indexed keys */
4205
+ private allKeys;
4206
+ /** Key separator */
4207
+ private readonly separator;
4208
+ /** Retrieval cost (lower than individual indexes combined) */
4209
+ private static readonly RETRIEVAL_COST;
4210
+ /**
4211
+ * Create a CompoundIndex.
4212
+ *
4213
+ * @param attributes - Array of attributes to index (order matters!)
4214
+ * @param options - Optional configuration
4215
+ *
4216
+ * @example
4217
+ * ```typescript
4218
+ * const statusAttr = simpleAttribute<Product, string>('status', p => p.status);
4219
+ * const categoryAttr = simpleAttribute<Product, string>('category', p => p.category);
4220
+ *
4221
+ * const compoundIndex = new CompoundIndex<string, Product>([statusAttr, categoryAttr]);
4222
+ * ```
4223
+ */
4224
+ constructor(attributes: Attribute<V, unknown>[], options?: CompoundIndexOptions);
4225
+ /**
4226
+ * Get the first attribute (used for Index interface compatibility).
4227
+ * Note: CompoundIndex spans multiple attributes.
4228
+ */
4229
+ get attribute(): Attribute<V, unknown>;
4230
+ /**
4231
+ * Get all attributes in this compound index.
4232
+ */
4233
+ get attributes(): Attribute<V, unknown>[];
4234
+ /**
4235
+ * Get attribute names as a combined identifier.
4236
+ */
4237
+ get compoundName(): string;
4238
+ getRetrievalCost(): number;
4239
+ supportsQuery(queryType: string): boolean;
4240
+ /**
4241
+ * Retrieve records matching compound query.
4242
+ *
4243
+ * @param query - Compound query with values matching each attribute
4244
+ * @returns ResultSet of matching keys
4245
+ *
4246
+ * @example
4247
+ * ```typescript
4248
+ * // Find products where status='active' AND category='electronics'
4249
+ * index.retrieve({
4250
+ * type: 'compound',
4251
+ * values: ['active', 'electronics']
4252
+ * });
4253
+ * ```
4254
+ */
4255
+ retrieve(query: IndexQuery<unknown>): ResultSet<K>;
4256
+ /**
4257
+ * Retrieve with explicit values (convenience method).
4258
+ *
4259
+ * @param values - Values in order of index attributes
4260
+ * @returns ResultSet of matching keys
4261
+ */
4262
+ retrieveByValues(...values: unknown[]): ResultSet<K>;
4263
+ add(key: K, record: V): void;
4264
+ remove(key: K, record: V): void;
4265
+ update(key: K, oldRecord: V, newRecord: V): void;
4266
+ clear(): void;
4267
+ getStats(): IndexStats;
4268
+ /**
4269
+ * Get extended statistics for compound index.
4270
+ */
4271
+ getExtendedStats(): CompoundIndexStats;
4272
+ /**
4273
+ * Check if this compound index can answer a query on the given attributes.
4274
+ * Compound indexes can be used if query attributes match in prefix order.
4275
+ *
4276
+ * @param attributeNames - Attribute names being queried
4277
+ * @returns true if this index can answer the query
4278
+ */
4279
+ canAnswerQuery(attributeNames: string[]): boolean;
4280
+ /**
4281
+ * Build composite key from array of values.
4282
+ */
4283
+ private buildCompositeKey;
4284
+ /**
4285
+ * Build composite key from record by extracting attribute values.
4286
+ * Returns null if any attribute value is undefined.
4287
+ */
4288
+ private buildCompositeKeyFromRecord;
4289
+ /**
4290
+ * Encode value for composite key.
4291
+ * Handles common types and escapes separator.
4292
+ */
4293
+ private encodeValue;
4294
+ /**
4295
+ * Escape regex special characters.
4296
+ */
4297
+ private escapeRegex;
4298
+ }
4299
+ /**
4300
+ * Extended statistics for compound index.
4301
+ */
4302
+ interface CompoundIndexStats extends IndexStats {
4303
+ /** Number of attributes in compound key */
4304
+ attributeCount: number;
4305
+ /** Names of indexed attributes */
4306
+ attributeNames: string[];
4307
+ /** Number of unique composite keys */
4308
+ compositeKeyCount: number;
4309
+ }
4310
+
4311
+ /**
4312
+ * Types for Adaptive Indexing System (Phase 8.02)
4313
+ *
4314
+ * Defines interfaces for query pattern tracking, index suggestions,
4315
+ * and auto-indexing configuration.
4316
+ *
4317
+ * @module query/adaptive/types
4318
+ */
4319
+ /**
4320
+ * Query type for pattern tracking.
4321
+ * Matches the query types from QueryTypes.ts and indexes/types.ts
4322
+ */
4323
+ type TrackedQueryType = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'in' | 'has' | 'contains' | 'containsAll' | 'containsAny' | 'compound';
4324
+ /**
4325
+ * Statistics for a single attribute + query type combination.
4326
+ */
4327
+ interface QueryStatistics {
4328
+ /** Attribute name being queried */
4329
+ attribute: string;
4330
+ /** Type of query (eq, gt, between, etc.) */
4331
+ queryType: TrackedQueryType;
4332
+ /** Number of times this pattern was queried */
4333
+ queryCount: number;
4334
+ /** Cumulative execution time in milliseconds */
4335
+ totalCost: number;
4336
+ /** Average execution time per query */
4337
+ averageCost: number;
4338
+ /** Timestamp of last query */
4339
+ lastQueried: number;
4340
+ /** Estimated result size (max observed) */
4341
+ estimatedCardinality: number;
4342
+ /** Whether an index exists for this attribute */
4343
+ hasIndex: boolean;
4344
+ }
4345
+ /**
4346
+ * Statistics for compound query patterns (Phase 9.03).
4347
+ * Tracks AND combinations of attributes for compound index suggestions.
4348
+ */
4349
+ interface CompoundQueryStatistics {
4350
+ /** Attribute names in the compound query (sorted) */
4351
+ attributes: string[];
4352
+ /** Combined key for identification */
4353
+ compoundKey: string;
4354
+ /** Number of times this pattern was queried */
4355
+ queryCount: number;
4356
+ /** Cumulative execution time in milliseconds */
4357
+ totalCost: number;
4358
+ /** Average execution time per query */
4359
+ averageCost: number;
4360
+ /** Timestamp of last query */
4361
+ lastQueried: number;
4362
+ /** Whether a compound index exists for this combination */
4363
+ hasCompoundIndex: boolean;
4364
+ }
4365
+ /**
4366
+ * Index type recommendation.
4367
+ */
4368
+ type RecommendedIndexType = 'hash' | 'navigable' | 'inverted' | 'compound';
4369
+ /**
4370
+ * Priority level for index suggestions.
4371
+ */
4372
+ type SuggestionPriority = 'high' | 'medium' | 'low';
4373
+ /**
4374
+ * Index suggestion generated by IndexAdvisor.
4375
+ */
4376
+ interface IndexSuggestion {
4377
+ /** Attribute to index (or compound key for compound indexes) */
4378
+ attribute: string;
4379
+ /** Recommended index type */
4380
+ indexType: RecommendedIndexType;
4381
+ /** Human-readable explanation */
4382
+ reason: string;
4383
+ /** Expected performance improvement multiplier */
4384
+ estimatedBenefit: number;
4385
+ /** Estimated memory overhead in bytes */
4386
+ estimatedCost: number;
4387
+ /** Priority based on query patterns */
4388
+ priority: SuggestionPriority;
4389
+ /** Query count that triggered this suggestion */
4390
+ queryCount: number;
4391
+ /** Average query cost in milliseconds */
4392
+ averageCost: number;
4393
+ /** For compound indexes: array of attribute names in order */
4394
+ compoundAttributes?: string[];
4395
+ }
4396
+ /**
4397
+ * Options for getting index suggestions.
4398
+ */
4399
+ interface IndexSuggestionOptions {
4400
+ /** Minimum query count to consider (default: 10) */
4401
+ minQueryCount?: number;
4402
+ /** Minimum average cost in ms to consider (default: 1) */
4403
+ minAverageCost?: number;
4404
+ /** Whether to exclude already indexed attributes (default: true) */
4405
+ excludeExistingIndexes?: boolean;
4406
+ /** Maximum number of suggestions to return (default: unlimited) */
4407
+ maxSuggestions?: number;
4408
+ }
4409
+ /**
4410
+ * Configuration for Index Advisor.
4411
+ */
4412
+ interface AdvisorConfig {
4413
+ /** Enable advisor mode (default: true) */
4414
+ enabled: boolean;
4415
+ /** Minimum query count before suggesting (default: 10) */
4416
+ minQueryCount?: number;
4417
+ /** Minimum average cost in ms to suggest (default: 1) */
4418
+ minAverageCost?: number;
4419
+ }
4420
+ /**
4421
+ * Callback for index creation events.
4422
+ */
4423
+ type IndexCreatedCallback = (attribute: string, indexType: RecommendedIndexType) => void;
4424
+ /**
4425
+ * Configuration for Auto-Index Manager.
4426
+ */
4427
+ interface AutoIndexConfig {
4428
+ /** Enable auto-indexing (default: false) */
4429
+ enabled: boolean;
4430
+ /** Number of queries before auto-creating index (default: 10) */
4431
+ threshold?: number;
4432
+ /** Maximum number of auto-created indexes (default: 20) */
4433
+ maxIndexes?: number;
4434
+ /** Callback when index is automatically created */
4435
+ onIndexCreated?: IndexCreatedCallback;
4436
+ }
4437
+ /**
4438
+ * Default indexing strategy.
4439
+ * - 'none': No automatic indexing (default)
4440
+ * - 'scalar': Index all top-level scalar (primitive) fields
4441
+ * - 'all': Index all fields including nested (not recommended)
4442
+ */
4443
+ type DefaultIndexingStrategy = 'none' | 'scalar' | 'all';
4444
+ /**
4445
+ * Complete adaptive indexing configuration.
4446
+ */
4447
+ interface AdaptiveIndexingConfig {
4448
+ /** Index Advisor configuration */
4449
+ advisor?: AdvisorConfig;
4450
+ /** Auto-Index Manager configuration */
4451
+ autoIndex?: AutoIndexConfig;
4452
+ }
4453
+ /**
4454
+ * Progress callback for lazy index building (Phase 9.01).
4455
+ */
4456
+ type IndexBuildProgressCallback = (attributeName: string, progress: number, // 0-100
4457
+ recordsProcessed: number, totalRecords: number) => void;
4458
+ /**
4459
+ * Extended options for IndexedLWWMap/IndexedORMap.
4460
+ */
4461
+ interface IndexedMapOptions {
4462
+ /** Adaptive indexing configuration */
4463
+ adaptiveIndexing?: AdaptiveIndexingConfig;
4464
+ /** Default indexing strategy (default: 'none') */
4465
+ defaultIndexing?: DefaultIndexingStrategy;
4466
+ /**
4467
+ * Enable lazy index building (Phase 9.01).
4468
+ * When true, indexes are not built until first query.
4469
+ * Default: false
4470
+ */
4471
+ lazyIndexBuilding?: boolean;
4472
+ /**
4473
+ * Callback for index building progress (Phase 9.01).
4474
+ * Called during lazy index materialization.
4475
+ */
4476
+ onIndexBuilding?: IndexBuildProgressCallback;
4477
+ }
4478
+
4479
+ /**
4480
+ * Lazy Index Types
4481
+ *
4482
+ * Types and interfaces for lazy index building (Phase 9.01).
4483
+ * Lazy indexes defer actual index construction until first query.
4484
+ *
4485
+ * @module query/indexes/lazy/types
4486
+ */
4487
+
4488
+ /**
4489
+ * Extended interface for lazy indexes.
4490
+ * Adds lazy-specific properties and methods.
4491
+ */
4492
+ interface LazyIndex<K, V, A = unknown> extends Index<K, V, A> {
4493
+ /**
4494
+ * Whether the index has been materialized (built).
4495
+ */
4496
+ readonly isBuilt: boolean;
4497
+ /**
4498
+ * Number of pending records awaiting materialization.
4499
+ */
4500
+ readonly pendingCount: number;
4501
+ /**
4502
+ * Force materialization of the index.
4503
+ * Called automatically on first query, but can be called manually.
4504
+ *
4505
+ * @param progressCallback - Optional progress callback
4506
+ */
4507
+ materialize(progressCallback?: IndexBuildProgressCallback): void;
4508
+ /**
4509
+ * Check if this is a lazy index wrapper.
4510
+ */
4511
+ readonly isLazy: true;
4512
+ }
4513
+ /**
4514
+ * Options for lazy index creation.
4515
+ */
4516
+ interface LazyIndexOptions {
4517
+ /**
4518
+ * Progress callback for index building.
4519
+ */
4520
+ onProgress?: IndexBuildProgressCallback;
4521
+ /**
4522
+ * Batch size for progress reporting.
4523
+ * Default: 1000
4524
+ */
4525
+ progressBatchSize?: number;
4526
+ }
4527
+
4528
+ /**
4529
+ * LazyHashIndex Implementation
4530
+ *
4531
+ * Hash-based index with deferred building (Phase 9.01).
4532
+ * Records are buffered until first query, then index is materialized.
4533
+ *
4534
+ * Benefits:
4535
+ * - Fast application startup (indexes built on-demand)
4536
+ * - Memory efficiency (unused indexes not built)
4537
+ * - Bulk import optimization (no index overhead during import)
4538
+ *
4539
+ * @module query/indexes/lazy/LazyHashIndex
4540
+ */
4541
+
4542
+ /**
4543
+ * Lazy hash-based index for O(1) equality lookups.
4544
+ * Defers index construction until first query.
4545
+ *
4546
+ * K = record key type, V = record value type, A = attribute value type
4547
+ */
4548
+ declare class LazyHashIndex<K, V, A> implements LazyIndex<K, V, A> {
4549
+ readonly attribute: Attribute<V, A>;
4550
+ readonly type: "hash";
4551
+ readonly isLazy: true;
4552
+ /** Underlying hash index (created on first query) */
4553
+ private innerIndex;
4554
+ /** Pending records before materialization */
4555
+ private pendingRecords;
4556
+ /** Track if index has been built */
4557
+ private built;
4558
+ /** Progress callback */
4559
+ private readonly onProgress?;
4560
+ /** Batch size for progress reporting */
4561
+ private readonly progressBatchSize;
4562
+ constructor(attribute: Attribute<V, A>, options?: LazyIndexOptions);
4563
+ get isBuilt(): boolean;
4564
+ get pendingCount(): number;
4565
+ getRetrievalCost(): number;
4566
+ supportsQuery(queryType: string): boolean;
4567
+ retrieve(query: IndexQuery<A>): ResultSet<K>;
4568
+ add(key: K, record: V): void;
4569
+ remove(key: K, record: V): void;
4570
+ update(key: K, oldRecord: V, newRecord: V): void;
4571
+ clear(): void;
4572
+ getStats(): IndexStats;
4573
+ /**
4574
+ * Force materialization of the index.
4575
+ * Called automatically on first query.
4576
+ */
4577
+ materialize(progressCallback?: IndexBuildProgressCallback): void;
4578
+ /**
4579
+ * Get the underlying HashIndex (for testing/debugging).
4580
+ * Returns null if not yet materialized.
4581
+ */
4582
+ getInnerIndex(): HashIndex<K, V, A> | null;
4583
+ }
4584
+
4585
+ /**
4586
+ * LazyNavigableIndex Implementation
4587
+ *
4588
+ * Sorted index with deferred building (Phase 9.01).
4589
+ * Records are buffered until first query, then index is materialized.
4590
+ *
4591
+ * Benefits:
4592
+ * - Fast application startup (indexes built on-demand)
4593
+ * - Memory efficiency (unused indexes not built)
4594
+ * - Bulk import optimization (no index overhead during import)
4595
+ *
4596
+ * @module query/indexes/lazy/LazyNavigableIndex
4597
+ */
4598
+
4599
+ /**
4600
+ * Lazy sorted index for O(log N) range queries.
4601
+ * Defers index construction until first query.
4602
+ *
4603
+ * K = record key type, V = record value type, A = attribute value type (must be orderable)
4604
+ */
4605
+ declare class LazyNavigableIndex<K, V, A extends string | number> implements LazyIndex<K, V, A> {
4606
+ readonly attribute: Attribute<V, A>;
4607
+ readonly type: "navigable";
4608
+ readonly isLazy: true;
4609
+ /** Underlying navigable index (created on first query) */
4610
+ private innerIndex;
4611
+ /** Pending records before materialization */
4612
+ private pendingRecords;
4613
+ /** Track if index has been built */
4614
+ private built;
4615
+ /** Custom comparator (stored for later index creation) */
4616
+ private readonly comparator?;
4617
+ /** Progress callback */
4618
+ private readonly onProgress?;
4619
+ /** Batch size for progress reporting */
4620
+ private readonly progressBatchSize;
4621
+ constructor(attribute: Attribute<V, A>, comparator?: Comparator<A>, options?: LazyIndexOptions);
4622
+ get isBuilt(): boolean;
4623
+ get pendingCount(): number;
4624
+ getRetrievalCost(): number;
4625
+ supportsQuery(queryType: string): boolean;
4626
+ retrieve(query: IndexQuery<A>): ResultSet<K>;
4627
+ add(key: K, record: V): void;
4628
+ remove(key: K, record: V): void;
4629
+ update(key: K, oldRecord: V, newRecord: V): void;
4630
+ clear(): void;
4631
+ getStats(): IndexStats;
4632
+ /**
4633
+ * Force materialization of the index.
4634
+ * Called automatically on first query.
4635
+ */
4636
+ materialize(progressCallback?: IndexBuildProgressCallback): void;
4637
+ /**
4638
+ * Get the underlying NavigableIndex (for testing/debugging).
4639
+ * Returns null if not yet materialized.
4640
+ */
4641
+ getInnerIndex(): NavigableIndex<K, V, A> | null;
4642
+ /**
4643
+ * Get the minimum indexed value.
4644
+ * Forces materialization if not built.
4645
+ */
4646
+ getMinValue(): A | undefined;
4647
+ /**
4648
+ * Get the maximum indexed value.
4649
+ * Forces materialization if not built.
4650
+ */
4651
+ getMaxValue(): A | undefined;
4652
+ }
4653
+
4654
+ /**
4655
+ * LazyInvertedIndex Implementation
4656
+ *
4657
+ * Full-text search index with deferred building (Phase 9.01).
4658
+ * Records are buffered until first query, then index is materialized.
4659
+ *
4660
+ * Benefits:
4661
+ * - Fast application startup (indexes built on-demand)
4662
+ * - Memory efficiency (unused indexes not built)
4663
+ * - Bulk import optimization (no index overhead during import)
4664
+ *
4665
+ * @module query/indexes/lazy/LazyInvertedIndex
4666
+ */
4667
+
4668
+ /**
4669
+ * Lazy inverted index for full-text search.
4670
+ * Defers index construction until first query.
4671
+ *
4672
+ * K = record key type, V = record value type, A = attribute value type (should be string)
4673
+ */
4674
+ declare class LazyInvertedIndex<K, V, A extends string = string> implements LazyIndex<K, V, A> {
4675
+ readonly attribute: Attribute<V, A>;
4676
+ readonly type: "inverted";
4677
+ readonly isLazy: true;
4678
+ /** Underlying inverted index (created on first query) */
4679
+ private innerIndex;
4680
+ /** Pending records before materialization */
4681
+ private pendingRecords;
4682
+ /** Track if index has been built */
4683
+ private built;
4684
+ /** Tokenization pipeline (stored for later index creation) */
4685
+ private readonly pipeline;
4686
+ /** Progress callback */
4687
+ private readonly onProgress?;
4688
+ /** Batch size for progress reporting */
4689
+ private readonly progressBatchSize;
4690
+ constructor(attribute: Attribute<V, A>, pipeline?: TokenizationPipeline, options?: LazyIndexOptions);
4691
+ get isBuilt(): boolean;
4692
+ get pendingCount(): number;
4693
+ getRetrievalCost(): number;
4694
+ supportsQuery(queryType: string): boolean;
4695
+ retrieve(query: IndexQuery<A>): ResultSet<K>;
4696
+ add(key: K, record: V): void;
4697
+ remove(key: K, record: V): void;
4698
+ update(key: K, oldRecord: V, newRecord: V): void;
4699
+ clear(): void;
4700
+ getStats(): IndexStats;
4701
+ /**
4702
+ * Get extended statistics for full-text index.
4703
+ * Forces materialization if not built.
4704
+ */
4705
+ getExtendedStats(): InvertedIndexStats;
4706
+ /**
4707
+ * Force materialization of the index.
4708
+ * Called automatically on first query.
4709
+ */
4710
+ materialize(progressCallback?: IndexBuildProgressCallback): void;
4711
+ /**
4712
+ * Get the underlying InvertedIndex (for testing/debugging).
4713
+ * Returns null if not yet materialized.
4714
+ */
4715
+ getInnerIndex(): InvertedIndex<K, V, A> | null;
4716
+ /**
4717
+ * Get the tokenization pipeline.
4718
+ */
4719
+ getPipeline(): TokenizationPipeline;
4720
+ /**
4721
+ * Check if a specific token exists in the index.
4722
+ * Forces materialization if not built.
4723
+ */
4724
+ hasToken(token: string): boolean;
4725
+ /**
4726
+ * Get the number of documents for a specific token.
4727
+ * Forces materialization if not built.
4728
+ */
4729
+ getTokenDocumentCount(token: string): number;
4730
+ }
4731
+
4167
4732
  /**
4168
4733
  * SetResultSet Implementation
4169
4734
  *
@@ -4614,6 +5179,8 @@ declare class LimitResultSet<K> implements ResultSet<K> {
4614
5179
  declare class IndexRegistry<K, V> {
4615
5180
  /** Indexes grouped by attribute name */
4616
5181
  private attributeIndexes;
5182
+ /** Compound indexes (Phase 9.03) - keyed by sorted attribute names */
5183
+ private compoundIndexes;
4617
5184
  /** Fallback index for full scan (optional) */
4618
5185
  private fallbackIndex;
4619
5186
  /**
@@ -4623,6 +5190,12 @@ declare class IndexRegistry<K, V> {
4623
5190
  * @param index - Index to register
4624
5191
  */
4625
5192
  addIndex<A>(index: Index<K, V, A>): void;
5193
+ /**
5194
+ * Register a compound index (Phase 9.03).
5195
+ *
5196
+ * @param index - Compound index to register
5197
+ */
5198
+ addCompoundIndex(index: CompoundIndex<K, V>): void;
4626
5199
  /**
4627
5200
  * Remove an index from the registry.
4628
5201
  *
@@ -4630,6 +5203,13 @@ declare class IndexRegistry<K, V> {
4630
5203
  * @returns true if index was found and removed
4631
5204
  */
4632
5205
  removeIndex<A>(index: Index<K, V, A>): boolean;
5206
+ /**
5207
+ * Remove a compound index (Phase 9.03).
5208
+ *
5209
+ * @param index - Compound index to remove
5210
+ * @returns true if index was found and removed
5211
+ */
5212
+ removeCompoundIndex(index: CompoundIndex<K, V>): boolean;
4633
5213
  /**
4634
5214
  * Get all indexes for an attribute.
4635
5215
  *
@@ -4673,6 +5253,31 @@ declare class IndexRegistry<K, V> {
4673
5253
  * @returns Array of matching indexes sorted by retrieval cost
4674
5254
  */
4675
5255
  findIndexes(attributeName: string, queryType: string): Index<K, V, unknown>[];
5256
+ /**
5257
+ * Find a compound index that covers the given attribute names (Phase 9.03).
5258
+ * The compound index must cover ALL the attributes (exact match or superset).
5259
+ *
5260
+ * @param attributeNames - Array of attribute names to search for
5261
+ * @returns Matching compound index or null
5262
+ */
5263
+ findCompoundIndex(attributeNames: string[]): CompoundIndex<K, V> | null;
5264
+ /**
5265
+ * Check if a compound index exists for the given attributes (Phase 9.03).
5266
+ *
5267
+ * @param attributeNames - Array of attribute names
5268
+ * @returns true if a compound index exists
5269
+ */
5270
+ hasCompoundIndex(attributeNames: string[]): boolean;
5271
+ /**
5272
+ * Get all compound indexes (Phase 9.03).
5273
+ *
5274
+ * @returns Array of all compound indexes
5275
+ */
5276
+ getCompoundIndexes(): CompoundIndex<K, V>[];
5277
+ /**
5278
+ * Create a compound key from attribute names (sorted for consistency).
5279
+ */
5280
+ private makeCompoundKey;
4676
5281
  /**
4677
5282
  * Set a fallback index for queries without a suitable index.
4678
5283
  * Typically a FallbackIndex that performs full scan.
@@ -4733,6 +5338,8 @@ interface IndexRegistryStats {
4733
5338
  totalIndexes: number;
4734
5339
  /** Number of indexed attributes */
4735
5340
  indexedAttributes: number;
5341
+ /** Number of compound indexes (Phase 9.03) */
5342
+ compoundIndexes?: number;
4736
5343
  /** Stats for each index */
4737
5344
  indexes: Array<{
4738
5345
  attribute: string;
@@ -4977,11 +5584,31 @@ declare class QueryOptimizer<K, V> {
4977
5584
  * Strategy: Find child with lowest cost, use as base, filter with rest.
4978
5585
  *
4979
5586
  * CQEngine "smallest first" strategy:
4980
- * 1. Sort children by merge cost
4981
- * 2. Use intersection if multiple indexes available
4982
- * 3. Apply remaining predicates as filters
5587
+ * 1. Check for CompoundIndex covering all eq children (Phase 9.03)
5588
+ * 2. Sort children by merge cost
5589
+ * 3. Use intersection if multiple indexes available
5590
+ * 4. Apply remaining predicates as filters
4983
5591
  */
4984
5592
  private optimizeAnd;
5593
+ /**
5594
+ * Try to use a CompoundIndex for an AND query (Phase 9.03).
5595
+ *
5596
+ * Returns a compound index scan step if:
5597
+ * 1. All children are simple 'eq' queries
5598
+ * 2. A CompoundIndex exists covering all queried attributes
5599
+ *
5600
+ * @param children - Children of the AND query
5601
+ * @returns IndexScanStep using CompoundIndex, or null if not applicable
5602
+ */
5603
+ private tryCompoundIndex;
5604
+ /**
5605
+ * Build values array for compound index query in correct attribute order.
5606
+ *
5607
+ * @param compoundIndex - The compound index to use
5608
+ * @param eqQueries - Array of 'eq' queries
5609
+ * @returns Values array in compound index order, or null if mismatch
5610
+ */
5611
+ private buildCompoundValues;
4985
5612
  /**
4986
5613
  * Optimize OR query.
4987
5614
  * Strategy: Union of all child results with deduplication.
@@ -5168,136 +5795,6 @@ interface LiveQueryManagerStats extends StandingQueryRegistryStats {
5168
5795
  totalSubscribers: number;
5169
5796
  }
5170
5797
 
5171
- /**
5172
- * Types for Adaptive Indexing System (Phase 8.02)
5173
- *
5174
- * Defines interfaces for query pattern tracking, index suggestions,
5175
- * and auto-indexing configuration.
5176
- *
5177
- * @module query/adaptive/types
5178
- */
5179
- /**
5180
- * Query type for pattern tracking.
5181
- * Matches the query types from QueryTypes.ts and indexes/types.ts
5182
- */
5183
- type TrackedQueryType = 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'in' | 'has' | 'contains' | 'containsAll' | 'containsAny';
5184
- /**
5185
- * Statistics for a single attribute + query type combination.
5186
- */
5187
- interface QueryStatistics {
5188
- /** Attribute name being queried */
5189
- attribute: string;
5190
- /** Type of query (eq, gt, between, etc.) */
5191
- queryType: TrackedQueryType;
5192
- /** Number of times this pattern was queried */
5193
- queryCount: number;
5194
- /** Cumulative execution time in milliseconds */
5195
- totalCost: number;
5196
- /** Average execution time per query */
5197
- averageCost: number;
5198
- /** Timestamp of last query */
5199
- lastQueried: number;
5200
- /** Estimated result size (max observed) */
5201
- estimatedCardinality: number;
5202
- /** Whether an index exists for this attribute */
5203
- hasIndex: boolean;
5204
- }
5205
- /**
5206
- * Index type recommendation.
5207
- */
5208
- type RecommendedIndexType = 'hash' | 'navigable' | 'inverted';
5209
- /**
5210
- * Priority level for index suggestions.
5211
- */
5212
- type SuggestionPriority = 'high' | 'medium' | 'low';
5213
- /**
5214
- * Index suggestion generated by IndexAdvisor.
5215
- */
5216
- interface IndexSuggestion {
5217
- /** Attribute to index */
5218
- attribute: string;
5219
- /** Recommended index type */
5220
- indexType: RecommendedIndexType;
5221
- /** Human-readable explanation */
5222
- reason: string;
5223
- /** Expected performance improvement multiplier */
5224
- estimatedBenefit: number;
5225
- /** Estimated memory overhead in bytes */
5226
- estimatedCost: number;
5227
- /** Priority based on query patterns */
5228
- priority: SuggestionPriority;
5229
- /** Query count that triggered this suggestion */
5230
- queryCount: number;
5231
- /** Average query cost in milliseconds */
5232
- averageCost: number;
5233
- }
5234
- /**
5235
- * Options for getting index suggestions.
5236
- */
5237
- interface IndexSuggestionOptions {
5238
- /** Minimum query count to consider (default: 10) */
5239
- minQueryCount?: number;
5240
- /** Minimum average cost in ms to consider (default: 1) */
5241
- minAverageCost?: number;
5242
- /** Whether to exclude already indexed attributes (default: true) */
5243
- excludeExistingIndexes?: boolean;
5244
- /** Maximum number of suggestions to return (default: unlimited) */
5245
- maxSuggestions?: number;
5246
- }
5247
- /**
5248
- * Configuration for Index Advisor.
5249
- */
5250
- interface AdvisorConfig {
5251
- /** Enable advisor mode (default: true) */
5252
- enabled: boolean;
5253
- /** Minimum query count before suggesting (default: 10) */
5254
- minQueryCount?: number;
5255
- /** Minimum average cost in ms to suggest (default: 1) */
5256
- minAverageCost?: number;
5257
- }
5258
- /**
5259
- * Callback for index creation events.
5260
- */
5261
- type IndexCreatedCallback = (attribute: string, indexType: RecommendedIndexType) => void;
5262
- /**
5263
- * Configuration for Auto-Index Manager.
5264
- */
5265
- interface AutoIndexConfig {
5266
- /** Enable auto-indexing (default: false) */
5267
- enabled: boolean;
5268
- /** Number of queries before auto-creating index (default: 10) */
5269
- threshold?: number;
5270
- /** Maximum number of auto-created indexes (default: 20) */
5271
- maxIndexes?: number;
5272
- /** Callback when index is automatically created */
5273
- onIndexCreated?: IndexCreatedCallback;
5274
- }
5275
- /**
5276
- * Default indexing strategy.
5277
- * - 'none': No automatic indexing (default)
5278
- * - 'scalar': Index all top-level scalar (primitive) fields
5279
- * - 'all': Index all fields including nested (not recommended)
5280
- */
5281
- type DefaultIndexingStrategy = 'none' | 'scalar' | 'all';
5282
- /**
5283
- * Complete adaptive indexing configuration.
5284
- */
5285
- interface AdaptiveIndexingConfig {
5286
- /** Index Advisor configuration */
5287
- advisor?: AdvisorConfig;
5288
- /** Auto-Index Manager configuration */
5289
- autoIndex?: AutoIndexConfig;
5290
- }
5291
- /**
5292
- * Extended options for IndexedLWWMap/IndexedORMap.
5293
- */
5294
- interface IndexedMapOptions {
5295
- /** Adaptive indexing configuration */
5296
- adaptiveIndexing?: AdaptiveIndexingConfig;
5297
- /** Default indexing strategy (default: 'none') */
5298
- defaultIndexing?: DefaultIndexingStrategy;
5299
- }
5300
-
5301
5798
  /**
5302
5799
  * QueryPatternTracker (Phase 8.02.1)
5303
5800
  *
@@ -5347,6 +5844,9 @@ interface QueryPatternTrackerOptions {
5347
5844
  * tracker.recordQuery('category', 'eq', 5.2, 100, false);
5348
5845
  * tracker.recordQuery('category', 'eq', 4.8, 100, false);
5349
5846
  *
5847
+ * // Record compound AND queries (Phase 9.03)
5848
+ * tracker.recordCompoundQuery(['status', 'category'], 10.5, 50, false);
5849
+ *
5350
5850
  * // Get statistics
5351
5851
  * const stats = tracker.getStatistics();
5352
5852
  * // [{ attribute: 'category', queryType: 'eq', queryCount: 2, averageCost: 5.0, ... }]
@@ -5354,6 +5854,7 @@ interface QueryPatternTrackerOptions {
5354
5854
  */
5355
5855
  declare class QueryPatternTracker {
5356
5856
  private stats;
5857
+ private compoundStats;
5357
5858
  private queryCounter;
5358
5859
  private readonly samplingRate;
5359
5860
  private readonly maxTrackedPatterns;
@@ -5369,6 +5870,42 @@ declare class QueryPatternTracker {
5369
5870
  * @param hasIndex - Whether an index was used
5370
5871
  */
5371
5872
  recordQuery(attribute: string, queryType: TrackedQueryType, executionTime: number, resultSize: number, hasIndex: boolean): void;
5873
+ /**
5874
+ * Record a compound (AND) query execution for pattern tracking (Phase 9.03).
5875
+ *
5876
+ * @param attributes - Array of attribute names being queried together
5877
+ * @param executionTime - Query execution time in milliseconds
5878
+ * @param resultSize - Number of results returned
5879
+ * @param hasCompoundIndex - Whether a compound index was used
5880
+ */
5881
+ recordCompoundQuery(attributes: string[], executionTime: number, resultSize: number, hasCompoundIndex: boolean): void;
5882
+ /**
5883
+ * Get all compound query statistics (Phase 9.03).
5884
+ *
5885
+ * @returns Array of compound query statistics, sorted by query count descending
5886
+ */
5887
+ getCompoundStatistics(): CompoundQueryStatistics[];
5888
+ /**
5889
+ * Get compound statistics for a specific attribute combination.
5890
+ *
5891
+ * @param attributes - Array of attribute names
5892
+ * @returns Compound query statistics or undefined
5893
+ */
5894
+ getCompoundStats(attributes: string[]): CompoundQueryStatistics | undefined;
5895
+ /**
5896
+ * Check if attributes appear in any tracked compound queries.
5897
+ *
5898
+ * @param attribute - The attribute name to check
5899
+ * @returns True if attribute is part of any compound query pattern
5900
+ */
5901
+ isInCompoundPattern(attribute: string): boolean;
5902
+ /**
5903
+ * Update compound index status.
5904
+ *
5905
+ * @param attributes - Array of attribute names
5906
+ * @param hasCompoundIndex - Whether a compound index exists
5907
+ */
5908
+ updateCompoundIndexStatus(attributes: string[], hasCompoundIndex: boolean): void;
5372
5909
  /**
5373
5910
  * Get all query statistics.
5374
5911
  *
@@ -5435,6 +5972,7 @@ declare class QueryPatternTracker {
5435
5972
  */
5436
5973
  getTrackingInfo(): {
5437
5974
  patternsTracked: number;
5975
+ compoundPatternsTracked: number;
5438
5976
  totalQueries: number;
5439
5977
  samplingRate: number;
5440
5978
  memoryEstimate: number;
@@ -5447,6 +5985,14 @@ declare class QueryPatternTracker {
5447
5985
  * Prune stale statistics older than TTL.
5448
5986
  */
5449
5987
  private pruneStale;
5988
+ /**
5989
+ * Evict the oldest compound query entry (Phase 9.03).
5990
+ */
5991
+ private evictOldestCompound;
5992
+ /**
5993
+ * Prune stale compound statistics (Phase 9.03).
5994
+ */
5995
+ private pruneStaleCompound;
5450
5996
  }
5451
5997
 
5452
5998
  /**
@@ -5556,6 +6102,52 @@ declare class IndexAdvisor {
5556
6102
  * Generate human-readable reason for the suggestion.
5557
6103
  */
5558
6104
  private generateReason;
6105
+ /**
6106
+ * Get compound index suggestions based on AND query patterns.
6107
+ *
6108
+ * @param options - Suggestion options
6109
+ * @returns Array of compound index suggestions
6110
+ */
6111
+ getCompoundSuggestions(options?: IndexSuggestionOptions): IndexSuggestion[];
6112
+ /**
6113
+ * Get a suggestion for a specific compound attribute combination.
6114
+ *
6115
+ * @param attributes - Array of attribute names
6116
+ * @returns Compound index suggestion or null if not recommended
6117
+ */
6118
+ getCompoundSuggestionFor(attributes: string[]): IndexSuggestion | null;
6119
+ /**
6120
+ * Check if a compound index should be created for the given attributes.
6121
+ *
6122
+ * @param attributes - Array of attribute names
6123
+ * @param threshold - Minimum query count threshold
6124
+ * @returns True if compound index should be created
6125
+ */
6126
+ shouldCreateCompoundIndex(attributes: string[], threshold?: number): boolean;
6127
+ /**
6128
+ * Generate a suggestion for a compound query pattern.
6129
+ */
6130
+ private generateCompoundSuggestion;
6131
+ /**
6132
+ * Estimate performance benefit of adding a compound index.
6133
+ *
6134
+ * Compound indexes provide significant speedup for AND queries:
6135
+ * - Eliminates intersection operations (100-1000× for each attribute)
6136
+ * - Single O(1) lookup instead of multiple index scans
6137
+ */
6138
+ private estimateCompoundBenefit;
6139
+ /**
6140
+ * Estimate memory cost of adding a compound index.
6141
+ */
6142
+ private estimateCompoundMemoryCost;
6143
+ /**
6144
+ * Calculate priority for compound index suggestion.
6145
+ */
6146
+ private calculateCompoundPriority;
6147
+ /**
6148
+ * Generate human-readable reason for compound index suggestion.
6149
+ */
6150
+ private generateCompoundReason;
5559
6151
  }
5560
6152
 
5561
6153
  /**
@@ -5742,27 +6334,30 @@ declare class IndexedLWWMap<K extends string, V> extends LWWMap<K, V> {
5742
6334
  constructor(hlc: HLC, options?: IndexedMapOptions);
5743
6335
  /**
5744
6336
  * Add a hash index on an attribute.
6337
+ * If lazyIndexBuilding is enabled, creates a LazyHashIndex instead.
5745
6338
  *
5746
6339
  * @param attribute - Attribute to index
5747
- * @returns Created HashIndex
6340
+ * @returns Created HashIndex (or LazyHashIndex)
5748
6341
  */
5749
- addHashIndex<A>(attribute: Attribute<V, A>): HashIndex<K, V, A>;
6342
+ addHashIndex<A>(attribute: Attribute<V, A>): HashIndex<K, V, A> | LazyHashIndex<K, V, A>;
5750
6343
  /**
5751
6344
  * Add a navigable index on an attribute.
5752
6345
  * Navigable indexes support range queries (gt, gte, lt, lte, between).
6346
+ * If lazyIndexBuilding is enabled, creates a LazyNavigableIndex instead.
5753
6347
  *
5754
6348
  * @param attribute - Attribute to index
5755
6349
  * @param comparator - Optional custom comparator
5756
- * @returns Created NavigableIndex
6350
+ * @returns Created NavigableIndex (or LazyNavigableIndex)
5757
6351
  */
5758
- addNavigableIndex<A extends string | number>(attribute: Attribute<V, A>, comparator?: (a: A, b: A) => number): NavigableIndex<K, V, A>;
6352
+ addNavigableIndex<A extends string | number>(attribute: Attribute<V, A>, comparator?: (a: A, b: A) => number): NavigableIndex<K, V, A> | LazyNavigableIndex<K, V, A>;
5759
6353
  /**
5760
6354
  * Add an inverted index for full-text search on an attribute.
5761
6355
  * Inverted indexes support text search queries (contains, containsAll, containsAny).
6356
+ * If lazyIndexBuilding is enabled, creates a LazyInvertedIndex instead.
5762
6357
  *
5763
6358
  * @param attribute - Text attribute to index
5764
6359
  * @param pipeline - Optional custom tokenization pipeline
5765
- * @returns Created InvertedIndex
6360
+ * @returns Created InvertedIndex (or LazyInvertedIndex)
5766
6361
  *
5767
6362
  * @example
5768
6363
  * ```typescript
@@ -5773,7 +6368,7 @@ declare class IndexedLWWMap<K extends string, V> extends LWWMap<K, V> {
5773
6368
  * products.query({ type: 'contains', attribute: 'name', value: 'wireless' });
5774
6369
  * ```
5775
6370
  */
5776
- addInvertedIndex<A extends string = string>(attribute: Attribute<V, A>, pipeline?: TokenizationPipeline): InvertedIndex<K, V, A>;
6371
+ addInvertedIndex<A extends string = string>(attribute: Attribute<V, A>, pipeline?: TokenizationPipeline): InvertedIndex<K, V, A> | LazyInvertedIndex<K, V, A>;
5777
6372
  /**
5778
6373
  * Add a custom index.
5779
6374
  *
@@ -5984,6 +6579,26 @@ declare class IndexedLWWMap<K extends string, V> extends LWWMap<K, V> {
5984
6579
  * Check if auto-indexing is enabled.
5985
6580
  */
5986
6581
  isAutoIndexingEnabled(): boolean;
6582
+ /**
6583
+ * Check if lazy index building is enabled.
6584
+ */
6585
+ isLazyIndexingEnabled(): boolean;
6586
+ /**
6587
+ * Force materialization of all lazy indexes.
6588
+ * Useful to pre-warm indexes before critical operations.
6589
+ *
6590
+ * @param progressCallback - Optional progress callback
6591
+ */
6592
+ materializeAllIndexes(progressCallback?: IndexBuildProgressCallback): void;
6593
+ /**
6594
+ * Get count of pending records across all lazy indexes.
6595
+ * Returns 0 if no lazy indexes or all are materialized.
6596
+ */
6597
+ getPendingIndexCount(): number;
6598
+ /**
6599
+ * Check if any lazy indexes are still pending (not built).
6600
+ */
6601
+ hasUnbuiltIndexes(): boolean;
5987
6602
  /**
5988
6603
  * Track query pattern for adaptive indexing.
5989
6604
  */