gs-idb-pro
Version:
> A full-featured wrapper for browser IndexedDB
2 lines (1 loc) • 29.2 kB
JavaScript
import{copyFields as e,isFunction as t,isObject as r,deepFreeze as a,isNumber as n,asyncMap as i,isString as s,asyncForEach as o,isBoolean as c,destroyRecords as u,destroy as d,logJson as h,toJson as m,copyObject as l}from"gs-base";import{isDbQueryOrNull as f,requestDbResult as y,findExistDb as p,openDb as g,readTx as w,DefaultDbName as S,DefaultStorageStoreName as b}from"gs-idb-basic";const x=Symbol("save"),v=Symbol("delete"),k=Object.freeze({key:({primaryKey:e})=>({value:e}),value:({value:e})=>({value:e}),keyValue:({primaryKey:e,value:t})=>({value:[e,t]})});function P(e){if(Array.isArray(e))return{key:e[1],value:e[0]};if("value"in e){const{key:t,value:r}=e;return{key:t,value:r}}throw new Error(`not include value in invalid DBRecord:${JSON.stringify(e)}`)}const D=Symbol("break"),I=Symbol("finished"),O=Symbol("continue"),M=Symbol("continue key"),q=Symbol("next key"),E=Symbol("continue primary key"),j=Symbol("next primary key");function F(e){return e instanceof IDBObjectStore||e instanceof IDBIndex}const R=Object.freeze({keyPath:"id",autoIncrement:!0,addedTimeField:!0,updatedTimeField:!0}),$=Object.freeze({addedTimeField:"added_at",softDeletedField:"deleted",updatedCountField:"updated_count",updatedTimeField:"updated_at"}),B=e=>e instanceof Date?e.getTime():e;function C(e){if(f(e))return e;const t=e;if("lt"in t&&"gt"in t){if(B(t.gt)>B(t.lt))throw new Error(`Invalid IDBRange: gt (${t.gt}) cannot be greater than lt (${t.lt})`);return IDBKeyRange.bound(t.gt,t.lt,!0,!0)}if("lt"in t&&"gte"in t){if(B(t.gte)>B(t.lt))throw new Error(`Invalid IDBRange: gte (${t.gte}) cannot be greater than lt (${t.lt})`);return IDBKeyRange.bound(t.gte,t.lt,!1,!0)}if("lte"in t&&"gt"in t){if(B(t.gt)>B(t.lte))throw new Error(`Invalid IDBRange: gt (${t.gt}) cannot be greater than lte (${t.lte})`);return IDBKeyRange.bound(t.gt,t.lte,!0,!1)}if("lte"in t&&"gte"in t){if(B(t.gte)>B(t.lte))throw new Error(`Invalid IDBRange: gte (${t.gte}) cannot be greater than lte (${t.lte})`);return IDBKeyRange.bound(t.gte,t.lte,!1,!1)}return"lt"in t?IDBKeyRange.upperBound(t.lt,!0):"lte"in t?IDBKeyRange.upperBound(t.lte,!1):"gt"in t?IDBKeyRange.lowerBound(t.gt,!0):"gte"in t?IDBKeyRange.lowerBound(t.gte,!1):void 0}function A(e){return null!=C(e)}async function N(e,t,r){const{query:a,direction:n="prev",preSkip:i,startKey:s,startPrimaryKey:o}=t,c=e.openCursor(C(a),n);return i&&(await y(c)).advance(i),s&&(o?(await y(c)).continuePrimaryKey(s,o):(await y(c)).continue(s)),c}function K(r,a,n){return Array.isArray(r)?t=>e({},t,r):t(r)?r:a?e=>e:n?(e,t)=>[e,t]:(e,t)=>({key:e,value:t})}class T{idbPro;target;#e;constructor(e,t){this.idbPro=t,this.#e=e.storeSchema,this.target=e.target,F(e.target)&&(this.tx=this.#t)}get storeName(){return this.nativeStore?.name||this.target.store}get storeSchema(){if(this.#e)return this.#e;const e=this.idbPro.getStoreSchema(this.storeName);return Object.isFrozen(e)&&(this.#e=e),e}get factory(){return this.idbPro.factory}get nativeStore(){const{target:e}=this;return e instanceof IDBObjectStore?e:e instanceof IDBIndex?e.objectStore:void 0}get keyPath(){const{target:e}=this;if(F(e))return e.keyPath;const{storeSchema:t}=this,{index:r}=e;return r?t.indexSchemas.find(e=>e.name===r)?.keyPath:t.keyPath}async forEach(e,r){return e=t(e)?{fn:e}:e,r?this.cursorResult(e,!1):this.cursorVoid(e,!1)}async tx(e,t,r){let{target:a}=this;const{store:n,index:i}=a,s=await this.idbPro.openNativeDb();let o,c;try{o=s.transaction(n,!0===e?"readwrite":"readonly"),a=c=o.objectStore(n),i&&(a=a.index(i))}catch(e){throw s.close(),e}if(!t)return Object.freeze({db:s,tx:o,nativeStore:c,target:a});try{if(!0===e){const e=await t(a,c);return o.commit(),e}return t(a)}catch(e){throw!1!==r&&o.abort(),e}finally{s.close()}}openCursor(e,t){return this.tx(t,t=>new Promise(async(r,a)=>{const{fn:n}=e,i=await N(t,e);i.onsuccess=async()=>{i.result?!1===await n(i.result)&&r():r()},i.onerror=()=>a(i.error)}))}cursorVoid({query:e,direction:t,preSkip:a,startKey:n,startPrimaryKey:i,fn:s},o){let c=0;return this.openCursor({query:e,direction:t,preSkip:a,startKey:n,startPrimaryKey:i,fn:async e=>{const{value:t,primaryKey:a}=e,n=await s(t,a,c++),{control:i,key:u,primaryKey:d,modify:h,value:m}=r(n)?n:{control:n};switch(o&&(h===x?e.update(m||t):h===v&&e.delete()),i){case D:return!1;case M:e.continue(u);break;case E:e.continuePrimaryKey(u,d);break;default:e.continue()}}},!0)}async cursorResult({query:e,direction:t,preSkip:r,startKey:a,startPrimaryKey:n,fn:i,mapper:s},o){const{keyPath:c,defaultGetMapper:u}=this.storeSchema,d=K(s||u,c),h=[];let m=0;return await this.openCursor({query:e,direction:t,preSkip:r,startKey:a,startPrimaryKey:n,fn:async e=>{const{value:t,primaryKey:r}=e,{control:a,value:n,key:s,primaryKey:c,modify:u}=await(i?.(t,r,m,h))||{};switch(o&&(u===x?e.update(n||t):u===v&&e.delete()),(!a||a===I||a===q||a===j)&&h.push(d(n||t,c||r,m)),a){case D:case I:return!1;case q:case M:e.continue(s);break;case j:case E:e.continuePrimaryKey(s,c);break;default:e.continue()}m++}},o),h}#t(e,t){const{target:r}=this,a=r instanceof IDBObjectStore?r:r.objectStore;return t?t(r,a):Object.freeze({nativeStore:a,target:r})}}class V{idbPro;schemas;#r;constructor(e,t){this.idbPro=e,this.schemas=t}get storeNames(){return this.#r||(this.#r=Array.from(new Set(this.schemas.map(e=>e.target.store))))}read(e){return this.tx("newReader",e)}write(e,t=!0){return this.tx("newWriter",e,!0,t)}export(){return this.tx("newReader",async(...e)=>{const t={};for(const r of e)t[r.storeName]=await r.export();return t})}import(e,t,r){return r||(r="addOrChangeMany"),this.tx("newWriter",async(...a)=>{const n={};a=Array.from(new Map(a.map(e=>[e.storeName,e.asStore(!0)])).values());for(const i of a){const{storeName:a}=i,s=e[a];s&&(n[a]=await i[r](s,t))}if(t)return n},!0)}async tx(e,t,r,a){const{idbPro:n,schemas:i}=this,{factory:s}=n.schema,o=await n.openNativeDb();try{const c=o.transaction(this.storeNames,r?"readwrite":"readonly");try{const a=i.map(({storeSchema:t,target:r})=>{let a=c.objectStore(r.store);return r.index&&(a=a.index(r.index)),s[e]({storeSchema:t,target:a},n)});if(r){const e=await t(...a);return c.commit(),e}return await t(...a)}catch(e){throw!1!==a&&c.abort(),e}}finally{o.close()}}}class W extends T{direction;query;writable;parser;endsWithNull;preSkip;startKey;startPrimaryKey;constructor(e,r,a){if(super(e,r),!a)return;const{parser:n}=a;this.direction=a.direction,this.query=a.query,this.writable=!!a.writable,this.endsWithNull=!!a.endsWithNull,this.preSkip=a.preSkip,this.startKey=a.startKey,this.startPrimaryKey=a.startPrimaryKey,n&&(this.parser=t(n)?n:k[n])}async*[Symbol.asyncIterator](){const{parser:e,writable:t,endsWithNull:r}=this,{db:a,tx:n,target:i}=await this.tx(t);try{const a=await N(i,this);let s;if(e)for(;s=await y(a);){const{control:t,value:r}=await e(s);if(t||(yield r),t===D)break;s.continue()}else{let e=!1;const t=()=>{e=!0};for(;!e&&(s=await y(a));)yield{cursor:s,end:t}}t&&n?.commit(),r&&!s&&(yield null)}finally{a?.close()}}}function z(e,a,n,i){const s=r(e)?e:{};return t(e)?s.fn=e:A(e)&&(s.query=e),t(a)?s.fn=a:a&&(s.direction=a),n&&(s.direction=n),i?s.limit=i:s.limit||(s.limit=1e3),s.maxEmptyChecks||(s.maxEmptyChecks=2e4),s}async function _(e,t,r){t.size||(t.size=100),t.nextSkip||(t.nextSkip=0);const{query:n,direction:i,total:s,maxEmptyChecks:o,fn:c}=t;return await e.batchRead(async e=>(s||(t.total=await e.count({query:n,direction:i,maxEmptyChecks:o,fn:c}),t.pages=Math.ceil(t.total/t.size)),t.total<1?{info:a(t),rows:[]}:c?await async function(e,t,r){t.maxEmptyChecks||(t.maxEmptyChecks=2e4);const{page:a,query:n,direction:i,nextSkip:s}=t,{keyPath:o}=e.storeSchema;return 1===a?await U(e,await N(e.target,{query:n,direction:i}),t,o):r&&s&&a-r.page===1?await U(e,await N(e.target,{query:n,direction:i,preSkip:s}),t,o):await U(e,await N(e.target,{query:n,direction:i}),t,o,!0)}(e,t,r):await async function(e,t){const{keyPath:r}=e.storeSchema,{page:n,query:i,direction:s,size:o,mapper:c}=t,u=(n-1)*o,d=await e.filter({query:i,preSkip:u,direction:s,limit:o,mapper:K(c,r,!0)});return t.nextSkip=u+d.length,{info:a(t),rows:d}}(e,t)))}async function U({storeSchema:{defaultGetMapper:e}},t,r,n,i){const{page:s,size:o,total:c,maxEmptyChecks:u,fn:d}=r,h=K(r.mapper||e,n,!0),m=[],l=(s-1)*r.size;if(l>=c)return{info:a(r),rows:[]};let f=0;return await new Promise(async(e,r)=>{let a=0,n=0;const s=async()=>{const{result:r}=t;if(!r)return e();let{value:n,primaryKey:i}=r;if(await d(n,i,f)?(a=0,m.push(h(n,i,f))):a++,m.length>=o||a>=u)return e();f++,r.continue()};t.onerror=()=>r(t.error),t.onsuccess=i?async()=>{const{result:r}=t;if(!r)return e();let{value:i,primaryKey:o}=r;if(await d(i,o,f)?(a=0,n++):a++,n>=l||a>=u)return f=a=0,t.onsuccess=s,void r.continue();r.continue(),f++}:s}),f&&(r.nextSkip+=f+1),{info:a(r),rows:m}}class G extends T{all(e,t){const a={};return n(t)&&(a.limit=t),A(e)?a.query=e:r(e)&&Object.assign(a,e),this.tx(!1,e=>y(e.getAll(C(a.query),a.limit||1e3)))}async count(e,t,r){const a=z(e,t,r),{query:n,direction:i,fn:s}=a;if(!s)return await this.tx(!1,e=>y(e.count(C(n))));const{maxEmptyChecks:o}=a,c=s;let u=0,d=0,h=0;return await this.openCursor({query:n,direction:i,fn:e=>{if(c(e.value,e.primaryKey,h++))u++,d=0;else if(++d>=o)return!1;e.continue()}}),u}get(e){return this.tx(!1,t=>y(t.get(C(e))))}getMany(e,t){return this.batchRead(async r=>{const a=await i(e,e=>r.get(e));return t?a.filter(e=>e):a})}getRange(e,t){return this.forEach({query:e,direction:t},!0)}async getRangeMany(e,t,r){return(await this.batchRead(r=>i(e,e=>r.getRange(e,t)))).flat()}index(e,t){let{target:r}=this;return r instanceof IDBIndex&&(r=r.objectStore),r instanceof IDBObjectStore?(r=r.index(e),this.createOperator(r,t)):this.idbPro.store(r.store,e)}asStore(e){let{target:t}=this;if(t instanceof IDBObjectStore)return this;if(t instanceof IDBIndex)t=t.objectStore;else{if(!("index"in t))return this;t={store:t.store}}return this.createOperator(t,e)}batchRead(e){return F(this.target)?e(this):this.tx(!1,t=>e(this.idbPro.schema.factory.newReader({storeSchema:this.storeSchema,target:t},this.idbPro)))}iterator(e,t){const a={};return s(t)&&(a.direction=t),A(e)?a.query=e:r(e)&&Object.assign(a,e),new W({storeSchema:this.storeSchema,target:this.target},this.idbPro,{...a,parser:"value"})}async filter(e,t,r,a){const n=z(e,t,r,a),{maxEmptyChecks:i,limit:s,fn:o}=n,{keyPath:c,defaultGetMapper:u}=this.storeSchema,d=K(n.mapper||u,c,!0);if(!o)return await this.forEach({...n,mapper:d,fn:(e,t,r)=>{if(r>=s-1)return{control:I}}},!0);let h=0;return this.forEach({...n,mapper:d,fn:(e,t,r,a)=>o(e,t,r)?(h=0,a.length>=s-1?{control:I}:void 0):++h>=i?{control:D}:{control:O}},!0)}async find(e,t,r){const[a]=await this.filter(e,t,r,1);return a}async page(e,t){const r={...e};return r.page=t||e?.page||1,_(this,r,e)}nextPage(e){return this.page(e,e.page+1)}export(e,t){const r=z(e,t),{keyPath:a,exportMapper:n,name:i,defaultGetMapper:s}=this.storeSchema;if(!a&&Array.isArray(n))throw new Error(`When store [ ${i} ] keyPath does not exist, exportMapper does not support string[].`);return r.direction="next",r.mapper=K(n||s,a,!0),r.limit=r.maxEmptyChecks=Number.MAX_SAFE_INTEGER,this.filter(r)}asMap(){let{target:e}=this;return e instanceof IDBIndex?e=e.objectStore:e instanceof IDBObjectStore||(e={store:e.store}),this.factory.newDbMap({target:e},this.idbPro)}createOperator(e,t){const{idbPro:r}=this,a=this.storeSchema,n={storeSchema:Object.isFrozen(a)?a:void 0,target:e};return t?this.factory.newWriter(n,r):this.factory.newReader(n,r)}}function J(e,t){if(!Array.isArray(e))return{[e]:t};const r={},a=e;for(let e=0;e<a.length;e++)r[a[e]]=t[e];return r}function L(e,t){if(!Array.isArray(e))return t[e];const r=[];for(const a of e){if(!t[a])return;r.push(t[a])}return r}function X(e,t){if(!t||!(t instanceof Object)||Array.isArray(t))return t;const{addedTimeField:r,updatedTimeField:a,updatedCountField:i,softDeletedField:s}=e;return t={...t},r?.name&&!n(t[r.name])&&(t[r.name]=Date.now()),a?.name&&!n(t[a.name])&&(t[a.name]=Date.now()),s?.name&&!n(t[s.name])&&(t[s.name]=0),i?.name&&(t[i.name]=0),t}function H(e,t,r){if(!t||!(t instanceof Object)||Array.isArray(t))return t;const{updatedTimeField:a,updatedCountField:n}=e;return t={...r,...t},a.name&&(t[a.name]=Date.now()),n.name&&(t[n.name]=(t[n.name]||0)+1),t}class Q extends G{add(e){return this.changeByPk({record:e,fn:async(e,t,r,a,n)=>{const{storeSchema:i}=this;return r=X(i,r),n?[{...r,...J(n,await y(e.add(r)))},t]:[r,await y(e.add(r,t))]}})}addMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.add(e)):o(e,e=>r.add(e)),!0)}addOrSkip(e){return this.batchWrite(async t=>{const{keyPath:r,defaultGetMapper:a}=t.storeSchema,{key:n,value:i}=r?{key:L(r,e),value:e}:P(e);if(n){const e=await y(t.nativeStore.get(n));if(e)return K(a,r)?.(e,n)}if(t.target instanceof IDBIndex){const{keyPath:r}=t,a=L(r,i);if(!a)return t.add(e);let n=await t.find(a);if(n)return n}return t.add(e)})}addOrSkipMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.addOrSkip(e)):o(e,e=>r.addOrSkip(e)),!0)}replace(e){return this.changeByPk({record:e,getOld:!0,fn:async(e,t,r,a,n)=>{const{storeSchema:i}=this,{updatedTimeField:s,updatedCountField:o,addedTimeField:c}=i;return r=a?H(i,r,{[s.name]:a[s.name],[o.name]:a[o.name],[c.name]:a[c.name]}):X(i,r),n?[{...r,...J(n,await y(e.put(r)))},t]:[r,await y(e.put(r,t))]}})}replaceMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.replace(e)):o(e,e=>r.replace(e)),!0)}change(e,t){return this.changeByPk({record:e,getOld:!0,requiredOld:t,requiredPk:t,fn:async(e,t,r,a,n)=>{const{storeSchema:i}=this;if(a)return r=H(i,r,a),n?[{...r,...J(n,await y(e.put(r)))},t]:[r,await y(e.put(r,t))]}})}changeMany(e,t){const{returns:r,throwIfMissing:a}=c(t)?{returns:t}:t||{};return this.batchWrite(t=>r?i(e,e=>t.change(e,a)):o(e,e=>t.change(e,a)),!0)}addOrChange(e){return this.changeByPk({record:e,getOld:!0,fn:async(e,t,r,a,n)=>{const{storeSchema:i}=this;return a?(r=H(i,r,a),n?[{...r,...J(n,await y(e.put(r)))},t]:[r,await y(e.put(r,t))]):(r=X(i,r),n?[{...r,...J(n,await y(e.add(r)))},t]:[r,await y(e.add(r,t))])}})}addOrChangeMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.addOrChange(e)):o(e,e=>r.addOrChange(e)),!0)}delete(e,t){return this.changeByPk({pk:e,getOld:t,fn:(e,r,a,n)=>{if(e.delete(r),t)return[n,r]}})}deleteMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.delete(e,!0)):o(e,e=>r.delete(e)),!0)}deleteRange(e,t){const{returns:r,physical:a,direction:n}=c(t)?{returns:t}:t||{},{name:i}=this.storeSchema.softDeletedField||{};return this.cursor({query:e,direction:n,fn:e=>a||!i?{modify:v}:(e[i]=1,{modify:x})},r)}deleteRangeMany(e,t){const r=c(t)?{returns:t}:t;return this.batchWrite(t=>r?.returns?i(e,e=>t.deleteRange(e,r)):o(e,e=>t.deleteRange(e,r)),!0)}changeRange(e,t){let{direction:r="next",query:a,newValue:n}="newValue"in e?e:{newValue:e};if(a||(a=L(this.keyPath,n)),!a)throw new Error(`query is required:${JSON.stringify(e)}`);return this.cursor({query:a,direction:r,fn:e=>e instanceof Object?{modify:x,value:{...e,...n}}:{modify:x,value:n}},t)}changeRangeMany(e,t){return this.batchWrite(r=>t?i(e,e=>r.changeRange(e,t)):o(e,e=>r.changeRange(e,t)),!0)}cursor(e,r){return(e=t(e)?{fn:e}:e||{}).fn?r?this.cursorResult(e,!0):this.cursorVoid(e,!0):new W(this,this.idbPro)}batchWrite(e,t){const{target:r}=this;if(F(r))try{return e(this)}catch(e){throw!1!==t&&(r instanceof IDBIndex?r.objectStore:r).transaction.abort(),e}return this.tx(!0,t=>e(this.idbPro.schema.factory.newWriter({storeSchema:this.storeSchema,target:t},this.idbPro)),t)}changeByPk({pk:e,record:t,fn:r,requiredPk:a,getOld:n,requiredOld:i,saveMapper:s,getMapper:o}){const{storeSchema:c}=this,{keyPath:u,defaultSaveMapper:d,defaultGetMapper:h}=c;return t&&(s||d)&&(t=K(s||d,u)?.(t)),this.batchWrite(async s=>{let c,d=t;if(e)c=C(e);else if(u)c=L(u,t);else{const{key:e,value:r}=P(t);c=e,d=r}if(a&&!c)throw new Error(`key is required: ${JSON.stringify(t)}`);const m=c&&(n||i)?await y(s.nativeStore.get(c)):void 0;if(i&&!m)throw new Error(`record not found: ${JSON.stringify(t)}`);const l=await r(s.nativeStore,c,d,m,u);if(l)return K(o||h,u)?.(l[0],l[1])})}}class Y extends T{get size(){return this.tx(!1,e=>y(e.count()))}delete(e){return this.tx(!0,async(t,r)=>{r.delete(e)})}batch(e){const{idbPro:t,storeSchema:r,factory:a}=this;return this.tx(!0,async(n,i)=>await e(a.newDbMap({storeSchema:r,target:i},t)))}asStore(e){const{factory:t}=this.idbPro.schema;return e?t.newWriter(this,this.idbPro):t.newReader({target:this.target},this.idbPro)}entries(){return new W({target:this.target},this.idbPro,{parser:"keyValue"})}async get(e,t){return await this.tx(!1,t=>y(t.get(e)))||t}getMany(e){return this.tx(!1,async t=>{const r=[];for(const a of e)r.push(await y(t.get(a)));return r})}async has(e){return!!await this.get(e)}keys(){return new W({storeSchema:this.storeSchema,target:this.target},this.idbPro,{parser:"key"})}set(e,t){return this.tx(!0,async(r,a)=>{await y(a.put(t,e))})}setMany(e){return this.tx(!0,async(t,r)=>{for(const[t,a]of e)r.put(a,t)})}values(){return new W({storeSchema:this.storeSchema,target:this.target},this.idbPro,{parser:"value"})}}function Z(e,t){if(e==t)return!0;if(typeof e!=typeof t)return!1;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}return!1}const ee=({stores:e,schema:t})=>{const r=t.storeSchemas;let a="";for(const t of e){const e=r.find(e=>e.name===t.name);if(e){if(!Z(t.keyPath,e.keyPath)){a=`store [ ${t.name} ] keyPath not equal,schema.keyPath:${e.keyPath},store.keyPath:${t.keyPath}[]`;break}if(!t.autoIncrement!=!e.autoIncrement){a=`store [ ${t.name} ] autoIncrement not equal`;break}}}return!a||`The existing database is inconsistent with the definition and cannot be corrected: ${a}`},te=async e=>{let t=ee(e);return s(t)||(t=re(e)),t},re=({stores:e,schema:t})=>{const r=t.storeSchemas,a=e.map(e=>e.name);let n="";const i=r.map(e=>e.name).filter(e=>!a.includes(e));if(i.length)n=`store [ ${i.join(",")} ] not exist`;else for(const t of e){const e=r.find(e=>e.name===t.name);if(e&&(n=ae(t,Array.from(t.indexNames),e.indexSchemas),n))break}return!n||`The existing database Store index is inconsistent with the definition and requires a database version upgrade to be fixed: ${n}`};function ae(e,t,r){if(t.length!==r.length)return`store [ ${e.name} ] index count not equal`;for(const a of t){const t=r.find(e=>e.name===a);if(!t)return`store [ ${e.name} ] index [ ${a} ] not exist`;const n=e.index(a);if(!t.unique!=!n.unique)return`store [ ${e.name} ] index [ ${a} ] unique not equal`;if(!t.multiEntry!=!n.multiEntry)return`store [ ${e.name} ] index [ ${a} ] multiEntry not equal`;if(!Z(t.keyPath,n.keyPath))return`store [ ${e.name} ] index [ ${a} ] keyPath not equal`}return""}class ne{upgradeContext;storeSchema;nativeStore;#a;constructor(e,t,r){this.upgradeContext=e,this.storeSchema=t,this.nativeStore=r}get writer(){return this.#a||(this.#a=this.upgradeContext.dbSchema.factory?.newWriter({target:this.nativeStore,storeSchema:this.storeSchema}))}add(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.addMany(t,r):Promise.resolve()}addOrChange(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.addOrChangeMany(t,r):Promise.resolve()}async call(e,t){if(this.upgradeContext.versionIn(e))return await t(this.writer,this.upgradeContext)}replace(e,t,r){return this.upgradeContext.versionIn(e)?this.writer.replaceMany(t,r):Promise.resolve()}}const ie=Object.freeze({newDataOperators:(e,t)=>new V(t,e),newDbMap:(e,t)=>new Y(e,t),newReader:(e,t)=>new G(e,t),newStoreUpgradeable:(e,t,r)=>new ne(r,t,e),newWriter:(e,t)=>new Q(e,t)});function se(e,t,a,n){const i=function(e,t,a){if(!1===e)return!1;if(s(e))return{name:e};if(r(e)){const r=e;return c(r.name)&&(r.name=t),e}if(!0===e||a)return{name:t};return!1}(t,a,n);if(!i)return i;const o=i;if(!1!==o.isIndexed){o.isIndexed||(o.isIndexed=!0);const{name:t}=o,r=e.indexSchemas;r.some(e=>e===t||e.name===t)||r.push(t)}return o}function oe(e,t){let r=s(e)?{name:e}:e;return t&&(r={...t,...r}),r.indexSchemas||(r.indexSchemas=[]),function(e){Object.isFrozen(e)||(e.addedTimeField=se(e,e.addedTimeField,"added_at",!0),e.updatedTimeField=se(e,e.updatedTimeField,"updated_at",!0),e.updatedCountField=se(e,e.updatedCountField,"updated_count",!1),e.softDeletedField=se(e,e.softDeletedField,"deleted",!1))}(r),Object.isFrozen(r)||(r.indexSchemas=r.indexSchemas.map(ce)),function(e){if(!e.keyPath&&e.defaultData?.length)for(const t of e.defaultData)if(!Array.isArray(t)&&!("value"in t))throw new Error(`When \`defaultData\` must contain \`value\` fields or be an array:${JSON.stringify(t)}`)}(r),r}function ce(e){const t=s(e)?{name:e}:e;return t.keyPath||(t.keyPath=t.name),t}const ue=e=>{const{versionDiffValidate:t,versionSameValidate:r,factory:a}=e;return e.storeSchemas||(e.storeSchemas=[]),e.storeTemplate||(e.storeTemplate={...R}),!t&&!1!==t&&(e.versionDiffValidate=ee),!r&&!1!==r&&(e.versionSameValidate=te),a?a!==ie&&(e.factory={...ie,...a}):e.factory=ie,e.storeSchemas=e.storeSchemas.map(t=>oe(t,e.storeTemplate)),e};function de(e,t){(function(e,t){return e.unique===t.unique&&e.multiEntry===t.multiEntry&&Z(t.keyPath,e.keyPath)})(e.index(t.name),t)||(e.deleteIndex(t.name),he(e,t))}function he(e,t){try{e.createIndex(t.name,t.keyPath,{unique:t.unique,multiEntry:t.multiEntry})}catch{throw new Error(`store [ ${e.name} ] index [ ${t.name} ] create error: ${JSON.stringify(t)}`)}}function me(e,t){return e.database.objectStoreNames.contains(t.name)?function(e,t){const{indexSchemas:r}=e,a=t.indexNames,n=r.map(e=>e.name);for(const e of Array.from(a))n.includes(e)||t.deleteIndex(e);for(const e of r)a.contains(e.name)?de(t,e):he(t,e);return t}(t,e.transaction?.objectStore(t.name)):function(e,t){const r=t.createObjectStore(e.name,{keyPath:e.keyPath,autoIncrement:e.autoIncrement});for(const t of e.indexSchemas)he(r,t);return r}(t,e.database)}class le{database;newVersion;oldVersion;dbSchema;transaction;#n={};constructor(e){this.database=e.database,this.newVersion=e.newVersion,this.oldVersion=e.oldVersion,this.dbSchema=e.dbSchema,this.transaction=e.transaction}deleteStoreIfExists(e){const t=this.database;t.objectStoreNames.contains(e)&&t.deleteObjectStore(e)}destroy(){try{u(this.#n)}finally{for(const e of Object.keys(this.#n))delete this.#n[e]}}store(e){if(e in this.#n)return this.#n[e];const{factory:t}=this.dbSchema,{storeSchemas:r}=this.dbSchema,a=r.find(t=>t.name===e),n=me(this,a);return this.#n[e]=t.newStoreUpgradeable(n,a,this)}versionIn({oldMin:e,oldMax:t,newMax:r,newMin:a}){if(void 0===t&&void 0===r&&void 0===e&&void 0===a)throw new Error(`versionIn bounds must not be empty ${JSON.stringify({oldMax:t,newMax:r,oldMin:e,newMin:a})}`);if(t<e)throw new Error(`oldMax (${t}) cannot be less than oldMin (${e})`);if(r<a)throw new Error(`newMax (${r}) cannot be less than newMin (${a})`);const{oldVersion:n,newVersion:i}=this;return!(void 0!==e&&n<e||void 0!==t&&n>t||void 0!==a&&i<a)&&!(void 0!==r&&i>r)}}function fe(e,t){let{store:r,index:a}=e;const{storeTemplate:n}=t,{storeSchemas:i=[]}=t,o=s(r)?r:r.name,c=i.findIndex(e=>e===o||e.name===o),u=c>-1&&i[c];let d;d=s(r)?u||o:!u||s(u)||r===u?r:{...u,...r},(a||u?.indexSchemas?.length||r?.indexSchemas?.length)&&(s(d)&&(d={name:d}),d.indexSchemas=function(e,t,r){r&&t.push(r);for(const r of t){const t=s(r)?r:r.name,a=e.findIndex(e=>e===t||e.name===t);if(a>-1){const t=e[a];s(t)?e[a]=r:s(r)||(e[a]=Object.assign(t,r))}else e.push(r)}return e}(u.indexSchemas||[],r.indexSchemas||[],a));const h=oe(d,n);c>-1?i[c]=h:i.push(h),t.storeSchemas=i;const m={store:o};return a&&(m.index=s(a)?a:a.name),{target:m}}const ye=Object.assign({name:"",addedTimeField:!1,autoIncrement:!1,indexSchemas:[],keyPath:void 0,softDeletedField:!1,updatedCountField:!1,updatedTimeField:!1});class pe{static#i;#s;#o;#c={};constructor(e,t){this.#s=e=s(e)?{name:e}:e,Array.isArray(e.storeSchemas)||(e.storeSchemas=[]),r(e.storeTemplate)||(e.storeTemplate=R),t&&(this.#o=!0)}static get defaultDb(){return this.#i||(this.#i=new pe(S))}get initialized(){return Object.isFrozen(this.#s)}get schema(){return this.#s}get storeNames(){return Array.from(new Set(this.#s.storeSchemas.map(e=>s(e)?e:e.name)))}get factory(){return this.#s.factory||(this.#s.factory=ie)}static releaseDefaultDB(){this.#i=void 0}static async openExistDb(e){const{generateDbSchema:t}=await Promise.resolve().then(function(){return Pe});return new pe(await t(e))}static store(e,t){return pe.defaultDb.store(e,t)}static stores(e){return pe.defaultDb.stores(e)}static map(e,t){return pe.defaultDb.map(e,t)}async openNativeDb(){const e=this.#s=a(this.initSchema());await this.#u();const{name:r,version:n}=e;return await g({name:r,version:n,onupgradeneeded:(r,a,n)=>async function(e,r,a,n){const{storeSchemas:i,beforeUpgrade:s,afterUpgrade:o,version:c}=e,{newVersion:u=c,oldVersion:h}=a,{transaction:m}=n,l=new le({database:r,newVersion:u,oldVersion:h,dbSchema:e,transaction:m});try{const e=[];if(t(s))try{await s(l)}catch(t){e.push(t)}for(const t of i.map(e=>e.name))try{l.store(t)}catch(t){e.push(t)}for(const{name:t,defaultData:r}of i)if(r)try{await l.store(t).add({oldMax:0},r)}catch(t){e.push(t)}for(const{name:t,versionData:r}of i)if(r)for(const{version:a,data:n,use:i="addOrChange"}of r)try{await l.store(t)[i](a,n)}catch(t){e.push(t)}for(const{name:t,storeDefined:r}of i)try{await(r?.(l.store(t)))}catch(t){e.push(t)}if(t(o))try{await o(l)}catch(t){e.push(t)}if(!e.length)return;throw 1===e.length?e[0]:new AggregateError(e,"Database upgrade error")}finally{d(l)}}(e,r,a,n)})}store(e,t){const r=e.store?e:{store:e};return r.store||(r.store=e),r.index||(r.index=t),this.factory.newWriter(fe(r,this.schema),this)}stores(e){const{schema:t}=this,r=e.map(e=>fe(s(e)?{store:e}:e,t));return this.factory.newDataOperators(r,this)}initSchema(){if(this.initialized)return this.#s;const{validateSchemaWithDefaults:e=ue}=this.#s;return this.#s=e(this.#s)}async traceSchema(e){await h(this.schema,e)}map(e,t){const r=s(e)?e:s(t)?t:b;Array.isArray(e)&&(t=e);const{storeSchemas:a}=this.schema;return a.find(e=>e.name===r||e===r)||a.push({...ye,name:r,defaultData:t}),this.factory.newDbMap({target:{store:r}},this)}export(){return this.stores(this.storeNames).export()}import(e,t,r){return this.stores(this.storeNames).import(e,t,r)}getStoreSchema(e){if(e in this.#c)return this.#c[e];const t=this.schema.storeSchemas.findIndex(t=>t===e||t.name===e);let r=this.schema.storeSchemas[t];return this.initialized?this.#c[e]=r:s(r)&&(this.schema.storeSchemas[t]=r={name:r}),r}async#u(){let e=this.#o;if(void 0===e&&(e=this.#o=await async function(e){const{name:t,version:r}=e,a=await p(t);if(!a)return!0;const{versionDiffValidate:n,versionSameValidate:i}=e,o=await g(t);try{if(e.version<o.version)return"The existing database version is greater than the current version";const c=void 0===e.version||o.version===e.version?i:n;if(!c)return!0;const u=Array.from(o.objectStoreNames);if(u.length<1)return`The existing database [ ${t} ] is empty`;const d=await w(o,u),h=await c({schema:e,db:o,stores:d});if(s(h)||r!==a.version)return h}finally{o?.close()}return!0}(this.#s)),!0===e)return!0;if(s(e))throw new Error(e)}}function ge(e,t){return pe.defaultDb.store(e,t)}function we(e,t){return pe.defaultDb.map(e,t)}function Se(e){return pe.defaultDb.stores(e)}function be(){pe.releaseDefaultDB()}function xe(e,t){const r=Array.from(e.indexNames).map(t=>e.index(t)),a=[],n=[];for(const{name:e,keyPath:t,unique:i,multiEntry:s}of r)Array.isArray(t)?n.push(...t):n.push(t),a.push({name:e,keyPath:t,unique:i,multiEntry:s});const i=new Set(n);return{indexSchemas:a,addedTimeField:ve(t.addedTimeField,i),updatedTimeField:ve(t.updatedTimeField,i),updatedCountField:ve(t.updatedCountField,i),softDeletedField:ve(t.softDeletedField,i)}}function ve(e,t){return!!t.has(e)&&{name:e,isIndexed:!1}}async function ke(e,t){if(!await p(e))throw new Error(`db [ ${e} ] not exist`);let{asString:r,specialFields:a=$,dataExportTarget:n}=t||{};!0===r&&(r=160),isNaN(r)||r<1&&(r=1);let i=await function(e,t){return g(e,async function(e){const r=Array.from(e.objectStoreNames),a=e.transaction(r,"readonly");try{return{name:e.name,version:e.version,storeSchemas:r.map(e=>function(e,t){const{name:r,keyPath:a,autoIncrement:n}=e;return{name:r,keyPath:a,autoIncrement:n,...xe(e,t)}}(a.objectStore(e),t))}}finally{a.abort()}})}(e,a);return n&&await async function(e,t){const r=await new pe(l(e),!0).export();for(const a of e.storeSchemas){const n=r[a.name];n?.length&&("defaultData"===t?a.defaultData=n:"versionData"===t&&(a.versionData||(a.versionData=[]),a.versionData.push({version:{oldMax:e.version},data:n})))}return e}(i,n),r?await m({rootData$:i,spaceEffectiveLength:r}):i}var Pe=Object.freeze({__proto__:null,generateDbSchema:ke});export{D as Break,O as Continue,M as ContinueKey,E as ContinuePrimaryKey,T as DataOperationBase,V as DataOperators,G as DataReader,Q as DataWriter,W as DbIterator,k as DbIteratorParsers,Y as DbMap,v as Delete,I as Finished,pe as IDbPro,q as NextKey,j as NextPrimaryKey,x as Save,ne as StoreUpgradeable,le as UpgradeContext,we as dbMap,ge as dbStore,Se as dbStores,$ as defaultSpecialFields,R as defaultStoreSchemaTemplate,ke as generateDbSchema,A as isIDbQuery,F as isNativeTarget,P as parseDbNoneKeyPathRecord,C as parseIDbQuery,be as releaseDefaultDB,ue as validateSchemaWithDefaults,ee as versionDiffValidate,te as versionSameValidate};