import{AbstractSublevel}from"abstract-level";import{filterObject,getType,mergeObject,randomID}from"../../../common/utils/helpers.mjs";export default class SublevelDatabase extends AbstractSublevel{async createNewId(){for(;;){const e=randomID(16);if(!await this.has(e))return e}}async get(e,t={}){if(e)return super.get(e,t)}prefixKey(e,t="utf8"){return super.prefixKey(e,t)}async put(e,t,r={}){return await super.put(e,t,r),t}async has(e){const t=this.keys({gte:e,lte:e,limit:1,fillCache:!1}),r=await t.next();return await t.close(),!!r}async delMany(e=[]){const t=await this.getMany(e,{fillCache:!1}),r=this.batch();for(const[a,s]of t.entries()){const t=e[a];s&&r.del(t)}return await r.write(),t}async find(e,{project:t,map:r,sort:a}={}){e=SublevelDatabase.#e(e);const s=[],i=await this.values({fillCache:!1}).all();for(let a of i)SublevelDatabase.#t(a,e)&&(t&&(a=filterObject(a,t)),r&&(a=await r(a)),s.push(a));return a&&("string"==typeof a&&(a={[a]:1}),s.sort(((e,t)=>SublevelDatabase.#r(e,t,a)))),s}async findOne(e,t){const r=await this.find(e,t);if(r.length)return r.length>1&&global.logger.warn(`Multiple results found for query "${JSON.stringify(e)}"`),r[0]}async findUpdate(e,t){e=SublevelDatabase.#e(e);const r=this.batch(),a=[];for(const[s,i]of await this.iterator({fillCache:!1}).all())SublevelDatabase.#t(i,e)&&(mergeObject(i,t),r.put(s,i),a.push(i));return await r.write(),a}async findDelete(e){e=SublevelDatabase.#e(e);const t=this.batch(),r=[];for(const[a,s]of await this.iterator({fillCache:!1}).all())SublevelDatabase.#t(s,e)&&(t.del(a),r.push(s));return await t.write(),r}static#r(e,t,r={}){for(const[a,s]of Object.entries(r)){const r=e[a],i=t[a];let n=0;if("string"==typeof r?n=r.compare(i)*s:"number"==typeof i&&(n=(r-i)*s),0!==n)return n}return 0}static#e(e){if(!e)return;const t=/^([A-z]+)__([a-z]+)$/;for(const[r,a]of Object.entries(e)){const s=r.match(t);if(s){const[t,i,n]=s;switch(delete e[r],n){case"in":e[i]=new QueryOperation(i,a,QueryOperation.matchInArray);break;case"ne":e[i]=new QueryOperation(i,a,QueryOperation.matchNotEqual)}}else"Object"===getType(a)&&SublevelDatabase.#e(a)}return e}static#t(e,t){if(!t)return!0;for(const[r,a]of Object.entries(t)){const t=e[r];if(a instanceof QueryOperation){if(!a.test(t))return!1}else if("Object"===getType(a)){if(!SublevelDatabase.#t(t,a))return!1}else if(t!==a)return!1}return!0}static#a(e,t){if(!Array.isArray(t))throw new Error("You must provide an array of target values when querying field__in");return t.includes(e)}}class QueryOperation{constructor(e,t,r){Object.defineProperties(this,{key:{value:e,writable:!1},target:{value:t,writable:!1},comparator:{value:r,writable:!1}})}test(e){return this.comparator(e,this.target)}static matchInArray(e,t){if(!Array.isArray(t))throw new Error("You must provide an array of target values when querying field__in");return t.includes(e)}static matchNotEqual(e,t){return e!==t}}