UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

114 lines (113 loc) 4.06 kB
import { compileSingleRowExpression } from "../query/compiler/evaluators.js"; import { DEFAULT_COMPARE_OPTIONS, deepEquals } from "../utils.js"; function normalizeLocaleOptions(options) { return Object.fromEntries( Object.entries(options ?? {}).filter(([, value]) => value !== void 0) ); } function canonicalizeLocale(locale) { return locale === void 0 ? void 0 : Intl.getCanonicalLocales(locale)[0]; } function usesLocaleCollation(options) { return (options.stringSort ?? DEFAULT_COMPARE_OPTIONS.stringSort) === `locale`; } class BaseIndex { constructor(id, expression, name, options) { this.hasCustomComparator = false; this.rangeValueDomains = /* @__PURE__ */ new Map(); this.id = id; this.expression = expression; this.compareOptions = DEFAULT_COMPARE_OPTIONS; this.name = name; this.initialize(options); } // Common methods rangeQueryReversed(options = {}) { const { from, to, fromInclusive = true, toInclusive = true } = options; const reversed = {}; if (`to` in options) { reversed.from = to; reversed.fromInclusive = toInclusive; } if (`from` in options) { reversed.to = from; reversed.toInclusive = fromInclusive; } return this.rangeQuery(reversed); } supports(operation) { return this.supportedOperations.has(operation); } get supportsRangeOptimization() { return !this.hasCustomComparator; } addRangeValue(value) { const domain = rangeValueDomain(value); if (domain === void 0) return; this.rangeValueDomains.set( domain, (this.rangeValueDomains.get(domain) ?? 0) + 1 ); } removeRangeValue(value) { const domain = rangeValueDomain(value); if (domain === void 0) return; const count = this.rangeValueDomains.get(domain); if (count === void 0) return; if (count === 1) this.rangeValueDomains.delete(domain); else this.rangeValueDomains.set(domain, count - 1); } clearRangeValues() { this.rangeValueDomains.clear(); } canOptimizeRangeFor(value) { const domain = rangeValueDomain(value); if (domain === void 0) return true; if (!isNativeRangeDomain(domain)) return false; return this.rangeValueDomains.size === 0 || this.rangeValueDomains.size === 1 && this.rangeValueDomains.has(domain); } matchesField(fieldPath) { return this.expression.type === `ref` && this.expression.path.length === fieldPath.length && this.expression.path.every((part, i) => part === fieldPath[i]); } /** * Checks if the compare options match the index's compare options. * The direction is ignored because the index can be reversed if the direction is different. */ matchesCompareOptions(compareOptions) { const indexCompareOptions = this.compareOptions; const indexUsesLocale = usesLocaleCollation(indexCompareOptions); const requestedUsesLocale = usesLocaleCollation(compareOptions); if (indexCompareOptions.nulls !== compareOptions.nulls || indexUsesLocale !== requestedUsesLocale) { return false; } if (!indexUsesLocale || !requestedUsesLocale) { return true; } return canonicalizeLocale(indexCompareOptions.locale) === canonicalizeLocale(compareOptions.locale) && deepEquals( normalizeLocaleOptions(indexCompareOptions.localeOptions), normalizeLocaleOptions(compareOptions.localeOptions) ); } /** * Checks if the index matches the provided direction. */ matchesDirection(direction) { return this.compareOptions.direction === direction; } evaluateIndexExpression(item) { const evaluator = this.compiledIndexEvaluator ??= compileSingleRowExpression(this.expression); return evaluator(item); } } function rangeValueDomain(value) { if (value == null) return void 0; if (value instanceof Date) return `date`; return typeof value; } function isNativeRangeDomain(domain) { return domain === `number` || domain === `bigint` || domain === `boolean` || domain === `string` || domain === `date`; } export { BaseIndex }; //# sourceMappingURL=base-index.js.map