tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 9.44 kB
JavaScript
const a=a=>typeof a,t="tinybase",e="",n=",",s=a(e),i="true",r=(a,t,e)=>a.replace(t,e),o=Promise,c=a=>(t,e,n)=>a(t)?n?.():e(t),l=globalThis,w=a=>null==a,y=a=>void 0===a,u=a=>null===a,d=c(w),E=c(y),N=t=>a(t)==s,g=a=>Array.isArray(a),A=(a,t,e)=>a.slice(t,e),T=a=>a.length,$=async a=>o.all(a),p=a=>{throw Error(a)},O=async(a,t,e)=>{try{return await a()}catch(a){t?.(a)}},R=(a,t)=>a.forEach(t),m=(a,t="")=>a.join(t),v=(a,t)=>a.map(t),C=a=>0==T(a),S=(a,t)=>a.filter(t),I=(a,...t)=>a.push(...t),L=a=>a.shift(),_=(a,t)=>a?.has(t)??!1,b=a=>y(a)||0==(a=>a?.size??0)(a),f=a=>[...a?.values()??[]],D=(a,t)=>a?.forEach(t),h=(a,t)=>a?.delete(t),P=Object,M=a=>P.getPrototypeOf(a),F=P.entries,U=a=>!w(a)&&d(M(a),a=>a==P.prototype||w(M(a)),()=>!0),G=P.keys,j=P.freeze,x=(a=[])=>P.fromEntries(a),W=(...a)=>P.assign({},...a),B=(a,t)=>(delete a[t],a),H=(a,t)=>v(F(a),([a,e])=>t(e,a)),X=(a,t)=>x(H(a,(a,e)=>[e,t(a,e)])),Y=a=>P.values(a),k=a=>T(G(a)),q=a=>U(a)&&0==k(a),z=JSON.stringify,J=JSON.parse,K=a=>z(a,(a,t)=>y(t)?"":t),V=a=>""===a?void 0:g(a)?v(a,V):U(a)?X(a,V):a,Q=new l.TextEncoder,Z=Map,aa=a=>new Z(a),ta=(a,t)=>a?.get(t),ea=(a,t)=>v([...a?.entries()??[]],([a,e])=>t(e,a)),na=(a,t,e)=>y(e)?(h(a,t),a):a?.set(t,e),sa=(a,t,e,n)=>(_(a,t)?n?.(ta(a,t)):na(a,t,e()),ta(a,t)),ia=(a,t,e,n,s=0)=>E((e?sa:ta)(a,t[s],s>T(t)-2?e:aa),i=>{if(s>T(t)-2)return n?.(i)&&na(a,t[s]),i;const r=ia(i,t,e,n,s+1);return b(i)&&na(a,t[s]),r}),ra="_",oa="_id",ca="SELECT",la="WHERE",wa="TABLE",ya="INSERT",ua="DELETE",da="UPDATE",Ea="ALTER "+wa,Na="FROM",ga=ua+" "+Na,Aa=ca+"*"+Na,Ta="CREATE ",$a=Ta+wa,pa="OR REPLACE ",Oa="FUNCTION",Ra="$tableName",ma=a=>m(v(((a,t="",e)=>a.split(t,e))(a,"."),a=>`"${r(a,/"/g,'""')}"`),"."),va=(...a)=>ma(m(a,"_")),Ca=(a,t=[1])=>m(v(a,()=>"$"+t[0]++),n),Sa=(a,t=i)=>la+`(${r(t,Ra,ma(a))})`,Ia=a=>new Set(g(a)||y(a)?a:[a]),La=(a,t)=>a?.add(t),_a="ColumnName",ba="store",fa="json",Da=ba+"TableName",ha=ba+"Id"+_a,Pa=ba+_a,Ma="autoLoadIntervalSeconds",Fa="rowId"+_a,Ua="tableId",Ga="tableName",ja="deleteEmptyColumns",xa="deleteEmptyTable",Wa="condition",Ba={mode:fa,[Ma]:1},Ha={load:0,save:0,[Ga]:t+"_values"},Xa=(a,t,e,n,s)=>{const i=aa();return X(a,(a,r)=>{const o=A(Y(W(t,N(a)?{[e]:a}:a)),0,k(t));u(o[0])||n(r,o[0])||(s(r,o[0]),na(i,r,o))}),i},Ya=/^\d+$/,ka=aa(),qa=aa(),za=(a,t,n,s,i,r,o,c={},l=0,w=[])=>{let d,N,A,$=0,m=0,v=0;sa(ka,w,()=>0),sa(qa,w,()=>[]);const C=aa(),[S,_,f,P,M]=((a=1,t,e)=>1!=a&&t.isMergeable()?[1,t.getMergeableContent,()=>t.getTransactionMergeableChanges(!e),([[a],[t]])=>!q(a)||!q(t),t.setDefaultContent]:2!=a?[0,t.getContent,t.getTransactionChanges,([a,t])=>!q(a)||!q(t),t.setContent]:p("Store type not supported by this Persister"))(o,a,l),[F,U,G]=(()=>{let a;const[t,n]=(()=>{const a=[];let t=0;return[n=>(n?L(a):null)??e+t++,t=>{Ya.test(t)&&T(a)<1e3&&I(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]),La(ia(i,r??[e],Ia),l),l},(t,n,...i)=>R(((a,t=[e])=>{const n=[],s=(a,e)=>e==T(t)?I(n,a):u(t[e])?D(a,a=>s(a,e+1)):R([t[e],null],t=>s(ta(a,t),e+1));return s(a,0),n})(t,n),t=>D(t,t=>ta(s,t)[0](a,...n??[],...i))),a=>E(ta(s,a),([,t,i])=>(ia(t,i??[e],void 0,t=>(h(t,a),b(t)?1:0)),na(s,a),n(a),i)),t=>E(ta(s,t),([t,,e=[],n,s])=>{const i=(...r)=>{const o=T(r);o==T(e)?t(a,...r,...s(r)):u(e[o])?R(n[o]?.(...r)??[],a=>i(...r,a)):i(...r,e[o])};i()})]})(),x=a=>{a!=$&&($=a,U(C,void 0,$))},W=t=>{(S&&g(t?.[0])?1===t?.[2]?a.applyMergeableChanges:a.setMergeableContent:1===t?.[2]?a.applyChanges:a.setContent)(t)},B=async()=>{K()&&a.hadMutated?.()&&await k()},H=async a=>(2!=$&&(x(1),m++,await Q(async()=>{await O(async()=>{const e=await t();g(e)?W(e):a?M(a):p("Content is not an array: "+e)},()=>{a&&M(a)}),x(0),await B()})),Z),X=async a=>(Y(),await H(a),await O(async()=>N=await s(async(a,t)=>{t||a?2!=$&&(x(1),m++,W(t??a),x(0),await B()):await H()}),r),Z),Y=async()=>(N&&(await O(()=>i(N),r),N=void 0),Z),k=async a=>(1!=$&&(x(2),v++,await Q(async()=>{await O(()=>n(_,a),r),x(0)})),Z),z=async()=>(J(),await k(),A=a.addDidFinishTransactionListener(()=>{const a=f();P(a)&&k(a)}),Z),J=async()=>(A&&(a.delListener(A),A=void 0),Z),K=()=>!y(A),V=async(a=!1)=>{const[t,e]=a?[J,Y]:[Y,J];return await t(),await e(),Z},Q=async(...a)=>(I(ta(qa,w),...a),await(async()=>{if(!ta(ka,w)){for(na(ka,w,1);!y(d=L(ta(qa,w)));)await O(d,r);na(ka,w,0)}})(),Z),Z={load:H,startAutoLoad:X,stopAutoLoad:Y,isAutoLoading:()=>!y(N),save:k,startAutoSave:z,stopAutoSave:J,isAutoSaving:K,startAutoPersisting:async(a,t=!1)=>{const[e,n]=t?[z,X]:[X,z];return await e(a),await n(a),Z},stopAutoPersisting:V,getStatus:()=>$,addStatusListener:a=>F(a,C),delListener:t=>(G(t),a),schedule:Q,getStore:()=>a,destroy:()=>(ta(qa,w).splice(0,void 0),V()),getStats:()=>({loads:m,saves:v}),...c};return j(Z)},Ja=(a,t,e,s,r,o=Ka,c,l)=>{const w=aa();return[async()=>{w.clear(),v(await e(a,t),({tn:a,cn:t})=>La(sa(w,a,Ia),t))},async(t,e,n)=>((a,t)=>_(ta(w,a),t))(t,e)?x(S(v(await a(Aa+ma(t)+Sa(t,n)),a=>[a[e],l?X(B(a,e),l):B(a,e)]),([a,t])=>!y(a)&&!q(t))):{},async(t,e,s,l,u,d=!1,E=i)=>{const N=Ia();X(s??{},a=>v(G(a??{}),a=>La(N,a)));const g=f(N);if(!d&&u&&E==i&&C(g)&&_(w,t))return await a("DROP "+wa+ma(t)),void na(w,t);const A=ta(w,t),T=Ia(f(A));if(C(g)||(_(w,t)?await $(v([e,...g],async(n,s)=>{h(T,n)||(await a(Ea+ma(t)+"ADD"+ma(n)+r),0==s&&await a("CREATE UNIQUE INDEX pk ON "+ma(t)+`(${ma(e)})`),La(A,n))})):(await a($a+ma(t)+`(${ma(e)}${r} PRIMARY KEY${m(v(g,a=>n+ma(a)+r))});`),na(w,t,Ia([e,...g])))),await $([...!d&&l?v(f(T),async n=>{n!=e&&(await a(Ea+ma(t)+"DROP"+ma(n)),h(A,n))}):[]]),d)y(s)?await a(ga+ma(t)+Sa(t,E)):await $(H(s,async(n,s)=>{y(n)?await a(ga+ma(t)+Sa(t,E)+`AND(${ma(e)}=$1)`,[s]):C(g)||await o(a,t,e,G(n),{[s]:c?v(Y(n),c):Y(n)},A)}));else if(C(g))_(w,t)&&await a(ga+ma(t)+Sa(t,E));else{const n=S(f(ta(w,t)),a=>a!=e),i={},r=[];X(s??{},(a,t)=>{i[t]=v(n,t=>c?c(a?.[t]):a?.[t]),I(r,t)}),await o(a,t,e,n,i),await a(ga+ma(t)+Sa(t,E)+`AND${ma(e)}NOT IN(${Ca(r)})`,r)}},async t=>{let e;return await a("BEGIN"),await O(async()=>e=await t(),s),await a("END"),e}]},Ka=async(a,t,e,s,i)=>{const r=[1];await a(ya+" INTO"+ma(t)+"("+((...a)=>m(v(a,ma),n))(e,...s)+")VALUES"+m(H(i,a=>"($"+r[0]+++","+Ca(a,r)+")"),n)+"ON CONFLICT("+ma(e)+`)DO ${da} SET`+m(v(s,a=>ma(a)+"=excluded."+ma(a)),n),H(i,(a,t)=>[t,...v(a,a=>a??null)]).flat())},Va=(a,t,e,n,s,i,r,[o,c,l],w,y,u,d,E,N)=>{const[g,A,T,$]=Ja(t,w,y,s,E,N),p=za(a,()=>$(async()=>{return await g(),a=(await A(o,c))[ra]?.[l]??"null",V(J(a));var a}),a=>$(async()=>{await g(),await T(o,c,{[ra]:{[l]:K(a()??null)}},!0,!0)}),e,n,s,r,{[d]:()=>u,destroy:async()=>(await p.stopAutoPersisting(),i(),p)},0,u);return p},Qa=(a,t,e,n,s,i,r,[o,c,[l,w,u]],d,E,N,g,A,T,p,O)=>{const[R,m,v,C]=Ja(t,d,E,s,A,T,p,O),I=(a,t)=>$(ea(c,async([e,n,s,i,r],o)=>{t&&!(o in a)||await v(e,n,a[o],s,i,t,r)})),L=async(a,t)=>w?await v(u,oa,{[ra]:a},!0,!0,t):null,_=za(a,()=>C(async()=>{await R();const a=await(async()=>x(S(await $(ea(o,async([a,t,e],n)=>[a,await m(n,t,e)])),a=>!q(a[1]))))(),t=await(async()=>l?(await m(u,oa))[ra]:{})();return q(a)&&y(t)?void 0:[a,t]}),(a,t)=>C(async()=>{if(await R(),y(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]:()=>N,destroy:async()=>(await _.stopAutoPersisting(),i(),_)},0,N);return _},Za=/^([cd]:)(.+)/,at=(a,n,s,o,c,l,w,y,u,d,g="getDb")=>{const T=((a,t)=>t?async(e,n)=>(t(e,n),await a(e,n)):a)(s,l),[p,,O,C]=(a=>{const e=(a=>W(Ba,N(a)?{[Da]:a}:a??{}))(a),n=e[Ma];if(e.mode==fa){const a=e[Da]??t;return[1,n,[a,e[ha]??oa,e[Pa]??ba],Ia(a)]}const{tables:{load:s={},save:r={}}={},values:o={}}=e,c=A(Y(W(Ha,o)),0,k(Ha)),l=c[2],w=Ia(l),y=Ia(l),u=Xa(s,{[Ua]:null,[Fa]:oa,[Wa]:i},Ua,a=>_(y,a),a=>La(w,a)),d=Xa(r,{[Ga]:null,[Fa]:oa,[ja]:0,[xa]:0,[Wa]:null},Ga,(a,t)=>_(y,t),(a,t)=>La(w,t));var E;return E=(a,t)=>t[4]??=ta(u,t[0])?.[2]??i,D(d,(a,t)=>E(0,a)),[0,n,[u,d,c],w]})(n),S=e+(a=>{let t=2166136261;return R(Q.encode(a),a=>{t^=a,t+=(t<<1)+(t<<4)+(t<<7)+(t<<8)+(t<<24)}),t>>>0})(K(O)),I=t+"_"+S,L=async(a,e,n="",s="")=>{const i=va(t,a,S);return await T(Ta+pa+Oa+i+`()RETURNS ${n}trigger AS $$ ${s}BEGIN ${e}END;$$ LANGUAGE plpgsql;`),i},b=async(a,t,e,n)=>(await T(Ta+a+"TRIGGER"+t+e+"EXECUTE "+Oa+n+"()"),t),h=a=>`PERFORM pg_notify('${I}',${a});`,P=(a,t)=>p?i:2===t?P(a,0)+" OR "+P(a,1):r(ta(O[0],a)?.[2]??i,Ra,0==t?"NEW":"OLD"),M=(a,e)=>$(v([ya,ua,da],(n,s)=>b(pa,va(t,"d",S,a,n),`AFTER ${n} ON${ma(a)}FOR EACH ROW WHEN(${P(a,s)})`,e)));return(p?Va:Qa)(a,T,async a=>{const e=await L("c",`FOR row IN SELECT object_identity FROM pg_event_trigger_ddl_commands()${la} command_tag='${$a}' LOOP ${h("'c:'||SPLIT_PART(row.object_identity,'.',2)")}END LOOP;`,"event_","DECLARE row record;");await b("EVENT ",va(t,"c",S),`ON ddl_command_end WHEN TAG IN('${$a}')`,e);const n=await L("d",h("'d:'||TG_TABLE_NAME")+"RETURN NULL;");return await $(v(f(C),async a=>(await T($a+` IF NOT EXISTS${ma(a)}("_id"text PRIMARY KEY)`),await M(a,n)))),[await o(I,t=>{return E((e=t,s=Za,e?.match(s)),async([,t,e])=>{_(C,e)&&("c:"==t&&await M(e,n),a())});var e,s}),[e,n]]},async([a,t])=>{c(a),await T(`DROP FUNCTION IF EXISTS${m(t,",")}CASCADE`)},w,y,u,O,f(C),async(a,t)=>await a(ca+` table_name tn,column_name cn FROM information_schema.columns ${la} table_schema='public'AND table_name IN(${Ca(t)})`,t),d,g,"text",void 0,a=>z(a),a=>J(a))},tt=async(a,t,e,n,s)=>{const i=await(t.reserve?.());return at(a,e,i?.unsafe,async(a,e)=>t.listen(a,e),a=>O(a.unlisten,s),n,s,()=>i?.release?.(),3,t,"getSql")};export{tt as createPostgresPersister};