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