tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 8.01 kB
JavaScript
import{addDatabaseChangeListener as a}from"expo-sqlite";const t=a=>typeof a,e="tinybase",n="",s=",",i=t(n),o=Promise,r=clearInterval,c=a=>null==a,l=(a,t,e)=>c(a)?e?.():t(a),y=a=>t(a)==i,w=a=>Array.isArray(a),u=(a,t,e)=>a.slice(t,e),d=a=>a.length,p=async a=>o.all(a),v=a=>{throw Error(a)},E=(a,t)=>a.forEach(t),g=(a,t="")=>a.join(t),m=(a,t)=>a.map(t),A=a=>0==d(a),h=(a,t)=>a.filter(t),N=(a,...t)=>a.push(...t),$=a=>a.shift(),f=(a,t)=>a?.has(t)??!1,S=a=>c(a)||0==(a=>a?.size??0)(a),C=a=>[...a?.values()??[]],O=(a,t)=>a?.forEach(t),T=(a,t)=>a?.delete(t),b="_",I="_id",L="SELECT",D="WHERE",R="TABLE",M="ALTER "+R,_="DELETE FROM",P=L+"*FROM",F="pragma_",U="data_version",j="schema_version",x="pragma_table_",B=a=>`"${a.replace(/"/g,'""')}"`,J=(a,t=[1])=>g(m(a,(()=>"$"+t[0]++)),s),Y=Object,k=a=>Y.getPrototypeOf(a),z=Y.entries,G=Y.keys,H=Y.freeze,q=(a=[])=>Y.fromEntries(a),K=(...a)=>Y.assign({},...a),Q=(a,t)=>(delete a[t],a),V=(a,t)=>m(z(a),(([a,e])=>t(e,a))),W=(a,t)=>q(V(a,((a,e)=>[e,t(a,e)]))),X=a=>Y.values(a),Z=a=>d(G(a)),aa=a=>(a=>!c(a)&&l(k(a),(a=>a==Y.prototype||c(k(a))),(()=>!0)))(a)&&0==Z(a),ta=a=>new Map(a),ea=(a,t)=>a?.get(t),na=(a,t)=>m([...a?.entries()??[]],(([a,e])=>t(e,a))),sa=(a,t,e)=>c(e)?(T(a,t),a):a?.set(t,e),ia=(a,t,e,n)=>(f(a,t)?n?.(ea(a,t)):sa(a,t,e()),ea(a,t)),oa=(a,t,e,n,s=0)=>l((e?ia:ea)(a,t[s],s>d(t)-2?e:ta),(i=>{if(s>d(t)-2)return n?.(i)&&sa(a,t[s]),i;const o=oa(i,t,e,n,s+1);return S(i)&&sa(a,t[s]),o})),ra=a=>new Set(w(a)||c(a)?a:[a]),ca=(a,t)=>a?.add(t),la="ColumnName",ya="store",wa="json",ua=ya+"TableName",da=ya+"Id"+la,pa=ya+la,va="autoLoadIntervalSeconds",Ea="rowId"+la,ga="tableId",ma="tableName",Aa="deleteEmptyColumns",ha="deleteEmptyTable",Na={mode:wa,[va]:1},$a={load:0,save:0,[ma]:e+"_values"},fa=(a,t,e,n,s)=>{const i=ta();return W(a,((a,o)=>{const r=u(X(K(t,y(a)?{[e]:a}:a)),0,Z(t));c(r[0])||n(o,r[0])||(s(o,r[0]),sa(i,o,r))})),i},Sa=JSON.stringify,Ca=JSON.parse,Oa=/^\d+$/,Ta=ta(),ba=ta(),Ia=(a,t,e,s,i,o,r,y={},u=0,p=[])=>{let g,m,A,h=0,f=0,C=0;ia(Ta,p,(()=>0)),ia(ba,p,(()=>[]));const b=ta(),[I,L,D,R,M]=((a=1,t,e)=>1!=a&&t.isMergeable()?[1,t.getMergeableContent,()=>t.getTransactionMergeableChanges(!e),([[a],[t]])=>!aa(a)||!aa(t),t.setDefaultContent]:2!=a?[0,t.getContent,t.getTransactionChanges,([a,t])=>!aa(a)||!aa(t),t.setContent]:v("Store type not supported by this Persister"))(r,a,u),[_,P,F]=(()=>{let a;const[t,e]=(()=>{const a=[];let t=0;return[e=>(e?$(a):null)??n+t++,t=>{Oa.test(t)&&d(a)<1e3&&N(a,t)}]})(),s=ta();return[(e,i,o,r=[],c=()=>[])=>{a??=z;const l=t(1);return sa(s,l,[e,i,o,r,c]),ca(oa(i,o??[n],ra),l),l},(t,e,...i)=>E(((a,t=[n])=>{const e=[],s=(a,n)=>n==d(t)?N(e,a):null===t[n]?O(a,(a=>s(a,n+1))):E([t[n],null],(t=>s(ea(a,t),n+1)));return s(a,0),e})(t,e),(t=>O(t,(t=>ea(s,t)[0](a,...e??[],...i))))),a=>l(ea(s,a),(([,t,i])=>(oa(t,i??[n],void 0,(t=>(T(t,a),S(t)?1:0))),sa(s,a),e(a),i))),t=>l(ea(s,t),(([t,,e=[],n,s])=>{const i=(...o)=>{const r=d(o);r==d(e)?t(a,...o,...s(o)):c(e[r])?E(n[r]?.(...o)??[],(a=>i(...o,a))):i(...o,e[r])};i()}))]})(),U=a=>{a!=h&&(h=a,P(b,void 0,h))},j=t=>{(I&&w(t?.[0])?1===t?.[2]?a.applyMergeableChanges:a.setMergeableContent:1===t?.[2]?a.applyChanges:a.setContent)(t)},x=async a=>(2!=h&&(U(1),f++,await k((async()=>{try{const e=await t();w(e)?j(e):a?M(a):v("Content is not an array: "+e)}catch(t){o?.(t),a&&M(a)}U(0)}))),z),B=()=>(m&&(i(m),m=void 0),z),J=async a=>(1!=h&&(U(2),C++,await k((async()=>{try{await e(L,a)}catch(a){o?.(a)}U(0)}))),z),Y=()=>(A&&(a.delListener(A),A=void 0),z),k=async(...a)=>(N(ea(ba,p),...a),await(async()=>{if(!ea(Ta,p)){for(sa(Ta,p,1);!c(g=$(ea(ba,p)));)try{await g()}catch(a){o?.(a)}sa(Ta,p,0)}})(),z),z={load:x,startAutoLoad:async a=>{B(),await x(a);try{m=await s((async(a,t)=>{t||a?2!=h&&(U(1),f++,j(t??a),U(0)):await x()}))}catch(a){o?.(a)}return z},stopAutoLoad:B,isAutoLoading:()=>!c(m),save:J,startAutoSave:async()=>(Y(),await J(),A=a.addDidFinishTransactionListener((()=>{const a=D();R(a)&&J(a)})),z),stopAutoSave:Y,isAutoSaving:()=>!c(A),getStatus:()=>h,addStatusListener:a=>_(a,b),delListener:t=>(F(t),a),schedule:k,getStore:()=>a,destroy:()=>(ea(ba,p).splice(0,void 0),B().stopAutoSave()),getStats:()=>({loads:f,saves:C}),...y};return H(z)},La=(a,t,e,n,i,o=Da,r,l)=>{const y=ta();return[async()=>{y.clear(),m(await e(a,t),(({tn:a,cn:t})=>ca(ia(y,a,ra),t)))},async(t,e)=>((a,t)=>f(ea(y,a),t))(t,e)?q(h(m(await a(P+B(t)),(a=>[a[e],l?W(Q(a,e),l):Q(a,e)])),(([a,t])=>!c(a)&&!aa(t)))):{},async(t,e,n,l,w,u=!1)=>{const d=ra();W(n??{},(a=>m(G(a??{}),(a=>ca(d,a)))));const v=C(d);if(!u&&w&&A(v)&&f(y,t))return await a("DROP "+R+B(t)),void sa(y,t);const E=ea(y,t),$=ra(C(E));if(A(v)||(f(y,t)?await p(m([e,...v],(async(n,s)=>{T($,n)||(await a(M+B(t)+"ADD"+B(n)+i),0==s&&await a("CREATE UNIQUE INDEX pk ON "+B(t)+`(${B(e)})`),ca(E,n))}))):(await a("CREATE "+R+B(t)+`(${B(e)}${i} PRIMARY KEY${g(m(v,(a=>s+B(a)+i)))});`),sa(y,t,ra([e,...v])))),await p([...!u&&l?m(C($),(async n=>{n!=e&&(await a(M+B(t)+"DROP"+B(n)),T(E,n))})):[]]),u)c(n)?await a(_+B(t)+D+" true"):await p(V(n,(async(n,s)=>{c(n)?await a(_+B(t)+D+B(e)+"=$1",[s]):A(v)||await o(a,t,e,G(n),{[s]:r?m(X(n),r):X(n)},E)})));else if(A(v))f(y,t)&&await a(_+B(t)+D+" true");else{const s=h(C(ea(y,t)),(a=>a!=e)),i={},c=[];W(n??{},((a,t)=>{i[t]=m(s,(t=>r?r(a?.[t]):a?.[t])),N(c,t)})),await o(a,t,e,s,i),await a(_+B(t)+D+B(e)+`NOT IN(${J(c)})`,c)}},async t=>{let e;await a("BEGIN");try{e=await t()}catch(a){n?.(a)}return await a("END"),e}]},Da=async(a,t,e,n,i)=>{const o=[1];await a("INSERT INTO"+B(t)+"("+((...a)=>g(m(a,B),s))(e,...n)+")VALUES"+g(V(i,(a=>"($"+o[0]+++","+J(a,o)+")")),s)+"ON CONFLICT("+B(e)+")DO UPDATE SET"+g(m(n,(a=>B(a)+"=excluded."+B(a))),s),V(i,((a,t)=>[t,...m(a,(a=>a??null))])).flat())},Ra=(a,t,e,n,s,i,o,[r,c,l],y,w,u,d,p,v)=>{const[E,g,m,A]=La(t,y,w,s,p,v),h=Ia(a,(async()=>await A((async()=>{return await E(),a=(await g(r,c))[b]?.[l]??"null",Ca(a,((a,t)=>""===t?void 0:t));var a}))),(async a=>await A((async()=>{var t;await E(),await m(r,c,{[b]:{[l]:(t=a()??null,Sa(t,((a,t)=>void 0===t?"":t)))}},!0,!0)}))),e,n,s,o,{[d]:()=>u,destroy:()=>(h.stopAutoLoad().stopAutoSave(),i(),h)},0,u);return h},Ma=(a,t,e,n,s,i,o,[r,l,[y,w,u]],d,v,E,g,m,A,N,$)=>{const[f,S,C,O]=La(t,d,v,s,m,A,N,$),T=async(a,t)=>await p(na(l,(async([e,n,s,i],o)=>{t&&!(o in a)||await C(e,n,a[o],s,i,t)}))),L=async(a,t)=>w?await C(u,I,{[b]:a},!0,!0,t):null,D=Ia(a,(async()=>await O((async()=>{await f();const a=await(async()=>q(h(await p(na(r,(async([a,t],e)=>[a,await S(e,t)]))),(a=>!aa(a[1])))))(),t=await(async()=>y?(await S(u,I))[b]:{})();return aa(a)&&c(t)?void 0:[a,t]}))),(async(a,t)=>await O((async()=>{if(await f(),c(t)){const[t,e]=a();await T(t),await L(e)}else await T(t[0],!0),await L(t[1],!0)}))),e,n,s,o,{[g]:()=>E,destroy:()=>(D.stopAutoLoad().stopAutoSave(),i(),D)},0,E);return D},_a=(a,t,s,i,o,c,l,w,d,p,v="getDb",E)=>{let g,m,A;const h=((a,t)=>t?async(e,n)=>(t(e,n),await a(e,n)):a)(s,c),[N,$,S,O]=(a=>{const t=(a=>K(Na,y(a)?{[ua]:a}:a??{}))(a),n=t[va];if(t.mode==wa){const a=t[ua]??e;return[1,n,[a,t[da]??I,t[pa]??ya],ra(a)]}const{tables:{load:s={},save:i={}}={},values:o={}}=t,r=u(X(K($a,o)),0,Z($a)),c=r[2],l=ra(c),w=ra(c);return[0,n,[fa(s,{[ga]:null,[Ea]:I},ga,(a=>f(w,a)),(a=>ca(l,a))),fa(i,{[ma]:null,[Ea]:I,[Aa]:0,[ha]:0},ma,((a,t)=>f(w,t)),((a,t)=>ca(l,t))),r],l]})(t);return(N?Ra:Ma)(a,h,(a=>{let t;const e=()=>t=setInterval((async()=>{try{const[{d:t,s:e,c:n}]=await h(`${L} ${U} d,${j} s,TOTAL_CHANGES() c FROM ${F}${U} JOIN ${F}${j}`);t==g&&e==m&&n==A||(null!=g&&a(),g=t,m=e,A=n)}catch{}}),1e3*$),n=()=>{g=m=A=null,r(t)},s=i((t=>{O.has(t)&&(n(),a(),e())}));return e(),()=>{n(),o(s)}}),(a=>a()),l,w,d,S,C(O),(async(a,t)=>await a(`${L} t.name tn,c.name cn FROM ${x}list()t,${x}info(t.name)c ${D} t.schema='main'AND t.type IN('table','view')AND t.name IN(${J(t)})ORDER BY t.name,c.name`,t)),p,v,n,E,(a=>!0===a?1:!1===a?0:a),void 0)},Pa=(t,e,n,s,i)=>_a(t,n,(async(a,t=[])=>await e.getAllAsync(a,t)),(t=>a((({tableName:a})=>t(a)))),(a=>a.remove()),s,i,(()=>0),3,e);export{Pa as createExpoSqlitePersister};