UNPKG

tinybase

Version:

A reactive data store and sync engine.

2 lines (1 loc) 9.35 kB
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,E=a=>Array.isArray(a),w=(a,t,e)=>a.slice(t,e),y=a=>a.length,d=async a=>i.all(a),u=a=>{throw Error(a)},R=(a,t)=>a.forEach(t),A=(a,t="")=>a.join(t),T=(a,t)=>a.map(t),N=a=>0==y(a),g=(a,t)=>a.filter(t),O=(a,...t)=>a.push(...t),$=a=>a.shift(),p=(a,t)=>a?.has(t)??!1,m=a=>o(a)||0==(a=>a?.size??0)(a),v=a=>[...a?.values()??[]],C=(a,t)=>a?.forEach(t),L=(a,t)=>a?.delete(t),I=Object,S=a=>I.getPrototypeOf(a),_=I.entries,h=I.keys,b=I.freeze,f=(a=[])=>I.fromEntries(a),D=(...a)=>I.assign({},...a),M=(a,t)=>(delete a[t],a),P=(a,t)=>T(_(a),(([a,e])=>t(e,a))),F=(a,t)=>f(P(a,((a,e)=>[e,t(a,e)]))),U=a=>I.values(a),G=a=>y(h(a)),B=a=>(a=>!o(a)&&c(S(a),(a=>a==I.prototype||o(S(a))),(()=>!0)))(a)&&0==G(a),j=a=>new Map(a),Y=(a,t)=>a?.get(t),x=(a,t)=>T([...a?.entries()??[]],(([a,e])=>t(e,a))),H=(a,t,e)=>o(e)?(L(a,t),a):a?.set(t,e),X=(a,t,e,n)=>(p(a,t)?n?.(Y(a,t)):H(a,t,e()),Y(a,t)),J=(a,t,e,n,s=0)=>c((e?X:Y)(a,t[s],s>y(t)-2?e:j),(i=>{if(s>y(t)-2)return n?.(i)&&H(a,t[s]),i;const r=J(i,t,e,n,s+1);return m(i)&&H(a,t[s]),r})),W=/^\d+$/,k=a=>new Set(E(a)||o(a)?a:[a]),q=(a,t)=>a?.add(t),z={Idle:0,Loading:1,Saving:2},K={StoreOnly:1,MergeableStoreOnly:2,StoreOrMergeableStore:3},V=j(),Q=j(),Z=(a,t,n,s,i,r,l,w={},d=0,A=[])=>{let T,N,g,p=0,v=0,I=0;X(V,A,(()=>0)),X(Q,A,(()=>[]));const S=j(),[_,h,f,D,M]=((a=1,t,e)=>1!=a&&t.isMergeable()?[1,t.getMergeableContent,()=>t.getTransactionMergeableChanges(!e),([[a],[t]])=>!B(a)||!B(t),t.setDefaultContent]:2!=a?[0,t.getContent,t.getTransactionChanges,([a,t])=>!B(a)||!B(t),t.setContent]:u("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?$(a):null)??e+t++,t=>{W.test(t)&&y(a)<1e3&&O(a,t)}]})(),s=j();return[(n,i,r,o=[],c=()=>[])=>{a??=ea;const l=t(1);return H(s,l,[n,i,r,o,c]),q(J(i,r??[e],k),l),l},(t,n,...i)=>R(((a,t=[e])=>{const n=[],s=(a,e)=>e==y(t)?O(n,a):null===t[e]?C(a,(a=>s(a,e+1))):R([t[e],null],(t=>s(Y(a,t),e+1)));return s(a,0),n})(t,n),(t=>C(t,(t=>Y(s,t)[0](a,...n??[],...i))))),a=>c(Y(s,a),(([,t,i])=>(J(t,i??[e],void 0,(t=>(L(t,a),m(t)?1:0))),H(s,a),n(a),i))),t=>c(Y(s,t),(([t,,e=[],n,s])=>{const i=(...r)=>{const c=y(r);c==y(e)?t(a,...r,...s(r)):o(e[c])?R(n[c]?.(...r)??[],(a=>i(...r,a))):i(...r,e[c])};i()}))]})(),G=a=>{a!=p&&(p=a,F(S,void 0,p))},x=t=>{(_&&E(t?.[0])?1===t?.[2]?a.applyMergeableChanges:a.setMergeableContent:1===t?.[2]?a.applyChanges:a.setContent)(t)},z=async a=>(2!=p&&(G(1),v++,await ta((async()=>{try{const e=await t();E(e)?x(e):a?M(a):u("Content is not an array: "+e)}catch(t){r?.(t),a&&M(a)}G(0)}))),ea),K=()=>(N&&(i(N),N=void 0),ea),Z=async a=>(1!=p&&(G(2),I++,await ta((async()=>{try{await n(h,a)}catch(a){r?.(a)}G(0)}))),ea),aa=()=>(g&&(a.delListener(g),g=void 0),ea),ta=async(...a)=>(O(Y(Q,A),...a),await(async()=>{if(!Y(V,A)){for(H(V,A,1);!o(T=$(Y(Q,A)));)try{await T()}catch(a){r?.(a)}H(V,A,0)}})(),ea),ea={load:z,startAutoLoad:async a=>{K(),await z(a);try{N=await s((async(a,t)=>{t||a?2!=p&&(G(1),v++,x(t??a),G(0)):await z()}))}catch(a){r?.(a)}return ea},stopAutoLoad:K,isAutoLoading:()=>!o(N),save:Z,startAutoSave:async()=>(aa(),await Z(),g=a.addDidFinishTransactionListener((()=>{const a=f();D(a)&&Z(a)})),ea),stopAutoSave:aa,isAutoSaving:()=>!o(g),getStatus:()=>p,addStatusListener:a=>P(a,S),delListener:t=>(U(t),a),schedule:ta,getStore:()=>a,destroy:()=>(Y(Q,A).splice(0,void 0),K().stopAutoSave()),getStats:()=>({loads:v,saves:I}),...w};return b(ea)},aa="_",ta="_id",ea="SELECT",na="WHERE",sa="TABLE",ia="ALTER "+sa,ra="DELETE FROM",oa=ea+"*FROM",ca="pragma_",la="data_version",Ea="schema_version",wa="pragma_table_",ya=(a,t)=>t?async(e,n)=>(t(e,n),await a(e,n)):a,da=a=>`"${a.replace(/"/g,'""')}"`,ua=(a,t=[1])=>A(T(a,(()=>"$"+t[0]++)),n),Ra="ColumnName",Aa="store",Ta="json",Na=Aa+"TableName",ga=Aa+"Id"+Ra,Oa=Aa+Ra,$a="autoLoadIntervalSeconds",pa="rowId"+Ra,ma="tableId",va="tableName",Ca="deleteEmptyColumns",La="deleteEmptyTable",Ia={mode:Ta,[$a]:1},Sa={load:0,save:0,[va]:t+"_values"},_a=(a,t,e,n,s)=>{const i=j();return F(a,((a,r)=>{const c=w(U(D(t,l(a)?{[e]:a}:a)),0,G(t));o(c[0])||n(r,c[0])||(s(r,c[0]),H(i,r,c))})),i},ha=a=>{const e=(a=>D(Ia,l(a)?{[Na]:a}:a??{}))(a),n=e[$a];if(e.mode==Ta){const a=e[Na]??t;return[1,n,[a,e[ga]??ta,e[Oa]??Aa],k(a)]}const{tables:{load:s={},save:i={}}={},values:r={}}=e,o=w(U(D(Sa,r)),0,G(Sa)),c=o[2],E=k(c),y=k(c);return[0,n,[_a(s,{[ma]:null,[pa]:ta},ma,(a=>p(y,a)),(a=>q(E,a))),_a(i,{[va]:null,[pa]:ta,[Ca]:0,[La]:0},va,((a,t)=>p(y,t)),((a,t)=>q(E,t))),o],E]},ba=JSON.stringify,fa=JSON.parse,Da=(a,t,e,s,i,r=Ma,c,l)=>{const E=j();return[async()=>{E.clear(),T(await e(a,t),(({tn:a,cn:t})=>q(X(E,a,k),t)))},async(t,e)=>((a,t)=>p(Y(E,a),t))(t,e)?f(g(T(await a(oa+da(t)),(a=>[a[e],l?F(M(a,e),l):M(a,e)])),(([a,t])=>!o(a)&&!B(t)))):{},async(t,e,s,l,w,y=!1)=>{const u=k();F(s??{},(a=>T(h(a??{}),(a=>q(u,a)))));const R=v(u);if(!y&&w&&N(R)&&p(E,t))return await a("DROP "+sa+da(t)),void H(E,t);const $=Y(E,t),m=k(v($));if(N(R)||(p(E,t)?await d(T([e,...R],(async(n,s)=>{L(m,n)||(await a(ia+da(t)+"ADD"+da(n)+i),0==s&&await a("CREATE UNIQUE INDEX pk ON "+da(t)+`(${da(e)})`),q($,n))}))):(await a("CREATE "+sa+da(t)+`(${da(e)}${i} PRIMARY KEY${A(T(R,(a=>n+da(a)+i)))});`),H(E,t,k([e,...R])))),await d([...!y&&l?T(v(m),(async n=>{n!=e&&(await a(ia+da(t)+"DROP"+da(n)),L($,n))})):[]]),y)o(s)?await a(ra+da(t)+na+" true"):await d(P(s,(async(n,s)=>{o(n)?await a(ra+da(t)+na+da(e)+"=$1",[s]):N(R)||await r(a,t,e,h(n),{[s]:c?T(U(n),c):U(n)},$)})));else if(N(R))p(E,t)&&await a(ra+da(t)+na+" true");else{const n=g(v(Y(E,t)),(a=>a!=e)),i={},o=[];F(s??{},((a,t)=>{i[t]=T(n,(t=>c?c(a?.[t]):a?.[t])),O(o,t)})),await r(a,t,e,n,i),await a(ra+da(t)+na+da(e)+`NOT IN(${ua(o)})`,o)}},async t=>{let e;await a("BEGIN");try{e=await t()}catch(a){s?.(a)}return await a("END"),e}]},Ma=async(a,t,e,s,i)=>{const r=[1];await a("INSERT INTO"+da(t)+"("+((...a)=>A(T(a,da),n))(e,...s)+")VALUES"+A(P(i,(a=>"($"+r[0]+++","+ua(a,r)+")")),n)+"ON CONFLICT("+da(e)+")DO UPDATE SET"+A(T(s,(a=>da(a)+"=excluded."+da(a))),n),P(i,((a,t)=>[t,...T(a,(a=>a??null))])).flat())},Pa=(a,t,e,n,s,i,r,[o,c,l],E,w,y,d,u,R)=>{const[A,T,N,g]=Da(t,E,w,s,u,R),O=Z(a,(async()=>await g((async()=>{return await A(),a=(await T(o,c))[aa]?.[l]??"null",fa(a,((a,t)=>""===t?void 0:t));var a}))),(async a=>await g((async()=>{var t;await A(),await N(o,c,{[aa]:{[l]:(t=a()??null,ba(t,((a,t)=>void 0===t?"":t)))}},!0,!0)}))),e,n,s,r,{[d]:()=>y,destroy:()=>(O.stopAutoLoad().stopAutoSave(),i(),O)},0,y);return O},Fa=(a,t,e,n,s,i,r,[c,l,[E,w,y]],u,R,A,T,N,O,$,p)=>{const[m,v,C,L]=Da(t,u,R,s,N,O,$,p),I=async(a,t)=>await d(x(l,(async([e,n,s,i],r)=>{t&&!(r in a)||await C(e,n,a[r],s,i,t)}))),S=async(a,t)=>w?await C(y,ta,{[aa]:a},!0,!0,t):null,_=Z(a,(async()=>await L((async()=>{await m();const a=await(async()=>f(g(await d(x(c,(async([a,t],e)=>[a,await v(e,t)]))),(a=>!B(a[1])))))(),t=await(async()=>E?(await v(y,ta))[aa]:{})();return B(a)&&o(t)?void 0:[a,t]}))),(async(a,t)=>await L((async()=>{if(await m(),o(t)){const[t,e]=a();await I(t),await S(e)}else await I(t[0],!0),await S(t[1],!0)}))),e,n,s,r,{[T]:()=>A,destroy:()=>(_.stopAutoLoad().stopAutoSave(),i(),_)},0,A);return _},Ua=(a,t,n,s,i,o,c,l,E,w,y="getDb",d)=>{let u,R,A;const T=ya(n,o),[N,g,O,$]=ha(t);return(N?Pa:Fa)(a,T,(a=>{let t;const e=()=>t=setInterval((async()=>{try{const[{d:t,s:e,c:n}]=await T(`${ea} ${la} d,${Ea} s,TOTAL_CHANGES() c FROM ${ca}${la} JOIN ${ca}${Ea}`);t==u&&e==R&&n==A||(null!=u&&a(),u=t,R=e,A=n)}catch{}}),1e3*g),n=()=>{u=R=A=null,r(t)},o=s((t=>{$.has(t)&&(n(),a(),e())}));return e(),()=>{n(),i(o)}}),(a=>a()),c,l,E,O,v($),(async(a,t)=>await a(`${ea} t.name tn,c.name cn FROM ${wa}list()t,${wa}info(t.name)c ${na} t.schema='main'AND t.type IN('table','view')AND t.name IN(${ua(t)})ORDER BY t.name,c.name`,t)),w,y,e,d,(a=>!0===a?1:!1===a?0:a),void 0)},Ga=t,Ba=/^([cd]:)(.+)/,ja=t+"_data",Ya=t+"_table",xa=(a,t,e,n,s,i,r,o,l,E,w="getDb")=>{const y=ya(e,i),[u,,R,A]=ha(t),N=async a=>{await y(`CREATE OR REPLACE TRIGGER ${da(ja+"_"+a)} AFTER INSERT OR UPDATE OR DELETE ON ${da(a)} EXECUTE FUNCTION ${ja}()`)};return(u?Pa:Fa)(a,y,(async a=>{await y(`CREATE OR REPLACE FUNCTION ${Ya}()RETURNS event_trigger AS $t2$ DECLARE row record; BEGIN FOR row IN SELECT object_identity FROM pg_event_trigger_ddl_commands()WHERE command_tag='CREATE TABLE' LOOP PERFORM pg_notify('${Ga}','c:'||SPLIT_PART(row.object_identity,'.',2));END LOOP;END;$t2$ LANGUAGE plpgsql;`);try{await y(`CREATE EVENT TRIGGER ${Ya} ON ddl_command_end WHEN TAG IN('CREATE TABLE')EXECUTE FUNCTION ${Ya}();`)}catch{}return await y(`CREATE OR REPLACE FUNCTION ${ja}()RETURNS trigger AS $t1$ BEGIN PERFORM pg_notify('${Ga}','d:'||TG_TABLE_NAME);RETURN NULL;END;$t1$ LANGUAGE plpgsql;`),await d(T(v(A),(async a=>{await y(`CREATE TABLE IF NOT EXISTS ${da(a)}("_id"text PRIMARY KEY)`),await N(a)}))),await n(Ga,(async t=>{return await c((e=t,n=Ba,e?.match(n)),(async([,t,e])=>{p(A,e)&&("c:"==t&&await N(e),a())}));var e,n}))}),s,r,o,l,R,v(A),(async(a,t)=>await a(`${ea} table_name tn,column_name cn FROM information_schema.columns ${na} table_schema='public'AND table_name IN(${ua(t)})`,t)),E,w,"text",void 0,(a=>ba(a)),(a=>fa(a)))};export{K as Persists,z as Status,Z as createCustomPersister,xa as createCustomPostgreSqlPersister,Ua as createCustomSqlitePersister};