@tanstack/db
Version:
A reactive client store for building super fast apps on sync
1 lines • 7.95 kB
Source Map (JSON)
{"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<\n TKey extends string | number = string | number,\n> implements IndexInterface<TKey> {\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,UAEY;AAAA,EAWhC,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;;;"}