@devisfuture/mega-collection 2.1.3 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,6 +19,9 @@ If this package saved you some time, a ⭐ on GitHub would be much appreciated.
19
19
  - [Nested collections search](#nested-collections-search) – search inside nested arrays like `orders.status`
20
20
  - [Filter only](#filter-only) – use only filtering
21
21
  - [Flat collections filter](#flat-collections-filter) – filter by simple top-level fields
22
+ - [Exclude items with `exclude`](#exclude-items-with-exclude) – remove matching items from the result
23
+ - [Result-only exclude](#result-only-exclude) – return a filtered result without mutating stored data
24
+ - [Mutable exclude with `mutableExcludeField`](#mutable-exclude-with-mutableexcludefield) – fast delete-like removal via swap-pop
22
25
  - [Nested collections filter](#nested-collections-filter) – filter by nested array fields
23
26
  - [Sort only](#sort-only) – use only sorting
24
27
  - [API Reference](#api-reference) – list of options and methods
@@ -34,15 +37,18 @@ If this package saved you some time, a ⭐ on GitHub would be much appreciated.
34
37
 
35
38
  ## What does this package solve
36
39
 
37
- Sometimes in projects, you need to iterate through huge collections (100K+ elements in an array) that have come from the server. Usually, the most common features are searching, filtering, and sorting.
38
- This package helps you search, filter, and sort large collections faster than plain JavaScript methods. Usually you do this before showing data in the UI.
40
+ Sometimes the server returns a very large array, for example 100K+ items.
41
+ Most often you then need to search, filter, or sort this data.
39
42
 
40
- Zero dependencies. Tree-shakeable. Import only what you need.
43
+ This package helps do these operations faster than plain JavaScript methods.
44
+ Usually this happens before data is shown in the UI.
41
45
 
42
- Each engine lives in its own entry point (`/search`, `/filter`, `/sort`).
43
- Importing just `@devisfuture/mega-collection/search` or the other sub-modules means
44
- only that code goes into your bundle. Unused engines stay out. For example, if
45
- you only import `TextSearchEngine`, the filter and sort code will not be included.
46
+ The package has no dependencies.
47
+ You can import only the parts you need.
48
+
49
+ Each engine has its own entry point: `/search`, `/filter`, `/sort`.
50
+ If you import only `@devisfuture/mega-collection/search`, only search code goes into the bundle.
51
+ Unused modules are not included.
46
52
 
47
53
  ## Features
48
54
 
@@ -57,10 +63,10 @@ you only import `TextSearchEngine`, the filter and sort code will not be include
57
63
 
58
64
  ## React demo
59
65
 
60
- A small [repository](https://github.com/trae-op/quick-start_react_mega-collection) demonstrates using `@devisfuture/mega-collection` in a React project.
61
- The example shows search, filter, sort and merge all modules setups with a minimal UI.
66
+ A small [repository](https://github.com/trae-op/quick-start_react_mega-collection) shows how to use `@devisfuture/mega-collection` in React.
67
+ It has examples for search, filter, sort, and `MergeEngines` with a simple UI.
62
68
 
63
- A live build of the React app is available at [demo](https://trae-op.github.io/quick-start_react_mega-collection/), showcasing how the package works in a real application.
69
+ There is also a live [demo](https://trae-op.github.io/quick-start_react_mega-collection/).
64
70
 
65
71
  ## Install
66
72
 
@@ -92,19 +98,17 @@ interface UserWithOrders extends User {
92
98
 
93
99
  ### All-in-one: `MergeEngines`
94
100
 
95
- Use `MergeEngines` when you want one engine that works with the same dataset.
96
- Add the engines you need in `imports`. Only those engines will be created.
101
+ Use `MergeEngines` when you want one class that works with one dataset.
102
+ Add needed engines to `imports`. Only those engines will be created.
97
103
 
98
104
  You can create many engine instances in one project for different collections.
99
- Each instance keeps its own data and its own indexes, so they work separately
100
- and do not overwrite each other.
105
+ Each instance stores its own data and indexes, so they do not affect each other.
106
+
107
+ Each engine can receive an optional `fields` array through `search`, `filter`, or `sort` options.
108
+ These fields are used for indexes.
101
109
 
102
- Each engine accepts an optional `fields` array (set via the `search`,
103
- `filter` or `sort` option) which tells it which properties should use indexed
104
- execution. Those indexes are built lazily on the first matching operation, so
105
- initial engine creation stays fast even for very large collections. If you skip
106
- `fields`, everything still works, but the engine may need to scan the full
107
- array.
110
+ Indexes are built lazily on first use, so engine creation stays fast.
111
+ If you skip `fields`, everything still works, but the engine may scan the full array.
108
112
 
109
113
  ```ts
110
114
  import { MergeEngines } from "@devisfuture/mega-collection";
@@ -120,13 +124,19 @@ const engine = new MergeEngines<User>({
120
124
  sort: { fields: ["age", "name", "city"] },
121
125
  });
122
126
 
123
- // dataset is passed once at init — no need to repeat it in every call
127
+ const mutableMerge = new MergeEngines<User>({
128
+ imports: [FilterEngine],
129
+ data: users,
130
+ filter: { fields: ["id", "city"], mutableExcludeField: "id" },
131
+ });
132
+
133
+ // Dataset is passed once in the constructor.
124
134
  engine
125
135
  .search("john")
126
136
  .sort([{ field: "age", direction: "asc" }])
127
137
  .filter([{ field: "city", values: ["Miami", "New York"] }]);
128
138
 
129
- // with nested collection fields (e.g. orders inside each user)
139
+ // Example with nested fields, for example `orders` inside each user.
130
140
  const nestedEngine = new MergeEngines<UserWithOrders>({
131
141
  imports: [TextSearchEngine, SortEngine, FilterEngine],
132
142
  data: usersWithOrders,
@@ -146,7 +156,7 @@ const nestedEngine = new MergeEngines<UserWithOrders>({
146
156
  nestedEngine.search("pending"); // finds users whose orders contain "pending"
147
157
  nestedEngine.filter([{ field: "orders.status", values: ["delivered"] }]);
148
158
 
149
- // update dataset later without creating a new instance
159
+ // Replace dataset later without creating a new instance.
150
160
  engine.data([
151
161
  {
152
162
  id: 1,
@@ -156,12 +166,15 @@ engine.data([
156
166
  },
157
167
  ]);
158
168
 
159
- // clear indexes/data for one module
169
+ // Clear indexes or data for one module.
160
170
  engine.clearIndexes("search").clearIndexes("sort").clearIndexes("filter");
161
171
  engine.clearData("search").clearData("sort").clearData("filter");
162
172
 
163
- // get shared original dataset
173
+ // Get shared original dataset.
164
174
  engine.getOriginData();
175
+
176
+ // Remove items through the root facade.
177
+ mutableMerge.filter([{ field: "id", exclude: [1, 4] }]);
165
178
  ```
166
179
 
167
180
  ---
@@ -169,7 +182,7 @@ engine.getOriginData();
169
182
  ### Search only
170
183
 
171
184
  Use `TextSearchEngine` when you only need text search.
172
- The examples below show the difference between simple fields and nested fields.
185
+ The examples below show search by simple fields and nested fields.
173
186
 
174
187
  #### Flat collections search
175
188
 
@@ -177,16 +190,16 @@ The examples below show the difference between simple fields and nested fields.
177
190
  import { TextSearchEngine } from "@devisfuture/mega-collection/search";
178
191
 
179
192
  // `fields` tells the engine which fields should use indexed search.
180
- // The index is built lazily on first use. If you skip `fields`, search still
181
- // works, but it will scan the full dataset.
193
+ // The index is built only when it is needed for the first time.
194
+ // If you skip `fields`, search still works, but it scans the full dataset.
182
195
  const engine = new TextSearchEngine<User>({
183
196
  data: users,
184
197
  fields: ["name", "city"],
185
198
  minQueryLength: 2, // begins searching when query length >= 2
186
199
  });
187
200
 
188
- // If the query is shorter than `minQueryLength`, the engine returns the
189
- // original dataset. Empty or blank queries also return the original dataset.
201
+ // If the query is shorter than `minQueryLength`, the engine returns
202
+ // the original dataset. Empty or blank queries do the same.
190
203
 
191
204
  engine.search("john"); // searches all indexed fields, deduplicated
192
205
  engine.search("name", "john"); // searches a specific field
@@ -222,16 +235,16 @@ nestedSearch.search("orders.status", "delivered"); // search a specific nested f
222
235
  ### Filter only
223
236
 
224
237
  Use `FilterEngine` when you only need filtering.
225
- The examples below show the difference between simple fields and nested fields.
238
+ The examples below show filtering by simple fields and nested fields.
226
239
 
227
240
  #### Flat collections filter
228
241
 
229
242
  ```ts
230
243
  import { FilterEngine } from "@devisfuture/mega-collection/filter";
231
244
 
232
- // `fields` tells the engine which fields should use indexed filter lookups.
233
- // The index is built lazily on first use. Without `fields`, filtering still
234
- // works, but it will scan the data.
245
+ // `fields` tells the engine which fields should use indexes for filtering.
246
+ // The index is built only when it is needed for the first time.
247
+ // Without `fields`, filtering still works, but it scans the data.
235
248
  const engine = new FilterEngine<User>({
236
249
  data: users,
237
250
  fields: ["city", "age"],
@@ -243,24 +256,118 @@ engine.filter([
243
256
  { field: "age", values: [25, 30, 35] },
244
257
  ]);
245
258
 
246
- // replace dataset without re-initializing
259
+ // Replace dataset without creating a new engine.
247
260
  engine.data(users);
248
261
 
249
- // access original dataset stored in the engine
262
+ // Get original stored dataset.
250
263
  engine.getOriginData();
251
264
 
252
- engine
253
- .filter([{ field: "city", values: ["Miami", "New York"] }])
254
- .filter([{ field: "age", values: [25, 30, 35] }])
255
- .clearIndexes()
256
- .resetFilterState()
257
- .clearData();
258
-
259
265
  // Sequential mode example:
260
- // 1) First call filters by city
266
+ // 1) First call filters by city.
261
267
  const byCity = engine.filter([{ field: "city", values: ["Miami"] }]);
262
- // 2) Second call filters only inside the previous result
268
+ // 2) Second call works only on the previous result.
263
269
  const byCityAndAge = engine.filter([{ field: "age", values: [22] }]);
270
+ // 3) Returning to an earlier criteria state restores its previous result.
271
+ const byCityAgain = engine.filter([{ field: "city", values: ["Miami"] }]);
272
+ ```
273
+
274
+ #### Exclude items with `exclude`
275
+
276
+ Use `exclude` when you want to remove items from the result by exact field values.
277
+ This is useful when you already know which `id` values or other field values should not be in the result.
278
+
279
+ `exclude` changes only the returned result. It does not change the stored dataset inside the engine.
280
+
281
+ There are two ways to work with `exclude`:
282
+
283
+ - Result-only exclude: returns a filtered array and leaves the stored dataset unchanged.
284
+ - Mutable exclude with `mutableExcludeField`: removes items from the stored dataset with **swap-pop**.
285
+
286
+ **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.
287
+
288
+ #### Result-only exclude
289
+
290
+ If the engine already stores the full dataset, `exclude` alone is enough. For example,
291
+ `engine.filter([{ field: "id", exclude: [1, 4] }])` returns all stored users except users with `id` `1` and `4`.
292
+
293
+ This mode does not use swap-pop on the stored dataset. `filter(...)` returns a new array,
294
+ so the engine still needs one pass over the current data to build the result.
295
+ If `id` is indexed, the engine does not scan the full dataset again for each excluded `id`,
296
+ but it still has to build the final array.
297
+
298
+ If you need repeated removals from a large collection and do not want O(n) work for each removed item,
299
+ use mutable exclude mode.
300
+ In this mode the engine removes items from the stored dataset with swap-pop.
301
+ Order is not preserved.
302
+
303
+ If the field is listed in `fields`, the engine uses indexes for exclude values
304
+ instead of scanning the full dataset again for every removed value.
305
+
306
+ ```ts
307
+ import { FilterEngine } from "@devisfuture/mega-collection/filter";
308
+
309
+ const engine = new FilterEngine<User>({
310
+ data: users,
311
+ fields: ["id", "city"],
312
+ });
313
+
314
+ // Returns all users except users with ids 1 and 3.
315
+ const visibleUsers = engine.filter([{ field: "id", exclude: [1, 3] }]);
316
+
317
+ // You can combine normal filtering and exclude.
318
+ engine.filter([
319
+ { field: "city", values: ["Miami", "New York"] },
320
+ { field: "id", exclude: [1, 3] },
321
+ ]);
322
+ ```
323
+
324
+ #### Mutable exclude with `mutableExcludeField`
325
+
326
+ If you need repeated fast removals from a large stored dataset, use `mutableExcludeField`.
327
+ In this mode the engine removes items from the stored dataset with swap-pop.
328
+
329
+ Use this mode when all of these points are true:
330
+
331
+ - the engine already stores the full dataset
332
+ - the exclude field is unique, for example `id`
333
+ - order does not need to be preserved
334
+ - you want repeated removals without O(n) per removed id
335
+
336
+ This mode changes the stored dataset.
337
+ After exclusion, `getOriginData()` returns the reduced collection.
338
+
339
+ ```ts
340
+ import { FilterEngine } from "@devisfuture/mega-collection/filter";
341
+
342
+ const mutableEngine = new FilterEngine<User>({
343
+ data: users,
344
+ fields: ["id", "city"],
345
+ mutableExcludeField: "id",
346
+ });
347
+
348
+ // Removes items from the stored dataset with swap-pop.
349
+ mutableEngine.filter([{ field: "id", exclude: [1, 4] }]);
350
+
351
+ // The stored dataset is now smaller.
352
+ mutableEngine.getOriginData();
353
+ ```
354
+
355
+ The same mode also works through `MergeEngines`:
356
+
357
+ ```ts
358
+ import { MergeEngines } from "@devisfuture/mega-collection";
359
+ import { FilterEngine } from "@devisfuture/mega-collection/filter";
360
+
361
+ const mutableMerge = new MergeEngines<User>({
362
+ imports: [FilterEngine],
363
+ data: users,
364
+ filter: {
365
+ fields: ["id", "city"],
366
+ mutableExcludeField: "id",
367
+ },
368
+ });
369
+
370
+ mutableMerge.filter([{ field: "id", exclude: [1, 4] }]);
264
371
  ```
265
372
 
266
373
  #### Nested collections filter
@@ -324,17 +431,17 @@ engine.sort([
324
431
 
325
432
  ### `MergeEngines<T>` (root module)
326
433
 
327
- One engine that brings search, filter, and sort together on the same dataset.
434
+ One class that combines search, filter, and sort for the same dataset.
328
435
 
329
436
  **Constructor options:**
330
437
 
331
- | Option | Type | Description |
332
- | --------- | ----------------------------------------------------------- | -------------------------------------------- |
333
- | `imports` | `(typeof TextSearchEngine \| SortEngine \| FilterEngine)[]` | Engine classes to activate |
334
- | `data` | `T[]` | Shared dataset — passed once at construction |
335
- | `search` | `{ fields, nestedFields?, minQueryLength? }` | Config for TextSearchEngine |
336
- | `filter` | `{ fields, nestedFields?, filterByPreviousResult? }` | Config for FilterEngine |
337
- | `sort` | `{ fields }` | Config for SortEngine |
438
+ | Option | Type | Description |
439
+ | --------- | -------------------------------------------------------------------------- | -------------------------------------------- |
440
+ | `imports` | `(typeof TextSearchEngine \| SortEngine \| FilterEngine)[]` | Engine classes to create |
441
+ | `data` | `T[]` | Shared dataset — passed once at construction |
442
+ | `search` | `{ fields, nestedFields?, minQueryLength? }` | Config for TextSearchEngine |
443
+ | `filter` | `{ fields, nestedFields?, filterByPreviousResult?, mutableExcludeField? }` | Config for FilterEngine |
444
+ | `sort` | `{ fields }` | Config for SortEngine |
338
445
 
339
446
  **Methods:**
340
447
 
@@ -351,13 +458,16 @@ One engine that brings search, filter, and sort together on the same dataset.
351
458
  | `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
352
459
  | `clearData(module)` | Clear stored data for one module (`"search"`, `"sort"`, `"filter"`) |
353
460
 
461
+ If `filter.mutableExcludeField` is configured, `filter([{ field, exclude }])` on that field removes items from the stored filter dataset with swap-pop.
462
+ This changes the stored filter dataset and does not preserve order.
463
+
354
464
  ---
355
465
 
356
466
  ### `TextSearchEngine<T>` (search module)
357
467
 
358
- Text search engine. It supports `nestedFields` if you need to search inside
359
- nested collections such as `["orders.status"]`. Search methods return plain
360
- arrays.
468
+ Text search engine.
469
+ It supports `nestedFields` if you need to search inside nested collections such as `["orders.status"]`.
470
+ Search methods return plain arrays.
361
471
 
362
472
  | Method | Description |
363
473
  | ---------------------- | ---------------------------------------------------------- |
@@ -370,14 +480,16 @@ arrays.
370
480
 
371
481
  ### `FilterEngine<T>` (filter module)
372
482
 
373
- Filter engine for one or more rules. It supports `nestedFields` if you need to
374
- filter by values inside nested collections such as `["orders.status"]`.
483
+ Filter engine for one or more rules.
484
+ It supports `nestedFields` if you need to filter by values inside nested collections such as `["orders.status"]`.
485
+ Each criterion can use `values`, `exclude`, or both in the same rule.
375
486
 
376
- Constructor option highlights:
487
+ Main constructor options:
377
488
 
378
489
  | Option | Type | Description |
379
490
  | ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
380
491
  | `filterByPreviousResult` | `boolean` | When `true`, the next `filter(criteria)` call works on the previous result. By default each call starts from the original dataset. |
492
+ | `mutableExcludeField` | `string` | Optional field for removing items from stored data with swap-pop. This changes the stored dataset and does not preserve order. |
381
493
  | `nestedFields` | `string[]` | Nested field paths in dot notation, for example `["orders.status"]`. |
382
494
 
383
495
  | Method | Description |
@@ -392,8 +504,8 @@ Constructor option highlights:
392
504
 
393
505
  ### `SortEngine<T>` (sort module)
394
506
 
395
- Sort engine with prepared indexes for faster sorting in common cases. Sort
396
- methods return plain arrays.
507
+ Sort engine with prepared indexes for faster sorting in common cases.
508
+ Sort methods return plain arrays.
397
509
 
398
510
  | Method | Description |
399
511
  | ----------------------------------- | ----------------------------------------------------- |
@@ -406,7 +518,7 @@ methods return plain arrays.
406
518
 
407
519
  ---
408
520
 
409
- **Note on `data` method:** Calling `data` updates the stored dataset. It also rebuilds configured indexes and resets internal state when needed, so you usually do not need to call `clearIndexes` before it.
521
+ **Note on `data` method:** Calling `data` updates the stored dataset. It also rebuilds configured indexes and resets internal state when needed, so usually you do not need to call `clearIndexes` before it.
410
522
 
411
523
  ## Types
412
524
 
@@ -423,7 +535,7 @@ import type {
423
535
  } from "@devisfuture/mega-collection";
424
536
  ```
425
537
 
426
- Or from individual sub-modules:
538
+ You can also import them from individual sub-modules:
427
539
 
428
540
  ```ts
429
541
  import type {
@@ -0,0 +1 @@
1
+ var C=class{constructor(){this.indexes=new Map;this.itemPositions=new Map;}buildIndex(e,t){let n=new Map,s=new Map;for(let i=0,r=e.length;i<r;i++){let l=e[i],a=l[t];if(a==null)continue;let d=n.get(a);if(d)d.push(l),s.get(a).set(l,d.length-1);else {n.set(a,[l]);let u=new WeakMap;u.set(l,0),s.set(a,u);}}this.indexes.set(t,n),this.itemPositions.set(t,s);}getByValue(e,t){let n=this.indexes.get(e);return n?n.get(t)??[]:[]}getByValues(e,t){let n=this.indexes.get(e);if(!n)return [];if(t.length===1)return n.get(t[0])??[];let s=new Set,i=[];for(let r=0;r<t.length;r++){let l=n.get(t[r]);if(l!==void 0)for(let a=0;a<l.length;a++){let d=l[a];s.has(d)||(s.add(d),i.push(d));}}return i}hasIndex(e){return this.indexes.has(e)}removeItem(e){for(let t of this.indexes.keys())this.removeItemFromField(t,e);}clear(){this.indexes.clear(),this.itemPositions.clear();}getIndexMap(e){return this.indexes.get(e)}removeItemFromField(e,t){let n=t[e];if(n==null)return;let s=this.indexes.get(e),i=this.itemPositions.get(e),r=s?.get(n),l=i?.get(n),a=l?.get(t);if(!s||!i||!r||!l||a===void 0)return;let d=r.length-1,u=r[d];a!==d&&(r[a]=u,l.set(u,a)),r.pop(),l.delete(t),r.length===0&&(s.delete(n),i.delete(n));}};function g(x){return {value:x,enumerable:false,configurable:true,writable:true}}var y=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperties(t,{filter:g((n,s)=>s===void 0?this.callbacks.filter(e,n):this.callbacks.filter(n,s)),clearIndexes:g(()=>this.callbacks.clearIndexes()),data:g(n=>this.callbacks.data(n)),getOriginData:g(()=>this.callbacks.getOriginData()),clearData:g(()=>this.callbacks.clearData()),resetFilterState:g(()=>this.callbacks.resetFilterState())}),t}};var v=class x extends Error{constructor(e){super(e),this.name="FilterEngineError";}static missingDatasetForBuildIndex(){return new x("FilterEngine: no dataset in memory.")}static missingDatasetForFilter(){return new x("FilterEngine: no dataset in memory.")}static duplicateMutableExcludeField(e){return new x(`FilterEngine: cannot use mutable exclude on field \`${e}\` because it contains duplicate values.`)}};function T(x){let e=[];for(let t=0;t<x.length;t++){let n=x[t],s=Array.isArray(n.values),i=E(n.exclude),r=i!==null,l=s?R(n.values,i):null;!s&&!r||e.push({field:n.field,values:l?[...l]:[],exclude:i?[...i]:[],hasValues:s,hasExclude:r,includedValues:l,excludedValues:i});}return e}function F(x,e){return !(x.hasValues&&!x.includedValues.has(e)||x.hasExclude&&x.excludedValues.has(e))}function b(x){return x.hasValues&&x.values.length===0}function E(x){return !Array.isArray(x)||x.length===0?null:new Set(x)}function R(x,e){let t=new Set;for(let n=0;n<x.length;n++){let s=x[n];e?.has(s)||t.add(s);}return t}var I=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.indexes=new Map;this.itemPositions=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.indexes.clear(),this.itemPositions.clear();}buildIndexes(e){this.indexes.clear(),this.itemPositions.clear();for(let t of this.registeredFields)this.buildIndex(e,t);}removeItem(e){for(let t of this.indexes.keys())this.removeItemFromIndex(t,e);}filter(e,t,n){let s=this.resolveCriteria(t);if(e.length===0||s.length===0)return e;let i=[],r=[];for(let a=0;a<s.length;a++){let d=s[a];if(this.indexes.has(d.field)){i.push(d);continue}r.push(d);}let l=e;if(i.length>0&&(l=this.filterByIndexes(i,e,n),l.length===0))return l;for(let a=0;a<r.length;a++)if(l=this.filterLinearly(l,r[a]),l.length===0)return l;return l}resolveCriteria(e){if(e.length===0)return [];let t=e[0];return "hasValues"in t&&"hasExclude"in t&&"includedValues"in t?e:T(e)}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let n=this.fieldDescriptors.get(t);if(!n)return;let{collectionKey:s,nestedKey:i}=n,r=new Map,l=new Map;for(let a=0,d=e.length;a<d;a++){let u=e[a],h=u[s];if(Array.isArray(h))for(let o=0;o<h.length;o++){let c=h[o][i];if(c==null)continue;let f=r.get(c);if(f){f[f.length-1]!==u&&(f.push(u),l.get(c).set(u,f.length-1));continue}r.set(c,[u]);let p=new WeakMap;p.set(u,0),l.set(c,p);}}this.indexes.set(t,r),this.itemPositions.set(t,l);}removeItemFromIndex(e,t){let n=this.fieldDescriptors.get(e),s=this.indexes.get(e),i=this.itemPositions.get(e);if(!n||!s||!i)return;let{collectionKey:r,nestedKey:l}=n,a=t[r];if(!Array.isArray(a)||a.length===0)return;let d=new Set;for(let u=0;u<a.length;u++){let h=a[u][l];h!=null&&d.add(h);}for(let u of d){let h=s.get(u),o=i.get(u),c=o?.get(t);if(!h||!o||c===void 0)continue;let f=h.length-1,p=h[f];c!==f&&(h[c]=p,o.set(p,c)),h.pop(),o.delete(t),h.length===0&&(s.delete(u),i.delete(u));}}filterByIndexes(e,t,n){let s=e.filter(u=>u.hasValues),i=e.filter(u=>u.hasExclude),r=t===n?null:new Set(t);if(s.length===0)return this.applyIndexedExclusions(t,i);if(s.length===1){let u=this.indexes.get(s[0].field);if(!u)return [];let h=this.getItemsByValues(u,s[0].values);if(h.length===0)return [];let o=[];for(let c=0;c<h.length;c++){let f=h[c];r&&!r.has(f)||o.push(f);}return this.applyIndexedExclusions(o,i)}let l=s.map(u=>({criterion:u,size:this.estimateIndexSize(u)})).sort((u,h)=>u.size-h.size),a=r,d=[];for(let u=0;u<l.length;u++){let{criterion:h}=l[u],o=this.indexes.get(h.field);if(!o)return [];let c=this.getItemsByValues(o,h.values);if(c.length===0)return [];if(a===null)d=c;else {d=[];for(let f=0;f<c.length;f++){let p=c[f];a.has(p)&&d.push(p);}}if(d.length===0)return [];a=new Set(d);}return this.applyIndexedExclusions(d,i)}getItemsByValues(e,t){if(t.length===1)return e.get(t[0])??[];let n=new Set,s=[];for(let i=0;i<t.length;i++){let r=e.get(t[i]);if(r)for(let l=0;l<r.length;l++){let a=r[l];n.has(a)||(n.add(a),s.push(a));}}return s}estimateIndexSize(e){let t=this.indexes.get(e.field);return t?e.values.reduce((n,s)=>{let i=t.get(s);return i?n+i.length:n},0):1/0}filterLinearly(e,t){let n=this.fieldDescriptors.get(t.field);if(!n)return e;let{collectionKey:s,nestedKey:i}=n,r=[];for(let l=0;l<e.length;l++){let a=e[l],d=a[s];if(!Array.isArray(d))continue;let u=!t.hasValues,h=false;for(let o=0;o<d.length;o++){let c=d[o][i];if(t.hasExclude&&t.excludedValues.has(c)){h=true;break}t.hasValues&&t.includedValues.has(c)&&(u=true);}!h&&u&&r.push(a);}return r}applyIndexedExclusions(e,t){if(t.length===0||e.length===0)return e;let n=new Set;for(let i=0;i<t.length;i++){let r=t[i],l=this.indexes.get(r.field);if(!l)continue;let a=this.getItemsByValues(l,r.exclude);for(let d=0;d<a.length;d++)n.add(a[d]);}if(n.size===0)return e;let s=[];for(let i=0;i<e.length;i++){let r=e[i];n.has(r)||s.push(r);}return s}};var V=class{constructor(e={}){this.dataset=[];this.datasetPositions=new Map;this.hasDuplicateMutableExcludeValues=false;this.indexedFields=new Set;this.nestedCollection=new I;this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;this.previousResultsByCriteria=new Map;this.chainBuilder=new y({filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()});if(this.indexer=new C,this.filterByPreviousResult=e.filterByPreviousResult??false,this.mutableExcludeField=e.mutableExcludeField??null,this.nestedCollection.registerFields(e.nestedFields),!e.data)return;this.dataset=e.data,this.rebuildMutableExcludeState();let t=e.fields?.length,n=this.nestedCollection.hasRegisteredFields();if(t)for(let s of e.fields)this.indexedFields.add(s);(t||n)&&this.rebuildConfiguredIndexes();}rebuildConfiguredIndexes(){this.indexer.clear(),this.nestedCollection.clearIndexes();for(let 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 v.missingDatasetForBuildIndex();return this.indexer.buildIndex(this.dataset,e),this}return this.dataset=e,this.resetFilterState(),this.rebuildMutableExcludeState(),this.indexer.buildIndex(e,t),this}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),this}resetFilterState(){return this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this.previousResultsByCriteria.clear(),this}clearData(){return this.dataset=[],this.datasetPositions.clear(),this.hasDuplicateMutableExcludeValues=false,this.indexer.clear(),this.nestedCollection.clearIndexes(),this.resetFilterState(),this}data(e){return this.dataset=e,this.rebuildMutableExcludeState(),this.resetFilterState(),this.rebuildConfiguredIndexes(),this}getOriginData(){return this.dataset}filter(e,t){return t===void 0?this.withChain(this.rawFilter(e)):this.withChain(this.rawFilter(e,t))}rawFilter(e,t){let n=t===void 0,s,i,r;if(n){if(!this.dataset.length)throw v.missingDatasetForFilter();i=T(e);let o=this.applyMutableExclude(i);if(o!==void 0)return o;if(this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let c=this.createCriteriaCacheKey(i),f=this.createCriteriaCacheKey(this.previousCriteria),p=this.previousResultsByCriteria.get(c);if(c===f)return this.previousResult;if(p!==void 0)return this.storePreviousResult(p,true,this.dataset,i),p;let m=this.hasCriteriaBacktrack(this.previousCriteria,i)||this.previousResult.length===0&&!this.canApplySequentiallyToEmptyResult(this.previousCriteria,i);s=m?this.dataset:this.previousResult,r=m?i:this.createSequentialExecutionCriteria(this.previousCriteria,i);}else s=this.dataset,r=i;}else if(i=T(t),s=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===s){let o=this.createCriteriaCacheKey(i),c=this.createCriteriaCacheKey(this.previousCriteria),f=this.previousResultsByCriteria.get(o);if(o===c)return this.previousResult;if(f!==void 0)return this.storePreviousResult(f,false,e,i),f;let p=this.hasCriteriaBacktrack(this.previousCriteria,i)||this.previousResult.length===0&&!this.canApplySequentiallyToEmptyResult(this.previousCriteria,i);s=p?e:this.previousResult,r=p?i:this.createSequentialExecutionCriteria(this.previousCriteria,i);}else r=i;if(i.length===0)return this.filterByPreviousResult&&this.resetFilterState(),n?this.dataset:e;for(let o=0;o<r.length;o++)if(b(r[o]))return this.createEmptyResult(n,e,i);let l=[],a=[];for(let o=0;o<r.length;o++){let c=r[o];this.nestedCollection.hasField(c.field)?l.push(c):a.push(c);}if(l.length>0&&(s=this.nestedCollection.filter(s,l,this.dataset),s.length===0))return this.createEmptyResult(n,e,i);if(a.length===0)return this.storePreviousResult(s,n,e,i),s;let{indexedCriteria:d,linearCriteria:u}=a.reduce((o,c)=>(this.indexer.hasIndex(c.field)?o.indexedCriteria.push(c):o.linearCriteria.push(c),o),{indexedCriteria:[],linearCriteria:[]}),h;if(d.length>0&&u.length===0)return h=this.filterViaIndex(d,s),this.storePreviousResult(h,n,e,i),h;if(d.length>0&&u.length>0){let o=this.filterViaIndex(d,s);return h=this.linearFilter(o,u),this.storePreviousResult(h,n,e,i),h}return h=this.linearFilter(s,a),this.storePreviousResult(h,n,e,i),h}withChain(e){return this.chainBuilder.create(e)}rebuildMutableExcludeState(){if(this.datasetPositions.clear(),this.hasDuplicateMutableExcludeValues=false,this.mutableExcludeField!==null)for(let e=0;e<this.dataset.length;e++){let n=this.dataset[e][this.mutableExcludeField];n!=null&&(this.datasetPositions.has(n)&&(this.hasDuplicateMutableExcludeValues=true),this.datasetPositions.set(n,e));}}applyMutableExclude(e){if(this.mutableExcludeField===null||e.length!==1)return;let t=e[0];if(!(t.field!==this.mutableExcludeField||t.hasValues||!t.hasExclude)){if(this.hasDuplicateMutableExcludeValues)throw v.duplicateMutableExcludeField(this.mutableExcludeField);for(let n=0;n<t.exclude.length;n++)this.removeStoredItem(t.exclude[n]);return this.resetFilterState(),this.dataset}}removeStoredItem(e){let t=this.datasetPositions.get(e);if(t===void 0)return;let n=this.dataset.length-1,s=this.dataset[t],i=this.dataset[n];if(this.indexer.removeItem(s),this.nestedCollection.removeItem(s),t!==n&&(this.dataset[t]=i,this.mutableExcludeField!==null)){let r=i[this.mutableExcludeField];r!=null&&this.datasetPositions.set(r,t);}this.dataset.pop(),this.datasetPositions.delete(e);}linearFilter(e,t){let n=[];for(let s=0;s<e.length;s++){let i=e[s],r=true;for(let l=0;l<t.length;l++){let a=t[l];if(!F(a,i[a.field])){r=false;break}}r&&n.push(i);}return n}filterViaIndex(e,t){let s=t!==this.dataset?new Set(t):null,i=e.filter(o=>o.hasValues),r=e.filter(o=>o.hasExclude);if(i.length===0)return this.applyIndexedExclusions(t,r);if(i.length===1){let o=this.indexer.getByValues(i[0].field,i[0].values),c=[];for(let f=0;f<o.length;f++){let p=o[f];s&&!s.has(p)||F(i[0],p[i[0].field])&&c.push(p);}return this.applyIndexedExclusions(c,r)}let l=i.map(o=>({criterion:o,size:this.estimateIndexSize(o)})).sort((o,c)=>o.size-c.size),{field:a,values:d}=l[0].criterion,u=this.indexer.getByValues(a,d);if(u.length===0)return [];let h=[];for(let o=0;o<u.length;o++){let c=u[o],f=true;if(!(s&&!s.has(c))){for(let p=0;p<l.length;p++){let m=l[p].criterion;if(!F(m,c[m.field])){f=false;break}}f&&h.push(c);}}return this.applyIndexedExclusions(h,r)}estimateIndexSize(e){let t=this.indexer.getIndexMap(e.field);return t?e.values.reduce((n,s)=>{let i=t.get(s);return i?n+i.length:n},0):1/0}applyIndexedExclusions(e,t){if(t.length===0||e.length===0)return e.slice();let n=new Set;for(let i=0;i<t.length;i++){let r=t[i],l=this.indexer.getIndexMap(r.field);if(l)for(let a=0;a<r.exclude.length;a++){let d=l.get(r.exclude[a]);if(d)for(let u=0;u<d.length;u++)n.add(d[u]);}}if(n.size===0)return e.slice();let s=[];for(let i=0;i<e.length;i++){let r=e[i];n.has(r)||s.push(r);}return s}createEmptyResult(e,t,n){let s=[];return this.storePreviousResult(s,e,t,n),s}storePreviousResult(e,t,n,s){this.filterByPreviousResult&&(this.previousResult=e,this.previousCriteria=s,this.previousBaseData=t?this.dataset:n,this.previousResultsByCriteria.set(this.createCriteriaCacheKey(s),e));}createCriteriaCacheKey(e){let t=this.createCriteriaStateMap(e);return JSON.stringify([...t.entries()].sort(([n],[s])=>n.localeCompare(s)).map(([n,s])=>({field:n,hasValues:s.hasValues,hasExclude:s.hasExclude,values:s.values.map(i=>JSON.stringify(i)).sort(),exclude:s.exclude.map(i=>JSON.stringify(i)).sort()})))}createSequentialExecutionCriteria(e,t){let n=new Map;for(let s=0;s<e.length;s++){let i=e[s];n.set(i.field,i);}return t.map(s=>{let i=n.get(s.field);if(!i||!i.hasValues||!s.hasValues||i.hasExclude||s.hasExclude||s.includedValues.size<=i.includedValues.size)return s;for(let l of i.includedValues)if(!s.includedValues.has(l))return s;let r=[];for(let l of s.includedValues)i.includedValues.has(l)||r.push(l);return r.length===0?s:{...s,values:r,includedValues:new Set(r)}})}hasCriteriaBacktrack(e,t){let n=this.createCriteriaStateMap(e),s=this.createCriteriaStateMap(t);for(let[i,r]of n){let l=s.get(i);if(!l||this.isCriterionBacktracked(r,l))return true}return false}canApplySequentiallyToEmptyResult(e,t){let n=this.createCriteriaStateMap(e),s=this.createCriteriaStateMap(t);for(let[i,r]of s){let l=n.get(i);if(l){if(l.hasValues!==r.hasValues&&(l.hasValues||!r.hasValues))return false;if(l.hasValues&&r.hasValues){let a=l.includedValues,d=r.includedValues;if(!this.areSetsEqual(a,d)&&!this.isSubset(a,d))return false}if(l.hasExclude!==r.hasExclude&&(l.hasExclude||!r.hasExclude))return false;if(l.hasExclude&&r.hasExclude){let a=l.excludedValues,d=r.excludedValues;if(!this.areSetsEqual(a,d)&&!this.isSubset(a,d))return false}}}return true}createCriteriaStateMap(e){let t=new Map;for(let n=0;n<e.length;n++){let s=e[n],i=t.get(s.field);if(!i){t.set(s.field,{...s,values:s.values.slice(),exclude:s.exclude.slice(),includedValues:s.includedValues?new Set(s.includedValues):null,excludedValues:s.excludedValues?new Set(s.excludedValues):null});continue}if(s.hasValues)if(!i.hasValues)i.hasValues=true,i.includedValues=new Set(s.includedValues);else for(let r of i.includedValues)s.includedValues.has(r)||i.includedValues.delete(r);if(s.hasExclude)if(!i.hasExclude)i.hasExclude=true,i.excludedValues=new Set(s.excludedValues);else for(let r of s.excludedValues)i.excludedValues.add(r);if(i.hasValues&&i.hasExclude)for(let r of i.excludedValues)i.includedValues.delete(r);i.values=i.includedValues?[...i.includedValues]:[],i.exclude=i.excludedValues?[...i.excludedValues]:[];}return t}isCriterionBacktracked(e,t){if(e.hasValues&&!t.hasValues)return true;if(e.hasValues&&t.hasValues){let n=e.includedValues,s=t.includedValues;if(!this.areSetsEqual(n,s))return this.isSubset(s,n)}if(!e.hasValues&&t.hasValues)return false;if(e.hasExclude&&!t.hasExclude)return true;if(!e.hasExclude&&t.hasExclude)return false;if(e.hasExclude&&t.hasExclude){let n=e.excludedValues,s=t.excludedValues;if(!this.areSetsEqual(n,s))return this.isSubset(s,n)}return false}isSubset(e,t){for(let n of e)if(!t.has(n))return false;return true}areSetsEqual(e,t){if(e===t)return true;if(!e||!t||e.size!==t.size)return false;for(let n of e)if(!t.has(n))return false;return true}};export{V as a};
@@ -0,0 +1 @@
1
+ import {a}from'./chunk-XCB43Y63.mjs';import {a as a$2}from'./chunk-LSQXPQRE.mjs';import {a as a$1}from'./chunk-ZJ6RQRJN.mjs';function c(a){return {value:a,enumerable:false,configurable:true,writable:true}}var g=class{constructor(e){this.callbacks=e;}create(e){let r=e;return Object.defineProperties(r,{search:c((t,i)=>i===void 0?this.callbacks.search(t):this.callbacks.search(t,i)),sort:c((t,i,n)=>i===void 0?this.callbacks.sort(e,t,n):this.callbacks.sort(t,i,n)),filter:c((t,i)=>i===void 0?this.callbacks.filter(e,t):this.callbacks.filter(t,i)),clearIndexes:c(t=>(this.callbacks.clearIndexes(t),this.create(e))),clearData:c(t=>(this.callbacks.clearData(t),this.create(e))),data:c(t=>this.callbacks.data(t)),getOriginData:c(()=>this.callbacks.getOriginData())}),r}};var x=a$3=>a$3===a?"search":a$3===a$1?"sort":a$3===a$2?"filter":null,y=(a$3,e,r)=>{if(a$3===a){let t=new a({data:e,...r});return {moduleName:"search",executeSearch:(i,n)=>n===void 0?t.search(i):t.search(i,n),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:i=>t.data(i),getOriginData:()=>t.getOriginData()}}if(a$3===a$1){let t=new a$1({data:e,...r});return {moduleName:"sort",executeSort:(i,n,s)=>n===void 0?t.sort(i):t.sort(i,n,s),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:i=>t.data(i),getOriginData:()=>t.getOriginData()}}if(a$3===a$2){let t=new a$2({data:e,...r});return {moduleName:"filter",executeFilter:(i,n)=>n===void 0?t.rawFilter(i):t.rawFilter(i,n),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:i=>t.data(i),getOriginData:()=>t.getOriginData()}}return null};var w={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},l=class a extends Error{constructor(e){super(e),this.name="MergeEnginesError";}static unavailableMethod(e){return new a(`MergeEngines: Method "${e}" is not available.`)}static unavailableEngine(e){let r=w[e];return new a(`MergeEngines: ${r} is not available.`)}static unavailableGetOriginData(){return new a("MergeEngines: getOriginData is not available.")}};var f=class{constructor(e){this.previousSearchState=null;this.previousSortState=null;this.chainBuilder=new g({search:(e,r)=>r===void 0?this.search(e):this.search(e,r),sort:(e,r,t)=>r===void 0?this.sort(e):this.sort(e,r,t),filter:(e,r)=>r===void 0?this.filter(e):this.filter(e,r),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:e=>this.clearIndexes(e),clearData:e=>this.clearData(e)});let{imports:r,data:t,...i}=e,n=new Set(r),s=null,M=null,p=null,m={},S={},D={},C=null;for(let T of n){let E=x(T);if(!E)continue;let N=this.getModuleInitOptions(E,T.name,i),o=y(T,t,N);o&&(o.moduleName==="search"&&!s&&(s=o),o.moduleName==="sort"&&!M&&(M=o),o.moduleName==="filter"&&!p&&(p=o),m[o.moduleName]=()=>o.clearIndexes(),S[o.moduleName]=()=>o.clearData(),D[o.moduleName]=v=>o.data(v),C??(C=()=>o.getOriginData()));}this.searchModule=s,this.sortModule=M,this.filterModule=p,this.clearIndexMethods=m,this.clearDataMethods=S,this.setDataMethods=D,this.getOriginDataMethod=C;}getModuleInitOptions(e,r,t){let i={};for(let n of [e,r]){let s=t[n];this.isRecord(s)&&Object.assign(i,s);}return i}isRecord(e){return typeof e=="object"&&e!==null}clearOperationState(e){(!e||e==="search")&&(this.previousSearchState=null),(!e||e==="sort")&&(this.previousSortState=null);}createSearchCacheKey(e,r){return JSON.stringify([e,r??null])}createSortCacheKey(e,r){return JSON.stringify({descriptors:e,inPlace:r??false})}search(e,r){if(!this.searchModule)throw l.unavailableEngine("search");let t=this.searchModule.getOriginData(),i=this.createSearchCacheKey(e,r);if(this.previousSearchState?.originData===t&&this.previousSearchState.key===i)return this.withChain(this.previousSearchState.result);let n;return r===void 0?n=this.searchModule.executeSearch(e):n=this.searchModule.executeSearch(e,r),this.previousSearchState={key:i,originData:t,result:n},this.withChain(n)}sort(e,r,t){if(!this.sortModule)throw l.unavailableEngine("sort");if(r===void 0)return this.withChain(this.sortModule.executeSort(e));let i=e;if(!t){let n=this.createSortCacheKey(r,t);if(this.previousSortState?.sourceData===i&&this.previousSortState.key===n)return this.withChain(this.previousSortState.result);let s=this.sortModule.executeSort(i,r,t);return this.previousSortState={key:n,sourceData:i,result:s},this.withChain(s)}return this.withChain(this.sortModule.executeSort(i,r,t))}filter(e,r){if(!this.filterModule)throw l.unavailableEngine("filter");return r===void 0?this.withChain(this.filterModule.executeFilter(e)):this.withChain(this.filterModule.executeFilter(e,r))}withChain(e){return this.chainBuilder.create(e)}getOriginData(){if(this.getOriginDataMethod)return this.getOriginDataMethod();throw l.unavailableGetOriginData()}clearIndexes(e){let r=this.clearIndexMethods[e];if(r)return r(),this.clearOperationState(e),this;throw l.unavailableEngine(e)}data(e){let r=["search","sort","filter"];this.clearOperationState();for(let t of r){let i=this.setDataMethods[t];i&&i(e);}return this}clearData(e){let r=this.clearDataMethods[e];if(r)return r(),this.clearOperationState(e),this;throw l.unavailableEngine(e)}};export{f as a};
@@ -0,0 +1,2 @@
1
+ var p=class u extends Error{constructor(e){super(e),this.name="TextSearchEngineError";}static missingDatasetForBuildIndex(){return new u("TextSearchEngine: no dataset in memory.")}};function T(u){let e=u.toLowerCase(),t=Math.min(3,e.length),s=e.length-t+1,n=new Array(s);for(let i=0;i<s;i++)n[i]=e.substring(i,i+t);return n}function L(u,e){let t=u.get(e);if(t)return t;let s=new Set;return u.set(e,s),s}function I(u){let e=T(u);if(e.length<=12)return new Set(e);let t=new Set,s=e.length-1,n=11;for(let i=0;i<=n;i++){let o=Math.round(i*s/n);t.add(e[o]);}return t}function x(u,e,t){for(let s=0,n=e.length;s<n;s++){let i=n-s,o=Math.min(3,i);for(let r=1;r<=o;r++){let a=e.substring(s,s+r);L(u,a).add(t);}}}var y=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.ngramIndexes=new Map;this.normalizedFieldValues=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)}hasIndexes(){return this.ngramIndexes.size>0}clearIndexes(){this.ngramIndexes.clear(),this.normalizedFieldValues.clear();}buildIndexes(e){this.clearIndexes();for(let t of this.registeredFields)this.buildIndex(e,t);}searchAllIndexedFields(e,t,s){let n=new Set,i=[];for(let o of this.registeredFields)for(let r of this.searchIndexedField(e,o,t,s))n.has(r)||(n.add(r),i.push(r));return i}searchIndexedField(e,t,s,n){let i=this.ngramIndexes.get(t);if(!i)return [];let o=[];for(let d of n){let l=i.get(d);if(!l)return [];o.push(l);}o.sort((d,l)=>d.size-l.size);let r=o[0],a=o.length,h=[],c=this.normalizedFieldValues.get(t);for(let d of r){let l=true;for(let m=1;m<a;m++)if(!o[m].has(d)){l=false;break}if(!l)continue;let g=e[d];!g||!c?.[d]?.includes(s)||h.push(g);}return h}searchFieldLinear(e,t,s){let n=this.fieldDescriptors.get(t);if(!n)return [];let{collectionKey:i,nestedKey:o}=n,r=[];for(let a=0;a<e.length;a++){let h=e[a],c=h[i];if(!Array.isArray(c))continue;let d=false;for(let l=0;l<c.length;l++){let g=c[l][o];if(typeof g=="string"&&g.toLowerCase().includes(s)){d=true;break}}d&&r.push(h);}return r}matchesAnyField(e,t){for(let s of this.registeredFields){let n=this.fieldDescriptors.get(s);if(!n)continue;let{collectionKey:i,nestedKey:o}=n,r=e[i];if(Array.isArray(r))for(let a=0;a<r.length;a++){let h=r[a][o];if(typeof h=="string"&&h.toLowerCase().includes(t))return true}}return false}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let s=this.fieldDescriptors.get(t);if(!s)return;let{collectionKey:n,nestedKey:i}=s,o=new Map,r=new Array(e.length);for(let a=0,h=e.length;a<h;a++){let d=e[a][n];if(!Array.isArray(d))continue;let l=[];for(let g=0;g<d.length;g++){let f=d[g][i];if(typeof f!="string")continue;let m=f.toLowerCase();l.push(m),x(o,m,a);}l.length!==0&&(r[a]=l.join(`
2
+ `));}this.ngramIndexes.set(t,o),this.normalizedFieldValues.set(t,r);}};var F=class{constructor(e={}){this.ngramIndexes=new Map;this.normalizedFieldValues=new Map;this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new y;if(this.minQueryLength=e.minQueryLength??1,this.nestedCollection.registerFields(e.nestedFields),!e.data)return;this.dataset=e.data;let t=e.fields?.length,s=this.nestedCollection.hasRegisteredFields();if(t)for(let n of e.fields)this.indexedFields.add(n);(t||s)&&this.rebuildConfiguredIndexes();}rebuildConfiguredIndexes(){this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes();for(let e of this.indexedFields)this.buildIndex(this.dataset,e);this.nestedCollection.hasRegisteredFields()&&this.nestedCollection.buildIndexes(this.dataset);}buildIndex(e,t){let s,n;if(Array.isArray(e))s=e,n=t;else {if(!this.dataset.length)throw p.missingDatasetForBuildIndex();s=this.dataset,n=e;}this.dataset=s;let i=new Map,o=new Array(s.length);for(let r=0,a=s.length;r<a;r++){let h=s[r][n];if(typeof h!="string")continue;let c=h.toLowerCase();o[r]=c,x(i,c,r);}return this.ngramIndexes.set(n,i),this.normalizedFieldValues.set(n,o),this}search(e,t){return t===void 0?this.searchAllFields(e):this.searchField(e,t)}normalizeQuery(e){return e.trim().toLowerCase()}searchAllFields(e){let t=this.normalizeQuery(e);if(!t)return this.dataset;if(t.length<this.minQueryLength)return this.dataset;if(!this.ngramIndexes.size&&!this.nestedCollection.hasIndexes())return this.searchAllFieldsLinear(t);let s=I(t);if(!s.size)return [];let n=new Set,i=[];for(let o of this.ngramIndexes.keys())for(let r of this.searchFieldWithPreparedQuery(o,t,s))n.has(r)||(n.add(r),i.push(r));for(let o of this.nestedCollection.searchAllIndexedFields(this.dataset,t,s))n.has(o)||(n.add(o),i.push(o));return i}searchField(e,t){let s=this.normalizeQuery(t);if(!s)return this.dataset;if(s.length<this.minQueryLength)return this.dataset;if(this.nestedCollection.hasField(e)){let i=I(s);return i.size?this.nestedCollection.hasIndexes()?this.nestedCollection.searchIndexedField(this.dataset,e,s,i):this.nestedCollection.searchFieldLinear(this.dataset,e,s):[]}if(!this.ngramIndexes.size)return this.searchFieldLinear(e,s);let n=I(s);return n.size?this.searchFieldWithPreparedQuery(e,s,n):[]}searchFieldWithPreparedQuery(e,t,s){let n=this.ngramIndexes.get(e);if(!n)return [];let i=[];for(let c of s){let d=n.get(c);if(!d)return [];i.push(d);}i.sort((c,d)=>c.size-d.size);let o=i[0],r=i.length,a=[],h=this.normalizedFieldValues.get(e);for(let c of o){let d=true;for(let f=1;f<r;f++)if(!i[f].has(c)){d=false;break}if(!d)continue;let l=this.dataset[c];if(!l)continue;h?.[c]?.includes(t)&&a.push(l);}return a}searchAllFieldsLinear(e){if(!this.dataset.length)return [];let t=[];for(let s=0;s<this.dataset.length;s++){let n=this.dataset[s],i=false;for(let o in n){let r=n[o];if(typeof r=="string"&&r.toLowerCase().includes(e)){i=true;break}}i||(i=this.nestedCollection.matchesAnyField(n,e)),i&&t.push(n);}return t}searchFieldLinear(e,t){if(!this.dataset.length)return [];if(this.nestedCollection.hasField(e))return this.nestedCollection.searchFieldLinear(this.dataset,e,t);let s=[];for(let n=0;n<this.dataset.length;n++){let i=this.dataset[n][e];typeof i=="string"&&i.toLowerCase().includes(t)&&s.push(this.dataset[n]);}return s}clearIndexes(){return this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}getOriginData(){return this.dataset}data(e){return this.dataset=e,this.rebuildConfiguredIndexes(),this}clearData(){return this.dataset=[],this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}};export{F as a};
@@ -0,0 +1 @@
1
+ var u=class f extends Error{constructor(r){super(r),this.name="SortEngineError";}static missingDatasetForBuildIndex(){return new f("SortEngine: no dataset in memory.")}static missingDatasetForSort(){return new f("SortEngine: no dataset in memory.")}};var g=class{constructor(r={}){this.cache=new Map;this.dataset=[];this.indexedFields=new Set;if(r.data&&(this.dataset=r.data,r.fields?.length)){for(let a of r.fields)this.indexedFields.add(a);this.rebuildConfiguredIndexes();}}rebuildConfiguredIndexes(){this.cache.clear();for(let r of this.indexedFields)this.buildIndex(this.dataset,r);}buildIndex(r,a){let l,t;if(Array.isArray(r))l=r,t=a;else {if(!this.dataset.length)throw u.missingDatasetForBuildIndex();l=this.dataset,t=r;}this.dataset=l;let e=l.length,s=new Uint32Array(e),n=new Array(e);for(let o=0;o<e;o++)s[o]=o,n[o]=l[o][t];if(typeof n[0]=="number"){let o=new Float64Array(e);for(let d=0;d<e;d++)o[d]=n[d];s.sort((d,c)=>o[d]-o[c]);}else s.sort((o,d)=>{let c=n[o],h=n[d];return c<h?-1:c>h?1:0});return this.cache.set(t,{indexes:s,dataRef:l,itemCount:e}),this}clearIndexes(){return this.cache.clear(),this}clearData(){return this.dataset=[],this.cache.clear(),this}data(r){return this.dataset=r,this.rebuildConfiguredIndexes(),this}getOriginData(){return this.dataset}sort(r,a,l=false){let t,e,s=a===void 0;if(a===void 0){if(!this.dataset.length)throw u.missingDatasetForSort();t=this.dataset,e=r;}else t=r,e=a;if(e.length===0||t.length===0)return t;if(e.length===1){let{field:o,direction:d}=e[0],c=this.cache.get(o);if(s&&c?.dataRef===t&&c.itemCount===t.length)return this.reconstructFromIndex(t,c.indexes,d)}let n=l?t:t.slice();if(e.length===1&&t.length>0&&typeof t[0][e[0].field]=="number")return this.radixSortNumeric(n,e[0].field,e[0].direction);let i=this.buildComparator(e);return n.sort(i),n}reconstructFromIndex(r,a,l){let t=r.length,e=new Array(t);if(l==="asc")for(let s=0;s<t;s++)e[s]=r[a[s]];else for(let s=0;s<t;s++)e[s]=r[a[t-1-s]];return e}buildComparator(r){let a=r.map(({field:e})=>e),l=r.map(({direction:e})=>e==="asc"?1:-1),t=a.length;return (e,s)=>{for(let n=0;n<t;n++){let i=e[a[n]],o=s[a[n]];if(i<o)return -l[n];if(i>o)return l[n]}return 0}}radixSortNumeric(r,a,l){let t=r.length,e=new Float64Array(t);for(let i=0;i<t;i++)e[i]=r[i][a];let s=new Uint32Array(t);for(let i=0;i<t;i++)s[i]=i;s.sort((i,o)=>e[i]-e[o]);let n=new Array(t);if(l==="asc")for(let i=0;i<t;i++)n[i]=r[s[i]];else for(let i=0;i<t;i++)n[t-1-i]=r[s[i]];return n}};export{g as a};
@@ -1,5 +1,5 @@
1
- import { C as CollectionItem, F as FilterCriterion } from '../types-DuQWbqOC.mjs';
2
- export { I as IndexableKey } from '../types-DuQWbqOC.mjs';
1
+ import { C as CollectionItem, F as FilterCriterion } from '../types-4YEflcxU.mjs';
2
+ export { I as IndexableKey } from '../types-4YEflcxU.mjs';
3
3
 
4
4
  interface FilterEngineChain<T extends CollectionItem> {
5
5
  filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
@@ -12,13 +12,12 @@ interface FilterEngineChain<T extends CollectionItem> {
12
12
  }
13
13
  interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
14
14
  data?: T[];
15
+ mutableExcludeField?: keyof T & string;
15
16
  fields?: (keyof T & string)[];
16
17
  nestedFields?: string[];
17
18
  filterByPreviousResult?: boolean;
18
19
  }
19
20
 
20
- declare const FILTER_ENGINE_EXECUTE: unique symbol;
21
-
22
21
  /**
23
22
  * FilterEngine class for filtering collections by multiple criteria,
24
23
  * supporting indexed lookups and linear scans for large datasets.
@@ -27,19 +26,26 @@ declare const FILTER_ENGINE_EXECUTE: unique symbol;
27
26
  declare class FilterEngine<T extends CollectionItem> {
28
27
  private indexer;
29
28
  private readonly filterByPreviousResult;
29
+ private readonly mutableExcludeField;
30
30
  private dataset;
31
+ private readonly datasetPositions;
32
+ private hasDuplicateMutableExcludeValues;
31
33
  private readonly indexedFields;
32
34
  private readonly nestedCollection;
33
35
  private previousResult;
34
36
  private previousCriteria;
35
37
  private previousBaseData;
38
+ private readonly previousResultsByCriteria;
36
39
  private readonly chainBuilder;
37
40
  /**
38
41
  * Creates a new FilterEngine with optional data and fields to index.
39
42
  */
40
43
  constructor(options?: FilterEngineOptions<T>);
41
- private ensureConfiguredFieldIndex;
42
- private ensureIndexesForCriteria;
44
+ private rebuildConfiguredIndexes;
45
+ /**
46
+ * Builds an index for the given field.
47
+ */
48
+ private buildIndex;
43
49
  clearIndexes(): this;
44
50
  resetFilterState(): this;
45
51
  clearData(): this;
@@ -50,22 +56,12 @@ declare class FilterEngine<T extends CollectionItem> {
50
56
  */
51
57
  filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
52
58
  filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
53
- [FILTER_ENGINE_EXECUTE](criteria: FilterCriterion<T>[]): T[];
54
- [FILTER_ENGINE_EXECUTE](data: T[], criteria: FilterCriterion<T>[]): T[];
59
+ rawFilter(criteria: FilterCriterion<T>[]): T[];
60
+ rawFilter(data: T[], criteria: FilterCriterion<T>[]): T[];
55
61
  private withChain;
56
- private cloneCriteria;
57
- /**
58
- * Checks if there are new criteria added.
59
- */
60
- private hasCriteriaAdditions;
61
- /**
62
- * Checks if there are criteria removed.
63
- */
64
- private hasCriteriaRemovals;
65
- /**
66
- * Gets the newly added criteria.
67
- */
68
- private getAddedCriteria;
62
+ private rebuildMutableExcludeState;
63
+ private applyMutableExclude;
64
+ private removeStoredItem;
69
65
  /**
70
66
  * Filters data linearly without index.
71
67
  */
@@ -78,6 +74,17 @@ declare class FilterEngine<T extends CollectionItem> {
78
74
  * Estimates the size of the index for a criterion.
79
75
  */
80
76
  private estimateIndexSize;
77
+ private applyIndexedExclusions;
78
+ private createEmptyResult;
79
+ private storePreviousResult;
80
+ private createCriteriaCacheKey;
81
+ private createSequentialExecutionCriteria;
82
+ private hasCriteriaBacktrack;
83
+ private canApplySequentiallyToEmptyResult;
84
+ private createCriteriaStateMap;
85
+ private isCriterionBacktracked;
86
+ private isSubset;
87
+ private areSetsEqual;
81
88
  }
82
89
 
83
90
  export { CollectionItem, FilterCriterion, FilterEngine, type FilterEngineChain, type FilterEngineOptions };
@@ -1 +1 @@
1
- export{b as FilterEngine}from'../chunk-RIPRMLMT.mjs';
1
+ export{a as FilterEngine}from'../chunk-LSQXPQRE.mjs';
package/dist/index.d.mts CHANGED
@@ -2,4 +2,6 @@ export { TextSearchEngine } from './search/index.mjs';
2
2
  export { FilterEngine } from './filter/index.mjs';
3
3
  export { SortEngine } from './sort/index.mjs';
4
4
  export { EngineApi, EngineConstructor, MergeEngines, MergeEnginesChain, MergeEnginesOptions, MergeModuleName } from './merge/index.mjs';
5
- export { C as CollectionItem, F as FilterCriterion, I as IndexableKey, S as SortDescriptor, a as SortDirection } from './types-DuQWbqOC.mjs';
5
+ export { C as CollectionItem, F as FilterCriterion, I as IndexableKey, S as SortDescriptor, a as SortDirection } from './types-4YEflcxU.mjs';
6
+ import './types-MIbN5Q4o.mjs';
7
+ import './types-C7pwTB0o.mjs';
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export{a as MergeEngines}from'./chunk-OJWACBNG.mjs';export{a as TextSearchEngine}from'./chunk-PLHHLXUH.mjs';export{b as FilterEngine}from'./chunk-RIPRMLMT.mjs';export{a as SortEngine}from'./chunk-7RNFZK7U.mjs';
1
+ export{a as MergeEngines}from'./chunk-NHFG4LIO.mjs';export{a as TextSearchEngine}from'./chunk-XCB43Y63.mjs';export{a as FilterEngine}from'./chunk-LSQXPQRE.mjs';export{a as SortEngine}from'./chunk-ZJ6RQRJN.mjs';
@@ -1,5 +1,8 @@
1
- import { C as CollectionItem, S as SortDescriptor, F as FilterCriterion } from '../types-DuQWbqOC.mjs';
2
- export { I as IndexableKey, a as SortDirection } from '../types-DuQWbqOC.mjs';
1
+ import { C as CollectionItem, S as SortDescriptor, F as FilterCriterion } from '../types-4YEflcxU.mjs';
2
+ export { I as IndexableKey, a as SortDirection } from '../types-4YEflcxU.mjs';
3
+ import { FilterEngineOptions } from '../filter/index.mjs';
4
+ import { T as TextSearchEngineOptions } from '../types-MIbN5Q4o.mjs';
5
+ import { S as SortEngineOptions } from '../types-C7pwTB0o.mjs';
3
6
 
4
7
  type MergeModuleName = "search" | "sort" | "filter";
5
8
  interface MergeEnginesChain<T extends CollectionItem> {
@@ -25,6 +28,9 @@ interface EngineApi {
25
28
  interface MergeEnginesOptions<T extends CollectionItem> {
26
29
  imports: EngineConstructor[];
27
30
  data: T[];
31
+ search?: TextSearchEngineOptions<T>;
32
+ filter?: FilterEngineOptions<T>;
33
+ sort?: SortEngineOptions<T>;
28
34
  [key: string]: unknown;
29
35
  }
30
36
 
@@ -41,6 +47,8 @@ declare class MergeEngines<T extends CollectionItem> {
41
47
  private readonly clearDataMethods;
42
48
  private readonly setDataMethods;
43
49
  private readonly getOriginDataMethod;
50
+ private previousSearchState;
51
+ private previousSortState;
44
52
  private readonly chainBuilder;
45
53
  /**
46
54
  * Creates a new MergeEngines instance with the given options.
@@ -52,6 +60,9 @@ declare class MergeEngines<T extends CollectionItem> {
52
60
  */
53
61
  private getModuleInitOptions;
54
62
  private isRecord;
63
+ private clearOperationState;
64
+ private createSearchCacheKey;
65
+ private createSortCacheKey;
55
66
  search(query: string): T[] & MergeEnginesChain<T>;
56
67
  search(field: (keyof T & string) | (string & {}), query: string): T[] & MergeEnginesChain<T>;
57
68
  sort(descriptors: SortDescriptor<T>[]): T[] & MergeEnginesChain<T>;
@@ -1 +1 @@
1
- export{a as MergeEngines}from'../chunk-OJWACBNG.mjs';import'../chunk-PLHHLXUH.mjs';import'../chunk-RIPRMLMT.mjs';import'../chunk-7RNFZK7U.mjs';
1
+ export{a as MergeEngines}from'../chunk-NHFG4LIO.mjs';import'../chunk-XCB43Y63.mjs';import'../chunk-LSQXPQRE.mjs';import'../chunk-ZJ6RQRJN.mjs';
@@ -1,12 +1,6 @@
1
- import { C as CollectionItem } from '../types-DuQWbqOC.mjs';
2
- export { I as IndexableKey } from '../types-DuQWbqOC.mjs';
3
-
4
- interface TextSearchEngineOptions<T extends CollectionItem = CollectionItem> {
5
- data?: T[];
6
- fields?: (keyof T & string)[];
7
- nestedFields?: string[];
8
- minQueryLength?: number;
9
- }
1
+ import { C as CollectionItem } from '../types-4YEflcxU.mjs';
2
+ export { I as IndexableKey } from '../types-4YEflcxU.mjs';
3
+ import { T as TextSearchEngineOptions } from '../types-MIbN5Q4o.mjs';
10
4
 
11
5
  /**
12
6
  * TextSearchEngine class for performing fast substring search on string fields
@@ -24,10 +18,7 @@ declare class TextSearchEngine<T extends CollectionItem> {
24
18
  * Creates a new TextSearchEngine with optional data and fields to index.
25
19
  */
26
20
  constructor(options?: TextSearchEngineOptions<T>);
27
- private ensureConfiguredFieldIndex;
28
- private ensureConfiguredIndexes;
29
- private ensureConfiguredNestedIndex;
30
- private ensureConfiguredNestedIndexes;
21
+ private rebuildConfiguredIndexes;
31
22
  /**
32
23
  * Builds an n-gram index for the given field.
33
24
  */
@@ -61,4 +52,4 @@ declare class TextSearchEngine<T extends CollectionItem> {
61
52
  clearData(): this;
62
53
  }
63
54
 
64
- export { CollectionItem, TextSearchEngine, type TextSearchEngineOptions };
55
+ export { CollectionItem, TextSearchEngine, TextSearchEngineOptions };
@@ -1 +1 @@
1
- export{a as TextSearchEngine}from'../chunk-PLHHLXUH.mjs';
1
+ export{a as TextSearchEngine}from'../chunk-XCB43Y63.mjs';
@@ -1,10 +1,6 @@
1
- import { C as CollectionItem, S as SortDescriptor } from '../types-DuQWbqOC.mjs';
2
- export { a as SortDirection } from '../types-DuQWbqOC.mjs';
3
-
4
- interface SortEngineOptions<T extends CollectionItem = CollectionItem> {
5
- data?: T[];
6
- fields?: (keyof T & string)[];
7
- }
1
+ import { C as CollectionItem, S as SortDescriptor } from '../types-4YEflcxU.mjs';
2
+ export { a as SortDirection } from '../types-4YEflcxU.mjs';
3
+ import { S as SortEngineOptions } from '../types-C7pwTB0o.mjs';
8
4
 
9
5
  /**
10
6
  * SortEngine class for sorting large datasets using pre-built indexes
@@ -19,7 +15,7 @@ declare class SortEngine<T extends CollectionItem> {
19
15
  * Creates a new SortEngine with optional data and fields to index.
20
16
  */
21
17
  constructor(options?: SortEngineOptions<T>);
22
- private ensureConfiguredIndex;
18
+ private rebuildConfiguredIndexes;
23
19
  /**
24
20
  * Builds an index for sorting the given field.
25
21
  */
@@ -50,4 +46,4 @@ declare class SortEngine<T extends CollectionItem> {
50
46
  private radixSortNumeric;
51
47
  }
52
48
 
53
- export { CollectionItem, SortDescriptor, SortEngine, type SortEngineOptions };
49
+ export { CollectionItem, SortDescriptor, SortEngine, SortEngineOptions };
@@ -1 +1 @@
1
- export{a as SortEngine}from'../chunk-7RNFZK7U.mjs';
1
+ export{a as SortEngine}from'../chunk-ZJ6RQRJN.mjs';
@@ -4,7 +4,8 @@ type IndexableKey<T> = {
4
4
  }[keyof T];
5
5
  interface FilterCriterion<T extends CollectionItem> {
6
6
  field: (keyof T & string) | (string & {});
7
- values: any[];
7
+ values?: any[];
8
+ exclude?: any[];
8
9
  }
9
10
  type SortDirection = "asc" | "desc";
10
11
  interface SortDescriptor<T extends CollectionItem> {
@@ -0,0 +1,8 @@
1
+ import { C as CollectionItem } from './types-4YEflcxU.mjs';
2
+
3
+ interface SortEngineOptions<T extends CollectionItem = CollectionItem> {
4
+ data?: T[];
5
+ fields?: (keyof T & string)[];
6
+ }
7
+
8
+ export type { SortEngineOptions as S };
@@ -0,0 +1,10 @@
1
+ import { C as CollectionItem } from './types-4YEflcxU.mjs';
2
+
3
+ interface TextSearchEngineOptions<T extends CollectionItem = CollectionItem> {
4
+ data?: T[];
5
+ fields?: (keyof T & string)[];
6
+ nestedFields?: string[];
7
+ minQueryLength?: number;
8
+ }
9
+
10
+ export type { TextSearchEngineOptions as T };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devisfuture/mega-collection",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "High-performance search, filter & sort engine for 100K+ item collections in JavaScript/TypeScript",
5
5
  "exports": {
6
6
  ".": {
@@ -1 +0,0 @@
1
- var c=class h extends Error{constructor(e){super(e),this.name="SortEngineError";}static missingDatasetForBuildIndex(){return new h("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForSort(){return new h("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call sort(data, descriptors).")}};var g=class{constructor(e={}){this.cache=new Map;this.dataset=[];this.indexedFields=new Set;if(e.data&&(this.dataset=e.data,e.fields?.length))for(let a of e.fields)this.indexedFields.add(a);}ensureConfiguredIndex(e){this.indexedFields.has(e)&&(this.cache.has(e)||this.dataset.length!==0&&this.buildIndex(this.dataset,e));}buildIndex(e,a){let l,t;if(Array.isArray(e))l=e,t=a;else {if(!this.dataset.length)throw c.missingDatasetForBuildIndex();l=this.dataset,t=e;}this.dataset=l;let r=l.length,s=new Uint32Array(r),o=new Array(r);for(let n=0;n<r;n++)s[n]=n,o[n]=l[n][t];if(typeof o[0]=="number"){let n=new Float64Array(r);for(let d=0;d<r;d++)n[d]=o[d];s.sort((d,u)=>n[d]-n[u]);}else s.sort((n,d)=>{let u=o[n],f=o[d];return u<f?-1:u>f?1:0});return this.cache.set(t,{indexes:s,dataRef:l,itemCount:r}),this}clearIndexes(){return this.cache.clear(),this}clearData(){return this.dataset=[],this.cache.clear(),this}data(e){return this.dataset=e,this.clearIndexes(),this}getOriginData(){return this.dataset}sort(e,a,l=false){let t,r;if(a===void 0){if(!this.dataset.length)throw c.missingDatasetForSort();t=this.dataset,r=e;}else t=e,r=a;if(r.length===0||t.length===0)return t;if(r.length===1){let{field:i,direction:n}=r[0];t===this.dataset&&this.ensureConfiguredIndex(i);let d=this.cache.get(i);if(d?.dataRef===t&&d.itemCount===t.length)return this.reconstructFromIndex(t,d.indexes,n)}let s=l?t:t.slice();if(r.length===1&&t.length>0&&typeof t[0][r[0].field]=="number")return this.radixSortNumeric(s,r[0].field,r[0].direction);let o=this.buildComparator(r);return s.sort(o),s}reconstructFromIndex(e,a,l){let t=e.length,r=new Array(t);if(l==="asc")for(let s=0;s<t;s++)r[s]=e[a[s]];else for(let s=0;s<t;s++)r[s]=e[a[t-1-s]];return r}buildComparator(e){let a=e.map(({field:r})=>r),l=e.map(({direction:r})=>r==="asc"?1:-1),t=a.length;return (r,s)=>{for(let o=0;o<t;o++){let i=r[a[o]],n=s[a[o]];if(i<n)return -l[o];if(i>n)return l[o]}return 0}}radixSortNumeric(e,a,l){let t=e.length,r=new Float64Array(t);for(let i=0;i<t;i++)r[i]=e[i][a];let s=new Uint32Array(t);for(let i=0;i<t;i++)s[i]=i;s.sort((i,n)=>r[i]-r[n]);let o=new Array(t);if(l==="asc")for(let i=0;i<t;i++)o[i]=e[s[i]];else for(let i=0;i<t;i++)o[t-1-i]=e[s[i]];return o}};export{g as a};
@@ -1 +0,0 @@
1
- import {a}from'./chunk-PLHHLXUH.mjs';import {b,a as a$2}from'./chunk-RIPRMLMT.mjs';import {a as a$1}from'./chunk-7RNFZK7U.mjs';var g=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"search",{value:(r,n)=>n===void 0?this.callbacks.search(r):this.callbacks.search(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"sort",{value:(r,n,i)=>n===void 0?this.callbacks.sort(e,r,i):this.callbacks.sort(r,n,i),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"filter",{value:(r,n)=>n===void 0?this.callbacks.filter(e,r):this.callbacks.filter(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:r=>(this.callbacks.clearIndexes(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:r=>(this.callbacks.clearData(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:r=>this.callbacks.data(r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),t}};var x=o=>o===a?"search":o===a$1?"sort":o===b?"filter":null,y=(o,e,t)=>{if(o===a){let r=new a({data:e,...t});return {moduleName:"search",executeSearch:(n,i)=>i===void 0?r.search(n):r.search(n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===a$1){let r=new a$1({data:e,...t});return {moduleName:"sort",executeSort:(n,i,s)=>i===void 0?r.sort(n):r.sort(n,i,s),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===b){let r=new b({data:e,...t});return {moduleName:"filter",executeFilter:(n,i)=>i===void 0?r[a$2](n):r[a$2](n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}return null};var N={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},l=class o extends Error{constructor(e){super(e),this.name="MergeEnginesError";}static unavailableMethod(e){return new o(`MergeEngines: Method "${e}" is not available. Add module with method "${e}" to the \`imports\` array.`)}static unavailableEngine(e){let t=N[e];return new o(`MergeEngines: ${t} is not available. Add ${t} to the \`imports\` array.`)}static unavailableGetOriginData(){return new o("MergeEngines: getOriginData is not available. Add TextSearchEngine, SortEngine, or FilterEngine to the `imports` array.")}};var m=class{constructor(e){this.chainBuilder=new g({search:(e,t)=>t===void 0?this.search(e):this.search(e,t),sort:(e,t,r)=>t===void 0?this.sort(e):this.sort(e,t,r),filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:e=>this.clearIndexes(e),clearData:e=>this.clearData(e)});let{imports:t,data:r,...n}=e,i=new Set(t),s=null,h=null,M=null,f={},E={},C={},b=null;for(let p of i){let D=x(p);if(!D)continue;let S=this.getModuleInitOptions(D,p.name,n),a=y(p,r,S);a&&(a.moduleName==="search"&&!s&&(s=a),a.moduleName==="sort"&&!h&&(h=a),a.moduleName==="filter"&&!M&&(M=a),f[a.moduleName]=()=>a.clearIndexes(),E[a.moduleName]=()=>a.clearData(),C[a.moduleName]=w=>a.data(w),b??(b=()=>a.getOriginData()));}this.searchModule=s,this.sortModule=h,this.filterModule=M,this.clearIndexMethods=f,this.clearDataMethods=E,this.setDataMethods=C,this.getOriginDataMethod=b;}getModuleInitOptions(e,t,r){let n={};for(let i of [e,t]){let s=r[i];this.isRecord(s)&&Object.assign(n,s);}return n}isRecord(e){return typeof e=="object"&&e!==null}search(e,t){if(!this.searchModule)throw l.unavailableEngine("search");return t===void 0?this.withChain(this.searchModule.executeSearch(e)):this.withChain(this.searchModule.executeSearch(e,t))}sort(e,t,r){if(!this.sortModule)throw l.unavailableEngine("sort");return t===void 0?this.withChain(this.sortModule.executeSort(e)):this.withChain(this.sortModule.executeSort(e,t,r))}filter(e,t){if(!this.filterModule)throw l.unavailableEngine("filter");return t===void 0?this.withChain(this.filterModule.executeFilter(e)):this.withChain(this.filterModule.executeFilter(e,t))}withChain(e){return this.chainBuilder.create(e)}getOriginData(){if(this.getOriginDataMethod)return this.getOriginDataMethod();throw l.unavailableGetOriginData()}clearIndexes(e){let t=this.clearIndexMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}data(e){let t=["search","sort","filter"];for(let r of t){let n=this.setDataMethods[r];n&&n(e);}return this}clearData(e){let t=this.clearDataMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}};export{m as a};
@@ -1,2 +0,0 @@
1
- var x=class u extends Error{constructor(e){super(e),this.name="TextSearchEngineError";}static missingDatasetForBuildIndex(){return new u("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}};function T(u){let e=u.toLowerCase(),t=Math.min(3,e.length),s=e.length-t+1,n=new Array(s);for(let i=0;i<s;i++)n[i]=e.substring(i,i+t);return n}function C(u,e){let t=u.get(e);if(t)return t;let s=new Set;return u.set(e,s),s}function I(u){let e=T(u);if(e.length<=12)return new Set(e);let t=new Set,s=e.length-1,n=11;for(let i=0;i<=n;i++){let o=Math.round(i*s/n);t.add(e[o]);}return t}function p(u,e,t){for(let s=0,n=e.length;s<n;s++){let i=n-s,o=Math.min(3,i);for(let r=1;r<=o;r++){let a=e.substring(s,s+r);C(u,a).add(t);}}}var y=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.ngramIndexes=new Map;this.normalizedFieldValues=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)}hasIndex(e){return this.ngramIndexes.has(e)}hasIndexes(){return this.ngramIndexes.size>0}clearIndexes(){this.ngramIndexes.clear(),this.normalizedFieldValues.clear();}buildIndexes(e){this.clearIndexes();for(let t of this.registeredFields)this.buildIndex(e,t);}ensureIndex(e,t){this.registeredFields.has(t)&&(this.ngramIndexes.has(t)||this.buildIndex(e,t));}ensureAllIndexes(e){for(let t of this.registeredFields)this.ensureIndex(e,t);}searchAllIndexedFields(e,t,s){let n=new Set,i=[];for(let o of this.registeredFields)for(let r of this.searchIndexedField(e,o,t,s))n.has(r)||(n.add(r),i.push(r));return i}searchIndexedField(e,t,s,n){let i=this.ngramIndexes.get(t);if(!i)return [];let o=[];for(let d of n){let l=i.get(d);if(!l)return [];o.push(l);}o.sort((d,l)=>d.size-l.size);let r=o[0],a=o.length,h=[],c=this.normalizedFieldValues.get(t);for(let d of r){let l=true;for(let m=1;m<a;m++)if(!o[m].has(d)){l=false;break}if(!l)continue;let g=e[d];!g||!c?.[d]?.includes(s)||h.push(g);}return h}searchFieldLinear(e,t,s){let n=this.fieldDescriptors.get(t);if(!n)return [];let{collectionKey:i,nestedKey:o}=n,r=[];for(let a=0;a<e.length;a++){let h=e[a],c=h[i];if(!Array.isArray(c))continue;let d=false;for(let l=0;l<c.length;l++){let g=c[l][o];if(typeof g=="string"&&g.toLowerCase().includes(s)){d=true;break}}d&&r.push(h);}return r}matchesAnyField(e,t){for(let s of this.registeredFields){let n=this.fieldDescriptors.get(s);if(!n)continue;let{collectionKey:i,nestedKey:o}=n,r=e[i];if(Array.isArray(r))for(let a=0;a<r.length;a++){let h=r[a][o];if(typeof h=="string"&&h.toLowerCase().includes(t))return true}}return false}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let s=this.fieldDescriptors.get(t);if(!s)return;let{collectionKey:n,nestedKey:i}=s,o=new Map,r=new Array(e.length);for(let a=0,h=e.length;a<h;a++){let d=e[a][n];if(!Array.isArray(d))continue;let l=[];for(let g=0;g<d.length;g++){let f=d[g][i];if(typeof f!="string")continue;let m=f.toLowerCase();l.push(m),p(o,m,a);}l.length!==0&&(r[a]=l.join(`
2
- `));}this.ngramIndexes.set(t,o),this.normalizedFieldValues.set(t,r);}};var F=class{constructor(e={}){this.ngramIndexes=new Map;this.normalizedFieldValues=new Map;this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new y;if(this.minQueryLength=e.minQueryLength??1,this.nestedCollection.registerFields(e.nestedFields),!!e.data&&(this.dataset=e.data,e.fields?.length))for(let t of e.fields)this.indexedFields.add(t);}ensureConfiguredFieldIndex(e){this.indexedFields.has(e)&&(this.ngramIndexes.has(e)||this.dataset.length!==0&&this.buildIndex(this.dataset,e));}ensureConfiguredIndexes(){for(let e of this.indexedFields)this.ensureConfiguredFieldIndex(e);}ensureConfiguredNestedIndex(e){this.nestedCollection.hasField(e)&&(this.nestedCollection.hasIndex(e)||this.dataset.length!==0&&this.nestedCollection.ensureIndex(this.dataset,e));}ensureConfiguredNestedIndexes(){this.dataset.length!==0&&this.nestedCollection.ensureAllIndexes(this.dataset);}buildIndex(e,t){let s,n;if(Array.isArray(e))s=e,n=t;else {if(!this.dataset.length)throw x.missingDatasetForBuildIndex();s=this.dataset,n=e;}this.dataset=s;let i=new Map,o=new Array(s.length);for(let r=0,a=s.length;r<a;r++){let h=s[r][n];if(typeof h!="string")continue;let c=h.toLowerCase();o[r]=c,p(i,c,r);}return this.ngramIndexes.set(n,i),this.normalizedFieldValues.set(n,o),this}search(e,t){return t===void 0?this.searchAllFields(e):this.searchField(e,t)}normalizeQuery(e){return e.trim().toLowerCase()}searchAllFields(e){let t=this.normalizeQuery(e);if(!t)return this.dataset;if(t.length<this.minQueryLength)return this.dataset;if(this.ensureConfiguredIndexes(),this.ensureConfiguredNestedIndexes(),!this.ngramIndexes.size&&!this.nestedCollection.hasIndexes())return this.searchAllFieldsLinear(t);let s=I(t);if(!s.size)return [];let n=new Set,i=[];for(let o of this.ngramIndexes.keys())for(let r of this.searchFieldWithPreparedQuery(o,t,s))n.has(r)||(n.add(r),i.push(r));for(let o of this.nestedCollection.searchAllIndexedFields(this.dataset,t,s))n.has(o)||(n.add(o),i.push(o));return i}searchField(e,t){let s=this.normalizeQuery(t);if(!s)return this.dataset;if(s.length<this.minQueryLength)return this.dataset;if(this.nestedCollection.hasField(e)){this.ensureConfiguredNestedIndex(e);let i=I(s);return i.size?this.nestedCollection.hasIndex(e)?this.nestedCollection.searchIndexedField(this.dataset,e,s,i):this.nestedCollection.searchFieldLinear(this.dataset,e,s):[]}if(this.indexedFields.size>0){if(!this.indexedFields.has(e))return [];this.ensureConfiguredFieldIndex(e);}if(!this.ngramIndexes.size)return this.searchFieldLinear(e,s);let n=I(s);return n.size?this.searchFieldWithPreparedQuery(e,s,n):[]}searchFieldWithPreparedQuery(e,t,s){let n=this.ngramIndexes.get(e);if(!n)return [];let i=[];for(let c of s){let d=n.get(c);if(!d)return [];i.push(d);}i.sort((c,d)=>c.size-d.size);let o=i[0],r=i.length,a=[],h=this.normalizedFieldValues.get(e);for(let c of o){let d=true;for(let f=1;f<r;f++)if(!i[f].has(c)){d=false;break}if(!d)continue;let l=this.dataset[c];if(!l)continue;h?.[c]?.includes(t)&&a.push(l);}return a}searchAllFieldsLinear(e){if(!this.dataset.length)return [];let t=[];for(let s=0;s<this.dataset.length;s++){let n=this.dataset[s],i=false;for(let o in n){let r=n[o];if(typeof r=="string"&&r.toLowerCase().includes(e)){i=true;break}}i||(i=this.nestedCollection.matchesAnyField(n,e)),i&&t.push(n);}return t}searchFieldLinear(e,t){if(!this.dataset.length)return [];if(this.nestedCollection.hasField(e))return this.nestedCollection.searchFieldLinear(this.dataset,e,t);let s=[];for(let n=0;n<this.dataset.length;n++){let i=this.dataset[n][e];typeof i=="string"&&i.toLowerCase().includes(t)&&s.push(this.dataset[n]);}return s}clearIndexes(){return this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}getOriginData(){return this.dataset}data(e){return this.dataset=e,this.clearIndexes(),this}clearData(){return this.dataset=[],this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}};export{F as a};
@@ -1 +0,0 @@
1
- var T=class{constructor(){this.indexes=new Map;}buildIndex(e,t){let n=new Map;for(let s=0,r=e.length;s<r;s++){let i=e[s],l=i[t];if(l==null)continue;let a=n.get(l);a?a.push(i):n.set(l,[i]);}this.indexes.set(t,n);}getByValue(e,t){let n=this.indexes.get(e);return n?n.get(t)??[]:[]}getByValues(e,t){let n=this.indexes.get(e);if(!n)return [];if(t.length===1)return n.get(t[0])??[];let s=new Set,r=[];for(let i=0;i<t.length;i++){let l=n.get(t[i]);if(l!==void 0)for(let a=0;a<l.length;a++){let u=l[a];s.has(u)||(s.add(u),r.push(u));}}return r}hasIndex(e){return this.indexes.has(e)}clear(){this.indexes.clear();}getIndexMap(e){return this.indexes.get(e)}};var x=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"filter",{value:(n,s)=>s===void 0?this.callbacks.filter(e,n):this.callbacks.filter(n,s),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:()=>this.callbacks.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:n=>this.callbacks.data(n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:()=>this.callbacks.clearData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"resetFilterState",{value:()=>this.callbacks.resetFilterState(),enumerable:false,configurable:true,writable:true}),t}};var C=class p extends Error{constructor(e){super(e),this.name="FilterEngineError";}static missingDatasetForBuildIndex(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForFilter(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call filter(data, criteria).")}};var v=Symbol("FilterEngine.execute");var F=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.indexes=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)}hasIndex(e){return this.indexes.has(e)}clearIndexes(){this.indexes.clear();}buildIndexes(e){this.indexes.clear();for(let t of this.registeredFields)this.buildIndex(e,t);}ensureIndex(e,t){this.registeredFields.has(t)&&(this.indexes.has(t)||this.buildIndex(e,t));}filter(e,t,n){if(e.length===0||t.length===0)return e;let s=[],r=[];for(let a=0;a<t.length;a++){let u=t[a];if(this.indexes.has(u.field)){s.push(u);continue}r.push(u);}let i=e,l=e===n?null:new Set(e);if(s.length>0&&(i=this.filterByIndexes(s,l),i.length===0))return i;for(let a=0;a<r.length;a++)if(i=this.filterLinearly(i,r[a]),i.length===0)return i;return i}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let n=this.fieldDescriptors.get(t);if(!n)return;let{collectionKey:s,nestedKey:r}=n,i=new Map;for(let l=0,a=e.length;l<a;l++){let u=e[l],h=u[s];if(Array.isArray(h))for(let c=0;c<h.length;c++){let o=h[c][r];if(o==null)continue;let d=i.get(o);if(d){d[d.length-1]!==u&&d.push(u);continue}i.set(o,[u]);}}this.indexes.set(t,i);}filterByIndexes(e,t){if(e.length===1){let i=this.indexes.get(e[0].field);if(!i)return [];let l=this.getItemsByValues(i,e[0].values);if(l.length===0)return [];if(t===null)return l;let a=[];for(let u=0;u<l.length;u++){let h=l[u];t.has(h)&&a.push(h);}return a}let n=e.map(i=>({criterion:i,size:this.estimateIndexSize(i)})).sort((i,l)=>i.size-l.size),s=t,r=[];for(let i=0;i<n.length;i++){let{criterion:l}=n[i],a=this.indexes.get(l.field);if(!a)return [];let u=this.getItemsByValues(a,l.values);if(u.length===0)return [];if(s===null)r=u;else {r=[];for(let h=0;h<u.length;h++){let c=u[h];s.has(c)&&r.push(c);}}if(r.length===0)return [];s=new Set(r);}return r}getItemsByValues(e,t){if(t.length===1)return e.get(t[0])??[];let n=new Set,s=[];for(let r=0;r<t.length;r++){let i=e.get(t[r]);if(i)for(let l=0;l<i.length;l++){let a=i[l];n.has(a)||(n.add(a),s.push(a));}}return s}estimateIndexSize(e){let t=this.indexes.get(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}filterLinearly(e,t){let n=this.fieldDescriptors.get(t.field);if(!n)return e;let{collectionKey:s,nestedKey:r}=n,i=new Set(t.values),l=[];for(let a=0;a<e.length;a++){let u=e[a],h=u[s];if(!Array.isArray(h))continue;let c=false;for(let o=0;o<h.length;o++)if(i.has(h[o][r])){c=true;break}c&&l.push(u);}return l}};var I=class{constructor(e={}){this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new F;this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;this.chainBuilder=new x({filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()});if(this.indexer=new T,this.filterByPreviousResult=e.filterByPreviousResult??false,this.nestedCollection.registerFields(e.nestedFields),!!e.data&&(this.dataset=e.data,e.fields?.length))for(let t of e.fields)this.indexedFields.add(t);}ensureConfiguredFieldIndex(e){this.indexedFields.has(e)&&(this.indexer.hasIndex(e)||this.dataset.length!==0&&this.indexer.buildIndex(this.dataset,e));}ensureIndexesForCriteria(e){if(this.dataset.length!==0)for(let t=0;t<e.length;t++){let n=e[t].field;if(this.nestedCollection.hasField(n)){this.nestedCollection.ensureIndex(this.dataset,n);continue}this.ensureConfiguredFieldIndex(n);}}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),this}resetFilterState(){return this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this}clearData(){return this.dataset=[],this.indexer.clear(),this.nestedCollection.clearIndexes(),this.resetFilterState(),this}data(e){return this.dataset=e,this.resetFilterState(),this.clearIndexes(),this}getOriginData(){return this.dataset}filter(e,t){return t===void 0?this.withChain(this[v](e)):this.withChain(this[v](e,t))}[v](e,t){let n=t===void 0,s,r,i;if(n){if(!this.dataset.length)throw C.missingDatasetForFilter();if(r=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):(s=this.dataset,i=r);}else s=this.dataset,i=r;}else if(r=t,s=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===s){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):i=r;}else i=r;if(r.length===0)return this.filterByPreviousResult&&(this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null),n?this.dataset:s;this.ensureIndexesForCriteria(i),n&&!i&&(i=r);let l=[],a=[];for(let o=0;o<i.length;o++){let d=i[o];this.nestedCollection.hasField(d.field)?l.push(d):a.push(d);}if(l.length>0&&(s=this.nestedCollection.filter(s,l,this.dataset),s.length===0)){let o=[];return this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),o}if(a.length===0)return this.filterByPreviousResult&&(this.previousResult=s,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),s;let{indexedCriteria:u,linearCriteria:h}=a.reduce((o,d)=>(this.indexer.hasIndex(d.field)?o.indexedCriteria.push(d):o.linearCriteria.push(d),o),{indexedCriteria:[],linearCriteria:[]}),c;if(u.length>0&&h.length===0)return c=this.filterViaIndex(u,s),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c;if(u.length>0&&h.length>0){let o=this.filterViaIndex(u,s);return c=this.linearFilter(o,h),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}return c=this.linearFilter(s,a),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}withChain(e){return this.chainBuilder.create(e)}cloneCriteria(e){return e.map(({field:t,values:n})=>({field:t,values:[...n]}))}hasCriteriaAdditions(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of s){let l=n.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}hasCriteriaRemovals(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of n){let l=s.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}getAddedCriteria(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=[];for(let{field:r,values:i}of t){let l=n.get(r);if(!l){s.push({field:r,values:[...i]});continue}let a=i.filter(u=>!l.has(u));a.length>0&&s.push({field:r,values:a});}return s}linearFilter(e,t){let n=new Map(t.map(({field:i,values:l})=>[i,new Set(l)])),s=t.map(({field:i})=>i),r=[];for(let i=0;i<e.length;i++){let l=e[i],a=true;for(let u=0;u<s.length;u++){let h=s[u];if(!n.get(h).has(l[h])){a=false;break}}a&&r.push(l);}return r}filterViaIndex(e,t){let s=t!==this.dataset?new Set(t):null;if(e.length===1){let o=this.indexer.getByValues(e[0].field,e[0].values);if(!s)return o.slice();let d=[];for(let f=0;f<o.length;f++){let g=o[f];s.has(g)&&d.push(g);}return d}let r=e.map(o=>({criterion:o,size:this.estimateIndexSize(o)})).sort((o,d)=>o.size-d.size),{field:i,values:l}=r[0].criterion,a=this.indexer.getByValues(i,l);if(a.length===0)return [];let u=new Map(r.slice(1).map(({criterion:{field:o,values:d}})=>[o,new Set(d)])),h=Array.from(u.keys()),c=[];for(let o=0;o<a.length;o++){let d=a[o],f=true;for(let g=0;g<h.length;g++){let m=h[g];if(!u.get(m).has(d[m])){f=false;break}}f&&s&&!s.has(d)&&(f=false),f&&c.push(d);}return c}estimateIndexSize(e){let t=this.indexer.getIndexMap(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}};export{v as a,I as b};