tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 7.22 kB
JavaScript
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),C=(t,...e)=>t.push(...e),M=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=k.keys,z=k.freeze,N=(t,e)=>p(E(t),([t,a])=>e(a,t)),R=t=>(t=>!c(t)&&d(O(t),t=>t==k.prototype||c(O(t)),()=>!0))(t)&&0==(t=>h(I(t)))(t),V=(t,e,a)=>(((t,e)=>e in t)(t,e)||(t[e]=a()),t[e]),x=t=>new Map(t),J=t=>[...t?.keys()??[]],$=(t,e)=>t?.get(e),j=(t,e,a)=>l(a)?(D(t,e),t):t?.set(e,a),F=(t,e,a,s)=>{var n,o;return n=t,o=e,n?.has(o)?s?.($(t,e)):j(t,e,a()),$(t,e)},U=(t,e,a,s,n=0)=>y((a?F:$)(t,e[n],n>h(e)-2?a:x),o=>{if(n>h(e)-2)return s?.(o)&&j(t,e[n]),o;const r=U(o,e,a,s,n+1);return P(o)&&j(t,e[n]),r}),W=/^\d+$/,q=t=>new Set(u(t)||l(t)?t:[t]),B=e=>{let a;const[s,n]=(()=>{const e=[];let a=0;return[s=>(s?M(e):null)??t+a++,t=>{W.test(t)&&h(e)<1e3&&C(e,t)}]})(),o=x();return[(n,r,i,c=[],l=()=>[])=>{a??=e();const g=s(1);var d,y;return j(o,g,[n,r,i,c,l]),d=U(r,i??[t],q),y=g,d?.add(y),g},(e,s,...n)=>p(((e,a=[t])=>{const s=[],n=(t,e)=>e==h(a)?C(s,t):g(a[e])?H(t,t=>n(t,e+1)):p([a[e],null],a=>n($(t,a),e+1));return n(e,0),s})(e,s),t=>H(t,t=>$(o,t)[0](a,...s??[],...n))),e=>y($(o,e),([,a,s])=>(U(a,s??[t],void 0,t=>(D(t,e),P(t)?1:0)),j(o,e),n(e),s)),t=>y($(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()})]},G=JSON.stringify,K=JSON.parse,Q=(t,e)=>{const a=t.indexOf("\n");-1!==a&&e(w(t,0,a),w(t,a+1))},X=(t,e)=>t+"\n"+e,Y=a("-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"),Z=o.crypto?t=>o.crypto.getRandomValues(t):t=>f(t,()=>i(256*r.random())),_=(e=16)=>b(Z(new Uint8Array(e)),(t,e)=>t+Y[63&e],t),tt=(t,e)=>e?[t,e]:[t],et=(t,e)=>((t??"")>(e??"")?t:e)??"",at=(t="")=>tt(((t=[])=>k.fromEntries(t))(),t),st=x(),nt=x(),ot=/\/([^?]*)/,rt=(a,n,o)=>{const r=x(),i=x(),c=x(),d=x(),[w,h,b]=B(()=>k),m=async t=>{await(t[1]?.destroy()),await(t[2]?.destroy())},T=(e,a,s)=>n=>Q(n,(n,o)=>{const r=X(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):$(a,n)?.send(r)});a.on("connection",(a,w)=>{return y((f=w.url,b=ot,f?.match(b)),([,f])=>y(w.headers["sec-websocket-key"],async w=>{const b=F(c,f,x),A=F(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=x(),L=()=>_(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+"."+_(4),c=((t,e=0)=>setTimeout(t,1e3*e))(()=>{D(A,i),o(`No response from ${t??"anyone"} to ${i}, `+e)},r);j(A,i,[t,(t,e)=>{clearTimeout(c),D(A,i),s([t,e,n])}]),m(t,i,e,a)}),T=(t,[e,a])=>{N(e,([e,a],s)=>{const n=V(t[0],s,at);N(e,([t,e],a)=>{const s=V(n[0],a,at);N(t,([t,e],a)=>s[0][a]=tt(t,e)),s[1]=et(s[1],e)}),n[1]=et(n[1],a)}),t[1]=et(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=at();if(i!=o){const[t,s]=(await P(a,4,e.getMergeableTableHashes(),n))[0];if(g=t,!R(s)){const[t,o]=(await P(a,5,e.getMergeableRowHashes(s),n))[0];if(T(g,t),!R(o)){const t=(await P(a,6,e.getMergeableCellHashes(o),n))[0];T(g,t)}}}return[g,c==r?at():(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;F(st,g,()=>0),F(nt,g,()=>[]);const b=x(),[A,L,m,P,T]=((t=1,e,a)=>1!=t&&e.isMergeable()?[1,e.getMergeableContent,()=>e.getTransactionMergeableChanges(!a),([[t],[e]])=>!R(t)||!R(e),e.setDefaultContent]:2!=t?[0,e.getContent,e.getTransactionChanges,([t,e])=>!R(t)||!R(e),e.setContent]:v("Store type not supported by this Persister"))(r,t,c),[H,D,k]=B(()=>K),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 t=>(2!=h&&(O(1),p++,await G(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)})),K),N=async t=>(V(),await I(t),await S(async()=>y=await s(async(t,e)=>{e||t?2!=h&&(O(1),p++,E(e??t),O(0)):await I()}),o),K),V=async()=>(y&&(await S(()=>n(y),o),y=void 0),K),J=async t=>(1!=h&&(O(2),f++,await G(async()=>{await S(()=>a(L,t),o),O(0)})),K),U=async()=>(W(),await J(),w=t.addDidFinishTransactionListener(()=>{const t=m();P(t)&&J(t)}),K),W=async()=>(w&&(t.delListener(w),w=void 0),K),q=async(t=!1)=>{const[e,a]=t?[W,V]:[V,W];return await e(),await a(),K},G=async(...t)=>(C($(nt,g),...t),await(async()=>{if(!$(st,g)){for(j(st,g,1);!l(d=M($(nt,g)));)await S(d,o);j(st,g,0)}})(),K),K={load:I,startAutoLoad:N,stopAutoLoad:V,isAutoLoading:()=>!l(y),save:J,startAutoSave:U,stopAutoSave:W,isAutoSaving:()=>!l(w),startAutoPersisting:async(t,e=!1)=>{const[a,s]=e?[U,N]:[N,U];return await a(t),await s(t),K},stopAutoPersisting:q,getStatus:()=>h,addStatusListener:t=>H(t,b),delListener:e=>(k(e),t),schedule:G,getStore:()=>t,destroy:()=>($(nt,g).splice(0,void 0),q()),getStats:()=>({loads:p,saves:f}),...i};return z(K)})(e,async()=>{const t=await H();return!t||R(t[0][0])&&R(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($(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)=>X(e??t,G(a,(t,e)=>l(e)?"":e)))(e,a,s,o)),t=>e[3]=e=>((t,e)=>Q(t,(t,a)=>{return e(t,...(s=a,K(s,(t,e)=>""===e?void 0:e)));var s}))(e,t),0,1,0,0,o),e[4]=[],e[5]=u(a)?a[1]:t=>0}))(A,f,b)),j(b,w,a),h(i,[f],w,1),a.on("message",t=>{const e=t.toString("utf8");0==A[0]?L(e):C(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:()=>J(c),getClientIds:t=>J($(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 z(k)};export{rt as createWsServer};