@devisfuture/mega-collection 2.0.3 → 2.1.3

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
@@ -100,10 +100,11 @@ Each instance keeps its own data and its own indexes, so they work separately
100
100
  and do not overwrite each other.
101
101
 
102
102
  Each engine accepts an optional `fields` array (set via the `search`,
103
- `filter` or `sort` option) which tells it which properties should be indexed up
104
- front. This means the engine prepares those fields once so later calls can be
105
- faster. If you skip `fields`, everything still works, but the engine may need
106
- to scan the full array.
103
+ `filter` or `sort` option) which tells it which properties should use indexed
104
+ execution. Those indexes are built lazily on the first matching operation, so
105
+ initial engine creation stays fast even for very large collections. If you skip
106
+ `fields`, everything still works, but the engine may need to scan the full
107
+ array.
107
108
 
108
109
  ```ts
109
110
  import { MergeEngines } from "@devisfuture/mega-collection";
@@ -175,8 +176,9 @@ The examples below show the difference between simple fields and nested fields.
175
176
  ```ts
176
177
  import { TextSearchEngine } from "@devisfuture/mega-collection/search";
177
178
 
178
- // `fields` tells the engine which fields it should prepare for faster search.
179
- // If you skip `fields`, search still works, but it will scan the full dataset.
179
+ // `fields` tells the engine which fields should use indexed search.
180
+ // The index is built lazily on first use. If you skip `fields`, search still
181
+ // works, but it will scan the full dataset.
180
182
  const engine = new TextSearchEngine<User>({
181
183
  data: users,
182
184
  fields: ["name", "city"],
@@ -227,8 +229,9 @@ The examples below show the difference between simple fields and nested fields.
227
229
  ```ts
228
230
  import { FilterEngine } from "@devisfuture/mega-collection/filter";
229
231
 
230
- // `fields` tells the engine which fields should be prepared for faster filter
231
- // lookups. Without `fields`, filtering still works, but it will scan the data.
232
+ // `fields` tells the engine which fields should use indexed filter lookups.
233
+ // The index is built lazily on first use. Without `fields`, filtering still
234
+ // works, but it will scan the data.
232
235
  const engine = new FilterEngine<User>({
233
236
  data: users,
234
237
  fields: ["city", "age"],
@@ -287,8 +290,9 @@ Use `SortEngine` when you only need sorting.
287
290
  ```ts
288
291
  import { SortEngine } from "@devisfuture/mega-collection/sort";
289
292
 
290
- // `fields` tells the engine which fields should be prepared for faster
291
- // single-field sorting. If you skip `fields`, sorting still works.
293
+ // `fields` tells the engine which fields should use cached single-field
294
+ // sorting. The cache is built lazily on first use. If you skip `fields`,
295
+ // sorting still works.
292
296
  const engine = new SortEngine<User>({
293
297
  data: users,
294
298
  fields: ["age", "name", "city"],
@@ -0,0 +1 @@
1
+ var c=class h extends Error{constructor(e){super(e),this.name="SortEngineError";}static missingDatasetForBuildIndex(){return new h("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForSort(){return new h("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call sort(data, descriptors).")}};var g=class{constructor(e={}){this.cache=new Map;this.dataset=[];this.indexedFields=new Set;if(e.data&&(this.dataset=e.data,e.fields?.length))for(let a of e.fields)this.indexedFields.add(a);}ensureConfiguredIndex(e){this.indexedFields.has(e)&&(this.cache.has(e)||this.dataset.length!==0&&this.buildIndex(this.dataset,e));}buildIndex(e,a){let l,t;if(Array.isArray(e))l=e,t=a;else {if(!this.dataset.length)throw c.missingDatasetForBuildIndex();l=this.dataset,t=e;}this.dataset=l;let r=l.length,s=new Uint32Array(r),o=new Array(r);for(let n=0;n<r;n++)s[n]=n,o[n]=l[n][t];if(typeof o[0]=="number"){let n=new Float64Array(r);for(let d=0;d<r;d++)n[d]=o[d];s.sort((d,u)=>n[d]-n[u]);}else s.sort((n,d)=>{let u=o[n],f=o[d];return u<f?-1:u>f?1:0});return this.cache.set(t,{indexes:s,dataRef:l,itemCount:r}),this}clearIndexes(){return this.cache.clear(),this}clearData(){return this.dataset=[],this.cache.clear(),this}data(e){return this.dataset=e,this.clearIndexes(),this}getOriginData(){return this.dataset}sort(e,a,l=false){let t,r;if(a===void 0){if(!this.dataset.length)throw c.missingDatasetForSort();t=this.dataset,r=e;}else t=e,r=a;if(r.length===0||t.length===0)return t;if(r.length===1){let{field:i,direction:n}=r[0];t===this.dataset&&this.ensureConfiguredIndex(i);let d=this.cache.get(i);if(d?.dataRef===t&&d.itemCount===t.length)return this.reconstructFromIndex(t,d.indexes,n)}let s=l?t:t.slice();if(r.length===1&&t.length>0&&typeof t[0][r[0].field]=="number")return this.radixSortNumeric(s,r[0].field,r[0].direction);let o=this.buildComparator(r);return s.sort(o),s}reconstructFromIndex(e,a,l){let t=e.length,r=new Array(t);if(l==="asc")for(let s=0;s<t;s++)r[s]=e[a[s]];else for(let s=0;s<t;s++)r[s]=e[a[t-1-s]];return r}buildComparator(e){let a=e.map(({field:r})=>r),l=e.map(({direction:r})=>r==="asc"?1:-1),t=a.length;return (r,s)=>{for(let o=0;o<t;o++){let i=r[a[o]],n=s[a[o]];if(i<n)return -l[o];if(i>n)return l[o]}return 0}}radixSortNumeric(e,a,l){let t=e.length,r=new Float64Array(t);for(let i=0;i<t;i++)r[i]=e[i][a];let s=new Uint32Array(t);for(let i=0;i<t;i++)s[i]=i;s.sort((i,n)=>r[i]-r[n]);let o=new Array(t);if(l==="asc")for(let i=0;i<t;i++)o[i]=e[s[i]];else for(let i=0;i<t;i++)o[t-1-i]=e[s[i]];return o}};export{g as a};
@@ -1 +1 @@
1
- import {a}from'./chunk-4PTQMQ73.mjs';import {b,a as a$2}from'./chunk-5B7Y4C22.mjs';import {a as a$1}from'./chunk-IYELLKOW.mjs';var g=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"search",{value:(r,n)=>n===void 0?this.callbacks.search(r):this.callbacks.search(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"sort",{value:(r,n,i)=>n===void 0?this.callbacks.sort(e,r,i):this.callbacks.sort(r,n,i),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"filter",{value:(r,n)=>n===void 0?this.callbacks.filter(e,r):this.callbacks.filter(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:r=>(this.callbacks.clearIndexes(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:r=>(this.callbacks.clearData(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:r=>this.callbacks.data(r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),t}};var x=o=>o===a?"search":o===a$1?"sort":o===b?"filter":null,y=(o,e,t)=>{if(o===a){let r=new a({data:e,...t});return {moduleName:"search",executeSearch:(n,i)=>i===void 0?r.search(n):r.search(n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===a$1){let r=new a$1({data:e,...t});return {moduleName:"sort",executeSort:(n,i,s)=>i===void 0?r.sort(n):r.sort(n,i,s),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===b){let r=new b({data:e,...t});return {moduleName:"filter",executeFilter:(n,i)=>i===void 0?r[a$2](n):r[a$2](n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}return null};var N={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},l=class o extends Error{constructor(e){super(e),this.name="MergeEnginesError";}static unavailableMethod(e){return new o(`MergeEngines: Method "${e}" is not available. Add module with method "${e}" to the \`imports\` array.`)}static unavailableEngine(e){let t=N[e];return new o(`MergeEngines: ${t} is not available. Add ${t} to the \`imports\` array.`)}static unavailableGetOriginData(){return new o("MergeEngines: getOriginData is not available. Add TextSearchEngine, SortEngine, or FilterEngine to the `imports` array.")}};var m=class{constructor(e){this.chainBuilder=new g({search:(e,t)=>t===void 0?this.search(e):this.search(e,t),sort:(e,t,r)=>t===void 0?this.sort(e):this.sort(e,t,r),filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:e=>this.clearIndexes(e),clearData:e=>this.clearData(e)});let{imports:t,data:r,...n}=e,i=new Set(t),s=null,h=null,M=null,f={},E={},C={},b=null;for(let p of i){let D=x(p);if(!D)continue;let S=this.getModuleInitOptions(D,p.name,n),a=y(p,r,S);a&&(a.moduleName==="search"&&!s&&(s=a),a.moduleName==="sort"&&!h&&(h=a),a.moduleName==="filter"&&!M&&(M=a),f[a.moduleName]=()=>a.clearIndexes(),E[a.moduleName]=()=>a.clearData(),C[a.moduleName]=w=>a.data(w),b??(b=()=>a.getOriginData()));}this.searchModule=s,this.sortModule=h,this.filterModule=M,this.clearIndexMethods=f,this.clearDataMethods=E,this.setDataMethods=C,this.getOriginDataMethod=b;}getModuleInitOptions(e,t,r){let n={};for(let i of [e,t]){let s=r[i];this.isRecord(s)&&Object.assign(n,s);}return n}isRecord(e){return typeof e=="object"&&e!==null}search(e,t){if(!this.searchModule)throw l.unavailableEngine("search");return t===void 0?this.withChain(this.searchModule.executeSearch(e)):this.withChain(this.searchModule.executeSearch(e,t))}sort(e,t,r){if(!this.sortModule)throw l.unavailableEngine("sort");return t===void 0?this.withChain(this.sortModule.executeSort(e)):this.withChain(this.sortModule.executeSort(e,t,r))}filter(e,t){if(!this.filterModule)throw l.unavailableEngine("filter");return t===void 0?this.withChain(this.filterModule.executeFilter(e)):this.withChain(this.filterModule.executeFilter(e,t))}withChain(e){return this.chainBuilder.create(e)}getOriginData(){if(this.getOriginDataMethod)return this.getOriginDataMethod();throw l.unavailableGetOriginData()}clearIndexes(e){let t=this.clearIndexMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}data(e){let t=["search","sort","filter"];for(let r of t){let n=this.setDataMethods[r];n&&n(e);}return this}clearData(e){let t=this.clearDataMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}};export{m as a};
1
+ import {a}from'./chunk-PLHHLXUH.mjs';import {b,a as a$2}from'./chunk-RIPRMLMT.mjs';import {a as a$1}from'./chunk-7RNFZK7U.mjs';var g=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"search",{value:(r,n)=>n===void 0?this.callbacks.search(r):this.callbacks.search(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"sort",{value:(r,n,i)=>n===void 0?this.callbacks.sort(e,r,i):this.callbacks.sort(r,n,i),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"filter",{value:(r,n)=>n===void 0?this.callbacks.filter(e,r):this.callbacks.filter(r,n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:r=>(this.callbacks.clearIndexes(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:r=>(this.callbacks.clearData(r),this.create(e)),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:r=>this.callbacks.data(r),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),t}};var x=o=>o===a?"search":o===a$1?"sort":o===b?"filter":null,y=(o,e,t)=>{if(o===a){let r=new a({data:e,...t});return {moduleName:"search",executeSearch:(n,i)=>i===void 0?r.search(n):r.search(n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===a$1){let r=new a$1({data:e,...t});return {moduleName:"sort",executeSort:(n,i,s)=>i===void 0?r.sort(n):r.sort(n,i,s),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}if(o===b){let r=new b({data:e,...t});return {moduleName:"filter",executeFilter:(n,i)=>i===void 0?r[a$2](n):r[a$2](n,i),clearIndexes:()=>r.clearIndexes(),clearData:()=>r.clearData(),data:n=>r.data(n),getOriginData:()=>r.getOriginData()}}return null};var N={search:"TextSearchEngine",sort:"SortEngine",filter:"FilterEngine"},l=class o extends Error{constructor(e){super(e),this.name="MergeEnginesError";}static unavailableMethod(e){return new o(`MergeEngines: Method "${e}" is not available. Add module with method "${e}" to the \`imports\` array.`)}static unavailableEngine(e){let t=N[e];return new o(`MergeEngines: ${t} is not available. Add ${t} to the \`imports\` array.`)}static unavailableGetOriginData(){return new o("MergeEngines: getOriginData is not available. Add TextSearchEngine, SortEngine, or FilterEngine to the `imports` array.")}};var m=class{constructor(e){this.chainBuilder=new g({search:(e,t)=>t===void 0?this.search(e):this.search(e,t),sort:(e,t,r)=>t===void 0?this.sort(e):this.sort(e,t,r),filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:e=>this.clearIndexes(e),clearData:e=>this.clearData(e)});let{imports:t,data:r,...n}=e,i=new Set(t),s=null,h=null,M=null,f={},E={},C={},b=null;for(let p of i){let D=x(p);if(!D)continue;let S=this.getModuleInitOptions(D,p.name,n),a=y(p,r,S);a&&(a.moduleName==="search"&&!s&&(s=a),a.moduleName==="sort"&&!h&&(h=a),a.moduleName==="filter"&&!M&&(M=a),f[a.moduleName]=()=>a.clearIndexes(),E[a.moduleName]=()=>a.clearData(),C[a.moduleName]=w=>a.data(w),b??(b=()=>a.getOriginData()));}this.searchModule=s,this.sortModule=h,this.filterModule=M,this.clearIndexMethods=f,this.clearDataMethods=E,this.setDataMethods=C,this.getOriginDataMethod=b;}getModuleInitOptions(e,t,r){let n={};for(let i of [e,t]){let s=r[i];this.isRecord(s)&&Object.assign(n,s);}return n}isRecord(e){return typeof e=="object"&&e!==null}search(e,t){if(!this.searchModule)throw l.unavailableEngine("search");return t===void 0?this.withChain(this.searchModule.executeSearch(e)):this.withChain(this.searchModule.executeSearch(e,t))}sort(e,t,r){if(!this.sortModule)throw l.unavailableEngine("sort");return t===void 0?this.withChain(this.sortModule.executeSort(e)):this.withChain(this.sortModule.executeSort(e,t,r))}filter(e,t){if(!this.filterModule)throw l.unavailableEngine("filter");return t===void 0?this.withChain(this.filterModule.executeFilter(e)):this.withChain(this.filterModule.executeFilter(e,t))}withChain(e){return this.chainBuilder.create(e)}getOriginData(){if(this.getOriginDataMethod)return this.getOriginDataMethod();throw l.unavailableGetOriginData()}clearIndexes(e){let t=this.clearIndexMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}data(e){let t=["search","sort","filter"];for(let r of t){let n=this.setDataMethods[r];n&&n(e);}return this}clearData(e){let t=this.clearDataMethods[e];if(t)return t(),this;throw l.unavailableEngine(e)}};export{m as a};
@@ -0,0 +1,2 @@
1
+ var x=class u extends Error{constructor(e){super(e),this.name="TextSearchEngineError";}static missingDatasetForBuildIndex(){return new u("TextSearchEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}};function T(u){let e=u.toLowerCase(),t=Math.min(3,e.length),s=e.length-t+1,n=new Array(s);for(let i=0;i<s;i++)n[i]=e.substring(i,i+t);return n}function C(u,e){let t=u.get(e);if(t)return t;let s=new Set;return u.set(e,s),s}function I(u){let e=T(u);if(e.length<=12)return new Set(e);let t=new Set,s=e.length-1,n=11;for(let i=0;i<=n;i++){let o=Math.round(i*s/n);t.add(e[o]);}return t}function p(u,e,t){for(let s=0,n=e.length;s<n;s++){let i=n-s,o=Math.min(3,i);for(let r=1;r<=o;r++){let a=e.substring(s,s+r);C(u,a).add(t);}}}var y=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.ngramIndexes=new Map;this.normalizedFieldValues=new Map;}registerFields(e){if(e?.length)for(let t=0;t<e.length;t++)this.registerField(e[t]);}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}hasIndex(e){return this.ngramIndexes.has(e)}hasIndexes(){return this.ngramIndexes.size>0}clearIndexes(){this.ngramIndexes.clear(),this.normalizedFieldValues.clear();}buildIndexes(e){this.clearIndexes();for(let t of this.registeredFields)this.buildIndex(e,t);}ensureIndex(e,t){this.registeredFields.has(t)&&(this.ngramIndexes.has(t)||this.buildIndex(e,t));}ensureAllIndexes(e){for(let t of this.registeredFields)this.ensureIndex(e,t);}searchAllIndexedFields(e,t,s){let n=new Set,i=[];for(let o of this.registeredFields)for(let r of this.searchIndexedField(e,o,t,s))n.has(r)||(n.add(r),i.push(r));return i}searchIndexedField(e,t,s,n){let i=this.ngramIndexes.get(t);if(!i)return [];let o=[];for(let d of n){let l=i.get(d);if(!l)return [];o.push(l);}o.sort((d,l)=>d.size-l.size);let r=o[0],a=o.length,h=[],c=this.normalizedFieldValues.get(t);for(let d of r){let l=true;for(let m=1;m<a;m++)if(!o[m].has(d)){l=false;break}if(!l)continue;let g=e[d];!g||!c?.[d]?.includes(s)||h.push(g);}return h}searchFieldLinear(e,t,s){let n=this.fieldDescriptors.get(t);if(!n)return [];let{collectionKey:i,nestedKey:o}=n,r=[];for(let a=0;a<e.length;a++){let h=e[a],c=h[i];if(!Array.isArray(c))continue;let d=false;for(let l=0;l<c.length;l++){let g=c[l][o];if(typeof g=="string"&&g.toLowerCase().includes(s)){d=true;break}}d&&r.push(h);}return r}matchesAnyField(e,t){for(let s of this.registeredFields){let n=this.fieldDescriptors.get(s);if(!n)continue;let{collectionKey:i,nestedKey:o}=n,r=e[i];if(Array.isArray(r))for(let a=0;a<r.length;a++){let h=r[a][o];if(typeof h=="string"&&h.toLowerCase().includes(t))return true}}return false}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let s=this.fieldDescriptors.get(t);if(!s)return;let{collectionKey:n,nestedKey:i}=s,o=new Map,r=new Array(e.length);for(let a=0,h=e.length;a<h;a++){let d=e[a][n];if(!Array.isArray(d))continue;let l=[];for(let g=0;g<d.length;g++){let f=d[g][i];if(typeof f!="string")continue;let m=f.toLowerCase();l.push(m),p(o,m,a);}l.length!==0&&(r[a]=l.join(`
2
+ `));}this.ngramIndexes.set(t,o),this.normalizedFieldValues.set(t,r);}};var F=class{constructor(e={}){this.ngramIndexes=new Map;this.normalizedFieldValues=new Map;this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new y;if(this.minQueryLength=e.minQueryLength??1,this.nestedCollection.registerFields(e.nestedFields),!!e.data&&(this.dataset=e.data,e.fields?.length))for(let t of e.fields)this.indexedFields.add(t);}ensureConfiguredFieldIndex(e){this.indexedFields.has(e)&&(this.ngramIndexes.has(e)||this.dataset.length!==0&&this.buildIndex(this.dataset,e));}ensureConfiguredIndexes(){for(let e of this.indexedFields)this.ensureConfiguredFieldIndex(e);}ensureConfiguredNestedIndex(e){this.nestedCollection.hasField(e)&&(this.nestedCollection.hasIndex(e)||this.dataset.length!==0&&this.nestedCollection.ensureIndex(this.dataset,e));}ensureConfiguredNestedIndexes(){this.dataset.length!==0&&this.nestedCollection.ensureAllIndexes(this.dataset);}buildIndex(e,t){let s,n;if(Array.isArray(e))s=e,n=t;else {if(!this.dataset.length)throw x.missingDatasetForBuildIndex();s=this.dataset,n=e;}this.dataset=s;let i=new Map,o=new Array(s.length);for(let r=0,a=s.length;r<a;r++){let h=s[r][n];if(typeof h!="string")continue;let c=h.toLowerCase();o[r]=c,p(i,c,r);}return this.ngramIndexes.set(n,i),this.normalizedFieldValues.set(n,o),this}search(e,t){return t===void 0?this.searchAllFields(e):this.searchField(e,t)}normalizeQuery(e){return e.trim().toLowerCase()}searchAllFields(e){let t=this.normalizeQuery(e);if(!t)return this.dataset;if(t.length<this.minQueryLength)return this.dataset;if(this.ensureConfiguredIndexes(),this.ensureConfiguredNestedIndexes(),!this.ngramIndexes.size&&!this.nestedCollection.hasIndexes())return this.searchAllFieldsLinear(t);let s=I(t);if(!s.size)return [];let n=new Set,i=[];for(let o of this.ngramIndexes.keys())for(let r of this.searchFieldWithPreparedQuery(o,t,s))n.has(r)||(n.add(r),i.push(r));for(let o of this.nestedCollection.searchAllIndexedFields(this.dataset,t,s))n.has(o)||(n.add(o),i.push(o));return i}searchField(e,t){let s=this.normalizeQuery(t);if(!s)return this.dataset;if(s.length<this.minQueryLength)return this.dataset;if(this.nestedCollection.hasField(e)){this.ensureConfiguredNestedIndex(e);let i=I(s);return i.size?this.nestedCollection.hasIndex(e)?this.nestedCollection.searchIndexedField(this.dataset,e,s,i):this.nestedCollection.searchFieldLinear(this.dataset,e,s):[]}if(this.indexedFields.size>0){if(!this.indexedFields.has(e))return [];this.ensureConfiguredFieldIndex(e);}if(!this.ngramIndexes.size)return this.searchFieldLinear(e,s);let n=I(s);return n.size?this.searchFieldWithPreparedQuery(e,s,n):[]}searchFieldWithPreparedQuery(e,t,s){let n=this.ngramIndexes.get(e);if(!n)return [];let i=[];for(let c of s){let d=n.get(c);if(!d)return [];i.push(d);}i.sort((c,d)=>c.size-d.size);let o=i[0],r=i.length,a=[],h=this.normalizedFieldValues.get(e);for(let c of o){let d=true;for(let f=1;f<r;f++)if(!i[f].has(c)){d=false;break}if(!d)continue;let l=this.dataset[c];if(!l)continue;h?.[c]?.includes(t)&&a.push(l);}return a}searchAllFieldsLinear(e){if(!this.dataset.length)return [];let t=[];for(let s=0;s<this.dataset.length;s++){let n=this.dataset[s],i=false;for(let o in n){let r=n[o];if(typeof r=="string"&&r.toLowerCase().includes(e)){i=true;break}}i||(i=this.nestedCollection.matchesAnyField(n,e)),i&&t.push(n);}return t}searchFieldLinear(e,t){if(!this.dataset.length)return [];if(this.nestedCollection.hasField(e))return this.nestedCollection.searchFieldLinear(this.dataset,e,t);let s=[];for(let n=0;n<this.dataset.length;n++){let i=this.dataset[n][e];typeof i=="string"&&i.toLowerCase().includes(t)&&s.push(this.dataset[n]);}return s}clearIndexes(){return this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}getOriginData(){return this.dataset}data(e){return this.dataset=e,this.clearIndexes(),this}clearData(){return this.dataset=[],this.ngramIndexes.clear(),this.normalizedFieldValues.clear(),this.nestedCollection.clearIndexes(),this}};export{F as a};
@@ -0,0 +1 @@
1
+ var T=class{constructor(){this.indexes=new Map;}buildIndex(e,t){let n=new Map;for(let s=0,r=e.length;s<r;s++){let i=e[s],l=i[t];if(l==null)continue;let a=n.get(l);a?a.push(i):n.set(l,[i]);}this.indexes.set(t,n);}getByValue(e,t){let n=this.indexes.get(e);return n?n.get(t)??[]:[]}getByValues(e,t){let n=this.indexes.get(e);if(!n)return [];if(t.length===1)return n.get(t[0])??[];let s=new Set,r=[];for(let i=0;i<t.length;i++){let l=n.get(t[i]);if(l!==void 0)for(let a=0;a<l.length;a++){let u=l[a];s.has(u)||(s.add(u),r.push(u));}}return r}hasIndex(e){return this.indexes.has(e)}clear(){this.indexes.clear();}getIndexMap(e){return this.indexes.get(e)}};var x=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"filter",{value:(n,s)=>s===void 0?this.callbacks.filter(e,n):this.callbacks.filter(n,s),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:()=>this.callbacks.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:n=>this.callbacks.data(n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:()=>this.callbacks.clearData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"resetFilterState",{value:()=>this.callbacks.resetFilterState(),enumerable:false,configurable:true,writable:true}),t}};var C=class p extends Error{constructor(e){super(e),this.name="FilterEngineError";}static missingDatasetForBuildIndex(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForFilter(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call filter(data, criteria).")}};var v=Symbol("FilterEngine.execute");var F=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.indexes=new Map;}registerFields(e){if(e?.length)for(let t=0;t<e.length;t++)this.registerField(e[t]);}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}hasIndex(e){return this.indexes.has(e)}clearIndexes(){this.indexes.clear();}buildIndexes(e){this.indexes.clear();for(let t of this.registeredFields)this.buildIndex(e,t);}ensureIndex(e,t){this.registeredFields.has(t)&&(this.indexes.has(t)||this.buildIndex(e,t));}filter(e,t,n){if(e.length===0||t.length===0)return e;let s=[],r=[];for(let a=0;a<t.length;a++){let u=t[a];if(this.indexes.has(u.field)){s.push(u);continue}r.push(u);}let i=e,l=e===n?null:new Set(e);if(s.length>0&&(i=this.filterByIndexes(s,l),i.length===0))return i;for(let a=0;a<r.length;a++)if(i=this.filterLinearly(i,r[a]),i.length===0)return i;return i}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let n=this.fieldDescriptors.get(t);if(!n)return;let{collectionKey:s,nestedKey:r}=n,i=new Map;for(let l=0,a=e.length;l<a;l++){let u=e[l],h=u[s];if(Array.isArray(h))for(let c=0;c<h.length;c++){let o=h[c][r];if(o==null)continue;let d=i.get(o);if(d){d[d.length-1]!==u&&d.push(u);continue}i.set(o,[u]);}}this.indexes.set(t,i);}filterByIndexes(e,t){if(e.length===1){let i=this.indexes.get(e[0].field);if(!i)return [];let l=this.getItemsByValues(i,e[0].values);if(l.length===0)return [];if(t===null)return l;let a=[];for(let u=0;u<l.length;u++){let h=l[u];t.has(h)&&a.push(h);}return a}let n=e.map(i=>({criterion:i,size:this.estimateIndexSize(i)})).sort((i,l)=>i.size-l.size),s=t,r=[];for(let i=0;i<n.length;i++){let{criterion:l}=n[i],a=this.indexes.get(l.field);if(!a)return [];let u=this.getItemsByValues(a,l.values);if(u.length===0)return [];if(s===null)r=u;else {r=[];for(let h=0;h<u.length;h++){let c=u[h];s.has(c)&&r.push(c);}}if(r.length===0)return [];s=new Set(r);}return r}getItemsByValues(e,t){if(t.length===1)return e.get(t[0])??[];let n=new Set,s=[];for(let r=0;r<t.length;r++){let i=e.get(t[r]);if(i)for(let l=0;l<i.length;l++){let a=i[l];n.has(a)||(n.add(a),s.push(a));}}return s}estimateIndexSize(e){let t=this.indexes.get(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}filterLinearly(e,t){let n=this.fieldDescriptors.get(t.field);if(!n)return e;let{collectionKey:s,nestedKey:r}=n,i=new Set(t.values),l=[];for(let a=0;a<e.length;a++){let u=e[a],h=u[s];if(!Array.isArray(h))continue;let c=false;for(let o=0;o<h.length;o++)if(i.has(h[o][r])){c=true;break}c&&l.push(u);}return l}};var I=class{constructor(e={}){this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new F;this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;this.chainBuilder=new x({filter:(e,t)=>t===void 0?this.filter(e):this.filter(e,t),getOriginData:()=>this.getOriginData(),data:e=>this.data(e),clearIndexes:()=>this.clearIndexes(),clearData:()=>this.clearData(),resetFilterState:()=>this.resetFilterState()});if(this.indexer=new T,this.filterByPreviousResult=e.filterByPreviousResult??false,this.nestedCollection.registerFields(e.nestedFields),!!e.data&&(this.dataset=e.data,e.fields?.length))for(let t of e.fields)this.indexedFields.add(t);}ensureConfiguredFieldIndex(e){this.indexedFields.has(e)&&(this.indexer.hasIndex(e)||this.dataset.length!==0&&this.indexer.buildIndex(this.dataset,e));}ensureIndexesForCriteria(e){if(this.dataset.length!==0)for(let t=0;t<e.length;t++){let n=e[t].field;if(this.nestedCollection.hasField(n)){this.nestedCollection.ensureIndex(this.dataset,n);continue}this.ensureConfiguredFieldIndex(n);}}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),this}resetFilterState(){return this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this}clearData(){return this.dataset=[],this.indexer.clear(),this.nestedCollection.clearIndexes(),this.resetFilterState(),this}data(e){return this.dataset=e,this.resetFilterState(),this.clearIndexes(),this}getOriginData(){return this.dataset}filter(e,t){return t===void 0?this.withChain(this[v](e)):this.withChain(this[v](e,t))}[v](e,t){let n=t===void 0,s,r,i;if(n){if(!this.dataset.length)throw C.missingDatasetForFilter();if(r=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):(s=this.dataset,i=r);}else s=this.dataset,i=r;}else if(r=t,s=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===s){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):i=r;}else i=r;if(r.length===0)return this.filterByPreviousResult&&(this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null),n?this.dataset:s;this.ensureIndexesForCriteria(i),n&&!i&&(i=r);let l=[],a=[];for(let o=0;o<i.length;o++){let d=i[o];this.nestedCollection.hasField(d.field)?l.push(d):a.push(d);}if(l.length>0&&(s=this.nestedCollection.filter(s,l,this.dataset),s.length===0)){let o=[];return this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),o}if(a.length===0)return this.filterByPreviousResult&&(this.previousResult=s,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),s;let{indexedCriteria:u,linearCriteria:h}=a.reduce((o,d)=>(this.indexer.hasIndex(d.field)?o.indexedCriteria.push(d):o.linearCriteria.push(d),o),{indexedCriteria:[],linearCriteria:[]}),c;if(u.length>0&&h.length===0)return c=this.filterViaIndex(u,s),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c;if(u.length>0&&h.length>0){let o=this.filterViaIndex(u,s);return c=this.linearFilter(o,h),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}return c=this.linearFilter(s,a),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}withChain(e){return this.chainBuilder.create(e)}cloneCriteria(e){return e.map(({field:t,values:n})=>({field:t,values:[...n]}))}hasCriteriaAdditions(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of s){let l=n.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}hasCriteriaRemovals(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of n){let l=s.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}getAddedCriteria(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=[];for(let{field:r,values:i}of t){let l=n.get(r);if(!l){s.push({field:r,values:[...i]});continue}let a=i.filter(u=>!l.has(u));a.length>0&&s.push({field:r,values:a});}return s}linearFilter(e,t){let n=new Map(t.map(({field:i,values:l})=>[i,new Set(l)])),s=t.map(({field:i})=>i),r=[];for(let i=0;i<e.length;i++){let l=e[i],a=true;for(let u=0;u<s.length;u++){let h=s[u];if(!n.get(h).has(l[h])){a=false;break}}a&&r.push(l);}return r}filterViaIndex(e,t){let s=t!==this.dataset?new Set(t):null;if(e.length===1){let o=this.indexer.getByValues(e[0].field,e[0].values);if(!s)return o.slice();let d=[];for(let f=0;f<o.length;f++){let g=o[f];s.has(g)&&d.push(g);}return d}let r=e.map(o=>({criterion:o,size:this.estimateIndexSize(o)})).sort((o,d)=>o.size-d.size),{field:i,values:l}=r[0].criterion,a=this.indexer.getByValues(i,l);if(a.length===0)return [];let u=new Map(r.slice(1).map(({criterion:{field:o,values:d}})=>[o,new Set(d)])),h=Array.from(u.keys()),c=[];for(let o=0;o<a.length;o++){let d=a[o],f=true;for(let g=0;g<h.length;g++){let m=h[g];if(!u.get(m).has(d[m])){f=false;break}}f&&s&&!s.has(d)&&(f=false),f&&c.push(d);}return c}estimateIndexSize(e){let t=this.indexer.getIndexMap(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}};export{v as a,I as b};
@@ -38,11 +38,8 @@ declare class FilterEngine<T extends CollectionItem> {
38
38
  * Creates a new FilterEngine with optional data and fields to index.
39
39
  */
40
40
  constructor(options?: FilterEngineOptions<T>);
41
- private rebuildConfiguredIndexes;
42
- /**
43
- * Builds an index for the given field.
44
- */
45
- private buildIndex;
41
+ private ensureConfiguredFieldIndex;
42
+ private ensureIndexesForCriteria;
46
43
  clearIndexes(): this;
47
44
  resetFilterState(): this;
48
45
  clearData(): this;
@@ -1 +1 @@
1
- export{b as FilterEngine}from'../chunk-5B7Y4C22.mjs';
1
+ export{b as FilterEngine}from'../chunk-RIPRMLMT.mjs';
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- export{a as MergeEngines}from'./chunk-LKNVBEFD.mjs';export{a as TextSearchEngine}from'./chunk-4PTQMQ73.mjs';export{b as FilterEngine}from'./chunk-5B7Y4C22.mjs';export{a as SortEngine}from'./chunk-IYELLKOW.mjs';
1
+ export{a as MergeEngines}from'./chunk-OJWACBNG.mjs';export{a as TextSearchEngine}from'./chunk-PLHHLXUH.mjs';export{b as FilterEngine}from'./chunk-RIPRMLMT.mjs';export{a as SortEngine}from'./chunk-7RNFZK7U.mjs';
@@ -1 +1 @@
1
- export{a as MergeEngines}from'../chunk-LKNVBEFD.mjs';import'../chunk-4PTQMQ73.mjs';import'../chunk-5B7Y4C22.mjs';import'../chunk-IYELLKOW.mjs';
1
+ export{a as MergeEngines}from'../chunk-OJWACBNG.mjs';import'../chunk-PLHHLXUH.mjs';import'../chunk-RIPRMLMT.mjs';import'../chunk-7RNFZK7U.mjs';
@@ -24,7 +24,10 @@ declare class TextSearchEngine<T extends CollectionItem> {
24
24
  * Creates a new TextSearchEngine with optional data and fields to index.
25
25
  */
26
26
  constructor(options?: TextSearchEngineOptions<T>);
27
- private rebuildConfiguredIndexes;
27
+ private ensureConfiguredFieldIndex;
28
+ private ensureConfiguredIndexes;
29
+ private ensureConfiguredNestedIndex;
30
+ private ensureConfiguredNestedIndexes;
28
31
  /**
29
32
  * Builds an n-gram index for the given field.
30
33
  */
@@ -1 +1 @@
1
- export{a as TextSearchEngine}from'../chunk-4PTQMQ73.mjs';
1
+ export{a as TextSearchEngine}from'../chunk-PLHHLXUH.mjs';
@@ -19,7 +19,7 @@ declare class SortEngine<T extends CollectionItem> {
19
19
  * Creates a new SortEngine with optional data and fields to index.
20
20
  */
21
21
  constructor(options?: SortEngineOptions<T>);
22
- private rebuildConfiguredIndexes;
22
+ private ensureConfiguredIndex;
23
23
  /**
24
24
  * Builds an index for sorting the given field.
25
25
  */
@@ -1 +1 @@
1
- export{a as SortEngine}from'../chunk-IYELLKOW.mjs';
1
+ export{a as SortEngine}from'../chunk-7RNFZK7U.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devisfuture/mega-collection",
3
- "version": "2.0.3",
3
+ "version": "2.1.3",
4
4
  "description": "High-performance search, filter & sort engine for 100K+ item collections in JavaScript/TypeScript",
5
5
  "exports": {
6
6
  ".": {
@@ -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. Either pass `data` in the constructor options, or call buildIndex(data, field).")}};function T(u){let e=u.toLowerCase(),t=Math.min(3,e.length),s=e.length-t+1,n=new Array(s);for(let i=0;i<s;i++)n[i]=e.substring(i,i+t);return n}function 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 C=class{constructor(){this.indexes=new Map;}buildIndex(e,t){let n=new Map;for(let s=0,r=e.length;s<r;s++){let i=e[s],l=i[t];if(l==null)continue;let a=n.get(l);a?a.push(i):n.set(l,[i]);}this.indexes.set(t,n);}getByValue(e,t){let n=this.indexes.get(e);return n?n.get(t)??[]:[]}getByValues(e,t){let n=this.indexes.get(e);if(!n)return [];if(t.length===1)return n.get(t[0])??[];let s=new Set,r=[];for(let i=0;i<t.length;i++){let l=n.get(t[i]);if(l!==void 0)for(let a=0;a<l.length;a++){let u=l[a];s.has(u)||(s.add(u),r.push(u));}}return r}hasIndex(e){return this.indexes.has(e)}clear(){this.indexes.clear();}getIndexMap(e){return this.indexes.get(e)}};var v=class{constructor(e){this.callbacks=e;}create(e){let t=e;return Object.defineProperty(t,"filter",{value:(n,s)=>s===void 0?this.callbacks.filter(e,n):this.callbacks.filter(n,s),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearIndexes",{value:()=>this.callbacks.clearIndexes(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"data",{value:n=>this.callbacks.data(n),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"getOriginData",{value:()=>this.callbacks.getOriginData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"clearData",{value:()=>this.callbacks.clearData(),enumerable:false,configurable:true,writable:true}),Object.defineProperty(t,"resetFilterState",{value:()=>this.callbacks.resetFilterState(),enumerable:false,configurable:true,writable:true}),t}};var T=class p extends Error{constructor(e){super(e),this.name="FilterEngineError";}static missingDatasetForBuildIndex(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForFilter(){return new p("FilterEngine: no dataset in memory. Either pass `data` in the constructor options, or call filter(data, criteria).")}};var x=Symbol("FilterEngine.execute");var F=class{constructor(){this.registeredFields=new Set;this.fieldDescriptors=new Map;this.indexes=new Map;}registerFields(e){if(e?.length)for(let t=0;t<e.length;t++)this.registerField(e[t]);}hasRegisteredFields(){return this.registeredFields.size>0}hasField(e){return this.registeredFields.has(e)}clearIndexes(){this.indexes.clear();}buildIndexes(e){this.indexes.clear();for(let t of this.registeredFields)this.buildIndex(e,t);}filter(e,t,n){if(e.length===0||t.length===0)return e;let s=[],r=[];for(let a=0;a<t.length;a++){let u=t[a];if(this.indexes.has(u.field)){s.push(u);continue}r.push(u);}let i=e,l=e===n?null:new Set(e);if(s.length>0&&(i=this.filterByIndexes(s,l),i.length===0))return i;for(let a=0;a<r.length;a++)if(i=this.filterLinearly(i,r[a]),i.length===0)return i;return i}registerField(e){let t=this.createDescriptor(e);t&&(this.registeredFields.add(e),this.fieldDescriptors.set(e,t));}createDescriptor(e){let t=e.indexOf(".");return t===-1?null:{collectionKey:e.substring(0,t),nestedKey:e.substring(t+1)}}buildIndex(e,t){let n=this.fieldDescriptors.get(t);if(!n)return;let{collectionKey:s,nestedKey:r}=n,i=new Map;for(let l=0,a=e.length;l<a;l++){let u=e[l],h=u[s];if(Array.isArray(h))for(let c=0;c<h.length;c++){let o=h[c][r];if(o==null)continue;let d=i.get(o);if(d){d[d.length-1]!==u&&d.push(u);continue}i.set(o,[u]);}}this.indexes.set(t,i);}filterByIndexes(e,t){if(e.length===1){let i=this.indexes.get(e[0].field);if(!i)return [];let l=this.getItemsByValues(i,e[0].values);if(l.length===0)return [];if(t===null)return l;let a=[];for(let u=0;u<l.length;u++){let h=l[u];t.has(h)&&a.push(h);}return a}let n=e.map(i=>({criterion:i,size:this.estimateIndexSize(i)})).sort((i,l)=>i.size-l.size),s=t,r=[];for(let i=0;i<n.length;i++){let{criterion:l}=n[i],a=this.indexes.get(l.field);if(!a)return [];let u=this.getItemsByValues(a,l.values);if(u.length===0)return [];if(s===null)r=u;else {r=[];for(let h=0;h<u.length;h++){let c=u[h];s.has(c)&&r.push(c);}}if(r.length===0)return [];s=new Set(r);}return r}getItemsByValues(e,t){if(t.length===1)return e.get(t[0])??[];let n=new Set,s=[];for(let r=0;r<t.length;r++){let i=e.get(t[r]);if(i)for(let l=0;l<i.length;l++){let a=i[l];n.has(a)||(n.add(a),s.push(a));}}return s}estimateIndexSize(e){let t=this.indexes.get(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}filterLinearly(e,t){let n=this.fieldDescriptors.get(t.field);if(!n)return e;let{collectionKey:s,nestedKey:r}=n,i=new Set(t.values),l=[];for(let a=0;a<e.length;a++){let u=e[a],h=u[s];if(!Array.isArray(h))continue;let c=false;for(let o=0;o<h.length;o++)if(i.has(h[o][r])){c=true;break}c&&l.push(u);}return l}};var y=class{constructor(e={}){this.dataset=[];this.indexedFields=new Set;this.nestedCollection=new F;this.previousResult=null;this.previousCriteria=null;this.previousBaseData=null;this.chainBuilder=new v({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.nestedCollection.registerFields(e.nestedFields),!e.data)return;this.dataset=e.data;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 T.missingDatasetForBuildIndex();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,t),this}clearIndexes(){return this.indexer.clear(),this.nestedCollection.clearIndexes(),this}resetFilterState(){return this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null,this}clearData(){return this.dataset=[],this.indexer.clear(),this.nestedCollection.clearIndexes(),this.resetFilterState(),this}data(e){return this.dataset=e,this.resetFilterState(),this.rebuildConfiguredIndexes(),this}getOriginData(){return this.dataset}filter(e,t){return t===void 0?this.withChain(this[x](e)):this.withChain(this[x](e,t))}[x](e,t){let n=t===void 0,s,r,i;if(n){if(!this.dataset.length)throw T.missingDatasetForFilter();if(r=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===this.dataset){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):(s=this.dataset,i=r);}else s=this.dataset,i=r;}else if(r=t,s=e,this.filterByPreviousResult&&this.previousResult!==null&&this.previousCriteria!==null&&this.previousBaseData===s){let o=this.hasCriteriaAdditions(this.previousCriteria,r),d=this.hasCriteriaRemovals(this.previousCriteria,r);if(!o&&!d)return this.previousResult;o&&!d?(s=this.previousResult,i=this.getAddedCriteria(this.previousCriteria,r)):i=r;}else i=r;if(r.length===0)return this.filterByPreviousResult&&(this.previousResult=null,this.previousCriteria=null,this.previousBaseData=null),n?this.dataset:s;n&&!i&&(i=r);let l=[],a=[];for(let o=0;o<i.length;o++){let d=i[o];this.nestedCollection.hasField(d.field)?l.push(d):a.push(d);}if(l.length>0&&(s=this.nestedCollection.filter(s,l,this.dataset),s.length===0)){let o=[];return this.filterByPreviousResult&&(this.previousResult=o,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),o}if(a.length===0)return this.filterByPreviousResult&&(this.previousResult=s,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),s;let{indexedCriteria:u,linearCriteria:h}=a.reduce((o,d)=>(this.indexer.hasIndex(d.field)?o.indexedCriteria.push(d):o.linearCriteria.push(d),o),{indexedCriteria:[],linearCriteria:[]}),c;if(u.length>0&&h.length===0)return c=this.filterViaIndex(u,s),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c;if(u.length>0&&h.length>0){let o=this.filterViaIndex(u,s);return c=this.linearFilter(o,h),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}return c=this.linearFilter(s,a),this.filterByPreviousResult&&(this.previousResult=c,this.previousCriteria=this.cloneCriteria(r),this.previousBaseData=n?this.dataset:e),c}withChain(e){return this.chainBuilder.create(e)}cloneCriteria(e){return e.map(({field:t,values:n})=>({field:t,values:[...n]}))}hasCriteriaAdditions(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of s){let l=n.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}hasCriteriaRemovals(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=new Map(t.map(({field:r,values:i})=>[r,new Set(i)]));for(let[r,i]of n){let l=s.get(r);if(!l)return true;for(let a of i)if(!l.has(a))return true}return false}getAddedCriteria(e,t){let n=new Map(e.map(({field:r,values:i})=>[r,new Set(i)])),s=[];for(let{field:r,values:i}of t){let l=n.get(r);if(!l){s.push({field:r,values:[...i]});continue}let a=i.filter(u=>!l.has(u));a.length>0&&s.push({field:r,values:a});}return s}linearFilter(e,t){let n=new Map(t.map(({field:i,values:l})=>[i,new Set(l)])),s=t.map(({field:i})=>i),r=[];for(let i=0;i<e.length;i++){let l=e[i],a=true;for(let u=0;u<s.length;u++){let h=s[u];if(!n.get(h).has(l[h])){a=false;break}}a&&r.push(l);}return r}filterViaIndex(e,t){let s=t!==this.dataset?new Set(t):null;if(e.length===1){let o=this.indexer.getByValues(e[0].field,e[0].values);if(!s)return o.slice();let d=[];for(let f=0;f<o.length;f++){let g=o[f];s.has(g)&&d.push(g);}return d}let r=e.map(o=>({criterion:o,size:this.estimateIndexSize(o)})).sort((o,d)=>o.size-d.size),{field:i,values:l}=r[0].criterion,a=this.indexer.getByValues(i,l);if(a.length===0)return [];let u=new Map(r.slice(1).map(({criterion:{field:o,values:d}})=>[o,new Set(d)])),h=Array.from(u.keys()),c=[];for(let o=0;o<a.length;o++){let d=a[o],f=true;for(let g=0;g<h.length;g++){let m=h[g];if(!u.get(m).has(d[m])){f=false;break}}f&&s&&!s.has(d)&&(f=false),f&&c.push(d);}return c}estimateIndexSize(e){let t=this.indexer.getIndexMap(e.field);return t?e.values.reduce((n,s)=>{let r=t.get(s);return r?n+r.length:n},0):1/0}};export{x as a,y as b};
@@ -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. Either pass `data` in the constructor options, or call buildIndex(data, field).")}static missingDatasetForSort(){return new f("SortEngine: no dataset in memory. Either pass `data` in the constructor options, or call sort(data, descriptors).")}};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 d,t;if(Array.isArray(r))d=r,t=a;else {if(!this.dataset.length)throw u.missingDatasetForBuildIndex();d=this.dataset,t=r;}this.dataset=d;let e=d.length,s=new Uint32Array(e),n=new Array(e);for(let o=0;o<e;o++)s[o]=o,n[o]=d[o][t];if(typeof n[0]=="number"){let o=new Float64Array(e);for(let l=0;l<e;l++)o[l]=n[l];s.sort((l,c)=>o[l]-o[c]);}else s.sort((o,l)=>{let c=n[o],h=n[l];return c<h?-1:c>h?1:0});return this.cache.set(t,{indexes:s,dataRef:d,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,d=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:l}=e[0],c=this.cache.get(o);if(s&&c?.dataRef===t&&c.itemCount===t.length)return this.reconstructFromIndex(t,c.indexes,l)}let n=d?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,d){let t=r.length,e=new Array(t);if(d==="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),d=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 -d[n];if(i>o)return d[n]}return 0}}radixSortNumeric(r,a,d){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(d==="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};