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