tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 5.66 kB
JavaScript
const t=(t,e="",a)=>t.split(e,a),e=Promise,a=globalThis,s=Math,n=s.floor,o=t=>null==t,r=(t,e,a)=>o(t)?a?.():e(t),i=t=>Array.isArray(t),c=t=>t.length,l=t=>{throw Error(t)},g=async(t,e,a)=>{try{return await t()}catch(t){e?.(t)}},u=(t,e)=>t.forEach(e),y=(t,...e)=>t.push(...e),d=t=>t.shift(),w=t=>o(t)||0==(t=>t?.size??0)(t),h=(t,e)=>t?.forEach(e),p=(t,e)=>t?.delete(e),f=Object,b=t=>f.getPrototypeOf(t),v=f.entries,M=f.keys,C=f.freeze,A=(t,e)=>u(v(t),([t,a])=>e(a,t)),S=t=>(t=>!o(t)&&r(b(t),t=>t==f.prototype||o(b(t)),()=>!0))(t)&&0==(t=>c(M(t)))(t),m=(t,e,a)=>(((t,e)=>e in t)(t,e)||(t[e]=a()),t[e]),L=t=>new Map(t),T=(t,e)=>t?.get(e),H=(t,e,a)=>o(a)?(p(t,e),t):t?.set(e,a),P=(t,e,a,s)=>{var n,o;return n=t,o=e,n?.has(o)?s?.(T(t,e)):H(t,e,a()),T(t,e)},D=(t,e,a,s,n=0)=>r((a?P:T)(t,e[n],n>c(e)-2?a:L),o=>{if(n>c(e)-2)return s?.(o)&&H(t,e[n]),o;const r=D(o,e,a,s,n+1);return w(o)&&H(t,e[n]),r}),E=t("-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"),z=a.crypto?t=>a.crypto.getRandomValues(t):t=>(t=>t.map(()=>n(256*s.random())))(t),R=(t=16)=>{return e=(t,e)=>t+E[63&e],z(new Uint8Array(t)).reduce(e,"");var e},V=(t,e)=>e?[t,e]:[t],N=(t,e)=>((t??"")>(e??"")?t:e)??"",O=(t="")=>V(((t=[])=>f.fromEntries(t))(),t),$=/^\d+$/,j=t=>new Set(i(t)||o(t)?t:[t]),k=L(),x=L(),B=(t,e,a,s,n,f,b,v={},M=0,A=[])=>{let m,E,z,R=0,V=0,N=0;P(k,A,()=>0),P(x,A,()=>[]);const O=L(),[B,F,U,q,G]=((t=1,e,a)=>1!=t&&e.isMergeable()?[1,e.getMergeableContent,()=>e.getTransactionMergeableChanges(!a),([[t],[e]])=>!S(t)||!S(e),e.setDefaultContent]:2!=t?[0,e.getContent,e.getTransactionChanges,([t,e])=>!S(t)||!S(e),e.setContent]:l("Store type not supported by this Persister"))(b,t,M),[I,J,K]=(()=>{let t;const[e,a]=(()=>{const t=[];let e=0;return[a=>(a?d(t):null)??""+e++,e=>{$.test(e)&&c(t)<1e3&&y(t,e)}]})(),s=L();return[(a,n,o,r=[],i=()=>[])=>{t??=nt;const c=e(1);var l,g;return H(s,c,[a,n,o,r,i]),l=D(n,o??[""],j),g=c,l?.add(g),c},(e,a,...n)=>u(((t,e=[""])=>{const a=[],s=(t,n)=>n==c(e)?y(a,t):null===e[n]?h(t,t=>s(t,n+1)):u([e[n],null],e=>s(T(t,e),n+1));return s(t,0),a})(e,a),e=>h(e,e=>T(s,e)[0](t,...a??[],...n))),t=>r(T(s,t),([,e,n])=>(D(e,n??[""],void 0,e=>(p(e,t),w(e)?1:0)),H(s,t),a(t),n)),e=>r(T(s,e),([e,,a=[],s,n])=>{const r=(...i)=>{const l=c(i);l==c(a)?e(t,...i,...n(i)):o(a[l])?u(s[l]?.(...i)??[],t=>r(...i,t)):r(...i,a[l])};r()})]})(),Q=t=>{t!=R&&(R=t,J(O,void 0,R))},W=e=>{(B&&i(e?.[0])?1===e?.[2]?t.applyMergeableChanges:t.setMergeableContent:1===e?.[2]?t.applyChanges:t.setContent)(e)},X=async t=>(2!=R&&(Q(1),V++,await st(async()=>{await g(async()=>{const a=await e();i(a)?W(a):t?G(t):l("Content is not an array: "+a)},()=>{t&&G(t)}),Q(0)})),nt),Y=async t=>(Z(),await X(t),await g(async()=>E=await s(async(t,e)=>{e||t?2!=R&&(Q(1),V++,W(e??t),Q(0)):await X()}),f),nt),Z=async()=>(E&&(await g(()=>n(E),f),E=void 0),nt),_=async t=>(1!=R&&(Q(2),N++,await st(async()=>{await g(()=>a(F,t),f),Q(0)})),nt),tt=async()=>(et(),await _(),z=t.addDidFinishTransactionListener(()=>{const t=U();q(t)&&_(t)}),nt),et=async()=>(z&&(t.delListener(z),z=void 0),nt),at=async(t=!1)=>{const[e,a]=t?[et,Z]:[Z,et];return await e(),await a(),nt},st=async(...t)=>(y(T(x,A),...t),await(async()=>{if(!T(k,A)){for(H(k,A,1);!o(m=d(T(x,A)));)await g(m,f);H(k,A,0)}})(),nt),nt={load:X,startAutoLoad:Y,stopAutoLoad:Z,isAutoLoading:()=>!o(E),save:_,startAutoSave:tt,stopAutoSave:et,isAutoSaving:()=>!o(z),startAutoPersisting:async(t,e=!1)=>{const[a,s]=e?[tt,Y]:[Y,tt];return await a(t),await s(t),nt},stopAutoPersisting:at,getStatus:()=>R,addStatusListener:t=>I(t,O),delListener:e=>(K(e),t),schedule:st,getStore:()=>t,destroy:()=>(T(x,A).splice(0,void 0),at()),getStats:()=>({loads:V,saves:N}),...v};return C(nt)},F=(t,a,s,n,i)=>{const c=R(),l=new BroadcastChannel(a);return((t,a,s,n,i,c,l,u,y={})=>{let d,w=0,h=0,f=0;const b=L(),v=()=>R(11),M=(t,e,s,n)=>{h++,c?.(t,e,s,n),a(t,e,s,n)},C=async(t,a,s,n)=>new e((e,o)=>{const r=n+"."+R(4),c=((t,e=0)=>setTimeout(t,1e3*e))(()=>{p(b,r),o(`No response from ${t??"anyone"} to ${r}, `+a)},i);H(b,r,[t,(t,a)=>{clearTimeout(c),p(b,r),e([t,a,n])}]),M(t,r,a,s)}),P=(t,[e,a])=>{A(e,([e,a],s)=>{const n=m(t[0],s,O);A(e,([t,e],a)=>{const s=m(n[0],a,O);A(t,([t,e],a)=>s[0][a]=V(t,e)),s[1]=N(s[1],e)}),n[1]=N(n[1],a)}),t[1]=N(t[1],a)},D=(e=null,a,s=v())=>g(async()=>{o(a)&&([a,e,s]=await C(null,1,"",s));const[n,r]=a,[i,c]=t.getMergeableContentHashes();let l=O();if(i!=n){const[a,n]=(await C(e,4,t.getMergeableTableHashes(),s))[0];if(l=a,!S(n)){const[a,o]=(await C(e,5,t.getMergeableRowHashes(n),s))[0];if(P(l,a),!S(o)){const a=(await C(e,6,t.getMergeableCellHashes(o),s))[0];P(l,a)}}}return[l,c==r?O():(await C(e,7,t.getMergeableValueHashes(),s))[0],1]},u),E=B(t,async()=>{const t=await D();return!t||S(t[0][0])&&S(t[1][0])?void 0:t},async(e,a)=>a?M(null,v(),3,a):M(null,v(),2,t.getMergeableContentHashes()),t=>d=t,()=>d=void 0,u,2,{startSync:async t=>(w=1,await E.startAutoPersisting(t)),stopSync:async()=>(w=0,await E.stopAutoPersisting(),E),destroy:async()=>(await E.stopSync(),n(),E),getSynchronizerStats:()=>({sends:h,receives:f}),...y},1);return s((e,a,s,n)=>{const i=w||E.isAutoLoading();f++,l?.(e,a,s,n),0==s?r(T(b,a),([t,a])=>o(t)||t==e?a(n,e):0):2==s&&i?D(e,n,a??void 0).then(t=>{d?.(void 0,t)}).catch(u):3==s&&i?d?.(void 0,n):r(1==s&&(w||E.isAutoSaving())?t.getMergeableContentHashes():4==s?t.getMergeableTableDiff(n):5==s?t.getMergeableRowDiff(n):6==s?t.getMergeableCellDiff(n):7==s?t.getMergeableValueDiff(n):void 0,t=>{M(e,a,0,t)})}),E})(t,(t,e,a,s)=>l.postMessage([c,t,e,a,s]),t=>{l.onmessage=({data:[e,a,s,n,r]})=>o(a)||a==c?t(e,s,n,r):0},()=>{l.close()},.01,s,n,i,{getChannelName:()=>a})};export{F as createBroadcastChannelSynchronizer};