@devisfuture/mega-collection 2.4.7 → 2.5.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.
Files changed (66) hide show
  1. package/README.md +93 -75
  2. package/dist/{State.d.ts → State-CYIe-3He.d.ts} +5 -3
  3. package/dist/chunks/constants-DK9S0Db0.mjs +1 -0
  4. package/dist/chunks/merge-C6intZSe.mjs +1 -0
  5. package/dist/filter/index.d.ts +114 -4
  6. package/dist/filter/index.mjs +1 -2
  7. package/dist/index.d.ts +2 -4
  8. package/dist/index.mjs +1 -2
  9. package/dist/merge/index.d.ts +131 -4
  10. package/dist/merge/index.mjs +1 -2
  11. package/dist/search/index.d.ts +191 -4
  12. package/dist/search/index.mjs +1 -2
  13. package/dist/sort/index.d.ts +57 -4
  14. package/dist/sort/index.mjs +1 -2
  15. package/dist/types-DONld7xY.d.ts +74 -0
  16. package/package.json +6 -2
  17. package/dist/State.mjs +0 -183
  18. package/dist/constants.d.ts +0 -5
  19. package/dist/constants.mjs +0 -4
  20. package/dist/filter/chain.d.ts +0 -9
  21. package/dist/filter/chain.mjs +0 -22
  22. package/dist/filter/constants.d.ts +0 -2
  23. package/dist/filter/criterion.d.ts +0 -6
  24. package/dist/filter/criterion.mjs +0 -64
  25. package/dist/filter/errors.d.ts +0 -7
  26. package/dist/filter/errors.mjs +0 -17
  27. package/dist/filter/filter.d.ts +0 -89
  28. package/dist/filter/filter.mjs +0 -439
  29. package/dist/filter/nested.d.ts +0 -32
  30. package/dist/filter/nested.mjs +0 -246
  31. package/dist/filter/types.d.ts +0 -74
  32. package/dist/filter/utils.d.ts +0 -4
  33. package/dist/filter/utils.mjs +0 -29
  34. package/dist/indexer.d.ts +0 -41
  35. package/dist/indexer.mjs +0 -101
  36. package/dist/internal.d.ts +0 -6
  37. package/dist/internal.mjs +0 -18
  38. package/dist/merge/chain.d.ts +0 -9
  39. package/dist/merge/chain.mjs +0 -23
  40. package/dist/merge/constants.d.ts +0 -6
  41. package/dist/merge/constants.mjs +0 -8
  42. package/dist/merge/errors.d.ts +0 -8
  43. package/dist/merge/errors.mjs +0 -19
  44. package/dist/merge/merge-engines.d.ts +0 -75
  45. package/dist/merge/merge-engines.mjs +0 -432
  46. package/dist/merge/module-adapters.d.ts +0 -7
  47. package/dist/merge/module-adapters.mjs +0 -41
  48. package/dist/merge/types.d.ts +0 -125
  49. package/dist/search/constants.d.ts +0 -5
  50. package/dist/search/nested.d.ts +0 -41
  51. package/dist/search/nested.mjs +0 -210
  52. package/dist/search/ngram.d.ts +0 -23
  53. package/dist/search/ngram.mjs +0 -96
  54. package/dist/search/text-search.d.ts +0 -146
  55. package/dist/search/text-search.mjs +0 -696
  56. package/dist/search/types.d.ts +0 -93
  57. package/dist/search/utils.d.ts +0 -4
  58. package/dist/search/utils.mjs +0 -22
  59. package/dist/sort/errors.d.ts +0 -5
  60. package/dist/sort/errors.mjs +0 -11
  61. package/dist/sort/sorter.d.ts +0 -47
  62. package/dist/sort/sorter.mjs +0 -375
  63. package/dist/sort/types.d.ts +0 -18
  64. package/dist/sort/utils.d.ts +0 -17
  65. package/dist/sort/utils.mjs +0 -38
  66. package/dist/types.d.ts +0 -73
package/README.md CHANGED
@@ -17,6 +17,7 @@ If this package saved you some time, a ⭐ on GitHub would be much appreciated.
17
17
  - [All-in-one: `MergeEngines`](#all-in-one-mergeengines) – use search, filter, and sort from one engine
18
18
  - [Add items with `add([])`](#add-items-with-add) – append multiple items to stored data
19
19
  - [Update items with `update(...)`](#update-items-with-update) – replace one stored item by unique field
20
+ - [Delete items with `delete(...)`](#delete-items-with-delete) – remove stored items by unique field value
20
21
  - [Search only](#search-only) – use only text search
21
22
  - [Flat collections search](#flat-collections-search) – search simple fields like `name` or `city`
22
23
  - [Nested collections search](#nested-collections-search) – search inside nested arrays like `orders.status`
@@ -24,7 +25,6 @@ If this package saved you some time, a ⭐ on GitHub would be much appreciated.
24
25
  - [Flat collections filter](#flat-collections-filter) – filter by simple top-level fields
25
26
  - [Exclude items with `exclude`](#exclude-items-with-exclude) – remove matching items from the result
26
27
  - [Result-only exclude](#result-only-exclude) – return a filtered result without mutating stored data
27
- - [Mutable exclude with `mutableExcludeField`](#mutable-exclude-with-mutableexcludefield) – fast delete-like removal via swap-pop
28
28
  - [Nested collections filter](#nested-collections-filter) – filter by nested array fields
29
29
  - [Sort only](#sort-only) – use only sorting
30
30
  - [API Reference](#api-reference) – list of options and methods
@@ -173,7 +173,7 @@ const engine = new MergeEngines<User>({
173
173
  const mutableMerge = new MergeEngines<User>({
174
174
  imports: [FilterEngine],
175
175
  data: users,
176
- filter: { fields: ["id", "city"], mutableExcludeField: "id" },
176
+ filter: { fields: ["id", "city"] },
177
177
  });
178
178
 
179
179
  // Dataset is passed once in the constructor.
@@ -228,7 +228,7 @@ engine.clearData("search").clearData("sort").clearData("filter");
228
228
  engine.getOriginData();
229
229
 
230
230
  // Remove items through the root facade.
231
- mutableMerge.filter([{ field: "id", exclude: [1, 4] }]);
231
+ mutableMerge.delete("id", [1, 4]);
232
232
  ```
233
233
 
234
234
  ---
@@ -363,6 +363,68 @@ searchEngine.update({
363
363
 
364
364
  ---
365
365
 
366
+ ### Delete items with `delete(...)`
367
+
368
+ Use `delete(...)` when you need to remove stored items from the original dataset by a unique field such as `id`.
369
+
370
+ - `delete(...)` changes the stored dataset.
371
+ - removal uses **swap-pop**, so order is not preserved.
372
+ - indexed engines update their internal state from the shared `State` mutation instead of rebuilding the full dataset.
373
+ - the target field values must be unique for the values you remove.
374
+
375
+ ```ts
376
+ import { MergeEngines } from "@devisfuture/mega-collection";
377
+ import { TextSearchEngine } from "@devisfuture/mega-collection/search";
378
+ import { SortEngine } from "@devisfuture/mega-collection/sort";
379
+ import { FilterEngine } from "@devisfuture/mega-collection/filter";
380
+
381
+ const merge = new MergeEngines<User>({
382
+ imports: [TextSearchEngine, SortEngine, FilterEngine],
383
+ data: users,
384
+ search: { fields: ["name", "city"], minQueryLength: 2 },
385
+ filter: { fields: ["id", "city"] },
386
+ sort: { fields: ["age", "name"] },
387
+ });
388
+
389
+ merge.delete("id", [1, 4]);
390
+
391
+ merge.getOriginData();
392
+ merge.search("Kyiv");
393
+ merge.filter([{ field: "city", values: ["Lviv"] }]);
394
+ merge.sort([{ field: "age", direction: "asc" }]);
395
+ ```
396
+
397
+ The same method works in each engine:
398
+
399
+ ```ts
400
+ import { TextSearchEngine } from "@devisfuture/mega-collection/search";
401
+ import { FilterEngine } from "@devisfuture/mega-collection/filter";
402
+ import { SortEngine } from "@devisfuture/mega-collection/sort";
403
+
404
+ const searchEngine = new TextSearchEngine<User>({
405
+ data: users,
406
+ fields: ["name", "city"],
407
+ });
408
+
409
+ searchEngine.delete("id", 2);
410
+
411
+ const filterEngine = new FilterEngine<User>({
412
+ data: users,
413
+ fields: ["id", "city"],
414
+ });
415
+
416
+ filterEngine.delete("id", [1, 4]);
417
+
418
+ const sortEngine = new SortEngine<User>({
419
+ data: users,
420
+ fields: ["age", "name"],
421
+ });
422
+
423
+ sortEngine.delete("id", 3);
424
+ ```
425
+
426
+ ---
427
+
366
428
  ### Search only
367
429
 
368
430
  Use `TextSearchEngine` when you only need text search.
@@ -398,6 +460,9 @@ engine.update({
398
460
  data: { id: 2, name: "Bob", city: "Paris", age: 19 },
399
461
  });
400
462
 
463
+ // remove one stored item by unique field
464
+ engine.delete("id", 2);
465
+
401
466
  // access original dataset stored in the engine
402
467
  engine.getOriginData();
403
468
 
@@ -456,6 +521,9 @@ engine.update({
456
521
  data: { id: 2, name: "Bob", city: "Paris", age: 19, active: true },
457
522
  });
458
523
 
524
+ // Remove stored items by unique field.
525
+ engine.delete("id", [1, 4]);
526
+
459
527
  // Get original stored dataset.
460
528
  engine.getOriginData();
461
529
 
@@ -475,12 +543,7 @@ This is useful when you already know which `id` values or other field values sho
475
543
 
476
544
  `exclude` changes only the returned result. It does not change the stored dataset inside the engine.
477
545
 
478
- There are two ways to work with `exclude`:
479
-
480
- - Result-only exclude: returns a filtered array and leaves the stored dataset unchanged.
481
- - Mutable exclude with `mutableExcludeField`: removes items from the stored dataset with **swap-pop**.
482
-
483
- **Swap-pop** is an efficient array removal technique where the element to be removed is swapped with the last element in the array, and then the array length is decreased by one. This provides O(1) time complexity for removal but does not preserve the original order of elements.
546
+ `exclude` is always result-only. It never changes the stored dataset inside the engine.
484
547
 
485
548
  #### Result-only exclude
486
549
 
@@ -492,10 +555,8 @@ so the engine still needs one pass over the current data to build the result.
492
555
  If `id` is indexed, the engine does not scan the full dataset again for each excluded `id`,
493
556
  but it still has to build the final array.
494
557
 
495
- If you need repeated removals from a large collection and do not want O(n) work for each removed item,
496
- use mutable exclude mode.
497
- In this mode the engine removes items from the stored dataset with swap-pop.
498
- Order is not preserved.
558
+ If you need to remove items from the stored dataset itself, use `delete(...)`.
559
+ That operation is separate from filtering so result-only `exclude` stays predictable.
499
560
 
500
561
  If the field is listed in `fields`, the engine uses indexes for exclude values
501
562
  instead of scanning the full dataset again for every removed value.
@@ -518,55 +579,6 @@ engine.filter([
518
579
  ]);
519
580
  ```
520
581
 
521
- #### Mutable exclude with `mutableExcludeField`
522
-
523
- If you need repeated fast removals from a large stored dataset, use `mutableExcludeField`.
524
- In this mode the engine removes items from the stored dataset with swap-pop.
525
-
526
- Use this mode when all of these points are true:
527
-
528
- - the engine already stores the full dataset
529
- - the exclude field is unique, for example `id`
530
- - order does not need to be preserved
531
- - you want repeated removals without O(n) per removed id
532
-
533
- This mode changes the stored dataset.
534
- After exclusion, `getOriginData()` returns the reduced collection.
535
-
536
- ```ts
537
- import { FilterEngine } from "@devisfuture/mega-collection/filter";
538
-
539
- const mutableEngine = new FilterEngine<User>({
540
- data: users,
541
- fields: ["id", "city"],
542
- mutableExcludeField: "id",
543
- });
544
-
545
- // Removes items from the stored dataset with swap-pop.
546
- mutableEngine.filter([{ field: "id", exclude: [1, 4] }]);
547
-
548
- // The stored dataset is now smaller.
549
- mutableEngine.getOriginData();
550
- ```
551
-
552
- The same mode also works through `MergeEngines`:
553
-
554
- ```ts
555
- import { MergeEngines } from "@devisfuture/mega-collection";
556
- import { FilterEngine } from "@devisfuture/mega-collection/filter";
557
-
558
- const mutableMerge = new MergeEngines<User>({
559
- imports: [FilterEngine],
560
- data: users,
561
- filter: {
562
- fields: ["id", "city"],
563
- mutableExcludeField: "id",
564
- },
565
- });
566
-
567
- mutableMerge.filter([{ field: "id", exclude: [1, 4] }]);
568
- ```
569
-
570
582
  #### Nested collections filter
571
583
 
572
584
  ```ts
@@ -614,6 +626,9 @@ engine.update({
614
626
  data: { id: 2, name: "Bob", city: "Paris", age: 19 },
615
627
  });
616
628
 
629
+ // remove one stored item by unique field
630
+ engine.delete("id", 2);
631
+
617
632
  // access original dataset stored in the engine
618
633
  engine.getOriginData();
619
634
 
@@ -644,7 +659,7 @@ One class that combines search, filter, and sort for the same dataset.
644
659
  | `data` | `T[]` | Shared dataset — passed once at construction |
645
660
  | `filterByPreviousResult` | `boolean` | When `true`, separate `filter(...)` and `sort(...)` calls continue from the last result stored in shared State |
646
661
  | `search` | `{ fields, nestedFields?, minQueryLength? }` | Config for TextSearchEngine |
647
- | `filter` | `{ fields, nestedFields?, mutableExcludeField? }` | Config for FilterEngine |
662
+ | `filter` | `{ fields, nestedFields? }` | Config for FilterEngine |
648
663
  | `sort` | `{ fields }` | Config for SortEngine |
649
664
 
650
665
  **Methods:**
@@ -659,6 +674,7 @@ One class that combines search, filter, and sort for the same dataset.
659
674
  | `filter(data, criteria)` | Filter with an explicit dataset |
660
675
  | `getOriginData()` | Get the shared original dataset |
661
676
  | `add(items)` | Append multiple items to the stored dataset and update existing indexes or caches for new items only |
677
+ | `delete(field, valueOrValues)` | Remove stored items by unique field value using swap-pop semantics |
662
678
  | `update({ field, data })` | Replace one stored item by a unique field and refresh only the affected cached or indexed data |
663
679
  | `data(data)` | Replace stored dataset for all imported modules, rebuilding configured indexes and resetting filter state where applicable |
664
680
  | `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
@@ -687,6 +703,7 @@ Main constructor options:
687
703
  | `resetSearchState()` | Reset previous-result state for sequential narrowing search |
688
704
  | `getOriginData()` | Get the original stored dataset |
689
705
  | `add(items)` | Append multiple items to the stored dataset |
706
+ | `delete(field, valueOrValues)` | Remove stored items by unique field value |
690
707
  | `update({ field, data })` | Replace one stored item by a unique field |
691
708
  | `data(data)` | Replace stored dataset and rebuild configured indexes |
692
709
  | `clearIndexes()` | Clear n-gram indexes (including nested) |
@@ -705,20 +722,20 @@ Main constructor options:
705
722
  | Option | Type | Description |
706
723
  | ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
707
724
  | `filterByPreviousResult` | `boolean` | When `true`, the next `filter(criteria)` call works on the previous result. By default each call starts from the original dataset. |
708
- | `mutableExcludeField` | `string` | Optional field for removing items from stored data with swap-pop. This changes the stored dataset and does not preserve order. |
709
725
  | `nestedFields` | `string[]` | Nested field paths in dot notation, for example `["orders.status"]`. |
710
726
 
711
- | Method | Description |
712
- | ------------------------- | -------------------------------------------------------------------------- |
713
- | `filter(criteria)` | Filter using stored dataset (supports nested field criteria) |
714
- | `filter(data, criteria)` | Filter with an explicit dataset |
715
- | `getOriginData()` | Get the original stored dataset |
716
- | `add(items)` | Append multiple items to the stored dataset |
717
- | `update({ field, data })` | Replace one stored item by a unique field |
718
- | `data(data)` | Replace stored dataset, rebuild configured indexes, and reset filter state |
719
- | `resetFilterState()` | Reset previous-result state for sequential filtering |
720
- | `clearIndexes()` | Free all index memory (including nested indexes) |
721
- | `clearData()` | Clear stored data |
727
+ | Method | Description |
728
+ | ------------------------------ | -------------------------------------------------------------------------- |
729
+ | `filter(criteria)` | Filter using stored dataset (supports nested field criteria) |
730
+ | `filter(data, criteria)` | Filter with an explicit dataset |
731
+ | `getOriginData()` | Get the original stored dataset |
732
+ | `add(items)` | Append multiple items to the stored dataset |
733
+ | `delete(field, valueOrValues)` | Remove stored items by unique field value |
734
+ | `update({ field, data })` | Replace one stored item by a unique field |
735
+ | `data(data)` | Replace stored dataset, rebuild configured indexes, and reset filter state |
736
+ | `resetFilterState()` | Reset previous-result state for sequential filtering |
737
+ | `clearIndexes()` | Free all index memory (including nested indexes) |
738
+ | `clearData()` | Clear stored data |
722
739
 
723
740
  ### `SortEngine<T>` (sort module)
724
741
 
@@ -731,6 +748,7 @@ Sort methods return plain arrays.
731
748
  | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
732
749
  | `getOriginData()` | Get the original stored dataset |
733
750
  | `add(items)` | Append multiple items to the stored dataset |
751
+ | `delete(field, valueOrValues)` | Remove stored items by unique field value |
734
752
  | `update({ field, data })` | Replace one stored item by a unique field |
735
753
  | `data(data)` | Replace stored dataset and rebuild configured indexes |
736
754
  | `clearIndexes()` | Free all cached indexes |
@@ -1,5 +1,6 @@
1
- import type { CollectionItem, IndexableKey, StateListener, StateOptions, StatePreviousResult, StateRegistryFactory, UpdateDescriptor } from "./types";
2
- export declare class State<T extends CollectionItem> {
1
+ import { C as CollectionItem, S as StateOptions, a as StateListener, b as StatePreviousResult, c as StateRegistryFactory, U as UpdateDescriptor, I as IndexableKey } from './types-DONld7xY.js';
2
+
3
+ declare class State<T extends CollectionItem> {
3
4
  private originData;
4
5
  private filterByPreviousResult;
5
6
  private itemIndexLookup;
@@ -39,4 +40,5 @@ export declare class State<T extends CollectionItem> {
39
40
  private rebuildIndexMap;
40
41
  private rebuildItemIndexLookup;
41
42
  }
42
- //# sourceMappingURL=State.d.ts.map
43
+
44
+ export { State as S };
@@ -0,0 +1 @@
1
+ var e=class{constructor(e=[],t={}){this.itemIndexLookup=/* @__PURE__ */new WeakMap,this.mutationVersion=0,this.namespaceSequence=0,this.previousResultState=null,this.indexMaps=/* @__PURE__ */new Map,this.scopedRegistry=/* @__PURE__ */new Map,this.listeners=/* @__PURE__ */new Set,this.originData=e,this.filterByPreviousResult=t.filterByPreviousResult??!1,this.rebuildItemIndexLookup()}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}getOriginData(){return this.originData}getItemIndex(e){return this.itemIndexLookup.get(e)}getMutationVersion(){return this.mutationVersion}isFilterByPreviousResultEnabled(){return this.filterByPreviousResult}setFilterByPreviousResult(e){this.filterByPreviousResult=e,e||this.clearPreviousResult()}getPreviousResult(){return this.getPreviousResultState()?.result??null}getPreviousResultState(){return null===this.previousResultState||this.previousResultState.version!==this.mutationVersion?null:this.previousResultState}setPreviousResult(e,t){this.previousResultState={result:e,sourceData:t,version:this.mutationVersion}}clearPreviousResult(){this.previousResultState=null}createNamespace(e="scope"){return this.namespaceSequence+=1,`${e}:${this.namespaceSequence}`}getScopedValue(e,t){return this.scopedRegistry.get(e)?.get(t)}getOrCreateScopedValue(e,t,i){const s=this.getScopedValue(e,t);if(void 0!==s)return s;const n=this.getOrCreateScope(e),r=i();return n.set(t,r),r}setScopedValue(e,t,i){return this.getOrCreateScope(e).set(t,i),i}deleteScopedValue(e,t){const i=this.scopedRegistry.get(e);i&&(i.delete(t),0===i.size&&this.scopedRegistry.delete(e))}clearScope(e){this.scopedRegistry.delete(e)}data(e){this.originData=e,this.bumpMutationVersion(),this.rebuildItemIndexLookup();for(const t of this.indexMaps.keys())this.rebuildIndexMap(t);this.emit({type:"data",data:e})}add(e){if(0===e.length)return;const t=this.originData.length;for(let i=0;i<e.length;i++)this.originData.push(e[i]),this.itemIndexLookup.set(e[i],t+i);this.bumpMutationVersion();for(const[i,s]of this.indexMaps)for(let n=0;n<e.length;n++)s.set(e[n][i],t+n);this.emit({type:"add",items:e,startIndex:t})}update(e){const{field:t,data:i}=e,s=i[t];if(null==s)return;const n=this.getOrCreateIndexMap(t).get(s);if(void 0===n)return;const r=this.originData[n];this.originData[n]=i,this.itemIndexLookup.delete(r),this.itemIndexLookup.set(i,n),this.bumpMutationVersion();for(const[o,a]of this.indexMaps){const e=r[o],t=i[o];e!==t&&(a.get(e)===n&&a.delete(e),a.set(t,n))}this.emit({type:"update",field:t,index:n,previousItem:r,nextItem:i})}clearData(){const e=[];this.originData=e,this.itemIndexLookup=/* @__PURE__ */new WeakMap,this.bumpMutationVersion();for(const t of this.indexMaps.values())t.clear();this.emit({type:"clearData",data:e})}removeByFieldValue(e,t){const i=this.getOrCreateIndexMap(e).get(t);if(void 0===i)return;const s=this.originData.length-1,n=this.originData[i],r=i===s?null:this.originData[s];i!==s&&r&&(this.originData[i]=r,this.itemIndexLookup.set(r,i)),this.originData.pop(),this.itemIndexLookup.delete(n),this.bumpMutationVersion();for(const[o,a]of this.indexMaps){const e=n[o];a.get(e)===i&&a.delete(e),r&&a.set(r[o],i)}this.emit({type:"remove",field:e,value:t,removedItem:n,removedIndex:i,movedItem:r,movedFromIndex:r?s:null})}removeByFieldValues(e,t){if(0===t.length)return;const i=this.getOrCreateIndexMap(e),s=[];for(let n=0;n<t.length;n++){const e=t[n],r=i.get(e);if(void 0===r)continue;const o=this.originData.length-1,a=this.originData[r],u=r===o?null:this.originData[o];r!==o&&u&&(this.originData[r]=u,this.itemIndexLookup.set(u,r)),this.originData.pop(),this.itemIndexLookup.delete(a);for(const[t,i]of this.indexMaps){const e=a[t];i.get(e)===r&&i.delete(e),u&&i.set(u[t],r)}s.push({value:e,removedItem:a,removedIndex:r,movedItem:u,movedFromIndex:u?o:null})}0!==s.length&&(this.bumpMutationVersion(),this.emit({type:"removeMany",field:e,entries:s}))}emit(e){for(const t of this.listeners)t(e)}getOrCreateScope(e){const t=this.scopedRegistry.get(e);if(t)return t;const i=/* @__PURE__ */new Map;return this.scopedRegistry.set(e,i),i}bumpMutationVersion(){this.mutationVersion+=1,this.clearPreviousResult()}getOrCreateIndexMap(e){return this.indexMaps.get(e)||this.rebuildIndexMap(e)}rebuildIndexMap(e){const t=/* @__PURE__ */new Map;for(let i=0;i<this.originData.length;i++)t.set(this.originData[i][e],i);return this.indexMaps.set(e,t),t}rebuildItemIndexLookup(){this.itemIndexLookup=/* @__PURE__ */new WeakMap;for(let e=0;e<this.originData.length;e++)this.itemIndexLookup.set(this.originData[e],e)}};function t(e){return{value:e,enumerable:!1,configurable:!0,writable:!0}}function i(e){const t=e.indexOf(".");return-1===t?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}function s(e){return Array.isArray(e)?e:[e]}function n(e,t,i){if(0===i.length||0===e.length)return[];const s=new Set(i),n=/* @__PURE__ */new Set,r=/* @__PURE__ */new Set;for(let o=0;o<e.length;o++){const i=e[o][t];s.has(i)&&(n.has(i)?r.add(i):n.add(i))}return Array.from(r)}function r(e,t,i){const s=i.map(e=>JSON.stringify(e)).join(", ");return`${e}: delete() requires unique field values. Field \`${t}\` matched multiple items for ${1===i.length?"value":"values"} ${s}.`}var o="__merge__",a="deferFilterMutationIndexUpdates",u="deferSearchMutationIndexUpdates",l="deferSortMutationCacheUpdates";export{t as a,n as c,o as i,s as l,u as n,i as o,l as r,r as s,a as t,e as u};
@@ -0,0 +1 @@
1
+ import{a as t,c as e,i,l as r,n as s,r as a,s as n,t as o,u as l}from"./constants-DK9S0Db0.mjs";var u=class{constructor(t){this.callbacks=t}create(e){const i=e;return Object.defineProperties(i,{search:t((t,e)=>void 0===e?this.callbacks.search(t):this.callbacks.search(t,e)),sort:t((t,i,r)=>void 0===i?this.callbacks.sort(e,t,r):this.callbacks.sort(t,i,r)),filter:t((t,i)=>void 0===i?this.callbacks.filter(e,t):this.callbacks.filter(t,i)),add:t(t=>this.callbacks.add(t)),delete:t((t,e)=>this.callbacks.delete(t,e)),update:t(t=>this.callbacks.update(t)),clearIndexes:t(t=>(this.callbacks.clearIndexes(t),this.create(e))),clearData:t(t=>(this.callbacks.clearData(t),this.create(e))),data:t(t=>this.callbacks.data(t)),getOriginData:t(()=>this.callbacks.getOriginData())}),i}};function h(t){return"object"==typeof t&&null!==t}function c(t,e){return h(t)&&"function"==typeof t[e]}function d(t){return c(t,"search")&&c(t,"getOriginData")}function p(t){return c(t,"sort")&&c(t,"getOriginData")}function g(t){return c(t,"rawFilter")&&c(t,"getOriginData")}var v=t=>{const{prototype:e}=t;return g(e)?"filter":p(e)?"sort":d(e)?"search":null},S=(t,e,i,r)=>{const s=new t({data:e,state:i,...r});return g(s)?{moduleName:"filter",executeFilter:(t,e)=>void 0===e?s.rawFilter(t):s.rawFilter(t,e),clearIndexes:()=>s.clearIndexes()}:p(s)?{moduleName:"sort",executeSort:(t,e,i)=>void 0===e?s.sort(t):s.sort(t,e,i),clearIndexes:()=>s.clearIndexes()}:d(s)?{moduleName:"search",executeSearch:(t,e)=>void 0===e?s.search(t):s.search(t,e),clearIndexes:()=>s.clearIndexes()}:null},f={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},M=class t extends Error{constructor(t){super(t),this.name="MergeEnginesError"}static unavailableEngine(e){return new t(`MergeEngines: ${f[e]} is not available.`)}static unavailableGetOriginData(){return new t("MergeEngines: getOriginData is not available.")}static invalidFilterByPreviousResultOption(){return new t('MergeEngines: "filter.filterByPreviousResult" is not supported. Configure "filterByPreviousResult" on the MergeEngines root options.')}},m=class{constructor(t){this.previousSearchState=null,this.previousFilterState=null,this.previousSortState=null;const{imports:e,data:r,filterByPreviousResult:n=!1,...h}=t;this.validateFilterByPreviousResultOptions(h.filter),this.state=new l(r,{filterByPreviousResult:n});const c=new Set(e);let d=null,p=null,g=null;for(const i of c){const t=v(i);if(!t)continue;const e=this.getModuleInitOptions(t,i.name,h),s=S(i,r,this.state,e);s&&("search"!==s.moduleName||d||(d=s),"sort"!==s.moduleName||p||(p=s),"filter"!==s.moduleName||g||(g=s))}this.searchModule=d,this.sortModule=p,this.filterModule=g,this.sortModule&&this.state.setScopedValue(i,a,!0),this.searchModule&&this.state.setScopedValue(i,s,!0),this.filterModule&&this.state.setScopedValue(i,o,!0),this.state.subscribe(t=>this.handleStateMutation(t)),this.chainBuilder=new u({search:(t,e)=>void 0===e?this.search(t):this.search(t,e),sort:(t,e,i)=>this.sort(t,e,i),filter:(t,e)=>this.filter(t,e),getOriginData:()=>this.getOriginData(),add:t=>this.add(t),delete:(t,e)=>this.delete(t,e),update:t=>this.update(t),data:t=>this.data(t),clearIndexes:t=>this.clearIndexes(t),clearData:t=>this.clearData(t)})}getAdapter(t){return"search"===t?this.searchModule:"sort"===t?this.sortModule:this.filterModule}getModuleInitOptions(t,e,i){const r={};for(const s of[t,e]){const t=i[s];h(t)&&Object.assign(r,t)}return r}validateFilterByPreviousResultOptions(t){if(h(t)&&Object.prototype.hasOwnProperty.call(t,"filterByPreviousResult"))throw M.invalidFilterByPreviousResultOption()}isPreviousResultEnabled(){return this.state.isFilterByPreviousResultEnabled()}getPreviousResultInput(){return this.isPreviousResultEnabled()?this.state.getPreviousResult():null}trackPreviousResult(t,e){return this.isPreviousResultEnabled()&&this.state.setPreviousResult(t,e),t}clearOperationState(t){t&&"search"!==t||(this.previousSearchState=null),t&&"filter"!==t||(this.previousFilterState=null),t&&"sort"!==t||(this.previousSortState=null)}createSearchCacheKey(t,e){return JSON.stringify([t,e??null])}createSortCacheKey(t,e){return JSON.stringify({descriptors:t,inPlace:e??!1})}createFilterCacheKey(t){return JSON.stringify(t)}handleStateMutation(t){switch(t.type){case"add":case"update":return this.queueSearchCacheMutation(t),this.queueFilterCacheMutation(t),void this.queueSortCacheMutation(t);case"remove":case"removeMany":return this.previousSearchState=null,this.previousFilterState=null,void this.queueSortCacheMutation(t);case"data":case"clearData":return this.previousSearchState=null,this.previousFilterState=null,void(this.previousSortState=null)}}queueSearchCacheMutation(t){const e=this.previousSearchState;null!==e&&(this.canPatchStoredDatasetSearch(e)?this.previousSearchState={...e,version:this.state.getMutationVersion(),pendingMutations:e.pendingMutations.concat(t)}:this.previousSearchState=null)}queueFilterCacheMutation(t){const e=this.previousFilterState;null!==e&&(this.canPatchStoredDatasetFilter(e)?this.previousFilterState={...e,version:this.state.getMutationVersion(),pendingMutations:e.pendingMutations.concat(t)}:this.previousFilterState=null)}queueSortCacheMutation(t){const e=this.previousSortState;null!==e&&(this.canPatchStoredDatasetSort(e)?this.previousSortState={...e,version:this.state.getMutationVersion(),pendingMutations:e.pendingMutations.concat(t)}:this.previousSortState=null)}resolvePendingSortCache(t){if(0===t.pendingMutations.length)return t;let e={...t,pendingMutations:[]};for(let i=0;i<t.pendingMutations.length;i++)if(e=this.applySortCacheMutation(e,t.pendingMutations[i]),null===e)return null;return e}resolvePendingSearchCache(t){if(0===t.pendingMutations.length)return t;let e={...t,pendingMutations:[]};for(let i=0;i<t.pendingMutations.length;i++)if(e=this.applySearchCacheMutation(e,t.pendingMutations[i]),null===e)return null;return e}resolvePendingFilterCache(t){if(0===t.pendingMutations.length)return t;let e={...t,pendingMutations:[]};for(let i=0;i<t.pendingMutations.length;i++)if(e=this.applyFilterCacheMutation(e,t.pendingMutations[i]),null===e)return null;return e}applySortCacheMutation(t,e){switch(e.type){case"add":return this.patchSortCacheForAddedItems(t,e.items);case"update":return this.patchSortCacheForUpdatedItem(t,e.previousItem,e.nextItem);case"remove":return this.patchSortCacheForRemovedItems(t,[e.removedItem]);case"removeMany":return this.patchSortCacheForRemovedItems(t,e.entries.map(t=>t.removedItem));case"data":case"clearData":return null}}applySearchCacheMutation(t,e){switch(e.type){case"add":return this.patchSearchCacheForAddedItems(t,e.items);case"update":return this.patchSearchCacheForUpdatedItem(t,e.previousItem,e.nextItem);case"remove":case"removeMany":case"data":case"clearData":return null}}applyFilterCacheMutation(t,e){switch(e.type){case"add":return this.patchFilterCacheForAddedItems(t,e.items);case"update":return this.patchFilterCacheForUpdatedItem(t,e.previousItem,e.nextItem);case"remove":case"removeMany":case"data":case"clearData":return null}}canPatchStoredDatasetSearch(t){return t.originData===this.state.getOriginData()&&null!==t.field}canPatchStoredDatasetFilter(t){if(t.sourceData!==this.state.getOriginData())return!1;for(let e=0;e<t.criteria.length;e++)if(!this.isPatchableFilterCriterion(t.criteria[e]))return!1;return!0}canPatchStoredDatasetSort(t){return t.sourceData===this.state.getOriginData()}compareItemsByDescriptors(t,e,i){for(let r=0;r<i.length;r++){const{field:s,direction:a}=i[r],n=t[s],o=e[s];if(n<o)return"asc"===a?-1:1;if(n>o)return"asc"===a?1:-1}return(this.state.getItemIndex(t)??-1)-(this.state.getItemIndex(e)??-1)}findSortInsertPosition(t,e,i){let r=0,s=t.length;for(;r<s;){const a=r+s>>1;this.compareItemsByDescriptors(t[a],e,i)<=0?r=a+1:s=a}return r}findDatasetInsertPosition(t,e){const i=this.state.getItemIndex(e)??Number.MAX_SAFE_INTEGER;for(let r=0;r<t.length;r++)if((this.state.getItemIndex(t[r])??Number.MAX_SAFE_INTEGER)>i)return r;return t.length}doesItemMatchSearchCache(t,e){if(null===t.field||0===t.lowerQuery.length)return!1;const i=e[t.field];return"string"==typeof i&&i.toLowerCase().includes(t.lowerQuery)}patchSearchCacheForAddedItems(t,e){if(!this.canPatchStoredDatasetSearch(t))return null;const i=t.result.slice();for(let r=0;r<e.length;r++){const s=e[r];this.doesItemMatchSearchCache(t,s)&&i.push(s)}return{...t,result:i,pendingMutations:[],version:this.state.getMutationVersion()}}patchSearchCacheForUpdatedItem(t,e,i){if(!this.canPatchStoredDatasetSearch(t))return null;const r=t.result.slice(),s=r.indexOf(e),a=this.doesItemMatchSearchCache(t,i);if(-1!==s)a?r[s]=i:r.splice(s,1);else if(a){const t=this.findDatasetInsertPosition(r,i);r.splice(t,0,i)}return{...t,result:r,pendingMutations:[],version:this.state.getMutationVersion()}}isPatchableFilterCriterion(t){return!String(t.field).includes(".")}doesItemMatchFilterCache(t,e){for(let i=0;i<t.criteria.length;i++){const r=t.criteria[i];if(!this.isPatchableFilterCriterion(r))return!1;const s=e[r.field];if(void 0!==r.values&&r.values.length>0&&!r.values.includes(s))return!1;if(void 0!==r.exclude&&r.exclude.length>0&&r.exclude.includes(s))return!1}return!0}patchFilterCacheForAddedItems(t,e){if(!this.canPatchStoredDatasetFilter(t))return null;const i=t.result.slice();for(let r=0;r<e.length;r++){const s=e[r];this.doesItemMatchFilterCache(t,s)&&i.push(s)}return{...t,result:i,pendingMutations:[],version:this.state.getMutationVersion()}}patchFilterCacheForUpdatedItem(t,e,i){if(!this.canPatchStoredDatasetFilter(t))return null;const r=t.result.slice(),s=r.indexOf(e),a=this.doesItemMatchFilterCache(t,i);if(-1!==s)a?r[s]=i:r.splice(s,1);else if(a){const t=this.findDatasetInsertPosition(r,i);r.splice(t,0,i)}return{...t,result:r,pendingMutations:[],version:this.state.getMutationVersion()}}patchSortCacheForAddedItems(t,e){if(!this.canPatchStoredDatasetSort(t))return null;const i=t.result.slice();for(let r=0;r<e.length;r++){const s=e[r],a=this.findSortInsertPosition(i,s,t.descriptors);i.splice(a,0,s)}return{...t,result:i,pendingMutations:[],version:this.state.getMutationVersion()}}patchSortCacheForUpdatedItem(t,e,i){if(!this.canPatchStoredDatasetSort(t))return null;const r=t.result.slice(),s=r.indexOf(e);if(-1===s)return-1!==t.result.indexOf(i)?{...t,pendingMutations:[],version:this.state.getMutationVersion()}:null;if(!t.descriptors.some(({field:t})=>e[t]!==i[t]))return r[s]=i,{...t,result:r,pendingMutations:[],version:this.state.getMutationVersion()};r.splice(s,1);const a=this.findSortInsertPosition(r,i,t.descriptors);return r.splice(a,0,i),{...t,result:r,pendingMutations:[],version:this.state.getMutationVersion()}}patchSortCacheForRemovedItems(t,e){if(!this.canPatchStoredDatasetSort(t))return null;const i=new Set(e);return{...t,result:Array.prototype.filter.call(t.result,t=>!i.has(t)),pendingMutations:[],version:this.state.getMutationVersion()}}search(t,e){if(!this.searchModule)throw M.unavailableEngine("search");const i=this.state.getOriginData(),r=this.state.getMutationVersion(),s=this.createSearchCacheKey(t,e),a=this.previousSearchState;if(a?.originData===i&&a.key===s&&a.version===r){const t=this.resolvePendingSearchCache(a);if(null!==t)return this.previousSearchState=t,this.withChain(this.trackPreviousResult(t.result,i));this.previousSearchState=null}const n=void 0===e?this.searchModule.executeSearch(t):this.searchModule.executeSearch(t,e);return this.previousSearchState={key:s,originData:i,result:n,version:r,field:void 0===e?null:t,lowerQuery:(e??t).trim().toLowerCase(),pendingMutations:[]},this.withChain(this.trackPreviousResult(n,i))}sort(t,e,i){if(!this.sortModule)throw M.unavailableEngine("sort");let r,s;if(void 0===e?(s=t,r=this.getPreviousResultInput()??this.state.getOriginData()):(r=t,s=e),!i){const t=this.state.getMutationVersion(),a=this.createSortCacheKey(s,i),n=this.previousSortState;if(n?.sourceData===r&&n.key===a&&n.version===t){const t=this.resolvePendingSortCache(n);if(null!==t)return this.previousSortState=t,this.withChain(this.trackPreviousResult(t.result,r));this.previousSortState=null}const o=void 0===e&&r===this.state.getOriginData()?this.sortModule.executeSort(s):this.sortModule.executeSort(r,s,i);return this.previousSortState={key:a,sourceData:r,result:o,version:t,descriptors:s,pendingMutations:[]},this.withChain(this.trackPreviousResult(o,r))}return this.withChain(this.trackPreviousResult(this.sortModule.executeSort(r,s,i),r))}filter(t,e){if(!this.filterModule)throw M.unavailableEngine("filter");if(void 0===e){const e=this.getPreviousResultInput(),i=e??this.state.getOriginData(),r=t,s=this.state.getMutationVersion(),a=this.createFilterCacheKey(r),n=this.previousFilterState;if(n?.sourceData===i&&n.key===a&&n.version===s){const t=this.resolvePendingFilterCache(n);if(null!==t)return this.previousFilterState=t,this.withChain(this.trackPreviousResult(t.result,i));this.previousFilterState=null}const o=null===e?this.filterModule.executeFilter(r):this.filterModule.executeFilter(e,r);return this.previousFilterState={key:a,sourceData:i,result:o,version:s,criteria:r,pendingMutations:[]},this.withChain(this.trackPreviousResult(o,i))}const i=t;return this.withChain(this.trackPreviousResult(this.filterModule.executeFilter(i,e),i))}withChain(t){return this.chainBuilder.create(t)}getOriginData(){if(this.searchModule||this.sortModule||this.filterModule)return this.state.getOriginData();throw M.unavailableGetOriginData()}add(t){return 0===t.length||this.state.add(t),this}delete(t,i){const s=r(i);if(0===s.length)return this;const a=e(this.state.getOriginData(),t,s);if(a.length>0)throw new Error(n("MergeEngines",t,a));return 1===s.length?(this.state.removeByFieldValue(t,s[0]),this):(this.state.removeByFieldValues(t,s),this)}update(t){return this.state.update(t),this}clearIndexes(t){const e=this.getAdapter(t);if(e)return e.clearIndexes(),this.clearOperationState(t),this;throw M.unavailableEngine(t)}data(t){return this.state.data(t),this}clearData(t){if(this.getAdapter(t))return this.state.clearData(),this;throw M.unavailableEngine(t)}};export{m as t};
@@ -1,4 +1,114 @@
1
- export { FilterEngine } from "./filter";
2
- export type { FilterEngineOptions, FilterEngineChain } from "./types";
3
- export type { CollectionItem, IndexableKey, FilterCriterion } from "../types";
4
- //# sourceMappingURL=index.d.ts.map
1
+ import { S as State } from '../State-CYIe-3He.js';
2
+ import { C as CollectionItem, F as FilterCriterion, I as IndexableKey, U as UpdateDescriptor } from '../types-DONld7xY.js';
3
+
4
+ interface FilterEngineChain<T extends CollectionItem> {
5
+ filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
6
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
7
+ getOriginData(): T[];
8
+ add(items: T[]): FilterEngine<T>;
9
+ delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): FilterEngine<T>;
10
+ delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): FilterEngine<T>;
11
+ update(descriptor: UpdateDescriptor<T>): FilterEngine<T>;
12
+ data(data: T[]): FilterEngine<T>;
13
+ clearIndexes(): FilterEngine<T>;
14
+ clearData(): FilterEngine<T>;
15
+ resetFilterState(): FilterEngine<T>;
16
+ }
17
+ interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
18
+ data?: T[];
19
+ fields?: (keyof T & string)[];
20
+ nestedFields?: string[];
21
+ filterByPreviousResult?: boolean;
22
+ }
23
+
24
+ /**
25
+ * FilterEngine class for filtering collections by multiple criteria,
26
+ * supporting indexed lookups and linear scans for large datasets.
27
+ */
28
+
29
+ declare class FilterEngine<T extends CollectionItem> {
30
+ private readonly indexer;
31
+ private readonly filterByPreviousResult;
32
+ private readonly state;
33
+ private readonly namespace;
34
+ private readonly nestedCollection;
35
+ private readonly chainBuilder;
36
+ /**
37
+ * Creates a new FilterEngine with optional data and fields to index.
38
+ */
39
+ constructor(options?: FilterEngineOptions<T> & {
40
+ state?: State<T>;
41
+ });
42
+ private get dataset();
43
+ private get runtime();
44
+ private get indexedFields();
45
+ private get sequentialCache();
46
+ private get persistentIndexedResults();
47
+ private shouldDeferMutationIndexUpdates;
48
+ private markDeferredMutationState;
49
+ private ensureRuntimeReady;
50
+ private rebuildConfiguredIndexes;
51
+ private clearPersistentIndexedResults;
52
+ private getPersistentIndexedResult;
53
+ private setPersistentIndexedResult;
54
+ /**
55
+ * Builds an index for the given field.
56
+ */
57
+ private buildIndex;
58
+ clearIndexes(): this;
59
+ resetFilterState(): this;
60
+ clearData(): this;
61
+ data(data: T[]): this;
62
+ add(items: T[]): this;
63
+ delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): this;
64
+ delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): this;
65
+ update(descriptor: UpdateDescriptor<T>): this;
66
+ private applyAddedItems;
67
+ getOriginData(): T[];
68
+ /**
69
+ * Filters the data based on the given criteria.
70
+ */
71
+ filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
72
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
73
+ rawFilter(criteria: FilterCriterion<T>[]): T[];
74
+ rawFilter(data: T[], criteria: FilterCriterion<T>[]): T[];
75
+ private tryFastStoredExcludeView;
76
+ private createIndexedExcludeView;
77
+ private countIndexedExcludedItems;
78
+ private resolveWithSequentialCache;
79
+ private withChain;
80
+ private handleStateMutation;
81
+ private applyUpdatedItem;
82
+ private applyRemovedItem;
83
+ private applyRemovedItems;
84
+ /**
85
+ * Filters data linearly without index.
86
+ */
87
+ private linearFilter;
88
+ /**
89
+ * Filters data using the index.
90
+ */
91
+ private filterViaIndex;
92
+ /**
93
+ * Estimates the size of the index for a criterion.
94
+ */
95
+ private estimateIndexSize;
96
+ private applyIndexedExclusions;
97
+ private applySubsetExclusions;
98
+ private createEmptyResult;
99
+ private storePreviousResult;
100
+ private shouldSkipSequentialHistoryCache;
101
+ private createCriteriaCacheKey;
102
+ private createSequentialCacheEntry;
103
+ private createSequentialExecutionCriteria;
104
+ private hasEquivalentSequentialValues;
105
+ private hasCriteriaBacktrack;
106
+ private canApplySequentiallyToEmptyResult;
107
+ private createCriteriaStateMap;
108
+ private isCriterionBacktracked;
109
+ private isSubset;
110
+ private areSetsEqual;
111
+ }
112
+
113
+ export { CollectionItem, FilterCriterion, FilterEngine, IndexableKey };
114
+ export type { FilterEngineChain, FilterEngineOptions };
@@ -1,2 +1 @@
1
- import { FilterEngine as e } from "./filter.mjs";
2
- export { e as FilterEngine };
1
+ import{a as e,c as t,i as s,l as i,o as n,s as r,t as l,u as a}from"../chunks/constants-DK9S0Db0.mjs";var u=class{constructor(e={indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map}){this.storage=e}addItems(e){if(0!==e.length&&0!==this.storage.indexes.size)for(let t=0;t<e.length;t++)this.addItem(e[t])}buildIndex(e,t){const s=/* @__PURE__ */new Map,i=/* @__PURE__ */new Map;for(let n=0,r=e.length;n<r;n++){const r=e[n],l=r[t];if(null==l)continue;const a=s.get(l);if(a)a.push(r),i.get(l).set(r,a.length-1);else{s.set(l,[r]);const e=/* @__PURE__ */new WeakMap;e.set(r,0),i.set(l,e)}}this.storage.indexes.set(t,s),this.storage.itemPositions.set(t,i)}getByValue(e,t){const s=this.storage.indexes.get(e);return s?s.get(t)??[]:[]}getByValues(e,t){const s=this.storage.indexes.get(e);if(!s)return[];if(1===t.length)return s.get(t[0])??[];if(2===t.length){const e=s.get(t[0]),i=s.get(t[1]);return e?i?e.concat(i):e:i??[]}const i=[];for(let n=0;n<t.length;n++){const e=s.get(t[n]);if(void 0!==e)for(let t=0;t<e.length;t++)i.push(e[t])}return i}hasIndex(e){return this.storage.indexes.has(e)}addItem(e){for(const t of this.storage.indexes.keys())this.addItemToField(t,e)}updateItem(e,t){for(const s of this.storage.indexes.keys())this.updateItemInField(s,e,t)}removeItem(e){for(const t of this.storage.indexes.keys())this.removeItemFromField(t,e)}clear(){this.storage.indexes.clear(),this.storage.itemPositions.clear()}getIndexMap(e){return this.storage.indexes.get(e)}removeItemFromField(e,t){const s=t[e];if(null==s)return;const i=this.storage.indexes.get(e),n=this.storage.itemPositions.get(e),r=i?.get(s),l=n?.get(s),a=l?.get(t);if(!(i&&n&&r&&l&&void 0!==a))return;const u=r.length-1,o=r[u];a!==u&&(r[a]=o,l.set(o,a)),r.pop(),l.delete(t),0===r.length&&(i.delete(s),n.delete(s))}updateItemInField(e,t,s){const i=t[e];if(i!==s[e])this.removeItemFromField(e,t),this.addItemToField(e,s);else{if(null==i)return;this.replaceItemReferenceInField(e,i,t,s)}}replaceItemReferenceInField(e,t,s,i){const n=this.storage.indexes.get(e),r=this.storage.itemPositions.get(e),l=n?.get(t),a=r?.get(t),u=a?.get(s);l&&a&&void 0!==u&&(l[u]=i,a.delete(s),a.set(i,u))}addItemToField(e,t){const s=t[e];if(null==s)return;const i=this.storage.indexes.get(e),n=this.storage.itemPositions.get(e);if(!i||!n)return;const r=i.get(s),l=n.get(s);if(r&&l)return r.push(t),void l.set(t,r.length-1);i.set(s,[t]);const a=/* @__PURE__ */new WeakMap;a.set(t,0),n.set(s,a)}},o=class{constructor(e){this.callbacks=e}create(t){const s=t;return Object.defineProperties(s,{filter:e((e,s)=>void 0===s?this.callbacks.filter(t,e):this.callbacks.filter(e,s)),add:e(e=>this.callbacks.add(e)),delete:e((e,t)=>this.callbacks.delete(e,t)),update:e(e=>this.callbacks.update(e)),clearIndexes:e(()=>this.callbacks.clearIndexes()),data:e(e=>this.callbacks.data(e)),getOriginData:e(()=>this.callbacks.getOriginData()),clearData:e(()=>this.callbacks.clearData()),resetFilterState:e(()=>this.callbacks.resetFilterState())}),s}},d=class e extends Error{constructor(e){super(e),this.name="FilterEngineError"}static missingDatasetForBuildIndex(){return new e("FilterEngine: no dataset in memory. Call data() or add() before buildIndex().")}static missingDatasetForFilter(){return new e("FilterEngine: no dataset in memory. Call data() or add() before filter().")}};function h(e){const t=/* @__PURE__ */new Map;for(let i=0;i<e.length;i++){const s=e[i],n=Array.isArray(s.values),r=g(s.exclude),l=null!==r,a=n?x(s.values,r):null;if(!n&&!l)continue;const u=s.field,o=t.get(u);if(o){if(n)if(o.hasValues)for(const e of o.includedValues)a.has(e)||o.includedValues.delete(e);else o.hasValues=!0,o.includedValues=new Set(a);if(l)if(o.hasExclude)for(const e of r)o.excludedValues.add(e);else o.hasExclude=!0,o.excludedValues=new Set(r)}else t.set(u,{field:s.field,values:[],exclude:[],hasValues:n,hasExclude:l,includedValues:a?new Set(a):null,excludedValues:r?new Set(r):null,cacheKeySegment:""})}const s=[...t.values()].sort((e,t)=>e.field.localeCompare(t.field));for(let i=0;i<s.length;i++)p(s[i]);return s}function c(e,t){return!(e.hasValues&&!e.includedValues.has(t)||e.hasExclude&&e.excludedValues.has(t))}function f(e){return e.hasValues&&0===e.values.length}function g(e){return Array.isArray(e)&&0!==e.length?new Set(e):null}function x(e,t){const s=/* @__PURE__ */new Set;for(let i=0;i<e.length;i++){const n=e[i];t?.has(n)||s.add(n)}return s}function p(e){if(e.hasValues&&e.hasExclude)for(const t of e.excludedValues)e.includedValues.delete(t);e.values=e.includedValues?[...e.includedValues]:[],e.exclude=e.excludedValues?[...e.excludedValues]:[],e.cacheKeySegment=function(e){let t=e.field;return t+=`|hv:${e.hasValues?"1":"0"}|v:`,e.hasValues&&(t+=I(e.values)),t+=`|hx:${e.hasExclude?"1":"0"}|x:`,e.hasExclude&&(t+=I(e.exclude)),t}(e)}function I(e){return 0===e.length?"":e.map(e=>function(e){if(null===e)return"null:null";const t=typeof e;return"object"===t?`object:${JSON.stringify(e)}`:`${t}:${String(e)}`}(e)).sort().join(",")}var m=class{constructor(e={indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map}){this.storage=e,this.registeredFields=/* @__PURE__ */new Set,this.fieldDescriptors=/* @__PURE__ */new Map}registerFields(e){if(e?.length)for(let t=0;t<e.length;t++)this.registerField(e[t])}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}clearIndexes(){this.storage.indexes.clear(),this.storage.itemPositions.clear()}buildIndexes(e){this.storage.indexes.clear(),this.storage.itemPositions.clear();for(const t of this.registeredFields)this.buildIndex(e,t)}addItems(e){if(0!==e.length&&0!==this.storage.indexes.size)for(let t=0;t<e.length;t++)this.addItem(e[t])}removeItem(e){for(const t of this.storage.indexes.keys())this.removeItemFromIndex(t,e)}updateItem(e,t){for(const s of this.storage.indexes.keys())this.updateItemInIndex(s,e,t)}filter(e,t,s){const i=this.resolveCriteria(t);if(0===e.length||0===i.length)return e;const n=[],r=[];for(let a=0;a<i.length;a++){const e=i[a];this.storage.indexes.has(e.field)?n.push(e):r.push(e)}let l=e;if(n.length>0&&(l=this.filterByIndexes(n,e,s),0===l.length))return l;for(let a=0;a<r.length;a++)if(l=this.filterLinearly(l,r[a]),0===l.length)return l;return l}resolveCriteria(e){if(0===e.length)return[];const t=e[0];return"hasValues"in t&&"hasExclude"in t&&"includedValues"in t?e:h(e)}registerField(e){const t=n(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t))}buildIndex(e,t){const s=this.fieldDescriptors.get(t);if(!s)return;const{collectionKey:i,nestedKey:n}=s,r=/* @__PURE__ */new Map,l=/* @__PURE__ */new Map;for(let a=0,u=e.length;a<u;a++){const t=e[a],s=t[i];if(Array.isArray(s))for(let e=0;e<s.length;e++){const i=s[e][n];if(null==i)continue;const a=r.get(i);if(a){a[a.length-1]!==t&&(a.push(t),l.get(i).set(t,a.length-1));continue}r.set(i,[t]);const u=/* @__PURE__ */new WeakMap;u.set(t,0),l.set(i,u)}}this.storage.indexes.set(t,r),this.storage.itemPositions.set(t,l)}removeItemFromIndex(e,t){const s=this.fieldDescriptors.get(e),i=this.storage.indexes.get(e),n=this.storage.itemPositions.get(e);if(!s||!i||!n)return;const{collectionKey:r,nestedKey:l}=s,a=t[r];if(!Array.isArray(a)||0===a.length)return;const u=/* @__PURE__ */new Set;for(let o=0;o<a.length;o++){const e=a[o][l];null!=e&&u.add(e)}for(const o of u){const e=i.get(o),s=n.get(o),r=s?.get(t);if(!e||!s||void 0===r)continue;const l=e.length-1,a=e[l];r!==l&&(e[r]=a,s.set(a,r)),e.pop(),s.delete(t),0===e.length&&(i.delete(o),n.delete(o))}}addItem(e){for(const t of this.storage.indexes.keys())this.addItemToIndex(t,e)}addItemToIndex(e,t){const s=this.fieldDescriptors.get(e),i=this.storage.indexes.get(e),n=this.storage.itemPositions.get(e);if(!s||!i||!n)return;const{collectionKey:r,nestedKey:l}=s,a=t[r];if(!Array.isArray(a)||0===a.length)return;const u=/* @__PURE__ */new Set;for(let o=0;o<a.length;o++){const e=a[o][l];null!=e&&u.add(e)}for(const o of u){const e=i.get(o),s=n.get(o);if(e&&s){e.push(t),s.set(t,e.length-1);continue}i.set(o,[t]);const r=/* @__PURE__ */new WeakMap;r.set(t,0),n.set(o,r)}}updateItemInIndex(e,t,s){const i=this.fieldDescriptors.get(e),n=this.storage.indexes.get(e),r=this.storage.itemPositions.get(e);if(!i||!n||!r)return;const l=this.collectUniqueValues(s,i),a=this.collectUniqueValues(t,i);if(this.areValueSetsEqual(l,a))for(const u of l){const e=n.get(u),i=r.get(u),l=i?.get(s);e&&i&&void 0!==l&&(e[l]=t,i.delete(s),i.set(t,l))}else this.removeItemFromIndex(e,s),this.addItemToIndex(e,t)}collectUniqueValues(e,t){const{collectionKey:s,nestedKey:i}=t,n=e[s],r=/* @__PURE__ */new Set;if(!Array.isArray(n)||0===n.length)return r;for(let l=0;l<n.length;l++){const e=n[l][i];null!=e&&r.add(e)}return r}areValueSetsEqual(e,t){if(e.size!==t.size)return!1;for(const s of e)if(!t.has(s))return!1;return!0}filterByIndexes(e,t,s){const i=e.filter(e=>e.hasValues),n=e.filter(e=>e.hasExclude),r=t===s?null:new Set(t);if(0===i.length)return this.applyIndexedExclusions(t,n);if(1===i.length){const e=this.storage.indexes.get(i[0].field);if(!e)return[];const t=this.getItemsByValues(e,i[0].values);if(0===t.length)return[];const s=[];for(let i=0;i<t.length;i++){const e=t[i];r&&!r.has(e)||s.push(e)}return this.applyIndexedExclusions(s,n)}const l=i.map(e=>({criterion:e,size:this.estimateIndexSize(e)})).sort((e,t)=>e.size-t.size);let a=r,u=[];for(let o=0;o<l.length;o++){const{criterion:e}=l[o],t=this.storage.indexes.get(e.field);if(!t)return[];const s=this.getItemsByValues(t,e.values);if(0===s.length)return[];if(null===a)u=s;else{u=[];for(let e=0;e<s.length;e++){const t=s[e];a.has(t)&&u.push(t)}}if(0===u.length)return[];a=new Set(u)}return this.applyIndexedExclusions(u,n)}getItemsByValues(e,t){if(1===t.length)return e.get(t[0])??[];const s=/* @__PURE__ */new Set,i=[];for(let n=0;n<t.length;n++){const r=e.get(t[n]);if(r)for(let e=0;e<r.length;e++){const t=r[e];s.has(t)||(s.add(t),i.push(t))}}return i}estimateIndexSize(e){const t=this.storage.indexes.get(e.field);return t?e.values.reduce((e,s)=>{const i=t.get(s);return i?e+i.length:e},0):1/0}filterLinearly(e,t){const s=this.fieldDescriptors.get(t.field);if(!s)return e;const{collectionKey:i,nestedKey:n}=s,r=[];for(let l=0;l<e.length;l++){const s=e[l],a=s[i];if(!Array.isArray(a))continue;let u=!t.hasValues,o=!1;for(let e=0;e<a.length;e++){const s=a[e][n];if(t.hasExclude&&t.excludedValues.has(s)){o=!0;break}t.hasValues&&t.includedValues.has(s)&&(u=!0)}!o&&u&&r.push(s)}return r}applyIndexedExclusions(e,t){if(0===t.length||0===e.length)return e;const s=/* @__PURE__ */new Set;for(let n=0;n<t.length;n++){const e=t[n],i=this.storage.indexes.get(e.field);if(!i)continue;const r=this.getItemsByValues(i,e.exclude);for(let t=0;t<r.length;t++)s.add(r[t])}if(0===s.size)return e;const i=[];for(let n=0;n<e.length;n++){const t=e[n];s.has(t)||i.push(t)}return i}},v=()=>({indexedFields:/* @__PURE__ */new Set,indexerStorage:{indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map},nestedStorage:{indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map},deferredMutationVersion:null,sequentialCache:{previousResult:null,previousCriteria:null,previousCriteriaKey:null,previousBaseData:null,previousResultsByCriteria:/* @__PURE__ */new Map,previousResultSet:null},persistentIndexedResults:/* @__PURE__ */new Map}),y=class{constructor(e={}){this.chainBuilder=new o({filter:(e,t)=>void 0===t?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),add:e=>this.add(e),delete:(e,t)=>this.delete(e,t),update:e=>this.update(e),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()}),this.state=e.state??new a(e.data??[],{filterByPreviousResult:e.filterByPreviousResult??!1}),e.state&&e.filterByPreviousResult&&this.state.setFilterByPreviousResult(!0),this.filterByPreviousResult=this.state.isFilterByPreviousResultEnabled(),this.namespace=this.state.createNamespace("filter"),this.indexer=new u(this.runtime.indexerStorage),this.nestedCollection=new m(this.runtime.nestedStorage),this.nestedCollection.registerFields(e.nestedFields),this.state.subscribe(e=>this.handleStateMutation(e));const t=e.fields?.length,s=this.nestedCollection.hasRegisteredFields();if(t)for(const i of e.fields)this.indexedFields.add(i);this.dataset.length>0&&(t||s)&&this.rebuildConfiguredIndexes()}get dataset(){return this.state.getOriginData()}get runtime(){return this.state.getOrCreateScopedValue(this.namespace,"runtime",v)}get indexedFields(){return this.runtime.indexedFields}get sequentialCache(){return this.runtime.sequentialCache}get persistentIndexedResults(){return this.runtime.persistentIndexedResults}shouldDeferMutationIndexUpdates(){return!0===this.state.getScopedValue(s,l)}markDeferredMutationState(){this.runtime.deferredMutationVersion=this.state.getMutationVersion(),this.indexer.clear(),this.nestedCollection.clearIndexes(),this.clearPersistentIndexedResults(),this.resetFilterState()}ensureRuntimeReady(){null!==this.runtime.deferredMutationVersion&&(this.runtime.deferredMutationVersion=null,this.dataset.length>0&&(this.indexedFields.size>0||this.nestedCollection.hasRegisteredFields())&&this.rebuildConfiguredIndexes())}rebuildConfiguredIndexes(){this.indexer.clear(),this.nestedCollection.clearIndexes();for(const e of this.indexedFields)this.buildIndex(this.dataset,e);this.nestedCollection.hasRegisteredFields()&&this.nestedCollection.buildIndexes(this.dataset)}clearPersistentIndexedResults(){this.persistentIndexedResults.clear()}getPersistentIndexedResult(e){return this.persistentIndexedResults.get(e)}setPersistentIndexedResult(e,t){const s=this.persistentIndexedResults;if(s.has(e)&&s.delete(e),s.set(e,this.createSequentialCacheEntry(t,null)),s.size>32){const e=s.keys().next().value;void 0!==e&&s.delete(e)}}buildIndex(e,t){if(this.clearPersistentIndexedResults(),!Array.isArray(e)){if(!this.dataset.length)throw d.missingDatasetForBuildIndex();return this.indexer.buildIndex(this.dataset,e),this}return this.resetFilterState(),this.indexer.buildIndex(e,t),this}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),this.clearPersistentIndexedResults(),this}resetFilterState(){return this.sequentialCache.previousResult=null,this.sequentialCache.previousCriteria=null,this.sequentialCache.previousCriteriaKey=null,this.sequentialCache.previousBaseData=null,this.sequentialCache.previousResultsByCriteria.clear(),this.sequentialCache.previousResultSet=null,this.state.clearPreviousResult(),this}clearData(){return this.state.clearData(),this}data(e){return this.state.data(e),this}add(e){return this.state.add(e),this}delete(e,s){const n=i(s);if(0===n.length)return this;const l=t(this.dataset,e,n);if(l.length>0)throw new Error(r("FilterEngine",e,l));return 1===n.length?(this.state.removeByFieldValue(e,n[0]),this):(this.state.removeByFieldValues(e,n),this)}update(e){return this.state.update(e),this}applyAddedItems(e){return 0===e.length||(this.resetFilterState(),this.clearPersistentIndexedResults(),this.indexer.addItems(e),this.nestedCollection.addItems(e)),this}getOriginData(){return this.state.getOriginData()}filter(e,t){return void 0===t?this.withChain(this.rawFilter(e)):this.withChain(this.rawFilter(e,t))}rawFilter(e,t){this.ensureRuntimeReady();const s=void 0===t,i=s?e:t;if(s&&!this.dataset.length)throw d.missingDatasetForFilter();const n=s?this.dataset:e,r=h(i),l=this.createCriteriaCacheKey(r),a=this.tryFastStoredExcludeView(n,s,r,l);if(null!==a)return a;let u=n,o=r;if(this.filterByPreviousResult){const e=this.resolveWithSequentialCache(n,s,r);if(e.isFromCache)return e.result;u=e.sourceData,o=e.executionCriteria}if(0===r.length)return this.filterByPreviousResult&&this.resetFilterState(),n;for(let d=0;d<o.length;d++)if(f(o[d]))return this.createEmptyResult(s,n,r);const c=s&&u===this.dataset&&o===r,g=[],x=[];for(let d=0;d<o.length;d++){const e=o[d];this.nestedCollection.hasField(e.field)?g.push(e):x.push(e)}if(g.length>0&&(u=this.nestedCollection.filter(u,g,this.dataset),0===u.length))return this.createEmptyResult(s,n,r);if(0===x.length)return this.storePreviousResult(u,s,n,r),u;const p=[],I=[];for(let d=0;d<x.length;d++){const e=x[d];this.indexer.hasIndex(e.field)?p.push(e):I.push(e)}const m=c&&0===g.length&&x.length>0;if(m){const e=this.getPersistentIndexedResult(l);if(void 0!==e)return this.storePreviousResult(e.result,s,n,r,l,e.resultSet),e.result}let v;if(p.length>0&&0===I.length)return v=this.filterViaIndex(p,u),m&&this.setPersistentIndexedResult(l,v),this.storePreviousResult(v,s,n,r,l),v;if(p.length>0&&I.length>0){const e=this.filterViaIndex(p,u);return v=this.linearFilter(e,I),m&&this.setPersistentIndexedResult(l,v),this.storePreviousResult(v,s,n,r),v}return v=this.linearFilter(u,x),m&&this.setPersistentIndexedResult(l,v),this.storePreviousResult(v,s,n,r),v}tryFastStoredExcludeView(e,t,s,i){if(!t||e!==this.dataset||1!==s.length)return null;const n=s[0];if(n.hasValues||!n.hasExclude||0===n.exclude.length||!this.indexer.hasIndex(n.field))return null;const r=this.sequentialCache.previousResult,l=this.sequentialCache.previousCriteriaKey,a=this.sequentialCache.previousBaseData;if(null!==r&&l===i&&a===e)return r;const u=this.getPersistentIndexedResult(i);if(void 0!==u)return this.storePreviousResult(u.result,!0,e,s,i,u.resultSet),u.result;const o=this.createIndexedExcludeView(e,n);return o===e?(this.storePreviousResult(o,!0,e,s,i),o):(this.setPersistentIndexedResult(i,o),this.storePreviousResult(o,!0,e,s,i),o)}createIndexedExcludeView(e,t){const s=this.countIndexedExcludedItems(t);if(0===s)return e;const i={data:e,field:t.field,excludedValues:t.excludedValues,visibleCount:Math.max(0,e.length-s),visibleIndexes:[],nextSourceIndex:0},n=e=>{if(!(e<0||e>=i.visibleCount)){for(;i.visibleIndexes.length<=e;)for(;i.nextSourceIndex<i.data.length;){const e=i.nextSourceIndex;i.nextSourceIndex+=1;const t=i.data[e];if(!i.excludedValues.has(t[i.field])){i.visibleIndexes.push(e);break}}return i.visibleIndexes[e]}},r=new Array(i.visibleCount);return new Proxy(r,{get:(e,t,s)=>{if("length"===t)return i.visibleCount;if(t===Symbol.iterator)return function*(){for(let e=0;e<i.visibleCount;e++){const t=n(e);void 0!==t&&(yield i.data[t])}};if("string"==typeof t){const e=Number(t);if(Number.isInteger(e)&&e>=0){const t=n(e);return void 0===t?void 0:i.data[t]}}return Reflect.get(e,t,s)},has:(e,t)=>{if("string"==typeof t){const e=Number(t);if(Number.isInteger(e)&&e>=0)return e<i.visibleCount}return t in r}})}countIndexedExcludedItems(e){const t=this.indexer.getIndexMap(e.field);if(!t)return 0;const s=/* @__PURE__ */new Set;for(let i=0;i<e.exclude.length;i++){const n=t.get(e.exclude[i]);if(n)for(let e=0;e<n.length;e++){const t=this.state.getItemIndex(n[e]);void 0!==t&&s.add(t)}}return s.size}resolveWithSequentialCache(e,t,s){const{previousResult:i,previousCriteria:n,previousCriteriaKey:r,previousBaseData:l,previousResultsByCriteria:a}=this.sequentialCache;if(null===i||null===n||l!==e)return{isFromCache:!1,sourceData:e,executionCriteria:s};const u=this.createCriteriaCacheKey(s),o=a.get(u);if(u===r)return{isFromCache:!0,result:i};if(void 0!==o)return this.storePreviousResult(o.result,t,e,s,u,o.resultSet),{isFromCache:!0,result:o.result};const d=this.hasCriteriaBacktrack(n,s)||0===i.length&&!this.canApplySequentiallyToEmptyResult(n,s);return{isFromCache:!1,sourceData:d?e:i,executionCriteria:d?s:this.createSequentialExecutionCriteria(n,s)}}withChain(e){return this.chainBuilder.create(e)}handleStateMutation(e){if(!this.shouldDeferMutationIndexUpdates()||"add"!==e.type&&"update"!==e.type)switch(e.type){case"add":return void this.applyAddedItems(e.items);case"update":return void this.applyUpdatedItem(e.previousItem,e.nextItem);case"data":return this.runtime.deferredMutationVersion=null,this.resetFilterState(),this.clearPersistentIndexedResults(),void this.rebuildConfiguredIndexes();case"clearData":return this.runtime.deferredMutationVersion=null,this.indexer.clear(),this.nestedCollection.clearIndexes(),this.clearPersistentIndexedResults(),void this.resetFilterState();case"remove":return void this.applyRemovedItem(e.removedItem);case"removeMany":return void this.applyRemovedItems(e.entries)}else this.markDeferredMutationState()}applyUpdatedItem(e,t){this.resetFilterState(),this.clearPersistentIndexedResults(),this.indexer.updateItem(e,t),this.nestedCollection.updateItem(t,e)}applyRemovedItem(e){this.resetFilterState(),this.clearPersistentIndexedResults(),this.indexer.removeItem(e),this.nestedCollection.removeItem(e)}applyRemovedItems(e){this.clearPersistentIndexedResults();for(let t=0;t<e.length;t++){const s=e[t];this.indexer.removeItem(s.removedItem),this.nestedCollection.removeItem(s.removedItem)}this.resetFilterState()}linearFilter(e,t){const s=[];for(let i=0;i<e.length;i++){const n=e[i];let r=!0;for(let e=0;e<t.length;e++){const s=t[e];if(!c(s,n[s.field])){r=!1;break}}r&&s.push(n)}return s}filterViaIndex(e,t){let s=null;if(t!==this.dataset)if(t===this.sequentialCache.previousResult&&null!==this.sequentialCache.previousResultSet)s=this.sequentialCache.previousResultSet;else if(s=new Set(t),t===this.sequentialCache.previousResult){this.sequentialCache.previousResultSet=s;const e=this.sequentialCache.previousCriteriaKey;if(null!==e){const t=this.sequentialCache.previousResultsByCriteria.get(e);t&&(t.resultSet=s)}}const i=[],n=[];for(let o=0;o<e.length;o++){const t=e[o];t.hasValues&&i.push(t),t.hasExclude&&n.push(t)}if(0===i.length)return this.applyIndexedExclusions(t,n);if(1===i.length){const e=i[0];let t=!1;for(let s=0;s<n.length;s++)if(n[s].field!==e.field){t=!0;break}if(null===s&&!t)return 1===e.values.length?this.indexer.getByValue(e.field,e.values[0]).slice():this.indexer.getByValues(e.field,e.values);const r=this.indexer.getByValues(e.field,e.values),l=[];for(let i=0;i<r.length;i++){const e=r[i];s&&!s.has(e)||l.push(e)}return this.applyIndexedExclusions(l,n)}let r=i[0],l=this.estimateIndexSize(r);for(let o=1;o<i.length;o++){const e=i[o],t=this.estimateIndexSize(e);t<l&&(r=e,l=t)}const a=this.indexer.getByValues(r.field,r.values);if(0===a.length)return[];const u=[];for(let o=0;o<a.length;o++){const e=a[o];let t=!0;if(!s||s.has(e)){for(let s=0;s<i.length;s++){const n=i[s];if(n!==r&&!c(n,e[n.field])){t=!1;break}}t&&u.push(e)}}return this.applyIndexedExclusions(u,n)}estimateIndexSize(e){const t=this.indexer.getIndexMap(e.field);if(!t)return 1/0;let s=0;for(let i=0;i<e.values.length;i++){const n=t.get(e.values[i]);n&&(s+=n.length)}return s}applyIndexedExclusions(e,t){if(0===t.length||0===e.length)return e;if(1===t.length){const s=t[0],i=Array.prototype.filter.call(e,e=>!s.excludedValues.has(e[s.field]));return i.length===e.length?e:i}if(e!==this.dataset)return this.applySubsetExclusions(e,t);const s=new Uint8Array(this.dataset.length);let i=0;for(let l=0;l<t.length;l++){const e=t[l],n=this.indexer.getIndexMap(e.field);if(n)for(let t=0;t<e.exclude.length;t++){const r=n.get(e.exclude[t]);if(r)for(let e=0;e<r.length;e++){const t=this.state.getItemIndex(r[e]);void 0!==t&&1!==s[t]&&(s[t]=1,i+=1)}}}if(0===i)return e;const n=new Array(e.length-i);let r=0;for(let l=0;l<e.length;l++)0===s[l]&&(n[r]=e[l],r+=1);return n}applySubsetExclusions(e,t){const s=new Array(e.length);let i=0;for(let n=0;n<e.length;n++){const r=e[n];let l=!1;for(let e=0;e<t.length;e++){const s=t[e];if(s.excludedValues?.has(r[s.field])){l=!0;break}}l||(s[i]=r,i+=1)}return i===e.length?e:(s.length=i,s)}createEmptyResult(e,t,s){const i=[];return this.storePreviousResult(i,e,t,s),i}storePreviousResult(e,t,s,i,n=this.createCriteriaCacheKey(i),r){if(!this.filterByPreviousResult)return;const l=void 0===r?null:r;if(this.sequentialCache.previousResult=e,this.sequentialCache.previousCriteria=i,this.sequentialCache.previousCriteriaKey=n,this.sequentialCache.previousBaseData=t?this.dataset:s,this.sequentialCache.previousResultSet=l,this.state.setPreviousResult(e,t?this.dataset:s),this.shouldSkipSequentialHistoryCache(i))return;const a=this.sequentialCache.previousResultsByCriteria;if(a.has(n)&&a.delete(n),a.set(n,this.createSequentialCacheEntry(e,l)),a.size>12){const e=a.keys().next().value;void 0!==e&&a.delete(e)}}shouldSkipSequentialHistoryCache(e){if(0===e.length)return!1;for(let t=0;t<e.length;t++){const s=e[t];if(!s.hasExclude||s.hasValues)return!1}return!0}createCriteriaCacheKey(e){let t="";for(let s=0;s<e.length;s++)t+=e[s].cacheKeySegment,t+=";";return t}createSequentialCacheEntry(e,t){return{result:e,resultSet:t}}createSequentialExecutionCriteria(e,t){const s=/* @__PURE__ */new Map;for(let i=0;i<e.length;i++){const t=e[i];s.set(t.field,t)}return t.map(e=>{const t=s.get(e.field);let i=e;if(t&&t.hasValues&&e.hasValues&&!t.hasExclude&&!e.hasExclude&&e.includedValues.size>t.includedValues.size){let s=!0;for(const i of t.includedValues)if(!e.includedValues.has(i)){s=!1;break}if(s){const s=[];for(const i of e.includedValues)t.includedValues.has(i)||s.push(i);s.length>0&&(i={...e,values:s,includedValues:new Set(s)})}}if(t&&t.hasExclude&&i.hasExclude&&this.hasEquivalentSequentialValues(t,i)){const e=t.excludedValues,s=i.excludedValues;if(!this.areSetsEqual(e,s)&&this.isSubset(e,s)){const t=[];for(const i of s)e.has(i)||t.push(i);t.length>0&&(i={...i,exclude:t,excludedValues:new Set(t)})}}return i})}hasEquivalentSequentialValues(e,t){return e.hasValues===t.hasValues&&(!e.hasValues&&!t.hasValues||this.areSetsEqual(e.includedValues,t.includedValues))}hasCriteriaBacktrack(e,t){const s=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(const[n,r]of s){const e=i.get(n);if(!e)return!0;if(this.isCriterionBacktracked(r,e))return!0}return!1}canApplySequentiallyToEmptyResult(e,t){const s=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(const[n,r]of i){const e=s.get(n);if(e){if(e.hasValues!==r.hasValues&&(e.hasValues||!r.hasValues))return!1;if(e.hasValues&&r.hasValues){const t=e.includedValues,s=r.includedValues;if(!this.areSetsEqual(t,s)&&!this.isSubset(t,s))return!1}if(e.hasExclude!==r.hasExclude&&(e.hasExclude||!r.hasExclude))return!1;if(e.hasExclude&&r.hasExclude){const t=e.excludedValues,s=r.excludedValues;if(!this.areSetsEqual(t,s)&&!this.isSubset(t,s))return!1}}}return!0}createCriteriaStateMap(e){const t=/* @__PURE__ */new Map;for(let s=0;s<e.length;s++){const i=e[s];t.set(i.field,i)}return t}isCriterionBacktracked(e,t){if(e.hasValues&&!t.hasValues)return!0;if(e.hasValues&&t.hasValues){const s=e.includedValues,i=t.includedValues;if(!this.areSetsEqual(s,i))return this.isSubset(i,s)}if(!e.hasValues&&t.hasValues)return!1;if(e.hasExclude&&!t.hasExclude)return!0;if(!e.hasExclude&&t.hasExclude)return!1;if(e.hasExclude&&t.hasExclude){const s=e.excludedValues,i=t.excludedValues;if(!this.areSetsEqual(s,i))return this.isSubset(i,s)}return!1}isSubset(e,t){for(const s of e)if(!t.has(s))return!1;return!0}areSetsEqual(e,t){if(e===t)return!0;if(!e||!t||e.size!==t.size)return!1;for(const s of e)if(!t.has(s))return!1;return!0}};export{y as FilterEngine};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,2 @@
1
- export { MergeEngines } from "./merge";
2
- export type { MergeEnginesOptions, EngineApi, EngineConstructor, MergeEnginesChain, MergeModuleName, } from "./merge";
3
- export type { CollectionItem, FilterCriterion, SortDescriptor, SortDirection, IndexableKey, UpdateDescriptor, } from "./types";
4
- //# sourceMappingURL=index.d.ts.map
1
+ export { EngineApi, EngineConstructor, MergeEngines, MergeEnginesChain, MergeEnginesOptions, MergeModuleName } from './merge/index.js';
2
+ export { C as CollectionItem, F as FilterCriterion, I as IndexableKey, d as SortDescriptor, e as SortDirection, U as UpdateDescriptor } from './types-DONld7xY.js';
package/dist/index.mjs CHANGED
@@ -1,2 +1 @@
1
- import { MergeEngines as e } from "./merge/merge-engines.mjs";
2
- export { e as MergeEngines };
1
+ import{t as m}from"./chunks/merge-C6intZSe.mjs";export{m as MergeEngines};