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