@devisfuture/mega-collection 2.2.0 → 2.3.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 CHANGED
@@ -1,573 +1,5 @@
1
- <p align="center">
2
- <img src="./illustration.png" alt="mega-collection illustration" width="100%" />
3
- </p>
1
+ # @devisfuture/mega-collection
4
2
 
5
- [![npm version](https://img.shields.io/npm/v/@devisfuture/mega-collection.svg)](https://www.npmjs.com/package/@devisfuture/mega-collection) [![Downloads](https://img.shields.io/npm/dt/@devisfuture/mega-collection.svg)](https://www.npmjs.com/package/@devisfuture/mega-collection) [![Coverage](https://img.shields.io/codecov/c/github/trae-op/mega-collection/main)](https://codecov.io/gh/trae-op/mega-collection) [![TypeScript](https://img.shields.io/badge/TypeScript-%233178C6.svg?style=flat&logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![GitHub Stars](https://img.shields.io/github/stars/trae-op/mega-collection?style=social)](https://github.com/trae-op/mega-collection)
3
+ Docs and examples: https://github.com/trae-op/mega-collection#readme
6
4
 
7
- If this package saved you some time, a ⭐ on GitHub would be much appreciated.
8
-
9
- ## Table of Contents
10
-
11
- - [What does this package solve](#what-does-this-package-solve) – what problem this package helps with
12
- - [Features](#features) – what the package can do
13
- - [React demo](#react-demo) – example project and live demo
14
- - [Install](#install) – how to install the package
15
- - [Quick Start](#quick-start) – basic usage examples
16
- - [All-in-one: `MergeEngines`](#all-in-one-mergeengines) – use search, filter, and sort from one engine
17
- - [Search only](#search-only) – use only text search
18
- - [Flat collections search](#flat-collections-search) – search simple fields like `name` or `city`
19
- - [Nested collections search](#nested-collections-search) – search inside nested arrays like `orders.status`
20
- - [Filter only](#filter-only) – use only filtering
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
25
- - [Nested collections filter](#nested-collections-filter) – filter by nested array fields
26
- - [Sort only](#sort-only) – use only sorting
27
- - [API Reference](#api-reference) – list of options and methods
28
- - [`MergeEngines<T>`](#mergeenginest-root-module) – one engine that combines everything
29
- - [`TextSearchEngine<T>`](#textsearchenginet-search-module) – engine for text search
30
- - [`FilterEngine<T>`](#filterenginet-filter-module) – engine for filtering
31
- - [`SortEngine<T>`](#sortenginet-sort-module) – engine for sorting
32
- - [Types](#types) – TypeScript types you can import
33
- - [Build](#build) – commands for build and development
34
- - [Contributing](#contributing) – contribution rules
35
- - [Security](#security) – security policy
36
- - [License](#license) – license information
37
-
38
- ## What does this package solve
39
-
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.
42
-
43
- This package helps do these operations faster than plain JavaScript methods.
44
- Usually this happens before data is shown in the UI.
45
-
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.
52
-
53
- ## Features
54
-
55
- | Capability | Strategy | Complexity |
56
- | ---------------------------- | -------------------------------------- | ---------------------------------- |
57
- | **Indexed filter** | Hash-Map index (`Map<value, T[]>`) | **O(1)** |
58
- | **Multi-value filter** | Index intersection + `Set` membership | **O(k)** indexed / **O(n)** linear |
59
- | **Nested collection filter** | Pre-built nested index + `Set` lookup | **O(k)** indexed / **O(n)** linear |
60
- | **Text search** (contains) | Trigram inverted index + verify | **O(candidates)** |
61
- | **Nested collection search** | Nested trigram index + verify | **O(candidates)** |
62
- | **Sorting** | Pre-sorted index (cached) / V8 TimSort | **O(n)** cached / **O(n log n)** |
63
-
64
- ## React demo
65
-
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.
68
-
69
- There is also a live [demo](https://trae-op.github.io/quick-start_react_mega-collection/).
70
-
71
- ## Install
72
-
73
- ```bash
74
- npm install @devisfuture/mega-collection
75
- ```
76
-
77
- _This package is framework-agnostic and works in all popular front‑end frameworks including React, Angular, Vue and so on._
78
-
79
- ## Quick Start
80
-
81
- ```ts
82
- interface User {
83
- id: number;
84
- name: string;
85
- city: string;
86
- age: number;
87
- }
88
-
89
- interface Order {
90
- id: string;
91
- status: string;
92
- }
93
-
94
- interface UserWithOrders extends User {
95
- orders: Order[];
96
- }
97
- ```
98
-
99
- ### All-in-one: `MergeEngines`
100
-
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.
103
-
104
- You can create many engine instances in one project for different collections.
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.
109
-
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.
112
-
113
- ```ts
114
- import { MergeEngines } from "@devisfuture/mega-collection";
115
- import { TextSearchEngine } from "@devisfuture/mega-collection/search";
116
- import { SortEngine } from "@devisfuture/mega-collection/sort";
117
- import { FilterEngine } from "@devisfuture/mega-collection/filter";
118
-
119
- const engine = new MergeEngines<User>({
120
- imports: [TextSearchEngine, SortEngine, FilterEngine],
121
- data: users,
122
- search: { fields: ["name", "city"], minQueryLength: 2 },
123
- filter: { fields: ["city", "age"], filterByPreviousResult: true },
124
- sort: { fields: ["age", "name", "city"] },
125
- });
126
-
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.
134
- engine
135
- .search("john")
136
- .sort([{ field: "age", direction: "asc" }])
137
- .filter([{ field: "city", values: ["Miami", "New York"] }]);
138
-
139
- // Example with nested fields, for example `orders` inside each user.
140
- const nestedEngine = new MergeEngines<UserWithOrders>({
141
- imports: [TextSearchEngine, SortEngine, FilterEngine],
142
- data: usersWithOrders,
143
- search: {
144
- fields: ["name", "city"],
145
- nestedFields: ["orders.status"],
146
- minQueryLength: 2,
147
- },
148
- filter: {
149
- fields: ["city", "age"],
150
- nestedFields: ["orders.status"],
151
- filterByPreviousResult: true,
152
- },
153
- sort: { fields: ["age", "name", "city"] },
154
- });
155
-
156
- nestedEngine.search("pending"); // finds users whose orders contain "pending"
157
- nestedEngine.filter([{ field: "orders.status", values: ["delivered"] }]);
158
-
159
- // Replace dataset later without creating a new instance.
160
- engine.data([
161
- {
162
- id: 1,
163
- name: "Tim",
164
- city: "New-York",
165
- age: 30,
166
- },
167
- ]);
168
-
169
- // Clear indexes or data for one module.
170
- engine.clearIndexes("search").clearIndexes("sort").clearIndexes("filter");
171
- engine.clearData("search").clearData("sort").clearData("filter");
172
-
173
- // Get shared original dataset.
174
- engine.getOriginData();
175
-
176
- // Remove items through the root facade.
177
- mutableMerge.filter([{ field: "id", exclude: [1, 4] }]);
178
- ```
179
-
180
- ---
181
-
182
- ### Search only
183
-
184
- Use `TextSearchEngine` when you only need text search.
185
- The examples below show search by simple fields and nested fields.
186
-
187
- #### Flat collections search
188
-
189
- ```ts
190
- import { TextSearchEngine } from "@devisfuture/mega-collection/search";
191
-
192
- // `fields` tells the engine which fields should use indexed search.
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.
195
- const engine = new TextSearchEngine<User>({
196
- data: users,
197
- fields: ["name", "city"],
198
- minQueryLength: 2, // begins searching when query length >= 2
199
- });
200
-
201
- // If the query is shorter than `minQueryLength`, the engine returns
202
- // the original dataset. Empty or blank queries do the same.
203
-
204
- engine.search("john"); // searches all indexed fields, deduplicated
205
- engine.search("name", "john"); // searches a specific field
206
-
207
- // replace dataset without re-initializing
208
- engine.data(users);
209
-
210
- // access original dataset stored in the engine
211
- engine.getOriginData();
212
-
213
- // service methods stay on the engine instance
214
- engine.clearIndexes();
215
- engine.clearData();
216
- ```
217
-
218
- #### Nested collections search
219
-
220
- ```ts
221
- import { TextSearchEngine } from "@devisfuture/mega-collection/search";
222
-
223
- // Search inside nested arrays. `nestedFields` uses dot notation.
224
- const nestedSearch = new TextSearchEngine<UserWithOrders>({
225
- data: usersWithOrders,
226
- fields: ["name", "city"],
227
- nestedFields: ["orders.status"],
228
- minQueryLength: 2,
229
- });
230
-
231
- nestedSearch.search("pending"); // finds users whose orders match
232
- nestedSearch.search("orders.status", "delivered"); // search a specific nested field
233
- ```
234
-
235
- ### Filter only
236
-
237
- Use `FilterEngine` when you only need filtering.
238
- The examples below show filtering by simple fields and nested fields.
239
-
240
- #### Flat collections filter
241
-
242
- ```ts
243
- import { FilterEngine } from "@devisfuture/mega-collection/filter";
244
-
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.
248
- const engine = new FilterEngine<User>({
249
- data: users,
250
- fields: ["city", "age"],
251
- filterByPreviousResult: true,
252
- });
253
-
254
- engine.filter([
255
- { field: "city", values: ["Miami", "New York"] },
256
- { field: "age", values: [25, 30, 35] },
257
- ]);
258
-
259
- // Replace dataset without creating a new engine.
260
- engine.data(users);
261
-
262
- // Get original stored dataset.
263
- engine.getOriginData();
264
-
265
- // Sequential mode example:
266
- // 1) First call filters by city.
267
- const byCity = engine.filter([{ field: "city", values: ["Miami"] }]);
268
- // 2) Second call works only on the previous result.
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] }]);
371
- ```
372
-
373
- #### Nested collections filter
374
-
375
- ```ts
376
- import { FilterEngine } from "@devisfuture/mega-collection/filter";
377
-
378
- // Filter inside nested arrays. `nestedFields` uses dot notation.
379
- const nestedFilter = new FilterEngine<UserWithOrders>({
380
- data: usersWithOrders,
381
- fields: ["city", "age"],
382
- nestedFields: ["orders.status"],
383
- filterByPreviousResult: true,
384
- });
385
-
386
- nestedFilter.filter([{ field: "orders.status", values: ["pending"] }]);
387
- nestedFilter.filter([
388
- { field: "orders.status", values: ["pending"] },
389
- { field: "city", values: ["New-York"] },
390
- ]);
391
- ```
392
-
393
- ### Sort only
394
-
395
- Use `SortEngine` when you only need sorting.
396
-
397
- ```ts
398
- import { SortEngine } from "@devisfuture/mega-collection/sort";
399
-
400
- // `fields` tells the engine which fields should use cached single-field
401
- // sorting. The cache is built lazily on first use. If you skip `fields`,
402
- // sorting still works.
403
- const engine = new SortEngine<User>({
404
- data: users,
405
- fields: ["age", "name", "city"],
406
- });
407
-
408
- // Single-field sort
409
- engine.sort([{ field: "age", direction: "asc" }]);
410
-
411
- // replace dataset without re-initializing
412
- engine.data(users);
413
-
414
- // access original dataset stored in the engine
415
- engine.getOriginData();
416
-
417
- // service methods stay on the engine instance
418
- engine.clearIndexes();
419
- engine.clearData();
420
-
421
- // Multi-field sort
422
- engine.sort([
423
- { field: "age", direction: "asc" },
424
- { field: "name", direction: "desc" },
425
- ]);
426
- ```
427
-
428
- ---
429
-
430
- ## API Reference
431
-
432
- ### `MergeEngines<T>` (root module)
433
-
434
- One class that combines search, filter, and sort for the same dataset.
435
-
436
- **Constructor options:**
437
-
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 |
445
-
446
- **Methods:**
447
-
448
- | Method | Description |
449
- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
450
- | `search(query)` | Search all indexed fields |
451
- | `search(field, query)` | Search a specific field |
452
- | `sort(descriptors)` | Sort using stored dataset |
453
- | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
454
- | `filter(criteria)` | Filter using stored dataset |
455
- | `filter(data, criteria)` | Filter with an explicit dataset |
456
- | `getOriginData()` | Get the shared original dataset |
457
- | `data(data)` | Replace stored dataset for all imported modules, rebuilding configured indexes and resetting filter state where applicable |
458
- | `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
459
- | `clearData(module)` | Clear stored data for one module (`"search"`, `"sort"`, `"filter"`) |
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
-
464
- ---
465
-
466
- ### `TextSearchEngine<T>` (search module)
467
-
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.
471
-
472
- | Method | Description |
473
- | ---------------------- | ---------------------------------------------------------- |
474
- | `search(query)` | Search all indexed fields (including nested), deduplicated |
475
- | `search(field, query)` | Search a specific indexed field or nested field path |
476
- | `getOriginData()` | Get the original stored dataset |
477
- | `data(data)` | Replace stored dataset and rebuild configured indexes |
478
- | `clearIndexes()` | Clear n-gram indexes (including nested) |
479
- | `clearData()` | Clear stored data |
480
-
481
- ### `FilterEngine<T>` (filter module)
482
-
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.
486
-
487
- Main constructor options:
488
-
489
- | Option | Type | Description |
490
- | ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------- |
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. |
493
- | `nestedFields` | `string[]` | Nested field paths in dot notation, for example `["orders.status"]`. |
494
-
495
- | Method | Description |
496
- | ------------------------ | -------------------------------------------------------------------------- |
497
- | `filter(criteria)` | Filter using stored dataset (supports nested field criteria) |
498
- | `filter(data, criteria)` | Filter with an explicit dataset |
499
- | `getOriginData()` | Get the original stored dataset |
500
- | `data(data)` | Replace stored dataset, rebuild configured indexes, and reset filter state |
501
- | `resetFilterState()` | Reset previous-result state for sequential filtering |
502
- | `clearIndexes()` | Free all index memory (including nested indexes) |
503
- | `clearData()` | Clear stored data |
504
-
505
- ### `SortEngine<T>` (sort module)
506
-
507
- Sort engine with prepared indexes for faster sorting in common cases.
508
- Sort methods return plain arrays.
509
-
510
- | Method | Description |
511
- | ----------------------------------- | ----------------------------------------------------- |
512
- | `sort(descriptors)` | Sort using stored dataset |
513
- | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
514
- | `getOriginData()` | Get the original stored dataset |
515
- | `data(data)` | Replace stored dataset and rebuild configured indexes |
516
- | `clearIndexes()` | Free all cached indexes |
517
- | `clearData()` | Clear stored data |
518
-
519
- ---
520
-
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.
522
-
523
- ## Types
524
-
525
- All types are exported from the root package and from each sub-module:
526
-
527
- ```ts
528
- import type {
529
- CollectionItem,
530
- IndexableKey,
531
- FilterCriterion,
532
- SortDescriptor,
533
- SortDirection,
534
- MergeEnginesOptions,
535
- } from "@devisfuture/mega-collection";
536
- ```
537
-
538
- You can also import them from individual sub-modules:
539
-
540
- ```ts
541
- import type {
542
- CollectionItem,
543
- IndexableKey,
544
- } from "@devisfuture/mega-collection/search";
545
- import type { FilterCriterion } from "@devisfuture/mega-collection/filter";
546
- import type {
547
- SortDescriptor,
548
- SortDirection,
549
- } from "@devisfuture/mega-collection/sort";
550
- ```
551
-
552
- ---
553
-
554
- ## Build
555
-
556
- ```bash
557
- npm install
558
- npm run build # Build ESM + declarations
559
- npm run typecheck # Type-check without emitting
560
- npm run dev # Watch mode
561
- ```
562
-
563
- ## Contributing
564
-
565
- See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
566
-
567
- ## Security
568
-
569
- See [SECURITY.md](SECURITY.md) for our security policy.
570
-
571
- ## License
572
-
573
- MIT — see [LICENSE](LICENSE) for details.
5
+ Imports: @devisfuture/mega-collection, /search, /filter, /sort, /merge
@@ -0,0 +1 @@
1
+ import {a}from'./chunk-Y7NSBYLS.mjs';import {a as a$2}from'./chunk-U3IU4NI6.mjs';import {a as a$1}from'./chunk-Z4QO4GOM.mjs';function c(o){return {value:o,enumerable:false,configurable:true,writable:true}}var p=class{constructor(e){this.callbacks=e;}create(e){let a=e;return Object.defineProperties(a,{search:c((t,r)=>r===void 0?this.callbacks.search(t):this.callbacks.search(t,r)),sort:c((t,r,i)=>r===void 0?this.callbacks.sort(e,t,i):this.callbacks.sort(t,r,i)),filter:c((t,r)=>r===void 0?this.callbacks.filter(e,t):this.callbacks.filter(t,r)),add:c(t=>this.callbacks.add(t)),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())}),a}};var v=o=>o===a?"search":o===a$1?"sort":o===a$2?"filter":null,w=(o,e,a$3)=>{if(o===a){let t=new a({data:e,...a$3});return {moduleName:"search",executeSearch:(r,i)=>i===void 0?t.search(r):t.search(r,i),add:(r,i=true)=>t.applyAddedItems(r,i),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:r=>t.data(r),getOriginData:()=>t.getOriginData()}}if(o===a$1){let t=new a$1({data:e,...a$3});return {moduleName:"sort",executeSort:(r,i,s)=>i===void 0?t.sort(r):t.sort(r,i,s),add:(r,i=true)=>t.applyAddedItems(r,i),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:r=>t.data(r),getOriginData:()=>t.getOriginData()}}if(o===a$2){let t=new a$2({data:e,...a$3});return {moduleName:"filter",executeFilter:(r,i)=>i===void 0?t.rawFilter(r):t.rawFilter(r,i),add:(r,i=true)=>t.applyAddedItems(r,i),clearIndexes:()=>t.clearIndexes(),clearData:()=>t.clearData(),data:r=>t.data(r),getOriginData:()=>t.getOriginData()}}return null};var b={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.`)}static unavailableEngine(e){let a=b[e];return new o(`MergeEngines: ${a} is not available.`)}static unavailableGetOriginData(){return new o("MergeEngines: getOriginData is not available.")}};var f=class{constructor(e){this.previousSearchState=null;this.previousSortState=null;this.chainBuilder=new p({search:(e,a)=>a===void 0?this.search(e):this.search(e,a),sort:(e,a,t)=>a===void 0?this.sort(e):this.sort(e,a,t),filter:(e,a)=>a===void 0?this.filter(e):this.filter(e,a),getOriginData:()=>this.getOriginData(),add:e=>this.add(e),data:e=>this.data(e),clearIndexes:e=>this.clearIndexes(e),clearData:e=>this.clearData(e)});let{imports:a,data:t,...r}=e,i=new Set(a),s=null,d=null,u=null,S={},D={},C={},E={},x={},y=null;for(let T of i){let N=v(T);if(!N)continue;let k=this.getModuleInitOptions(N,T.name,r),n=w(T,t,k);n&&(n.moduleName==="search"&&!s&&(s=n),n.moduleName==="sort"&&!d&&(d=n),n.moduleName==="filter"&&!u&&(u=n),S[n.moduleName]=()=>n.clearIndexes(),D[n.moduleName]=()=>n.clearData(),C[n.moduleName]=(m,O)=>n.add(m,O),E[n.moduleName]=()=>n.getOriginData(),x[n.moduleName]=m=>n.data(m),y??(y=()=>n.getOriginData()));}this.searchModule=s,this.sortModule=d,this.filterModule=u,this.clearIndexMethods=S,this.clearDataMethods=D,this.addMethods=C,this.getOriginDataMethods=E,this.setDataMethods=x,this.getOriginDataMethod=y;}getModuleInitOptions(e,a,t){let r={};for(let i of [e,a]){let s=t[i];this.isRecord(s)&&Object.assign(r,s);}return r}isRecord(e){return typeof e=="object"&&e!==null}clearOperationState(e){(!e||e==="search")&&(this.previousSearchState=null),(!e||e==="sort")&&(this.previousSortState=null);}createSearchCacheKey(e,a){return JSON.stringify([e,a??null])}createSortCacheKey(e,a){return JSON.stringify({descriptors:e,inPlace:a??false})}search(e,a){if(!this.searchModule)throw l.unavailableEngine("search");let t=this.searchModule.getOriginData(),r=this.createSearchCacheKey(e,a);if(this.previousSearchState?.originData===t&&this.previousSearchState.key===r)return this.withChain(this.previousSearchState.result);let i;return a===void 0?i=this.searchModule.executeSearch(e):i=this.searchModule.executeSearch(e,a),this.previousSearchState={key:r,originData:t,result:i},this.withChain(i)}sort(e,a,t){if(!this.sortModule)throw l.unavailableEngine("sort");if(a===void 0)return this.withChain(this.sortModule.executeSort(e));let r=e;if(!t){let i=this.createSortCacheKey(a,t);if(this.previousSortState?.sourceData===r&&this.previousSortState.key===i)return this.withChain(this.previousSortState.result);let s=this.sortModule.executeSort(r,a,t);return this.previousSortState={key:i,sourceData:r,result:s},this.withChain(s)}return this.withChain(this.sortModule.executeSort(r,a,t))}filter(e,a){if(!this.filterModule)throw l.unavailableEngine("filter");return a===void 0?this.withChain(this.filterModule.executeFilter(e)):this.withChain(this.filterModule.executeFilter(e,a))}withChain(e){return this.chainBuilder.create(e)}getOriginData(){if(this.getOriginDataMethod)return this.getOriginDataMethod();throw l.unavailableGetOriginData()}add(e){if(e.length===0)return this;let a=["search","sort","filter"],t=new Set;this.clearOperationState();for(let r of a){let i=this.addMethods[r],s=this.getOriginDataMethods[r];if(!i)continue;let d=s?.(),u=d===void 0||!t.has(d);i(e,u),d!==void 0&&t.add(d);}return this}clearIndexes(e){let a=this.clearIndexMethods[e];if(a)return a(),this.clearOperationState(e),this;throw l.unavailableEngine(e)}data(e){let a=["search","sort","filter"];this.clearOperationState();for(let t of a){let r=this.setDataMethods[t];r&&r(e);}return this}clearData(e){let a=this.clearDataMethods[e];if(a)return a(),this.clearOperationState(e),this;throw l.unavailableEngine(e)}};export{f as a};
@@ -0,0 +1 @@
1
+ var I=class{constructor(){this.indexes=new Map;this.itemPositions=new Map;}addItems(e){if(!(e.length===0||this.indexes.size===0))for(let t=0;t<e.length;t++)this.addItem(e[t]);}buildIndex(e,t){let n=new Map,i=new Map;for(let s=0,r=e.length;s<r;s++){let l=e[s],a=l[t];if(a==null)continue;let u=n.get(a);if(u)u.push(l),i.get(a).set(l,u.length-1);else {n.set(a,[l]);let o=new WeakMap;o.set(l,0),i.set(a,o);}}this.indexes.set(t,n),this.itemPositions.set(t,i);}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 i=new Set,s=[];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 u=l[a];i.has(u)||(i.add(u),s.push(u));}}return s}hasIndex(e){return this.indexes.has(e)}addItem(e){for(let t of this.indexes.keys())this.addItemToField(t,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 i=this.indexes.get(e),s=this.itemPositions.get(e),r=i?.get(n),l=s?.get(n),a=l?.get(t);if(!i||!s||!r||!l||a===void 0)return;let u=r.length-1,o=r[u];a!==u&&(r[a]=o,l.set(o,a)),r.pop(),l.delete(t),r.length===0&&(i.delete(n),s.delete(n));}addItemToField(e,t){let n=t[e];if(n==null)return;let i=this.indexes.get(e),s=this.itemPositions.get(e);if(!i||!s)return;let r=i.get(n),l=s.get(n);if(r&&l){r.push(t),l.set(t,r.length-1);return}i.set(n,[t]);let a=new WeakMap;a.set(t,0),s.set(n,a);}};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,i)=>i===void 0?this.callbacks.filter(e,n):this.callbacks.filter(n,i)),add:g(n=>this.callbacks.add(n)),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 m(x){let e=[];for(let t=0;t<x.length;t++){let n=x[t],i=Array.isArray(n.values),s=E(n.exclude),r=s!==null,l=i?R(n.values,s):null;!i&&!r||e.push({field:n.field,values:l?[...l]:[],exclude:s?[...s]:[],hasValues:i,hasExclude:r,includedValues:l,excludedValues:s});}return e}function C(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 i=x[n];e?.has(i)||t.add(i);}return t}var F=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);}addItems(e){if(!(e.length===0||this.indexes.size===0))for(let t=0;t<e.length;t++)this.addItem(e[t]);}removeItem(e){for(let t of this.indexes.keys())this.removeItemFromIndex(t,e);}filter(e,t,n){let i=this.resolveCriteria(t);if(e.length===0||i.length===0)return e;let s=[],r=[];for(let a=0;a<i.length;a++){let u=i[a];if(this.indexes.has(u.field)){s.push(u);continue}r.push(u);}let l=e;if(s.length>0&&(l=this.filterByIndexes(s,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:m(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:i,nestedKey:s}=n,r=new Map,l=new Map;for(let a=0,u=e.length;a<u;a++){let o=e[a],h=o[i];if(Array.isArray(h))for(let d=0;d<h.length;d++){let c=h[d][s];if(c==null)continue;let f=r.get(c);if(f){f[f.length-1]!==o&&(f.push(o),l.get(c).set(o,f.length-1));continue}r.set(c,[o]);let p=new WeakMap;p.set(o,0),l.set(c,p);}}this.indexes.set(t,r),this.itemPositions.set(t,l);}removeItemFromIndex(e,t){let n=this.fieldDescriptors.get(e),i=this.indexes.get(e),s=this.itemPositions.get(e);if(!n||!i||!s)return;let{collectionKey:r,nestedKey:l}=n,a=t[r];if(!Array.isArray(a)||a.length===0)return;let u=new Set;for(let o=0;o<a.length;o++){let h=a[o][l];h!=null&&u.add(h);}for(let o of u){let h=i.get(o),d=s.get(o),c=d?.get(t);if(!h||!d||c===void 0)continue;let f=h.length-1,p=h[f];c!==f&&(h[c]=p,d.set(p,c)),h.pop(),d.delete(t),h.length===0&&(i.delete(o),s.delete(o));}}addItem(e){for(let t of this.indexes.keys())this.addItemToIndex(t,e);}addItemToIndex(e,t){let n=this.fieldDescriptors.get(e),i=this.indexes.get(e),s=this.itemPositions.get(e);if(!n||!i||!s)return;let{collectionKey:r,nestedKey:l}=n,a=t[r];if(!Array.isArray(a)||a.length===0)return;let u=new Set;for(let o=0;o<a.length;o++){let h=a[o][l];h!=null&&u.add(h);}for(let o of u){let h=i.get(o),d=s.get(o);if(h&&d){h.push(t),d.set(t,h.length-1);continue}i.set(o,[t]);let c=new WeakMap;c.set(t,0),s.set(o,c);}}filterByIndexes(e,t,n){let i=e.filter(o=>o.hasValues),s=e.filter(o=>o.hasExclude),r=t===n?null:new Set(t);if(i.length===0)return this.applyIndexedExclusions(t,s);if(i.length===1){let o=this.indexes.get(i[0].field);if(!o)return [];let h=this.getItemsByValues(o,i[0].values);if(h.length===0)return [];let d=[];for(let c=0;c<h.length;c++){let f=h[c];r&&!r.has(f)||d.push(f);}return this.applyIndexedExclusions(d,s)}let l=i.map(o=>({criterion:o,size:this.estimateIndexSize(o)})).sort((o,h)=>o.size-h.size),a=r,u=[];for(let o=0;o<l.length;o++){let{criterion:h}=l[o],d=this.indexes.get(h.field);if(!d)return [];let c=this.getItemsByValues(d,h.values);if(c.length===0)return [];if(a===null)u=c;else {u=[];for(let f=0;f<c.length;f++){let p=c[f];a.has(p)&&u.push(p);}}if(u.length===0)return [];a=new Set(u);}return this.applyIndexedExclusions(u,s)}getItemsByValues(e,t){if(t.length===1)return e.get(t[0])??[];let n=new Set,i=[];for(let s=0;s<t.length;s++){let r=e.get(t[s]);if(r)for(let l=0;l<r.length;l++){let a=r[l];n.has(a)||(n.add(a),i.push(a));}}return i}estimateIndexSize(e){let t=this.indexes.get(e.field);return t?e.values.reduce((n,i)=>{let s=t.get(i);return s?n+s.length:n},0):1/0}filterLinearly(e,t){let n=this.fieldDescriptors.get(t.field);if(!n)return e;let{collectionKey:i,nestedKey:s}=n,r=[];for(let l=0;l<e.length;l++){let a=e[l],u=a[i];if(!Array.isArray(u))continue;let o=!t.hasValues,h=false;for(let d=0;d<u.length;d++){let c=u[d][s];if(t.hasExclude&&t.excludedValues.has(c)){h=true;break}t.hasValues&&t.includedValues.has(c)&&(o=true);}!h&&o&&r.push(a);}return r}applyIndexedExclusions(e,t){if(t.length===0||e.length===0)return e;let n=new Set;for(let s=0;s<t.length;s++){let r=t[s],l=this.indexes.get(r.field);if(!l)continue;let a=this.getItemsByValues(l,r.exclude);for(let u=0;u<a.length;u++)n.add(a[u]);}if(n.size===0)return e;let i=[];for(let s=0;s<e.length;s++){let r=e[s];n.has(r)||i.push(r);}return i}};var V=class{constructor(e={}){this.dataset=[];this.datasetPositions=new Map;this.hasDuplicateMutableExcludeValues=false;this.indexedFields=new Set;this.nestedCollection=new F;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(),add:e=>this.add(e),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()});if(this.indexer=new I,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 i of e.fields)this.indexedFields.add(i);(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}add(e){return this.applyAddedItems(e,true)}applyAddedItems(e,t){if(e.length===0)return this;let n=t?this.dataset.length:this.dataset.length-e.length;return t&&this.dataset.push(...e),this.updateMutableExcludeStateForAddedItems(e,n),this.resetFilterState(),this.indexer.addItems(e),this.nestedCollection.addItems(e),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,i,s,r;if(n){if(!this.dataset.length)throw v.missingDatasetForFilter();s=m(e);let d=this.applyMutableExclude(s);if(d!==void 0)return d;if(this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let c=this.createCriteriaCacheKey(s),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,s),p;let T=this.hasCriteriaBacktrack(this.previousCriteria,s)||this.previousResult.length===0&&!this.canApplySequentiallyToEmptyResult(this.previousCriteria,s);i=T?this.dataset:this.previousResult,r=T?s:this.createSequentialExecutionCriteria(this.previousCriteria,s);}else i=this.dataset,r=s;}else if(s=m(t),i=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===i){let d=this.createCriteriaCacheKey(s),c=this.createCriteriaCacheKey(this.previousCriteria),f=this.previousResultsByCriteria.get(d);if(d===c)return this.previousResult;if(f!==void 0)return this.storePreviousResult(f,false,e,s),f;let p=this.hasCriteriaBacktrack(this.previousCriteria,s)||this.previousResult.length===0&&!this.canApplySequentiallyToEmptyResult(this.previousCriteria,s);i=p?e:this.previousResult,r=p?s:this.createSequentialExecutionCriteria(this.previousCriteria,s);}else r=s;if(s.length===0)return this.filterByPreviousResult&&this.resetFilterState(),n?this.dataset:e;for(let d=0;d<r.length;d++)if(b(r[d]))return this.createEmptyResult(n,e,s);let l=[],a=[];for(let d=0;d<r.length;d++){let c=r[d];this.nestedCollection.hasField(c.field)?l.push(c):a.push(c);}if(l.length>0&&(i=this.nestedCollection.filter(i,l,this.dataset),i.length===0))return this.createEmptyResult(n,e,s);if(a.length===0)return this.storePreviousResult(i,n,e,s),i;let{indexedCriteria:u,linearCriteria:o}=a.reduce((d,c)=>(this.indexer.hasIndex(c.field)?d.indexedCriteria.push(c):d.linearCriteria.push(c),d),{indexedCriteria:[],linearCriteria:[]}),h;if(u.length>0&&o.length===0)return h=this.filterViaIndex(u,i),this.storePreviousResult(h,n,e,s),h;if(u.length>0&&o.length>0){let d=this.filterViaIndex(u,i);return h=this.linearFilter(d,o),this.storePreviousResult(h,n,e,s),h}return h=this.linearFilter(i,a),this.storePreviousResult(h,n,e,s),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));}}updateMutableExcludeStateForAddedItems(e,t){if(this.mutableExcludeField!==null)for(let n=0;n<e.length;n++){let i=e[n][this.mutableExcludeField];i!=null&&(this.datasetPositions.has(i)&&(this.hasDuplicateMutableExcludeValues=true),this.datasetPositions.set(i,t+n));}}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,i=this.dataset[t],s=this.dataset[n];if(this.indexer.removeItem(i),this.nestedCollection.removeItem(i),t!==n&&(this.dataset[t]=s,this.mutableExcludeField!==null)){let r=s[this.mutableExcludeField];r!=null&&this.datasetPositions.set(r,t);}this.dataset.pop(),this.datasetPositions.delete(e);}linearFilter(e,t){let n=[];for(let i=0;i<e.length;i++){let s=e[i],r=true;for(let l=0;l<t.length;l++){let a=t[l];if(!C(a,s[a.field])){r=false;break}}r&&n.push(s);}return n}filterViaIndex(e,t){let i=t!==this.dataset?new Set(t):null,s=e.filter(d=>d.hasValues),r=e.filter(d=>d.hasExclude);if(s.length===0)return this.applyIndexedExclusions(t,r);if(s.length===1){let d=this.indexer.getByValues(s[0].field,s[0].values),c=[];for(let f=0;f<d.length;f++){let p=d[f];i&&!i.has(p)||C(s[0],p[s[0].field])&&c.push(p);}return this.applyIndexedExclusions(c,r)}let l=s.map(d=>({criterion:d,size:this.estimateIndexSize(d)})).sort((d,c)=>d.size-c.size),{field:a,values:u}=l[0].criterion,o=this.indexer.getByValues(a,u);if(o.length===0)return [];let h=[];for(let d=0;d<o.length;d++){let c=o[d],f=true;if(!(i&&!i.has(c))){for(let p=0;p<l.length;p++){let T=l[p].criterion;if(!C(T,c[T.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,i)=>{let s=t.get(i);return s?n+s.length:n},0):1/0}applyIndexedExclusions(e,t){if(t.length===0||e.length===0)return e.slice();let n=new Set;for(let s=0;s<t.length;s++){let r=t[s],l=this.indexer.getIndexMap(r.field);if(l)for(let a=0;a<r.exclude.length;a++){let u=l.get(r.exclude[a]);if(u)for(let o=0;o<u.length;o++)n.add(u[o]);}}if(n.size===0)return e.slice();let i=[];for(let s=0;s<e.length;s++){let r=e[s];n.has(r)||i.push(r);}return i}createEmptyResult(e,t,n){let i=[];return this.storePreviousResult(i,e,t,n),i}storePreviousResult(e,t,n,i){this.filterByPreviousResult&&(this.previousResult=e,this.previousCriteria=i,this.previousBaseData=t?this.dataset:n,this.previousResultsByCriteria.set(this.createCriteriaCacheKey(i),e));}createCriteriaCacheKey(e){let t=this.createCriteriaStateMap(e);return JSON.stringify([...t.entries()].sort(([n],[i])=>n.localeCompare(i)).map(([n,i])=>({field:n,hasValues:i.hasValues,hasExclude:i.hasExclude,values:i.values.map(s=>JSON.stringify(s)).sort(),exclude:i.exclude.map(s=>JSON.stringify(s)).sort()})))}createSequentialExecutionCriteria(e,t){let n=new Map;for(let i=0;i<e.length;i++){let s=e[i];n.set(s.field,s);}return t.map(i=>{let s=n.get(i.field);if(!s||!s.hasValues||!i.hasValues||s.hasExclude||i.hasExclude||i.includedValues.size<=s.includedValues.size)return i;for(let l of s.includedValues)if(!i.includedValues.has(l))return i;let r=[];for(let l of i.includedValues)s.includedValues.has(l)||r.push(l);return r.length===0?i:{...i,values:r,includedValues:new Set(r)}})}hasCriteriaBacktrack(e,t){let n=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(let[s,r]of n){let l=i.get(s);if(!l||this.isCriterionBacktracked(r,l))return true}return false}canApplySequentiallyToEmptyResult(e,t){let n=this.createCriteriaStateMap(e),i=this.createCriteriaStateMap(t);for(let[s,r]of i){let l=n.get(s);if(l){if(l.hasValues!==r.hasValues&&(l.hasValues||!r.hasValues))return false;if(l.hasValues&&r.hasValues){let a=l.includedValues,u=r.includedValues;if(!this.areSetsEqual(a,u)&&!this.isSubset(a,u))return false}if(l.hasExclude!==r.hasExclude&&(l.hasExclude||!r.hasExclude))return false;if(l.hasExclude&&r.hasExclude){let a=l.excludedValues,u=r.excludedValues;if(!this.areSetsEqual(a,u)&&!this.isSubset(a,u))return false}}}return true}createCriteriaStateMap(e){let t=new Map;for(let n=0;n<e.length;n++){let i=e[n],s=t.get(i.field);if(!s){t.set(i.field,{...i,values:i.values.slice(),exclude:i.exclude.slice(),includedValues:i.includedValues?new Set(i.includedValues):null,excludedValues:i.excludedValues?new Set(i.excludedValues):null});continue}if(i.hasValues)if(!s.hasValues)s.hasValues=true,s.includedValues=new Set(i.includedValues);else for(let r of s.includedValues)i.includedValues.has(r)||s.includedValues.delete(r);if(i.hasExclude)if(!s.hasExclude)s.hasExclude=true,s.excludedValues=new Set(i.excludedValues);else for(let r of i.excludedValues)s.excludedValues.add(r);if(s.hasValues&&s.hasExclude)for(let r of s.excludedValues)s.includedValues.delete(r);s.values=s.includedValues?[...s.includedValues]:[],s.exclude=s.excludedValues?[...s.excludedValues]:[];}return t}isCriterionBacktracked(e,t){if(e.hasValues&&!t.hasValues)return true;if(e.hasValues&&t.hasValues){let n=e.includedValues,i=t.includedValues;if(!this.areSetsEqual(n,i))return this.isSubset(i,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,i=t.excludedValues;if(!this.areSetsEqual(n,i))return this.isSubset(i,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,3 @@
1
+ var I=class g extends Error{constructor(e){super(e),this.name="TextSearchEngineError";}static missingDatasetForBuildIndex(){return new g("TextSearchEngine: no dataset in memory.")}};function L(g){let e=g.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 w(g,e){let t=g.get(e);if(t)return t;let s=new Set;return g.set(e,s),s}function x(g){let e=L(g);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 r=Math.round(i*s/n);t.add(e[r]);}return t}function p(g,e,t){for(let s=0,n=e.length;s<n;s++){let i=n-s,r=Math.min(3,i);for(let o=1;o<=r;o++){let a=e.substring(s,s+o);w(g,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);}addItems(e,t){if(!(e.length===0||this.ngramIndexes.size===0))for(let s of this.ngramIndexes.keys())this.addItemsToField(s,e,t);}searchAllIndexedFields(e,t,s){let n=new Set,i=[];for(let r of this.registeredFields)for(let o of this.searchIndexedField(e,r,t,s))n.has(o)||(n.add(o),i.push(o));return i}searchIndexedField(e,t,s,n){let i=this.ngramIndexes.get(t);if(!i)return [];let r=[];for(let d of n){let c=i.get(d);if(!c)return [];r.push(c);}r.sort((d,c)=>d.size-c.size);let o=r[0],a=r.length,l=[],h=this.normalizedFieldValues.get(t);for(let d of o){let c=true;for(let m=1;m<a;m++)if(!r[m].has(d)){c=false;break}if(!c)continue;let u=e[d];!u||!h?.[d]?.includes(s)||l.push(u);}return l}searchFieldLinear(e,t,s){let n=this.fieldDescriptors.get(t);if(!n)return [];let{collectionKey:i,nestedKey:r}=n,o=[];for(let a=0;a<e.length;a++){let l=e[a],h=l[i];if(!Array.isArray(h))continue;let d=false;for(let c=0;c<h.length;c++){let u=h[c][r];if(typeof u=="string"&&u.toLowerCase().includes(s)){d=true;break}}d&&o.push(l);}return o}matchesAnyField(e,t){for(let s of this.registeredFields){let n=this.fieldDescriptors.get(s);if(!n)continue;let{collectionKey:i,nestedKey:r}=n,o=e[i];if(Array.isArray(o))for(let a=0;a<o.length;a++){let l=o[a][r];if(typeof l=="string"&&l.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,r=new Map,o=new Array(e.length);for(let a=0,l=e.length;a<l;a++){let d=e[a][n];if(!Array.isArray(d))continue;let c=[];for(let u=0;u<d.length;u++){let f=d[u][i];if(typeof f!="string")continue;let m=f.toLowerCase();c.push(m),p(r,m,a);}c.length!==0&&(o[a]=c.join(`
2
+ `));}this.ngramIndexes.set(t,r),this.normalizedFieldValues.set(t,o);}addItemsToField(e,t,s){let n=this.fieldDescriptors.get(e),i=this.ngramIndexes.get(e);if(!n||!i)return;let r=this.normalizedFieldValues.get(e)??[],{collectionKey:o,nestedKey:a}=n;for(let l=0;l<t.length;l++){let d=t[l][o];if(!Array.isArray(d))continue;let c=[],u=s+l;for(let f=0;f<d.length;f++){let m=d[f][a];if(typeof m!="string")continue;let F=m.toLowerCase();c.push(F),p(i,F,u);}c.length!==0&&(r[u]=c.join(`
3
+ `));}this.normalizedFieldValues.set(e,r);}};var T=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 I.missingDatasetForBuildIndex();s=this.dataset,n=e;}this.dataset=s;let i=new Map,r=new Array(s.length);for(let o=0,a=s.length;o<a;o++){let l=s[o][n];if(typeof l!="string")continue;let h=l.toLowerCase();r[o]=h,p(i,h,o);}return this.ngramIndexes.set(n,i),this.normalizedFieldValues.set(n,r),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=x(t);if(!s.size)return [];let n=new Set,i=[];for(let r of this.ngramIndexes.keys())for(let o of this.searchFieldWithPreparedQuery(r,t,s))n.has(o)||(n.add(o),i.push(o));for(let r of this.nestedCollection.searchAllIndexedFields(this.dataset,t,s))n.has(r)||(n.add(r),i.push(r));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=x(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=x(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 h of s){let d=n.get(h);if(!d)return [];i.push(d);}i.sort((h,d)=>h.size-d.size);let r=i[0],o=i.length,a=[],l=this.normalizedFieldValues.get(e);for(let h of r){let d=true;for(let f=1;f<o;f++)if(!i[f].has(h)){d=false;break}if(!d)continue;let c=this.dataset[h];if(!c)continue;l?.[h]?.includes(t)&&a.push(c);}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 r in n){let o=n[r];if(typeof o=="string"&&o.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}add(e){return this.applyAddedItems(e,true)}applyAddedItems(e,t){if(e.length===0)return this;let s=t?this.dataset.length:this.dataset.length-e.length;t&&this.dataset.push(...e);for(let n of this.indexedFields)this.addItemsToField(n,e,s);return this.nestedCollection.addItems(e,s),this}clearData(){return this.dataset=[],this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}addItemsToField(e,t,s){let n=this.ngramIndexes.get(e);if(!n)return;let i=this.normalizedFieldValues.get(e)??[];for(let r=0;r<t.length;r++){let o=t[r][e];if(typeof o!="string")continue;let a=o.toLowerCase(),l=s+r;i[l]=a,p(n,a,l);}this.normalizedFieldValues.set(e,i);}};export{T as a};
@@ -0,0 +1 @@
1
+ var h=class u extends Error{constructor(r){super(r),this.name="SortEngineError";}static missingDatasetForBuildIndex(){return new u("SortEngine: no dataset in memory.")}static missingDatasetForSort(){return new u("SortEngine: no dataset in memory.")}};var g=class{constructor(r={}){this.cache=new Map;this.dataset=[];this.indexedFields=new Set;this.dirtyIndexedFields=new Set;if(r.data&&(this.dataset=r.data,r.fields?.length)){for(let n of r.fields)this.indexedFields.add(n);this.rebuildConfiguredIndexes();}}rebuildConfiguredIndexes(){this.cache.clear();for(let r of this.indexedFields)this.buildIndex(this.dataset,r);}buildIndex(r,n){let s,e;if(Array.isArray(r))s=r,e=n;else {if(!this.dataset.length)throw h.missingDatasetForBuildIndex();s=this.dataset,e=r;}this.dataset=s;let t=s.length,i=new Uint32Array(t),a=new Array(t);for(let d=0;d<t;d++)i[d]=d,a[d]=s[d][e];if(typeof a[0]=="number"){let d=new Float64Array(t);for(let l=0;l<t;l++)d[l]=a[l];i.sort((l,c)=>d[l]-d[c]);}else i.sort((d,l)=>{let c=a[d],f=a[l];return c<f?-1:c>f?1:0});return this.cache.set(e,{indexes:i,dataRef:s,itemCount:t}),this.dirtyIndexedFields.delete(e),this}clearIndexes(){return this.cache.clear(),this.dirtyIndexedFields.clear(),this}clearData(){return this.dataset=[],this.cache.clear(),this.dirtyIndexedFields.clear(),this}data(r){return this.dataset=r,this.dirtyIndexedFields.clear(),this.rebuildConfiguredIndexes(),this}add(r){return this.applyAddedItems(r,true)}applyAddedItems(r,n){if(r.length===0)return this;let s=n?this.dataset.length:this.dataset.length-r.length;n&&this.dataset.push(...r);for(let e of this.indexedFields){let t=this.cache.get(e);if(t){if(this.dirtyIndexedFields.has(e)||t.dataRef!==this.dataset||t.itemCount!==s){this.dirtyIndexedFields.add(e);continue}this.updateCachedIndexForAddedItems(e,s,r.length);}}return this}getOriginData(){return this.dataset}sort(r,n,s=false){let e,t,i=n===void 0;if(n===void 0){if(!this.dataset.length)throw h.missingDatasetForSort();e=this.dataset,t=r;}else e=r,t=n;if(t.length===0||e.length===0)return e;if(t.length===1){let{field:d,direction:l}=t[0];i&&this.dirtyIndexedFields.has(d)&&this.cache.has(d)&&this.buildIndex(d);let c=this.cache.get(d);if(i&&c?.dataRef===e&&c.itemCount===e.length)return this.reconstructFromIndex(e,c.indexes,l)}let a=s?e:e.slice();if(t.length===1&&e.length>0&&typeof e[0][t[0].field]=="number")return this.radixSortNumeric(a,t[0].field,t[0].direction);let o=this.buildComparator(t);return a.sort(o),a}reconstructFromIndex(r,n,s){let e=r.length,t=new Array(e);if(s==="asc")for(let i=0;i<e;i++)t[i]=r[n[i]];else for(let i=0;i<e;i++)t[i]=r[n[e-1-i]];return t}updateCachedIndexForAddedItems(r,n,s){let e=this.cache.get(r);if(!e)return;let t=this.buildSortedIndexesForRange(r,n,s);this.cache.set(r,{indexes:this.mergeSortedIndexes(r,e.indexes,t),dataRef:this.dataset,itemCount:n+s}),this.dirtyIndexedFields.delete(r);}buildSortedIndexesForRange(r,n,s){let e=new Uint32Array(s);for(let t=0;t<s;t++)e[t]=n+t;return e.sort((t,i)=>this.compareIndexesByField(r,t,i)),e}mergeSortedIndexes(r,n,s){let e=new Uint32Array(n.length+s.length),t=0,i=0,a=0;for(;t<n.length&&i<s.length;){if(this.compareIndexesByField(r,n[t],s[i])<=0){e[a++]=n[t++];continue}e[a++]=s[i++];}for(;t<n.length;)e[a++]=n[t++];for(;i<s.length;)e[a++]=s[i++];return e}compareIndexesByField(r,n,s){let e=this.dataset[n]?.[r],t=this.dataset[s]?.[r];if(typeof e=="number"&&typeof t=="number"){let i=e-t;if(i!==0)return i}else {if(e<t)return -1;if(e>t)return 1}return n-s}buildComparator(r){let n=r.map(({field:t})=>t),s=r.map(({direction:t})=>t==="asc"?1:-1),e=n.length;return (t,i)=>{for(let a=0;a<e;a++){let o=t[n[a]],d=i[n[a]];if(o<d)return -s[a];if(o>d)return s[a]}return 0}}radixSortNumeric(r,n,s){let e=r.length,t=new Float64Array(e);for(let o=0;o<e;o++)t[o]=r[o][n];let i=new Uint32Array(e);for(let o=0;o<e;o++)i[o]=o;i.sort((o,d)=>t[o]-t[d]);let a=new Array(e);if(s==="asc")for(let o=0;o<e;o++)a[o]=r[i[o]];else for(let o=0;o<e;o++)a[e-1-o]=r[i[o]];return a}};export{g as a};
@@ -5,6 +5,7 @@ interface FilterEngineChain<T extends CollectionItem> {
5
5
  filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
6
6
  filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
7
7
  getOriginData(): T[];
8
+ add(items: T[]): FilterEngine<T>;
8
9
  data(data: T[]): FilterEngine<T>;
9
10
  clearIndexes(): FilterEngine<T>;
10
11
  clearData(): FilterEngine<T>;
@@ -50,6 +51,8 @@ declare class FilterEngine<T extends CollectionItem> {
50
51
  resetFilterState(): this;
51
52
  clearData(): this;
52
53
  data(data: T[]): this;
54
+ add(items: T[]): this;
55
+ private applyAddedItems;
53
56
  getOriginData(): T[];
54
57
  /**
55
58
  * Filters the data based on the given criteria.
@@ -60,6 +63,7 @@ declare class FilterEngine<T extends CollectionItem> {
60
63
  rawFilter(data: T[], criteria: FilterCriterion<T>[]): T[];
61
64
  private withChain;
62
65
  private rebuildMutableExcludeState;
66
+ private updateMutableExcludeStateForAddedItems;
63
67
  private applyMutableExclude;
64
68
  private removeStoredItem;
65
69
  /**
@@ -1 +1 @@
1
- export{a as FilterEngine}from'../chunk-LSQXPQRE.mjs';
1
+ export{a as FilterEngine}from'../chunk-U3IU4NI6.mjs';
package/dist/index.mjs CHANGED
@@ -1 +1 @@
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
+ export{a as MergeEngines}from'./chunk-5FVJLC7Y.mjs';export{a as TextSearchEngine}from'./chunk-Y7NSBYLS.mjs';export{a as FilterEngine}from'./chunk-U3IU4NI6.mjs';export{a as SortEngine}from'./chunk-Z4QO4GOM.mjs';
@@ -13,6 +13,7 @@ interface MergeEnginesChain<T extends CollectionItem> {
13
13
  filter(criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
14
14
  filter(data: T[], criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
15
15
  getOriginData(): T[];
16
+ add(items: T[]): MergeEngines<T>;
16
17
  data(data: T[]): MergeEngines<T>;
17
18
  clearIndexes(module: MergeModuleName): T[] & MergeEnginesChain<T>;
18
19
  clearData(module: MergeModuleName): T[] & MergeEnginesChain<T>;
@@ -45,6 +46,8 @@ declare class MergeEngines<T extends CollectionItem> {
45
46
  private readonly filterModule;
46
47
  private readonly clearIndexMethods;
47
48
  private readonly clearDataMethods;
49
+ private readonly addMethods;
50
+ private readonly getOriginDataMethods;
48
51
  private readonly setDataMethods;
49
52
  private readonly getOriginDataMethod;
50
53
  private previousSearchState;
@@ -71,6 +74,7 @@ declare class MergeEngines<T extends CollectionItem> {
71
74
  filter(data: T[], criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
72
75
  private withChain;
73
76
  getOriginData(): T[];
77
+ add(items: T[]): this;
74
78
  clearIndexes(module: MergeModuleName): this;
75
79
  data(data: T[]): this;
76
80
  clearData(module: MergeModuleName): this;
@@ -1 +1 @@
1
- export{a as MergeEngines}from'../chunk-NHFG4LIO.mjs';import'../chunk-XCB43Y63.mjs';import'../chunk-LSQXPQRE.mjs';import'../chunk-ZJ6RQRJN.mjs';
1
+ export{a as MergeEngines}from'../chunk-5FVJLC7Y.mjs';import'../chunk-Y7NSBYLS.mjs';import'../chunk-U3IU4NI6.mjs';import'../chunk-Z4QO4GOM.mjs';
@@ -49,7 +49,10 @@ declare class TextSearchEngine<T extends CollectionItem> {
49
49
  clearIndexes(): this;
50
50
  getOriginData(): T[];
51
51
  data(data: T[]): this;
52
+ add(items: T[]): this;
53
+ private applyAddedItems;
52
54
  clearData(): this;
55
+ private addItemsToField;
53
56
  }
54
57
 
55
58
  export { CollectionItem, TextSearchEngine, TextSearchEngineOptions };
@@ -1 +1 @@
1
- export{a as TextSearchEngine}from'../chunk-XCB43Y63.mjs';
1
+ export{a as TextSearchEngine}from'../chunk-Y7NSBYLS.mjs';
@@ -11,6 +11,7 @@ declare class SortEngine<T extends CollectionItem> {
11
11
  private cache;
12
12
  private dataset;
13
13
  private readonly indexedFields;
14
+ private readonly dirtyIndexedFields;
14
15
  /**
15
16
  * Creates a new SortEngine with optional data and fields to index.
16
17
  */
@@ -26,6 +27,8 @@ declare class SortEngine<T extends CollectionItem> {
26
27
  clearIndexes(): this;
27
28
  clearData(): this;
28
29
  data(data: T[]): this;
30
+ add(items: T[]): this;
31
+ private applyAddedItems;
29
32
  getOriginData(): T[];
30
33
  /**
31
34
  * Sorts the data based on the given descriptors.
@@ -36,6 +39,10 @@ declare class SortEngine<T extends CollectionItem> {
36
39
  * Reconstructs the sorted array from the cached index.
37
40
  */
38
41
  private reconstructFromIndex;
42
+ private updateCachedIndexForAddedItems;
43
+ private buildSortedIndexesForRange;
44
+ private mergeSortedIndexes;
45
+ private compareIndexesByField;
39
46
  /**
40
47
  * Builds a comparator function for sorting.
41
48
  */
@@ -1 +1 @@
1
- export{a as SortEngine}from'../chunk-ZJ6RQRJN.mjs';
1
+ export{a as SortEngine}from'../chunk-Z4QO4GOM.mjs';
package/package.json CHANGED
@@ -1,99 +1 @@
1
- {
2
- "name": "@devisfuture/mega-collection",
3
- "version": "2.2.0",
4
- "description": "High-performance search, filter & sort engine for 100K+ item collections in JavaScript/TypeScript",
5
- "exports": {
6
- ".": {
7
- "types": "./dist/index.d.mts",
8
- "default": "./dist/index.mjs"
9
- },
10
- "./search": {
11
- "types": "./dist/search/index.d.mts",
12
- "default": "./dist/search/index.mjs"
13
- },
14
- "./filter": {
15
- "types": "./dist/filter/index.d.mts",
16
- "default": "./dist/filter/index.mjs"
17
- },
18
- "./sort": {
19
- "types": "./dist/sort/index.d.mts",
20
- "default": "./dist/sort/index.mjs"
21
- },
22
- "./merge": {
23
- "types": "./dist/merge/index.d.mts",
24
- "default": "./dist/merge/index.mjs"
25
- },
26
- "./package.json": "./package.json"
27
- },
28
- "typesVersions": {
29
- "*": {
30
- "search": [
31
- "./dist/search/index.d.mts"
32
- ],
33
- "filter": [
34
- "./dist/filter/index.d.mts"
35
- ],
36
- "sort": [
37
- "./dist/sort/index.d.mts"
38
- ],
39
- "merge": [
40
- "./dist/merge/index.d.mts"
41
- ]
42
- }
43
- },
44
- "files": [
45
- "dist"
46
- ],
47
- "sideEffects": false,
48
- "scripts": {
49
- "build": "tsup",
50
- "build:watch": "tsup --watch",
51
- "dev": "tsup --watch",
52
- "test": "vitest run",
53
- "test:watch": "vitest",
54
- "test:coverage": "vitest run --coverage",
55
- "test:ci": "vitest run --coverage --reporter=verbose --reporter=json",
56
- "clean": "rm -rf dist",
57
- "prepublishOnly": "npm run build",
58
- "typecheck": "tsc --noEmit"
59
- },
60
- "keywords": [
61
- "javascript",
62
- "search",
63
- "filter",
64
- "sort",
65
- "collection",
66
- "performance",
67
- "trigram",
68
- "inverted-index",
69
- "hashmap",
70
- "large-dataset",
71
- "big-data",
72
- "typescript",
73
- "zero-dependencies",
74
- "tree-shakeable",
75
- "esm",
76
- "indexer",
77
- "50k",
78
- "100k",
79
- "text-search",
80
- "multi-filter",
81
- "sort-engine",
82
- "merge-engines",
83
- "o1-lookup"
84
- ],
85
- "publishConfig": {
86
- "access": "public"
87
- },
88
- "repository": {
89
- "type": "git",
90
- "url": "git+https://github.com/trae-op/mega-collection.git"
91
- },
92
- "devDependencies": {
93
- "@vitest/coverage-v8": "^2.1.9",
94
- "tsup": "^8.0.0",
95
- "typescript": "^5.3.0",
96
- "vitest": "^2.1.8"
97
- },
98
- "license": "MIT"
99
- }
1
+ {"name":"@devisfuture/mega-collection","version":"2.3.1","license":"MIT","sideEffects":false,"types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./search":{"types":"./dist/search/index.d.mts","default":"./dist/search/index.mjs"},"./filter":{"types":"./dist/filter/index.d.mts","default":"./dist/filter/index.mjs"},"./sort":{"types":"./dist/sort/index.d.mts","default":"./dist/sort/index.mjs"},"./merge":{"types":"./dist/merge/index.d.mts","default":"./dist/merge/index.mjs"},"./package.json":"./package.json"},"typesVersions":{"*":{"search":["./dist/search/index.d.mts"],"filter":["./dist/filter/index.d.mts"],"sort":["./dist/sort/index.d.mts"],"merge":["./dist/merge/index.d.mts"]}},"repository":{"type":"git","url":"https://github.com/trae-op/mega-collection"}}
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 devisfuture
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1 +0,0 @@
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};
@@ -1 +0,0 @@
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};
@@ -1,2 +0,0 @@
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};
@@ -1 +0,0 @@
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};