UNPKG

tinybase

Version:

A reactive data store and sync engine.

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