tinybase
Version:
A reactive data store and sync engine.
2 lines (1 loc) • 3.52 kB
JavaScript
const t=globalThis.window,e=t=>null==t,a=(t,a,n)=>e(t)?n?.():a(t),n=t=>Array.isArray(t),r=t=>t.length,s=t=>{throw Error(t)},o=(t,e)=>t.forEach(e),i=(t,...e)=>t.push(...e),c=t=>t.shift(),l=Object,g=t=>l.getPrototypeOf(t),u=l.keys,d=l.freeze,y=t=>(t=>!e(t)&&a(g(t),(t=>t==l.prototype||e(g(t))),(()=>!0)))(t)&&0==(t=>r(u(t)))(t),h=JSON.stringify,v=JSON.parse,p=t=>e(t)||0==(t=>t?.size??0)(t),w=(t,e)=>t?.forEach(e),S=(t,e)=>t?.delete(e),f=t=>new Map(t),C=(t,e)=>t?.get(e),A=(t,a,n)=>e(n)?(S(t,a),t):t?.set(a,n),L=(t,e,a,n)=>{var r,s;return r=t,s=e,r?.has(s)?n?.(C(t,e)):A(t,e,a()),C(t,e)},b=(t,e,n,s,o=0)=>a((n?L:C)(t,e[o],o>r(e)-2?n:f),(a=>{if(o>r(e)-2)return s?.(a)&&A(t,e[o]),a;const i=b(a,e,n,s,o+1);return p(a)&&A(t,e[o]),i})),M=/^\d+$/,E=t=>new Set(n(t)||e(t)?t:[t]),m=f(),O=f(),T=(t,l,g,u,h,v,T,N={},k=0,z=[])=>{let D,I,J,P=0,j=0,x=0;L(m,z,(()=>0)),L(O,z,(()=>[]));const F=f(),[V,$,q,B,G]=((t=1,e,a)=>1!=t&&e.isMergeable()?[1,e.getMergeableContent,()=>e.getTransactionMergeableChanges(!a),([[t],[e]])=>!y(t)||!y(e),e.setDefaultContent]:2!=t?[0,e.getContent,e.getTransactionChanges,([t,e])=>!y(t)||!y(e),e.setContent]:s("Store type not supported by this Persister"))(T,t,k),[H,K,Q]=(()=>{let t;const[n,s]=(()=>{const t=[];let e=0;return[a=>(a?c(t):null)??""+e++,e=>{M.test(e)&&r(t)<1e3&&i(t,e)}]})(),l=f();return[(e,a,r,s=[],o=()=>[])=>{t??=tt;const i=n(1);var c,g;return A(l,i,[e,a,r,s,o]),c=b(a,r??[""],E),g=i,c?.add(g),i},(e,a,...n)=>o(((t,e=[""])=>{const a=[],n=(t,s)=>s==r(e)?i(a,t):null===e[s]?w(t,(t=>n(t,s+1))):o([e[s],null],(e=>n(C(t,e),s+1)));return n(t,0),a})(e,a),(e=>w(e,(e=>C(l,e)[0](t,...a??[],...n))))),t=>a(C(l,t),(([,e,a])=>(b(e,a??[""],void 0,(e=>(S(e,t),p(e)?1:0))),A(l,t),s(t),a))),n=>a(C(l,n),(([a,,n=[],s,i])=>{const c=(...l)=>{const g=r(l);g==r(n)?a(t,...l,...i(l)):e(n[g])?o(s[g]?.(...l)??[],(t=>c(...l,t))):c(...l,n[g])};c()}))]})(),R=t=>{t!=P&&(P=t,K(F,void 0,P))},U=e=>{(V&&n(e?.[0])?1===e?.[2]?t.applyMergeableChanges:t.setMergeableContent:1===e?.[2]?t.applyChanges:t.setContent)(e)},W=async t=>(2!=P&&(R(1),j++,await _((async()=>{try{const e=await l();n(e)?U(e):t?G(t):s("Content is not an array: "+e)}catch(e){v?.(e),t&&G(t)}R(0)}))),tt),X=()=>(I&&(h(I),I=void 0),tt),Y=async t=>(1!=P&&(R(2),x++,await _((async()=>{try{await g($,t)}catch(t){v?.(t)}R(0)}))),tt),Z=()=>(J&&(t.delListener(J),J=void 0),tt),_=async(...t)=>(i(C(O,z),...t),await(async()=>{if(!C(m,z)){for(A(m,z,1);!e(D=c(C(O,z)));)try{await D()}catch(t){v?.(t)}A(m,z,0)}})(),tt),tt={load:W,startAutoLoad:async t=>{X(),await W(t);try{I=await u((async(t,e)=>{e||t?2!=P&&(R(1),j++,U(e??t),R(0)):await W()}))}catch(t){v?.(t)}return tt},stopAutoLoad:X,isAutoLoading:()=>!e(I),save:Y,startAutoSave:async()=>(Z(),await Y(),J=t.addDidFinishTransactionListener((()=>{const t=q();B(t)&&Y(t)})),tt),stopAutoSave:Z,isAutoSaving:()=>!e(J),getStatus:()=>P,addStatusListener:t=>H(t,F),delListener:e=>(Q(e),t),schedule:_,getStore:()=>t,destroy:()=>(C(O,z).splice(0,void 0),X().stopAutoSave()),getStats:()=>({loads:j,saves:x}),...N};return d(tt)},N="storage",k=(e,a,n,r)=>T(e,(async()=>{return t=n.getItem(a),v(t,((t,e)=>""===e?void 0:e));var t}),(async t=>{return n.setItem(a,(e=t(),h(e,((t,e)=>void 0===e?"":e))));var e}),(e=>{const r=t=>{if(t.storageArea===n&&t.key===a)try{e(v(t.newValue))}catch{e()}};return t.addEventListener(N,r),r}),(e=>t.removeEventListener(N,e)),r,3,{getStorageName:()=>a}),z=(t,e,a)=>k(t,e,localStorage,a),D=(t,e,a)=>k(t,e,sessionStorage,a);export{z as createLocalPersister,D as createSessionPersister};