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