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