stunk
Version:
Stunk is a lightweight, framework-agnostic state management library for JavaScript and TypeScript. It uses chunk-based state units for efficient updates, reactivity, and performance optimization in React, Vue(WIP), Svelte(Coming soon), and Vanilla JS/TS a
1 lines • 12 kB
JavaScript
var Ve=Object.defineProperty;var pe=(e,r)=>{for(var t in r)Ve(e,t,{get:r[t],enumerable:true});};function ge(e,r){if(e===void 0)throw new Error("Value cannot be undefined.");if(r.length===0)return e;let t=e;for(let d=0;d<r.length;d++){let n=r[d],s=typeof n=="function"?n:n.fn,y=typeof n=="function"?`index ${d}`:n.name||`index ${d}`;try{let u=s(t);if(u===void 0)break;if(u===null)throw new Error(`Middleware "${y}" returned null value.`);t=u;}catch(u){let a=u instanceof Error?u.message:String(u);throw new Error(`Middleware "${y}" threw an error: ${a}`)}}return t}function _(e,r){if(e===r)return true;if(!e||!r||typeof e!=typeof r)return false;if(Array.isArray(e)&&Array.isArray(r)){if(e.length!==r.length)return false;for(let t=0;t<e.length;t++)if(e[t]!==r[t])return false;return true}if(typeof e=="object"&&typeof r=="object"){let t=Object.keys(e),d=Object.keys(r);if(t.length!==d.length)return false;for(let n of t)if(!Object.prototype.hasOwnProperty.call(r,n)||e[n]!==r[n])return false;return true}return false}function Re(e){return e[Symbol.for("stunk.meta")]}var G=null;function K(e){let r=new Set,t=G;G=r;try{return [e(),Array.from(r)]}finally{G=t;}}function $e(e){G&&G.add(e);}var Z=false,te=new Set,ee=new Map,Fe=0;function je(e){let r=Z;Z=true;try{e();}finally{if(!r){Z=false;let t=[...te];te.clear(),t.forEach(d=>{let n=ee.get(d);n&&n.notify();});}}}function w(e,r={}){let t=Fe++,d=`chunk_${t}`,n=r.middleware||[];r.strict??false;if(e===void 0)throw new Error(`[${d}] Initial value cannot be undefined.`);let u=n.length>0,a=false,g=e,c=new Set,o=()=>{c.forEach(m=>m(g));};ee.set(t,{notify:o});let f=()=>{if(c.size===0){ee.delete(t);return}Z?te.add(t):o();},i=()=>($e(v),g),b=()=>g,A=m=>{let E;if(typeof m=="function"?E=m(g):E=m,a);let C=u?ge(E,n):E;C!==g&&(g=C,f());},k=m=>{if(typeof m!="function")throw new Error("Callback must be a function.");return c.add(m),()=>c.delete(m)},v={get:i,peek:b,set:A,subscribe:k,derive:m=>{if(typeof m!="function")throw new Error("Derive function must be a function.");let E=m(g),C=w(E),S=k(()=>{let p=m(g);C.set(p);}),M=C.destroy;return C.destroy=()=>{S(),M();},C},reset:()=>{g=e,f();},destroy:()=>{c.clear(),g=e,te.delete(t),ee.delete(t);}};return v}function he(e){let[r,t]=K(e),d=r,n=t,s=false,y=[],u=new Set,a=w(d),g=i=>i.map(b=>b.subscribe(()=>{s=true,(u.size>0||a.subscribe!==void 0)&&c();})),c=()=>{if(!s)return;s=false;let[i,b]=K(e);(b.length!==n.length||b.some(($,T)=>$!==n[T]))&&(y.forEach($=>$()),y=g(b),n=b),(typeof i=="object"&&i!==null&&typeof d=="object"&&d!==null?!_(i,d):i!==d)&&(d=i,a.set(i),u.forEach($=>$(d)));},o=()=>()=>{s=true,u.size>0&&c();};y=n.map(i=>i.subscribe(o()));let f;return f={get:()=>(s&&c(),a.get()),peek:()=>d,subscribe:i=>(u.add(i),()=>{u.delete(i);}),derive:i=>{let b=f.subscribe(()=>{}),A=he(()=>i(f.get())),k=A.destroy;return A.destroy=()=>{b(),k();},A},recompute:()=>{s=true,c();},isDirty:()=>s,destroy:()=>{y.forEach(i=>i()),u.clear(),a.destroy();}},f}function me(e,r,t={}){let{useShallowEqual:d=false}=t,n=e.get(),s=r(n),y=w(s),u=()=>{let f=e.get(),i=r(f);(d?!_(i,s):i!==s)&&(s=i,y.set(i));},a=e.subscribe(u),{set:g,reset:c,...o}=y;return {...o,derive:f=>me(y,f,t),destroy:()=>{a(),y.destroy();}}}var Ee={};pe(Ee,{history:()=>ke,logger:()=>Te,nonNegativeValidator:()=>be,persist:()=>Pe});function Te(){return e=>(console.log("Setting value:",e),e)}var be=e=>{if(e<0)throw new Error("Value must be non-negative!");return e};function ke(e,r={}){let{maxHistory:t=100,skipDuplicates:d=false}=r,n=[e.get()],s=0;return {...e,get:()=>e.get(),peek:()=>e.peek(),set:u=>{let a;if(typeof u=="function"?a=u(e.get()):a=u,d){let g=n[s];if(a===g||d==="shallow"&&typeof a=="object"&&typeof g=="object"&&a!==null&&g!==null&&_(a,g))return}if(n.splice(s+1),n.push(a),n.length>t){let g=n.length-t;n.splice(0,g);}s=n.length-1,e.set(a);},undo:()=>{s<=0||(s--,e.set(n[s]));},redo:()=>{s>=n.length-1||(s++,e.set(n[s]));},canUndo:()=>s>0,canRedo:()=>s<n.length-1,getHistory:()=>[...n],clearHistory:()=>{let u=e.get();n.length=0,n.push(u),s=0;},reset:()=>{e.reset(),n.length=0,n.push(e.get()),s=0;},destroy:()=>{n.length=0,e.destroy();},subscribe:u=>e.subscribe(u)}}function Pe(e,r){let{key:t,serialize:d=JSON.stringify,deserialize:n=JSON.parse,onError:s}=r,y="storage"in r?r.storage:typeof window<"u"?localStorage:void 0;if(!y)return console.warn(`persist: Storage not available for key "${t}". Persistence disabled.`),{...e,clearStorage:()=>{}};let u=e.get();try{let c=y.getItem(t);if(c!==null){let o=n(c);if(o!==null&&u!==null&&(typeof o!=typeof u||Array.isArray(o)!==Array.isArray(u))){let b=`persist: Type mismatch for "${t}". Expected ${Array.isArray(u)?"array":typeof u}, got ${Array.isArray(o)?"array":typeof o}. Using initial value.`;console.warn(b),s?.(new Error(b),"load");}else e.set(o);}}catch(c){let o=c instanceof Error?c:new Error(String(c));console.error(`persist: Failed to load state for "${t}":`,o),s?.(o,"load");}let a=e.subscribe(c=>{try{y.setItem(t,d(c));}catch(o){let f=o instanceof Error?o:new Error(String(o));console.error(`persist: Failed to save state for "${t}":`,f),s?.(f,"save");}});return {...e,get:()=>e.get(),peek:()=>e.peek(),set:c=>e.set(c),subscribe:c=>e.subscribe(c),derive:c=>e.derive(c),reset:()=>e.reset(),destroy:()=>{a(),e.destroy();},clearStorage:()=>{try{y.removeItem(t);}catch(c){let o=c instanceof Error?c:new Error(String(c));console.error(`persist: Failed to clear storage for "${t}":`,o),s?.(o,"save");}}}}var De={};pe(De,{asyncChunk:()=>ve,combineAsyncChunks:()=>we,configureQuery:()=>Ce,getGlobalQueryConfig:()=>I,infiniteAsyncChunk:()=>Se,mutation:()=>Ae,paginatedAsyncChunk:()=>re,resetQueryConfig:()=>xe});var H={};function Ce(e){H={...e.query!==void 0&&{query:{...H.query,...e.query}},...e.mutation!==void 0&&{mutation:{...H.mutation,...e.mutation}}};}function I(){return H}function xe(){H={};}var q=new Map,Ne=0;function ie(e,r={}){let t=I().query??{},{key:d,initialData:n=null,enabled:s=true,onSuccess:y=t.onSuccess,onError:u=t.onError,retryCount:a=t.retryCount??0,retryDelay:g=t.retryDelay??1e3,keepPreviousData:c=false,clearOnParamChange:o=false,staleTime:f=t.staleTime??0,cacheTime:i=t.cacheTime??5*60*1e3,refetchInterval:b=t.refetchInterval,refetchOnWindowFocus:A=t.refetchOnWindowFocus??false,pagination:k,scoped:$=false}=r,T={},ne=d??`async_chunk_${Ne++}`,v=()=>typeof s=="function"?s(T):s??true,m=!!k,E=k?.mode||"replace",C=!!k?.cursorMode,S=e.length>0,M={loading:v()&&!S,error:null,data:n,lastFetched:void 0,isPlaceholderData:false,pagination:m?{page:k.initialPage||1,pageSize:k.pageSize||10,total:void 0,hasMore:void 0,cursor:void 0}:void 0},p=w(M),z=null,F=null,j=null,J=0,Q=false,U=false,ue=()=>{let l=p.get();return !l.lastFetched||f===0?true:Date.now()-l.lastFetched>f},Me=()=>{p.set({...p.get(),data:n,lastFetched:void 0});},Oe=()=>{F&&clearTimeout(F),i>0&&(F=setTimeout(()=>{J<=0&&Me();},i));},B=()=>{z&&(clearInterval(z),z=null),F&&(clearTimeout(F),F=null),j&&typeof window<"u"&&(window.removeEventListener("focus",j),j=null);},oe=()=>{v()&&(typeof window>"u"||(b&&b>0&&!z&&(z=setInterval(()=>{x(void 0,0,false);},b)),A&&!j&&(j=()=>{ue()&&x(void 0,0,false);},window.addEventListener("focus",j))));},x=async(l,h=a,P=false)=>{if(!v()||(l!==void 0&&(T={...T,...l}),!P&&!ue()&&p.get().data!==null))return;let N=JSON.stringify(T),W=`${ne}:${N}`;if(q.has(W))return q.get(W);let X=p.get(),ae=X.data;p.set({...X,loading:true,error:null,data:X.data,isPlaceholderData:c&&X.data!==null});let le=(async()=>{try{let O={...T};if(m){let D=p.get().pagination;D&&(C?(O.cursor=D.cursor,O.pageSize=D.pageSize):(O.page=D.page,O.pageSize=D.pageSize));}let V=S?await e(O):await e();if(JSON.stringify(T)!==N||U)return;let R,de,fe,se;if(V&&typeof V=="object"&&"data"in V){let D=V;R=D.data,de=D.total,fe=D.hasMore,C&&(se=k.cursorMode.getNextCursor(D));}else R=V;let ye=p.get();m&&E==="accumulate"&&Q&&ae&&Array.isArray(ae)&&Array.isArray(R)&&(R=[...ae,...R]),p.set({loading:!1,error:null,data:R,lastFetched:Date.now(),isPlaceholderData:!1,pagination:m?{...ye.pagination,total:de,hasMore:C?se!==void 0:fe,cursor:C?se:ye.pagination.cursor}:void 0}),Oe(),y&&y(R);}catch(O){if(JSON.stringify(T)!==N)return;if(h>0&&!O?.nonRetryable)return await new Promise(R=>setTimeout(R,g)),q.delete(W),x(l,h-1,P);let V=p.get();p.set({loading:false,error:O,data:V.data,lastFetched:V.lastFetched,isPlaceholderData:false,pagination:V.pagination}),u&&u(O);}finally{q.delete(W);}})();return q.set(W,le),le};if(typeof s=="function"){let[,l]=K(()=>s(T)),h=v();l.forEach(P=>{P.subscribe(()=>{let N=v();!h&&N&&!S&&(B(),oe(),x(void 0,a,true)),h=N;});});}oe(),v()&&!S&&x();let ce={...p,subscribe:l=>{J++;let h=p.subscribe(l);return ()=>{h(),J--;}},cancel:()=>{U=true;let l=`${ne}:${JSON.stringify(T)}`;q.delete(l);let h=p.get();h.loading&&p.set({...h,loading:false});},reload:async l=>{if(U=false,!(S&&!m&&Object.keys(T).length===0)){if(m){let h=p.get();h.pagination&&p.set({...h,pagination:{...h.pagination,page:k?.initialPage||1,cursor:void 0}});}await x(l,a,true);}},refresh:async l=>{await x(l,a,false);},mutate:l=>{let h=p.get();p.set({...h,data:l(h.data)});},reset:(l=true)=>{B(),T={},p.set({...M,loading:v()&&l&&(m||!S)}),oe(),v()&&l&&(m||!S)&&x();},cleanup:()=>{J<=0&&B();},forceCleanup:()=>{B();},setParams:l=>{U=false;let h={...T};for(let P in l)l[P]===null?delete h[P]:h[P]=l[P];if(T=h,m){let P=p.get();P.pagination&&p.set({...P,data:o||E==="accumulate"?n:P.data,pagination:{...P.pagination,page:k?.initialPage||1,cursor:void 0}});}else if(o){let P=p.get();p.set({...P,data:n,error:null,lastFetched:void 0,isPlaceholderData:false});}v()&&x(T,a,true);},clearParams:()=>{T={},v()&&x(void 0,a,true);}},L;return m?L={...ce,nextPage:async()=>{let l=p.get();!l.pagination||l.pagination.hasMore===false||(C?(Q=true,await x(T,a,true),Q=false):(p.set({...l,pagination:{...l.pagination,page:l.pagination.page+1}}),Q=true,await x(T,a,true),Q=false));},prevPage:async()=>{if(C)return;let l=p.get();!l.pagination||l.pagination.page<=1||(p.set({...l,pagination:{...l.pagination,page:l.pagination.page-1}}),await x(T,a,true));},goToPage:async l=>{if(C)return;let h=p.get();!h.pagination||l<1||(p.set({...h,pagination:{...h.pagination,page:l}}),await x(T,a,true));},resetPagination:async()=>{let l=p.get();l.pagination&&(p.set({...l,data:E==="accumulate"?n:l.data,pagination:{...l.pagination,page:k?.initialPage||1,cursor:void 0}}),await x(T,a,true));}}:L=ce,$&&Object.defineProperty(L,"__scopedFactory",{value:()=>ie(e,r),enumerable:false,writable:false}),L}function ve(e,r={}){return ie(e,r)}function re(e,r){return ie(e,r)}function Se(e,r={}){let{pageSize:t=10,cursorMode:d,...n}=r;return re(e,{...n,pagination:{pageSize:t,mode:"accumulate",initialPage:1,cursorMode:d}})}function we(e){let r=Object.entries(e),t=r.reduce((a,[g,c])=>(a[g]=c.get().data,a),{}),d=r.reduce((a,[g,c])=>{let o=c.get().error;return o&&(a[g]=o),a},{}),n=r.some(([,a])=>a.get().loading),s=r.find(([,a])=>a.get().error)?.[1].get().error??null,u=w({loading:n,error:s,errors:d,data:t});return r.forEach(([a,g])=>{g.subscribe(()=>{let c=false,o=null,f={},i={...u.get().data};r.forEach(([b,A])=>{let k=A.get();k.loading&&(c=true),k.error&&(o||(o=k.error),f[b]=k.error),i[b]=k.data;}),u.set({loading:c,error:o,errors:f,data:i});});}),u}function Ae(e,r={}){let t=I().mutation??{},{invalidates:d=[],onSuccess:n=t.onSuccess,onError:s=t.onError,onSettled:y}=r,u={loading:false,data:null,error:null,isSuccess:false},a=w(u);return {mutate:async(...c)=>{let o=c[0];a.set({loading:true,data:null,error:null,isSuccess:false});try{let f=await e(o);return a.set({loading:!1,data:f,error:null,isSuccess:!0}),d.length>0&&await Promise.all(d.map(i=>"resetPagination"in i?i.resetPagination():i.reload())),n&&n(f,o),y&&y(f,null,o),{data:f,error:null}}catch(f){let i=f;return a.set({loading:false,data:null,error:i,isSuccess:false}),s&&s(i,o),y&&y(null,i,o),{data:null,error:i}}},get:()=>a.get(),subscribe:c=>a.subscribe(c),reset:()=>a.set(u)}}export{je as batch,w as chunk,he as computed,Re as getChunkMeta,Ee as middleware,De as query,me as select};