tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 3.5 kB
JavaScript
const t=clearInterval,e=t=>null==t,a=(t,a,n)=>e(t)?n?.():a(t),n=t=>Array.isArray(t),s=t=>t.length,r=t=>{throw Error(t)},o=(t,e)=>t.forEach(e),i=(t,...e)=>t.push(...e),c=t=>t.shift(),l=Object,y=t=>l.getPrototypeOf(t),d=l.keys,u=l.freeze,g=t=>(t=>!e(t)&&a(y(t),(t=>t==l.prototype||e(y(t))),(()=>!0)))(t)&&0==(t=>s(d(t)))(t),h=JSON.stringify,p=JSON.parse,w=t=>e(t)||0==(t=>t?.size??0)(t),v=(t,e)=>t?.forEach(e),f=(t,e)=>t?.delete(e),S=t=>new Map(t),C=(t,e)=>t?.get(e),A=(t,a,n)=>e(n)?(f(t,a),t):t?.set(a,n),b=(t,e,a,n)=>{var s,r;return s=t,r=e,s?.has(r)?n?.(C(t,e)):A(t,e,a()),C(t,e)},L=(t,e,n,r,o=0)=>a((n?b:C)(t,e[o],o>s(e)-2?n:S),(a=>{if(o>s(e)-2)return r?.(a)&&A(t,e[o]),a;const i=L(a,e,n,r,o+1);return w(a)&&A(t,e[o]),i})),M=/^\d+$/,E=t=>new Set(n(t)||e(t)?t:[t]),T=S(),O=S(),m=(t,l,y,d,h,p,m,D={},P=0,j=[])=>{let x,z,I,J=0,N=0,k=0;b(T,j,(()=>0)),b(O,j,(()=>[]));const F=S(),[H,U,$,q,B]=((t=1,e,a)=>1!=t&&e.isMergeable()?[1,e.getMergeableContent,()=>e.getTransactionMergeableChanges(!a),([[t],[e]])=>!g(t)||!g(e),e.setDefaultContent]:2!=t?[0,e.getContent,e.getTransactionChanges,([t,e])=>!g(t)||!g(e),e.setContent]:r("Store type not supported by this Persister"))(m,t,P),[G,K,Q]=(()=>{let t;const[n,r]=(()=>{const t=[];let e=0;return[a=>(a?c(t):null)??""+e++,e=>{M.test(e)&&s(t)<1e3&&i(t,e)}]})(),l=S();return[(e,a,s,r=[],o=()=>[])=>{t??=tt;const i=n(1);var c,y;return A(l,i,[e,a,s,r,o]),c=L(a,s??[""],E),y=i,c?.add(y),i},(e,a,...n)=>o(((t,e=[""])=>{const a=[],n=(t,r)=>r==s(e)?i(a,t):null===e[r]?v(t,(t=>n(t,r+1))):o([e[r],null],(e=>n(C(t,e),r+1)));return n(t,0),a})(e,a),(e=>v(e,(e=>C(l,e)[0](t,...a??[],...n))))),t=>a(C(l,t),(([,e,a])=>(L(e,a??[""],void 0,(e=>(f(e,t),w(e)?1:0))),A(l,t),r(t),a))),n=>a(C(l,n),(([a,,n=[],r,i])=>{const c=(...l)=>{const y=s(l);y==s(n)?a(t,...l,...i(l)):e(n[y])?o(r[y]?.(...l)??[],(t=>c(...l,t))):c(...l,n[y])};c()}))]})(),R=t=>{t!=J&&(J=t,K(F,void 0,J))},V=e=>{(H&&n(e?.[0])?1===e?.[2]?t.applyMergeableChanges:t.setMergeableContent:1===e?.[2]?t.applyChanges:t.setContent)(e)},W=async t=>(2!=J&&(R(1),N++,await _((async()=>{try{const e=await l();n(e)?V(e):t?B(t):r("Content is not an array: "+e)}catch(e){p?.(e),t&&B(t)}R(0)}))),tt),X=()=>(z&&(h(z),z=void 0),tt),Y=async t=>(1!=J&&(R(2),k++,await _((async()=>{try{await y(U,t)}catch(t){p?.(t)}R(0)}))),tt),Z=()=>(I&&(t.delListener(I),I=void 0),tt),_=async(...t)=>(i(C(O,j),...t),await(async()=>{if(!C(T,j)){for(A(T,j,1);!e(x=c(C(O,j)));)try{await x()}catch(t){p?.(t)}A(T,j,0)}})(),tt),tt={load:W,startAutoLoad:async t=>{X(),await W(t);try{z=await d((async(t,e)=>{e||t?2!=J&&(R(1),N++,V(e??t),R(0)):await W()}))}catch(t){p?.(t)}return tt},stopAutoLoad:X,isAutoLoading:()=>!e(z),save:Y,startAutoSave:async()=>(Z(),await Y(),I=t.addDidFinishTransactionListener((()=>{const t=$();q(t)&&Y(t)})),tt),stopAutoSave:Z,isAutoSaving:()=>!e(I),getStatus:()=>J,addStatusListener:t=>G(t,F),delListener:e=>(Q(e),t),schedule:_,getStore:()=>t,destroy:()=>(C(O,j).splice(0,void 0),X().stopAutoSave()),getStats:()=>({loads:N,saves:k}),...D};return u(tt)},D=t=>t.headers.get("ETag"),P=(a,n,s,r=5,o)=>{let i;return m(a,(async()=>{const t=await fetch(n);return i=D(t),p(await t.text())}),(async t=>{return await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:(e=t(),h(e,((t,e)=>e instanceof Map?l.fromEntries([...e]):e)))});var e}),(t=>setInterval((async()=>{const a=await fetch(n,{method:"HEAD"}),s=D(a);e(i)||e(s)||s==i||(i=s,t())}),1e3*r)),(e=>t(e)),o,1,{getUrls:()=>[n,s]})};export{P as createRemotePersister};