UNPKG

@tanstack/db

Version:

A reactive client store for building super fast apps on sync

1 lines 20.1 kB
{"version":3,"file":"basic-index.cjs","sources":["../../../src/indexes/basic-index.ts"],"sourcesContent":["import { compareKeys } from '@tanstack/db-ivm'\nimport {\n areSameValueZeroEqual,\n defaultComparator,\n makeComparator,\n normalizeValue,\n} from '../utils/comparison.js'\nimport {\n compareKeysReversed,\n findInsertPositionInArray,\n} from '../utils/array-utils.js'\nimport { BaseIndex } from './base-index.js'\nimport type { CompareOptions } from '../query/builder/types.js'\nimport type { BasicExpression } from '../query/ir.js'\nimport type { IndexOperation } from './base-index.js'\n\n/**\n * Options for range queries\n */\nexport interface RangeQueryOptions {\n from?: any\n to?: any\n fromInclusive?: boolean\n toInclusive?: boolean\n}\n\n/**\n * Options for Basic index\n */\nexport interface BasicIndexOptions {\n compareFn?: (a: any, b: any) => number\n compareOptions?: CompareOptions\n}\n\n/**\n * Basic index using Map + sorted Array.\n *\n * - Map for O(1) equality lookups\n * - Sorted Array for O(log n) range queries via binary search\n * - O(n) updates to maintain sort order\n *\n * Simpler and smaller than BTreeIndex, good for read-heavy workloads.\n * Use BTreeIndex for write-heavy workloads with large collections.\n */\nexport class BasicIndex<\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 // Map for O(1) equality lookups: indexedValue -> Set of PKs\n private valueMap = new Map<any, Set<TKey>>()\n // Sorted array of unique indexed values for range queries\n private sortedValues: Array<any> = []\n // Set of all indexed PKs\n private indexedKeys = new Set<TKey>()\n // Comparator function\n private compareFn: (a: any, b: any) => number = defaultComparator\n\n constructor(\n id: number,\n expression: BasicExpression,\n name?: string,\n options?: any,\n ) {\n super(id, expression, name, options)\n if (options?.compareOptions) {\n this.compareOptions = options!.compareOptions\n }\n this.compareFn = options?.compareFn ?? makeComparator(this.compareOptions)\n this.hasCustomComparator = options?.compareFn != null\n }\n\n protected initialize(_options?: BasicIndexOptions): 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 { cause: error },\n )\n }\n\n const normalizedValue = normalizeValue(indexedValue)\n\n this.addToBucket(key, normalizedValue)\n this.addRangeValue(indexedValue)\n\n this.indexedKeys.add(key)\n }\n\n private addToBucket(key: TKey, normalizedValue: unknown): void {\n const keySet = this.valueMap.get(normalizedValue)\n if (keySet) {\n // Value already exists, just add the key to the set\n keySet.add(key)\n } else {\n // New value - add to map and insert into sorted array\n this.valueMap.set(normalizedValue, new Set([key]))\n\n // Insert into sorted position\n const insertIdx = findInsertPositionInArray(\n this.sortedValues,\n normalizedValue,\n this.compareFn,\n )\n this.sortedValues.splice(insertIdx, 0, normalizedValue)\n }\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 this.indexedKeys.delete(key)\n return\n }\n\n const normalizedValue = normalizeValue(indexedValue)\n\n this.removeFromBucket(key, normalizedValue)\n this.removeRangeValue(indexedValue)\n\n this.indexedKeys.delete(key)\n }\n\n private removeFromBucket(key: TKey, normalizedValue: unknown): void {\n const keySet = this.valueMap.get(normalizedValue)\n if (keySet) {\n keySet.delete(key)\n\n if (keySet.size === 0) {\n // No more keys for this value, remove from map and sorted array\n this.valueMap.delete(normalizedValue)\n let sortedIndex = findInsertPositionInArray(\n this.sortedValues,\n normalizedValue,\n this.compareFn,\n )\n // Distinct equality keys may share one comparator position.\n while (\n sortedIndex < this.sortedValues.length &&\n this.compareFn(this.sortedValues[sortedIndex], normalizedValue) === 0\n ) {\n if (\n areSameValueZeroEqual(\n this.sortedValues[sortedIndex],\n normalizedValue,\n )\n ) {\n this.sortedValues.splice(sortedIndex, 1)\n break\n }\n sortedIndex++\n }\n }\n }\n }\n\n /**\n * Updates a value in the index\n */\n update(key: TKey, oldItem: any, newItem: any): void {\n let oldIndexedValue: unknown\n let newIndexedValue: unknown\n try {\n oldIndexedValue = this.evaluateIndexExpression(oldItem)\n newIndexedValue = this.evaluateIndexExpression(newItem)\n } catch {\n this.remove(key, oldItem)\n this.add(key, newItem)\n return\n }\n\n const oldValue = normalizeValue(oldIndexedValue)\n const newValue = normalizeValue(newIndexedValue)\n if (\n areSameValueZeroEqual(oldValue, newValue) &&\n this.valueMap.get(newValue)?.has(key) &&\n this.indexedKeys.has(key)\n ) {\n this.removeRangeValue(oldIndexedValue)\n this.addRangeValue(newIndexedValue)\n return\n }\n\n this.removeFromBucket(key, oldValue)\n this.removeRangeValue(oldIndexedValue)\n this.addToBucket(key, newValue)\n this.addRangeValue(newIndexedValue)\n this.indexedKeys.add(key)\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 // Collect all entries first\n const entriesArray: Array<{ key: TKey; value: any }> = []\n for (const [key, item] of entries) {\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 { cause: error },\n )\n }\n entriesArray.push({ key, value: normalizeValue(indexedValue) })\n this.addRangeValue(indexedValue)\n this.indexedKeys.add(key)\n }\n\n // Group by value\n for (const { key, value } of entriesArray) {\n if (this.valueMap.has(value)) {\n this.valueMap.get(value)!.add(key)\n } else {\n this.valueMap.set(value, new Set([key]))\n }\n }\n\n // Build sorted array from unique values\n this.sortedValues = Array.from(this.valueMap.keys()).sort(this.compareFn)\n }\n\n /**\n * Clears all data from the index\n */\n clear(): void {\n this.valueMap.clear()\n this.sortedValues = []\n this.indexedKeys.clear()\n this.clearRangeValues()\n }\n\n /**\n * Performs a lookup operation\n */\n lookup(operation: IndexOperation, value: any): Set<TKey> {\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 BasicIndex`)\n }\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 /**\n * Performs an equality lookup - O(1)\n */\n equalityLookup(value: any): Set<TKey> {\n const normalizedValue = normalizeValue(value)\n return this.valueMap.get(normalizedValue) ?? new Set()\n }\n\n /**\n * Performs a range query using binary search - O(log n + m)\n */\n rangeQuery(options: RangeQueryOptions = {}): Set<TKey> {\n const { from, to, fromInclusive = true, toInclusive = true } = options\n const result = new Set<TKey>()\n\n if (this.sortedValues.length === 0) {\n return result\n }\n\n const normalizedFrom = normalizeValue(from)\n const normalizedTo = normalizeValue(to)\n const hasFrom = `from` in options\n const hasTo = `to` in options\n\n // Find start index\n let startIdx = 0\n if (hasFrom) {\n startIdx = findInsertPositionInArray(\n this.sortedValues,\n normalizedFrom,\n this.compareFn,\n )\n // Comparator-equal values form one range boundary even when they are\n // distinct equality keys.\n while (\n !fromInclusive &&\n startIdx < this.sortedValues.length &&\n this.compareFn(this.sortedValues[startIdx], normalizedFrom) === 0\n ) {\n startIdx++\n }\n }\n\n // Find end index\n let endIdx = this.sortedValues.length\n if (hasTo) {\n endIdx = findInsertPositionInArray(\n this.sortedValues,\n normalizedTo,\n this.compareFn,\n )\n // Include the whole comparator group at an inclusive upper boundary.\n while (\n toInclusive &&\n endIdx < this.sortedValues.length &&\n this.compareFn(this.sortedValues[endIdx], normalizedTo) === 0\n ) {\n endIdx++\n }\n }\n\n // Collect all keys in range\n for (let i = startIdx; i < endIdx; i++) {\n const keys = this.valueMap.get(this.sortedValues[i])\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n\n return result\n }\n\n /**\n * Returns the next n items in sorted order\n */\n take(n: number, from: any, filterFn?: (key: TKey) => boolean): Array<TKey> {\n const normalizedFrom = normalizeValue(from)\n let startIdx = findInsertPositionInArray(\n this.sortedValues,\n normalizedFrom,\n this.compareFn,\n )\n // Skip past the 'from' value (exclusive)\n while (\n startIdx < this.sortedValues.length &&\n this.compareFn(this.sortedValues[startIdx], normalizedFrom) <= 0\n ) {\n startIdx++\n }\n\n return this.takeFromIndex(n, startIdx, 1, filterFn)\n }\n\n /**\n * Returns the next n items in reverse sorted order\n */\n takeReversed(\n n: number,\n from: any,\n filterFn?: (key: TKey) => boolean,\n ): Array<TKey> {\n const normalizedFrom = normalizeValue(from)\n let startIdx =\n findInsertPositionInArray(\n this.sortedValues,\n normalizedFrom,\n this.compareFn,\n ) - 1\n // Skip past the 'from' value (exclusive)\n while (\n startIdx >= 0 &&\n this.compareFn(this.sortedValues[startIdx], normalizedFrom) >= 0\n ) {\n startIdx--\n }\n\n return this.takeFromIndex(n, startIdx, -1, filterFn)\n }\n\n /**\n * Returns the first n items in sorted order (from the start)\n */\n takeFromStart(n: number, filterFn?: (key: TKey) => boolean): Array<TKey> {\n return this.takeFromIndex(n, 0, 1, filterFn)\n }\n\n /**\n * Returns the first n items in reverse sorted order (from the end)\n */\n takeReversedFromEnd(\n n: number,\n filterFn?: (key: TKey) => boolean,\n ): Array<TKey> {\n return this.takeFromIndex(n, this.sortedValues.length - 1, -1, filterFn)\n }\n\n private takeFromIndex(\n n: number,\n startIndex: number,\n step: 1 | -1,\n filterFn?: (key: TKey) => boolean,\n ): Array<TKey> {\n const result: Array<TKey> = []\n let index = startIndex\n while (\n index >= 0 &&\n index < this.sortedValues.length &&\n result.length < n\n ) {\n const groupValue = this.sortedValues[index]\n const groupKeys: Array<TKey> = []\n do {\n for (const key of this.valueMap.get(this.sortedValues[index]) ?? []) {\n groupKeys.push(key)\n }\n index += step\n } while (\n index >= 0 &&\n index < this.sortedValues.length &&\n this.compareFn(this.sortedValues[index], groupValue) === 0\n )\n groupKeys.sort(step === 1 ? compareKeys : compareKeysReversed)\n for (const key of groupKeys) {\n if (filterFn?.(key) ?? true) result.push(key)\n if (result.length >= n) break\n }\n }\n return result\n }\n\n /**\n * Performs an IN array lookup - O(k) where k is values.length\n */\n inArrayLookup(values: Array<any>): Set<TKey> {\n const result = new Set<TKey>()\n\n for (const value of values) {\n const normalizedValue = normalizeValue(value)\n const keys = this.valueMap.get(normalizedValue)\n if (keys) {\n keys.forEach((key) => result.add(key))\n }\n }\n\n return result\n }\n}\n"],"names":["BaseIndex","defaultComparator","makeComparator","normalizeValue","findInsertPositionInArray","areSameValueZeroEqual","compareKeys","compareKeysReversed"],"mappings":";;;;;;AA4CO,MAAM,mBAEHA,UAAAA,UAAgB;AAAA,EAmBxB,YACE,IACA,YACA,MACA,SACA;AACA,UAAM,IAAI,YAAY,MAAM,OAAO;AAxBrC,SAAgB,0CAA0B,IAAoB;AAAA,MAC5D;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,CACD;AAGD,SAAQ,+BAAe,IAAA;AAEvB,SAAQ,eAA2B,CAAA;AAEnC,SAAQ,kCAAkB,IAAA;AAE1B,SAAQ,YAAwCC,WAAAA;AAS9C,QAAI,SAAS,gBAAgB;AAC3B,WAAK,iBAAiB,QAAS;AAAA,IACjC;AACA,SAAK,YAAY,SAAS,aAAaC,WAAAA,eAAe,KAAK,cAAc;AACzE,SAAK,sBAAsB,SAAS,aAAa;AAAA,EACnD;AAAA,EAEU,WAAW,UAAoC;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA,EAK1D,IAAI,KAAW,MAAiB;AAC9B,QAAI;AACJ,QAAI;AACF,qBAAe,KAAK,wBAAwB,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,+CAA+C,GAAG,KAAK,KAAK;AAAA,QAC5D,EAAE,OAAO,MAAA;AAAA,MAAM;AAAA,IAEnB;AAEA,UAAM,kBAAkBC,WAAAA,eAAe,YAAY;AAEnD,SAAK,YAAY,KAAK,eAAe;AACrC,SAAK,cAAc,YAAY;AAE/B,SAAK,YAAY,IAAI,GAAG;AAAA,EAC1B;AAAA,EAEQ,YAAY,KAAW,iBAAgC;AAC7D,UAAM,SAAS,KAAK,SAAS,IAAI,eAAe;AAChD,QAAI,QAAQ;AAEV,aAAO,IAAI,GAAG;AAAA,IAChB,OAAO;AAEL,WAAK,SAAS,IAAI,iBAAiB,oBAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AAGjD,YAAM,YAAYC,WAAAA;AAAAA,QAChB,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAEP,WAAK,aAAa,OAAO,WAAW,GAAG,eAAe;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAW,MAAiB;AACjC,QAAI;AACJ,QAAI;AACF,qBAAe,KAAK,wBAAwB,IAAI;AAAA,IAClD,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,+CAA+C,GAAG;AAAA,QAClD;AAAA,MAAA;AAEF,WAAK,YAAY,OAAO,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,kBAAkBD,WAAAA,eAAe,YAAY;AAEnD,SAAK,iBAAiB,KAAK,eAAe;AAC1C,SAAK,iBAAiB,YAAY;AAElC,SAAK,YAAY,OAAO,GAAG;AAAA,EAC7B;AAAA,EAEQ,iBAAiB,KAAW,iBAAgC;AAClE,UAAM,SAAS,KAAK,SAAS,IAAI,eAAe;AAChD,QAAI,QAAQ;AACV,aAAO,OAAO,GAAG;AAEjB,UAAI,OAAO,SAAS,GAAG;AAErB,aAAK,SAAS,OAAO,eAAe;AACpC,YAAI,cAAcC,WAAAA;AAAAA,UAChB,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,QAAA;AAGP,eACE,cAAc,KAAK,aAAa,UAChC,KAAK,UAAU,KAAK,aAAa,WAAW,GAAG,eAAe,MAAM,GACpE;AACA,cACEC,WAAAA;AAAAA,YACE,KAAK,aAAa,WAAW;AAAA,YAC7B;AAAA,UAAA,GAEF;AACA,iBAAK,aAAa,OAAO,aAAa,CAAC;AACvC;AAAA,UACF;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,KAAW,SAAc,SAAoB;AAClD,QAAI;AACJ,QAAI;AACJ,QAAI;AACF,wBAAkB,KAAK,wBAAwB,OAAO;AACtD,wBAAkB,KAAK,wBAAwB,OAAO;AAAA,IACxD,QAAQ;AACN,WAAK,OAAO,KAAK,OAAO;AACxB,WAAK,IAAI,KAAK,OAAO;AACrB;AAAA,IACF;AAEA,UAAM,WAAWF,WAAAA,eAAe,eAAe;AAC/C,UAAM,WAAWA,WAAAA,eAAe,eAAe;AAC/C,QACEE,WAAAA,sBAAsB,UAAU,QAAQ,KACxC,KAAK,SAAS,IAAI,QAAQ,GAAG,IAAI,GAAG,KACpC,KAAK,YAAY,IAAI,GAAG,GACxB;AACA,WAAK,iBAAiB,eAAe;AACrC,WAAK,cAAc,eAAe;AAClC;AAAA,IACF;AAEA,SAAK,iBAAiB,KAAK,QAAQ;AACnC,SAAK,iBAAiB,eAAe;AACrC,SAAK,YAAY,KAAK,QAAQ;AAC9B,SAAK,cAAc,eAAe;AAClC,SAAK,YAAY,IAAI,GAAG;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAsC;AAC1C,SAAK,MAAA;AAGL,UAAM,eAAiD,CAAA;AACvD,eAAW,CAAC,KAAK,IAAI,KAAK,SAAS;AACjC,UAAI;AACJ,UAAI;AACF,uBAAe,KAAK,wBAAwB,IAAI;AAAA,MAClD,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,+CAA+C,GAAG,KAAK,KAAK;AAAA,UAC5D,EAAE,OAAO,MAAA;AAAA,QAAM;AAAA,MAEnB;AACA,mBAAa,KAAK,EAAE,KAAK,OAAOF,WAAAA,eAAe,YAAY,GAAG;AAC9D,WAAK,cAAc,YAAY;AAC/B,WAAK,YAAY,IAAI,GAAG;AAAA,IAC1B;AAGA,eAAW,EAAE,KAAK,MAAA,KAAW,cAAc;AACzC,UAAI,KAAK,SAAS,IAAI,KAAK,GAAG;AAC5B,aAAK,SAAS,IAAI,KAAK,EAAG,IAAI,GAAG;AAAA,MACnC,OAAO;AACL,aAAK,SAAS,IAAI,OAAO,oBAAI,IAAI,CAAC,GAAG,CAAC,CAAC;AAAA,MACzC;AAAA,IACF;AAGA,SAAK,eAAe,MAAM,KAAK,KAAK,SAAS,MAAM,EAAE,KAAK,KAAK,SAAS;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,SAAS,MAAA;AACd,SAAK,eAAe,CAAA;AACpB,SAAK,YAAY,MAAA;AACjB,SAAK,iBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAA2B,OAAuB;AACvD,QAAI;AAEJ,YAAQ,WAAA;AAAA,MACN,KAAK;AACH,iBAAS,KAAK,eAAe,KAAK;AAClC;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,WAAW,EAAE,MAAM,OAAO,eAAe,OAAO;AAC9D;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,WAAW,EAAE,MAAM,OAAO,eAAe,MAAM;AAC7D;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,WAAW,EAAE,IAAI,OAAO,aAAa,OAAO;AAC1D;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,WAAW,EAAE,IAAI,OAAO,aAAa,MAAM;AACzD;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,cAAc,KAAK;AACjC;AAAA,MACF;AACE,cAAM,IAAI,MAAM,aAAa,SAAS,8BAA8B;AAAA,IAAA;AAExE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAmB;AACrB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,OAAuB;AACpC,UAAM,kBAAkBA,WAAAA,eAAe,KAAK;AAC5C,WAAO,KAAK,SAAS,IAAI,eAAe,yBAAS,IAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,UAA6B,IAAe;AACrD,UAAM,EAAE,MAAM,IAAI,gBAAgB,MAAM,cAAc,SAAS;AAC/D,UAAM,6BAAa,IAAA;AAEnB,QAAI,KAAK,aAAa,WAAW,GAAG;AAClC,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiBA,WAAAA,eAAe,IAAI;AAC1C,UAAM,eAAeA,WAAAA,eAAe,EAAE;AACtC,UAAM,UAAU,UAAU;AAC1B,UAAM,QAAQ,QAAQ;AAGtB,QAAI,WAAW;AACf,QAAI,SAAS;AACX,iBAAWC,WAAAA;AAAAA,QACT,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAIP,aACE,CAAC,iBACD,WAAW,KAAK,aAAa,UAC7B,KAAK,UAAU,KAAK,aAAa,QAAQ,GAAG,cAAc,MAAM,GAChE;AACA;AAAA,MACF;AAAA,IACF;AAGA,QAAI,SAAS,KAAK,aAAa;AAC/B,QAAI,OAAO;AACT,eAASA,WAAAA;AAAAA,QACP,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MAAA;AAGP,aACE,eACA,SAAS,KAAK,aAAa,UAC3B,KAAK,UAAU,KAAK,aAAa,MAAM,GAAG,YAAY,MAAM,GAC5D;AACA;AAAA,MACF;AAAA,IACF;AAGA,aAAS,IAAI,UAAU,IAAI,QAAQ,KAAK;AACtC,YAAM,OAAO,KAAK,SAAS,IAAI,KAAK,aAAa,CAAC,CAAC;AACnD,UAAI,MAAM;AACR,aAAK,QAAQ,CAAC,QAAQ,OAAO,IAAI,GAAG,CAAC;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,GAAW,MAAW,UAAgD;AACzE,UAAM,iBAAiBD,WAAAA,eAAe,IAAI;AAC1C,QAAI,WAAWC,WAAAA;AAAAA,MACb,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,IAAA;AAGP,WACE,WAAW,KAAK,aAAa,UAC7B,KAAK,UAAU,KAAK,aAAa,QAAQ,GAAG,cAAc,KAAK,GAC/D;AACA;AAAA,IACF;AAEA,WAAO,KAAK,cAAc,GAAG,UAAU,GAAG,QAAQ;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,aACE,GACA,MACA,UACa;AACb,UAAM,iBAAiBD,WAAAA,eAAe,IAAI;AAC1C,QAAI,WACFC,WAAAA;AAAAA,MACE,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,IAAA,IACH;AAEN,WACE,YAAY,KACZ,KAAK,UAAU,KAAK,aAAa,QAAQ,GAAG,cAAc,KAAK,GAC/D;AACA;AAAA,IACF;AAEA,WAAO,KAAK,cAAc,GAAG,UAAU,IAAI,QAAQ;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,GAAW,UAAgD;AACvE,WAAO,KAAK,cAAc,GAAG,GAAG,GAAG,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,oBACE,GACA,UACa;AACb,WAAO,KAAK,cAAc,GAAG,KAAK,aAAa,SAAS,GAAG,IAAI,QAAQ;AAAA,EACzE;AAAA,EAEQ,cACN,GACA,YACA,MACA,UACa;AACb,UAAM,SAAsB,CAAA;AAC5B,QAAI,QAAQ;AACZ,WACE,SAAS,KACT,QAAQ,KAAK,aAAa,UAC1B,OAAO,SAAS,GAChB;AACA,YAAM,aAAa,KAAK,aAAa,KAAK;AAC1C,YAAM,YAAyB,CAAA;AAC/B,SAAG;AACD,mBAAW,OAAO,KAAK,SAAS,IAAI,KAAK,aAAa,KAAK,CAAC,KAAK,IAAI;AACnE,oBAAU,KAAK,GAAG;AAAA,QACpB;AACA,iBAAS;AAAA,MACX,SACE,SAAS,KACT,QAAQ,KAAK,aAAa,UAC1B,KAAK,UAAU,KAAK,aAAa,KAAK,GAAG,UAAU,MAAM;AAE3D,gBAAU,KAAK,SAAS,IAAIE,MAAAA,cAAcC,WAAAA,mBAAmB;AAC7D,iBAAW,OAAO,WAAW;AAC3B,YAAI,WAAW,GAAG,KAAK,KAAM,QAAO,KAAK,GAAG;AAC5C,YAAI,OAAO,UAAU,EAAG;AAAA,MAC1B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,QAA+B;AAC3C,UAAM,6BAAa,IAAA;AAEnB,eAAW,SAAS,QAAQ;AAC1B,YAAM,kBAAkBJ,WAAAA,eAAe,KAAK;AAC5C,YAAM,OAAO,KAAK,SAAS,IAAI,eAAe;AAC9C,UAAI,MAAM;AACR,aAAK,QAAQ,CAAC,QAAQ,OAAO,IAAI,GAAG,CAAC;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;"}