@devisfuture/mega-collection 1.1.14 → 1.2.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
@@ -106,14 +106,24 @@ const engine = new MergeEngines<User>({
106
106
  });
107
107
 
108
108
  // dataset is passed once at init — no need to repeat it in every call
109
- engine.search("john");
110
- engine.sort([{ field: "age", direction: "asc" }]);
111
- engine.filter([{ field: "city", values: ["Miami", "New York"] }]);
109
+ engine
110
+ .search("john")
111
+ .sort([{ field: "age", direction: "asc" }])
112
+ .filter([{ field: "city", values: ["Miami", "New York"] }]);
113
+
114
+ // update dataset later without creating a new instance
115
+ engine.data([
116
+ {
117
+ id: 1,
118
+ name: "Tim",
119
+ city: "New-York",
120
+ age: 30,
121
+ },
122
+ ]);
112
123
 
113
- // clear indexes for one module
114
- engine.clearIndexes("search");
115
- engine.clearIndexes("sort");
116
- engine.clearIndexes("filter");
124
+ // clear indexes/data for one module
125
+ engine.clearIndexes("search").clearIndexes("sort").clearIndexes("filter");
126
+ engine.clearData("search").clearData("sort").clearData("filter");
117
127
  ```
118
128
 
119
129
  ---
@@ -141,6 +151,12 @@ const engine = new TextSearchEngine<User>({
141
151
 
142
152
  engine.search("john"); // searches all indexed fields, deduplicated
143
153
  engine.search("name", "john"); // searches a specific field
154
+
155
+ // replace dataset without re-initializing
156
+ engine.data(users);
157
+
158
+ // chain support
159
+ engine.search("john").clearIndexes().clearData();
144
160
  ```
145
161
 
146
162
  ### Filter only
@@ -163,6 +179,16 @@ engine.filter([
163
179
  { field: "age", values: [25, 30, 35] },
164
180
  ]);
165
181
 
182
+ // replace dataset without re-initializing
183
+ engine.data(users);
184
+
185
+ engine
186
+ .filter([{ field: "city", values: ["Miami", "New York"] }])
187
+ .filter([{ field: "age", values: [25, 30, 35] }])
188
+ .clearIndexes()
189
+ .resetFilterState()
190
+ .clearData();
191
+
166
192
  // Sequential mode example:
167
193
  // 1) First call filters by city
168
194
  const byCity = engine.filter([{ field: "city", values: ["Miami"] }]);
@@ -188,6 +214,16 @@ const engine = new SortEngine<User>({
188
214
  // Single-field sort — O(n) via cached index
189
215
  engine.sort([{ field: "age", direction: "asc" }]);
190
216
 
217
+ // replace dataset without re-initializing
218
+ engine.data(users);
219
+
220
+ // chain support
221
+ engine
222
+ .sort([{ field: "age", direction: "asc" }])
223
+ .sort([{ field: "name", direction: "desc" }])
224
+ .clearIndexes()
225
+ .clearData();
226
+
191
227
  // Multi-field sort — O(n log n)
192
228
  engine.sort([
193
229
  { field: "age", direction: "asc" },
@@ -215,15 +251,17 @@ Unified facade that composes all three engines around a shared dataset.
215
251
 
216
252
  **Methods:**
217
253
 
218
- | Method | Description |
219
- | ----------------------------------- | --------------------------------------------------------------- |
220
- | `search(query)` | Search all indexed fields |
221
- | `search(field, query)` | Search a specific field |
222
- | `sort(descriptors)` | Sort using stored dataset |
223
- | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
224
- | `filter(criteria)` | Filter using stored dataset |
225
- | `filter(data, criteria)` | Filter with an explicit dataset |
226
- | `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
254
+ | Method | Description |
255
+ | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
256
+ | `search(query)` | Search all indexed fields |
257
+ | `search(field, query)` | Search a specific field |
258
+ | `sort(descriptors)` | Sort using stored dataset |
259
+ | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
260
+ | `filter(criteria)` | Filter using stored dataset |
261
+ | `filter(data, criteria)` | Filter with an explicit dataset |
262
+ | `data(data)` | Replace stored dataset for all imported modules, rebuilding configured indexes and resetting filter state where applicable |
263
+ | `clearIndexes(module)` | Clear indexes for one module (`"search"`, `"sort"`, `"filter"`) |
264
+ | `clearData(module)` | Clear stored data for one module (`"search"`, `"sort"`, `"filter"`) |
227
265
 
228
266
  ---
229
267
 
@@ -231,11 +269,13 @@ Unified facade that composes all three engines around a shared dataset.
231
269
 
232
270
  Trigram-based text search engine.
233
271
 
234
- | Method | Description |
235
- | ---------------------- | --------------------------------------- |
236
- | `search(query)` | Search all indexed fields, deduplicated |
237
- | `search(field, query)` | Search a specific indexed field |
238
- | `clearIndexes()` | Free memory |
272
+ | Method | Description |
273
+ | ---------------------- | ----------------------------------------------------- |
274
+ | `search(query)` | Search all indexed fields, deduplicated |
275
+ | `search(field, query)` | Search a specific indexed field |
276
+ | `data(data)` | Replace stored dataset and rebuild configured indexes |
277
+ | `clearIndexes()` | Clear n-gram indexes |
278
+ | `clearData()` | Clear stored data |
239
279
 
240
280
  ### `FilterEngine<T>` (filter module)
241
281
 
@@ -247,25 +287,31 @@ Constructor option highlights:
247
287
  | ------------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
248
288
  | `filterByPreviousResult` | `boolean` | When `true`, each `filter(criteria)` call filters from previous result. Defaults to `false` (each call starts from the original dataset). |
249
289
 
250
- | Method | Description |
251
- | ------------------------ | ---------------------------------------------------- |
252
- | `filter(criteria)` | Filter using stored dataset |
253
- | `filter(data, criteria)` | Filter with an explicit dataset |
254
- | `resetFilterState()` | Reset previous-result state for sequential filtering |
255
- | `clearIndexes()` | Free all index memory |
290
+ | Method | Description |
291
+ | ------------------------ | -------------------------------------------------------------------------- |
292
+ | `filter(criteria)` | Filter using stored dataset |
293
+ | `filter(data, criteria)` | Filter with an explicit dataset |
294
+ | `data(data)` | Replace stored dataset, rebuild configured indexes, and reset filter state |
295
+ | `resetFilterState()` | Reset previous-result state for sequential filtering |
296
+ | `clearIndexes()` | Free all index memory |
297
+ | `clearData()` | Clear stored data |
256
298
 
257
299
  ### `SortEngine<T>` (sort module)
258
300
 
259
301
  Sorting with pre-compiled comparators and cached sort indexes.
260
302
 
261
- | Method | Description |
262
- | ----------------------------------- | ----------------------------- |
263
- | `sort(descriptors)` | Sort using stored dataset |
264
- | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
265
- | `clearIndexes()` | Free all cached indexes |
303
+ | Method | Description |
304
+ | ----------------------------------- | ----------------------------------------------------- |
305
+ | `sort(descriptors)` | Sort using stored dataset |
306
+ | `sort(data, descriptors, inPlace?)` | Sort with an explicit dataset |
307
+ | `data(data)` | Replace stored dataset and rebuild configured indexes |
308
+ | `clearIndexes()` | Free all cached indexes |
309
+ | `clearData()` | Clear stored data |
266
310
 
267
311
  ---
268
312
 
313
+ **Note on `data` method:** Calling the `data` method automatically rebuilds configured indexes and resets any internal state (such as filter state in FilterEngine), so it is sufficient on its own without needing to call `clearIndexes` separately.
314
+
269
315
  ## Types
270
316
 
271
317
  All types are exported from the root package and from each sub-module:
@@ -0,0 +1 @@
1
+ var p=class{constructor(){this.indexes=new Map;}buildIndex(e,r){let n=new Map;for(let s=0,t=e.length;s<t;s++){let i=e[s],a=i[r];if(a==null)continue;let l=n.get(a);l?l.push(i):n.set(a,[i]);}this.indexes.set(r,n);}getByValue(e,r){let n=this.indexes.get(e);return n?n.get(r)??[]:[]}getByValues(e,r){let n=this.indexes.get(e);if(!n)return [];if(r.length===1)return n.get(r[0])??[];let s=new Set,t=[];for(let i=0;i<r.length;i++){let a=n.get(r[i]);if(a!==void 0)for(let l=0;l<a.length;l++){let o=a[l];s.has(o)||(s.add(o),t.push(o));}}return t}hasIndex(e){return this.indexes.has(e)}clear(){this.indexes.clear();}getIndexMap(e){return this.indexes.get(e)}};var g=class{constructor(e={}){this.dataset=[];this.indexedFields=new Set;this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;if(this.indexer=new p,this.filterByPreviousResult=e.filterByPreviousResult??false,!!e.data&&(this.dataset=e.data,e.fields?.length)){for(let r of e.fields)this.indexedFields.add(r);this.rebuildConfiguredIndexes();}}rebuildConfiguredIndexes(){this.indexer.clear();for(let e of this.indexedFields)this.buildIndex(this.dataset,e);}buildIndex(e,r){if(!Array.isArray(e)){if(!this.dataset.length)throw new Error("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");return this.indexer.buildIndex(this.dataset,e),this}return this.dataset=e,this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this.indexer.buildIndex(e,r),this}clearIndexes(){return this.indexer.clear(),this}resetFilterState(){return this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this}clearData(){return this.dataset=[],this.indexer.clear(),this.resetFilterState(),this}data(e){return this.dataset=e,this.resetFilterState(),this.rebuildConfiguredIndexes(),this}filter(e,r){let n=r===void 0,s,t,i;if(n){if(!this.dataset.length)throw new Error("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call filter(data, criteria).");if(t=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let u=this.hasCriteriaAdditions(this.previousCriteria,t),h=this.hasCriteriaRemovals(this.previousCriteria,t);if(!u&&!h)return this.withChain(this.previousResult);u&&!h?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,t)):(s=this.dataset,i=t);}else s=this.dataset,i=t;}else if(t=r,s=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===s){let u=this.hasCriteriaAdditions(this.previousCriteria,t),h=this.hasCriteriaRemovals(this.previousCriteria,t);if(!u&&!h)return this.withChain(this.previousResult);u&&!h?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,t)):i=t;}else i=t;if(t.length===0)return this.filterByPreviousResult&&(this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null),this.withChain(n?this.dataset:s);n&&!i&&(i=t);let{indexedCriteria:a,linearCriteria:l}=i.reduce((u,h)=>(this.indexer.hasIndex(h.field)?u.indexedCriteria.push(h):u.linearCriteria.push(h),u),{indexedCriteria:[],linearCriteria:[]}),o;if(a.length>0&&l.length===0)return o=this.filterViaIndex(a,s),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(t),this.previousBaseData=n?this.dataset:e),this.withChain(o);if(a.length>0&&l.length>0){let u=this.filterViaIndex(a,s);return o=this.linearFilter(u,l),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(t),this.previousBaseData=n?this.dataset:e),this.withChain(o)}return o=this.linearFilter(s,i),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(t),this.previousBaseData=n?this.dataset:e),this.withChain(o)}withChain(e){let r=e;return Object.defineProperty(r,"filter",{value:(n,s)=>s===void 0?this.filter(e,n):this.filter(n,s),enumerable:false,configurable:true,writable:true}),Object.defineProperty(r,"clearIndexes",{value:()=>this.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(r,"data",{value:n=>this.data(n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(r,"clearData",{value:()=>this.clearData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(r,"resetFilterState",{value:()=>this.resetFilterState(),enumerable:false,configurable:true,writable:true}),r}cloneCriteria(e){return e.map(({field:r,values:n})=>({field:r,values:[...n]}))}hasCriteriaAdditions(e,r){let n=new Map(e.map(({field:t,values:i})=>[t,new Set(i)])),s=new Map(r.map(({field:t,values:i})=>[t,new Set(i)]));for(let[t,i]of s){let a=n.get(t);if(!a)return true;for(let l of i)if(!a.has(l))return true}return false}hasCriteriaRemovals(e,r){let n=new Map(e.map(({field:t,values:i})=>[t,new Set(i)])),s=new Map(r.map(({field:t,values:i})=>[t,new Set(i)]));for(let[t,i]of n){let a=s.get(t);if(!a)return true;for(let l of i)if(!a.has(l))return true}return false}getAddedCriteria(e,r){let n=new Map(e.map(({field:t,values:i})=>[t,new Set(i)])),s=[];for(let{field:t,values:i}of r){let a=n.get(t);if(!a){s.push({field:t,values:[...i]});continue}let l=i.filter(o=>!a.has(o));l.length>0&&s.push({field:t,values:l});}return s}linearFilter(e,r){let n=new Map(r.map(({field:i,values:a})=>[i,new Set(a)])),s=r.map(({field:i})=>i),t=[];for(let i=0;i<e.length;i++){let a=e[i],l=true;for(let o=0;o<s.length;o++){let u=s[o];if(!n.get(u).has(a[u])){l=false;break}}l&&t.push(a);}return t}filterViaIndex(e,r){let s=r!==this.dataset?new Set(r):null;if(e.length===1){let d=this.indexer.getByValues(e[0].field,e[0].values);return s?d.filter(f=>s.has(f)):d}let t=e.map(d=>({criterion:d,size:this.estimateIndexSize(d)})).sort((d,f)=>d.size-f.size),{field:i,values:a}=t[0].criterion,l=this.indexer.getByValues(i,a);if(l.length===0)return [];let o=new Map(t.slice(1).map(({criterion:{field:d,values:f}})=>[d,new Set(f)])),u=Array.from(o.keys()),h=[];for(let d=0;d<l.length;d++){let f=l[d],c=true;for(let T=0;T<u.length;T++){let v=u[T];if(!o.get(v).has(f[v])){c=false;break}}c&&s&&!s.has(f)&&(c=false),c&&h.push(f);}return h}estimateIndexSize(e){let r=this.indexer.getIndexMap(e.field);return r?e.values.reduce((n,s)=>{let t=r.get(s);return t?n+t.length:n},0):1/0}};export{g as a};
@@ -0,0 +1 @@
1
+ var T=class{constructor(e){let{imports:t,data:n,...r}=e,s=new Set(t),a={},l={},g={},d={};for(let u of s){let M=u.prototype,c=this.getMethodNames(M);if(c.length===0)continue;let f=this.getModuleInitOptions(u.name,c,r),i=new u({data:n,...f}),o=this.getModuleName(c);o&&this.hasMethod(i,"clearIndexes")&&!l[o]&&(l[o]=i.clearIndexes.bind(i)),o&&this.hasMethod(i,"clearData")&&!g[o]&&(g[o]=i.clearData.bind(i)),o&&this.hasMethod(i,"data")&&!d[o]&&(d[o]=i.data.bind(i));for(let h of c)a[h]||this.hasMethod(i,h)&&(a[h]=i[h].bind(i));}this.engine=Object.keys(a).length>0?a:null,this.clearIndexMethods=l,this.clearDataMethods=g,this.setDataMethods=d;}getModuleName(e){return e.includes("search")?"search":e.includes("sort")?"sort":e.includes("filter")?"filter":null}getModuleInitOptions(e,t,n){let r={},s=n[e];this.isRecord(s)&&Object.assign(r,s);for(let a of t){let l=n[a];this.isRecord(l)&&Object.assign(r,l);}return r}getMethodNames(e){let t=e;return Object.getOwnPropertyNames(t).filter(n=>n==="constructor"?false:typeof t[n]=="function")}hasMethod(e,t){return typeof e=="object"&&e!==null&&typeof e[t]=="function"}isRecord(e){return typeof e=="object"&&e!==null}callEngineMethod(e,t){let n=this.engine?.[e];if(!n)throw new Error(`MergeEngines: Method "${e}" is not available. Add module with method "${e}" to the \`imports\` array.`);return n(...t)}search(e,t){if(!this.engine?.search)throw new Error("MergeEngines: TextSearchEngine is not available. Add TextSearchEngine to the `imports` array.");return t===void 0?this.withChain(this.callEngineMethod("search",[e])):this.withChain(this.callEngineMethod("search",[e,t]))}sort(e,t,n){if(!this.engine?.sort)throw new Error("MergeEngines: SortEngine is not available. Add SortEngine to the `imports` array.");return t===void 0?this.withChain(this.callEngineMethod("sort",[e])):this.withChain(this.callEngineMethod("sort",[e,t,n]))}filter(e,t){if(!this.engine?.filter)throw new Error("MergeEngines: FilterEngine is not available. Add FilterEngine to the `imports` array.");return t===void 0?this.withChain(this.callEngineMethod("filter",[e])):this.withChain(this.callEngineMethod("filter",[e,t]))}withChain(e){let t=e;return Object.defineProperty(t,"search",{value:(n,r)=>r===void 0?this.search(n):this.search(n,r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"sort",{value:(n,r,s)=>r===void 0?this.sort(e,n,s):this.sort(n,r,s),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"filter",{value:(n,r)=>r===void 0?this.filter(e,n):this.filter(n,r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:n=>(this.clearIndexes(n),this.withChain(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:n=>(this.clearData(n),this.withChain(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:n=>this.data(n),enumerable:false,configurable:true,writable:true}),t}clearIndexes(e){let t=this.clearIndexMethods[e];if(t)return t(),this;let n={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"};throw new Error(`MergeEngines: ${n[e]} is not available. Add ${n[e]} to the \`imports\` array.`)}data(e){let t=["search","sort","filter"];for(let n of t){let r=this.setDataMethods[n];r&&r(e);}return this}clearData(e){let t=this.clearDataMethods[e];if(t)return t(),this;let n={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"};throw new Error(`MergeEngines: ${n[e]} is not available. Add ${n[e]} to the \`imports\` array.`)}};export{T as a};
@@ -0,0 +1 @@
1
+ var y=3,T=12;function I(d){let e=d.toLowerCase(),n=Math.min(y,e.length),t=e.length-n+1,r=new Array(t);for(let i=0;i<t;i++)r[i]=e.substring(i,i+n);return r}function m(d){let e=I(d);if(e.length<=T)return new Set(e);let n=new Set,t=e.length-1,r=T-1;for(let i=0;i<=r;i++){let s=Math.round(i*t/r);n.add(e[s]);}return n}function b(d,e){let n=d.get(e);if(n)return n;let t=new Set;return d.set(e,t),t}var x=class{constructor(e={}){this.ngramIndexes=new Map;this.dataset=[];this.indexedFields=new Set;if(this.minQueryLength=e.minQueryLength??1,!!e.data&&(this.dataset=e.data,e.fields?.length)){for(let n of e.fields)this.indexedFields.add(n);this.rebuildConfiguredIndexes();}}rebuildConfiguredIndexes(){this.ngramIndexes.clear();for(let e of this.indexedFields)this.buildIndex(this.dataset,e);}buildIndex(e,n){let t,r;if(Array.isArray(e))t=e,r=n;else {if(!this.dataset.length)throw new Error("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");t=this.dataset,r=e;}this.dataset=t;let i=new Map;for(let s=0,c=t.length;s<c;s++){let o=t[s][r];if(typeof o!="string")continue;let h=o.toLowerCase();for(let a=0,l=h.length;a<l;a++){let g=l-a,u=Math.min(y,g);for(let f=1;f<=u;f++){let p=h.substring(a,a+f);b(i,p).add(s);}}}return this.ngramIndexes.set(r,i),this}search(e,n){return n===void 0?this.withChain(this.searchAllFields(e)):this.withChain(this.searchField(e,n))}normalizeQuery(e){return e.trim().toLowerCase()}searchAllFields(e){let n=[...this.ngramIndexes.keys()],t=this.normalizeQuery(e);if(!t)return this.dataset;if(t.length<this.minQueryLength)return this.dataset;if(!n.length)return this.searchAllFieldsLinear(t);let r=m(t);if(!r.size)return [];let i=new Set,s=[];for(let c of n)for(let o of this.searchFieldWithPreparedQuery(c,t,r))i.has(o)||(i.add(o),s.push(o));return s}searchField(e,n){let t=this.normalizeQuery(n);if(!t)return this.dataset;if(t.length<this.minQueryLength)return this.dataset;if(!this.ngramIndexes.size)return this.searchFieldLinear(e,t);let r=m(t);return r.size?this.searchFieldWithPreparedQuery(e,t,r):[]}searchFieldWithPreparedQuery(e,n,t){let r=this.ngramIndexes.get(e);if(!r)return [];let i=[];for(let h of t){let a=r.get(h);if(!a)return [];i.push(a);}i.sort((h,a)=>h.size-a.size);let s=i[0],c=i.length,o=[];for(let h of s){let a=true;for(let u=1;u<c;u++)if(!i[u].has(h)){a=false;break}if(!a)continue;let l=this.dataset[h];if(!l)continue;let g=l[e];typeof g=="string"&&g.toLowerCase().includes(n)&&o.push(l);}return o}searchAllFieldsLinear(e){if(!this.dataset.length)return [];let n=[];for(let t=0;t<this.dataset.length;t++){let r=this.dataset[t],i=false;for(let s of Object.values(r))if(typeof s=="string"&&s.toLowerCase().includes(e)){i=true;break}i&&n.push(r);}return n}searchFieldLinear(e,n){if(!this.dataset.length)return [];let t=[];for(let r=0;r<this.dataset.length;r++){let i=this.dataset[r][e];typeof i=="string"&&i.toLowerCase().includes(n)&&t.push(this.dataset[r]);}return t}withChain(e){let n=e;return Object.defineProperty(n,"search",{value:(t,r)=>r===void 0?this.search(t):this.search(t,r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(n,"clearIndexes",{value:()=>this.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(n,"data",{value:t=>this.data(t),enumerable:false,configurable:true,writable:true}),Object.defineProperty(n,"clearData",{value:()=>this.clearData(),enumerable:false,configurable:true,writable:true}),n}clearIndexes(){return this.ngramIndexes.clear(),this}data(e){return this.dataset=e,this.rebuildConfiguredIndexes(),this}clearData(){return this.dataset=[],this.ngramIndexes.clear(),this}};export{x as a};
@@ -0,0 +1 @@
1
+ var u=class{constructor(t={}){this.cache=new Map;this.dataset=[];this.indexedFields=new Set;if(t.data&&(this.dataset=t.data,t.fields?.length)){for(let s of t.fields)this.indexedFields.add(s);this.rebuildConfiguredIndexes();}}rebuildConfiguredIndexes(){this.cache.clear();for(let t of this.indexedFields)this.buildIndex(this.dataset,t);}buildIndex(t,s){let o,e;if(Array.isArray(t))o=t,e=s;else {if(!this.dataset.length)throw new Error("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");o=this.dataset,e=t;}this.dataset=o;let r=o.length,n=new Uint32Array(r);for(let a=0;a<r;a++)n[a]=a;let l=o.map(a=>a[e]);if(typeof l[0]=="number"){let a=new Float64Array(r);for(let d=0;d<r;d++)a[d]=l[d];n.sort((d,c)=>a[d]-a[c]);}else n.sort((a,d)=>{let c=l[a],h=l[d];return c<h?-1:c>h?1:0});return this.cache.set(e,{indexes:n,dataRef:o,itemCount:r,fieldSnapshot:l}),this}clearIndexes(){return this.cache.clear(),this}clearData(){return this.dataset=[],this.cache.clear(),this}data(t){return this.dataset=t,this.rebuildConfiguredIndexes(),this}sort(t,s,o=false){let e,r;if(s===void 0){if(!this.dataset.length)throw new Error("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call sort(data, descriptors).");e=this.dataset,r=t;}else e=t,r=s;if(r.length===0||e.length===0)return this.withChain(e);if(r.length===1){let{field:i,direction:a}=r[0],d=this.cache.get(i);if(d&&d.dataRef===e&&d.itemCount===e.length&&this.isFieldSnapshotValid(e,i,d.fieldSnapshot))return this.withChain(this.reconstructFromIndex(e,d.indexes,a))}let n=o?e:e.slice();if(r.length===1&&e.length>0&&typeof e[0][r[0].field]=="number")return this.withChain(this.radixSortNumeric(n,r[0].field,r[0].direction));let l=this.buildComparator(r);return n.sort(l),this.withChain(n)}withChain(t){let s=t;return Object.defineProperty(s,"sort",{value:(o,e,r=false)=>e===void 0?this.sort(t,o,r):this.sort(o,e,r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(s,"clearIndexes",{value:()=>this.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(s,"data",{value:o=>this.data(o),enumerable:false,configurable:true,writable:true}),Object.defineProperty(s,"clearData",{value:()=>this.clearData(),enumerable:false,configurable:true,writable:true}),s}reconstructFromIndex(t,s,o){let e=t.length,r=new Array(e);if(o==="asc")for(let n=0;n<e;n++)r[n]=t[s[n]];else for(let n=0;n<e;n++)r[n]=t[s[e-1-n]];return r}isFieldSnapshotValid(t,s,o){for(let e=0;e<t.length;e++)if(t[e][s]!==o[e])return false;return true}buildComparator(t){let s=t.map(({field:r})=>r),o=t.map(({direction:r})=>r==="asc"?1:-1),e=s.length;return (r,n)=>{for(let l=0;l<e;l++){let i=r[s[l]],a=n[s[l]];if(i<a)return -o[l];if(i>a)return o[l]}return 0}}radixSortNumeric(t,s,o){let e=t.length,r=new Float64Array(e);for(let i=0;i<e;i++)r[i]=t[i][s];let n=new Uint32Array(e);for(let i=0;i<e;i++)n[i]=i;n.sort((i,a)=>r[i]-r[a]);let l=new Array(e);if(o==="asc")for(let i=0;i<e;i++)l[i]=t[n[i]];else for(let i=0;i<e;i++)l[e-1-i]=t[n[i]];return l}};export{u as a};
@@ -11,10 +11,19 @@ interface FilterEngineOptions<T extends CollectionItem = CollectionItem> {
11
11
  fields?: (keyof T & string)[];
12
12
  filterByPreviousResult?: boolean;
13
13
  }
14
+ interface FilterEngineChain<T extends CollectionItem> {
15
+ filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
16
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
17
+ data(data: T[]): FilterEngine<T>;
18
+ clearIndexes(): FilterEngine<T>;
19
+ clearData(): FilterEngine<T>;
20
+ resetFilterState(): FilterEngine<T>;
21
+ }
14
22
  declare class FilterEngine<T extends CollectionItem> {
15
23
  private indexer;
16
24
  private readonly filterByPreviousResult;
17
- private data;
25
+ private dataset;
26
+ private readonly indexedFields;
18
27
  private previousResult;
19
28
  private previousCriteria;
20
29
  private previousBaseData;
@@ -22,17 +31,21 @@ declare class FilterEngine<T extends CollectionItem> {
22
31
  * Creates a new FilterEngine with optional data and fields to index.
23
32
  */
24
33
  constructor(options?: FilterEngineOptions<T>);
34
+ private rebuildConfiguredIndexes;
25
35
  /**
26
36
  * Builds an index for the given field.
27
37
  */
28
38
  private buildIndex;
29
- clearIndexes(): void;
30
- resetFilterState(): void;
39
+ clearIndexes(): this;
40
+ resetFilterState(): this;
41
+ clearData(): this;
42
+ data(data: T[]): this;
31
43
  /**
32
44
  * Filters the data based on the given criteria.
33
45
  */
34
- filter(criteria: FilterCriterion<T>[]): T[];
35
- filter(data: T[], criteria: FilterCriterion<T>[]): T[];
46
+ filter(criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
47
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & FilterEngineChain<T>;
48
+ private withChain;
36
49
  private cloneCriteria;
37
50
  /**
38
51
  * Checks if there are new criteria added.
@@ -1 +1 @@
1
- export{a as FilterEngine}from'../chunk-XFQ56UZU.mjs';
1
+ export{a as FilterEngine}from'../chunk-2HRTLOF4.mjs';
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export{a as TextSearchEngine}from'./chunk-MQLJXCPR.mjs';export{a as FilterEngine}from'./chunk-XFQ56UZU.mjs';export{a as SortEngine}from'./chunk-DBAABXBP.mjs';export{a as MergeEngines}from'./chunk-OZGQBUEM.mjs';
1
+ export{a as TextSearchEngine}from'./chunk-XWZBWMQK.mjs';export{a as FilterEngine}from'./chunk-2HRTLOF4.mjs';export{a as SortEngine}from'./chunk-Z33ISQHF.mjs';export{a as MergeEngines}from'./chunk-CVYC4YF4.mjs';
@@ -20,9 +20,22 @@ interface MergeEnginesOptions<T extends CollectionItem> {
20
20
  data: T[];
21
21
  [key: string]: unknown;
22
22
  }
23
+ interface MergeEnginesChain<T extends CollectionItem> {
24
+ search(query: string): T[] & MergeEnginesChain<T>;
25
+ search(field: keyof T & string, query: string): T[] & MergeEnginesChain<T>;
26
+ sort(descriptors: SortDescriptor<T>[]): T[] & MergeEnginesChain<T>;
27
+ sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[] & MergeEnginesChain<T>;
28
+ filter(criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
29
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
30
+ data(data: T[]): MergeEngines<T>;
31
+ clearIndexes(module: MergeModuleName): T[] & MergeEnginesChain<T>;
32
+ clearData(module: MergeModuleName): T[] & MergeEnginesChain<T>;
33
+ }
23
34
  declare class MergeEngines<T extends CollectionItem> {
24
35
  private readonly engine;
25
36
  private readonly clearIndexMethods;
37
+ private readonly clearDataMethods;
38
+ private readonly setDataMethods;
26
39
  /**
27
40
  * Creates a new MergeEngines instance with the given options.
28
41
  * Collects all modules from imports.
@@ -46,13 +59,16 @@ declare class MergeEngines<T extends CollectionItem> {
46
59
  * Calls a method on the engine.
47
60
  */
48
61
  private callEngineMethod;
49
- search(query: string): T[];
50
- search(field: keyof T & string, query: string): T[];
51
- sort(descriptors: SortDescriptor<T>[]): T[];
52
- sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[];
53
- filter(criteria: FilterCriterion<T>[]): T[];
54
- filter(data: T[], criteria: FilterCriterion<T>[]): T[];
55
- clearIndexes(module: MergeModuleName): void;
62
+ search(query: string): T[] & MergeEnginesChain<T>;
63
+ search(field: keyof T & string, query: string): T[] & MergeEnginesChain<T>;
64
+ sort(descriptors: SortDescriptor<T>[]): T[] & MergeEnginesChain<T>;
65
+ sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[] & MergeEnginesChain<T>;
66
+ filter(criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
67
+ filter(data: T[], criteria: FilterCriterion<T>[]): T[] & MergeEnginesChain<T>;
68
+ private withChain;
69
+ clearIndexes(module: MergeModuleName): this;
70
+ data(data: T[]): this;
71
+ clearData(module: MergeModuleName): this;
56
72
  }
57
73
 
58
74
  export { CollectionItem, type EngineApi, type EngineConstructor, FilterCriterion, MergeEngines, type MergeEnginesOptions, SortDescriptor };
@@ -1 +1 @@
1
- export{a as MergeEngines}from'../chunk-OZGQBUEM.mjs';
1
+ export{a as MergeEngines}from'../chunk-CVYC4YF4.mjs';
@@ -11,20 +11,29 @@ interface TextSearchEngineOptions<T extends CollectionItem = CollectionItem> {
11
11
  fields?: (keyof T & string)[];
12
12
  minQueryLength?: number;
13
13
  }
14
+ interface TextSearchEngineChain<T extends CollectionItem> {
15
+ search(query: string): T[] & TextSearchEngineChain<T>;
16
+ search(field: keyof T & string, query: string): T[] & TextSearchEngineChain<T>;
17
+ data(data: T[]): TextSearchEngine<T>;
18
+ clearIndexes(): TextSearchEngine<T>;
19
+ clearData(): TextSearchEngine<T>;
20
+ }
14
21
  declare class TextSearchEngine<T extends CollectionItem> {
15
22
  private ngramIndexes;
16
- private data;
23
+ private dataset;
24
+ private readonly indexedFields;
17
25
  private readonly minQueryLength;
18
26
  /**
19
27
  * Creates a new TextSearchEngine with optional data and fields to index.
20
28
  */
21
29
  constructor(options?: TextSearchEngineOptions<T>);
30
+ private rebuildConfiguredIndexes;
22
31
  /**
23
32
  * Builds an n-gram index for the given field.
24
33
  */
25
34
  private buildIndex;
26
- search(query: string): T[];
27
- search(field: keyof T & string, query: string): T[];
35
+ search(query: string): T[] & TextSearchEngineChain<T>;
36
+ search(field: keyof T & string, query: string): T[] & TextSearchEngineChain<T>;
28
37
  private normalizeQuery;
29
38
  /**
30
39
  * Searches all indexed fields.
@@ -46,7 +55,10 @@ declare class TextSearchEngine<T extends CollectionItem> {
46
55
  * Searches a specific field linearly without index.
47
56
  */
48
57
  private searchFieldLinear;
49
- clearIndexes(): void;
58
+ private withChain;
59
+ clearIndexes(): this;
60
+ data(data: T[]): this;
61
+ clearData(): this;
50
62
  }
51
63
 
52
64
  export { CollectionItem, TextSearchEngine, type TextSearchEngineOptions };
@@ -1 +1 @@
1
- export{a as TextSearchEngine}from'../chunk-MQLJXCPR.mjs';
1
+ export{a as TextSearchEngine}from'../chunk-XWZBWMQK.mjs';
@@ -10,13 +10,22 @@ interface SortEngineOptions<T extends CollectionItem = CollectionItem> {
10
10
  data?: T[];
11
11
  fields?: (keyof T & string)[];
12
12
  }
13
+ interface SortEngineChain<T extends CollectionItem> {
14
+ sort(descriptors: SortDescriptor<T>[]): T[] & SortEngineChain<T>;
15
+ sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[] & SortEngineChain<T>;
16
+ data(data: T[]): SortEngine<T>;
17
+ clearIndexes(): SortEngine<T>;
18
+ clearData(): SortEngine<T>;
19
+ }
13
20
  declare class SortEngine<T extends CollectionItem> {
14
21
  private cache;
15
- private data;
22
+ private dataset;
23
+ private readonly indexedFields;
16
24
  /**
17
25
  * Creates a new SortEngine with optional data and fields to index.
18
26
  */
19
27
  constructor(options?: SortEngineOptions<T>);
28
+ private rebuildConfiguredIndexes;
20
29
  /**
21
30
  * Builds an index for sorting the given field.
22
31
  */
@@ -24,12 +33,15 @@ declare class SortEngine<T extends CollectionItem> {
24
33
  /**
25
34
  * Clears all cached indexes.
26
35
  */
27
- clearIndexes(): void;
36
+ clearIndexes(): this;
37
+ clearData(): this;
38
+ data(data: T[]): this;
28
39
  /**
29
40
  * Sorts the data based on the given descriptors.
30
41
  */
31
- sort(descriptors: SortDescriptor<T>[]): T[];
32
- sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[];
42
+ sort(descriptors: SortDescriptor<T>[]): T[] & SortEngineChain<T>;
43
+ sort(data: T[], descriptors: SortDescriptor<T>[], inPlace?: boolean): T[] & SortEngineChain<T>;
44
+ private withChain;
33
45
  /**
34
46
  * Reconstructs the sorted array from the cached index.
35
47
  */
@@ -1 +1 @@
1
- export{a as SortEngine}from'../chunk-DBAABXBP.mjs';
1
+ export{a as SortEngine}from'../chunk-Z33ISQHF.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devisfuture/mega-collection",
3
- "version": "1.1.14",
3
+ "version": "1.2.1",
4
4
  "description": "High-performance search, filter & sort engine for 100K+ item collections in JavaScript/TypeScript",
5
5
  "exports": {
6
6
  ".": {
@@ -1 +0,0 @@
1
- var u=class{constructor(n={}){this.cache=new Map;this.data=[];if(n.data&&(this.data=n.data,!!n.fields?.length))for(let a of n.fields)this.buildIndex(n.data,a);}buildIndex(n,a){let l,t;if(Array.isArray(n))l=n,t=a;else {if(!this.data.length)throw new Error("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");l=this.data,t=n;}this.data=l;let e=l.length,i=new Uint32Array(e);for(let o=0;o<e;o++)i[o]=o;let s=l.map(o=>o[t]);if(typeof s[0]=="number"){let o=new Float64Array(e);for(let c=0;c<e;c++)o[c]=s[c];i.sort((c,d)=>o[c]-o[d]);}else i.sort((o,c)=>{let d=s[o],f=s[c];return d<f?-1:d>f?1:0});return this.cache.set(t,{indexes:i,dataRef:l,itemCount:e,fieldSnapshot:s}),this}clearIndexes(){this.cache.clear();}sort(n,a,l=false){let t,e;if(a===void 0){if(!this.data.length)throw new Error("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call sort(data, descriptors).");t=this.data,e=n;}else t=n,e=a;if(e.length===0||t.length===0)return t;if(e.length===1){let{field:r,direction:o}=e[0],c=this.cache.get(r);if(c&&c.dataRef===t&&c.itemCount===t.length&&this.isFieldSnapshotValid(t,r,c.fieldSnapshot))return this.reconstructFromIndex(t,c.indexes,o)}let i=l?t:t.slice();if(e.length===1&&t.length>0&&typeof t[0][e[0].field]=="number")return this.radixSortNumeric(i,e[0].field,e[0].direction);let s=this.buildComparator(e);return i.sort(s),i}reconstructFromIndex(n,a,l){let t=n.length,e=new Array(t);if(l==="asc")for(let i=0;i<t;i++)e[i]=n[a[i]];else for(let i=0;i<t;i++)e[i]=n[a[t-1-i]];return e}isFieldSnapshotValid(n,a,l){for(let t=0;t<n.length;t++)if(n[t][a]!==l[t])return false;return true}buildComparator(n){let a=n.map(({field:e})=>e),l=n.map(({direction:e})=>e==="asc"?1:-1),t=a.length;return (e,i)=>{for(let s=0;s<t;s++){let r=e[a[s]],o=i[a[s]];if(r<o)return -l[s];if(r>o)return l[s]}return 0}}radixSortNumeric(n,a,l){let t=n.length,e=new Float64Array(t);for(let r=0;r<t;r++)e[r]=n[r][a];let i=new Uint32Array(t);for(let r=0;r<t;r++)i[r]=r;i.sort((r,o)=>e[r]-e[o]);let s=new Array(t);if(l==="asc")for(let r=0;r<t;r++)s[r]=n[i[r]];else for(let r=0;r<t;r++)s[t-1-r]=n[i[r]];return s}};export{u as a};
@@ -1 +0,0 @@
1
- var T=3,f=12;function x(h){let t=h.toLowerCase(),n=Math.min(T,t.length),e=t.length-n+1,r=new Array(e);for(let s=0;s<e;s++)r[s]=t.substring(s,s+n);return r}function m(h){let t=x(h);if(t.length<=f)return new Set(t);let n=new Set,e=t.length-1,r=f-1;for(let s=0;s<=r;s++){let i=Math.round(s*e/r);n.add(t[i]);}return n}function L(h,t){let n=h.get(t);if(n)return n;let e=new Set;return h.set(t,e),e}var y=class{constructor(t={}){this.ngramIndexes=new Map;this.data=[];if(this.minQueryLength=t.minQueryLength??1,!!t.data&&(this.data=t.data,!!t.fields?.length))for(let n of t.fields)this.buildIndex(t.data,n);}buildIndex(t,n){let e,r;if(Array.isArray(t))e=t,r=n;else {if(!this.data.length)throw new Error("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");e=this.data,r=t;}this.data=e;let s=new Map;for(let i=0,l=e.length;i<l;i++){let d=e[i][r];if(typeof d!="string")continue;let o=d.toLowerCase();for(let a=0,u=o.length;a<u;a++){let g=u-a,p=Math.min(T,g);for(let c=1;c<=p;c++){let I=o.substring(a,a+c);L(s,I).add(i);}}}return this.ngramIndexes.set(r,s),this}search(t,n){return n===void 0?this.searchAllFields(t):this.searchField(t,n)}normalizeQuery(t){return t.trim().toLowerCase()}searchAllFields(t){let n=[...this.ngramIndexes.keys()],e=this.normalizeQuery(t);if(!e)return this.data;if(e.length<this.minQueryLength)return this.data;if(!n.length)return this.searchAllFieldsLinear(e);let r=m(e);if(!r.size)return [];let s=new Set,i=[];for(let l of n)for(let d of this.searchFieldWithPreparedQuery(l,e,r))s.has(d)||(s.add(d),i.push(d));return i}searchField(t,n){let e=this.normalizeQuery(n);if(!e)return this.data;if(e.length<this.minQueryLength)return this.data;if(!this.ngramIndexes.size)return this.searchFieldLinear(t,e);let r=m(e);return r.size?this.searchFieldWithPreparedQuery(t,e,r):[]}searchFieldWithPreparedQuery(t,n,e){let r=this.ngramIndexes.get(t);if(!r)return [];let s=[];for(let o of e){let a=r.get(o);if(!a)return [];s.push(a);}s.sort((o,a)=>o.size-a.size);let i=s[0],l=s.length,d=[];for(let o of i){let a=true;for(let g=1;g<l;g++)if(!s[g].has(o)){a=false;break}if(!a)continue;let u=this.data[o][t];typeof u=="string"&&u.toLowerCase().includes(n)&&d.push(this.data[o]);}return d}searchAllFieldsLinear(t){if(!this.data.length)return [];let n=[];for(let e=0;e<this.data.length;e++){let r=this.data[e],s=false;for(let i of Object.values(r))if(typeof i=="string"&&i.toLowerCase().includes(t)){s=true;break}s&&n.push(r);}return n}searchFieldLinear(t,n){if(!this.data.length)return [];let e=[];for(let r=0;r<this.data.length;r++){let s=this.data[r][t];typeof s=="string"&&s.toLowerCase().includes(n)&&e.push(this.data[r]);}return e}clearIndexes(){this.ngramIndexes.clear(),this.data=[];}};export{y as a};
@@ -1 +0,0 @@
1
- var u=class{constructor(e){let{imports:t,data:n,...s}=e,a=new Set(t),r={},o={};for(let d of a){let h=d.prototype,c=this.getMethodNames(h);if(c.length===0)continue;let p=this.getModuleInitOptions(d.name,c,s),i=new d({data:n,...p}),g=this.getModuleName(c);g&&this.hasMethod(i,"clearIndexes")&&!o[g]&&(o[g]=i.clearIndexes.bind(i));for(let l of c)r[l]||this.hasMethod(i,l)&&(r[l]=i[l].bind(i));}this.engine=Object.keys(r).length>0?r:null,this.clearIndexMethods=o;}getModuleName(e){return e.includes("search")?"search":e.includes("sort")?"sort":e.includes("filter")?"filter":null}getModuleInitOptions(e,t,n){let s={},a=n[e];this.isRecord(a)&&Object.assign(s,a);for(let r of t){let o=n[r];this.isRecord(o)&&Object.assign(s,o);}return s}getMethodNames(e){let t=e;return Object.getOwnPropertyNames(t).filter(n=>n==="constructor"?false:typeof t[n]=="function")}hasMethod(e,t){return typeof e=="object"&&e!==null&&typeof e[t]=="function"}isRecord(e){return typeof e=="object"&&e!==null}callEngineMethod(e,t){let n=this.engine?.[e];if(!n)throw new Error(`MergeEngines: Method "${e}" is not available. Add module with method "${e}" to the \`imports\` array.`);return n(...t)}search(e,t){if(!this.engine?.search)throw new Error("MergeEngines: TextSearchEngine is not available. Add TextSearchEngine to the `imports` array.");return t===void 0?this.callEngineMethod("search",[e]):this.callEngineMethod("search",[e,t])}sort(e,t,n){if(!this.engine?.sort)throw new Error("MergeEngines: SortEngine is not available. Add SortEngine to the `imports` array.");return t===void 0?this.callEngineMethod("sort",[e]):this.callEngineMethod("sort",[e,t,n])}filter(e,t){if(!this.engine?.filter)throw new Error("MergeEngines: FilterEngine is not available. Add FilterEngine to the `imports` array.");return t===void 0?this.callEngineMethod("filter",[e]):this.callEngineMethod("filter",[e,t])}clearIndexes(e){let t=this.clearIndexMethods[e];if(t){t();return}let n={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"};throw new Error(`MergeEngines: ${n[e]} is not available. Add ${n[e]} to the \`imports\` array.`)}};export{u as a};
@@ -1 +0,0 @@
1
- var c=class{constructor(){this.indexes=new Map;}buildIndex(t,s){let n=new Map;for(let r=0,e=t.length;r<e;r++){let i=t[r],l=i[s];if(l==null)continue;let a=n.get(l);a?a.push(i):n.set(l,[i]);}this.indexes.set(s,n);}getByValue(t,s){let n=this.indexes.get(t);return n?n.get(s)??[]:[]}getByValues(t,s){let n=this.indexes.get(t);if(!n)return [];if(s.length===1)return n.get(s[0])??[];let r=new Set,e=[];for(let i=0;i<s.length;i++){let l=n.get(s[i]);if(l!==void 0)for(let a=0;a<l.length;a++){let o=l[a];r.has(o)||(r.add(o),e.push(o));}}return e}hasIndex(t){return this.indexes.has(t)}clear(){this.indexes.clear();}getIndexMap(t){return this.indexes.get(t)}};var C=class{constructor(t={}){this.data=[];this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;if(this.indexer=new c,this.filterByPreviousResult=t.filterByPreviousResult??false,!!t.data&&(this.data=t.data,!!t.fields?.length))for(let s of t.fields)this.buildIndex(t.data,s);}buildIndex(t,s){if(!Array.isArray(t)){if(!this.data.length)throw new Error("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).");return this.indexer.buildIndex(this.data,t),this}return this.data=t,this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this.indexer.buildIndex(t,s),this}clearIndexes(){this.indexer.clear();}resetFilterState(){this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null;}filter(t,s){let n=s===void 0,r,e,i;if(n){if(!this.data.length)throw new Error("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call filter(data, criteria).");if(e=t,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.data){let u=this.hasCriteriaAdditions(this.previousCriteria,e),h=this.hasCriteriaRemovals(this.previousCriteria,e);if(!u&&!h)return this.previousResult;u&&!h?(r=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,e)):(r=this.data,i=e);}else r=this.data,i=e;}else if(e=s,r=t,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===r){let u=this.hasCriteriaAdditions(this.previousCriteria,e),h=this.hasCriteriaRemovals(this.previousCriteria,e);if(!u&&!h)return this.previousResult;u&&!h?(r=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,e)):i=e;}else i=e;if(e.length===0)return this.filterByPreviousResult&&(this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null),n?this.data:r;n&&!i&&(i=e);let{indexedCriteria:l,linearCriteria:a}=i.reduce((u,h)=>(this.indexer.hasIndex(h.field)?u.indexedCriteria.push(h):u.linearCriteria.push(h),u),{indexedCriteria:[],linearCriteria:[]}),o;if(l.length>0&&a.length===0)return o=this.filterViaIndex(l,r),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(e),this.previousBaseData=n?this.data:t),o;if(l.length>0&&a.length>0){let u=this.filterViaIndex(l,r);return o=this.linearFilter(u,a),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(e),this.previousBaseData=n?this.data:t),o}return o=this.linearFilter(r,i),this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(e),this.previousBaseData=n?this.data:t),o}cloneCriteria(t){return t.map(({field:s,values:n})=>({field:s,values:[...n]}))}hasCriteriaAdditions(t,s){let n=new Map(t.map(({field:e,values:i})=>[e,new Set(i)])),r=new Map(s.map(({field:e,values:i})=>[e,new Set(i)]));for(let[e,i]of r){let l=n.get(e);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}hasCriteriaRemovals(t,s){let n=new Map(t.map(({field:e,values:i})=>[e,new Set(i)])),r=new Map(s.map(({field:e,values:i})=>[e,new Set(i)]));for(let[e,i]of n){let l=r.get(e);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}getAddedCriteria(t,s){let n=new Map(t.map(({field:e,values:i})=>[e,new Set(i)])),r=[];for(let{field:e,values:i}of s){let l=n.get(e);if(!l){r.push({field:e,values:[...i]});continue}let a=i.filter(o=>!l.has(o));a.length>0&&r.push({field:e,values:a});}return r}linearFilter(t,s){let n=new Map(s.map(({field:i,values:l})=>[i,new Set(l)])),r=s.map(({field:i})=>i),e=[];for(let i=0;i<t.length;i++){let l=t[i],a=true;for(let o=0;o<r.length;o++){let u=r[o];if(!n.get(u).has(l[u])){a=false;break}}a&&e.push(l);}return e}filterViaIndex(t,s){let r=s!==this.data?new Set(s):null;if(t.length===1){let d=this.indexer.getByValues(t[0].field,t[0].values);return r?d.filter(f=>r.has(f)):d}let e=t.map(d=>({criterion:d,size:this.estimateIndexSize(d)})).sort((d,f)=>d.size-f.size),{field:i,values:l}=e[0].criterion,a=this.indexer.getByValues(i,l);if(a.length===0)return [];let o=new Map(e.slice(1).map(({criterion:{field:d,values:f}})=>[d,new Set(f)])),u=Array.from(o.keys()),h=[];for(let d=0;d<a.length;d++){let f=a[d],p=true;for(let v=0;v<u.length;v++){let g=u[v];if(!o.get(g).has(f[g])){p=false;break}}p&&r&&!r.has(f)&&(p=false),p&&h.push(f);}return h}estimateIndexSize(t){let s=this.indexer.getIndexMap(t.field);return s?t.values.reduce((n,r)=>{let e=s.get(r);return e?n+e.length:n},0):1/0}};export{C as a};