@devisfuture/mega-collection 2.4.8 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -75
- package/dist/chunks/{constants-BXQI1M5E.mjs → constants-DK9S0Db0.mjs} +1 -1
- package/dist/chunks/merge-C6intZSe.mjs +1 -0
- package/dist/filter/index.d.ts +16 -13
- package/dist/filter/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/merge/index.d.ts +7 -4
- package/dist/merge/index.mjs +1 -1
- package/dist/search/index.d.ts +4 -3
- package/dist/search/index.mjs +1 -1
- package/dist/sort/index.d.ts +3 -1
- package/dist/sort/index.mjs +1 -1
- package/package.json +2 -1
- package/dist/chunks/internal-COJC3Ik3.mjs +0 -1
- package/dist/chunks/merge-BRXHTBZ0.mjs +0 -1
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
|
|
@@ -155,6 +155,29 @@ These fields are used for indexes.
|
|
|
155
155
|
Indexes are built lazily on first use inside that shared state, so engine creation stays fast.
|
|
156
156
|
If you skip `fields`, everything still works, but the engine may scan the full array.
|
|
157
157
|
|
|
158
|
+
### Import
|
|
159
|
+
|
|
160
|
+
This section demonstrates extracting the final result after chained `search`, `sort`, and `filter` calls. Engine methods return an iterable/array-like result that may be evaluated, which enables convenient chaining.
|
|
161
|
+
|
|
162
|
+
It is best practice to convert the final result using `Array.from(...)` into an array before using it in UI or passing it further in your app:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const result1 = engine.search("Mia 1210"); // search result
|
|
166
|
+
console.log(Array.from(result1)); // clear array
|
|
167
|
+
|
|
168
|
+
const result2 = engine
|
|
169
|
+
.search("john")
|
|
170
|
+
.sort([{ field: "age", direction: "asc" }])
|
|
171
|
+
.filter([{ field: "city", values: ["Miami", "New York"] }]); // combined result
|
|
172
|
+
|
|
173
|
+
console.log(Array.from(result2)); // clear array
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
This is an example of result `const result1 = engine.search("Mia 1210");`:
|
|
177
|
+

|
|
178
|
+
|
|
179
|
+
The image shows that the result can be a combination of operations from `search`, `sort`, and `filter`. This combined result is intentional for easy method chaining, and you should call `Array.from(...)` on the final result when you need a stable, ready-to-use array.
|
|
180
|
+
|
|
158
181
|
```ts
|
|
159
182
|
import { MergeEngines } from "@devisfuture/mega-collection";
|
|
160
183
|
import { TextSearchEngine } from "@devisfuture/mega-collection/search";
|
|
@@ -173,7 +196,7 @@ const engine = new MergeEngines<User>({
|
|
|
173
196
|
const mutableMerge = new MergeEngines<User>({
|
|
174
197
|
imports: [FilterEngine],
|
|
175
198
|
data: users,
|
|
176
|
-
filter: { fields: ["id", "city"]
|
|
199
|
+
filter: { fields: ["id", "city"] },
|
|
177
200
|
});
|
|
178
201
|
|
|
179
202
|
// Dataset is passed once in the constructor.
|
|
@@ -228,7 +251,7 @@ engine.clearData("search").clearData("sort").clearData("filter");
|
|
|
228
251
|
engine.getOriginData();
|
|
229
252
|
|
|
230
253
|
// Remove items through the root facade.
|
|
231
|
-
mutableMerge.
|
|
254
|
+
mutableMerge.delete("id", [1, 4]);
|
|
232
255
|
```
|
|
233
256
|
|
|
234
257
|
---
|
|
@@ -363,6 +386,68 @@ searchEngine.update({
|
|
|
363
386
|
|
|
364
387
|
---
|
|
365
388
|
|
|
389
|
+
### Delete items with `delete(...)`
|
|
390
|
+
|
|
391
|
+
Use `delete(...)` when you need to remove stored items from the original dataset by a unique field such as `id`.
|
|
392
|
+
|
|
393
|
+
- `delete(...)` changes the stored dataset.
|
|
394
|
+
- removal uses **swap-pop**, so order is not preserved.
|
|
395
|
+
- indexed engines update their internal state from the shared `State` mutation instead of rebuilding the full dataset.
|
|
396
|
+
- the target field values must be unique for the values you remove.
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
import { MergeEngines } from "@devisfuture/mega-collection";
|
|
400
|
+
import { TextSearchEngine } from "@devisfuture/mega-collection/search";
|
|
401
|
+
import { SortEngine } from "@devisfuture/mega-collection/sort";
|
|
402
|
+
import { FilterEngine } from "@devisfuture/mega-collection/filter";
|
|
403
|
+
|
|
404
|
+
const merge = new MergeEngines<User>({
|
|
405
|
+
imports: [TextSearchEngine, SortEngine, FilterEngine],
|
|
406
|
+
data: users,
|
|
407
|
+
search: { fields: ["name", "city"], minQueryLength: 2 },
|
|
408
|
+
filter: { fields: ["id", "city"] },
|
|
409
|
+
sort: { fields: ["age", "name"] },
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
merge.delete("id", [1, 4]);
|
|
413
|
+
|
|
414
|
+
merge.getOriginData();
|
|
415
|
+
merge.search("Kyiv");
|
|
416
|
+
merge.filter([{ field: "city", values: ["Lviv"] }]);
|
|
417
|
+
merge.sort([{ field: "age", direction: "asc" }]);
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
The same method works in each engine:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
import { TextSearchEngine } from "@devisfuture/mega-collection/search";
|
|
424
|
+
import { FilterEngine } from "@devisfuture/mega-collection/filter";
|
|
425
|
+
import { SortEngine } from "@devisfuture/mega-collection/sort";
|
|
426
|
+
|
|
427
|
+
const searchEngine = new TextSearchEngine<User>({
|
|
428
|
+
data: users,
|
|
429
|
+
fields: ["name", "city"],
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
searchEngine.delete("id", 2);
|
|
433
|
+
|
|
434
|
+
const filterEngine = new FilterEngine<User>({
|
|
435
|
+
data: users,
|
|
436
|
+
fields: ["id", "city"],
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
filterEngine.delete("id", [1, 4]);
|
|
440
|
+
|
|
441
|
+
const sortEngine = new SortEngine<User>({
|
|
442
|
+
data: users,
|
|
443
|
+
fields: ["age", "name"],
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
sortEngine.delete("id", 3);
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
366
451
|
### Search only
|
|
367
452
|
|
|
368
453
|
Use `TextSearchEngine` when you only need text search.
|
|
@@ -398,6 +483,9 @@ engine.update({
|
|
|
398
483
|
data: { id: 2, name: "Bob", city: "Paris", age: 19 },
|
|
399
484
|
});
|
|
400
485
|
|
|
486
|
+
// remove one stored item by unique field
|
|
487
|
+
engine.delete("id", 2);
|
|
488
|
+
|
|
401
489
|
// access original dataset stored in the engine
|
|
402
490
|
engine.getOriginData();
|
|
403
491
|
|
|
@@ -456,6 +544,9 @@ engine.update({
|
|
|
456
544
|
data: { id: 2, name: "Bob", city: "Paris", age: 19, active: true },
|
|
457
545
|
});
|
|
458
546
|
|
|
547
|
+
// Remove stored items by unique field.
|
|
548
|
+
engine.delete("id", [1, 4]);
|
|
549
|
+
|
|
459
550
|
// Get original stored dataset.
|
|
460
551
|
engine.getOriginData();
|
|
461
552
|
|
|
@@ -475,12 +566,7 @@ This is useful when you already know which `id` values or other field values sho
|
|
|
475
566
|
|
|
476
567
|
`exclude` changes only the returned result. It does not change the stored dataset inside the engine.
|
|
477
568
|
|
|
478
|
-
|
|
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.
|
|
569
|
+
`exclude` is always result-only. It never changes the stored dataset inside the engine.
|
|
484
570
|
|
|
485
571
|
#### Result-only exclude
|
|
486
572
|
|
|
@@ -492,10 +578,8 @@ so the engine still needs one pass over the current data to build the result.
|
|
|
492
578
|
If `id` is indexed, the engine does not scan the full dataset again for each excluded `id`,
|
|
493
579
|
but it still has to build the final array.
|
|
494
580
|
|
|
495
|
-
If you need
|
|
496
|
-
|
|
497
|
-
In this mode the engine removes items from the stored dataset with swap-pop.
|
|
498
|
-
Order is not preserved.
|
|
581
|
+
If you need to remove items from the stored dataset itself, use `delete(...)`.
|
|
582
|
+
That operation is separate from filtering so result-only `exclude` stays predictable.
|
|
499
583
|
|
|
500
584
|
If the field is listed in `fields`, the engine uses indexes for exclude values
|
|
501
585
|
instead of scanning the full dataset again for every removed value.
|
|
@@ -518,55 +602,6 @@ engine.filter([
|
|
|
518
602
|
]);
|
|
519
603
|
```
|
|
520
604
|
|
|
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
605
|
#### Nested collections filter
|
|
571
606
|
|
|
572
607
|
```ts
|
|
@@ -614,6 +649,9 @@ engine.update({
|
|
|
614
649
|
data: { id: 2, name: "Bob", city: "Paris", age: 19 },
|
|
615
650
|
});
|
|
616
651
|
|
|
652
|
+
// remove one stored item by unique field
|
|
653
|
+
engine.delete("id", 2);
|
|
654
|
+
|
|
617
655
|
// access original dataset stored in the engine
|
|
618
656
|
engine.getOriginData();
|
|
619
657
|
|
|
@@ -644,7 +682,7 @@ One class that combines search, filter, and sort for the same dataset.
|
|
|
644
682
|
| `data` | `T[]` | Shared dataset — passed once at construction |
|
|
645
683
|
| `filterByPreviousResult` | `boolean` | When `true`, separate `filter(...)` and `sort(...)` calls continue from the last result stored in shared State |
|
|
646
684
|
| `search` | `{ fields, nestedFields?, minQueryLength? }` | Config for TextSearchEngine |
|
|
647
|
-
| `filter` | `{ fields, nestedFields
|
|
685
|
+
| `filter` | `{ fields, nestedFields? }` | Config for FilterEngine |
|
|
648
686
|
| `sort` | `{ fields }` | Config for SortEngine |
|
|
649
687
|
|
|
650
688
|
**Methods:**
|
|
@@ -659,6 +697,7 @@ One class that combines search, filter, and sort for the same dataset.
|
|
|
659
697
|
| `filter(data, criteria)` | Filter with an explicit dataset |
|
|
660
698
|
| `getOriginData()` | Get the shared original dataset |
|
|
661
699
|
| `add(items)` | Append multiple items to the stored dataset and update existing indexes or caches for new items only |
|
|
700
|
+
| `delete(field, valueOrValues)` | Remove stored items by unique field value using swap-pop semantics |
|
|
662
701
|
| `update({ field, data })` | Replace one stored item by a unique field and refresh only the affected cached or indexed data |
|
|
663
702
|
| `data(data)` | Replace stored dataset for all imported modules, rebuilding configured indexes and resetting filter state where applicable |
|
|
664
703
|
| `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
|
|
@@ -687,6 +726,7 @@ Main constructor options:
|
|
|
687
726
|
| `resetSearchState()` | Reset previous-result state for sequential narrowing search |
|
|
688
727
|
| `getOriginData()` | Get the original stored dataset |
|
|
689
728
|
| `add(items)` | Append multiple items to the stored dataset |
|
|
729
|
+
| `delete(field, valueOrValues)` | Remove stored items by unique field value |
|
|
690
730
|
| `update({ field, data })` | Replace one stored item by a unique field |
|
|
691
731
|
| `data(data)` | Replace stored dataset and rebuild configured indexes |
|
|
692
732
|
| `clearIndexes()` | Clear n-gram indexes (including nested) |
|
|
@@ -705,20 +745,20 @@ Main constructor options:
|
|
|
705
745
|
| Option | Type | Description |
|
|
706
746
|
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
707
747
|
| `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
748
|
| `nestedFields` | `string[]` | Nested field paths in dot notation, for example `["orders.status"]`. |
|
|
710
749
|
|
|
711
|
-
| Method
|
|
712
|
-
|
|
|
713
|
-
| `filter(criteria)`
|
|
714
|
-
| `filter(data, criteria)`
|
|
715
|
-
| `getOriginData()`
|
|
716
|
-
| `add(items)`
|
|
717
|
-
| `
|
|
718
|
-
| `
|
|
719
|
-
| `
|
|
720
|
-
| `
|
|
721
|
-
| `
|
|
750
|
+
| Method | Description |
|
|
751
|
+
| ------------------------------ | -------------------------------------------------------------------------- |
|
|
752
|
+
| `filter(criteria)` | Filter using stored dataset (supports nested field criteria) |
|
|
753
|
+
| `filter(data, criteria)` | Filter with an explicit dataset |
|
|
754
|
+
| `getOriginData()` | Get the original stored dataset |
|
|
755
|
+
| `add(items)` | Append multiple items to the stored dataset |
|
|
756
|
+
| `delete(field, valueOrValues)` | Remove stored items by unique field value |
|
|
757
|
+
| `update({ field, data })` | Replace one stored item by a unique field |
|
|
758
|
+
| `data(data)` | Replace stored dataset, rebuild configured indexes, and reset filter state |
|
|
759
|
+
| `resetFilterState()` | Reset previous-result state for sequential filtering |
|
|
760
|
+
| `clearIndexes()` | Free all index memory (including nested indexes) |
|
|
761
|
+
| `clearData()` | Clear stored data |
|
|
722
762
|
|
|
723
763
|
### `SortEngine<T>` (sort module)
|
|
724
764
|
|
|
@@ -731,6 +771,7 @@ Sort methods return plain arrays.
|
|
|
731
771
|
| `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
|
|
732
772
|
| `getOriginData()` | Get the original stored dataset |
|
|
733
773
|
| `add(items)` | Append multiple items to the stored dataset |
|
|
774
|
+
| `delete(field, valueOrValues)` | Remove stored items by unique field value |
|
|
734
775
|
| `update({ field, data })` | Replace one stored item by a unique field |
|
|
735
776
|
| `data(data)` | Replace stored dataset and rebuild configured indexes |
|
|
736
777
|
| `clearIndexes()` | Free all cached indexes |
|
|
@@ -1 +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
|
|
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};
|
package/dist/filter/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { S as State } from '../State-CYIe-3He.js';
|
|
2
|
-
import { C as CollectionItem, F as FilterCriterion, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
3
|
-
export { I as IndexableKey } from '../types-DONld7xY.js';
|
|
2
|
+
import { C as CollectionItem, F as FilterCriterion, I as IndexableKey, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
4
3
|
|
|
5
4
|
interface FilterEngineChain<T extends CollectionItem> {
|
|
6
5
|
filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
|
|
7
6
|
filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
|
|
8
7
|
getOriginData(): T[];
|
|
9
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>;
|
|
10
11
|
update(descriptor: UpdateDescriptor<T>): FilterEngine<T>;
|
|
11
12
|
data(data: T[]): FilterEngine<T>;
|
|
12
13
|
clearIndexes(): FilterEngine<T>;
|
|
@@ -15,7 +16,6 @@ interface FilterEngineChain<T extends CollectionItem> {
|
|
|
15
16
|
}
|
|
16
17
|
interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
17
18
|
data?: T[];
|
|
18
|
-
mutableExcludeField?: keyof T & string;
|
|
19
19
|
fields?: (keyof T & string)[];
|
|
20
20
|
nestedFields?: string[];
|
|
21
21
|
filterByPreviousResult?: boolean;
|
|
@@ -29,7 +29,6 @@ interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
|
29
29
|
declare class FilterEngine<T extends CollectionItem> {
|
|
30
30
|
private readonly indexer;
|
|
31
31
|
private readonly filterByPreviousResult;
|
|
32
|
-
private readonly mutableExcludeField;
|
|
33
32
|
private readonly state;
|
|
34
33
|
private readonly namespace;
|
|
35
34
|
private readonly nestedCollection;
|
|
@@ -42,13 +41,16 @@ declare class FilterEngine<T extends CollectionItem> {
|
|
|
42
41
|
});
|
|
43
42
|
private get dataset();
|
|
44
43
|
private get runtime();
|
|
45
|
-
private get mutableExcludeState();
|
|
46
44
|
private get indexedFields();
|
|
47
45
|
private get sequentialCache();
|
|
46
|
+
private get persistentIndexedResults();
|
|
48
47
|
private shouldDeferMutationIndexUpdates;
|
|
49
48
|
private markDeferredMutationState;
|
|
50
49
|
private ensureRuntimeReady;
|
|
51
50
|
private rebuildConfiguredIndexes;
|
|
51
|
+
private clearPersistentIndexedResults;
|
|
52
|
+
private getPersistentIndexedResult;
|
|
53
|
+
private setPersistentIndexedResult;
|
|
52
54
|
/**
|
|
53
55
|
* Builds an index for the given field.
|
|
54
56
|
*/
|
|
@@ -58,6 +60,8 @@ declare class FilterEngine<T extends CollectionItem> {
|
|
|
58
60
|
clearData(): this;
|
|
59
61
|
data(data: T[]): this;
|
|
60
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;
|
|
61
65
|
update(descriptor: UpdateDescriptor<T>): this;
|
|
62
66
|
private applyAddedItems;
|
|
63
67
|
getOriginData(): T[];
|
|
@@ -68,19 +72,15 @@ declare class FilterEngine<T extends CollectionItem> {
|
|
|
68
72
|
filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
|
|
69
73
|
rawFilter(criteria: FilterCriterion<T>[]): T[];
|
|
70
74
|
rawFilter(data: T[], criteria: FilterCriterion<T>[]): T[];
|
|
75
|
+
private tryFastStoredExcludeView;
|
|
76
|
+
private createIndexedExcludeView;
|
|
77
|
+
private countIndexedExcludedItems;
|
|
71
78
|
private resolveWithSequentialCache;
|
|
72
79
|
private withChain;
|
|
73
80
|
private handleStateMutation;
|
|
74
|
-
private rebuildMutableExcludeState;
|
|
75
|
-
private updateMutableExcludeStateForAddedItems;
|
|
76
|
-
private applyMutableExclude;
|
|
77
81
|
private applyUpdatedItem;
|
|
78
82
|
private applyRemovedItem;
|
|
79
83
|
private applyRemovedItems;
|
|
80
|
-
private updateMutableExcludeStateForUpdatedItem;
|
|
81
|
-
private clearMutableExcludeState;
|
|
82
|
-
private registerMutableExcludeValue;
|
|
83
|
-
private unregisterMutableExcludeValue;
|
|
84
84
|
/**
|
|
85
85
|
* Filters data linearly without index.
|
|
86
86
|
*/
|
|
@@ -94,11 +94,14 @@ declare class FilterEngine<T extends CollectionItem> {
|
|
|
94
94
|
*/
|
|
95
95
|
private estimateIndexSize;
|
|
96
96
|
private applyIndexedExclusions;
|
|
97
|
+
private applySubsetExclusions;
|
|
97
98
|
private createEmptyResult;
|
|
98
99
|
private storePreviousResult;
|
|
100
|
+
private shouldSkipSequentialHistoryCache;
|
|
99
101
|
private createCriteriaCacheKey;
|
|
100
102
|
private createSequentialCacheEntry;
|
|
101
103
|
private createSequentialExecutionCriteria;
|
|
104
|
+
private hasEquivalentSequentialValues;
|
|
102
105
|
private hasCriteriaBacktrack;
|
|
103
106
|
private canApplySequentiallyToEmptyResult;
|
|
104
107
|
private createCriteriaStateMap;
|
|
@@ -107,5 +110,5 @@ declare class FilterEngine<T extends CollectionItem> {
|
|
|
107
110
|
private areSetsEqual;
|
|
108
111
|
}
|
|
109
112
|
|
|
110
|
-
export { CollectionItem, FilterCriterion, FilterEngine };
|
|
113
|
+
export { CollectionItem, FilterCriterion, FilterEngine, IndexableKey };
|
|
111
114
|
export type { FilterEngineChain, FilterEngineOptions };
|
package/dist/filter/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,t as s}from"../chunks/constants-BXQI1M5E.mjs";import{n as i,t as l}from"../chunks/internal-COJC3Ik3.mjs";var a=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 l=0,a=e.length;l<a;l++){const a=e[l],r=a[t];if(null==r)continue;const n=s.get(r);if(n)n.push(a),i.get(r).set(a,n.length-1);else{s.set(r,[a]);const e=/* @__PURE__ */new WeakMap;e.set(a,0),i.set(r,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 l=0;l<t.length;l++){const e=s.get(t[l]);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),l=this.storage.itemPositions.get(e),a=i?.get(s),r=l?.get(s),n=r?.get(t);if(!(i&&l&&a&&r&&void 0!==n))return;const u=a.length-1,d=a[u];n!==u&&(a[n]=d,r.set(d,n)),a.pop(),r.delete(t),0===a.length&&(i.delete(s),l.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 l=this.storage.indexes.get(e),a=this.storage.itemPositions.get(e),r=l?.get(t),n=a?.get(t),u=n?.get(s);r&&n&&void 0!==u&&(r[u]=i,n.delete(s),n.set(i,u))}addItemToField(e,t){const s=t[e];if(null==s)return;const i=this.storage.indexes.get(e),l=this.storage.itemPositions.get(e);if(!i||!l)return;const a=i.get(s),r=l.get(s);if(a&&r)return a.push(t),void r.set(t,a.length-1);i.set(s,[t]);const n=/* @__PURE__ */new WeakMap;n.set(t,0),l.set(s,n)}},r=class{constructor(e){this.callbacks=e}create(e){const t=e;return Object.defineProperties(t,{filter:l((t,s)=>void 0===s?this.callbacks.filter(e,t):this.callbacks.filter(t,s)),add:l(e=>this.callbacks.add(e)),update:l(e=>this.callbacks.update(e)),clearIndexes:l(()=>this.callbacks.clearIndexes()),data:l(e=>this.callbacks.data(e)),getOriginData:l(()=>this.callbacks.getOriginData()),clearData:l(()=>this.callbacks.clearData()),resetFilterState:l(()=>this.callbacks.resetFilterState())}),t}},n=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().")}static duplicateMutableExcludeField(t){return new e(`FilterEngine: cannot use mutable exclude on field \`${t}\` because it contains duplicate values.`)}};function u(e){const t=/* @__PURE__ */new Map;for(let i=0;i<e.length;i++){const s=e[i],l=Array.isArray(s.values),a=h(s.exclude),r=null!==a,n=l?c(s.values,a):null;if(!l&&!r)continue;const u=s.field,d=t.get(u);if(d){if(l)if(d.hasValues)for(const e of d.includedValues)n.has(e)||d.includedValues.delete(e);else d.hasValues=!0,d.includedValues=new Set(n);if(r)if(d.hasExclude)for(const e of a)d.excludedValues.add(e);else d.hasExclude=!0,d.excludedValues=new Set(a)}else t.set(u,{field:s.field,values:[],exclude:[],hasValues:l,hasExclude:r,includedValues:n?new Set(n):null,excludedValues:a?new Set(a):null,cacheKeySegment:""})}const s=[...t.values()].sort((e,t)=>e.field.localeCompare(t.field));for(let i=0;i<s.length;i++)f(s[i]);return s}function d(e,t){return!(e.hasValues&&!e.includedValues.has(t)||e.hasExclude&&e.excludedValues.has(t))}function o(e){return e.hasValues&&0===e.values.length}function h(e){return Array.isArray(e)&&0!==e.length?new Set(e):null}function c(e,t){const s=/* @__PURE__ */new Set;for(let i=0;i<e.length;i++){const l=e[i];t?.has(l)||s.add(l)}return s}function f(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+=g(e.values)),t+=`|hx:${e.hasExclude?"1":"0"}|x:`,e.hasExclude&&(t+=g(e.exclude)),t}(e)}function g(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 x=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 l=[],a=[];for(let n=0;n<i.length;n++){const e=i[n];this.storage.indexes.has(e.field)?l.push(e):a.push(e)}let r=e;if(l.length>0&&(r=this.filterByIndexes(l,e,s),0===r.length))return r;for(let n=0;n<a.length;n++)if(r=this.filterLinearly(r,a[n]),0===r.length)return r;return r}resolveCriteria(e){if(0===e.length)return[];const t=e[0];return"hasValues"in t&&"hasExclude"in t&&"includedValues"in t?e:u(e)}registerField(e){const t=i(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:l}=s,a=/* @__PURE__ */new Map,r=/* @__PURE__ */new Map;for(let n=0,u=e.length;n<u;n++){const t=e[n],s=t[i];if(Array.isArray(s))for(let e=0;e<s.length;e++){const i=s[e][l];if(null==i)continue;const n=a.get(i);if(n){n[n.length-1]!==t&&(n.push(t),r.get(i).set(t,n.length-1));continue}a.set(i,[t]);const u=/* @__PURE__ */new WeakMap;u.set(t,0),r.set(i,u)}}this.storage.indexes.set(t,a),this.storage.itemPositions.set(t,r)}removeItemFromIndex(e,t){const s=this.fieldDescriptors.get(e),i=this.storage.indexes.get(e),l=this.storage.itemPositions.get(e);if(!s||!i||!l)return;const{collectionKey:a,nestedKey:r}=s,n=t[a];if(!Array.isArray(n)||0===n.length)return;const u=/* @__PURE__ */new Set;for(let d=0;d<n.length;d++){const e=n[d][r];null!=e&&u.add(e)}for(const d of u){const e=i.get(d),s=l.get(d),a=s?.get(t);if(!e||!s||void 0===a)continue;const r=e.length-1,n=e[r];a!==r&&(e[a]=n,s.set(n,a)),e.pop(),s.delete(t),0===e.length&&(i.delete(d),l.delete(d))}}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),l=this.storage.itemPositions.get(e);if(!s||!i||!l)return;const{collectionKey:a,nestedKey:r}=s,n=t[a];if(!Array.isArray(n)||0===n.length)return;const u=/* @__PURE__ */new Set;for(let d=0;d<n.length;d++){const e=n[d][r];null!=e&&u.add(e)}for(const d of u){const e=i.get(d),s=l.get(d);if(e&&s){e.push(t),s.set(t,e.length-1);continue}i.set(d,[t]);const a=/* @__PURE__ */new WeakMap;a.set(t,0),l.set(d,a)}}updateItemInIndex(e,t,s){const i=this.fieldDescriptors.get(e),l=this.storage.indexes.get(e),a=this.storage.itemPositions.get(e);if(!i||!l||!a)return;const r=this.collectUniqueValues(s,i),n=this.collectUniqueValues(t,i);if(this.areValueSetsEqual(r,n))for(const u of r){const e=l.get(u),i=a.get(u),r=i?.get(s);e&&i&&void 0!==r&&(e[r]=t,i.delete(s),i.set(t,r))}else this.removeItemFromIndex(e,s),this.addItemToIndex(e,t)}collectUniqueValues(e,t){const{collectionKey:s,nestedKey:i}=t,l=e[s],a=/* @__PURE__ */new Set;if(!Array.isArray(l)||0===l.length)return a;for(let r=0;r<l.length;r++){const e=l[r][i];null!=e&&a.add(e)}return a}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),l=e.filter(e=>e.hasExclude),a=t===s?null:new Set(t);if(0===i.length)return this.applyIndexedExclusions(t,l);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];a&&!a.has(e)||s.push(e)}return this.applyIndexedExclusions(s,l)}const r=i.map(e=>({criterion:e,size:this.estimateIndexSize(e)})).sort((e,t)=>e.size-t.size);let n=a,u=[];for(let d=0;d<r.length;d++){const{criterion:e}=r[d],t=this.storage.indexes.get(e.field);if(!t)return[];const s=this.getItemsByValues(t,e.values);if(0===s.length)return[];if(null===n)u=s;else{u=[];for(let e=0;e<s.length;e++){const t=s[e];n.has(t)&&u.push(t)}}if(0===u.length)return[];n=new Set(u)}return this.applyIndexedExclusions(u,l)}getItemsByValues(e,t){if(1===t.length)return e.get(t[0])??[];const s=/* @__PURE__ */new Set,i=[];for(let l=0;l<t.length;l++){const a=e.get(t[l]);if(a)for(let e=0;e<a.length;e++){const t=a[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:l}=s,a=[];for(let r=0;r<e.length;r++){const s=e[r],n=s[i];if(!Array.isArray(n))continue;let u=!t.hasValues,d=!1;for(let e=0;e<n.length;e++){const s=n[e][l];if(t.hasExclude&&t.excludedValues.has(s)){d=!0;break}t.hasValues&&t.includedValues.has(s)&&(u=!0)}!d&&u&&a.push(s)}return a}applyIndexedExclusions(e,t){if(0===t.length||0===e.length)return e;const s=/* @__PURE__ */new Set;for(let l=0;l<t.length;l++){const e=t[l],i=this.storage.indexes.get(e.field);if(!i)continue;const a=this.getItemsByValues(i,e.exclude);for(let t=0;t<a.length;t++)s.add(a[t])}if(0===s.size)return e;const i=[];for(let l=0;l<e.length;l++){const t=e[l];s.has(t)||i.push(t)}return i}},m=()=>({indexedFields:/* @__PURE__ */new Set,indexerStorage:{indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map},nestedStorage:{indexes:/* @__PURE__ */new Map,itemPositions:/* @__PURE__ */new Map},deferredMutationVersion:null,mutableExclude:{datasetPositions:/* @__PURE__ */new Map,valueCounts:/* @__PURE__ */new Map,duplicateValueCount:0,hasDuplicateValues:!1},sequentialCache:{previousResult:null,previousCriteria:null,previousCriteriaKey:null,previousBaseData:null,previousResultsByCriteria:/* @__PURE__ */new Map,previousResultSet:null}}),p=class{constructor(t={}){this.chainBuilder=new r({filter:(e,t)=>void 0===t?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),add:e=>this.add(e),update:e=>this.update(e),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()}),this.mutableExcludeField=t.mutableExcludeField??null,this.state=t.state??new e(t.data??[],{filterByPreviousResult:t.filterByPreviousResult??!1}),t.state&&t.filterByPreviousResult&&this.state.setFilterByPreviousResult(!0),this.filterByPreviousResult=this.state.isFilterByPreviousResultEnabled(),this.namespace=this.state.createNamespace("filter"),this.indexer=new a(this.runtime.indexerStorage),this.nestedCollection=new x(this.runtime.nestedStorage),this.nestedCollection.registerFields(t.nestedFields),this.state.subscribe(e=>this.handleStateMutation(e)),this.rebuildMutableExcludeState();const s=t.fields?.length,i=this.nestedCollection.hasRegisteredFields();if(s)for(const e of t.fields)this.indexedFields.add(e);this.dataset.length>0&&(s||i)&&this.rebuildConfiguredIndexes()}get dataset(){return this.state.getOriginData()}get runtime(){return this.state.getOrCreateScopedValue(this.namespace,"runtime",m)}get mutableExcludeState(){return this.runtime.mutableExclude}get indexedFields(){return this.runtime.indexedFields}get sequentialCache(){return this.runtime.sequentialCache}shouldDeferMutationIndexUpdates(){return!0===this.state.getScopedValue(t,s)}markDeferredMutationState(){this.runtime.deferredMutationVersion=this.state.getMutationVersion(),this.indexer.clear(),this.nestedCollection.clearIndexes(),this.clearMutableExcludeState(),this.resetFilterState()}ensureRuntimeReady(){null!==this.runtime.deferredMutationVersion&&(this.runtime.deferredMutationVersion=null,this.rebuildMutableExcludeState(),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)}buildIndex(e,t){if(!Array.isArray(e)){if(!this.dataset.length)throw n.missingDatasetForBuildIndex();return this.indexer.buildIndex(this.dataset,e),this}return this.resetFilterState(),this.rebuildMutableExcludeState(),this.indexer.buildIndex(e,t),this}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),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}update(e){return this.state.update(e),this}applyAddedItems(e,t){return 0===e.length||(this.updateMutableExcludeStateForAddedItems(e,t),this.resetFilterState(),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;if(s&&!this.dataset.length)throw n.missingDatasetForFilter();const i=u(s?e:t),l=s?this.dataset:e;if(s){const e=this.applyMutableExclude(i);if(void 0!==e)return e}let a=l,r=i;if(this.filterByPreviousResult){const e=this.resolveWithSequentialCache(l,s,i);if(e.isFromCache)return e.result;a=e.sourceData,r=e.executionCriteria}if(0===i.length)return this.filterByPreviousResult&&this.resetFilterState(),l;for(let n=0;n<r.length;n++)if(o(r[n]))return this.createEmptyResult(s,l,i);const d=[],h=[];for(let n=0;n<r.length;n++){const e=r[n];this.nestedCollection.hasField(e.field)?d.push(e):h.push(e)}if(d.length>0&&(a=this.nestedCollection.filter(a,d,this.dataset),0===a.length))return this.createEmptyResult(s,l,i);if(0===h.length)return this.storePreviousResult(a,s,l,i),a;const c=[],f=[];for(let n=0;n<h.length;n++){const e=h[n];this.indexer.hasIndex(e.field)?c.push(e):f.push(e)}let g;if(c.length>0&&0===f.length)return g=this.filterViaIndex(c,a),this.storePreviousResult(g,s,l,i),g;if(c.length>0&&f.length>0){const e=this.filterViaIndex(c,a);return g=this.linearFilter(e,f),this.storePreviousResult(g,s,l,i),g}return g=this.linearFilter(a,h),this.storePreviousResult(g,s,l,i),g}resolveWithSequentialCache(e,t,s){const{previousResult:i,previousCriteria:l,previousCriteriaKey:a,previousBaseData:r,previousResultsByCriteria:n}=this.sequentialCache;if(null===i||null===l||r!==e)return{isFromCache:!1,sourceData:e,executionCriteria:s};const u=this.createCriteriaCacheKey(s),d=n.get(u);if(u===a)return{isFromCache:!0,result:i};if(void 0!==d)return this.storePreviousResult(d.result,t,e,s,u,d.resultSet),{isFromCache:!0,result:d.result};const o=this.hasCriteriaBacktrack(l,s)||0===i.length&&!this.canApplySequentiallyToEmptyResult(l,s);return{isFromCache:!1,sourceData:o?e:i,executionCriteria:o?s:this.createSequentialExecutionCriteria(l,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,e.startIndex);case"update":return void this.applyUpdatedItem(e.index,e.previousItem,e.nextItem);case"data":return this.runtime.deferredMutationVersion=null,this.rebuildMutableExcludeState(),this.resetFilterState(),void this.rebuildConfiguredIndexes();case"clearData":return this.runtime.deferredMutationVersion=null,this.clearMutableExcludeState(),this.indexer.clear(),this.nestedCollection.clearIndexes(),void this.resetFilterState();case"remove":return void this.applyRemovedItem(e.field,e.value,e.removedItem,e.removedIndex,e.movedItem);case"removeMany":return void this.applyRemovedItems(e.field,e.entries)}else this.markDeferredMutationState()}rebuildMutableExcludeState(){if(this.clearMutableExcludeState(),null!==this.mutableExcludeField)for(let e=0;e<this.dataset.length;e++){const t=this.dataset[e][this.mutableExcludeField];null!=t&&this.registerMutableExcludeValue(t,e)}}updateMutableExcludeStateForAddedItems(e,t){if(null!==this.mutableExcludeField)for(let s=0;s<e.length;s++){const i=e[s][this.mutableExcludeField];null!=i&&this.registerMutableExcludeValue(i,t+s)}}applyMutableExclude(e){if(null===this.mutableExcludeField||1!==e.length)return;const t=e[0];if(t.field===this.mutableExcludeField&&!t.hasValues&&t.hasExclude){if(this.mutableExcludeState.hasDuplicateValues)throw n.duplicateMutableExcludeField(this.mutableExcludeField);return this.state.removeByFieldValues(this.mutableExcludeField,t.exclude),this.resetFilterState(),this.dataset}}applyUpdatedItem(e,t,s){this.updateMutableExcludeStateForUpdatedItem(e,t,s),this.resetFilterState(),this.indexer.updateItem(t,s),this.nestedCollection.updateItem(s,t)}applyRemovedItem(e,t,s,i,l){if(e===this.mutableExcludeField&&(this.unregisterMutableExcludeValue(t),this.mutableExcludeState.datasetPositions.delete(t),null!==l&&null!==this.mutableExcludeField)){const e=l[this.mutableExcludeField];null!=e&&this.mutableExcludeState.datasetPositions.set(e,i)}this.resetFilterState(),this.indexer.removeItem(s),this.nestedCollection.removeItem(s)}applyRemovedItems(e,t){for(let s=0;s<t.length;s++){const i=t[s];if(e===this.mutableExcludeField&&(this.unregisterMutableExcludeValue(i.value),this.mutableExcludeState.datasetPositions.delete(i.value),null!==i.movedItem&&null!==this.mutableExcludeField)){const e=i.movedItem[this.mutableExcludeField];null!=e&&this.mutableExcludeState.datasetPositions.set(e,i.removedIndex)}this.indexer.removeItem(i.removedItem),this.nestedCollection.removeItem(i.removedItem)}this.resetFilterState()}updateMutableExcludeStateForUpdatedItem(e,t,s){if(null===this.mutableExcludeField)return;const i=t[this.mutableExcludeField],l=s[this.mutableExcludeField];i!==l?(null!=i&&(this.unregisterMutableExcludeValue(i),this.mutableExcludeState.datasetPositions.get(i)===e&&this.mutableExcludeState.datasetPositions.delete(i)),null!=l&&this.registerMutableExcludeValue(l,e)):null!=l&&this.mutableExcludeState.datasetPositions.set(l,e)}clearMutableExcludeState(){this.mutableExcludeState.datasetPositions.clear(),this.mutableExcludeState.valueCounts.clear(),this.mutableExcludeState.duplicateValueCount=0,this.mutableExcludeState.hasDuplicateValues=!1}registerMutableExcludeValue(e,t){const s=(this.mutableExcludeState.valueCounts.get(e)??0)+1;2===s&&this.mutableExcludeState.duplicateValueCount++,this.mutableExcludeState.valueCounts.set(e,s),this.mutableExcludeState.datasetPositions.set(e,t),this.mutableExcludeState.hasDuplicateValues=this.mutableExcludeState.duplicateValueCount>0}unregisterMutableExcludeValue(e){const t=this.mutableExcludeState.valueCounts.get(e);void 0!==t&&(2===t&&this.mutableExcludeState.duplicateValueCount--,t<=1?this.mutableExcludeState.valueCounts.delete(e):this.mutableExcludeState.valueCounts.set(e,t-1),this.mutableExcludeState.hasDuplicateValues=this.mutableExcludeState.duplicateValueCount>0)}linearFilter(e,t){const s=[];for(let i=0;i<e.length;i++){const l=e[i];let a=!0;for(let e=0;e<t.length;e++){const s=t[e];if(!d(s,l[s.field])){a=!1;break}}a&&s.push(l)}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=[],l=[];for(let d=0;d<e.length;d++){const t=e[d];t.hasValues&&i.push(t),t.hasExclude&&l.push(t)}if(0===i.length)return this.applyIndexedExclusions(t,l);if(1===i.length){const e=i[0];let t=!1;for(let s=0;s<l.length;s++)if(l[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 a=this.indexer.getByValues(e.field,e.values),r=[];for(let i=0;i<a.length;i++){const e=a[i];s&&!s.has(e)||r.push(e)}return this.applyIndexedExclusions(r,l)}let a=i[0],r=this.estimateIndexSize(a);for(let d=1;d<i.length;d++){const e=i[d],t=this.estimateIndexSize(e);t<r&&(a=e,r=t)}const n=this.indexer.getByValues(a.field,a.values);if(0===n.length)return[];const u=[];for(let o=0;o<n.length;o++){const e=n[o];let t=!0;if(!s||s.has(e)){for(let s=0;s<i.length;s++){const l=i[s];if(l!==a&&!d(l,e[l.field])){t=!1;break}}t&&u.push(e)}}return this.applyIndexedExclusions(u,l)}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 l=t.get(e.values[i]);l&&(s+=l.length)}return s}applyIndexedExclusions(e,t){if(0===t.length||0===e.length)return e;const s=/* @__PURE__ */new Set;for(let l=0;l<t.length;l++){const e=t[l],i=this.indexer.getIndexMap(e.field);if(i)for(let t=0;t<e.exclude.length;t++){const l=i.get(e.exclude[t]);if(l)for(let e=0;e<l.length;e++)s.add(l[e])}}if(0===s.size)return e;const i=[];for(let l=0;l<e.length;l++){const t=e[l];s.has(t)||i.push(t)}return i}createEmptyResult(e,t,s){const i=[];return this.storePreviousResult(i,e,t,s),i}storePreviousResult(e,t,s,i,l=this.createCriteriaCacheKey(i),a){if(!this.filterByPreviousResult)return;const r=void 0===a?null:a;this.sequentialCache.previousResult=e,this.sequentialCache.previousCriteria=i,this.sequentialCache.previousCriteriaKey=l,this.sequentialCache.previousBaseData=t?this.dataset:s,this.sequentialCache.previousResultSet=r,this.state.setPreviousResult(e,t?this.dataset:s),this.sequentialCache.previousResultsByCriteria.set(l,this.createSequentialCacheEntry(e,r))}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);if(!t||!t.hasValues||!e.hasValues||t.hasExclude||e.hasExclude)return e;if(e.includedValues.size<=t.includedValues.size)return e;for(const s of t.includedValues)if(!e.includedValues.has(s))return e;const i=[];for(const s of e.includedValues)t.includedValues.has(s)||i.push(s);return 0===i.length?e:{...e,values:i,includedValues:new Set(i)}})}hasCriteriaBacktrack(e,t){const s=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(const[l,a]of s){const e=i.get(l);if(!e)return!0;if(this.isCriterionBacktracked(a,e))return!0}return!1}canApplySequentiallyToEmptyResult(e,t){const s=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(const[l,a]of i){const e=s.get(l);if(e){if(e.hasValues!==a.hasValues&&(e.hasValues||!a.hasValues))return!1;if(e.hasValues&&a.hasValues){const t=e.includedValues,s=a.includedValues;if(!this.areSetsEqual(t,s)&&!this.isSubset(t,s))return!1}if(e.hasExclude!==a.hasExclude&&(e.hasExclude||!a.hasExclude))return!1;if(e.hasExclude&&a.hasExclude){const t=e.excludedValues,s=a.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{p 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.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as m}from"./chunks/merge-
|
|
1
|
+
import{t as m}from"./chunks/merge-C6intZSe.mjs";export{m as MergeEngines};
|
package/dist/merge/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CollectionItem, d as SortDescriptor, F as FilterCriterion, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
2
|
-
export {
|
|
1
|
+
import { C as CollectionItem, d as SortDescriptor, F as FilterCriterion, I as IndexableKey, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
2
|
+
export { e as SortDirection } from '../types-DONld7xY.js';
|
|
3
3
|
|
|
4
4
|
type MergeModuleName = "search" | "sort" | "filter";
|
|
5
5
|
interface MergeSearchOptions<T extends CollectionItem = CollectionItem> {
|
|
@@ -15,7 +15,6 @@ interface MergeSortOptions<T extends CollectionItem = CollectionItem> {
|
|
|
15
15
|
}
|
|
16
16
|
interface MergeFilterOptions<T extends CollectionItem = CollectionItem> {
|
|
17
17
|
data?: T[];
|
|
18
|
-
mutableExcludeField?: keyof T & string;
|
|
19
18
|
fields?: (keyof T & string)[];
|
|
20
19
|
nestedFields?: string[];
|
|
21
20
|
}
|
|
@@ -28,6 +27,8 @@ interface MergeEnginesChain<T extends CollectionItem> {
|
|
|
28
27
|
filter(data: T[], criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
|
|
29
28
|
getOriginData(): T[];
|
|
30
29
|
add(items: T[]): MergeEngines<T>;
|
|
30
|
+
delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): MergeEngines<T>;
|
|
31
|
+
delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): MergeEngines<T>;
|
|
31
32
|
update(descriptor: UpdateDescriptor<T>): MergeEngines<T>;
|
|
32
33
|
data(data: T[]): MergeEngines<T>;
|
|
33
34
|
clearIndexes(module: MergeModuleName): T[] & MergeEnginesChain<T>;
|
|
@@ -118,11 +119,13 @@ declare class MergeEngines<T extends CollectionItem> {
|
|
|
118
119
|
private withChain;
|
|
119
120
|
getOriginData(): T[];
|
|
120
121
|
add(items: T[]): this;
|
|
122
|
+
delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): this;
|
|
123
|
+
delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): this;
|
|
121
124
|
update(descriptor: UpdateDescriptor<T>): this;
|
|
122
125
|
clearIndexes(module: MergeModuleName): this;
|
|
123
126
|
data(data: T[]): this;
|
|
124
127
|
clearData(module: MergeModuleName): this;
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
export { CollectionItem, FilterCriterion, MergeEngines, SortDescriptor };
|
|
130
|
+
export { CollectionItem, FilterCriterion, IndexableKey, MergeEngines, SortDescriptor };
|
|
128
131
|
export type { EngineApi, EngineConstructor, MergeEnginesChain, MergeEnginesOptions, MergeFilterOptions, MergeModuleName, MergeSearchOptions, MergeSortOptions };
|
package/dist/merge/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as m}from"../chunks/merge-
|
|
1
|
+
import{t as m}from"../chunks/merge-C6intZSe.mjs";export{m as MergeEngines};
|
package/dist/search/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { S as State } from '../State-CYIe-3He.js';
|
|
2
|
-
import { C as CollectionItem, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
3
|
-
export { I as IndexableKey } from '../types-DONld7xY.js';
|
|
2
|
+
import { C as CollectionItem, I as IndexableKey, U as UpdateDescriptor } from '../types-DONld7xY.js';
|
|
4
3
|
|
|
5
4
|
interface TextSearchEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
6
5
|
data?: T[];
|
|
@@ -173,6 +172,8 @@ declare class TextSearchEngine<T extends CollectionItem> {
|
|
|
173
172
|
getOriginData(): T[];
|
|
174
173
|
data(data: T[]): this;
|
|
175
174
|
add(items: T[]): this;
|
|
175
|
+
delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): this;
|
|
176
|
+
delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): this;
|
|
176
177
|
update(descriptor: UpdateDescriptor<T>): this;
|
|
177
178
|
private applyAddedItems;
|
|
178
179
|
clearData(): this;
|
|
@@ -186,5 +187,5 @@ declare class TextSearchEngine<T extends CollectionItem> {
|
|
|
186
187
|
private getNormalizedFieldValue;
|
|
187
188
|
}
|
|
188
189
|
|
|
189
|
-
export { CollectionItem, TextSearchEngine };
|
|
190
|
+
export { CollectionItem, IndexableKey, TextSearchEngine };
|
|
190
191
|
export type { SearchQueryOptions, TextSearchEngineOptions, TextSearchEngineStats };
|
package/dist/search/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,n as s}from"../chunks/constants-BXQI1M5E.mjs";import{n as i}from"../chunks/internal-COJC3Ik3.mjs";function n(e,t,s,i){const n=function(e,t){const s=[];for(const i of t){const t=e.get(i);if(!t)return null;s.push(t)}return function(e){for(let t=0;t<e.length-1;t++){let s=t;for(let i=t+1;i<e.length;i++)e[i].size<e[s].size&&(s=i);if(s!==t){const i=e[t];e[t]=e[s],e[s]=i}}}(s),s}(e,t);if(null===n)return null;const r=n[0];return{smallestPostingList:r,matches:e=>r.has(e)&&function(e,t){for(let s=0;s<t.length;s++)if(!t[s].has(e))return!1;return!0}(e,n)&&Boolean(s[e]?.includes(i))}}function r(e,t){const s=e.get(t);if(s)return s;const i=/* @__PURE__ */new Set;return e.set(t,i),i}function l(e,t,s){const i=Math.min(3,t.length);for(let n=2;n<=i;n++){const i=t.length-n;for(let l=0;l<=i;l++)r(e,t.substring(l,l+n)).add(s)}}function a(e,t,s,i,r={}){const{restrictionLookup:l=null,take:a=Number.POSITIVE_INFINITY}=r,o=n(e,t,s,i);if(null===o)return[];const d=[];for(const n of o.smallestPostingList)if((null===l||l[n])&&o.matches(n)&&(d.push(n),d.length>=a))break;return d}function o(e,t,s,i,r){const{candidateIndices:l,restrictionLookup:a=null,take:o=Number.POSITIVE_INFINITY}=r;if(0===l.length)return[];const d=n(e,t,s,i);if(null===d)return[];const h=[];if(null===a||l.length<=d.smallestPostingList.size){for(let e=0;e<l.length;e++){const t=l[e];if(d.matches(t)&&(h.push(t),h.length>=o))break}return h}for(const n of d.smallestPostingList)if(a[n]&&d.matches(n)&&(h.push(n),h.length>=o))break;return h}function d(e,t,s){const i=Math.min(3,t.length);for(let n=2;n<=i;n++){const i=t.length-n;for(let r=0;r<=i;r++){const i=t.substring(r,r+n),l=e.get(i);l&&(l.delete(s),0===l.size&&e.delete(i))}}}var h=class{constructor(e={ngramIndexes:/* @__PURE__ */new Map,normalizedFieldValues:/* @__PURE__ */new Map}){this.storage=e,this.registeredFields=/* @__PURE__ */new Set,this.fieldDescriptors=/* @__PURE__ */new Map}registerFields(e){if(e?.length)for(const t of e)this.registerField(t)}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}hasIndexes(){return this.storage.ngramIndexes.size>0}clearIndexes(){this.storage.ngramIndexes.clear(),this.storage.normalizedFieldValues.clear()}buildIndexes(e){this.clearIndexes();for(const t of this.registeredFields)this.buildIndex(e,t)}addItems(e,t){if(0!==e.length&&0!==this.storage.ngramIndexes.size)for(const s of this.storage.ngramIndexes.keys())this.addItemsToField(s,e,t)}updateItem(e,t,s){if(0!==this.storage.ngramIndexes.size)for(const i of this.storage.ngramIndexes.keys())this.updateItemInField(i,e,t,s)}removeItem(e,t){if(0!==this.storage.ngramIndexes.size)for(const s of this.storage.ngramIndexes.keys())this.removeItemFromField(s,e,t)}moveItem(e,t,s){if(0!==this.storage.ngramIndexes.size&&t!==s)for(const i of this.storage.ngramIndexes.keys())this.moveItemForField(i,e,t,s)}searchAllIndexedFieldIndices(e,t,s,i){const n=/* @__PURE__ */new Set,r=[];for(const l of this.storage.ngramIndexes.keys())for(const a of this.searchIndexedFieldIndices(l,e,t,s,i))n.has(a)||(n.add(a),r.push(a));return r}searchIndexedField(e,t,s,i,n,r,l=Number.POSITIVE_INFINITY){const a=this.searchIndexedFieldIndices(t,s,i,n,r,l),o=[];for(let d=0;d<a.length;d++){const t=e[a[d]];t&&o.push(t)}return o}searchIndexedFieldIndices(e,t,s,i,n,r=Number.POSITIVE_INFINITY){const l=this.storage.ngramIndexes.get(e);if(!l)return[];const d=this.storage.normalizedFieldValues.get(e)??[];return null!=n?o(l,s,d,t,{candidateIndices:n,restrictionLookup:i,take:r}):a(l,s,d,t,{restrictionLookup:i,take:r})}searchFieldLinear(e,t,s){const i=this.searchFieldLinearIndices(e,t,s),n=[];for(let r=0;r<i.length;r++){const t=e[i[r]];t&&n.push(t)}return n}searchFieldLinearIndices(e,t,s,i){const n=this.fieldDescriptors.get(t);if(!n)return[];const{collectionKey:r,nestedKey:l}=n,a=[];if(i){for(let t=0;t<i.length;t++){const n=i[t],o=e[n][r];if(!Array.isArray(o))continue;let d=!1;for(let e=0;e<o.length;e++){const t=o[e][l];if("string"==typeof t&&t.toLowerCase().includes(s)){d=!0;break}}d&&a.push(n)}return a}for(let o=0;o<e.length;o++){const t=e[o][r];if(!Array.isArray(t))continue;let i=!1;for(let e=0;e<t.length;e++){const n=t[e][l];if("string"==typeof n&&n.toLowerCase().includes(s)){i=!0;break}}i&&a.push(o)}return a}matchesAnyField(e,t){for(const s of this.registeredFields){const i=this.fieldDescriptors.get(s);if(!i)continue;const{collectionKey:n,nestedKey:r}=i,l=e[n];if(Array.isArray(l))for(let e=0;e<l.length;e++){const s=l[e][r];if("string"==typeof s&&s.toLowerCase().includes(t))return!0}}return!1}registerField(e){const t=i(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t))}getNormalizedValues(e){const t=this.storage.normalizedFieldValues.get(e);if(t)return t;const s=[];return this.storage.normalizedFieldValues.set(e,s),s}buildIndex(e,t){const s=this.fieldDescriptors.get(t);if(!s)return;const{collectionKey:i,nestedKey:n}=s,r=/* @__PURE__ */new Map,a=new Array(e.length);for(let o=0,d=e.length;o<d;o++){const t=e[o][i];if(!Array.isArray(t))continue;const s=[];for(let e=0;e<t.length;e++){const i=t[e][n];"string"==typeof i&&s.push(i.toLowerCase())}if(0===s.length)continue;const d=s.join("\n");a[o]=d,l(r,d,o)}this.storage.ngramIndexes.set(t,r),this.storage.normalizedFieldValues.set(t,a)}addItemsToField(e,t,s){const i=this.fieldDescriptors.get(e),n=this.storage.ngramIndexes.get(e);if(!i||!n)return;const r=this.getNormalizedValues(e),{collectionKey:a,nestedKey:o}=i;for(let d=0;d<t.length;d++){const e=t[d][a];if(!Array.isArray(e))continue;const i=[],h=s+d;for(let t=0;t<e.length;t++){const s=e[t][o];"string"==typeof s&&i.push(s.toLowerCase())}if(0===i.length)continue;const u=i.join("\n");r[h]=u,l(n,u,h)}}updateItemInField(e,t,s,i){const n=this.storage.ngramIndexes.get(e);if(!n)return;const r=this.getNormalizedValues(e),a=this.getNormalizedItemValue(e,s),o=this.getNormalizedItemValue(e,t);a!==o&&(a&&d(n,a,i),o?(r[i]=o,l(n,o,i)):delete r[i])}removeItemFromField(e,t,s){const i=this.storage.ngramIndexes.get(e);if(!i)return;const n=this.getNormalizedValues(e),r=n[s]??this.getNormalizedItemValue(e,t);r&&d(i,r,s),delete n[s]}moveItemForField(e,t,s,i){const n=this.storage.ngramIndexes.get(e);if(!n)return;const r=this.getNormalizedValues(e),a=r[s]??this.getNormalizedItemValue(e,t);a?(d(n,a,s),l(n,a,i),r[i]=a,delete r[s]):delete r[s]}getNormalizedItemValue(e,t){const s=this.fieldDescriptors.get(e);if(!s)return null;const{collectionKey:i,nestedKey:n}=s,r=t[i];if(!Array.isArray(r))return null;const l=[];for(let a=0;a<r.length;a++){const e=r[a][n];"string"==typeof e&&l.push(e.toLowerCase())}return 0===l.length?null:l.join("\n")}},u=()=>({indexedFields:/* @__PURE__ */new Set,flatIndexes:/* @__PURE__ */new Map,nestedStorage:{ngramIndexes:/* @__PURE__ */new Map,normalizedFieldValues:/* @__PURE__ */new Map},deferredMutationVersion:null,filterByPreviousResult:!1,previousResultIndices:null,previousResultLookup:null,previousQuery:null,stats:{totalQueries:0,indexedQueries:0,fallbackQueries:0,fallbackFields:/* @__PURE__ */new Map}}),c=class{constructor(t={}){this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.emittedWarningKeys=/* @__PURE__ */new Set,this.warnings=[],this.normalizedValuesCache=/* @__PURE__ */new Map,this.combinedNormalizedValuesCache=null,this.minQueryLength=t.minQueryLength??1,this.silent=t.silent??!1,this.state=t.state??new e(t.data??[]),this.namespace=this.state.createNamespace("search"),this.nestedCollection=new h(this.runtime.nestedStorage),this.nestedCollection.registerFields(t.nestedFields),this.state.subscribe(e=>this.handleStateMutation(e)),t.filterByPreviousResult&&(this.runtime.filterByPreviousResult=!0);const s=t.fields?.length,i=this.nestedCollection.hasRegisteredFields();if(s)for(const e of t.fields)this.indexedFields.add(e);this.dataset.length>0&&(s||i)&&this.rebuildConfiguredIndexes()}get dataset(){return this.state.getOriginData()}get runtime(){return this.state.getOrCreateScopedValue(this.namespace,"runtime",u)}get flatIndexes(){return this.runtime.flatIndexes}get indexedFields(){return this.runtime.indexedFields}shouldDeferMutationIndexUpdates(){return!0===this.state.getScopedValue(t,s)}markDeferredMutationState(){this.runtime.deferredMutationVersion=this.state.getMutationVersion(),this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,this.clearPreviousSearchState()}ensureConfiguredIndexesReady(){null!==this.runtime.deferredMutationVersion&&(this.runtime.deferredMutationVersion=null,this.dataset.length>0&&(this.indexedFields.size>0||this.nestedCollection.hasRegisteredFields())&&this.rebuildConfiguredIndexes())}rebuildConfiguredIndexes(){this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null;for(const e of this.indexedFields)this.buildIndexFromData(this.dataset,e);this.nestedCollection.hasRegisteredFields()&&this.nestedCollection.buildIndexes(this.dataset)}buildIndexFromData(e,t){const s=this.state.getMutationVersion(),i=/* @__PURE__ */new Map,n=new Array(e.length);for(let r=0,a=e.length;r<a;r++){const s=e[r][t];if("string"!=typeof s)continue;const a=s.toLowerCase();n[r]=a,l(i,a,r)}this.flatIndexes.set(t,{ngramMap:i,normalizedValues:n,version:s})}search(e,t,s){return"string"==typeof t?this.searchField(e,t,s):this.searchAll(e,t)}searchAll(e,t){return this.searchAllFields(e,t)}normalizeQuery(e){return e.trim().toLowerCase()}normalizeSearchWindow(e){const t=Math.max(0,Math.trunc(e?.offset??0)),s=e?.limit,i=void 0===s?Number.POSITIVE_INFINITY:Math.max(0,Math.trunc(s));return{offset:t,limit:i,take:Number.isFinite(i)?t+i:Number.POSITIVE_INFINITY,hasWindow:t>0||Number.isFinite(i)}}shouldTrackPreviousResult(e){return!e.hasWindow}hasReachedWindowLimit(e,t){return Number.isFinite(e.limit)&&t>=e.limit}sliceItems(e,t){return t.hasWindow?e.slice(t.offset,t.take):e}collectItemsFromIndices(e,t){const s=t.hasWindow&&e.length>0?e.slice(t.offset,t.take):e,i=[];for(let n=0;n<s.length;n++){const e=this.dataset[s[n]];e&&i.push(e)}return{items:i,indices:s}}createLookup(e){const t=new Uint8Array(this.dataset.length);for(let s=0;s<e.length;s++)t[e[s]]=1;return t}getRestrictionLookup(e){const t=this.runtime.previousResultLookup;if(null!==t&&this.runtime.previousResultIndices===e&&t.length===this.dataset.length)return t;const s=this.createLookup(e);return this.runtime.previousResultLookup=s,s}getSearchSource(e){const{runtime:t}=this;return t.filterByPreviousResult?null!==t.previousQuery&&null!==t.previousResultIndices&&e.includes(t.previousQuery)?{indices:t.previousResultIndices,lookup:this.getRestrictionLookup(t.previousResultIndices)}:(t.previousResultIndices=null,t.previousResultLookup=null,t.previousQuery=null,{indices:null,lookup:null}):{indices:null,lookup:null}}saveSearchResult(e,t){const{runtime:s}=this;s.filterByPreviousResult&&(s.previousResultIndices=e,s.previousResultLookup=null,s.previousQuery=t)}persistSearchResult(e,t,s){s&&this.saveSearchResult(e.indices,t)}resetSearchState(){return this.clearPreviousSearchState(),this}getWarnings(){return[...this.warnings]}getStats(){const{totalQueries:e,indexedQueries:t,fallbackQueries:s,fallbackFields:i}=this.runtime.stats;return{totalQueries:e,indexedQueries:t,fallbackQueries:s,fallbackRate:0===e?0:s/e,fallbackFields:Object.fromEntries(i)}}resetStats(){const{stats:e}=this.runtime;return e.totalQueries=0,e.indexedQueries=0,e.fallbackQueries=0,e.fallbackFields.clear(),this}clearPreviousSearchState(){const{runtime:e}=this;e.previousResultIndices=null,e.previousResultLookup=null,e.previousQuery=null}recordIndexedQuery(){const{stats:e}=this.runtime;e.totalQueries+=1,e.indexedQueries+=1}recordFallbackQuery(e){const{stats:t}=this.runtime;t.totalQueries+=1,t.fallbackQueries+=1,t.fallbackFields.set(e,(t.fallbackFields.get(e)??0)+1)}shouldEmitFallbackWarning(e){return!this.silent&&e.length>=2}warnAboutFallback(e,t,s){if(!this.shouldEmitFallbackWarning(t))return;const i=`${e}\0${t}\0${s}`;if(this.emittedWarningKeys.has(i))return;this.emittedWarningKeys.add(i);const n=`[TextSearchEngine] warn: query "${t}" on ${e} used linear fallback. ${s}. Add the field(s) to the index schema to enable indexed search.`;this.warnings.push(n),"undefined"!=typeof process&&"production"!==process.env.NODE_ENV&&"test"!==process.env.NODE_ENV&&console.warn(n)}getResolvedFlatIndex(e){const t=this.state.getMutationVersion();let s=this.flatIndexes.get(e);return s&&s.version!==t&&this.dataset.length>0&&(this.buildIndexFromData(this.dataset,e),s=this.flatIndexes.get(e)),s}getQueryGrams(e){const t=function(e){const t=function(e){const t=Math.min(3,Math.max(2,e.length)),s=e.length-t+1,i=new Array(s);for(let n=0;n<s;n++)i[n]=e.substring(n,n+t);return i}(e);if(t.length<=12)return new Set(t);const s=/* @__PURE__ */new Set,i=t.length-1;for(let n=0;n<=11;n++){const e=Math.round(n*i/11);s.add(t[e])}return s}(e);return t.size>0?t:null}searchAllFields(e,t){const s=this.normalizeQuery(e),i=this.normalizeSearchWindow(t),n="all fields";if(0===i.limit)return[];if(!s||s.length<this.minQueryLength)return this.sliceItems(this.dataset,i);s.length>=2&&this.ensureConfiguredIndexesReady();const r=this.shouldTrackPreviousResult(i),{indices:l,lookup:a}=this.getSearchSource(s);let o;const d=()=>(void 0!==o||(o=s.length>=2?this.getQueryGrams(s):null),o);if(null!==l){const e=d();if(null!==e&&(this.flatIndexes.size>0||this.nestedCollection.hasIndexes())){this.recordIndexedQuery();const t=this.searchAllFieldsIndexed(s,e,i,a,l);return this.persistSearchResult(t,s,r),t.items}this.recordFallbackQuery(n);const t=this.searchLinearAllFields(this.dataset,s,l,i);return this.persistSearchResult(t,s,r),t.items}if(!this.flatIndexes.size&&!this.nestedCollection.hasIndexes()){this.warnAboutFallback(n,s,this.indexedFields.size>0?"configured indexes are not currently built":"no indexed fields are configured"),this.recordFallbackQuery(n);const e=this.searchLinearAllFields(this.dataset,s,null,i);return this.persistSearchResult(e,s,r),e.items}const h=d();if(null===h){this.recordFallbackQuery(n);const e=this.searchLinearAllFields(this.dataset,s,null,i);return this.persistSearchResult(e,s,r),e.items}this.recordIndexedQuery();const u=this.searchAllFieldsIndexed(s,h,i,null);return this.persistSearchResult(u,s,r),u.items}searchAllFieldsIndexed(e,t,s,i,n=null){if(null!==n&&!this.nestedCollection.hasRegisteredFields()&&this.flatIndexes.size>0)return this.searchAllFieldsIndexedInCandidates(e,t,s,i,n);const r=this.dataset,l=new Uint8Array(r.length),a=[];let o=0;for(const d of this.flatIndexes.keys()){const r=this.searchFieldWithPreparedQueryIndices(d,e,t,i,n);for(let e=0;e<r.length;e++){const t=r[e];if(!l[t])if(l[t]=1,o<s.offset)o+=1;else if(a.push(t),o+=1,this.hasReachedWindowLimit(s,a.length))return this.materializeIndicesResult(a)}}for(const d of this.nestedCollection.searchAllIndexedFieldIndices(e,t,i,n))if(!l[d])if(l[d]=1,o<s.offset)o+=1;else if(a.push(d),o+=1,this.hasReachedWindowLimit(s,a.length))return this.materializeIndicesResult(a);return this.materializeIndicesResult(a)}searchAllFieldsIndexedInCandidates(e,t,s,i,r){const l=[];for(const d of this.flatIndexes.keys()){const s=this.getResolvedFlatIndex(d);if(!s)continue;const i=n(s.ngramMap,t,s.normalizedValues,e);null!==i&&l.push(i.matches)}if(0===l.length)return{items:[],indices:[]};const a=[];let o=0;for(let n=0;n<r.length;n++){const e=r[n];if(null!==i&&!i[e])continue;let t=!1;for(let s=0;s<l.length;s++)if(l[s](e)){t=!0;break}if(t)if(o<s.offset)o+=1;else if(a.push(e),o+=1,this.hasReachedWindowLimit(s,a.length))break}return this.materializeIndicesResult(a)}searchField(e,t,s){const i=this.normalizeQuery(t),n=this.normalizeSearchWindow(s),r=`field "${e}"`;if(0===n.limit)return[];if(!i||i.length<this.minQueryLength)return this.sliceItems(this.dataset,n);i.length>=2&&this.ensureConfiguredIndexesReady();const l=this.shouldTrackPreviousResult(n),{indices:a,lookup:o}=this.getSearchSource(i),d=this.nestedCollection.hasField(e);let h;const u=()=>(void 0!==h||(h=i.length>=2?this.getQueryGrams(i):null),h);if(null!==a){const t=u();if(d){if(null!==t&&this.nestedCollection.hasIndexes()){this.recordIndexedQuery();const s=this.nestedCollection.searchIndexedFieldIndices(e,i,t,o,a,n.take),r=this.collectItemsFromIndices(s,n);return this.persistSearchResult(r,i,l),r.items}this.recordFallbackQuery(r);const s=this.searchLinearSingleField(this.dataset,e,i,a,n);return this.persistSearchResult(s,i,l),s.items}if(null!==t&&this.flatIndexes.has(e)){this.recordIndexedQuery();const s=this.searchFieldWithPreparedQuery(e,i,t,n,o,a);return this.persistSearchResult(s,i,l),s.items}this.recordFallbackQuery(r);const s=this.searchLinearSingleField(this.dataset,e,i,a,n);return this.persistSearchResult(s,i,l),s.items}if(d){if(i.length>=2&&this.nestedCollection.hasIndexes()){const t=this.getQueryGrams(i);if(null===t)return[];this.recordIndexedQuery();const s=this.nestedCollection.searchIndexedFieldIndices(e,i,t,null,null,n.take),r=this.collectItemsFromIndices(s,n);return this.persistSearchResult(r,i,l),r.items}this.recordFallbackQuery(r);const t=this.searchLinearSingleField(this.dataset,e,i,null,n);return this.persistSearchResult(t,i,l),t.items}this.flatIndexes.size||this.warnAboutFallback(r,i,this.indexedFields.size>0?`field "${e}" is not backed by an active index`:"no indexed fields are configured");const c=u();if(this.flatIndexes.size>0&&null!==c){if(!this.flatIndexes.has(e))return[];this.recordIndexedQuery();const t=this.searchFieldWithPreparedQuery(e,i,c,n);return this.persistSearchResult(t,i,l),t.items}this.recordFallbackQuery(r);const f=this.searchLinearSingleField(this.dataset,e,i,null,n);return this.persistSearchResult(f,i,l),f.items}searchFieldWithPreparedQuery(e,t,s,i,n=null,r=null){const l=this.searchFieldWithPreparedQueryIndices(e,t,s,n,r,i.take);return this.collectItemsFromIndices(l,i)}searchFieldWithPreparedQueryIndices(e,t,s,i=null,n=null,r=Number.POSITIVE_INFINITY){const l=this.getResolvedFlatIndex(e);if(!l)return[];const{ngramMap:d,normalizedValues:h}=l;return null!==n?o(d,s,h,t,{candidateIndices:n,restrictionLookup:i,take:r}):a(d,s,h,t,{restrictionLookup:i,take:r})}getIndexedFieldsList(){return null===this.cachedIndexedFieldsList&&(this.cachedIndexedFieldsList=Array.from(this.indexedFields)),this.cachedIndexedFieldsList}materializeIndicesResult(e){const t=[];for(let s=0;s<e.length;s++){const i=this.dataset[e[s]];i&&t.push(i)}return{items:t,indices:e}}getLinearSearchFields(e){const t=this.getIndexedFieldsList();return t.length>0?t:(null!==this.cachedLinearSearchFieldsList||(this.cachedLinearSearchFieldsList=e.length?Object.keys(e[0]).filter(t=>"string"==typeof e[0][t]):[]),this.cachedLinearSearchFieldsList)}buildNormalizedValuesOnly(e,t){const s=new Array(e.length);for(let i=0,n=e.length;i<n;i++){const n=e[i][t];"string"==typeof n&&(s[i]=n.toLowerCase())}return this.normalizedValuesCache.set(t,s),s}buildCombinedNormalizedValues(e,t){const s=new Array(e.length);for(let i=0;i<e.length;i++)s[i]=this.buildCombinedNormalizedValue(e[i],t);return this.combinedNormalizedValuesCache={fieldsKey:t.join("\0"),values:s},s}buildCombinedNormalizedValue(e,t){let s="";for(let i=0;i<t.length;i++){const n=e[t[i]];"string"==typeof n&&(s&&(s+="\n"),s+=n.toLowerCase())}return s}getCombinedNormalizedValues(e,t){if(e!==this.dataset)return null;const s=t.join("\0");return this.combinedNormalizedValuesCache?.fieldsKey===s?this.combinedNormalizedValuesCache.values:this.buildCombinedNormalizedValues(e,t)}invalidateNormalizedValuesCacheEntry(e,t){for(const[s,i]of this.normalizedValuesCache){const n=t[s];i[e]="string"==typeof n?n.toLowerCase():""}if(null!==this.combinedNormalizedValuesCache){const s=this.combinedNormalizedValuesCache.fieldsKey.split("\0");this.combinedNormalizedValuesCache.values[e]=this.buildCombinedNormalizedValue(t,s)}}searchLinearAllFields(e,t,s,i){if(!e.length)return{items:[],indices:[]};const n=this.getLinearSearchFields(e),r=e===this.dataset,l=n.length,a=new Array(l);for(let f=0;f<l;f++){const t=n[f],s=this.flatIndexes.get(t);if(s)a[f]=s.normalizedValues;else{const s=this.normalizedValuesCache.get(t);a[f]=s||(r?this.buildNormalizedValuesOnly(e,t):null)}}const o=this.nestedCollection.hasRegisteredFields(),d=o?null:this.getCombinedNormalizedValues(e,n),h=!o&&a.every(e=>null!==e),u=[];let c=0;if(null!==s){const e=this.dataset;if(null!==d){for(let e=0;e<s.length;e++){const n=s[e];if(d[n]?.includes(t))if(c<i.offset)c+=1;else if(u.push(n),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}if(h){for(let e=0;e<s.length;e++){const n=s[e];let r=!1;for(let e=0;e<l;e++){const s=a[e][n];if(s&&s.includes(t)){r=!0;break}}if(r)if(c<i.offset)c+=1;else if(u.push(n),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}for(let r=0;r<s.length;r++){const d=s[r],h=e[d];let f=!1;for(let e=0;e<l;e++){const s=a[e];if(s){const e=s[d];if(e&&e.includes(t)){f=!0;break}}else{const s=h[n[e]];if("string"==typeof s&&s.toLowerCase().includes(t)){f=!0;break}}}if(!f&&o&&(f=this.nestedCollection.matchesAnyField(h,t)),f)if(c<i.offset)c+=1;else if(u.push(d),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}if(null!==d){for(let s=0;s<e.length;s++)if(d[s]?.includes(t))if(c<i.offset)c+=1;else if(u.push(s),c+=1,this.hasReachedWindowLimit(i,u.length))break;return this.materializeIndicesResult(u)}if(h){for(let s=0;s<e.length;s++){let e=!1;for(let i=0;i<l;i++){const n=a[i][s];if(n&&n.includes(t)){e=!0;break}}if(e)if(c<i.offset)c+=1;else if(u.push(s),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}for(let f=0;f<e.length;f++){const s=e[f];let r=!1;for(let e=0;e<l;e++){const i=a[e];if(i){const e=i[f];if(e&&e.includes(t)){r=!0;break}}else{const i=s[n[e]];if("string"==typeof i&&i.toLowerCase().includes(t)){r=!0;break}}}if(!r&&o&&(r=this.nestedCollection.matchesAnyField(s,t)),r)if(c<i.offset)c+=1;else if(u.push(f),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}searchLinearSingleField(e,t,s,i,n){if(!e.length)return{items:[],indices:[]};if(this.nestedCollection.hasField(t)){const r=this.nestedCollection.searchFieldLinearIndices(e,t,s,i??void 0);return this.collectItemsFromIndices(r,n)}const r=[],l=this.flatIndexes.get(t),a=l?l.normalizedValues:this.normalizedValuesCache.get(t)??(e===this.dataset?this.buildNormalizedValuesOnly(e,t):null);let o=0;if(null!==i){const e=this.dataset;if(a){for(let e=0;e<i.length;e++){const t=i[e];if(a[t]?.includes(s))if(o<n.offset)o+=1;else if(r.push(t),o+=1,this.hasReachedWindowLimit(n,r.length))break}return this.materializeIndicesResult(r)}for(let l=0;l<i.length;l++){const a=i[l],d=e[a];if("string"==typeof d[t]&&d[t].toLowerCase().includes(s))if(o<n.offset)o+=1;else if(r.push(a),o+=1,this.hasReachedWindowLimit(n,r.length))break}return this.materializeIndicesResult(r)}if(a){for(let t=0;t<e.length;t++)if(a[t]?.includes(s))if(o<n.offset)o+=1;else if(r.push(t),o+=1,this.hasReachedWindowLimit(n,r.length))break;return this.materializeIndicesResult(r)}for(let d=0;d<e.length;d++)if("string"==typeof e[d][t]&&e[d][t].toLowerCase().includes(s))if(o<n.offset)o+=1;else if(r.push(d),o+=1,this.hasReachedWindowLimit(n,r.length))break;return this.materializeIndicesResult(r)}clearIndexes(){return this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,this}getOriginData(){return this.state.getOriginData()}data(e){return this.state.data(e),this}add(e){return this.state.add(e),this}update(e){return this.state.update(e),this}applyAddedItems(e,t){if(0===e.length)return this;for(const s of this.indexedFields)this.addItemsToField(s,e,t);return this.nestedCollection.addItems(e,t),this}clearData(){return this.state.clearData(),this}handleStateMutation(e){if(!this.shouldDeferMutationIndexUpdates()||"add"!==e.type&&"update"!==e.type)switch(e.type){case"add":this.applyAddedItems(e.items,e.startIndex);for(const[t,s]of this.normalizedValuesCache)for(let i=0;i<e.items.length;i++){const n=e.items[i][t];s[e.startIndex+i]="string"==typeof n?n.toLowerCase():""}return this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"update":return this.applyUpdatedItem(e.index,e.previousItem,e.nextItem),this.invalidateNormalizedValuesCacheEntry(e.index,e.nextItem),void this.clearPreviousSearchState();case"data":return this.runtime.deferredMutationVersion=null,this.rebuildConfiguredIndexes(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"clearData":return this.runtime.deferredMutationVersion=null,this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"remove":return this.applyRemovedItem(e.removedItem,e.removedIndex,e.movedItem,e.movedFromIndex),this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"removeMany":for(let t=0;t<e.entries.length;t++){const s=e.entries[t];this.applyRemovedItem(s.removedItem,s.removedIndex,s.movedItem,s.movedFromIndex)}return this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState()}else this.markDeferredMutationState()}addItemsToField(e,t,s){const i=this.flatIndexes.get(e);if(!i)return;const{ngramMap:n,normalizedValues:r}=i;for(let a=0;a<t.length;a++){const i=t[a][e];if("string"!=typeof i)continue;const o=i.toLowerCase(),d=s+a;r[d]=o,l(n,o,d)}i.version=this.state.getMutationVersion()}applyUpdatedItem(e,t,s){for(const i of this.indexedFields)this.updateIndexedField(i,e,t,s);this.nestedCollection.updateItem(s,t,e)}applyRemovedItem(e,t,s,i){for(const n of this.indexedFields)this.removeIndexedFieldValue(n,e,t),null!==s&&null!==i&&this.moveIndexedFieldValue(n,s,i,t);this.nestedCollection.removeItem(e,t),null!==s&&null!==i&&this.nestedCollection.moveItem(s,i,t)}updateIndexedField(e,t,s,i){const n=this.flatIndexes.get(e);if(!n)return;if(s[e]===i[e])return void(n.version=this.state.getMutationVersion());const{ngramMap:r,normalizedValues:a}=n,o=this.getNormalizedFieldValue(s,e);o&&d(r,o,t);const h=this.getNormalizedFieldValue(i,e);if(!h)return delete a[t],void(n.version=this.state.getMutationVersion());a[t]=h,l(r,h,t),n.version=this.state.getMutationVersion()}removeIndexedFieldValue(e,t,s){const i=this.flatIndexes.get(e);if(!i)return;const{ngramMap:n,normalizedValues:r}=i,l=this.getNormalizedFieldValue(t,e);l&&d(n,l,s),delete r[s],i.version=this.state.getMutationVersion()}moveIndexedFieldValue(e,t,s,i){if(s===i)return;const n=this.flatIndexes.get(e);if(!n)return;const{ngramMap:r,normalizedValues:a}=n,o=a[s]??this.getNormalizedFieldValue(t,e);if(!o)return delete a[s],void(n.version=this.state.getMutationVersion());d(r,o,s),l(r,o,i),a[i]=o,delete a[s],n.version=this.state.getMutationVersion()}getNormalizedFieldValue(e,t){const s=e[t];return"string"==typeof s?s.toLowerCase():null}};export{c as TextSearchEngine};
|
|
1
|
+
import{c as e,i as t,l as s,n as i,o as n,s as r,u as l}from"../chunks/constants-DK9S0Db0.mjs";function a(e,t,s,i){const n=function(e,t){const s=[];for(const i of t){const t=e.get(i);if(!t)return null;s.push(t)}return function(e){for(let t=0;t<e.length-1;t++){let s=t;for(let i=t+1;i<e.length;i++)e[i].size<e[s].size&&(s=i);if(s!==t){const i=e[t];e[t]=e[s],e[s]=i}}}(s),s}(e,t);if(null===n)return null;const r=n[0];return{smallestPostingList:r,matches:e=>r.has(e)&&function(e,t){for(let s=0;s<t.length;s++)if(!t[s].has(e))return!1;return!0}(e,n)&&Boolean(s[e]?.includes(i))}}function o(e,t){const s=e.get(t);if(s)return s;const i=/* @__PURE__ */new Set;return e.set(t,i),i}function d(e,t,s){const i=Math.min(3,t.length);for(let n=2;n<=i;n++){const i=t.length-n;for(let r=0;r<=i;r++)o(e,t.substring(r,r+n)).add(s)}}function h(e,t,s,i,n={}){const{restrictionLookup:r=null,take:l=Number.POSITIVE_INFINITY}=n,o=a(e,t,s,i);if(null===o)return[];const d=[];for(const a of o.smallestPostingList)if((null===r||r[a])&&o.matches(a)&&(d.push(a),d.length>=l))break;return d}function u(e,t,s,i,n){const{candidateIndices:r,restrictionLookup:l=null,take:o=Number.POSITIVE_INFINITY}=n;if(0===r.length)return[];const d=a(e,t,s,i);if(null===d)return[];const h=[];if(null===l||r.length<=d.smallestPostingList.size){for(let e=0;e<r.length;e++){const t=r[e];if(d.matches(t)&&(h.push(t),h.length>=o))break}return h}for(const a of d.smallestPostingList)if(l[a]&&d.matches(a)&&(h.push(a),h.length>=o))break;return h}function c(e,t,s){const i=Math.min(3,t.length);for(let n=2;n<=i;n++){const i=t.length-n;for(let r=0;r<=i;r++){const i=t.substring(r,r+n),l=e.get(i);l&&(l.delete(s),0===l.size&&e.delete(i))}}}var f=class{constructor(e={ngramIndexes:/* @__PURE__ */new Map,normalizedFieldValues:/* @__PURE__ */new Map}){this.storage=e,this.registeredFields=/* @__PURE__ */new Set,this.fieldDescriptors=/* @__PURE__ */new Map}registerFields(e){if(e?.length)for(const t of e)this.registerField(t)}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}hasIndexes(){return this.storage.ngramIndexes.size>0}clearIndexes(){this.storage.ngramIndexes.clear(),this.storage.normalizedFieldValues.clear()}buildIndexes(e){this.clearIndexes();for(const t of this.registeredFields)this.buildIndex(e,t)}addItems(e,t){if(0!==e.length&&0!==this.storage.ngramIndexes.size)for(const s of this.storage.ngramIndexes.keys())this.addItemsToField(s,e,t)}updateItem(e,t,s){if(0!==this.storage.ngramIndexes.size)for(const i of this.storage.ngramIndexes.keys())this.updateItemInField(i,e,t,s)}removeItem(e,t){if(0!==this.storage.ngramIndexes.size)for(const s of this.storage.ngramIndexes.keys())this.removeItemFromField(s,e,t)}moveItem(e,t,s){if(0!==this.storage.ngramIndexes.size&&t!==s)for(const i of this.storage.ngramIndexes.keys())this.moveItemForField(i,e,t,s)}searchAllIndexedFieldIndices(e,t,s,i){const n=/* @__PURE__ */new Set,r=[];for(const l of this.storage.ngramIndexes.keys())for(const a of this.searchIndexedFieldIndices(l,e,t,s,i))n.has(a)||(n.add(a),r.push(a));return r}searchIndexedField(e,t,s,i,n,r,l=Number.POSITIVE_INFINITY){const a=this.searchIndexedFieldIndices(t,s,i,n,r,l),o=[];for(let d=0;d<a.length;d++){const t=e[a[d]];t&&o.push(t)}return o}searchIndexedFieldIndices(e,t,s,i,n,r=Number.POSITIVE_INFINITY){const l=this.storage.ngramIndexes.get(e);if(!l)return[];const a=this.storage.normalizedFieldValues.get(e)??[];return null!=n?u(l,s,a,t,{candidateIndices:n,restrictionLookup:i,take:r}):h(l,s,a,t,{restrictionLookup:i,take:r})}searchFieldLinear(e,t,s){const i=this.searchFieldLinearIndices(e,t,s),n=[];for(let r=0;r<i.length;r++){const t=e[i[r]];t&&n.push(t)}return n}searchFieldLinearIndices(e,t,s,i){const n=this.fieldDescriptors.get(t);if(!n)return[];const{collectionKey:r,nestedKey:l}=n,a=[];if(i){for(let t=0;t<i.length;t++){const n=i[t],o=e[n][r];if(!Array.isArray(o))continue;let d=!1;for(let e=0;e<o.length;e++){const t=o[e][l];if("string"==typeof t&&t.toLowerCase().includes(s)){d=!0;break}}d&&a.push(n)}return a}for(let o=0;o<e.length;o++){const t=e[o][r];if(!Array.isArray(t))continue;let i=!1;for(let e=0;e<t.length;e++){const n=t[e][l];if("string"==typeof n&&n.toLowerCase().includes(s)){i=!0;break}}i&&a.push(o)}return a}matchesAnyField(e,t){for(const s of this.registeredFields){const i=this.fieldDescriptors.get(s);if(!i)continue;const{collectionKey:n,nestedKey:r}=i,l=e[n];if(Array.isArray(l))for(let e=0;e<l.length;e++){const s=l[e][r];if("string"==typeof s&&s.toLowerCase().includes(t))return!0}}return!1}registerField(e){const t=n(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t))}getNormalizedValues(e){const t=this.storage.normalizedFieldValues.get(e);if(t)return t;const s=[];return this.storage.normalizedFieldValues.set(e,s),s}buildIndex(e,t){const s=this.fieldDescriptors.get(t);if(!s)return;const{collectionKey:i,nestedKey:n}=s,r=/* @__PURE__ */new Map,l=new Array(e.length);for(let a=0,o=e.length;a<o;a++){const t=e[a][i];if(!Array.isArray(t))continue;const s=[];for(let e=0;e<t.length;e++){const i=t[e][n];"string"==typeof i&&s.push(i.toLowerCase())}if(0===s.length)continue;const o=s.join("\n");l[a]=o,d(r,o,a)}this.storage.ngramIndexes.set(t,r),this.storage.normalizedFieldValues.set(t,l)}addItemsToField(e,t,s){const i=this.fieldDescriptors.get(e),n=this.storage.ngramIndexes.get(e);if(!i||!n)return;const r=this.getNormalizedValues(e),{collectionKey:l,nestedKey:a}=i;for(let o=0;o<t.length;o++){const e=t[o][l];if(!Array.isArray(e))continue;const i=[],h=s+o;for(let t=0;t<e.length;t++){const s=e[t][a];"string"==typeof s&&i.push(s.toLowerCase())}if(0===i.length)continue;const u=i.join("\n");r[h]=u,d(n,u,h)}}updateItemInField(e,t,s,i){const n=this.storage.ngramIndexes.get(e);if(!n)return;const r=this.getNormalizedValues(e),l=this.getNormalizedItemValue(e,s),a=this.getNormalizedItemValue(e,t);l!==a&&(l&&c(n,l,i),a?(r[i]=a,d(n,a,i)):delete r[i])}removeItemFromField(e,t,s){const i=this.storage.ngramIndexes.get(e);if(!i)return;const n=this.getNormalizedValues(e),r=n[s]??this.getNormalizedItemValue(e,t);r&&c(i,r,s),delete n[s]}moveItemForField(e,t,s,i){const n=this.storage.ngramIndexes.get(e);if(!n)return;const r=this.getNormalizedValues(e),l=r[s]??this.getNormalizedItemValue(e,t);l?(c(n,l,s),d(n,l,i),r[i]=l,delete r[s]):delete r[s]}getNormalizedItemValue(e,t){const s=this.fieldDescriptors.get(e);if(!s)return null;const{collectionKey:i,nestedKey:n}=s,r=t[i];if(!Array.isArray(r))return null;const l=[];for(let a=0;a<r.length;a++){const e=r[a][n];"string"==typeof e&&l.push(e.toLowerCase())}return 0===l.length?null:l.join("\n")}},m=()=>({indexedFields:/* @__PURE__ */new Set,flatIndexes:/* @__PURE__ */new Map,nestedStorage:{ngramIndexes:/* @__PURE__ */new Map,normalizedFieldValues:/* @__PURE__ */new Map},deferredMutationVersion:null,filterByPreviousResult:!1,previousResultIndices:null,previousResultLookup:null,previousQuery:null,stats:{totalQueries:0,indexedQueries:0,fallbackQueries:0,fallbackFields:/* @__PURE__ */new Map}}),g=class{constructor(e={}){this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.emittedWarningKeys=/* @__PURE__ */new Set,this.warnings=[],this.normalizedValuesCache=/* @__PURE__ */new Map,this.combinedNormalizedValuesCache=null,this.minQueryLength=e.minQueryLength??1,this.silent=e.silent??!1,this.state=e.state??new l(e.data??[]),this.namespace=this.state.createNamespace("search"),this.nestedCollection=new f(this.runtime.nestedStorage),this.nestedCollection.registerFields(e.nestedFields),this.state.subscribe(e=>this.handleStateMutation(e)),e.filterByPreviousResult&&(this.runtime.filterByPreviousResult=!0);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",m)}get flatIndexes(){return this.runtime.flatIndexes}get indexedFields(){return this.runtime.indexedFields}shouldDeferMutationIndexUpdates(){return!0===this.state.getScopedValue(t,i)}markDeferredMutationState(){this.runtime.deferredMutationVersion=this.state.getMutationVersion(),this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,this.clearPreviousSearchState()}ensureConfiguredIndexesReady(){null!==this.runtime.deferredMutationVersion&&(this.runtime.deferredMutationVersion=null,this.dataset.length>0&&(this.indexedFields.size>0||this.nestedCollection.hasRegisteredFields())&&this.rebuildConfiguredIndexes())}rebuildConfiguredIndexes(){this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedIndexedFieldsList=null,this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null;for(const e of this.indexedFields)this.buildIndexFromData(this.dataset,e);this.nestedCollection.hasRegisteredFields()&&this.nestedCollection.buildIndexes(this.dataset)}buildIndexFromData(e,t){const s=this.state.getMutationVersion(),i=/* @__PURE__ */new Map,n=new Array(e.length);for(let r=0,l=e.length;r<l;r++){const s=e[r][t];if("string"!=typeof s)continue;const l=s.toLowerCase();n[r]=l,d(i,l,r)}this.flatIndexes.set(t,{ngramMap:i,normalizedValues:n,version:s})}search(e,t,s){return"string"==typeof t?this.searchField(e,t,s):this.searchAll(e,t)}searchAll(e,t){return this.searchAllFields(e,t)}normalizeQuery(e){return e.trim().toLowerCase()}normalizeSearchWindow(e){const t=Math.max(0,Math.trunc(e?.offset??0)),s=e?.limit,i=void 0===s?Number.POSITIVE_INFINITY:Math.max(0,Math.trunc(s));return{offset:t,limit:i,take:Number.isFinite(i)?t+i:Number.POSITIVE_INFINITY,hasWindow:t>0||Number.isFinite(i)}}shouldTrackPreviousResult(e){return!e.hasWindow}hasReachedWindowLimit(e,t){return Number.isFinite(e.limit)&&t>=e.limit}sliceItems(e,t){return t.hasWindow?e.slice(t.offset,t.take):e}collectItemsFromIndices(e,t){const s=t.hasWindow&&e.length>0?e.slice(t.offset,t.take):e,i=[];for(let n=0;n<s.length;n++){const e=this.dataset[s[n]];e&&i.push(e)}return{items:i,indices:s}}createLookup(e){const t=new Uint8Array(this.dataset.length);for(let s=0;s<e.length;s++)t[e[s]]=1;return t}getRestrictionLookup(e){const t=this.runtime.previousResultLookup;if(null!==t&&this.runtime.previousResultIndices===e&&t.length===this.dataset.length)return t;const s=this.createLookup(e);return this.runtime.previousResultLookup=s,s}getSearchSource(e){const{runtime:t}=this;return t.filterByPreviousResult?null!==t.previousQuery&&null!==t.previousResultIndices&&e.includes(t.previousQuery)?{indices:t.previousResultIndices,lookup:this.getRestrictionLookup(t.previousResultIndices)}:(t.previousResultIndices=null,t.previousResultLookup=null,t.previousQuery=null,{indices:null,lookup:null}):{indices:null,lookup:null}}saveSearchResult(e,t){const{runtime:s}=this;s.filterByPreviousResult&&(s.previousResultIndices=e,s.previousResultLookup=null,s.previousQuery=t)}persistSearchResult(e,t,s){s&&this.saveSearchResult(e.indices,t)}resetSearchState(){return this.clearPreviousSearchState(),this}getWarnings(){return[...this.warnings]}getStats(){const{totalQueries:e,indexedQueries:t,fallbackQueries:s,fallbackFields:i}=this.runtime.stats;return{totalQueries:e,indexedQueries:t,fallbackQueries:s,fallbackRate:0===e?0:s/e,fallbackFields:Object.fromEntries(i)}}resetStats(){const{stats:e}=this.runtime;return e.totalQueries=0,e.indexedQueries=0,e.fallbackQueries=0,e.fallbackFields.clear(),this}clearPreviousSearchState(){const{runtime:e}=this;e.previousResultIndices=null,e.previousResultLookup=null,e.previousQuery=null}recordIndexedQuery(){const{stats:e}=this.runtime;e.totalQueries+=1,e.indexedQueries+=1}recordFallbackQuery(e){const{stats:t}=this.runtime;t.totalQueries+=1,t.fallbackQueries+=1,t.fallbackFields.set(e,(t.fallbackFields.get(e)??0)+1)}shouldEmitFallbackWarning(e){return!this.silent&&e.length>=2}warnAboutFallback(e,t,s){if(!this.shouldEmitFallbackWarning(t))return;const i=`${e}\0${t}\0${s}`;if(this.emittedWarningKeys.has(i))return;this.emittedWarningKeys.add(i);const n=`[TextSearchEngine] warn: query "${t}" on ${e} used linear fallback. ${s}. Add the field(s) to the index schema to enable indexed search.`;this.warnings.push(n),"undefined"!=typeof process&&"production"!==process.env.NODE_ENV&&"test"!==process.env.NODE_ENV&&console.warn(n)}getResolvedFlatIndex(e){const t=this.state.getMutationVersion();let s=this.flatIndexes.get(e);return s&&s.version!==t&&this.dataset.length>0&&(this.buildIndexFromData(this.dataset,e),s=this.flatIndexes.get(e)),s}getQueryGrams(e){const t=function(e){const t=function(e){const t=Math.min(3,Math.max(2,e.length)),s=e.length-t+1,i=new Array(s);for(let n=0;n<s;n++)i[n]=e.substring(n,n+t);return i}(e);if(t.length<=12)return new Set(t);const s=/* @__PURE__ */new Set,i=t.length-1;for(let n=0;n<=11;n++){const e=Math.round(n*i/11);s.add(t[e])}return s}(e);return t.size>0?t:null}searchAllFields(e,t){const s=this.normalizeQuery(e),i=this.normalizeSearchWindow(t),n="all fields";if(0===i.limit)return[];if(!s||s.length<this.minQueryLength)return this.sliceItems(this.dataset,i);s.length>=2&&this.ensureConfiguredIndexesReady();const r=this.shouldTrackPreviousResult(i),{indices:l,lookup:a}=this.getSearchSource(s);let o;const d=()=>(void 0!==o||(o=s.length>=2?this.getQueryGrams(s):null),o);if(null!==l){const e=d();if(null!==e&&(this.flatIndexes.size>0||this.nestedCollection.hasIndexes())){this.recordIndexedQuery();const t=this.searchAllFieldsIndexed(s,e,i,a,l);return this.persistSearchResult(t,s,r),t.items}this.recordFallbackQuery(n);const t=this.searchLinearAllFields(this.dataset,s,l,i);return this.persistSearchResult(t,s,r),t.items}if(!this.flatIndexes.size&&!this.nestedCollection.hasIndexes()){this.warnAboutFallback(n,s,this.indexedFields.size>0?"configured indexes are not currently built":"no indexed fields are configured"),this.recordFallbackQuery(n);const e=this.searchLinearAllFields(this.dataset,s,null,i);return this.persistSearchResult(e,s,r),e.items}const h=d();if(null===h){this.recordFallbackQuery(n);const e=this.searchLinearAllFields(this.dataset,s,null,i);return this.persistSearchResult(e,s,r),e.items}this.recordIndexedQuery();const u=this.searchAllFieldsIndexed(s,h,i,null);return this.persistSearchResult(u,s,r),u.items}searchAllFieldsIndexed(e,t,s,i,n=null){if(null!==n&&!this.nestedCollection.hasRegisteredFields()&&this.flatIndexes.size>0)return this.searchAllFieldsIndexedInCandidates(e,t,s,i,n);const r=this.dataset,l=new Uint8Array(r.length),a=[];let o=0;for(const d of this.flatIndexes.keys()){const r=this.searchFieldWithPreparedQueryIndices(d,e,t,i,n);for(let e=0;e<r.length;e++){const t=r[e];if(!l[t])if(l[t]=1,o<s.offset)o+=1;else if(a.push(t),o+=1,this.hasReachedWindowLimit(s,a.length))return this.materializeIndicesResult(a)}}for(const d of this.nestedCollection.searchAllIndexedFieldIndices(e,t,i,n))if(!l[d])if(l[d]=1,o<s.offset)o+=1;else if(a.push(d),o+=1,this.hasReachedWindowLimit(s,a.length))return this.materializeIndicesResult(a);return this.materializeIndicesResult(a)}searchAllFieldsIndexedInCandidates(e,t,s,i,n){const r=[];for(const d of this.flatIndexes.keys()){const s=this.getResolvedFlatIndex(d);if(!s)continue;const i=a(s.ngramMap,t,s.normalizedValues,e);null!==i&&r.push(i.matches)}if(0===r.length)return{items:[],indices:[]};const l=[];let o=0;for(let a=0;a<n.length;a++){const e=n[a];if(null!==i&&!i[e])continue;let t=!1;for(let s=0;s<r.length;s++)if(r[s](e)){t=!0;break}if(t)if(o<s.offset)o+=1;else if(l.push(e),o+=1,this.hasReachedWindowLimit(s,l.length))break}return this.materializeIndicesResult(l)}searchField(e,t,s){const i=this.normalizeQuery(t),n=this.normalizeSearchWindow(s),r=`field "${e}"`;if(0===n.limit)return[];if(!i||i.length<this.minQueryLength)return this.sliceItems(this.dataset,n);i.length>=2&&this.ensureConfiguredIndexesReady();const l=this.shouldTrackPreviousResult(n),{indices:a,lookup:o}=this.getSearchSource(i),d=this.nestedCollection.hasField(e);let h;const u=()=>(void 0!==h||(h=i.length>=2?this.getQueryGrams(i):null),h);if(null!==a){const t=u();if(d){if(null!==t&&this.nestedCollection.hasIndexes()){this.recordIndexedQuery();const s=this.nestedCollection.searchIndexedFieldIndices(e,i,t,o,a,n.take),r=this.collectItemsFromIndices(s,n);return this.persistSearchResult(r,i,l),r.items}this.recordFallbackQuery(r);const s=this.searchLinearSingleField(this.dataset,e,i,a,n);return this.persistSearchResult(s,i,l),s.items}if(null!==t&&this.flatIndexes.has(e)){this.recordIndexedQuery();const s=this.searchFieldWithPreparedQuery(e,i,t,n,o,a);return this.persistSearchResult(s,i,l),s.items}this.recordFallbackQuery(r);const s=this.searchLinearSingleField(this.dataset,e,i,a,n);return this.persistSearchResult(s,i,l),s.items}if(d){if(i.length>=2&&this.nestedCollection.hasIndexes()){const t=this.getQueryGrams(i);if(null===t)return[];this.recordIndexedQuery();const s=this.nestedCollection.searchIndexedFieldIndices(e,i,t,null,null,n.take),r=this.collectItemsFromIndices(s,n);return this.persistSearchResult(r,i,l),r.items}this.recordFallbackQuery(r);const t=this.searchLinearSingleField(this.dataset,e,i,null,n);return this.persistSearchResult(t,i,l),t.items}this.flatIndexes.size||this.warnAboutFallback(r,i,this.indexedFields.size>0?`field "${e}" is not backed by an active index`:"no indexed fields are configured");const c=u();if(this.flatIndexes.size>0&&null!==c){if(!this.flatIndexes.has(e))return[];this.recordIndexedQuery();const t=this.searchFieldWithPreparedQuery(e,i,c,n);return this.persistSearchResult(t,i,l),t.items}this.recordFallbackQuery(r);const f=this.searchLinearSingleField(this.dataset,e,i,null,n);return this.persistSearchResult(f,i,l),f.items}searchFieldWithPreparedQuery(e,t,s,i,n=null,r=null){const l=this.searchFieldWithPreparedQueryIndices(e,t,s,n,r,i.take);return this.collectItemsFromIndices(l,i)}searchFieldWithPreparedQueryIndices(e,t,s,i=null,n=null,r=Number.POSITIVE_INFINITY){const l=this.getResolvedFlatIndex(e);if(!l)return[];const{ngramMap:a,normalizedValues:o}=l;return null!==n?u(a,s,o,t,{candidateIndices:n,restrictionLookup:i,take:r}):h(a,s,o,t,{restrictionLookup:i,take:r})}getIndexedFieldsList(){return null===this.cachedIndexedFieldsList&&(this.cachedIndexedFieldsList=Array.from(this.indexedFields)),this.cachedIndexedFieldsList}materializeIndicesResult(e){const t=[];for(let s=0;s<e.length;s++){const i=this.dataset[e[s]];i&&t.push(i)}return{items:t,indices:e}}getLinearSearchFields(e){const t=this.getIndexedFieldsList();return t.length>0?t:(null!==this.cachedLinearSearchFieldsList||(this.cachedLinearSearchFieldsList=e.length?Object.keys(e[0]).filter(t=>"string"==typeof e[0][t]):[]),this.cachedLinearSearchFieldsList)}buildNormalizedValuesOnly(e,t){const s=new Array(e.length);for(let i=0,n=e.length;i<n;i++){const n=e[i][t];"string"==typeof n&&(s[i]=n.toLowerCase())}return this.normalizedValuesCache.set(t,s),s}buildCombinedNormalizedValues(e,t){const s=new Array(e.length);for(let i=0;i<e.length;i++)s[i]=this.buildCombinedNormalizedValue(e[i],t);return this.combinedNormalizedValuesCache={fieldsKey:t.join("\0"),values:s},s}buildCombinedNormalizedValue(e,t){let s="";for(let i=0;i<t.length;i++){const n=e[t[i]];"string"==typeof n&&(s&&(s+="\n"),s+=n.toLowerCase())}return s}getCombinedNormalizedValues(e,t){if(e!==this.dataset)return null;const s=t.join("\0");return this.combinedNormalizedValuesCache?.fieldsKey===s?this.combinedNormalizedValuesCache.values:this.buildCombinedNormalizedValues(e,t)}invalidateNormalizedValuesCacheEntry(e,t){for(const[s,i]of this.normalizedValuesCache){const n=t[s];i[e]="string"==typeof n?n.toLowerCase():""}if(null!==this.combinedNormalizedValuesCache){const s=this.combinedNormalizedValuesCache.fieldsKey.split("\0");this.combinedNormalizedValuesCache.values[e]=this.buildCombinedNormalizedValue(t,s)}}searchLinearAllFields(e,t,s,i){if(!e.length)return{items:[],indices:[]};const n=this.getLinearSearchFields(e),r=e===this.dataset,l=n.length,a=new Array(l);for(let f=0;f<l;f++){const t=n[f],s=this.flatIndexes.get(t);if(s)a[f]=s.normalizedValues;else{const s=this.normalizedValuesCache.get(t);a[f]=s||(r?this.buildNormalizedValuesOnly(e,t):null)}}const o=this.nestedCollection.hasRegisteredFields(),d=o?null:this.getCombinedNormalizedValues(e,n),h=!o&&a.every(e=>null!==e),u=[];let c=0;if(null!==s){const e=this.dataset;if(null!==d){for(let e=0;e<s.length;e++){const n=s[e];if(d[n]?.includes(t))if(c<i.offset)c+=1;else if(u.push(n),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}if(h){for(let e=0;e<s.length;e++){const n=s[e];let r=!1;for(let e=0;e<l;e++){const s=a[e][n];if(s&&s.includes(t)){r=!0;break}}if(r)if(c<i.offset)c+=1;else if(u.push(n),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}for(let r=0;r<s.length;r++){const d=s[r],h=e[d];let f=!1;for(let e=0;e<l;e++){const s=a[e];if(s){const e=s[d];if(e&&e.includes(t)){f=!0;break}}else{const s=h[n[e]];if("string"==typeof s&&s.toLowerCase().includes(t)){f=!0;break}}}if(!f&&o&&(f=this.nestedCollection.matchesAnyField(h,t)),f)if(c<i.offset)c+=1;else if(u.push(d),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}if(null!==d){for(let s=0;s<e.length;s++)if(d[s]?.includes(t))if(c<i.offset)c+=1;else if(u.push(s),c+=1,this.hasReachedWindowLimit(i,u.length))break;return this.materializeIndicesResult(u)}if(h){for(let s=0;s<e.length;s++){let e=!1;for(let i=0;i<l;i++){const n=a[i][s];if(n&&n.includes(t)){e=!0;break}}if(e)if(c<i.offset)c+=1;else if(u.push(s),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}for(let f=0;f<e.length;f++){const s=e[f];let r=!1;for(let e=0;e<l;e++){const i=a[e];if(i){const e=i[f];if(e&&e.includes(t)){r=!0;break}}else{const i=s[n[e]];if("string"==typeof i&&i.toLowerCase().includes(t)){r=!0;break}}}if(!r&&o&&(r=this.nestedCollection.matchesAnyField(s,t)),r)if(c<i.offset)c+=1;else if(u.push(f),c+=1,this.hasReachedWindowLimit(i,u.length))break}return this.materializeIndicesResult(u)}searchLinearSingleField(e,t,s,i,n){if(!e.length)return{items:[],indices:[]};if(this.nestedCollection.hasField(t)){const r=this.nestedCollection.searchFieldLinearIndices(e,t,s,i??void 0);return this.collectItemsFromIndices(r,n)}const r=[],l=this.flatIndexes.get(t),a=l?l.normalizedValues:this.normalizedValuesCache.get(t)??(e===this.dataset?this.buildNormalizedValuesOnly(e,t):null);let o=0;if(null!==i){const e=this.dataset;if(a){for(let e=0;e<i.length;e++){const t=i[e];if(a[t]?.includes(s))if(o<n.offset)o+=1;else if(r.push(t),o+=1,this.hasReachedWindowLimit(n,r.length))break}return this.materializeIndicesResult(r)}for(let l=0;l<i.length;l++){const a=i[l],d=e[a];if("string"==typeof d[t]&&d[t].toLowerCase().includes(s))if(o<n.offset)o+=1;else if(r.push(a),o+=1,this.hasReachedWindowLimit(n,r.length))break}return this.materializeIndicesResult(r)}if(a){for(let t=0;t<e.length;t++)if(a[t]?.includes(s))if(o<n.offset)o+=1;else if(r.push(t),o+=1,this.hasReachedWindowLimit(n,r.length))break;return this.materializeIndicesResult(r)}for(let d=0;d<e.length;d++)if("string"==typeof e[d][t]&&e[d][t].toLowerCase().includes(s))if(o<n.offset)o+=1;else if(r.push(d),o+=1,this.hasReachedWindowLimit(n,r.length))break;return this.materializeIndicesResult(r)}clearIndexes(){return this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,this}getOriginData(){return this.state.getOriginData()}data(e){return this.state.data(e),this}add(e){return this.state.add(e),this}delete(t,i){const n=s(i);if(0===n.length)return this;const l=e(this.dataset,t,n);if(l.length>0)throw new Error(r("TextSearchEngine",t,l));return 1===n.length?(this.state.removeByFieldValue(t,n[0]),this):(this.state.removeByFieldValues(t,n),this)}update(e){return this.state.update(e),this}applyAddedItems(e,t){if(0===e.length)return this;for(const s of this.indexedFields)this.addItemsToField(s,e,t);return this.nestedCollection.addItems(e,t),this}clearData(){return this.state.clearData(),this}handleStateMutation(e){if(!this.shouldDeferMutationIndexUpdates()||"add"!==e.type&&"update"!==e.type)switch(e.type){case"add":this.applyAddedItems(e.items,e.startIndex);for(const[t,s]of this.normalizedValuesCache)for(let i=0;i<e.items.length;i++){const n=e.items[i][t];s[e.startIndex+i]="string"==typeof n?n.toLowerCase():""}return this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"update":return this.applyUpdatedItem(e.index,e.previousItem,e.nextItem),this.invalidateNormalizedValuesCacheEntry(e.index,e.nextItem),void this.clearPreviousSearchState();case"data":return this.runtime.deferredMutationVersion=null,this.rebuildConfiguredIndexes(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"clearData":return this.runtime.deferredMutationVersion=null,this.flatIndexes.clear(),this.nestedCollection.clearIndexes(),this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"remove":return this.applyRemovedItem(e.removedItem,e.removedIndex,e.movedItem,e.movedFromIndex),this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState();case"removeMany":for(let t=0;t<e.entries.length;t++){const s=e.entries[t];this.applyRemovedItem(s.removedItem,s.removedIndex,s.movedItem,s.movedFromIndex)}return this.cachedLinearSearchFieldsList=null,this.normalizedValuesCache.clear(),this.combinedNormalizedValuesCache=null,void this.clearPreviousSearchState()}else this.markDeferredMutationState()}addItemsToField(e,t,s){const i=this.flatIndexes.get(e);if(!i)return;const{ngramMap:n,normalizedValues:r}=i;for(let l=0;l<t.length;l++){const i=t[l][e];if("string"!=typeof i)continue;const a=i.toLowerCase(),o=s+l;r[o]=a,d(n,a,o)}i.version=this.state.getMutationVersion()}applyUpdatedItem(e,t,s){for(const i of this.indexedFields)this.updateIndexedField(i,e,t,s);this.nestedCollection.updateItem(s,t,e)}applyRemovedItem(e,t,s,i){for(const n of this.indexedFields)this.removeIndexedFieldValue(n,e,t),null!==s&&null!==i&&this.moveIndexedFieldValue(n,s,i,t);this.nestedCollection.removeItem(e,t),null!==s&&null!==i&&this.nestedCollection.moveItem(s,i,t)}updateIndexedField(e,t,s,i){const n=this.flatIndexes.get(e);if(!n)return;if(s[e]===i[e])return void(n.version=this.state.getMutationVersion());const{ngramMap:r,normalizedValues:l}=n,a=this.getNormalizedFieldValue(s,e);a&&c(r,a,t);const o=this.getNormalizedFieldValue(i,e);if(!o)return delete l[t],void(n.version=this.state.getMutationVersion());l[t]=o,d(r,o,t),n.version=this.state.getMutationVersion()}removeIndexedFieldValue(e,t,s){const i=this.flatIndexes.get(e);if(!i)return;const{ngramMap:n,normalizedValues:r}=i,l=this.getNormalizedFieldValue(t,e);l&&c(n,l,s),delete r[s],i.version=this.state.getMutationVersion()}moveIndexedFieldValue(e,t,s,i){if(s===i)return;const n=this.flatIndexes.get(e);if(!n)return;const{ngramMap:r,normalizedValues:l}=n,a=l[s]??this.getNormalizedFieldValue(t,e);if(!a)return delete l[s],void(n.version=this.state.getMutationVersion());c(r,a,s),d(r,a,i),l[i]=a,delete l[s],n.version=this.state.getMutationVersion()}getNormalizedFieldValue(e,t){const s=e[t];return"string"==typeof s?s.toLowerCase():null}};export{g as TextSearchEngine};
|
package/dist/sort/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { S as State } from '../State-CYIe-3He.js';
|
|
2
|
-
import { C as CollectionItem, U as UpdateDescriptor, d as SortDescriptor } from '../types-DONld7xY.js';
|
|
2
|
+
import { C as CollectionItem, I as IndexableKey, U as UpdateDescriptor, d as SortDescriptor } from '../types-DONld7xY.js';
|
|
3
3
|
export { e as SortDirection } from '../types-DONld7xY.js';
|
|
4
4
|
|
|
5
5
|
interface SortEngineOptions<T extends CollectionItem = CollectionItem> {
|
|
@@ -26,6 +26,8 @@ declare class SortEngine<T extends CollectionItem> {
|
|
|
26
26
|
clearData(): this;
|
|
27
27
|
data(data: T[]): this;
|
|
28
28
|
add(items: T[]): this;
|
|
29
|
+
delete(field: IndexableKey<T> & string, value: T[IndexableKey<T> & string]): this;
|
|
30
|
+
delete(field: IndexableKey<T> & string, values: T[IndexableKey<T> & string][]): this;
|
|
29
31
|
update(descriptor: UpdateDescriptor<T>): this;
|
|
30
32
|
private applyAddedItems;
|
|
31
33
|
getOriginData(): T[];
|
package/dist/sort/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,r as s}from"../chunks/constants-BXQI1M5E.mjs";var n=class e extends Error{constructor(e){super(e),this.name="SortEngineError"}static missingDatasetForSort(){return new e("SortEngine: no dataset in memory.")}};function i(e,t){for(let s=0;s<t;s++){const t=e[s];if(t!==t>>>0)return!1}return!0}function a(e,t,s){const n=new Uint32Array(s),i=new Uint32Array(65536);for(let r=0;r<s;r++)i[65535&t[e[r]]]++;let a=0;for(let r=0;r<65536;r++){const e=i[r];i[r]=a,a+=e}for(let r=0;r<s;r++)n[i[65535&t[e[r]]]++]=e[r];i.fill(0);for(let r=0;r<s;r++)i[t[n[r]]>>>16&65535]++;a=0;for(let r=0;r<65536;r++){const e=i[r];i[r]=a,a+=e}for(let r=0;r<s;r++)e[i[t[n[r]]>>>16&65535]++]=n[r]}var r=()=>({indexedFields:/* @__PURE__ */new Set,cache:/* @__PURE__ */new Map}),d=class{constructor(t={}){if(this.state=t.state??new e(t.data??[]),this.namespace=this.state.createNamespace("sort"),this.state.subscribe(e=>this.handleStateMutation(e)),t.fields?.length){for(const e of t.fields)this.indexedFields.add(e);this.dataset.length>0&&this.rebuildConfiguredIndexes()}}get dataset(){return this.state.getOriginData()}get runtime(){return this.state.getOrCreateScopedValue(this.namespace,"runtime",r)}get cache(){return this.runtime.cache}get indexedFields(){return this.runtime.indexedFields}shouldDeferMutationCacheUpdates(){return!0===this.state.getScopedValue(t,s)}invalidateCachedIndexes(){for(const e of this.indexedFields)this.cache.delete(e)}rebuildConfiguredIndexes(){this.cache.clear();for(const e of this.indexedFields)this.buildIndexForDataset(e)}buildIndexForDataset(e){this.dataset.length&&this.buildIndexFromData(this.dataset,e)}buildIndexFromData(e,t){const s=e.length,n=new Uint32Array(s);for(let i=0;i<s;i++)n[i]=i;let r=0;for(;r<s&&null==e[r][t];)r++;if(r<s&&"number"==typeof e[r][t]){const r=new Float64Array(s);for(let n=0;n<s;n++)r[n]=e[n][t];i(r,s)?a(n,r,s):n.sort((e,t)=>r[e]-r[t])}else{const i=new Array(s);for(let n=0;n<s;n++)i[n]=e[n][t];n.sort((e,t)=>{const s=i[e],n=i[t];return s<n?-1:s>n?1:0})}const d=new Uint32Array(s);for(let i=0;i<s;i++)d[n[i]]=i;this.cache.set(t,{indexes:n,reverseIndex:d,ascItems:null,descItems:null,hasDuplicateValues:this.hasDuplicateValuesForIndexes(e,n,t),version:this.state.getMutationVersion()})}clearIndexes(){return this.cache.clear(),this}clearData(){return this.state.clearData(),this}data(e){return this.state.data(e),this}add(e){return this.state.add(e),this}update(e){return this.state.update(e),this}applyAddedItems(e,t){if(0===t)return this;if(this.shouldDeferMutationCacheUpdates())return this.invalidateCachedIndexes(),this;for(const s of this.indexedFields){const n=this.cache.get(s);n&&(this.shouldMaintainIncrementally(n)?this.updateCachedIndexForAddedItems(s,e,t):this.cache.delete(s))}return this}getOriginData(){return this.state.getOriginData()}handleStateMutation(e){switch(e.type){case"add":return void this.applyAddedItems(e.startIndex,e.items.length);case"update":return void this.applyUpdatedItem(e.index,e.previousItem,e.nextItem);case"data":return void this.rebuildConfiguredIndexes();case"clearData":return void this.cache.clear();case"remove":return void this.applyRemovedItem(e.removedIndex,e.movedFromIndex);case"removeMany":return void this.applyRemovedItemsBatch(e.entries)}}sort(e,t,s=!1){const i=void 0===t;let a,r;if(i){if(!this.dataset.length)throw n.missingDatasetForSort();a=this.dataset,r=e}else a=e,r=t;if(0===r.length||0===a.length)return a;if(1===r.length){const{field:e,direction:t}=r[0];if(i&&this.indexedFields.has(e)){let s=this.cache.get(e);const n=this.state.getMutationVersion();return s&&s.version===n||(this.buildIndexForDataset(e),s=this.cache.get(e)),this.getCachedSortedItems(s,t)}return this.sortNumericFastPath(a,e,t,s)}return this.sortMultiField(a,r,s,i)}sortNumericFastPath(e,t,s,n){if(0===e.length||"number"!=typeof e[0][t]){const i=n?e:e.slice();return i.sort((e,n)=>{const i=e[t],a=n[t],r=i<a?-1:i>a?1:0;return"asc"===s?r:-r}),i}const r=e.length,d=new Float64Array(r);for(let i=0;i<r;i++)d[i]=e[i][t];const o=new Uint32Array(r);for(let i=0;i<r;i++)o[i]=i;return i(d,r)?a(o,d,r):o.sort((e,t)=>d[e]-d[t]),this.materializeItemsFromIndexes(e,o,s)}sortMultiField(e,t,s,n){const[i,...a]=t;if(n&&this.indexedFields.has(i.field)){let e=this.cache.get(i.field);const t=this.state.getMutationVersion();e&&e.version===t||(this.buildIndexForDataset(i.field),e=this.cache.get(i.field));const s=e.hasDuplicateValues?this.getCachedSortedItems(e,i.direction).slice():this.getCachedSortedItems(e,i.direction);return e.hasDuplicateValues?this.sortTieGroups(s,i.field,a):s}const r=s?e:e.slice(),d=this.buildComparator(t);return r.sort(d),r}sortTieGroups(e,t,s){if(0===s.length)return e;const n=this.buildComparator(s),i=e.length;let a=0;for(;a<i;){let s=a+1;const r=e[a][t];for(;s<i&&e[s][t]===r;)s++;if(s-a>1){const t=e.slice(a,s);t.sort(n);for(let n=a;n<s;n++)e[n]=t[n-a]}a=s}return e}materializeItemsFromIndexes(e,t,s){const n=t.length,i=new Array(n);if("asc"===s){for(let s=0;s<n;s++)i[s]=e[t[s]];return i}for(let a=0;a<n;a++)i[a]=e[t[n-1-a]];return i}getCachedSortedItems(e,t){return"asc"===t?(null===e.ascItems&&(e.ascItems=this.materializeItemsFromIndexes(this.dataset,e.indexes,"asc")),e.ascItems):(null!==e.descItems||(e.descItems=this.getCachedSortedItems(e,"asc").slice().reverse()),e.descItems)}shouldMaintainIncrementally(e){return null!==e.ascItems||null!==e.descItems}hasDuplicateValuesForIndexes(e,t,s){for(let n=1;n<t.length;n++)if(e[t[n-1]][s]===e[t[n]][s])return!0;return!1}compareIndexesByField(e,t,s){const n=this.dataset[t][e],i=this.dataset[s][e];if("number"==typeof n&&"number"==typeof i){const e=n-i;if(0!==e)return e}else{if(n<i)return-1;if(n>i)return 1}return t-s}applyUpdatedItem(e,t,s){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const n of this.indexedFields){if(t[n]===s[n])continue;const i=this.cache.get(n);i&&(this.shouldMaintainIncrementally(i)?this.updateCachedIndexForUpdatedItem(n,e):this.cache.delete(n))}}updateCachedIndexForUpdatedItem(e,t){const s=this.cache.get(e);if(!s)return;const{indexes:n,reverseIndex:i}=s,a=n.length,r=i[t];if(r>=a||n[r]!==t)return void this.cache.delete(e);n.copyWithin(r,r+1);const d=a-1;let o=0,l=d;for(;o<l;){const s=o+l>>1;this.compareIndexesByField(e,n[s],t)<=0?o=s+1:l=s}const h=o;n.copyWithin(h+1,h,d),n[h]=t,null!==s.ascItems&&(s.ascItems.copyWithin(r,r+1),s.ascItems.copyWithin(h+1,h,d),s.ascItems[h]=this.dataset[t]);const c=Math.min(r,h),u=Math.max(r,h);for(let m=c;m<=u;m++)i[n[m]]=m;if(s.descItems=null,!s.hasDuplicateValues){const i=h>0?n[h-1]:-1,r=h+1<a?n[h+1]:-1;s.hasDuplicateValues=-1!==i&&this.dataset[i][e]===this.dataset[t][e]||-1!==r&&this.dataset[r][e]===this.dataset[t][e]}s.version=this.state.getMutationVersion()}updateCachedIndexForAddedItems(e,t,s){const n=this.cache.get(e);if(!n)return;const i=new Array(s);for(let u=0;u<s;u++)i[u]=t+u;i.sort((t,s)=>this.compareIndexesByField(e,t,s));const a=new Uint32Array(n.indexes.length+s);let r=-1,d=n.hasDuplicateValues,o=0,l=0,h=0;for(;o<n.indexes.length&&l<i.length;){const t=this.compareIndexesByField(e,n.indexes[o],i[l])<=0?n.indexes[o++]:i[l++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}for(;o<n.indexes.length;){const t=n.indexes[o++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}for(;l<i.length;){const t=i[l++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}const c=new Uint32Array(a.length);for(let u=0;u<a.length;u++)c[a[u]]=u;n.indexes=a,n.reverseIndex=c,n.ascItems=n.ascItems?this.materializeItemsFromIndexes(this.dataset,a,"asc"):null,n.descItems=null,n.hasDuplicateValues=d,n.version=this.state.getMutationVersion()}applyRemovedItem(e,t){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const s of this.indexedFields){const n=this.cache.get(s);n&&(this.shouldMaintainIncrementally(n)?this.updateCachedIndexForRemovedItem(s,e,t):this.cache.delete(s))}}applyRemovedItemsBatch(e){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const t of this.indexedFields){const s=this.cache.get(t);s&&(this.shouldMaintainIncrementally(s)?s.hasDuplicateValues?this.cache.delete(t):(this.updateUniqueCachedIndexForRemovedItems(s,e),s.version=this.state.getMutationVersion()):this.cache.delete(t))}}updateCachedIndexForRemovedItem(e,t,s){const n=this.cache.get(e);if(!n)return;if(!n.hasDuplicateValues)return this.updateUniqueCachedIndexForRemovedItem(n,t,s),void(n.version=this.state.getMutationVersion());const i=[];for(let d=0;d<n.indexes.length;d++){const e=n.indexes[d];e!==t&&e!==s&&i.push(e)}if(null!==s&&s!==t){let s=0,n=i.length;for(;s<n;){const a=s+n>>1;this.compareIndexesByField(e,i[a],t)<=0?s=a+1:n=a}i.splice(s,0,t)}const a=Uint32Array.from(i),r=new Uint32Array(this.dataset.length);for(let d=0;d<a.length;d++)r[a[d]]=d;n.indexes=a,n.reverseIndex=r,n.ascItems=n.ascItems?this.materializeItemsFromIndexes(this.dataset,a,"asc"):null,n.descItems=null,n.hasDuplicateValues=!!n.hasDuplicateValues&&this.hasDuplicateValuesForIndexes(this.dataset,a,e),n.version=this.state.getMutationVersion()}updateUniqueCachedIndexForRemovedItem(e,t,s){const n=e.indexes.length-1,i=new Uint32Array(n),a=new Uint32Array(this.dataset.length),r=null!==e.ascItems?new Array(n):null;let d=0;for(let o=0;o<e.indexes.length;o++){const n=e.indexes[o];if(n===t)continue;const l=null!==s&&n===s?t:n;i[d]=l,a[l]=d,null!==r&&(r[d]=this.dataset[l]),d+=1}e.indexes=i,e.reverseIndex=a,e.ascItems=r,e.descItems=null}updateUniqueCachedIndexForRemovedItems(e,t){const s=e.indexes.length,n=new Uint32Array(s),i=new Int32Array(s);for(let h=0;h<s;h++)n[h]=h,i[h]=-1;let a=s;for(let h=0;h<t.length;h++){const e=t[h];null!==e.movedFromIndex&&(n[e.removedIndex]=n[e.movedFromIndex]),a-=1}const r=new Uint32Array(a),d=new Uint32Array(a),o=null!==e.ascItems?new Array(a):null;for(let h=0;h<a;h++)i[n[h]]=h;let l=0;for(let h=0;h<e.indexes.length;h++){const t=i[e.indexes[h]];-1!==t&&(r[l]=t,d[t]=l,null!==o&&(o[l]=this.dataset[t]),l+=1)}e.indexes=r,e.reverseIndex=d,e.ascItems=o,e.descItems=null}buildComparator(e){const t=e.map(({field:e})=>e),s=e.map(({direction:e})=>"asc"===e?1:-1),n=t.length;return(e,i)=>{for(let a=0;a<n;a++){const n=t[a],r=e[n],d=i[n];if(r<d)return-s[a];if(r>d)return s[a]}return 0}}};export{d as SortEngine};
|
|
1
|
+
import{c as e,i as t,l as s,r as n,s as i,u as a}from"../chunks/constants-DK9S0Db0.mjs";var r=class e extends Error{constructor(e){super(e),this.name="SortEngineError"}static missingDatasetForSort(){return new e("SortEngine: no dataset in memory.")}};function d(e,t){for(let s=0;s<t;s++){const t=e[s];if(t!==t>>>0)return!1}return!0}function o(e,t,s){const n=new Uint32Array(s),i=new Uint32Array(65536);for(let r=0;r<s;r++)i[65535&t[e[r]]]++;let a=0;for(let r=0;r<65536;r++){const e=i[r];i[r]=a,a+=e}for(let r=0;r<s;r++)n[i[65535&t[e[r]]]++]=e[r];i.fill(0);for(let r=0;r<s;r++)i[t[n[r]]>>>16&65535]++;a=0;for(let r=0;r<65536;r++){const e=i[r];i[r]=a,a+=e}for(let r=0;r<s;r++)e[i[t[n[r]]>>>16&65535]++]=n[r]}var l=()=>({indexedFields:/* @__PURE__ */new Set,cache:/* @__PURE__ */new Map}),h=class{constructor(e={}){if(this.state=e.state??new a(e.data??[]),this.namespace=this.state.createNamespace("sort"),this.state.subscribe(e=>this.handleStateMutation(e)),e.fields?.length){for(const t of e.fields)this.indexedFields.add(t);this.dataset.length>0&&this.rebuildConfiguredIndexes()}}get dataset(){return this.state.getOriginData()}get runtime(){return this.state.getOrCreateScopedValue(this.namespace,"runtime",l)}get cache(){return this.runtime.cache}get indexedFields(){return this.runtime.indexedFields}shouldDeferMutationCacheUpdates(){return!0===this.state.getScopedValue(t,n)}invalidateCachedIndexes(){for(const e of this.indexedFields)this.cache.delete(e)}rebuildConfiguredIndexes(){this.cache.clear();for(const e of this.indexedFields)this.buildIndexForDataset(e)}buildIndexForDataset(e){this.dataset.length&&this.buildIndexFromData(this.dataset,e)}buildIndexFromData(e,t){const s=e.length,n=new Uint32Array(s);for(let r=0;r<s;r++)n[r]=r;let i=0;for(;i<s&&null==e[i][t];)i++;if(i<s&&"number"==typeof e[i][t]){const i=new Float64Array(s);for(let n=0;n<s;n++)i[n]=e[n][t];d(i,s)?o(n,i,s):n.sort((e,t)=>i[e]-i[t])}else{const i=new Array(s);for(let n=0;n<s;n++)i[n]=e[n][t];n.sort((e,t)=>{const s=i[e],n=i[t];return s<n?-1:s>n?1:0})}const a=new Uint32Array(s);for(let r=0;r<s;r++)a[n[r]]=r;this.cache.set(t,{indexes:n,reverseIndex:a,ascItems:null,descItems:null,hasDuplicateValues:this.hasDuplicateValuesForIndexes(e,n,t),version:this.state.getMutationVersion()})}clearIndexes(){return this.cache.clear(),this}clearData(){return this.state.clearData(),this}data(e){return this.state.data(e),this}add(e){return this.state.add(e),this}delete(t,n){const a=s(n);if(0===a.length)return this;const r=e(this.dataset,t,a);if(r.length>0)throw new Error(i("SortEngine",t,r));return 1===a.length?(this.state.removeByFieldValue(t,a[0]),this):(this.state.removeByFieldValues(t,a),this)}update(e){return this.state.update(e),this}applyAddedItems(e,t){if(0===t)return this;if(this.shouldDeferMutationCacheUpdates())return this.invalidateCachedIndexes(),this;for(const s of this.indexedFields){const n=this.cache.get(s);n&&(this.shouldMaintainIncrementally(n)?this.updateCachedIndexForAddedItems(s,e,t):this.cache.delete(s))}return this}getOriginData(){return this.state.getOriginData()}handleStateMutation(e){switch(e.type){case"add":return void this.applyAddedItems(e.startIndex,e.items.length);case"update":return void this.applyUpdatedItem(e.index,e.previousItem,e.nextItem);case"data":return void this.rebuildConfiguredIndexes();case"clearData":return void this.cache.clear();case"remove":return void this.applyRemovedItem(e.removedIndex,e.movedFromIndex);case"removeMany":return void this.applyRemovedItemsBatch(e.entries)}}sort(e,t,s=!1){const n=void 0===t;let i,a;if(n){if(!this.dataset.length)throw r.missingDatasetForSort();i=this.dataset,a=e}else i=e,a=t;if(0===a.length||0===i.length)return i;if(1===a.length){const{field:e,direction:t}=a[0];if(n&&this.indexedFields.has(e)){let s=this.cache.get(e);const n=this.state.getMutationVersion();return s&&s.version===n||(this.buildIndexForDataset(e),s=this.cache.get(e)),this.getCachedSortedItems(s,t)}return this.sortNumericFastPath(i,e,t,s)}return this.sortMultiField(i,a,s,n)}sortNumericFastPath(e,t,s,n){if(0===e.length||"number"!=typeof e[0][t]){const i=n?e:e.slice();return i.sort((e,n)=>{const i=e[t],a=n[t],r=i<a?-1:i>a?1:0;return"asc"===s?r:-r}),i}const i=e.length,a=new Float64Array(i);for(let d=0;d<i;d++)a[d]=e[d][t];const r=new Uint32Array(i);for(let d=0;d<i;d++)r[d]=d;return d(a,i)?o(r,a,i):r.sort((e,t)=>a[e]-a[t]),this.materializeItemsFromIndexes(e,r,s)}sortMultiField(e,t,s,n){const[i,...a]=t;if(n&&this.indexedFields.has(i.field)){let e=this.cache.get(i.field);const t=this.state.getMutationVersion();e&&e.version===t||(this.buildIndexForDataset(i.field),e=this.cache.get(i.field));const s=e.hasDuplicateValues?this.getCachedSortedItems(e,i.direction).slice():this.getCachedSortedItems(e,i.direction);return e.hasDuplicateValues?this.sortTieGroups(s,i.field,a):s}const r=s?e:e.slice(),d=this.buildComparator(t);return r.sort(d),r}sortTieGroups(e,t,s){if(0===s.length)return e;const n=this.buildComparator(s),i=e.length;let a=0;for(;a<i;){let s=a+1;const r=e[a][t];for(;s<i&&e[s][t]===r;)s++;if(s-a>1){const t=e.slice(a,s);t.sort(n);for(let n=a;n<s;n++)e[n]=t[n-a]}a=s}return e}materializeItemsFromIndexes(e,t,s){const n=t.length,i=new Array(n);if("asc"===s){for(let s=0;s<n;s++)i[s]=e[t[s]];return i}for(let a=0;a<n;a++)i[a]=e[t[n-1-a]];return i}getCachedSortedItems(e,t){return"asc"===t?(null===e.ascItems&&(e.ascItems=this.materializeItemsFromIndexes(this.dataset,e.indexes,"asc")),e.ascItems):(null!==e.descItems||(e.descItems=this.getCachedSortedItems(e,"asc").slice().reverse()),e.descItems)}shouldMaintainIncrementally(e){return null!==e.ascItems||null!==e.descItems}hasDuplicateValuesForIndexes(e,t,s){for(let n=1;n<t.length;n++)if(e[t[n-1]][s]===e[t[n]][s])return!0;return!1}compareIndexesByField(e,t,s){const n=this.dataset[t][e],i=this.dataset[s][e];if("number"==typeof n&&"number"==typeof i){const e=n-i;if(0!==e)return e}else{if(n<i)return-1;if(n>i)return 1}return t-s}applyUpdatedItem(e,t,s){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const n of this.indexedFields){if(t[n]===s[n])continue;const i=this.cache.get(n);i&&(this.shouldMaintainIncrementally(i)?this.updateCachedIndexForUpdatedItem(n,e):this.cache.delete(n))}}updateCachedIndexForUpdatedItem(e,t){const s=this.cache.get(e);if(!s)return;const{indexes:n,reverseIndex:i}=s,a=n.length,r=i[t];if(r>=a||n[r]!==t)return void this.cache.delete(e);n.copyWithin(r,r+1);const d=a-1;let o=0,l=d;for(;o<l;){const s=o+l>>1;this.compareIndexesByField(e,n[s],t)<=0?o=s+1:l=s}const h=o;n.copyWithin(h+1,h,d),n[h]=t,null!==s.ascItems&&(s.ascItems.copyWithin(r,r+1),s.ascItems.copyWithin(h+1,h,d),s.ascItems[h]=this.dataset[t]);const c=Math.min(r,h),u=Math.max(r,h);for(let m=c;m<=u;m++)i[n[m]]=m;if(s.descItems=null,!s.hasDuplicateValues){const i=h>0?n[h-1]:-1,r=h+1<a?n[h+1]:-1;s.hasDuplicateValues=-1!==i&&this.dataset[i][e]===this.dataset[t][e]||-1!==r&&this.dataset[r][e]===this.dataset[t][e]}s.version=this.state.getMutationVersion()}updateCachedIndexForAddedItems(e,t,s){const n=this.cache.get(e);if(!n)return;const i=new Array(s);for(let u=0;u<s;u++)i[u]=t+u;i.sort((t,s)=>this.compareIndexesByField(e,t,s));const a=new Uint32Array(n.indexes.length+s);let r=-1,d=n.hasDuplicateValues,o=0,l=0,h=0;for(;o<n.indexes.length&&l<i.length;){const t=this.compareIndexesByField(e,n.indexes[o],i[l])<=0?n.indexes[o++]:i[l++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}for(;o<n.indexes.length;){const t=n.indexes[o++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}for(;l<i.length;){const t=i[l++];a[h]=t,d||-1===r||this.dataset[r][e]!==this.dataset[t][e]||(d=!0),r=t,h+=1}const c=new Uint32Array(a.length);for(let u=0;u<a.length;u++)c[a[u]]=u;n.indexes=a,n.reverseIndex=c,n.ascItems=n.ascItems?this.materializeItemsFromIndexes(this.dataset,a,"asc"):null,n.descItems=null,n.hasDuplicateValues=d,n.version=this.state.getMutationVersion()}applyRemovedItem(e,t){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const s of this.indexedFields){const n=this.cache.get(s);n&&(this.shouldMaintainIncrementally(n)?this.updateCachedIndexForRemovedItem(s,e,t):this.cache.delete(s))}}applyRemovedItemsBatch(e){if(this.shouldDeferMutationCacheUpdates())this.invalidateCachedIndexes();else for(const t of this.indexedFields){const s=this.cache.get(t);s&&(this.shouldMaintainIncrementally(s)?s.hasDuplicateValues?this.cache.delete(t):(this.updateUniqueCachedIndexForRemovedItems(s,e),s.version=this.state.getMutationVersion()):this.cache.delete(t))}}updateCachedIndexForRemovedItem(e,t,s){const n=this.cache.get(e);if(!n)return;if(!n.hasDuplicateValues)return this.updateUniqueCachedIndexForRemovedItem(n,t,s),void(n.version=this.state.getMutationVersion());const i=[];for(let d=0;d<n.indexes.length;d++){const e=n.indexes[d];e!==t&&e!==s&&i.push(e)}if(null!==s&&s!==t){let s=0,n=i.length;for(;s<n;){const a=s+n>>1;this.compareIndexesByField(e,i[a],t)<=0?s=a+1:n=a}i.splice(s,0,t)}const a=Uint32Array.from(i),r=new Uint32Array(this.dataset.length);for(let d=0;d<a.length;d++)r[a[d]]=d;n.indexes=a,n.reverseIndex=r,n.ascItems=n.ascItems?this.materializeItemsFromIndexes(this.dataset,a,"asc"):null,n.descItems=null,n.hasDuplicateValues=!!n.hasDuplicateValues&&this.hasDuplicateValuesForIndexes(this.dataset,a,e),n.version=this.state.getMutationVersion()}updateUniqueCachedIndexForRemovedItem(e,t,s){const n=e.indexes.length-1,i=new Uint32Array(n),a=new Uint32Array(this.dataset.length),r=null!==e.ascItems?new Array(n):null;let d=0;for(let o=0;o<e.indexes.length;o++){const n=e.indexes[o];if(n===t)continue;const l=null!==s&&n===s?t:n;i[d]=l,a[l]=d,null!==r&&(r[d]=this.dataset[l]),d+=1}e.indexes=i,e.reverseIndex=a,e.ascItems=r,e.descItems=null}updateUniqueCachedIndexForRemovedItems(e,t){const s=e.indexes.length,n=new Uint32Array(s),i=new Int32Array(s);for(let h=0;h<s;h++)n[h]=h,i[h]=-1;let a=s;for(let h=0;h<t.length;h++){const e=t[h];null!==e.movedFromIndex&&(n[e.removedIndex]=n[e.movedFromIndex]),a-=1}const r=new Uint32Array(a),d=new Uint32Array(a),o=null!==e.ascItems?new Array(a):null;for(let h=0;h<a;h++)i[n[h]]=h;let l=0;for(let h=0;h<e.indexes.length;h++){const t=i[e.indexes[h]];-1!==t&&(r[l]=t,d[t]=l,null!==o&&(o[l]=this.dataset[t]),l+=1)}e.indexes=r,e.reverseIndex=d,e.ascItems=o,e.descItems=null}buildComparator(e){const t=e.map(({field:e})=>e),s=e.map(({direction:e})=>"asc"===e?1:-1),n=t.length;return(e,i)=>{for(let a=0;a<n;a++){const n=t[a],r=e[n],d=i[n];if(r<d)return-s[a];if(r>d)return s[a]}return 0}}};export{h as SortEngine};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devisfuture/mega-collection",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "High-performance search, filter & sort engine for 100K+ item collections in JavaScript/TypeScript",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"test:watch": "vitest",
|
|
42
42
|
"sort-bench": "npx tsx ./benchmarks/sorter.bench.ts",
|
|
43
43
|
"filter-bench": "npx tsx ./benchmarks/filter.bench.ts",
|
|
44
|
+
"filter-remove-bench": "npx tsx ./benchmarks/filter-remove.bench.ts",
|
|
44
45
|
"search-bench": "npx tsx ./benchmarks/search.bench.ts",
|
|
45
46
|
"controls-bench": "npx tsx ./benchmarks/controls.bench.ts",
|
|
46
47
|
"test:coverage": "vitest run --coverage",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function n(n){return{value:n,enumerable:!1,configurable:!0,writable:!0}}function e(n){const e=n.indexOf(".");return-1===e?null:{collectionKey:n.substring(0,e),nestedKey:n.substring(e+1)}}export{e as n,n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as t,i as e,n as i,r,t as s}from"./constants-BXQI1M5E.mjs";import{t as a}from"./internal-COJC3Ik3.mjs";var n=class{constructor(t){this.callbacks=t}create(t){const e=t;return Object.defineProperties(e,{search:a((t,e)=>void 0===e?this.callbacks.search(t):this.callbacks.search(t,e)),sort:a((e,i,r)=>void 0===i?this.callbacks.sort(t,e,r):this.callbacks.sort(e,i,r)),filter:a((e,i)=>void 0===i?this.callbacks.filter(t,e):this.callbacks.filter(e,i)),add:a(t=>this.callbacks.add(t)),update:a(t=>this.callbacks.update(t)),clearIndexes:a(e=>(this.callbacks.clearIndexes(e),this.create(t))),clearData:a(e=>(this.callbacks.clearData(e),this.create(t))),data:a(t=>this.callbacks.data(t)),getOriginData:a(()=>this.callbacks.getOriginData())}),e}};function o(t){return"object"==typeof t&&null!==t}function l(t,e){return o(t)&&"function"==typeof t[e]}function u(t){return l(t,"search")&&l(t,"getOriginData")}function h(t){return l(t,"sort")&&l(t,"getOriginData")}function c(t){return l(t,"rawFilter")&&l(t,"getOriginData")}var d=t=>{const{prototype:e}=t;return c(e)?"filter":h(e)?"sort":u(e)?"search":null},p=(t,e,i,r)=>{const s=new t({data:e,state:i,...r});return c(s)?{moduleName:"filter",executeFilter:(t,e)=>void 0===e?s.rawFilter(t):s.rawFilter(t,e),clearIndexes:()=>s.clearIndexes()}:h(s)?{moduleName:"sort",executeSort:(t,e,i)=>void 0===e?s.sort(t):s.sort(t,e,i),clearIndexes:()=>s.clearIndexes()}:u(s)?{moduleName:"search",executeSearch:(t,e)=>void 0===e?s.search(t):s.search(t,e),clearIndexes:()=>s.clearIndexes()}:null},g={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},v=class t extends Error{constructor(t){super(t),this.name="MergeEnginesError"}static unavailableEngine(e){return new t(`MergeEngines: ${g[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.')}},S=class{constructor(a){this.previousSearchState=null,this.previousFilterState=null,this.previousSortState=null;const{imports:o,data:l,filterByPreviousResult:u=!1,...h}=a;this.validateFilterByPreviousResultOptions(h.filter),this.state=new t(l,{filterByPreviousResult:u});const c=new Set(o);let g=null,v=null,S=null;for(const t of c){const e=d(t);if(!e)continue;const i=this.getModuleInitOptions(e,t.name,h),r=p(t,l,this.state,i);r&&("search"!==r.moduleName||g||(g=r),"sort"!==r.moduleName||v||(v=r),"filter"!==r.moduleName||S||(S=r))}this.searchModule=g,this.sortModule=v,this.filterModule=S,this.sortModule&&this.state.setScopedValue(e,r,!0),this.searchModule&&this.state.setScopedValue(e,i,!0),this.filterModule&&this.state.setScopedValue(e,s,!0),this.state.subscribe(t=>this.handleStateMutation(t)),this.chainBuilder=new n({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),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];o(t)&&Object.assign(r,t)}return r}validateFilterByPreviousResultOptions(t){if(o(t)&&Object.prototype.hasOwnProperty.call(t,"filterByPreviousResult"))throw v.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 v.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 v.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 v.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 v.unavailableGetOriginData()}add(t){return 0===t.length||this.state.add(t),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 v.unavailableEngine(t)}data(t){return this.state.data(t),this}clearData(t){if(this.getAdapter(t))return this.state.clearData(),this;throw v.unavailableEngine(t)}};export{S as t};
|