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