stroid 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/async.js CHANGED
@@ -1 +1 @@
1
- export{c as enableRevalidateOnFocus,a as fetchStore,d as getAsyncMetrics,b as refetchStore}from'./chunk-3CAQKMKY.js';import'./chunk-VNLWP332.js';
1
+ export{c as enableRevalidateOnFocus,a as fetchStore,d as getAsyncMetrics,b as refetchStore}from'./chunk-G6JMMJYH.js';import'./chunk-5F2FD6DX.js';
@@ -0,0 +1,17 @@
1
+ var Mt=typeof process<"u"&&typeof process.env?.NODE_ENV=="string"?process.env.NODE_ENV:void 0,zt=typeof import.meta<"u"&&import.meta?.env?.MODE?import.meta.env.MODE:void 0,bt=typeof globalThis<"u"&&typeof globalThis.__STROID_DEV__=="boolean"?globalThis.__STROID_DEV__:void 0,Ft=typeof process<"u"?"development":"production",qt=Mt??zt??Ft,H=typeof bt=="boolean"?bt:qt!=="production",w=()=>H,p=H?t=>{console.warn(`[stroid] ${t}`);}:()=>{},R=H?t=>{console.error(`[stroid] ${t}`);}:()=>{},j=H?t=>{console.log(`[stroid] ${t}`);}:()=>{},st=null,Lt=()=>{if(st)return st;let t,e=[];for(let n=0;n<256;n++){t=n;for(let r=0;r<8;r++)t=t&1?3988292384^t>>>1:t>>>1;e[n]=t>>>0;}return st=e,e},vt=t=>{let e=Lt(),n=-1;for(let r=0;r<t.length;r++)n=n>>>0,n=n>>>8^e[(n^t.charCodeAt(r))&255];return (n^-1)>>>0},G=t=>{try{return vt(JSON.stringify(t))}catch{return vt(String(t))}},Ut=typeof globalThis<"u"&&typeof globalThis.structuredClone=="function",h=t=>{try{return Ut?structuredClone(t):JSON.parse(JSON.stringify(t))}catch{return Array.isArray(t)?[...t]:t&&typeof t=="object"?{...t}:t}};var it=(t,e)=>{try{let n=h(t);return e(n),n}catch(n){throw new Error(`produceClone failed (possible circular reference or unserializable data): ${n?.message??n}`)}},at=(t,e)=>{if(!t)return {ok:true};try{if(typeof t.safeParse=="function"){let n=t.safeParse(e);return n.success?{ok:!0,data:n.data}:{ok:!1,error:n.error}}if(typeof t.parse=="function")return t.parse(e),{ok:!0,data:e};if(typeof t.validateSync=="function")return t.validateSync(e),{ok:!0,data:e};if(typeof t.isValidSync=="function")return t.isValidSync(e)?{ok:!0,data:e}:{ok:!1,error:"Schema validation failed"};if(typeof t.validate=="function")return t.validate(e)?{ok:!0,data:e}:{ok:!1,error:t.errors||"Schema validation failed"};if(typeof t=="function"){let n=t(e);return n===!1?{ok:!1,error:"Schema validation failed"}:{ok:!0,data:n===!0?e:n}}return {ok:!0,data:e}}catch(n){return {ok:false,error:n?.message??n}}};var C=t=>t===null?"null":Array.isArray(t)?"array":t instanceof Map?"map":t instanceof Set?"set":t instanceof Date?"date":typeof t=="function"?"function":typeof t,F=t=>{let e=C(t);return e==="function"?(R(`Functions cannot be stored in stroid.
2
+ Store data only - handle functions outside the store.`),false):e==="map"||e==="set"?(p(`Map/Set detected. stroid converts these to plain objects.
3
+ Use arrays or plain objects for best results.`),true):(e==="date"&&p(`Date object detected. stroid stores it as ISO string.
4
+ Use new Date(value) to convert back when reading.`),true)},O=t=>{let e=C(t);if(e==="date")return w()&&p("Date detected; stored as ISO string. Use new Date(value) when reading."),t.toISOString();if(e==="map")return w()&&p("Map detected; converting to plain object."),Object.fromEntries(t);if(e==="set")return w()&&p("Set detected; converting to array."),Array.from(t);if(e==="object"){let n={};for(let r in t)n[r]=O(t[r]);return n}return e==="array"?t.map(O):t},kt=10,Kt=5,q=t=>Array.isArray(t)?[...t]:typeof t=="string"&&!t.includes(".")?[t]:typeof t=="string"?t.split("."):[String(t)],ct=t=>{let e=q(t),n=e.length;return n>kt?(R(`Path depth of ${n} exceeded maximum of ${kt}.
5
+ "${e.join(".")}"
6
+ This is a data design issue. Split into separate stores:
7
+ createStore("${e[0]}", ...) and createStore("${e[1]}", ...)`),false):(n>Kt&&p(`Deep nesting detected (${n} levels): "${e.join(".")}"
8
+ Consider splitting into separate stores for better readability.`),true)},wt=(t,e)=>{let n=q(e),r=t;for(let o of n){if(r==null){p(`Path "${n.join(".")}" not found - reached null at "${o}"`);return}if(typeof r!="object"){p(`Cannot go deeper at "${o}" - value is not an object`);return}r=r[o];}return r},xt=(t,e,n)=>{let r=q(e);if(r.length===0)return t;let o=(s,a)=>{let l=r[a],f=a===r.length-1;if(Array.isArray(s)){let i=Number(l);if(!Number.isInteger(i))return s;let d=[...s];return f?(d[i]=n,d):(d[i]=o(d[i],a+1),d)}if(s&&typeof s=="object"){let i={...s};return f?(i[l]=n,i):(i[l]=o(i[l],a+1),i)}return s};return o(t,0)},$t=t=>typeof t!="string"||t.trim()===""?(R(`Store name must be a non-empty string. Got: ${JSON.stringify(t)}`),false):t.includes(" ")?(R(`Store name "${t}" contains spaces.
9
+ Use camelCase or kebab-case: "userName" or "user-name"`),false):true,Tt=(t,e)=>{let n=e.find(r=>{let o=r.toLowerCase(),s=t.toLowerCase();return o.includes(s)||s.includes(o)||Bt(o,s)<=2});n?p(`Store "${t}" not found. Did you mean "${n}"?`):R(`Store "${t}" not found.
10
+ Available stores: [${e.join(", ")}]
11
+ Call createStore("${t}", data) first.`);},Bt=(t,e)=>{let n=Array.from({length:e.length+1},(r,o)=>Array.from({length:t.length+1},(s,a)=>o===0?a:a===0?o:0));for(let r=1;r<=e.length;r++)for(let o=1;o<=t.length;o++)n[r][o]=e[r-1]===t[o-1]?n[r-1][o-1]:Math.min(n[r-1][o-1],n[r][o-1],n[r-1][o])+1;return n[e.length][t.length]};var L=t=>{if(typeof t!="object"||t===null)return t;Object.freeze(t);for(let e of Object.keys(t)){let n=t[e];typeof n=="object"&&n!==null&&!Object.isFrozen(n)&&L(n);}return t};var u=Object.create(null),_=Object.create(null),D=Object.create(null),c=Object.create(null),x=Object.create(null),B=Object.create(null),V=Object.create(null),Y=Object.create(null),Z=new Set,lt=false,U=0,et=`stroid_${Math.random().toString(16).slice(2)}`,ut={},Q=Object.create(null),N=Object.create(null),_t=false,Rt=t=>typeof t=="string"?t:t.name,K,X=(()=>{let t=new Map;return {getItem:e=>t.has(e)?t.get(e):null,setItem:(e,n)=>{t.set(e,n);},removeItem:e=>{t.delete(e);},type:"memory"}})(),Ot=()=>{if(lt)return;lt=true;let t=()=>{lt=false,Z.forEach(e=>{let n=_[e];if(!n||n.length===0)return;let r=typeof performance<"u"&&performance.now?performance.now():Date.now(),o=h(u[e]);n.forEach(f=>{try{f(o);}catch(i){p(`Subscriber for "${e}" threw: ${i?.message??i}`);}});let a=(typeof performance<"u"&&performance.now?performance.now():Date.now())-r,l=c[e]?.metrics||{notifyCount:0,totalNotifyMs:0,lastNotifyMs:0};l.notifyCount+=1,l.totalNotifyMs+=a,l.lastNotifyMs=a,c[e]&&(c[e].metrics=l);}),Z.clear();};typeof queueMicrotask=="function"?queueMicrotask(t):Promise.resolve().then(t);},J=t=>{Z.add(t),U===0&&Ot();},M=t=>u[t]!==void 0?true:(Tt(t,Object.keys(u)),false),Jt=(t,e,n,r)=>{let o=q(n);if(o.length===0)return {ok:true};if(e==null){let a=`Cannot set "${o.join(".")}" on "${t}" because the store value is ${e===null?"null":"undefined"}.`;return p(a),{ok:false,reason:a}}let s=e;for(let a=0;a<o.length;a++){let l=o[a],f=a===o.length-1;if(s==null||typeof s!="object"){let d=`Path "${o.join(".")}" is invalid for "${t}" - "${o.slice(0,a).join(".")||"root"}" is not an object.`;return p(d),{ok:false,reason:d}}if(Array.isArray(s)){let d=Number(l);if(!Number.isInteger(d)||d<0){let g=`Path "${o.join(".")}" targets non-numeric index "${l}" on an array in "${t}".`;return p(g),{ok:false,reason:g}}let y=s;if(d>=y.length){let g=`Path "${o.join(".")}" is invalid for "${t}" - index ${d} is out of bounds (length ${y.length}).`;return p(g),{ok:false,reason:g}}if(f){let g=y[d];if(g!==void 0){let k=C(g),T=C(r);if(k!==T){let P=`Type mismatch setting "${o.join(".")}" on "${t}": expected ${k}, received ${T}.`;return p(P),{ok:false,reason:P}}}return {ok:true}}s=y[d];continue}if(!Object.prototype.hasOwnProperty.call(s,l)){let d=`Path "${o.join(".")}" does not exist on store "${t}" (missing "${l}").`;return p(d),{ok:false,reason:d}}if(f){let d=s[l];if(d!==void 0){let y=C(d),g=C(r);if(y!==g){let k=`Type mismatch setting "${o.join(".")}" on "${t}": expected ${y}, received ${g}.`;return p(k),{ok:false,reason:k}}}return {ok:true}}s=s[l];}return {ok:true}},dt=t=>{try{return typeof window>"u"?X:t==="session"||t==="sessionStorage"?window.sessionStorage??X:window.localStorage??X}catch{return X}},Wt=(t,e)=>{N[t]&&(N[t].lastPresent=e);},Ht=(t,e)=>{if(!t)return null;let n={key:`stroid_${e}`,serialize:JSON.stringify,deserialize:JSON.parse,encrypt:r=>r,decrypt:r=>r,onMigrationFail:"reset"};return t===true?{driver:dt("localStorage"),...n}:typeof t=="string"?{driver:dt(t),...n}:{driver:t.driver||t.storage||dt("localStorage"),key:t.key||n.key,serialize:t.serialize||n.serialize,deserialize:t.deserialize||n.deserialize,encrypt:t.encrypt||n.encrypt,decrypt:t.decrypt||n.decrypt,onMigrationFail:t.onMigrationFail||"reset",onStorageCleared:t.onStorageCleared}},Gt=t=>{let e=c[t]?.options?.persist,n=e?.onStorageCleared;if(!e||typeof n!="function"||typeof window>"u"||typeof window.addEventListener!="function")return;N[t]?.dispose();let r=window,o=()=>{try{return e.driver.getItem?.(e.key)!=null}catch{return false}},s=f=>{let i=N[t],d=o();if(i){if(!i.lastPresent||d){i.lastPresent=d;return}i.lastPresent=false,n({name:t,key:e.key,reason:f});}},a=f=>{if(f.key===null){s("clear");return}f.key===e.key&&f.newValue===null&&s("remove");},l=()=>{s("missing");};r.addEventListener("storage",a),r.addEventListener("focus",l),N[t]={lastPresent:o(),dispose:()=>{r.removeEventListener("storage",a),r.removeEventListener("focus",l);}};},Xt=t=>{if(!c[t]?.options?.devtools||typeof window>"u")return;let n=window.__REDUX_DEVTOOLS_EXTENSION__||window.__REDUX_DEVTOOLS_EXTENSION__;if(!n||typeof n.connect!="function"){p(`DevTools requested for "${t}" but Redux DevTools extension not found.`);return}K||(K=n.connect({name:"stroid"}),K.init(u));},tt=(t,e)=>{let n=c[t]?.options?.redactor;if(typeof n=="function")try{return n(h(e))}catch{return e}return e},Yt=t=>typeof TextEncoder<"u"?new TextEncoder().encode(t).length:typeof Buffer<"u"?Buffer.byteLength(t):t.length,v=(t,e)=>{c[t]?.options?.onError?.(e),p(e);},ft=(t,e,n)=>{v(t,n);let r=c[t]?.options?.persist?.onMigrationFail??"reset";if(r==="keep")return {state:e,requiresValidation:false};if(typeof r=="function")try{let o=r(h(e));if(o!==void 0)return {state:O(o),requiresValidation:!0};v(t,`onMigrationFail for "${t}" returned undefined. Falling back to initial state.`);}catch(o){v(t,`onMigrationFail for "${t}" failed: ${o?.message??o}`);}return {state:h(D[t]),requiresValidation:false}},Zt=(t,e)=>{if(typeof t!="object"||typeof e!="object"||t===null||e===null)return null;let n=t,r=e,o=[],s=[],a=[],l=new Set(Object.keys(n)),f=new Set(Object.keys(r));return f.forEach(i=>{l.has(i)?Object.is(n[i],r[i])||a.push(i):o.push(i);}),l.forEach(i=>{f.has(i)||s.push(i);}),{added:o,removed:s,changed:a}},nt=(t,e,n,r)=>{let o=c[t]?.options?.historyLimit??50;if(o===0)return;x[t]||(x[t]=[]);let s={ts:Date.now(),action:e,prev:tt(t,n),next:tt(t,r),diff:Zt(n,r)};x[t].push(s),x[t].length>o&&x[t].splice(0,x[t].length-o);},rt=(t,e,n=false)=>{if(!(!K||!n&&!c[t]?.options?.devtools))try{let r={...u,[t]:tt(t,u[t])};K.send({type:`${t}/${e}`},r);}catch{}},Vt=(t,e)=>{let n=c[t]?.options?.middleware||[];if(!Array.isArray(n))return e.next;let r=e.next;for(let o of n){if(typeof o!="function")continue;let s;try{s=o({action:e.action,name:t,prev:e.prev,next:r,path:e.path});}catch(a){let l=`Middleware for "${t}" failed: ${a?.message??a}`;c[t]?.options?.onError?.(l),p(l);continue}s!==void 0&&(r=s);}return r},A=(t,e)=>{let n=c[t]?.options?.schema;if(!n)return {ok:true};let r=at(n,e);return r.ok||v(t,`Schema validation failed for "${t}": ${r.error}`),r},pt=t=>{let e=c[t]?.options?.persist;e&&(ut[t]&&clearTimeout(ut[t]),ut[t]=setTimeout(()=>{try{let n=e.serialize(u[t]),r=G(n),o=JSON.stringify({v:c[t]?.version??1,checksum:r,data:n}),s=e.encrypt(o);e.driver.setItem?.(e.key,s),Wt(t,!0);}catch(n){v(t,`Could not persist store "${t}" (${n?.message||n})`);}},0));},Qt=(t,{silent:e}={silent:false})=>{let n=c[t]?.options?.persist;if(n)try{let r=n.driver.getItem?.(n.key)??null;if(!r)return;let o=n.decrypt(r),s=JSON.parse(o),{v:a=1,checksum:l,data:f}=s||{};if(!f)return;if(l!==G(f)){v(t,`Checksum mismatch loading store "${t}". Falling back to initial state.`),u[t]=h(D[t]);return}let i=n.deserialize(f),d=c[t]?.version??1;if(a!==d){let g=c[t]?.options?.migrations||{},k=Object.keys(g).map(S=>Number(S)).filter(S=>S>a&&S<=d).sort((S,m)=>S-m);if(k.length===0){let S=ft(t,i,`No migration path from v${a} to v${d} for "${t}". Applying onMigrationFail strategy.`);if(i=S.state,!S.requiresValidation){u[t]=i;return}}let T=!1,P=!0;if(k.forEach(S=>{if(!T)try{let m=g[S](i);m!==void 0&&(i=m);}catch(m){let z=ft(t,i,`Migration to v${S} failed for "${t}": ${m?.message||m}`);i=z.state,P=z.requiresValidation,T=!0;}}),T){if(!P){u[t]=i;return}if(!A(t,i).ok){u[t]=h(D[t]);return}u[t]=i;return}}if(!A(t,i).ok){if(a!==d){let g=ft(t,i,`Persisted state for "${t}" failed schema after version change. Applying onMigrationFail strategy.`);if(!g.requiresValidation){u[t]=g.state;return}if(A(t,g.state).ok){u[t]=g.state;return}}v(t,`Persisted state for "${t}" failed schema; resetting to initial.`),u[t]=h(D[t]);return}u[t]=i,e||j(`Store "${t}" loaded from persistence`);}catch(r){v(t,`Could not load store "${t}" (${r?.message||r})`);}},W=(t,e,n={})=>{if(!$t(t)||!F(e))return;let r=typeof window>"u",o=typeof process<"u"?process.env?.NODE_ENV:void 0,s=r&&o==="production",a=n.allowSSRGlobalStore??false;if(s&&!a){w()&&R(`createStore("${t}") is blocked on the server in production to prevent cross-request memory leaks.
12
+ Call createStoreForRequest(...) inside each request scope or pass { allowSSRGlobalStore: true } to opt in.`);return}if(u[t]!==void 0){let b=`Store "${t}" already exists. Call setStore("${t}", data) to update instead.`;return p(b),c[t]?.options?.onError?.(b),{name:t}}let{persist:l=false,devtools:f=false,middleware:i=[],onSet:d,onReset:y,onDelete:g,onCreate:k,onError:T,validator:P,schema:S,migrations:m={},version:z=1,redactor:Ct,historyLimit:Nt=50,sync:At,allowSSRGlobalStore:St=a}=n;r&&!St&&!_t&&w()&&(_t=true,p(`createStore("${t}") called in a server environment. Use createStoreForRequest(...) per request to avoid cross-request leaks or pass { allowSSRGlobalStore: true } if you really want a global store on the server.`));let I=Ht(l,t);if(I?.key){let b=Q[I.key];b&&b!==t&&w()?p(`Persist key collision: "${I.key}" already used by store "${b}". Store "${t}" will overwrite the same storage key.`):Q[I.key]=t;}let E=O(e),It={persist:I,devtools:!!f,middleware:i??[],onSet:d,onReset:y,onDelete:g,onCreate:k,onError:T,validator:P,schema:S,migrations:m,version:z,redactor:Ct,historyLimit:Nt,sync:At??false,allowSSRGlobalStore:St},ht=S?at(S,E):{ok:true};if(!ht.ok){let b=`Schema validation failed for "${t}": ${ht.error}`;T?.(b),p(b);return}if(P&&P(E)===false){let b=`Validator blocked initial state for "${t}"`;T?.(b),p(b);return}return u[t]=E,_[t]=_[t]||[],D[t]=h(E),c[t]={createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),updateCount:0,version:z,metrics:{notifyCount:0,totalNotifyMs:0,lastNotifyMs:0},options:It},I&&(pt(t),Qt(t,{silent:true}),Gt(t)),c[t].options.onCreate?.(E),Xt(t),ne(t),nt(t,"create",null,E),j(`Store "${t}" created -> ${JSON.stringify(E)}`),{name:t}};function $(t,e,n){let r=Rt(t);if(!M(r))return;let o,s=u[r];if(typeof e=="function"&&n===void 0)o=it(s,e);else if(typeof e=="object"&&!Array.isArray(e)&&n===void 0){if(!F(e))return;o={...s,...O(e)};}else if(typeof e=="string"||Array.isArray(e)){if(!ct(e))return;let d=O(n),y=Jt(r,s,e,d);if(!y.ok){w()&&c[r]?.options?.onError?.(y.reason??`Invalid path for "${r}".`);return}o=xt(s,e,d);}else {R(`setStore("${r}") - invalid arguments.
13
+ Usage:
14
+ setStore("${r}", "field", value)
15
+ setStore("${r}", "nested.field", value)
16
+ setStore("${r}", { field: value })`);return}if(!F(o))return;let a=O(o);if(!A(r,a).ok)return;let f=c[r]?.options?.validator;if(f&&f(a)===false){c[r]?.options?.onError?.(`Validator blocked update for "${r}"`);return}let i=Vt(r,{action:"set",prev:s,next:a,path:e});u[r]=w()?L(i):i,c[r].updatedAt=new Date().toISOString(),c[r].updateCount++,yt(r),c[r].options?.persist&&pt(r),c[r].options.onSet?.(s,i),nt(r,"set",s,i),rt(r,"set"),ot(r),J(r),j(`Store "${r}" updated`);}var ue=t=>{U++;try{t();}finally{U=Math.max(0,U-1),U===0&&Z.size>0&&Ot();}};function gt(t,e){let n=Rt(t);if(!M(n))return null;let r=u[n];return e===void 0?Array.isArray(r)?[...r]:r&&typeof r=="object"?{...r}:r:ct(e)?wt(r,e):null}var Dt=t=>{if(!M(t))return;_[t]?.forEach(o=>o(null)),c[t].options.onDelete?.(u[t]);let n=c[t].options.persist,r=c[t].options.devtools;delete u[t],delete _[t],delete D[t],delete c[t];try{n?.driver?.removeItem&&n.driver.removeItem(n.key);}catch{}n?.key&&Q[n.key]===t&&delete Q[n.key],N[t]?.dispose(),delete N[t],B[t]?.close(),delete B[t],Y[t]?.(),delete Y[t],delete V[t],r&&rt(t,"delete",true),j(`Store "${t}" deleted`);},Et=t=>{if(!M(t)||!D[t])return;let e=u[t],n=h(D[t]);u[t]=w()?L(n):n,c[t].updatedAt=new Date().toISOString(),yt(t),c[t].options.onReset?.(e,n),nt(t,"reset",e,n),rt(t,"reset"),ot(t),J(t),j(`Store "${t}" reset to initial state/value`);},de=(t,e)=>{if(!M(t)||!F(e))return;let n=u[t];if(typeof n!="object"||Array.isArray(n)||n===null){R(`mergeStore("${t}") only works on object stores.
17
+ Use setStore("${t}", value) instead.`);return}let r={...n,...O(e)};if(!A(t,r).ok)return;let s=c[t]?.options?.validator;if(s&&s(r)===false){c[t]?.options?.onError?.(`Validator blocked update for "${t}"`);return}let a=Vt(t,{action:"merge",prev:n,next:r,path:null});u[t]=w()?L(a):a,c[t].updatedAt=new Date().toISOString(),c[t].updateCount++,yt(t),c[t].options?.persist&&pt(t),c[t].options.onSet?.(n,a),nt(t,"merge",n,a),rt(t,"merge"),ot(t),J(t),j(`Store "${t}" merged with data`);},fe=()=>{let t=Object.keys(u);t.forEach(Dt),p(`All stores cleared (${t.length} stores removed)`);},te=t=>u[t]!==void 0,pe=()=>Object.keys(u),ge=t=>M(t)?{...c[t]}:null,jt=(t,e)=>(_[t]||(_[t]=[]),_[t].push(e),()=>{_[t]=_[t].filter(n=>n!==e);}),ye=t=>u[t]??null,yt=t=>(V[t]=(V[t]??0)+1,V[t]),Pt=(t,e)=>(V[t]=Math.max(V[t]??0,e)+1,V[t]),ee=(t,e)=>{let n=V[t]??0,r=typeof e.clock=="number"?e.clock:0;if(r!==n)return r-n;let o=new Date(c[t]?.updatedAt||0).getTime(),s=typeof e.updatedAt=="number"?e.updatedAt:0;if(s!==o)return s-o;let a=et;return (e.source??"").localeCompare(a)},mt=t=>{let e=B[t];if(e)try{e.postMessage({type:"sync-request",source:et,name:t,requestedAt:Date.now()});}catch(n){v(t,`Failed to request sync snapshot for "${t}": ${n?.message??n}`);}},ne=t=>{let e=c[t]?.options?.sync;if(!e)return;if(typeof window>"u"||typeof BroadcastChannel>"u"){v(t,`Sync enabled for "${t}" but BroadcastChannel not available in this environment.`);return}let n=typeof e=="object"&&e.channel?e.channel:`stroid_sync_${t}`;try{let r=new BroadcastChannel(n);if(B[t]=r,r.onmessage=o=>{let s=o.data;if(!s||s.source===et||s.name!==t)return;if(s.type==="sync-request"){ot(t);return}let a=typeof e=="object"?e.conflictResolver:null;if(ee(t,{clock:s.clock,updatedAt:s.updatedAt,source:s.source})<=0){let i=new Date(c[t]?.updatedAt||0).getTime(),d=s.updatedAt;if(a){let y=a({local:u[t],incoming:s.data,localUpdated:i,incomingUpdated:d});if(y!==void 0){if(!A(t,y).ok)return;u[t]=y,c[t].updatedAt=new Date(Math.max(i,d)).toISOString(),c[t].updateCount++,Pt(t,typeof s.clock=="number"?s.clock:0),J(t);}}return}A(t,s.data).ok&&(u[t]=s.data,c[t].updatedAt=new Date(s.updatedAt).toISOString(),c[t].updateCount++,Pt(t,typeof s.clock=="number"?s.clock:0),J(t));},typeof window<"u"&&typeof window.addEventListener=="function"){Y[t]?.();let o=window,s=()=>{mt(t);};o.addEventListener("focus",s),o.addEventListener("online",s),Y[t]=()=>{o.removeEventListener("focus",s),o.removeEventListener("online",s);};}queueMicrotask(()=>{mt(t);});}catch(r){p(`Failed to setup sync for "${t}": ${r?.message||r}`);}},ot=t=>{let e=B[t];if(e)try{let n=c[t]?.options?.sync,r={type:"sync-state",source:et,name:t,clock:V[t]??0,updatedAt:Date.parse(c[t]?.updatedAt||new Date().toISOString()),data:tt(t,u[t]),checksum:G(u[t])},o=typeof n=="object"&&typeof n.maxPayloadBytes=="number"?n.maxPayloadBytes:64*1024,s=Yt(JSON.stringify(r));if(s>o){v(t,`Sync payload for "${t}" exceeds ${o} bytes (${s} bytes). Skipping BroadcastChannel sync.`);return}e.postMessage(r);}catch(n){v(t,`Failed to broadcast sync for "${t}": ${n?.message??n}`);}},Se=(t,e)=>{let n,r;return ()=>{let o=u[t];return o===void 0?null:(o===n||(n=o,r=e(o)),r??null)}},re=(t,e,n=Object.is,r)=>{if(typeof e!="function"||typeof r!="function")return p(`subscribeWithSelector("${t}") requires selector and listener functions.`),()=>{};let o=e(u[t]);return jt(t,a=>{let l=e(a);if(!n(l,o)){let f=o;o=l,r(l,f);}})},he=(t,e=0,n={})=>(W(t,{value:e},n),{inc:(r=1)=>$(t,o=>{o.value+=r;}),dec:(r=1)=>$(t,o=>{o.value-=r;}),set:r=>$(t,"value",r),reset:()=>Et(t),get:()=>gt(t,"value")}),be=(t,e=[],n={})=>(W(t,{items:e},n),{push:r=>$(t,o=>{o.items.push(r);}),removeAt:r=>$(t,o=>{o.items.splice(r,1);}),clear:()=>$(t,{items:[]}),replace:r=>$(t,{items:r}),all:()=>gt(t,"items")}),ve=(t,e={})=>(W(t,{entities:{},ids:[]},e),{upsert:n=>$(t,r=>{let o=n.id??n._id??(typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}_${Math.random().toString(16).slice(2)}`);r.ids.includes(o)||r.ids.push(o),r.entities[o]=n;}),remove:n=>$(t,r=>{r.ids=r.ids.filter(o=>o!==n),delete r.entities[n];}),all:()=>{let n=u[t];return n?n.ids.map(r=>n.entities[r]):[]},get:n=>gt(t,`entities.${n}`),clear:()=>Et(t)}),ke=()=>h(u),we=(t,e)=>{if(!x[t])return [];let n=x[t];return e&&e>0?n.slice(-e):[...n]},xe=t=>{t?delete x[t]:Object.keys(x).forEach(e=>delete x[e]);},$e=t=>{let e=c[t];return e?.metrics?{...e.metrics}:null},Te=t=>{let e={};return typeof t=="function"&&t({create:(r,o,s={})=>(e[r]=h(o),e[r]),set:(r,o)=>{if(e[r])return e[r]=typeof o=="function"?it(e[r],o):o,e[r]},get:r=>h(e[r])}),{snapshot:()=>h(e),hydrate:(r={})=>oe(e,r)}},oe=(t,e={})=>{!t||typeof t!="object"||Object.entries(t).forEach(([n,r])=>{te(n)?$(n,r):W(n,r,e[n]||e.default||{});});},_e=(t,e={})=>{let n=e.name||`zstore_${Date.now()}`,r=(l,f=false)=>{let i=u[n]??{},d=typeof l=="function"?l(i):l,y=f?d:{...i,...d};$(n,y);},o=()=>u[n],s={setState:r,getState:o,subscribe:l=>jt(n,l),subscribeWithSelector:(l,f=Object.is,i)=>re(n,l,f,i??(()=>{})),destroy:()=>Dt(n)},a=t(r,o,s);return W(n,a,e),s};export{oe as A,_e as B,w as a,p as b,R as c,W as d,$ as e,ue as f,gt as g,Dt as h,Et as i,de as j,fe as k,te as l,pe as m,ge as n,jt as o,ye as p,Se as q,re as r,he as s,be as t,ve as u,ke as v,we as w,xe as x,$e as y,Te as z};
@@ -0,0 +1,5 @@
1
+ import {c,a as a$1,b as b$1,l,d,e,o}from'./chunk-5F2FD6DX.js';var R={},u={},f={},b={},x=new Set,_={},a={},Y=e=>new Promise(t=>setTimeout(t,e)),Z=(e,t)=>{if(!t)return false;let r=b[e];return r?Date.now()-r.timestamp<t:false},n={cacheHits:0,cacheMisses:0,dedupes:0,requests:0,failures:0,avgMs:0,lastMs:0},ee=e=>{delete R[e],x.delete(e);let t=r=>r===e||r.startsWith(`${e}:`);Object.keys(u).forEach(r=>{t(r)&&delete u[r];}),Object.keys(f).forEach(r=>{t(r)&&delete f[r];}),Object.keys(b).forEach(r=>{t(r)&&delete b[r];});},D=(e,t)=>{a[e]||(a[e]=new Set),a[e].add(t),T(e);},L=(e,t)=>{let r=a[e];r&&(r.delete(t),r.size===0&&delete a[e]);},T=e=>{_[e]||(_[e]=o(e,t=>{if(t!==null)return;let r=a[e];r&&(r.forEach(o=>{try{o();}catch{}}),delete a[e]),_[e]?.(),delete _[e],ee(e);}));},te=async(e$1,t,r={})=>{if(!e$1||typeof e$1!="string"){c("fetchStore requires a store name as first argument");return}if(!t){c(`fetchStore("${e$1}") requires a URL or Promise as second argument`);return}let{transform:o,onSuccess:w,onError:W,method:H,headers:U,body:K,ttl:B,staleWhileRevalidate:I=false,dedupe:N=true,retry:V=0,retryDelay:z=400,retryBackoff:J=1.7,signal:E,cacheKey:M}=r;!E&&a$1()&&!x.has(e$1)&&(x.add(e$1),b$1(`fetchStore("${e$1}") called without an AbortSignal. Provide "signal" to enable cancellation (recommended).`));let s=M?`${e$1}:${M}`:e$1;if(l(e$1)||d(e$1,{data:null,loading:false,error:null,status:"idle"}),T(e$1),Z(s,B)){n.cacheHits+=1;let g=b[s].data;if(e(e$1,{data:g,loading:false,error:null,status:"success",cached:true}),!I)return g}else n.cacheMisses+=1;if(N&&u[s])return n.dedupes+=1,u[s];let $=(f[s]??0)+1;f[s]=$,e(e$1,{loading:true,error:null,status:"loading"}),n.requests+=1;let G=Date.now(),v=!E&&typeof AbortController<"u"?new AbortController:null,Q=E||v?.signal,S=v?()=>{v.signal.aborted||v.abort();}:null;S&&D(e$1,S);let q=(async()=>{let g=0,F=z??400;for(;;)try{let i;if(typeof t=="string"){let X=re({method:H,headers:U,body:K,signal:Q,...r}),l=await fetch(t,X);if(!l.ok)throw new Error(`HTTP ${l.status}: ${l.statusText}`);(l.headers.get("content-type")||"").includes("application/json")?i=await l.json():i=await l.text();}else if(typeof t.then=="function")i=await t;else return c(`fetchStore("${e$1}") - second argument must be a URL string or Promise.
2
+ Examples:
3
+ fetchStore("users", "https://api.example.com/users")
4
+ fetchStore("users", axios.get("/users"))`),null;let h=o?o(i):i;if(f[s]!==$)return null;b[s]={timestamp:Date.now(),data:h},l(e$1)&&e(e$1,{data:h,loading:!1,error:null,status:"success"}),w?.(h);let c$1=Date.now()-G;return n.lastMs=c$1,n.avgMs=(n.avgMs*(n.requests-1)+c$1)/n.requests,h}catch(i){if(g+=1,i?.name==="AbortError")return b$1(`fetchStore("${e$1}") aborted`),l(e$1)&&e(e$1,{loading:false,error:"aborted",status:"aborted"}),null;if(g<=(V??0)){await Y(F),F*=J??1.7;continue}if(f[s]!==$)return null;let c=i?.message||"Something went wrong";return l(e$1)&&e(e$1,{data:null,loading:false,error:c,status:"error"}),W?.(c),n.failures+=1,b$1(`fetchStore("${e$1}") failed: ${c}`),null}})().finally(()=>{delete u[s],S&&L(e$1,S);});return u[s]=q,R[e$1]={url:t,options:{...r,cacheKey:M}},q},j=async e=>{let t=R[e];if(!t){a$1()&&b$1(`refetchStore("${e}") - no previous fetch found.
5
+ Call fetchStore("${e}", url) first.`);return}return te(e,t.url,t.options)},A=new Set,C={},ae=e=>{if(typeof window>"u"||typeof window.addEventListener!="function")return ()=>{};let t=e??"*";if(A.has(t))return C[t]??(()=>{});let r=()=>{t==="*"?Object.keys(R).forEach(w=>{j(w);}):j(t);};window.addEventListener("focus",r),window.addEventListener("online",r),A.add(t);let o=()=>{window.removeEventListener("focus",r),window.removeEventListener("online",r),A.delete(t),delete C[t],t!=="*"&&L(t,o);};return C[t]=o,t!=="*"&&D(t,o),o},re=e=>{let t={};return e.method&&(t.method=e.method.toUpperCase()),e.headers?t.headers=e.headers:t.headers={"Content-Type":"application/json"},e.body&&(t.body=typeof e.body=="string"?e.body:JSON.stringify(e.body)),e.signal&&(t.signal=e.signal),t},ce=()=>({...n});export{te as a,j as b,ae as c,ce as d};
@@ -0,0 +1,3 @@
1
+ import {r,o,p,l,b,a,e}from'./chunk-5F2FD6DX.js';import {useCallback,useSyncExternalStore,useEffect,useRef}from'react';var m=(t,e)=>{if(!e)return t;let o=e.split("."),n=t;for(let r of o){if(n==null)return null;n=n[r];}return n??null},h=new Set,w=(t,e)=>{if(Object.is(t,e))return true;if(typeof t!="object"||typeof e!="object"||t===null||e===null)return false;let o=Object.keys(t),n=Object.keys(e);if(o.length!==n.length)return false;for(let r of o)if(!Object.prototype.hasOwnProperty.call(e,r)||!Object.is(t[r],e[r]))return false;return true};function c(t,e,o$1=Object.is){let n=typeof e=="function",r$1=typeof e=="string"?e:void 0,u=n?e:void 0,p$1=useCallback(s=>n?r(t,i=>u(i),o$1,s):o(t,()=>s()),[t,n,u,o$1]),S=useCallback(()=>{let s=p(t);return n?s==null?null:u(s):m(s,r$1)},[t,n,u,r$1]),l$1=useSyncExternalStore(p$1,S,S);return useEffect(()=>{l(t)||b(`useStore("${t}") - store not found yet.
2
+ Component will update automatically when createStore("${t}") is called.`),a()&&!n&&!r$1&&!h.has(t)&&(h.add(t),b(`useStore("${t}") without a selector/path subscribes to the entire store and may re-render on every change.
3
+ Prefer useSelector/useStoreField for better performance.`));},[t,n,r$1]),l$1}var v=(t,e)=>c(t,e),C=(t,e,o=w)=>{let n=useRef(null),r$1=useCallback(l=>{if(l==null)return null;let s=e(l),i=n.current;return i!==null&&o(s,i)?i:(n.current=s,s)},[e,o]),u=useCallback(()=>{let l=p(t);return r$1(l)},[t,r$1]),p$1=useCallback(l=>r(t,s=>r$1(s),o,()=>l()),[t,r$1,o]);return useSyncExternalStore(p$1,u,u)},E=(t,e)=>{let o=p(t);return o==null?null:m(o,e)};var A=t=>{let e=c(t);return {data:e?.data??null,loading:e?.loading??false,error:e?.error??null,status:e?.status??"idle",isEmpty:!e?.data&&!e?.loading&&!e?.error}};var _=(t,e$1)=>{let o=c(t,e$1),n=useCallback(r=>{let u=r?.target?r.target.value:r;e(t,e$1,u);},[t,e$1]);return {value:o,onChange:n}};export{c as a,v as b,C as c,E as d,A as e,_ as f};
@@ -1 +1 @@
1
- import {c,g,e,b,l as l$1}from'./chunk-VNLWP332.js';var l=class r{constructor(t,e=[]){this._storeName=t,this._path=e;}nested(t){return typeof t!="string"||t.trim()===""?(c(`nested() expects a string key. Got: ${JSON.stringify(t)}`),this):new r(this._storeName,[...this._path,t])}target(t){return typeof t!="string"||t.trim()===""?(c(`target() expects a string key. Got: ${JSON.stringify(t)}`),new a(this._storeName,this._path,null)):new a(this._storeName,this._path,t)}get value(){return this._path.length===0?g(this._storeName):g(this._storeName,this._path.join("."))}set(t){this._path.length===0?e(this._storeName,t):e(this._storeName,this._path.join("."),t);}},a=class{constructor(t,e,o){this._storeName=t,this._parentPath=e,this._key=o,this._fullPath=o?[...e,o].join("."):e.join(".");}get value(){return this._key?g(this._storeName,this._fullPath):(b("target() was called without a key - returning null"),null)}set(t){if(!this._key){b("target() was called without a key - cannot set value");return}e(this._storeName,this._fullPath,t);}},p=r=>(l$1(r)||b(`chain("${r}") called before store exists; operations will no-op until created.`),new l(r));export{p as a};
1
+ import {c,g,e,b,l as l$1}from'./chunk-5F2FD6DX.js';var l=class r{constructor(t,e=[]){this._storeName=t,this._path=e;}nested(t){return typeof t!="string"||t.trim()===""?(c(`nested() expects a string key. Got: ${JSON.stringify(t)}`),this):new r(this._storeName,[...this._path,t])}target(t){return typeof t!="string"||t.trim()===""?(c(`target() expects a string key. Got: ${JSON.stringify(t)}`),new a(this._storeName,this._path,null)):new a(this._storeName,this._path,t)}get value(){return this._path.length===0?g(this._storeName):g(this._storeName,this._path.join("."))}set(t){this._path.length===0?e(this._storeName,t):e(this._storeName,this._path.join("."),t);}},a=class{constructor(t,e,o){this._storeName=t,this._parentPath=e,this._key=o,this._fullPath=o?[...e,o].join("."):e.join(".");}get value(){return this._key?g(this._storeName,this._fullPath):(b("target() was called without a key - returning null"),null)}set(t){if(!this._key){b("target() was called without a key - cannot set value");return}e(this._storeName,this._fullPath,t);}},p=r=>(l$1(r)||b(`chain("${r}") called before store exists; operations will no-op until created.`),new l(r));export{p as a};
@@ -27,6 +27,12 @@ interface PersistConfig {
27
27
  deserialize: (v: string) => unknown;
28
28
  encrypt: (v: string) => string;
29
29
  decrypt: (v: string) => string;
30
+ onMigrationFail?: "reset" | "keep" | ((state: unknown) => unknown);
31
+ onStorageCleared?: (info: {
32
+ name: string;
33
+ key: string;
34
+ reason: "clear" | "remove" | "missing";
35
+ }) => void;
30
36
  }
31
37
  interface MiddlewareCtx {
32
38
  action: string;
@@ -53,6 +59,7 @@ interface StoreOptions<State = StoreValue> {
53
59
  allowSSRGlobalStore?: boolean;
54
60
  sync?: boolean | {
55
61
  channel?: string;
62
+ maxPayloadBytes?: number;
56
63
  conflictResolver?: (args: {
57
64
  local: StoreValue;
58
65
  incoming: StoreValue;
@@ -79,6 +86,7 @@ type NormalizedOptions = {
79
86
  allowSSRGlobalStore?: boolean;
80
87
  sync?: boolean | {
81
88
  channel?: string;
89
+ maxPayloadBytes?: number;
82
90
  conflictResolver?: (args: {
83
91
  local: StoreValue;
84
92
  incoming: StoreValue;
package/dist/core.d.ts CHANGED
@@ -1 +1 @@
1
- export { c as chain, a as clearAllStores, b as clearHistory, h as createStore, i as createStoreForRequest, k as deleteStore, l as getHistory, n as getMetrics, o as getStore, p as getStoreMeta, q as hasStore, r as hydrateStores, s as listStores, t as mergeStore, u as resetStore, v as setStore, w as setStoreBatch, x as subscribeWithSelector } from './core-CLIi-SLm.js';
1
+ export { c as chain, a as clearAllStores, b as clearHistory, h as createStore, i as createStoreForRequest, k as deleteStore, l as getHistory, n as getMetrics, o as getStore, p as getStoreMeta, q as hasStore, r as hydrateStores, s as listStores, t as mergeStore, u as resetStore, v as setStore, w as setStoreBatch, x as subscribeWithSelector } from './core-CKzRwVaY.js';
package/dist/core.js CHANGED
@@ -1 +1 @@
1
- export{a as chain}from'./chunk-KYAUSC7J.js';export{k as clearAllStores,x as clearHistory,d as createStore,z as createStoreForRequest,h as deleteStore,w as getHistory,y as getMetrics,g as getStore,n as getStoreMeta,l as hasStore,A as hydrateStores,m as listStores,j as mergeStore,i as resetStore,e as setStore,f as setStoreBatch,r as subscribeWithSelector}from'./chunk-VNLWP332.js';
1
+ export{a as chain}from'./chunk-K6QIWMMW.js';export{k as clearAllStores,x as clearHistory,d as createStore,z as createStoreForRequest,h as deleteStore,w as getHistory,y as getMetrics,g as getStore,n as getStoreMeta,l as hasStore,A as hydrateStores,m as listStores,j as mergeStore,i as resetStore,e as setStore,f as setStoreBatch,r as subscribeWithSelector}from'./chunk-5F2FD6DX.js';
package/dist/index.d.ts CHANGED
@@ -1,18 +1,3 @@
1
- export { c as chain, a as clearAllStores, b as clearHistory, d as createCounterStore, e as createEntityStore, f as createListStore, g as createSelector, h as createStore, i as createStoreForRequest, j as createZustandCompatStore, k as deleteStore, l as getHistory, m as getInitialState, n as getMetrics, o as getStore, p as getStoreMeta, q as hasStore, r as hydrateStores, s as listStores, t as mergeStore, u as resetStore, v as setStore, w as setStoreBatch, x as subscribeWithSelector } from './core-CLIi-SLm.js';
1
+ export { c as chain, a as clearAllStores, b as clearHistory, d as createCounterStore, e as createEntityStore, f as createListStore, g as createSelector, h as createStore, i as createStoreForRequest, j as createZustandCompatStore, k as deleteStore, l as getHistory, m as getInitialState, n as getMetrics, o as getStore, p as getStoreMeta, q as hasStore, r as hydrateStores, s as listStores, t as mergeStore, u as resetStore, v as setStore, w as setStoreBatch, x as subscribeWithSelector } from './core-CKzRwVaY.js';
2
2
  export { enableRevalidateOnFocus, fetchStore, getAsyncMetrics, refetchStore } from './async.js';
3
- export { useSelector, useStore, useStoreField, useStoreStatic } from './react.js';
4
-
5
- declare const useAsyncStore: (name: string) => {
6
- data: any;
7
- loading: any;
8
- error: any;
9
- status: any;
10
- isEmpty: boolean;
11
- };
12
-
13
- declare const useFormStore: <T = any>(storeName: string, field: string) => {
14
- value: T | null;
15
- onChange: (eOrValue: any) => void;
16
- };
17
-
18
- export { useAsyncStore, useFormStore };
3
+ export { useAsyncStore, useFormStore, useSelector, useStore, useStoreField, useStoreStatic } from './react.js';
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{a as chain}from'./chunk-KYAUSC7J.js';export{c as enableRevalidateOnFocus,a as fetchStore,d as getAsyncMetrics,b as refetchStore}from'./chunk-3CAQKMKY.js';import {a}from'./chunk-Y52AULFH.js';export{c as useSelector,a as useStore,b as useStoreField,d as useStoreStatic}from'./chunk-Y52AULFH.js';import {e}from'./chunk-VNLWP332.js';export{k as clearAllStores,x as clearHistory,s as createCounterStore,u as createEntityStore,t as createListStore,q as createSelector,d as createStore,z as createStoreForRequest,B as createZustandCompatStore,h as deleteStore,w as getHistory,v as getInitialState,y as getMetrics,g as getStore,n as getStoreMeta,l as hasStore,A as hydrateStores,m as listStores,j as mergeStore,i as resetStore,e as setStore,f as setStoreBatch,r as subscribeWithSelector}from'./chunk-VNLWP332.js';import {useCallback}from'react';var n=r=>{let e=a(r);return {data:e?.data??null,loading:e?.loading??false,error:e?.error??null,status:e?.status??"idle",isEmpty:!e?.data&&!e?.loading&&!e?.error}};var u=(r,e$1)=>{let i=a(r,e$1),l=useCallback(o=>{let m=o?.target?o.target.value:o;e(r,e$1,m);},[r,e$1]);return {value:i,onChange:l}};export{n as useAsyncStore,u as useFormStore};
1
+ export{a as chain}from'./chunk-K6QIWMMW.js';export{c as enableRevalidateOnFocus,a as fetchStore,d as getAsyncMetrics,b as refetchStore}from'./chunk-G6JMMJYH.js';export{e as useAsyncStore,f as useFormStore,c as useSelector,a as useStore,b as useStoreField,d as useStoreStatic}from'./chunk-JBYLHJKN.js';export{k as clearAllStores,x as clearHistory,s as createCounterStore,u as createEntityStore,t as createListStore,q as createSelector,d as createStore,z as createStoreForRequest,B as createZustandCompatStore,h as deleteStore,w as getHistory,v as getInitialState,y as getMetrics,g as getStore,n as getStoreMeta,l as hasStore,A as hydrateStores,m as listStores,j as mergeStore,i as resetStore,e as setStore,f as setStoreBatch,r as subscribeWithSelector}from'./chunk-5F2FD6DX.js';
package/dist/react.d.ts CHANGED
@@ -4,4 +4,17 @@ declare const useStoreField: <T = any>(storeName: string, field: string) => T |
4
4
  declare const useSelector: <T = any, R = any>(storeName: string, selectorFn: (state: T) => R, equalityFn?: (a: R, b: R) => boolean) => R | null;
5
5
  declare const useStoreStatic: <T = any>(name: string, path?: string) => T | null;
6
6
 
7
- export { useSelector, useStore, useStoreField, useStoreStatic };
7
+ declare const useAsyncStore: (name: string) => {
8
+ data: any;
9
+ loading: any;
10
+ error: any;
11
+ status: any;
12
+ isEmpty: boolean;
13
+ };
14
+
15
+ declare const useFormStore: <T = any>(storeName: string, field: string) => {
16
+ value: T | null;
17
+ onChange: (eOrValue: any) => void;
18
+ };
19
+
20
+ export { useAsyncStore, useFormStore, useSelector, useStore, useStoreField, useStoreStatic };
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- export{c as useSelector,a as useStore,b as useStoreField,d as useStoreStatic}from'./chunk-Y52AULFH.js';import'./chunk-VNLWP332.js';
1
+ export{e as useAsyncStore,f as useFormStore,c as useSelector,a as useStore,b as useStoreField,d as useStoreStatic}from'./chunk-JBYLHJKN.js';import'./chunk-5F2FD6DX.js';
package/dist/testing.js CHANGED
@@ -1 +1 @@
1
- import {d,i as i$1,e,k}from'./chunk-VNLWP332.js';var l=(e$1="mock",o={})=>(d(e$1,o),{set:r=>e(e$1,r),reset:()=>i$1(e$1),use:()=>({name:e$1})}),u=(e,o)=>{let r=Date.now;Date.now=()=>e;try{return o()}finally{Date.now=r;}},i=()=>k(),m=(e$1,o=1e3,r=t=>({value:t}))=>{let t=typeof performance<"u"&&performance.now?performance.now():Date.now();for(let n=0;n<o;n++)e(e$1,r(n));let s=(typeof performance<"u"&&performance.now?performance.now():Date.now())-t;return {iterations:o,totalMs:s,avgMs:s/o}};export{m as benchmarkStoreSet,l as createMockStore,i as resetAllStoresForTest,u as withMockedTime};
1
+ import {d,i as i$1,e,k}from'./chunk-5F2FD6DX.js';var l=(e$1="mock",o={})=>(d(e$1,o),{set:r=>e(e$1,r),reset:()=>i$1(e$1),use:()=>({name:e$1})}),u=(e,o)=>{let r=Date.now;Date.now=()=>e;try{return o()}finally{Date.now=r;}},i=()=>k(),m=(e$1,o=1e3,r=t=>({value:t}))=>{let t=typeof performance<"u"&&performance.now?performance.now():Date.now();for(let n=0;n<o;n++)e(e$1,r(n));let s=(typeof performance<"u"&&performance.now?performance.now():Date.now())-t;return {iterations:o,totalMs:s,avgMs:s/o}};export{m as benchmarkStoreSet,l as createMockStore,i as resetAllStoresForTest,u as withMockedTime};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stroid",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Compact state management library with persistence, async caching, sync, and React hooks.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,5 +0,0 @@
1
- import {c,a,b,l,d as d$1,e,o}from'./chunk-VNLWP332.js';var v={},d={},u={},p={},$=new Set,S={},y={},G=e=>new Promise(t=>setTimeout(t,e)),Q=(e,t)=>{if(!t)return false;let r=p[e];return r?Date.now()-r.timestamp<t:false},n={cacheHits:0,cacheMisses:0,dedupes:0,requests:0,failures:0,avgMs:0,lastMs:0},X=e=>{delete v[e],$.delete(e);let t=r=>r===e||r.startsWith(`${e}:`);Object.keys(d).forEach(r=>{t(r)&&delete d[r];}),Object.keys(u).forEach(r=>{t(r)&&delete u[r];}),Object.keys(p).forEach(r=>{t(r)&&delete p[r];});},Y=(e,t)=>{y[e]||(y[e]=new Set),y[e].add(t),P(e);},P=e=>{S[e]||(S[e]=o(e,t=>{if(t!==null)return;let r=y[e];r&&(r.forEach(o=>{try{o();}catch{}}),delete y[e]),S[e]?.(),delete S[e],X(e);}));},Z=async(e$1,t,r={})=>{if(!e$1||typeof e$1!="string"){c("fetchStore requires a store name as first argument");return}if(!t){c(`fetchStore("${e$1}") requires a URL or Promise as second argument`);return}let{transform:o,onSuccess:w,onError:j,method:D,headers:L,body:T,ttl:W,staleWhileRevalidate:H=false,dedupe:U=true,retry:K=0,retryDelay:B=400,retryBackoff:I=1.7,signal:m,cacheKey:k}=r;!m&&a()&&!$.has(e$1)&&($.add(e$1),b(`fetchStore("${e$1}") called without an AbortSignal. Provide "signal" to enable cancellation (recommended).`));let s=k?`${e$1}:${k}`:e$1;if(l(e$1)||d$1(e$1,{data:null,loading:false,error:null,status:"idle"}),P(e$1),Q(s,W)){n.cacheHits+=1;let f=p[s].data;if(e(e$1,{data:f,loading:false,error:null,status:"success",cached:true}),!H)return f}else n.cacheMisses+=1;if(U&&d[s])return n.dedupes+=1,d[s];let R=(u[s]??0)+1;u[s]=R,e(e$1,{loading:true,error:null,status:"loading"}),n.requests+=1;let N=Date.now(),V=!m&&typeof AbortController<"u"?new AbortController:null,J=m||V?.signal,A=(async()=>{let f=0,x=B??400;for(;;)try{let i;if(typeof t=="string"){let z=ee({method:D,headers:L,body:T,signal:J,...r}),c=await fetch(t,z);if(!c.ok)throw new Error(`HTTP ${c.status}: ${c.statusText}`);(c.headers.get("content-type")||"").includes("application/json")?i=await c.json():i=await c.text();}else if(typeof t.then=="function")i=await t;else return c(`fetchStore("${e$1}") - second argument must be a URL string or Promise.
2
- Examples:
3
- fetchStore("users", "https://api.example.com/users")
4
- fetchStore("users", axios.get("/users"))`),null;let h=o?o(i):i;if(u[s]!==R)return null;p[s]={timestamp:Date.now(),data:h},e(e$1,{data:h,loading:!1,error:null,status:"success"}),w?.(h);let a=Date.now()-N;return n.lastMs=a,n.avgMs=(n.avgMs*(n.requests-1)+a)/n.requests,h}catch(i){if(f+=1,i?.name==="AbortError")return b(`fetchStore("${e$1}") aborted`),e(e$1,{loading:false,error:"aborted",status:"aborted"}),null;if(f<=(K??0)){await G(x),x*=I??1.7;continue}if(u[s]!==R)return null;let a=i?.message||"Something went wrong";return e(e$1,{data:null,loading:false,error:a,status:"error"}),j?.(a),n.failures+=1,b(`fetchStore("${e$1}") failed: ${a}`),null}})().finally(()=>{delete d[s];});return d[s]=A,v[e$1]={url:t,options:{...r,cacheKey:k}},A},O=async e=>{let t=v[e];if(!t){a()&&b(`refetchStore("${e}") - no previous fetch found.
5
- Call fetchStore("${e}", url) first.`);return}return Z(e,t.url,t.options)},E=new Set,M={},oe=e=>{if(typeof window>"u"||typeof window.addEventListener!="function")return ()=>{};let t=e??"*";if(E.has(t))return M[t]??(()=>{});let r=()=>{t==="*"?Object.keys(v).forEach(w=>{O(w);}):O(t);};window.addEventListener("focus",r),window.addEventListener("online",r),E.add(t);let o=()=>{window.removeEventListener("focus",r),window.removeEventListener("online",r),E.delete(t),delete M[t];};return M[t]=o,t!=="*"&&Y(t,o),o},ee=e=>{let t={};return e.method&&(t.method=e.method.toUpperCase()),e.headers?t.headers=e.headers:t.headers={"Content-Type":"application/json"},e.body&&(t.body=typeof e.body=="string"?e.body:JSON.stringify(e.body)),e.signal&&(t.signal=e.signal),t},ie=()=>({...n});export{Z as a,O as b,oe as c,ie as d};
@@ -1,17 +0,0 @@
1
- var Rt=typeof process<"u"&&typeof process.env?.NODE_ENV=="string"?process.env.NODE_ENV:void 0,_t=typeof import.meta<"u"&&import.meta?.env?.MODE?import.meta.env.MODE:void 0,st=typeof globalThis<"u"&&typeof globalThis.__STROID_DEV__=="boolean"?globalThis.__STROID_DEV__:void 0,Ot=typeof process<"u"?"development":"production",Pt=Rt??_t??Ot,K=typeof st=="boolean"?st:Pt!=="production",v=()=>K,f=K?t=>{console.warn(`[stroid] ${t}`);}:()=>{},m=K?t=>{console.error(`[stroid] ${t}`);}:()=>{},R=K?t=>{console.log(`[stroid] ${t}`);}:()=>{},J=null,Dt=()=>{if(J)return J;let t,n=[];for(let e=0;e<256;e++){t=e;for(let r=0;r<8;r++)t=t&1?3988292384^t>>>1:t>>>1;n[e]=t>>>0;}return J=n,n},it=t=>{let n=Dt(),e=-1;for(let r=0;r<t.length;r++)e=e>>>0,e=e>>>8^n[(e^t.charCodeAt(r))&255];return (e^-1)>>>0},G=t=>{try{return it(JSON.stringify(t))}catch{return it(String(t))}},Vt=typeof globalThis<"u"&&typeof globalThis.structuredClone=="function",b=t=>{try{return Vt?structuredClone(t):JSON.parse(JSON.stringify(t))}catch{return Array.isArray(t)?[...t]:t&&typeof t=="object"?{...t}:t}};var X=(t,n)=>{try{let e=b(t);return n(e),e}catch(e){throw new Error(`produceClone failed (possible circular reference or unserializable data): ${e?.message??e}`)}},ct=(t,n)=>{if(!t)return {ok:true};try{if(typeof t.safeParse=="function"){let e=t.safeParse(n);return e.success?{ok:!0,data:e.data}:{ok:!1,error:e.error}}if(typeof t.parse=="function")return t.parse(n),{ok:!0,data:n};if(typeof t.validateSync=="function")return t.validateSync(n),{ok:!0,data:n};if(typeof t.isValidSync=="function")return t.isValidSync(n)?{ok:!0,data:n}:{ok:!1,error:"Schema validation failed"};if(typeof t.validate=="function")return t.validate(n)?{ok:!0,data:n}:{ok:!1,error:t.errors||"Schema validation failed"};if(typeof t=="function"){let e=t(n);return e===!1?{ok:!1,error:"Schema validation failed"}:{ok:!0,data:e===!0?n:e}}return {ok:!0,data:n}}catch(e){return {ok:false,error:e?.message??e}}};var _=t=>t===null?"null":Array.isArray(t)?"array":t instanceof Map?"map":t instanceof Set?"set":t instanceof Date?"date":typeof t=="function"?"function":typeof t,N=t=>{let n=_(t);return n==="function"?(m(`Functions cannot be stored in stroid.
2
- Store data only - handle functions outside the store.`),false):n==="map"||n==="set"?(f(`Map/Set detected. stroid converts these to plain objects.
3
- Use arrays or plain objects for best results.`),true):(n==="date"&&f(`Date object detected. stroid stores it as ISO string.
4
- Use new Date(value) to convert back when reading.`),true)},T=t=>{let n=_(t);if(n==="date")return v()&&f("Date detected; stored as ISO string. Use new Date(value) when reading."),t.toISOString();if(n==="map")return v()&&f("Map detected; converting to plain object."),Object.fromEntries(t);if(n==="set")return v()&&f("Set detected; converting to array."),Array.from(t);if(n==="object"){let e={};for(let r in t)e[r]=T(t[r]);return e}return n==="array"?t.map(T):t},at=10,jt=5,E=t=>Array.isArray(t)?[...t]:typeof t=="string"&&!t.includes(".")?[t]:typeof t=="string"?t.split("."):[String(t)],W=t=>{let n=E(t),e=n.length;return e>at?(m(`Path depth of ${e} exceeded maximum of ${at}.
5
- "${n.join(".")}"
6
- This is a data design issue. Split into separate stores:
7
- createStore("${n[0]}", ...) and createStore("${n[1]}", ...)`),false):(e>jt&&f(`Deep nesting detected (${e} levels): "${n.join(".")}"
8
- Consider splitting into separate stores for better readability.`),true)},ut=(t,n)=>{let e=E(n),r=t;for(let o of e){if(r==null){f(`Path "${e.join(".")}" not found - reached null at "${o}"`);return}if(typeof r!="object"){f(`Cannot go deeper at "${o}" - value is not an object`);return}r=r[o];}return r},lt=(t,n,e)=>{let r=E(n);if(r.length===0)return t;let o=(s,a)=>{let c=r[a],p=a===r.length-1;if(Array.isArray(s)){let u=Number(c);if(!Number.isInteger(u))return s;let l=[...s];return p?(l[u]=e,l):(l[u]=o(l[u],a+1),l)}if(s&&typeof s=="object"){let u={...s};return p?(u[c]=e,u):(u[c]=o(u[c],a+1),u)}return s};return o(t,0)},dt=t=>typeof t!="string"||t.trim()===""?(m(`Store name must be a non-empty string. Got: ${JSON.stringify(t)}`),false):t.includes(" ")?(m(`Store name "${t}" contains spaces.
9
- Use camelCase or kebab-case: "userName" or "user-name"`),false):true,ft=(t,n)=>{let e=n.find(r=>{let o=r.toLowerCase(),s=t.toLowerCase();return o.includes(s)||s.includes(o)||Nt(o,s)<=2});e?f(`Store "${t}" not found. Did you mean "${e}"?`):m(`Store "${t}" not found.
10
- Available stores: [${n.join(", ")}]
11
- Call createStore("${t}", data) first.`);},Nt=(t,n)=>{let e=Array.from({length:n.length+1},(r,o)=>Array.from({length:t.length+1},(s,a)=>o===0?a:a===0?o:0));for(let r=1;r<=n.length;r++)for(let o=1;o<=t.length;o++)e[r][o]=n[r-1]===t[o-1]?e[r-1][o-1]:Math.min(e[r-1][o-1],e[r][o-1],e[r-1][o])+1;return e[n.length][t.length]};var C=t=>{if(typeof t!="object"||t===null)return t;Object.freeze(t);for(let n of Object.keys(t)){let e=t[n];typeof e=="object"&&e!==null&&!Object.isFrozen(e)&&C(e);}return t};var d=Object.create(null),x=Object.create(null),D=Object.create(null),i=Object.create(null),k=Object.create(null),Et=Object.create(null),q=new Set,Y=false,I=0,Ct=`stroid_${Math.random().toString(16).slice(2)}`,Z={},L=Object.create(null),pt=false,gt=t=>typeof t=="string"?t:t.name,A,F=(()=>{let t=new Map;return {getItem:n=>t.has(n)?t.get(n):null,setItem:(n,e)=>{t.set(n,e);},removeItem:n=>{t.delete(n);},type:"memory"}})(),yt=()=>{if(Y)return;Y=true;let t=()=>{Y=false,q.forEach(n=>{let e=x[n];if(!e||e.length===0)return;let r=typeof performance<"u"&&performance.now?performance.now():Date.now(),o=b(d[n]);e.forEach(p=>{try{p(o);}catch(u){f(`Subscriber for "${n}" threw: ${u?.message??u}`);}});let a=(typeof performance<"u"&&performance.now?performance.now():Date.now())-r,c=i[n]?.metrics||{notifyCount:0,totalNotifyMs:0,lastNotifyMs:0};c.notifyCount+=1,c.totalNotifyMs+=a,c.lastNotifyMs=a,i[n]&&(i[n].metrics=c);}),q.clear();};typeof queueMicrotask=="function"?queueMicrotask(t):Promise.resolve().then(t);},M=t=>{q.add(t),I===0&&yt();},V=t=>d[t]!==void 0?true:(ft(t,Object.keys(d)),false),It=(t,n,e,r)=>{let o=E(e);if(o.length===0)return {ok:true};if(n==null){let a=`Cannot set "${o.join(".")}" on "${t}" because the store value is ${n===null?"null":"undefined"}.`;return f(a),{ok:false,reason:a}}let s=n;for(let a=0;a<o.length;a++){let c=o[a],p=a===o.length-1;if(s==null||typeof s!="object"){let l=`Path "${o.join(".")}" is invalid for "${t}" - "${o.slice(0,a).join(".")||"root"}" is not an object.`;return f(l),{ok:false,reason:l}}if(Array.isArray(s)){let l=Number(c);if(!Number.isInteger(l)||l<0){let y=`Path "${o.join(".")}" targets non-numeric index "${c}" on an array in "${t}".`;return f(y),{ok:false,reason:y}}let g=s;if(l>=g.length){let y=`Path "${o.join(".")}" is invalid for "${t}" - index ${l} is out of bounds (length ${g.length}).`;return f(y),{ok:false,reason:y}}if(p){let y=g[l];if(y!==void 0){let $=_(y),S=_(r);if($!==S){let h=`Type mismatch setting "${o.join(".")}" on "${t}": expected ${$}, received ${S}.`;return f(h),{ok:false,reason:h}}}return {ok:true}}s=g[l];continue}if(!Object.prototype.hasOwnProperty.call(s,c)){let l=`Path "${o.join(".")}" does not exist on store "${t}" (missing "${c}").`;return f(l),{ok:false,reason:l}}if(p){let l=s[c];if(l!==void 0){let g=_(l),y=_(r);if(g!==y){let $=`Type mismatch setting "${o.join(".")}" on "${t}": expected ${g}, received ${y}.`;return f($),{ok:false,reason:$}}}return {ok:true}}s=s[c];}return {ok:true}},Q=t=>{try{return typeof window>"u"?F:t==="session"||t==="sessionStorage"?window.sessionStorage??F:window.localStorage??F}catch{return F}},At=(t,n)=>{if(!t)return null;let e={key:`stroid_${n}`,serialize:JSON.stringify,deserialize:JSON.parse,encrypt:r=>r,decrypt:r=>r};return t===true?{driver:Q("localStorage"),...e}:typeof t=="string"?{driver:Q(t),...e}:{driver:t.driver||t.storage||Q("localStorage"),key:t.key||e.key,serialize:t.serialize||e.serialize,deserialize:t.deserialize||e.deserialize,encrypt:t.encrypt||e.encrypt,decrypt:t.decrypt||e.decrypt}},Mt=t=>{if(!i[t]?.options?.devtools||typeof window>"u")return;let e=window.__REDUX_DEVTOOLS_EXTENSION__||window.__REDUX_DEVTOOLS_EXTENSION__;if(!e||typeof e.connect!="function"){f(`DevTools requested for "${t}" but Redux DevTools extension not found.`);return}A||(A=e.connect({name:"stroid"}),A.init(d));},tt=(t,n)=>{let e=i[t]?.options?.redactor;if(typeof e=="function")try{return e(b(n))}catch{return n}return n},zt=(t,n)=>{if(typeof t!="object"||typeof n!="object"||t===null||n===null)return null;let e=t,r=n,o=[],s=[],a=[],c=new Set(Object.keys(e)),p=new Set(Object.keys(r));return p.forEach(u=>{c.has(u)?Object.is(e[u],r[u])||a.push(u):o.push(u);}),c.forEach(u=>{p.has(u)||s.push(u);}),{added:o,removed:s,changed:a}},B=(t,n,e,r)=>{let o=i[t]?.options?.historyLimit??50;if(o===0)return;k[t]||(k[t]=[]);let s={ts:Date.now(),action:n,prev:tt(t,e),next:tt(t,r),diff:zt(e,r)};k[t].push(s),k[t].length>o&&k[t].splice(0,k[t].length-o);},H=(t,n,e=false)=>{if(!(!A||!e&&!i[t]?.options?.devtools))try{let r={...d,[t]:tt(t,d[t])};A.send({type:`${t}/${n}`},r);}catch{}},St=(t,n)=>{let e=i[t]?.options?.middleware||[];if(!Array.isArray(e))return n.next;let r=n.next;for(let o of e){if(typeof o!="function")continue;let s=o({action:n.action,name:t,prev:n.prev,next:r,path:n.path});s!==void 0&&(r=s);}return r},z=(t,n)=>{let e=i[t]?.options?.schema;if(!e)return {ok:true};let r=ct(e,n);if(!r.ok){let o=`Schema validation failed for "${t}": ${r.error}`;i[t]?.options?.onError?.(o),f(o);}return r},et=t=>{let n=i[t]?.options?.persist;n&&(Z[t]&&clearTimeout(Z[t]),Z[t]=setTimeout(()=>{try{let e=n.serialize(d[t]),r=G(e),o=JSON.stringify({v:i[t]?.version??1,checksum:r,data:e}),s=n.encrypt(o);n.driver.setItem?.(n.key,s);}catch(e){let r=`Could not persist store "${t}" (${e?.message||e})`;f(r),i[t]?.options?.onError?.(r);}},0));},Ut=(t,{silent:n}={silent:false})=>{let e=i[t]?.options?.persist;if(e)try{let r=e.driver.getItem?.(e.key)??null;if(!r)return;let o=e.decrypt(r),s=JSON.parse(o),{v:a=1,checksum:c,data:p}=s||{};if(!p)return;if(c!==G(p)){f(`Checksum mismatch loading store "${t}". Falling back to initial state.`),d[t]=b(D[t]);return}let u=e.deserialize(p),l=i[t]?.version??1;if(a!==l){let y=i[t]?.options?.migrations||{};Object.keys(y).map(S=>Number(S)).filter(S=>S>a&&S<=l).sort((S,h)=>S-h).forEach(S=>{try{let h=y[S](u);h!==void 0&&(u=h);}catch(h){f(`Migration to v${S} failed for "${t}": ${h?.message||h}`);}});}if(!z(t,u).ok){f(`Persisted state for "${t}" failed schema; resetting to initial.`),d[t]=b(D[t]);return}d[t]=u,n||R(`Store "${t}" loaded from persistence`);}catch(r){f(`Could not load store "${t}" (${r?.message||r})`);}},U=(t,n,e={})=>{if(!dt(t)||!N(n))return;let r=typeof window>"u",o=typeof process<"u"?process.env?.NODE_ENV:void 0,s=r&&o==="production",a=e.allowSSRGlobalStore??false;if(s&&!a){v()&&m(`createStore("${t}") is blocked on the server in production to prevent cross-request memory leaks.
12
- Call createStoreForRequest(...) inside each request scope or pass { allowSSRGlobalStore: true } to opt in.`);return}if(d[t]!==void 0){let P=`Store "${t}" already exists. Call setStore("${t}", data) to update instead.`;return f(P),i[t]?.options?.onError?.(P),{name:t}}let{persist:c=false,devtools:p=false,middleware:u=[],onSet:l,onReset:g,onDelete:y,onCreate:$,onError:S,validator:h,schema:kt,migrations:wt={},version:rt=1,redactor:xt,historyLimit:mt=50,sync:$t,allowSSRGlobalStore:ot=a}=e;r&&!ot&&!pt&&v()&&(pt=true,f(`createStore("${t}") called in a server environment. Use createStoreForRequest(...) per request to avoid cross-request leaks or pass { allowSSRGlobalStore: true } if you really want a global store on the server.`));let O=At(c,t);if(O?.key){let P=L[O.key];P&&P!==t&&v()?f(`Persist key collision: "${O.key}" already used by store "${P}". Store "${t}" will overwrite the same storage key.`):L[O.key]=t;}let j=T(n),Tt={persist:O,devtools:!!p,middleware:u??[],onSet:l,onReset:g,onDelete:y,onCreate:$,onError:S,validator:h,schema:kt,migrations:wt,version:rt,redactor:xt,historyLimit:mt,sync:$t??false,allowSSRGlobalStore:ot};return d[t]=j,x[t]=x[t]||[],D[t]=b(j),i[t]={createdAt:new Date().toISOString(),updatedAt:new Date().toISOString(),updateCount:0,version:rt,metrics:{notifyCount:0,totalNotifyMs:0,lastNotifyMs:0},options:Tt},O&&(et(t),Ut(t,{silent:true})),i[t].options.onCreate?.(j),Mt(t),Ft(t),B(t,"create",null,j),R(`Store "${t}" created -> ${JSON.stringify(j)}`),{name:t}};function w(t,n,e){let r=gt(t);if(!V(r))return;let o,s=d[r];if(typeof n=="function"&&e===void 0)o=X(s,n);else if(typeof n=="object"&&!Array.isArray(n)&&e===void 0){if(!N(n))return;o={...s,...T(n)};}else if(typeof n=="string"||Array.isArray(n)){if(!W(n))return;let l=T(e),g=It(r,s,n,l);if(!g.ok){v()&&i[r]?.options?.onError?.(g.reason??`Invalid path for "${r}".`);return}o=lt(s,n,l);}else {m(`setStore("${r}") - invalid arguments.
13
- Usage:
14
- setStore("${r}", "field", value)
15
- setStore("${r}", "nested.field", value)
16
- setStore("${r}", { field: value })`);return}if(!N(o))return;let a=T(o);if(!z(r,a).ok)return;let p=i[r]?.options?.validator;if(p&&p(a)===false){i[r]?.options?.onError?.(`Validator blocked update for "${r}"`);return}let u=St(r,{action:"set",prev:s,next:a,path:n});d[r]=v()?C(u):u,i[r].updatedAt=new Date().toISOString(),i[r].updateCount++,i[r].options?.persist&&et(r),i[r].options.onSet?.(s,u),B(r,"set",s,u),H(r,"set"),M(r),R(`Store "${r}" updated`);}var Wt=t=>{I++;try{t();}finally{I=Math.max(0,I-1),I===0&&q.size>0&&yt();}};function nt(t,n){let e=gt(t);if(!V(e))return null;let r=d[e];return n===void 0?Array.isArray(r)?[...r]:r&&typeof r=="object"?{...r}:r:W(n)?ut(r,n):null}var ht=t=>{if(!V(t))return;x[t]?.forEach(o=>o(null)),i[t].options.onDelete?.(d[t]);let e=i[t].options.persist,r=i[t].options.devtools;delete d[t],delete x[t],delete D[t],delete i[t];try{e?.driver?.removeItem&&e.driver.removeItem(e.key);}catch{}e?.key&&L[e.key]===t&&delete L[e.key],r&&H(t,"delete",true),R(`Store "${t}" deleted`);},bt=t=>{if(!V(t)||!D[t])return;let n=d[t],e=b(D[t]);d[t]=v()?C(e):e,i[t].updatedAt=new Date().toISOString(),i[t].options.onReset?.(n,e),B(t,"reset",n,e),H(t,"reset"),M(t),R(`Store "${t}" reset to initial state/value`);},Yt=(t,n)=>{if(!V(t)||!N(n))return;let e=d[t];if(typeof e!="object"||Array.isArray(e)||e===null){m(`mergeStore("${t}") only works on object stores.
17
- Use setStore("${t}", value) instead.`);return}let r={...e,...T(n)};if(!z(t,r).ok)return;let s=i[t]?.options?.validator;if(s&&s(r)===false){i[t]?.options?.onError?.(`Validator blocked update for "${t}"`);return}let a=St(t,{action:"merge",prev:e,next:r,path:null});d[t]=v()?C(a):a,i[t].updatedAt=new Date().toISOString(),i[t].updateCount++,i[t].options?.persist&&et(t),i[t].options.onSet?.(e,a),B(t,"merge",e,a),H(t,"merge"),M(t),R(`Store "${t}" merged with data`);},Zt=()=>{let t=Object.keys(d);t.forEach(ht),f(`All stores cleared (${t.length} stores removed)`);},Kt=t=>d[t]!==void 0,Qt=()=>Object.keys(d),te=t=>V(t)?{...i[t]}:null,vt=(t,n)=>(x[t]||(x[t]=[]),x[t].push(n),()=>{x[t]=x[t].filter(e=>e!==n);}),ee=t=>d[t]??null,Ft=t=>{let n=i[t]?.options?.sync;if(!n)return;if(typeof window>"u"||typeof BroadcastChannel>"u"){f(`Sync enabled for "${t}" but BroadcastChannel not available in this environment.`);return}let e=typeof n=="object"&&n.channel?n.channel:`stroid_sync_${t}`;try{let r=new BroadcastChannel(e);Et[t]=r,r.onmessage=o=>{let s=o.data;if(!s||s.source===Ct||s.name!==t)return;let a=new Date(i[t]?.updatedAt||0).getTime(),c=s.updatedAt,p=typeof n=="object"?n.conflictResolver:null;if(c<=a){if(p){let l=p({local:d[t],incoming:s.data,localUpdated:a,incomingUpdated:c});if(l!==void 0){if(!z(t,l).ok)return;d[t]=l,i[t].updatedAt=new Date(Math.max(a,c)).toISOString(),i[t].updateCount++,M(t);}}return}z(t,s.data).ok&&(d[t]=s.data,i[t].updatedAt=new Date(c).toISOString(),i[t].updateCount++,M(t));};}catch(r){f(`Failed to setup sync for "${t}": ${r?.message||r}`);}};var ne=(t,n)=>{let e,r;return ()=>{let o=d[t];return o===void 0?null:(o===e||(e=o,r=n(o)),r??null)}},qt=(t,n,e=Object.is,r)=>{if(typeof n!="function"||typeof r!="function")return f(`subscribeWithSelector("${t}") requires selector and listener functions.`),()=>{};let o=n(d[t]);return vt(t,a=>{let c=n(a);if(!e(c,o)){let p=o;o=c,r(c,p);}})},re=(t,n=0,e={})=>(U(t,{value:n},e),{inc:(r=1)=>w(t,o=>{o.value+=r;}),dec:(r=1)=>w(t,o=>{o.value-=r;}),set:r=>w(t,"value",r),reset:()=>bt(t),get:()=>nt(t,"value")}),oe=(t,n=[],e={})=>(U(t,{items:n},e),{push:r=>w(t,o=>{o.items.push(r);}),removeAt:r=>w(t,o=>{o.items.splice(r,1);}),clear:()=>w(t,{items:[]}),replace:r=>w(t,{items:r}),all:()=>nt(t,"items")}),se=(t,n={})=>(U(t,{entities:{},ids:[]},n),{upsert:e=>w(t,r=>{let o=e.id??e._id??(typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`${Date.now()}_${Math.random().toString(16).slice(2)}`);r.ids.includes(o)||r.ids.push(o),r.entities[o]=e;}),remove:e=>w(t,r=>{r.ids=r.ids.filter(o=>o!==e),delete r.entities[e];}),all:()=>{let e=d[t];return e?e.ids.map(r=>e.entities[r]):[]},get:e=>nt(t,`entities.${e}`),clear:()=>bt(t)}),ie=()=>b(d),ae=(t,n)=>{if(!k[t])return [];let e=k[t];return n&&n>0?e.slice(-n):[...e]},ce=t=>{t?delete k[t]:Object.keys(k).forEach(n=>delete k[n]);},ue=t=>{let n=i[t];return n?.metrics?{...n.metrics}:null},le=t=>{let n={};return typeof t=="function"&&t({create:(r,o,s={})=>(n[r]=b(o),n[r]),set:(r,o)=>{if(n[r])return n[r]=typeof o=="function"?X(n[r],o):o,n[r]},get:r=>b(n[r])}),{snapshot:()=>b(n),hydrate:(r={})=>Lt(n,r)}},Lt=(t,n={})=>{!t||typeof t!="object"||Object.entries(t).forEach(([e,r])=>{Kt(e)?w(e,r):U(e,r,n[e]||n.default||{});});},de=(t,n={})=>{let e=n.name||`zstore_${Date.now()}`,r=(c,p=false)=>{let u=d[e]??{},l=typeof c=="function"?c(u):c,g=p?l:{...u,...l};w(e,g);},o=()=>d[e],s={setState:r,getState:o,subscribe:c=>vt(e,c),subscribeWithSelector:(c,p=Object.is,u)=>qt(e,c,p,u??(()=>{})),destroy:()=>ht(e)},a=t(r,o,s);return U(e,a,n),s};export{Lt as A,de as B,v as a,f as b,m as c,U as d,w as e,Wt as f,nt as g,ht as h,bt as i,Yt as j,Zt as k,Kt as l,Qt as m,te as n,vt as o,ee as p,ne as q,qt as r,re as s,oe as t,se as u,ie as v,ae as w,ce as x,ue as y,le as z};
@@ -1,3 +0,0 @@
1
- import {r,o,p,l,b,a}from'./chunk-VNLWP332.js';import {useCallback,useSyncExternalStore,useEffect,useRef}from'react';var h=(t,e)=>{if(!e)return t;let r=e.split("."),n=t;for(let s of r){if(n==null)return null;n=n[s];}return n??null},T=new Set,w=(t,e)=>{if(Object.is(t,e))return true;if(typeof t!="object"||typeof e!="object"||t===null||e===null)return false;let r=Object.keys(t),n=Object.keys(e);if(r.length!==n.length)return false;for(let s of r)if(!Object.prototype.hasOwnProperty.call(e,s)||!Object.is(t[s],e[s]))return false;return true};function x(t,e,r$1=Object.is){let n=typeof e=="function",s=typeof e=="string"?e:void 0,u=n?e:void 0,f=useCallback(o$1=>n?r(t,c=>u(c),r$1,o$1):o(t,()=>o$1()),[t,n,u,r$1]),p$1=useCallback(()=>{let o=p(t);return n?o==null?null:u(o):h(o,s)},[t,n,u,s]),l$1=useSyncExternalStore(f,p$1,p$1);return useEffect(()=>{l(t)||b(`useStore("${t}") - store not found yet.
2
- Component will update automatically when createStore("${t}") is called.`),a()&&!n&&!s&&!T.has(t)&&(T.add(t),b(`useStore("${t}") without a selector/path subscribes to the entire store and may re-render on every change.
3
- Prefer useSelector/useStoreField for better performance.`));},[t,n,s]),l$1}var P=(t,e)=>x(t,e),_=(t,e,r$1=w)=>{let n=useRef(null),s=useCallback(l=>{if(l==null)return null;let o=e(l),c=n.current;return c!==null&&r$1(o,c)?c:(n.current=o,o)},[e,r$1]),u=useCallback(()=>{let l=p(t);return s(l)},[t,s]),f=useCallback(l=>r(t,o=>s(o),r$1,()=>l()),[t,s,r$1]);return useSyncExternalStore(f,u,u)},$=(t,e)=>{let r=p(t);return r==null?null:h(r,e)};export{x as a,P as b,_ as c,$ as d};