@biglogic/rgs 2.9.3 → 3.0.0

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.
Files changed (49) hide show
  1. package/README.md +29 -8
  2. package/SECURITY.md +10 -0
  3. package/advanced.js +1 -1
  4. package/core/types.d.ts +22 -1
  5. package/core/utils.d.ts +2 -0
  6. package/examples/README.md +41 -0
  7. package/examples/async-data-fetch/UserLoader.d.ts +12 -0
  8. package/examples/async-data-fetch/UserLoader.ts +30 -0
  9. package/examples/basic-counter/CounterComponent.d.ts +2 -0
  10. package/examples/basic-counter/CounterComponent.tsx +22 -0
  11. package/examples/basic-counter/CounterStore.d.ts +7 -0
  12. package/examples/basic-counter/CounterStore.ts +25 -0
  13. package/examples/big-data-indexeddb/BigDataStore.d.ts +10 -0
  14. package/examples/big-data-indexeddb/BigDataStore.ts +60 -0
  15. package/examples/global-theme/ThemeManager.d.ts +7 -0
  16. package/examples/global-theme/ThemeManager.ts +32 -0
  17. package/examples/hybrid-cloud-sync/HybridStore.d.ts +19 -0
  18. package/examples/hybrid-cloud-sync/HybridStore.ts +78 -0
  19. package/examples/persistent-cart/CartStore.d.ts +13 -0
  20. package/examples/persistent-cart/CartStore.ts +41 -0
  21. package/examples/rbac-dashboard/DashboardStore.d.ts +47 -0
  22. package/examples/rbac-dashboard/DashboardStore.ts +46 -0
  23. package/examples/secure-auth/AuthStore.d.ts +14 -0
  24. package/examples/secure-auth/AuthStore.ts +36 -0
  25. package/examples/security-best-practices/SecurityStore.d.ts +22 -0
  26. package/examples/security-best-practices/SecurityStore.ts +75 -0
  27. package/examples/stress-tests/StressStore.d.ts +41 -0
  28. package/examples/stress-tests/StressStore.ts +61 -0
  29. package/examples/super-easy/EasyStore.d.ts +44 -0
  30. package/examples/super-easy/EasyStore.ts +61 -0
  31. package/examples/undo-redo-editor/EditorStore.d.ts +9 -0
  32. package/examples/undo-redo-editor/EditorStore.ts +28 -0
  33. package/index.d.ts +3 -2
  34. package/index.js +1 -1
  35. package/markdown/SUMMARY.md +4 -0
  36. package/markdown/api.md +40 -1
  37. package/markdown/chapters/03-the-magnetar-way.md +10 -3
  38. package/markdown/chapters/04-persistence-and-safety.md +46 -5
  39. package/markdown/chapters/05-plugins-and-extensibility.md +24 -8
  40. package/markdown/chapters/06-case-studies.md +69 -69
  41. package/markdown/chapters/08-migration-guide.md +48 -1
  42. package/markdown/chapters/09-security-architecture.md +40 -0
  43. package/package.json +84 -79
  44. package/plugins/index.d.ts +4 -2
  45. package/plugins/official/cloud-sync.plugin.d.ts +22 -0
  46. package/plugins/official/immer.plugin.d.ts +1 -1
  47. package/plugins/official/indexeddb.plugin.d.ts +7 -0
  48. package/plugins/official/undo-redo.plugin.d.ts +2 -2
  49. package/rgs-highlighter-2.9.5.vsix +0 -0
package/README.md CHANGED
@@ -101,7 +101,7 @@ Best for modern applications. Clean imports, zero global pollution.
101
101
  ```tsx
102
102
  import { gstate } from '@biglogic/rgs'
103
103
 
104
- // gstate CREA un hook personalizzato - NON si importa!
104
+ // gstate CREATES a custom hook - it is NOT imported!
105
105
  const useCounter = gstate({ count: 0 })
106
106
 
107
107
  // In your component
@@ -125,10 +125,8 @@ const [user, setUser] = useStore('user')
125
125
 
126
126
  ## 📚 Quick Examples
127
127
 
128
- ### Persistence
129
-
130
128
  ```tsx
131
- const store = gstate({ theme: 'dark' }, { persist: true })
129
+ const store = gstate({ theme: 'dark' }, "my-app")
132
130
  ```
133
131
 
134
132
  ### Encryption
@@ -154,16 +152,39 @@ const store = gstate({ theme: 'light' })
154
152
  store._addPlugin(syncPlugin({ channelName: 'my-app' }))
155
153
  ```
156
154
 
157
- ### Computed Values
158
-
159
155
  ```tsx
160
156
  const store = gstate({ firstName: 'John', lastName: 'Doe' })
161
- store.compute('fullName', ['firstName', 'lastName'],
162
- (s) => `${s.firstName} ${s.lastName}`)
157
+ store.compute('fullName', (get) => `${get('firstName')} ${get('lastName')}`)
163
158
 
164
159
  const [fullName] = store('fullName') // "John Doe"
165
160
  ```
166
161
 
162
+ ### Error Handling with onError
163
+
164
+ Handle errors gracefully with the `onError` callback - perfect for production apps:
165
+
166
+ ```tsx
167
+ const store = gstate({ data: null }, {
168
+ onError: (error, context) => {
169
+ console.error(`Error in ${context.operation}:`, error.message)
170
+ // Send to error tracking service (Sentry, etc.)
171
+ }
172
+ })
173
+ ```
174
+
175
+ ### Size Limits (maxObjectSize & maxTotalSize)
176
+
177
+ Protect your app from memory issues with automatic size warnings:
178
+
179
+ ```tsx
180
+ const store = gstate({ data: {} }, {
181
+ // Warn if single value exceeds 5MB (default)
182
+ maxObjectSize: 5 * 1024 * 1024,
183
+ // Warn if total store exceeds 50MB (default)
184
+ maxTotalSize: 50 * 1024 * 1024
185
+ })
186
+ ```
187
+
167
188
  ---
168
189
 
169
190
  ## Multiple Stores
package/SECURITY.md CHANGED
@@ -1,3 +1,13 @@
1
1
  # Security
2
2
 
3
+ React Globo State (RGS) implements enterprise-grade security including AES-256-GCM encryption, RBAC, and internal XSS sanitization as a secondary defense layer.
4
+
5
+ ## Reporting a Vulnerability
6
+
3
7
  Please email [@passariello](https://github.com/passariello) or see <https://dario.passariello.ca/contact/> if you have a potential security vulnerability to report.
8
+
9
+ ## Recent Hardening (v2.9.5)
10
+
11
+ - Improved XSS sanitization patterns to block `data:`, `vbscript:`, and complex HTML tag combinations.
12
+ - Implemented removal of HTML entity obfuscation.
13
+ - Enhanced deep cloning to support `Map`/`Set` and circular references.
package/advanced.js CHANGED
@@ -1 +1 @@
1
- var Lt=Object.defineProperty;var At=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),Jt=(e,t)=>{for(var r in t)Lt(e,r,{get:t[r],enumerable:!0})};var Wt=At((Or,Nt)=>{"use strict";var ht=Object.defineProperty,Xt=Object.getOwnPropertyDescriptor,Zt=Object.getOwnPropertyNames,Yt=Object.prototype.hasOwnProperty,er=(e,t)=>{for(var r in t)ht(e,r,{get:t[r],enumerable:!0})},tr=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Zt(t))!Yt.call(e,s)&&s!==r&&ht(e,s,{get:()=>t[s],enumerable:!(n=Xt(t,s))||n.enumerable});return e},rr=e=>tr(ht({},"__esModule",{value:!0}),e),Rt={};er(Rt,{Immer:()=>Vt,applyPatches:()=>Cr,castDraft:()=>_r,castImmutable:()=>Pr,createDraft:()=>Er,current:()=>Ut,enableArrayMethods:()=>Sr,enableMapSet:()=>mr,enablePatches:()=>yr,finishDraft:()=>Mr,freeze:()=>Ke,immerable:()=>se,isDraft:()=>L,isDraftable:()=>K,nothing:()=>Fe,original:()=>or,produce:()=>wr,produceWithPatches:()=>br,setAutoFreeze:()=>vr,setUseStrictIteration:()=>xr,setUseStrictShallowCopy:()=>Ar});Nt.exports=rr(Rt);var Fe=Symbol.for("immer-nothing"),se=Symbol.for("immer-draftable"),E=Symbol.for("immer-state");function T(e,...t){throw new Error(`[Immer] minified error nr: ${e}. Full error at: https://bit.ly/3cXEKWf`)}var F=Object,re=F.getPrototypeOf,ge="constructor",be="prototype",ut="configurable",ze="enumerable",De="writable",he="value",L=e=>!!e&&!!e[E];function K(e){return e?It(e)||ve(e)||!!e[se]||!!e[ge]?.[se]||Ae(e)||xe(e):!1}var nr=F[be][ge].toString(),Ct=new WeakMap;function It(e){if(!e||!ie(e))return!1;let t=re(e);if(t===null||t===F[be])return!0;let r=F.hasOwnProperty.call(t,ge)&&t[ge];if(r===Object)return!0;if(!te(r))return!1;let n=Ct.get(r);return n===void 0&&(n=Function.toString.call(r),Ct.set(r,n)),n===nr}function or(e){return L(e)||T(15,e),e[E].t}function ae(e,t,r=!0){ne(e)===0?(r?Reflect.ownKeys(e):F.keys(e)).forEach(n=>{t(n,e[n],e)}):e.forEach((n,s)=>t(s,n,e))}function ne(e){let t=e[E];return t?t.r:ve(e)?1:Ae(e)?2:xe(e)?3:0}var pe=(e,t,r=ne(e))=>r===2?e.has(t):F[be].hasOwnProperty.call(e,t),X=(e,t,r=ne(e))=>r===2?e.get(t):e[t],je=(e,t,r,n=ne(e))=>{n===2?e.set(t,r):n===3?e.add(r):e[t]=r};function sr(e,t){return e===t?e!==0||1/e===1/t:e!==e&&t!==t}var ve=Array.isArray,Ae=e=>e instanceof Map,xe=e=>e instanceof Set,ie=e=>typeof e=="object",te=e=>typeof e=="function",lt=e=>typeof e=="boolean";function ir(e){let t=+e;return Number.isInteger(t)&&String(t)===e}var Ot=e=>ie(e)?e?.[E]:null,z=e=>e.e||e.t,ar=e=>{let t=Ot(e);return t?t.e??t.t:e},yt=e=>e.s?e.e:e.t;function ft(e,t){if(Ae(e))return new Map(e);if(xe(e))return new Set(e);if(ve(e))return Array[be].slice.call(e);let r=It(e);if(t===!0||t==="class_only"&&!r){let n=F.getOwnPropertyDescriptors(e);delete n[E];let s=Reflect.ownKeys(n);for(let l=0;l<s.length;l++){let g=s[l],x=n[g];x[De]===!1&&(x[De]=!0,x[ut]=!0),(x.get||x.set)&&(n[g]={[ut]:!0,[De]:!0,[ze]:x[ze],[he]:e[g]})}return F.create(re(e),n)}else{let n=re(e);if(n!==null&&r)return{...e};let s=F.create(n);return F.assign(s,e)}}function Ke(e,t=!1){return Be(e)||L(e)||!K(e)||(ne(e)>1&&F.defineProperties(e,{set:Oe,add:Oe,clear:Oe,delete:Oe}),F.freeze(e),t&&ae(e,(r,n)=>{Ke(n,!0)},!1)),e}function lr(){T(2)}var Oe={[he]:lr};function Be(e){return e===null||!ie(e)?!0:F.isFrozen(e)}var ye="MapSet",Te="Patches",pt="ArrayMethods",Ve={};function oe(e){let t=Ve[e];return t||T(0,e),t}var Et=e=>!!Ve[e];function mt(e,t){Ve[e]||(Ve[e]=t)}var me,Ue=()=>me,cr=(e,t)=>({o:[],i:e,l:t,F:!0,m:0,P:new Set,T:new Set,I:Et(ye)?oe(ye):void 0,E:Et(pt)?oe(pt):void 0});function Mt(e,t){t&&(e.x=oe(Te),e.y=[],e.d=[],e.C=t)}function dt(e){gt(e),e.o.forEach(ur),e.o=null}function gt(e){e===me&&(me=e.i)}var _t=e=>me=cr(me,e);function ur(e){let t=e[E];t.r===0||t.r===1?t.b():t.g=!0}function Pt(e,t){t.m=t.o.length;let r=t.o[0];if(e!==void 0&&e!==r){r[E].s&&(dt(t),T(4)),K(e)&&(e=kt(t,e));let{x:n}=t;n&&n.M(r[E].t,e,t)}else e=kt(t,r);return fr(t,e,!0),dt(t),t.y&&t.C(t.y,t.d),e!==Fe?e:void 0}function kt(e,t){if(Be(t))return t;let r=t[E];if(!r)return Ne(t,e.P,e);if(!Le(r,e))return t;if(!r.s)return r.t;if(!r.u){let{f:n}=r;if(n)for(;n.length>0;)n.pop()(e);jt(r,e)}return r.e}function fr(e,t,r=!1){!e.i&&e.l.h&&e.F&&Ke(t,r)}function Dt(e){e.u=!0,e.a.m--}var Le=(e,t)=>e.a===t,pr=[];function zt(e,t,r,n){let s=z(e),l=e.r;if(n!==void 0&&X(s,n,l)===t){je(s,n,r,l);return}if(!e.D){let x=e.D=new Map;ae(s,(v,a)=>{if(L(a)){let u=x.get(a)||[];u.push(v),x.set(a,u)}})}let g=e.D.get(t)??pr;for(let x of g)je(s,x,r,l)}function dr(e,t,r){e.f.push(function(n){let s=t;if(!s||!Le(s,n))return;n.I?.fixSetContents(s);let l=yt(s);zt(e,s.c??s,l,r),jt(s,n)})}function jt(e,t){if(e.s&&!e.u&&(e.r===3||e.r===1&&e.R||(e.n?.size??0)>0)){let{x:r}=t;if(r){let n=r.getPath(e);n&&r.O(e,n,t)}Dt(e)}}function $e(e,t,r){let{a:n}=e;if(L(r)){let s=r[E];Le(s,n)&&s.f.push(function(){de(e);let l=yt(s);zt(e,r,l,t)})}else K(r)&&e.f.push(function(){let s=z(e);e.r===3?s.has(r)&&Ne(r,n.P,n):X(s,t,e.r)===r&&n.o.length>1&&(e.n.get(t)??!1)===!0&&e.e&&Ne(X(e.e,t,e.r),n.P,n)})}function Ne(e,t,r){return!r.l.h&&r.m<1||L(e)||t.has(e)||!K(e)||Be(e)||(t.add(e),ae(e,(n,s)=>{if(L(s)){let l=s[E];if(Le(l,r)){let g=yt(l);je(e,n,g,e.r),Dt(l)}}else K(s)&&Ne(s,t,r)})),e}function gr(e,t){let r=ve(e),n={r:r?1:0,a:t?t.a:Ue(),s:!1,u:!1,n:void 0,i:t,t:e,c:null,e:null,b:null,S:!1,f:void 0},s=n,l=We;r&&(s=[n],l=Se);let{revoke:g,proxy:x}=Proxy.revocable(s,l);return n.c=x,n.b=g,[x,n]}var We={get(e,t){if(t===E)return e;let r=e.a.E,n=e.r===1&&typeof t=="string";if(n&&r?.isArrayOperationMethod(t))return r.createMethodInterceptor(e,t);let s=z(e);if(!pe(s,t,e.r))return hr(e,s,t);let l=s[t];if(e.u||!K(l)||n&&e.operationMethod&&r?.isMutatingArrayMethod(e.operationMethod)&&ir(t))return l;if(l===ct(e.t,t)){de(e);let g=e.r===1?+t:t,x=we(e.a,l,e,g);return e.e[g]=x}return l},has(e,t){return t in z(e)},ownKeys(e){return Reflect.ownKeys(z(e))},set(e,t,r){let n=Tt(z(e),t);if(n?.set)return n.set.call(e.c,r),!0;if(!e.s){let s=ct(z(e),t),l=s?.[E];if(l&&l.t===r)return e.e[t]=r,e.n.set(t,!1),!0;if(sr(r,s)&&(r!==void 0||pe(e.t,t,e.r)))return!0;de(e),H(e)}return e.e[t]===r&&(r!==void 0||t in e.e)||Number.isNaN(r)&&Number.isNaN(e.e[t])||(e.e[t]=r,e.n.set(t,!0),$e(e,t,r)),!0},deleteProperty(e,t){return de(e),ct(e.t,t)!==void 0||t in e.t?(e.n.set(t,!1),H(e)):e.n.delete(t),e.e&&delete e.e[t],!0},getOwnPropertyDescriptor(e,t){let r=z(e),n=Reflect.getOwnPropertyDescriptor(r,t);return n&&{[De]:!0,[ut]:e.r!==1||t!=="length",[ze]:n[ze],[he]:r[t]}},defineProperty(){T(11)},getPrototypeOf(e){return re(e.t)},setPrototypeOf(){T(12)}},Se={};for(let e in We){let t=We[e];Se[e]=function(){let r=arguments;return r[0]=r[0][0],t.apply(this,r)}}Se.deleteProperty=function(e,t){return Se.set.call(this,e,t,void 0)};Se.set=function(e,t,r){return We.set.call(this,e[0],t,r,e[0])};function ct(e,t){let r=e[E];return(r?z(r):e)[t]}function hr(e,t,r){let n=Tt(t,r);return n?he in n?n[he]:n.get?.call(e.c):void 0}function Tt(e,t){if(!(t in e))return;let r=re(e);for(;r;){let n=Object.getOwnPropertyDescriptor(r,t);if(n)return n;r=re(r)}}function H(e){e.s||(e.s=!0,e.i&&H(e.i))}function de(e){e.e||(e.n=new Map,e.e=ft(e.t,e.a.l.A))}var Vt=class{constructor(e){this.h=!0,this.A=!1,this._=!1,this.produce=(t,r,n)=>{if(te(t)&&!te(r)){let l=r;r=t;let g=this;return function(x=l,...v){return g.produce(x,a=>r.call(this,a,...v))}}te(r)||T(6),n!==void 0&&!te(n)&&T(7);let s;if(K(t)){let l=_t(this),g=we(l,t,void 0),x=!0;try{s=r(g),x=!1}finally{x?dt(l):gt(l)}return Mt(l,n),Pt(s,l)}else if(!t||!ie(t)){if(s=r(t),s===void 0&&(s=t),s===Fe&&(s=void 0),this.h&&Ke(s,!0),n){let l=[],g=[];oe(Te).M(t,s,{y:l,d:g}),n(l,g)}return s}else T(1,t)},this.produceWithPatches=(t,r)=>{if(te(t))return(l,...g)=>this.produceWithPatches(l,x=>t(x,...g));let n,s;return[this.produce(t,r,(l,g)=>{n=l,s=g}),n,s]},lt(e?.autoFreeze)&&this.setAutoFreeze(e.autoFreeze),lt(e?.useStrictShallowCopy)&&this.setUseStrictShallowCopy(e.useStrictShallowCopy),lt(e?.useStrictIteration)&&this.setUseStrictIteration(e.useStrictIteration)}createDraft(e){K(e)||T(8),L(e)&&(e=Ut(e));let t=_t(this),r=we(t,e,void 0);return r[E].S=!0,gt(t),r}finishDraft(e,t){let r=e&&e[E];(!r||!r.S)&&T(9);let{a:n}=r;return Mt(n,t),Pt(void 0,n)}setAutoFreeze(e){this.h=e}setUseStrictShallowCopy(e){this.A=e}setUseStrictIteration(e){this._=e}shouldUseStrictIteration(){return this._}applyPatches(e,t){let r;for(r=t.length-1;r>=0;r--){let s=t[r];if(s.path.length===0&&s.op==="replace"){e=s.value;break}}r>-1&&(t=t.slice(r+1));let n=oe(Te).N;return L(e)?n(e,t):this.produce(e,s=>n(s,t))}};function we(e,t,r,n){let[s,l]=Ae(t)?oe(ye).w(t,r):xe(t)?oe(ye).V(t,r):gr(t,r);return(r?.a??Ue()).o.push(s),l.f=r?.f??[],l.p=n,r&&n!==void 0?dr(r,l,n):l.f.push(function(g){g.I?.fixSetContents(l);let{x}=g;l.s&&x&&x.O(l,[],g)}),s}function Ut(e){return L(e)||T(10,e),$t(e)}function $t(e){if(!K(e)||Be(e))return e;let t=e[E],r,n=!0;if(t){if(!t.s)return t.t;t.u=!0,r=ft(e,t.a.l.A),n=t.a.l.shouldUseStrictIteration()}else r=ft(e,!0);return ae(r,(s,l)=>{je(r,s,$t(l))},n),t&&(t.u=!1),r}function yr(){function e(p,S=[]){if(p.p!==void 0){let C=p.i.e??p.i.t,m=Ot(X(C,p.p)),R=X(C,p.p);if(R===void 0||R!==p.c&&R!==p.t&&R!==p.e||m!=null&&m.t!==p.t)return null;let I=p.i.r===3,A;if(I){let i=p.i;A=Array.from(i.o.keys()).indexOf(p.p)}else A=p.p;if(!(I&&C.size>A||pe(C,A)))return null;S.push(A)}if(p.i)return e(p.i,S);S.reverse();try{t(p.e,S)}catch{return null}return S}function t(p,S){let C=p;for(let m=0;m<S.length-1;m++){let R=S[m];if(C=X(C,R),!ie(C)||C===null)throw new Error(`Cannot resolve path at '${S.join("/")}'`)}return C}let r="replace",n="add",s="remove";function l(p,S,C){if(p.a.T.has(p))return;p.a.T.add(p);let{y:m,d:R}=C;switch(p.r){case 0:case 2:return x(p,S,m,R);case 1:return g(p,S,m,R);case 3:return v(p,S,m,R)}}function g(p,S,C,m){let{t:R,n:I}=p,A=p.e;A.length<R.length&&([R,A]=[A,R],[C,m]=[m,C]);let i=p.R===!0;for(let d=0;d<R.length;d++){let h=A[d],w=R[d];if((i||I?.get(d.toString()))&&h!==w){let _=h?.[E];if(_&&_.s)continue;let j=S.concat([d]);C.push({op:r,path:j,value:D(h)}),m.push({op:r,path:j,value:D(w)})}}for(let d=R.length;d<A.length;d++){let h=S.concat([d]);C.push({op:n,path:h,value:D(A[d])})}for(let d=A.length-1;R.length<=d;--d){let h=S.concat([d]);m.push({op:s,path:h})}}function x(p,S,C,m){let{t:R,e:I,r:A}=p;ae(p.n,(i,d)=>{let h=X(R,i,A),w=X(I,i,A),_=d?pe(R,i)?r:n:s;if(h===w&&_===r)return;let j=S.concat(i);C.push(_===s?{op:_,path:j}:{op:_,path:j,value:D(w)}),m.push(_===n?{op:s,path:j}:_===s?{op:n,path:j,value:D(h)}:{op:r,path:j,value:D(h)})})}function v(p,S,C,m){let{t:R,e:I}=p,A=0;R.forEach(i=>{if(!I.has(i)){let d=S.concat([A]);C.push({op:s,path:d,value:i}),m.unshift({op:n,path:d,value:i})}A++}),A=0,I.forEach(i=>{if(!R.has(i)){let d=S.concat([A]);C.push({op:n,path:d,value:i}),m.unshift({op:s,path:d,value:i})}A++})}function a(p,S,C){let{y:m,d:R}=C;m.push({op:r,path:[],value:S===Fe?void 0:S}),R.push({op:r,path:[],value:p})}function u(p,S){return S.forEach(C=>{let{path:m,op:R}=C,I=p;for(let h=0;h<m.length-1;h++){let w=ne(I),_=m[h];typeof _!="string"&&typeof _!="number"&&(_=""+_),(w===0||w===1)&&(_==="__proto__"||_===ge)&&T(19),te(I)&&_===be&&T(19),I=X(I,_),ie(I)||T(18,m.join("/"))}let A=ne(I),i=M(C.value),d=m[m.length-1];switch(R){case r:switch(A){case 2:return I.set(d,i);case 3:T(16);default:return I[d]=i}case n:switch(A){case 1:return d==="-"?I.push(i):I.splice(d,0,i);case 2:return I.set(d,i);case 3:return I.add(i);default:return I[d]=i}case s:switch(A){case 1:return I.splice(d,1);case 2:return I.delete(d);case 3:return I.delete(C.value);default:return delete I[d]}default:T(17,R)}}),p}function M(p){if(!K(p))return p;if(ve(p))return p.map(M);if(Ae(p))return new Map(Array.from(p.entries()).map(([C,m])=>[C,M(m)]));if(xe(p))return new Set(Array.from(p).map(M));let S=Object.create(re(p));for(let C in p)S[C]=M(p[C]);return pe(p,se)&&(S[se]=p[se]),S}function D(p){return L(p)?M(p):p}mt(Te,{N:u,O:l,M:a,getPath:e})}function mr(){class e extends Map{constructor(a,u){super(),this[E]={r:2,i:u,a:u?u.a:Ue(),s:!1,u:!1,e:void 0,n:void 0,t:a,c:this,S:!1,g:!1,f:[]}}get size(){return z(this[E]).size}has(a){return z(this[E]).has(a)}set(a,u){let M=this[E];return g(M),(!z(M).has(a)||z(M).get(a)!==u)&&(r(M),H(M),M.n.set(a,!0),M.e.set(a,u),M.n.set(a,!0),$e(M,a,u)),this}delete(a){if(!this.has(a))return!1;let u=this[E];return g(u),r(u),H(u),u.t.has(a)?u.n.set(a,!1):u.n.delete(a),u.e.delete(a),!0}clear(){let a=this[E];g(a),z(a).size&&(r(a),H(a),a.n=new Map,ae(a.t,u=>{a.n.set(u,!1)}),a.e.clear())}forEach(a,u){let M=this[E];z(M).forEach((D,p,S)=>{a.call(u,this.get(p),p,this)})}get(a){let u=this[E];g(u);let M=z(u).get(a);if(u.u||!K(M)||M!==u.t.get(a))return M;let D=we(u.a,M,u,a);return r(u),u.e.set(a,D),D}keys(){return z(this[E]).keys()}values(){let a=this.keys();return{[Symbol.iterator]:()=>this.values(),next:()=>{let u=a.next();return u.done?u:{done:!1,value:this.get(u.value)}}}}entries(){let a=this.keys();return{[Symbol.iterator]:()=>this.entries(),next:()=>{let u=a.next();if(u.done)return u;let M=this.get(u.value);return{done:!1,value:[u.value,M]}}}}[Symbol.iterator](){return this.entries()}}function t(v,a){let u=new e(v,a);return[u,u[E]]}function r(v){v.e||(v.n=new Map,v.e=new Map(v.t))}class n extends Set{constructor(a,u){super(),this[E]={r:3,i:u,a:u?u.a:Ue(),s:!1,u:!1,e:void 0,t:a,c:this,o:new Map,g:!1,S:!1,n:void 0,f:[]}}get size(){return z(this[E]).size}has(a){let u=this[E];return g(u),u.e?!!(u.e.has(a)||u.o.has(a)&&u.e.has(u.o.get(a))):u.t.has(a)}add(a){let u=this[E];return g(u),this.has(a)||(l(u),H(u),u.e.add(a),$e(u,a,a)),this}delete(a){if(!this.has(a))return!1;let u=this[E];return g(u),l(u),H(u),u.e.delete(a)||(u.o.has(a)?u.e.delete(u.o.get(a)):!1)}clear(){let a=this[E];g(a),z(a).size&&(l(a),H(a),a.e.clear())}values(){let a=this[E];return g(a),l(a),a.e.values()}entries(){let a=this[E];return g(a),l(a),a.e.entries()}keys(){return this.values()}[Symbol.iterator](){return this.values()}forEach(a,u){let M=this.values(),D=M.next();for(;!D.done;)a.call(u,D.value,D.value,this),D=M.next()}}function s(v,a){let u=new n(v,a);return[u,u[E]]}function l(v){v.e||(v.e=new Set,v.t.forEach(a=>{if(K(a)){let u=we(v.a,a,v,a);v.o.set(a,u),v.e.add(u)}else v.e.add(a)}))}function g(v){v.g&&T(3,JSON.stringify(z(v)))}function x(v){if(v.r===3&&v.e){let a=new Set(v.e);v.e.clear(),a.forEach(u=>{v.e.add(ar(u))})}}mt(ye,{w:t,V:s,fixSetContents:x})}function Sr(){let e=new Set(["shift","unshift"]),t=new Set(["push","pop"]),r=new Set([...t,...e]),n=new Set(["reverse","sort"]),s=new Set([...r,...n,"splice"]),l=new Set(["find","findLast"]),g=new Set(["filter","slice","concat","flat",...l,"findIndex","findLastIndex","some","every","indexOf","lastIndexOf","includes","join","toString","toLocaleString"]);function x(i){return s.has(i)}function v(i){return g.has(i)}function a(i){return x(i)||v(i)}function u(i,d){i.operationMethod=d}function M(i){i.operationMethod=void 0}function D(i,d,h=!0){de(i);let w=d();return H(i),h&&i.n.set("length",!0),w}function p(i){i.R=!0}function S(i,d){return i<0?Math.max(d+i,0):Math.min(i,d)}function C(i,d,h){for(let w=0;w<h.length;w++){let _=d+w;i.n.set(_,!0),$e(i,_,h[w])}}function m(i,d,h){return D(i,()=>{let w=i.e.length,_=i.e[d](...h);return e.has(d)&&p(i),d==="push"&&h.length>0?C(i,w,h):d==="unshift"&&h.length>0&&C(i,0,h),r.has(d)?_:i.c})}function R(i,d,h){return D(i,()=>(i.e[d](...h),p(i),i.c),!1)}function I(i,d){return function(...h){let w=d;u(i,w);try{if(x(w)){if(r.has(w))return m(i,w,h);if(n.has(w))return R(i,w,h);if(w==="splice"){let _=D(i,()=>i.e.splice(...h));if(p(i),h.length>2){let j=S(h[0]??0,i.e.length);C(i,j,h.slice(2))}return _}}else return A(i,w,h)}finally{M(i)}}}function A(i,d,h){let w=z(i);if(d==="filter"){let _=h[0],j=[];for(let N=0;N<w.length;N++)_(w[N],N,w)&&j.push(i.c[N]);return j}if(l.has(d)){let _=h[0],j=d==="find",N=j?1:-1,J=j?0:w.length-1;for(let W=J;W>=0&&W<w.length;W+=N)if(_(w[W],W,w))return i.c[W];return}if(d==="slice"){let _=h[0]??0,j=h[1]??w.length,N=S(_,w.length),J=S(j,w.length),W=[];for(let Z=N;Z<J;Z++)W.push(i.c[Z]);return W}return w[d](...h)}mt(pt,{createMethodInterceptor:I,isArrayOperationMethod:a,isMutatingArrayMethod:x})}var $=new Vt,wr=$.produce,br=$.produceWithPatches.bind($),vr=$.setAutoFreeze.bind($),Ar=$.setUseStrictShallowCopy.bind($),xr=$.setUseStrictIteration.bind($),Cr=$.applyPatches.bind($),Er=$.createDraft.bind($),Mr=$.finishDraft.bind($),_r=e=>e,Pr=e=>e});var Kt=At((zr,Ft)=>{"use strict";Ft.exports=Wt()});var at={};Jt(at,{addAccessRule:()=>Re,decrypt:()=>Ye,deleteUserData:()=>it,encrypt:()=>Ze,exportKey:()=>Ht,exportUserData:()=>st,generateEncryptionKey:()=>Gt,getConsents:()=>ot,hasConsent:()=>rt,hasPermission:()=>fe,importKey:()=>qt,isAuditActive:()=>et,isCryptoAvailable:()=>xt,logAudit:()=>ue,recordConsent:()=>Ie,revokeConsent:()=>nt,sanitizeValue:()=>ce,setAuditLogger:()=>Qt,validateKey:()=>tt});var xt=typeof crypto<"u"&&typeof crypto.subtle<"u"&&typeof crypto.subtle.generateKey=="function",Gt=async()=>{if(!xt)throw new Error("Web Crypto API not available");let e=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),t=crypto.getRandomValues(new Uint8Array(12));return{key:e,iv:t}},Ht=async e=>{let t=await crypto.subtle.exportKey("raw",e.key);return{key:btoa(String.fromCharCode(...new Uint8Array(t))),iv:btoa(String.fromCharCode(...e.iv))}},qt=async(e,t)=>{let r=Uint8Array.from(atob(e),l=>l.charCodeAt(0)),n=Uint8Array.from(atob(t),l=>l.charCodeAt(0));return{key:await crypto.subtle.importKey("raw",r,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),iv:n}},Ze=async(e,t)=>{let r=new TextEncoder,n=r.encode(JSON.stringify(e)),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:t.iv},t.key,n),l=new Uint8Array(t.iv.length+s.byteLength);return l.set(t.iv),l.set(new Uint8Array(s),t.iv.length),btoa(String.fromCharCode(...l))},Ye=async(e,t)=>{let r=Uint8Array.from(atob(e),g=>g.charCodeAt(0)),n=r.slice(0,12),s=r.slice(12),l=await crypto.subtle.decrypt({name:"AES-GCM",iv:n},t.key,s);return JSON.parse(new TextDecoder().decode(l))},ke=null,Qt=e=>{ke=e},et=()=>ke!==null,ue=e=>{ke&&ke(e)},Re=(e,t,r)=>{e.set(t instanceof RegExp?t.source:t,r)},fe=(e,t,r,n)=>{if(e.size===0)return!0;for(let[s,l]of e){let g;if(typeof s=="function")g=s(t,n);else try{g=new RegExp(s).test(t)}catch{continue}if(g)return l.includes(r)||l.includes("admin")}return!1},ce=e=>{if(typeof e=="string")return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"").replace(/javascript:/gi,"[REMOVED]").replace(/on\w+\s*=/gi,"[REMOVED]=").replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,"").replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi,"").replace(/<embed\b[^<]*(?:(?!<\/embed>)<[^<]*)*<\/embed>/gi,"").replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi,"").replace(/<foreignObject\b[^<]*(?:(?!<\/foreignObject>)<[^<]*)*<\/foreignObject>/gi,"").replace(/<math\b[^<]*(?:(?!<\/math>)<[^<]*)*<\/math>/gi,"").replace(/<\?php\b[^<]*(?:(?!<\?php>)<[^<]*)*<\?php>/gi,"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"&#x27;").replace(/`/g,"&#x60;");if(e&&typeof e=="object"&&!Array.isArray(e)){let t={};for(let[r,n]of Object.entries(e))t[r]=ce(n);return t}return Array.isArray(e)?e.map(t=>ce(t)):e},tt=e=>/^[a-zA-Z0-9_.-]+$/.test(e)&&e.length<=256,Ie=(e,t,r,n)=>{let s={id:crypto.randomUUID(),purpose:r,granted:n,timestamp:Date.now()},l=e.get(t)||[];return l.push(s),e.set(t,l),ue({timestamp:Date.now(),action:"set",key:`consent:${r}`,userId:t,success:!0}),s},rt=(e,t,r)=>{let n=e.get(t);if(!n)return!1;for(let s=n.length-1;s>=0;s--){let l=n[s];if(l&&l.purpose===r)return l.granted}return!1},nt=(e,t,r)=>Ie(e,t,r,!1),ot=(e,t)=>e.get(t)||[],st=(e,t)=>({userId:t,exportedAt:Date.now(),consents:e.get(t)||[]}),it=(e,t)=>{let r=e.get(t)?.length||0;return e.delete(t),{success:!0,deletedConsents:r}};var St=null,Ce=null,kr=()=>{if(!St)try{let e=Kt();St=e.produce,Ce=e.freeze}catch(e){throw console.error("[gState] Immer not installed. Run: npm install immer"),e}},He={local:()=>typeof window<"u"?window.localStorage:null,session:()=>typeof window<"u"?window.sessionStorage:null,memory:()=>{let e=new Map;return{getItem:t=>e.get(t)||null,setItem:(t,r)=>e.set(t,r),removeItem:t=>e.delete(t),key:t=>Array.from(e.keys())[t]||null,get length(){return e.size}}}},Je=e=>{if(e===null||typeof e!="object")return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch{}let t=new WeakMap,r=n=>{if(n===null||typeof n!="object")return n;if(t.has(n))return t.get(n);if(n instanceof Date)return new Date(n.getTime());if(n instanceof RegExp)return new RegExp(n.source,n.flags);let s=Array.isArray(n)?[]:Object.create(Object.getPrototypeOf(n));if(t.set(n,s),Array.isArray(n))for(let l=0;l<n.length;l++)s[l]=r(n[l]);else for(let l of Object.keys(n))s[l]=r(n[l]);return s};return r(e)},Ge=(e,t)=>{if(e===t)return!0;if(e===null||t===null||typeof e!="object"||typeof t!="object")return e===t;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let s=0;s<e.length;s++)if(!Ge(e[s],t[s]))return!1;return!0}let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let s of r)if(!n.includes(s)||!Ge(e[s],t[s]))return!1;return!0},qe=e=>{let t=new Map,r=new Map,n=new Map,s=new Set,l=new Map,g=new Set,x=new Map,v=new Map,a=new Map,u=new Map,M=new Map,D=new Map,p=new Map,S=new Map,C=e?.namespace||"gstate",m=e?.silent??!1,R=e?.debounceTime??150,I=e?.version??0,A=e?.storage||He.local(),i=e?.onError,d=e?.maxObjectSize??5*1024*1024,h=e?.maxTotalSize??50*1024*1024,w=e?.encryptionKey??null,_=e?.validateInput??!0,j=e?.auditEnabled??!0,N=e?.userId,J=e?.immer??!0;J&&kr(),e?.accessRules&&e.accessRules.forEach(o=>Re(p,o.pattern,o.permissions));let W=!1,Z=!1,Ee=!1,G=0,Qe=null,Me,Bt=new Promise(o=>{Me=o}),Xe=o=>{if(o==null)return 0;let c=0,f=[o],y=new WeakSet;for(;f.length>0;){let P=f.pop();if(typeof P=="boolean")c+=4;else if(typeof P=="number")c+=8;else if(typeof P=="string")c+=P.length*2;else if(typeof P=="object"&&P!==null){let b=P;if(y.has(b))continue;if(y.add(b),Array.isArray(b))for(let k=0;k<b.length;k++)f.push(b[k]);else for(let k of Object.keys(b))c+=k.length*2,f.push(b[k])}}return c},_e=()=>`${C}_`,Y=(o,c)=>{u.forEach(f=>{if(f.hooks?.[o])try{f.hooks[o](c)}catch(y){let P=y instanceof Error?y:new Error(String(y));i?i(P,{operation:`plugin:${f.name}:${o}`,key:c.key}):m||console.error(`[gState] Plugin "${f.name}" error:`,y)}})},q=(o,c,f,y)=>{j&&et()&&ue&&ue({timestamp:Date.now(),action:o,key:c,userId:N,success:f,error:y})},le=o=>{if(o&&(a.get(o)?.forEach(c=>wt(c)),x.get(o)?.forEach(c=>{try{c(U.get(o))}catch(f){let y=f instanceof Error?f:new Error(String(f));i?i(y,{operation:"watcher",key:o}):m||console.error(`[gState] Watcher error for "${o}":`,f)}}),l.get(o)?.forEach(c=>{try{c()}catch(f){let y=f instanceof Error?f:new Error(String(f));i?i(y,{operation:"keyListener",key:o}):m||console.error(`[gState] Listener error for "${o}":`,f)}})),W){Z=!0;return}s.forEach(c=>{try{c()}catch(f){let y=f instanceof Error?f:new Error(String(f));i?i(y,{operation:"listener"}):m||console.error("[gState] Global listener error:",f)}})},wt=o=>{let c=v.get(o),f=new Set;if(!c)return;let y=b=>(f.add(b),U.get(b)),P=c.selector(y);c.deps.forEach(b=>{if(!f.has(b)){let k=a.get(b);k&&(k.delete(o),k.size===0&&a.delete(b))}}),f.forEach(b=>{c.deps.has(b)||(a.has(b)||a.set(b,new Set),a.get(b).add(o))}),c.deps=f,Ge(c.lastValue,P)||(c.lastValue=J&&P!==null&&typeof P=="object"?Ce(Je(P),!0):P,r.set(o,(r.get(o)||0)+1),le(o))},bt=async()=>{if(!A)return;let o=Array.from(M.entries());M.clear();for(let[c,f]of o)try{let y=f.value,P=f.options.encoded||f.options.secure;if(f.options.encrypted){if(!w)throw new Error(`Encryption key missing for "${c}"`);y=await Ze(f.value,w)}else P?y=btoa(JSON.stringify(f.value)):typeof f.value=="object"&&f.value!==null&&(y=JSON.stringify(f.value));A.setItem(`${_e()}${c}`,JSON.stringify({v:r.get(c)||1,t:Date.now(),e:f.options.ttl?Date.now()+f.options.ttl:null,d:y,_sys_v:I,_enc:f.options.encrypted?!0:void 0,_b64:P?!0:void 0})),q("set",c,!0)}catch(y){let P=y instanceof Error?y:new Error(String(y));i?i(P,{operation:"persist",key:c}):m||console.error("[gState] Persist failed:",P)}},ee={},U={_setSilently:(o,c)=>{let f=n.get(o)||0,y=J&&c!==null&&typeof c=="object"?Ce(Je(c),!0):c,P=Xe(y);G=G-f+P,n.set(o,P),t.set(o,y),r.set(o,(r.get(o)||0)+1)},_registerMethod:(o,c,f)=>{if(f!==void 0){let b=o,k=c;ee[b]||(ee[b]={}),ee[b][k]=f;return}console.warn("[gState] _registerMethod(name, fn) is deprecated. Use _registerMethod(pluginName, methodName, fn) instead.");let y=o,P=c;ee.core||(ee.core={}),ee.core[y]=P},set:(o,c,f={})=>{let y=t.get(o),P=J&&typeof c=="function"?St(y,c):c;if(_&&!tt(o))return m||console.warn(`[gState] Invalid key: ${o}`),!1;if(!fe(p,o,"write",N))return q("set",o,!1,"RBAC Denied"),m||console.error(`[gState] RBAC Denied for "${o}"`),!1;let b=_?ce(P):P,k=n.get(o)||0;Y("onBeforeSet",{key:o,value:b,store:U,version:r.get(o)||0});let B=J&&b!==null&&typeof b=="object"?Ce(Je(b),!0):b;if(!Ge(y,B)){let O=d>0||h>0?Xe(B):0;if(d>0&&O>d){let V=new Error(`Object size (${O} bytes) exceeds maxObjectSize (${d} bytes)`);i?i(V,{operation:"set",key:o}):m||console.warn(`[gState] ${V.message} for "${o}"`)}if(h>0){let V=G-k+O;if(V>h){let Pe=new Error(`Total store size (${V} bytes) exceeds limit (${h} bytes)`);i?i(Pe,{operation:"set"}):m||console.warn(`[gState] ${Pe.message}`)}}G=G-k+O,n.set(o,O),t.set(o,B),r.set(o,(r.get(o)||0)+1);let Q=!!(f.persist||e?.persistByDefault||e?.persistence||f.encrypted||f.encoded||f.secure||f.ttl);return Q&&(M.set(o,{value:B,options:{...f,persist:Q}}),Qe&&clearTimeout(Qe),Qe=setTimeout(bt,R)),Y("onSet",{key:o,value:B,store:U,version:r.get(o)}),q("set",o,!0),le(o),!0}return!1},get:o=>{if(!fe(p,o,"read",N))return q("get",o,!1,"RBAC Denied"),null;let c=t.get(o);return Y("onGet",{store:U,key:o,value:c}),q("get",o,!0),c},compute:(o,c)=>{try{return v.has(o)||(v.set(o,{selector:c,lastValue:null,deps:new Set}),wt(o)),v.get(o).lastValue}catch(f){let y=f instanceof Error?f:new Error(String(f));return i?i(y,{operation:"compute",key:o}):m||console.error(`[gState] Compute error for "${o}":`,f),null}},watch:(o,c)=>{x.has(o)||x.set(o,new Set);let f=x.get(o);return f.add(c),()=>{f.delete(c),f.size===0&&x.delete(o)}},remove:o=>{if(!fe(p,o,"delete",N))return q("delete",o,!1,"RBAC Denied"),!1;let c=t.get(o),f=t.delete(o);return f&&(G-=n.get(o)||0,n.delete(o),Y("onRemove",{store:U,key:o,value:c})),r.set(o,(r.get(o)||0)+1),A&&A.removeItem(`${_e()}${o}`),q("delete",o,!0),le(o),f},delete:o=>U.remove(o),deleteAll:()=>{if(Array.from(t.keys()).forEach(o=>U.remove(o)),A){let o=_e();for(let c=0;c<(A.length||0);c++){let f=A.key(c);f?.startsWith(o)&&(A.removeItem(f),c--)}}return G=0,n.clear(),!0},list:()=>Object.fromEntries(t.entries()),use:o=>{g.add(o)},transaction:o=>{W=!0,Y("onTransaction",{store:U,key:"START"});try{o()}finally{W=!1,Y("onTransaction",{store:U,key:"END"}),Z&&(Z=!1,le())}},destroy:()=>{typeof window<"u"&&window.removeEventListener("beforeunload",vt),Y("onDestroy",{store:U}),s.clear(),l.clear(),x.clear(),v.clear(),a.clear(),u.clear(),t.clear(),n.clear(),G=0,p.clear(),S.clear()},_addPlugin:o=>{try{u.set(o.name,o),o.hooks?.onInstall?.({store:U})}catch(c){let f=c instanceof Error?c:new Error(String(c));i?i(f,{operation:"plugin:install",key:o.name}):m||console.error(`[gState] Failed to install plugin "${o.name}":`,c)}},_removePlugin:o=>{u.delete(o)},_subscribe:(o,c)=>{if(c){l.has(c)||l.set(c,new Set);let f=l.get(c);return f.add(o),()=>{f.delete(o),f.size===0&&l.delete(c)}}return s.add(o),()=>s.delete(o)},_getVersion:o=>r.get(o)??0,addAccessRule:(o,c)=>Re(p,o,c),hasPermission:(o,c,f)=>{if(p.size===0)return!0;for(let[y,P]of p){let b;if(typeof y=="function")b=y(o,f);else try{let k=D.get(y);k||(k=new RegExp(y),D.set(y,k)),b=k.test(o)}catch{continue}if(b)return P.includes(c)||P.includes("admin")}return!1},recordConsent:(o,c,f)=>Ie(S,o,c,f),hasConsent:(o,c)=>rt(S,o,c),getConsents:o=>ot(S,o),revokeConsent:(o,c)=>nt(S,o,c),exportUserData:o=>st(S,o),deleteUserData:o=>it(S,o),get plugins(){return ee},get isReady(){return Ee},whenReady:()=>Bt};["addAccessRule","recordConsent","hasConsent","getConsents","revokeConsent","exportUserData","deleteUserData"].forEach(o=>{let c=U[o];c&&U._registerMethod("security",o,c)});let vt=()=>{M.size>0&&bt()};return typeof window<"u"&&window.addEventListener("beforeunload",vt),A?(async()=>{try{let c={},f=_e(),y=0;for(let b=0;b<(A.length||0);b++){let k=A.key(b);if(!k||!k.startsWith(f))continue;let B=A.getItem(k);if(B)try{let O=JSON.parse(B),Q=k.substring(f.length);if(y=Math.max(y,O._sys_v!==void 0?O._sys_v:O.v||0),O.e&&Date.now()>O.e){A.removeItem(k),b--;continue}let V=O.d;if(O._enc&&w)V=await Ye(V,w);else if(typeof V=="string"){if(O._b64)try{V=JSON.parse(atob(V))}catch{}else if(V.startsWith("{")||V.startsWith("["))try{V=JSON.parse(V)}catch{}}c[Q]=V,q("hydrate",Q,!0)}catch(O){q("hydrate",k,!1,String(O));let Q=O instanceof Error?O:new Error(String(O));i?i(Q,{operation:"hydration",key:k}):m||console.error(`[gState] Hydration failed for "${k}":`,O)}}let P=y<I&&e?.migrate?e.migrate(c,y):c;Object.entries(P).forEach(([b,k])=>{let B=J&&k!==null&&typeof k=="object"?Ce(Je(k),!0):k,O=Xe(B),Q=n.get(b)||0;G=G-Q+O,n.set(b,O),t.set(b,B),r.set(b,1)}),Ee=!0,Me(),le()}catch(c){Ee=!0,Me();let f=c instanceof Error?c:new Error(String(c));i?i(f,{operation:"hydration"}):m||console.error("[gState] Hydration failed:",f)}})():(Ee=!0,Me()),U};var Vr=(e,t)=>qe({...t,storage:e}),Ur=e=>qe({...e,storage:He.memory()}),$r=e=>{let t=He.session();return t?qe({...e,storage:t}):null};export{at as Security,He as StorageAdapters,Ur as createMemoryStore,$r as createSessionStore,qe as createStore,Vr as createStoreWithStorage};
1
+ var It=Object.defineProperty;var zt=(e,t)=>{for(var r in t)It(e,r,{get:t[r],enumerable:!0})};var mt=Symbol.for("immer-nothing"),ut=Symbol.for("immer-draftable"),b=Symbol.for("immer-state");function v(e,...t){throw new Error(`[Immer] minified error nr: ${e}. Full error at: https://bit.ly/3cXEKWf`)}var M=Object,W=M.getPrototypeOf,de="constructor",me="prototype",Ne="configurable",pe="enumerable",le="writable",q="value",z=e=>!!e&&!!e[b];function D(e){return e?St(e)||we(e)||!!e[ut]||!!e[de]?.[ut]||be(e)||Ee(e):!1}var Tt=M[me][de].toString(),lt=new WeakMap;function St(e){if(!e||!Ge(e))return!1;let t=W(e);if(t===null||t===M[me])return!0;let r=M.hasOwnProperty.call(t,de)&&t[de];if(r===Object)return!0;if(!L(r))return!1;let n=lt.get(r);return n===void 0&&(n=Function.toString.call(r),lt.set(r,n)),n===Tt}function Se(e,t,r=!0){Y(e)===0?(r?Reflect.ownKeys(e):M.keys(e)).forEach(s=>{t(s,e[s],e)}):e.forEach((n,s)=>t(s,n,e))}function Y(e){let t=e[b];return t?t.type_:we(e)?1:be(e)?2:Ee(e)?3:0}var ft=(e,t,r=Y(e))=>r===2?e.has(t):M[me].hasOwnProperty.call(e,t),Fe=(e,t,r=Y(e))=>r===2?e.get(t):e[t],_e=(e,t,r,n=Y(e))=>{n===2?e.set(t,r):n===3?e.add(r):e[t]=r};function Vt(e,t){return e===t?e!==0||1/e===1/t:e!==e&&t!==t}var we=Array.isArray,be=e=>e instanceof Map,Ee=e=>e instanceof Set,Ge=e=>typeof e=="object",L=e=>typeof e=="function",Te=e=>typeof e=="boolean";function Nt(e){let t=+e;return Number.isInteger(t)&&String(t)===e}var k=e=>e.copy_||e.base_;var He=e=>e.modified_?e.copy_:e.base_;function Ue(e,t){if(be(e))return new Map(e);if(Ee(e))return new Set(e);if(we(e))return Array[me].slice.call(e);let r=St(e);if(t===!0||t==="class_only"&&!r){let n=M.getOwnPropertyDescriptors(e);delete n[b];let s=Reflect.ownKeys(n);for(let a=0;a<s.length;a++){let f=s[a],_=n[f];_[le]===!1&&(_[le]=!0,_[Ne]=!0),(_.get||_.set)&&(n[f]={[Ne]:!0,[le]:!0,[pe]:_[pe],[q]:e[f]})}return M.create(W(e),n)}else{let n=W(e);if(n!==null&&r)return{...e};let s=M.create(n);return M.assign(s,e)}}function T(e,t=!1){return Ce(e)||z(e)||!D(e)||(Y(e)>1&&M.defineProperties(e,{set:ue,add:ue,clear:ue,delete:ue}),M.freeze(e),t&&Se(e,(r,n)=>{T(n,!0)},!1)),e}function Ft(){v(2)}var ue={[q]:Ft};function Ce(e){return e===null||!Ge(e)?!0:M.isFrozen(e)}var ge="MapSet",je="Patches",dt="ArrayMethods",wt={};function j(e){let t=wt[e];return t||v(0,e),t}var pt=e=>!!wt[e];var Q,bt=()=>Q,Ut=(e,t)=>({drafts_:[],parent_:e,immer_:t,canAutoFreeze_:!0,unfinalizedDrafts_:0,handledSet_:new Set,processedForPatches_:new Set,mapSetPlugin_:pt(ge)?j(ge):void 0,arrayMethodsPlugin_:pt(dt)?j(dt):void 0});function _t(e,t){t&&(e.patchPlugin_=j(je),e.patches_=[],e.inversePatches_=[],e.patchListener_=t)}function $e(e){Le(e),e.drafts_.forEach(jt),e.drafts_=null}function Le(e){e===Q&&(Q=e.parent_)}var gt=e=>Q=Ut(Q,e);function jt(e){let t=e[b];t.type_===0||t.type_===1?t.revoke_():t.revoked_=!0}function ht(e,t){t.unfinalizedDrafts_=t.drafts_.length;let r=t.drafts_[0];if(e!==void 0&&e!==r){r[b].modified_&&($e(t),v(4)),D(e)&&(e=yt(t,e));let{patchPlugin_:s}=t;s&&s.generateReplacementPatches_(r[b].base_,e,t)}else e=yt(t,r);return $t(t,e,!0),$e(t),t.patches_&&t.patchListener_(t.patches_,t.inversePatches_),e!==mt?e:void 0}function yt(e,t){if(Ce(t))return t;let r=t[b];if(!r)return he(t,e.handledSet_,e);if(!Pe(r,e))return t;if(!r.modified_)return r.base_;if(!r.finalized_){let{callbacks_:n}=r;if(n)for(;n.length>0;)n.pop()(e);Pt(r,e)}return r.copy_}function $t(e,t,r=!1){!e.parent_&&e.immer_.autoFreeze_&&e.canAutoFreeze_&&T(t,r)}function Et(e){e.finalized_=!0,e.scope_.unfinalizedDrafts_--}var Pe=(e,t)=>e.scope_===t,Lt=[];function Ct(e,t,r,n){let s=k(e),a=e.type_;if(n!==void 0&&Fe(s,n,a)===t){_e(s,n,r,a);return}if(!e.draftLocations_){let _=e.draftLocations_=new Map;Se(s,(y,S)=>{if(z(S)){let x=_.get(S)||[];x.push(y),_.set(S,x)}})}let f=e.draftLocations_.get(t)??Lt;for(let _ of f)_e(s,_,r,a)}function Wt(e,t,r){e.callbacks_.push(function(s){let a=t;if(!a||!Pe(a,s))return;s.mapSetPlugin_?.fixSetContents(a);let f=He(a);Ct(e,a.draft_??a,f,r),Pt(a,s)})}function Pt(e,t){if(e.modified_&&!e.finalized_&&(e.type_===3||e.type_===1&&e.allIndicesReassigned_||(e.assigned_?.size??0)>0)){let{patchPlugin_:n}=t;if(n){let s=n.getPath(e);s&&n.generatePatches_(e,s,t)}Et(e)}}function Bt(e,t,r){let{scope_:n}=e;if(z(r)){let s=r[b];Pe(s,n)&&s.callbacks_.push(function(){fe(e);let f=He(s);Ct(e,r,f,t)})}else D(r)&&e.callbacks_.push(function(){let a=k(e);e.type_===3?a.has(r)&&he(r,n.handledSet_,n):Fe(a,t,e.type_)===r&&n.drafts_.length>1&&(e.assigned_.get(t)??!1)===!0&&e.copy_&&he(Fe(e.copy_,t,e.type_),n.handledSet_,n)})}function he(e,t,r){return!r.immer_.autoFreeze_&&r.unfinalizedDrafts_<1||z(e)||t.has(e)||!D(e)||Ce(e)||(t.add(e),Se(e,(n,s)=>{if(z(s)){let a=s[b];if(Pe(a,r)){let f=He(a);_e(e,n,f,e.type_),Et(a)}}else D(s)&&he(s,t,r)})),e}function Gt(e,t){let r=we(e),n={type_:r?1:0,scope_:t?t.scope_:bt(),modified_:!1,finalized_:!1,assigned_:void 0,parent_:t,base_:e,draft_:null,copy_:null,revoke_:null,isManual_:!1,callbacks_:void 0},s=n,a=ye;r&&(s=[n],a=X);let{revoke:f,proxy:_}=Proxy.revocable(s,a);return n.draft_=_,n.revoke_=f,[_,n]}var ye={get(e,t){if(t===b)return e;let r=e.scope_.arrayMethodsPlugin_,n=e.type_===1&&typeof t=="string";if(n&&r?.isArrayOperationMethod(t))return r.createMethodInterceptor(e,t);let s=k(e);if(!ft(s,t,e.type_))return Ht(e,s,t);let a=s[t];if(e.finalized_||!D(a)||n&&e.operationMethod&&r?.isMutatingArrayMethod(e.operationMethod)&&Nt(t))return a;if(a===Ve(e.base_,t)){fe(e);let f=e.type_===1?+t:t,_=Be(e.scope_,a,e,f);return e.copy_[f]=_}return a},has(e,t){return t in k(e)},ownKeys(e){return Reflect.ownKeys(k(e))},set(e,t,r){let n=Mt(k(e),t);if(n?.set)return n.set.call(e.draft_,r),!0;if(!e.modified_){let s=Ve(k(e),t),a=s?.[b];if(a&&a.base_===r)return e.copy_[t]=r,e.assigned_.set(t,!1),!0;if(Vt(r,s)&&(r!==void 0||ft(e.base_,t,e.type_)))return!0;fe(e),We(e)}return e.copy_[t]===r&&(r!==void 0||t in e.copy_)||Number.isNaN(r)&&Number.isNaN(e.copy_[t])||(e.copy_[t]=r,e.assigned_.set(t,!0),Bt(e,t,r)),!0},deleteProperty(e,t){return fe(e),Ve(e.base_,t)!==void 0||t in e.base_?(e.assigned_.set(t,!1),We(e)):e.assigned_.delete(t),e.copy_&&delete e.copy_[t],!0},getOwnPropertyDescriptor(e,t){let r=k(e),n=Reflect.getOwnPropertyDescriptor(r,t);return n&&{[le]:!0,[Ne]:e.type_!==1||t!=="length",[pe]:n[pe],[q]:r[t]}},defineProperty(){v(11)},getPrototypeOf(e){return W(e.base_)},setPrototypeOf(){v(12)}},X={};for(let e in ye){let t=ye[e];X[e]=function(){let r=arguments;return r[0]=r[0][0],t.apply(this,r)}}X.deleteProperty=function(e,t){return X.set.call(this,e,t,void 0)};X.set=function(e,t,r){return ye.set.call(this,e[0],t,r,e[0])};function Ve(e,t){let r=e[b];return(r?k(r):e)[t]}function Ht(e,t,r){let n=Mt(t,r);return n?q in n?n[q]:n.get?.call(e.draft_):void 0}function Mt(e,t){if(!(t in e))return;let r=W(e);for(;r;){let n=Object.getOwnPropertyDescriptor(r,t);if(n)return n;r=W(r)}}function We(e){e.modified_||(e.modified_=!0,e.parent_&&We(e.parent_))}function fe(e){e.copy_||(e.assigned_=new Map,e.copy_=Ue(e.base_,e.scope_.immer_.useStrictShallowCopy_))}var Jt=class{constructor(e){this.autoFreeze_=!0,this.useStrictShallowCopy_=!1,this.useStrictIteration_=!1,this.produce=(t,r,n)=>{if(L(t)&&!L(r)){let a=r;r=t;let f=this;return function(y=a,...S){return f.produce(y,x=>r.call(this,x,...S))}}L(r)||v(6),n!==void 0&&!L(n)&&v(7);let s;if(D(t)){let a=gt(this),f=Be(a,t,void 0),_=!0;try{s=r(f),_=!1}finally{_?$e(a):Le(a)}return _t(a,n),ht(s,a)}else if(!t||!Ge(t)){if(s=r(t),s===void 0&&(s=t),s===mt&&(s=void 0),this.autoFreeze_&&T(s,!0),n){let a=[],f=[];j(je).generateReplacementPatches_(t,s,{patches_:a,inversePatches_:f}),n(a,f)}return s}else v(1,t)},this.produceWithPatches=(t,r)=>{if(L(t))return(f,..._)=>this.produceWithPatches(f,y=>t(y,..._));let n,s;return[this.produce(t,r,(f,_)=>{n=f,s=_}),n,s]},Te(e?.autoFreeze)&&this.setAutoFreeze(e.autoFreeze),Te(e?.useStrictShallowCopy)&&this.setUseStrictShallowCopy(e.useStrictShallowCopy),Te(e?.useStrictIteration)&&this.setUseStrictIteration(e.useStrictIteration)}createDraft(e){D(e)||v(8),z(e)&&(e=Kt(e));let t=gt(this),r=Be(t,e,void 0);return r[b].isManual_=!0,Le(t),r}finishDraft(e,t){let r=e&&e[b];(!r||!r.isManual_)&&v(9);let{scope_:n}=r;return _t(n,t),ht(void 0,n)}setAutoFreeze(e){this.autoFreeze_=e}setUseStrictShallowCopy(e){this.useStrictShallowCopy_=e}setUseStrictIteration(e){this.useStrictIteration_=e}shouldUseStrictIteration(){return this.useStrictIteration_}applyPatches(e,t){let r;for(r=t.length-1;r>=0;r--){let s=t[r];if(s.path.length===0&&s.op==="replace"){e=s.value;break}}r>-1&&(t=t.slice(r+1));let n=j(je).applyPatches_;return z(e)?n(e,t):this.produce(e,s=>n(s,t))}};function Be(e,t,r,n){let[s,a]=be(t)?j(ge).proxyMap_(t,r):Ee(t)?j(ge).proxySet_(t,r):Gt(t,r);return(r?.scope_??bt()).drafts_.push(s),a.callbacks_=r?.callbacks_??[],a.key_=n,r&&n!==void 0?Wt(r,a,n):a.callbacks_.push(function(y){y.mapSetPlugin_?.fixSetContents(a);let{patchPlugin_:S}=y;a.modified_&&S&&S.generatePatches_(a,[],y)}),s}function Kt(e){return z(e)||v(10,e),At(e)}function At(e){if(!D(e)||Ce(e))return e;let t=e[b],r,n=!0;if(t){if(!t.modified_)return t.base_;t.finalized_=!0,r=Ue(e,t.scope_.immer_.useStrictShallowCopy_),n=t.scope_.immer_.shouldUseStrictIteration()}else r=Ue(e,!0);return Se(r,(s,a)=>{_e(r,s,At(a))},n),t&&(t.finalized_=!1),r}var qt=new Jt,vt=qt.produce;var rt={};zt(rt,{addAccessRule:()=>Ae,decrypt:()=>Ke,deleteUserData:()=>tt,encrypt:()=>Je,exportKey:()=>Xt,exportUserData:()=>et,generateEncryptionKey:()=>Qt,getConsents:()=>Ze,hasConsent:()=>Xe,hasPermission:()=>te,importKey:()=>Yt,isAuditActive:()=>qe,isCryptoAvailable:()=>xt,logAudit:()=>ee,recordConsent:()=>ve,revokeConsent:()=>Ye,sanitizeValue:()=>Z,setAuditLogger:()=>Zt,validateKey:()=>Qe});var xt=typeof crypto<"u"&&typeof crypto.subtle<"u"&&typeof crypto.subtle.generateKey=="function",Qt=async()=>{if(!xt)throw new Error("Web Crypto API not available");let e=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),t=crypto.getRandomValues(new Uint8Array(12));return{key:e,iv:t}},Xt=async e=>{let t=await crypto.subtle.exportKey("raw",e.key);return{key:btoa(String.fromCharCode(...new Uint8Array(t))),iv:btoa(String.fromCharCode(...e.iv))}},Yt=async(e,t)=>{let r=Uint8Array.from(atob(e),a=>a.charCodeAt(0)),n=Uint8Array.from(atob(t),a=>a.charCodeAt(0));return{key:await crypto.subtle.importKey("raw",r,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),iv:n}},Je=async(e,t)=>{let r=new TextEncoder,n=r.encode(JSON.stringify(e)),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:t.iv},t.key,n),a=new Uint8Array(t.iv.length+s.byteLength);return a.set(t.iv),a.set(new Uint8Array(s),t.iv.length),btoa(String.fromCharCode(...a))},Ke=async(e,t)=>{let r=Uint8Array.from(atob(e),f=>f.charCodeAt(0)),n=r.slice(0,12),s=r.slice(12),a=await crypto.subtle.decrypt({name:"AES-GCM",iv:n},t.key,s);return JSON.parse(new TextDecoder().decode(a))},Me=null,Zt=e=>{Me=e},qe=()=>Me!==null,ee=e=>{Me&&Me(e)},Ae=(e,t,r)=>{e.set(t instanceof RegExp?t.source:t,r)},te=(e,t,r,n)=>{if(e.size===0)return!0;for(let[s,a]of e){let f;if(typeof s=="function")f=s(t,n);else try{f=new RegExp(s).test(t)}catch{continue}if(f)return a.includes(r)||a.includes("admin")}return!1},Z=e=>{if(typeof e=="string")return e.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"[SEC-REMOVED]").replace(/javascript:/gi,"[SEC-REMOVED]").replace(/data:text\/html/gi,"[SEC-REMOVED]").replace(/vbscript:/gi,"[SEC-REMOVED]").replace(/on\w+\s*=/gi,"[SEC-REMOVED]=").replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi,"[SEC-REMOVED]").replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi,"[SEC-REMOVED]").replace(/<embed\b[^<]*(?:(?!<\/embed>)<[^<]*)*<\/embed>/gi,"[SEC-REMOVED]").replace(/<svg\b[^<]*(?:(?!<\/svg>)<[^<]*)*<\/svg>/gi,"[SEC-REMOVED]").replace(/<form\b[^<]*(?:(?!<\/form>)<[^<]*)*<\/form>/gi,"[SEC-REMOVED]").replace(/<base\b[^<]*(?:(?!<\/base>)<[^<]*)*<\/base>/gi,"[SEC-REMOVED]").replace(/<link\b[^<]*(?:(?!<\/link>)<[^<]*)*<\/link>/gi,"[SEC-REMOVED]").replace(/<meta\b[^<]*(?:(?!<\/meta>)<[^<]*)*<\/meta>/gi,"[SEC-REMOVED]").replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi,"[SEC-REMOVED]").replace(/&#[xX]?[0-9a-fA-F]+;?/g,"");if(e&&typeof e=="object"&&!Array.isArray(e)){if(Object.getPrototypeOf(e)===Object.prototype){let t={};for(let[r,n]of Object.entries(e))t[r]=Z(n);return t}return e}return Array.isArray(e)?e.map(t=>Z(t)):e},Qe=e=>/^[a-zA-Z0-9_.-]+$/.test(e)&&e.length<=256,ve=(e,t,r,n)=>{let s={id:crypto.randomUUID(),purpose:r,granted:n,timestamp:Date.now()},a=e.get(t)||[];return a.push(s),e.set(t,a),ee({timestamp:Date.now(),action:"set",key:`consent:${r}`,userId:t,success:!0}),s},Xe=(e,t,r)=>{let n=e.get(t);if(!n)return!1;for(let s=n.length-1;s>=0;s--){let a=n[s];if(a&&a.purpose===r)return a.granted}return!1},Ye=(e,t,r)=>ve(e,t,r,!1),Ze=(e,t)=>e.get(t)||[],et=(e,t)=>({userId:t,exportedAt:Date.now(),consents:e.get(t)||[]}),tt=(e,t)=>{let r=e.get(t)?.length||0;return e.delete(t),{success:!0,deletedConsents:r}};var ne=e=>{if(e===null||typeof e!="object")return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch{}let t=new WeakMap,r=n=>{if(n===null||typeof n!="object"||typeof n=="function")return n;if(t.has(n))return t.get(n);if(n instanceof Date)return new Date(n.getTime());if(n instanceof RegExp)return new RegExp(n.source,n.flags);if(n instanceof Map){let f=new Map;return t.set(n,f),n.forEach((_,y)=>f.set(r(y),r(_))),f}if(n instanceof Set){let f=new Set;return t.set(n,f),n.forEach(_=>f.add(r(_))),f}let s=Array.isArray(n)?[]:Object.create(Object.getPrototypeOf(n));t.set(n,s);let a=[...Object.keys(n),...Object.getOwnPropertySymbols(n)];for(let f of a)s[f]=r(n[f]);return s};return r(e)},re=(e,t)=>{if(e===t)return!0;if(e===null||t===null||typeof e!="object"||typeof t!="object")return e===t;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let s=0;s<e.length;s++)if(!re(e[s],t[s]))return!1;return!0}let r=Object.keys(e),n=Object.keys(t);if(r.length!==n.length)return!1;for(let s=0;s<r.length;s++){let a=r[s];if(!(a in t)||!re(e[a],t[a]))return!1}return!0};var xe={local:()=>typeof window<"u"?window.localStorage:null,session:()=>typeof window<"u"?window.sessionStorage:null,memory:()=>{let e=new Map;return{getItem:t=>e.get(t)||null,setItem:(t,r)=>e.set(t,r),removeItem:t=>e.delete(t),key:t=>Array.from(e.keys())[t]||null,get length(){return e.size}}}},Oe=e=>{let t=new Map,r=new Map,n=new Map,s=new Set,a=new Map,f=new Set,_=new Map,y=new Map,S=new Map,x=new Map,B=new Map,Re=new Map,I=new Map,V=new Map,nt=e?.namespace||"gstate",E=e?.silent??!1,Ot=e?.debounceTime??150,ke=e?.version??0,C=e?.storage||xe.local(),g=e?.onError,oe=e?.maxObjectSize??5*1024*1024,se=e?.maxTotalSize??50*1024*1024,ie=e?.encryptionKey??null,ot=e?.validateInput??!0,Rt=e?.auditEnabled??!0,G=e?.userId,H=e?.immer??!0,kt=e?.persistByDefault??e?.persistence??e?.persist??!1;e?.accessRules&&e.accessRules.forEach(o=>Ae(I,o.pattern,o.permissions));let De=!1,Ie=!1,ae=!1,O=0,$=null,ce,Dt=new Promise(o=>{ce=o}),ze=o=>{if(o==null)return 0;let i=typeof o;if(i==="boolean")return 4;if(i==="number")return 8;if(i==="string")return o.length*2;if(i!=="object")return 0;let c=0,l=[o],p=new WeakSet;for(;l.length>0;){let u=l.pop();if(typeof u=="boolean")c+=4;else if(typeof u=="number")c+=8;else if(typeof u=="string")c+=u.length*2;else if(typeof u=="object"&&u!==null){let d=u;if(p.has(d))continue;if(p.add(d),Array.isArray(d))for(let h=0;h<d.length;h++)l.push(d[h]);else for(let h of Object.keys(d))c+=h.length*2,l.push(d[h])}}return c},J=()=>`${nt}_`,N=(o,i)=>{if(x.size!==0)for(let c of x.values()){let l=c.hooks?.[o];if(l)try{l(i)}catch(p){let u=p instanceof Error?p:new Error(String(p));g?g(u,{operation:`plugin:${c.name}:${o}`,key:i.key}):E||console.error(`[gState] Plugin "${c.name}" error:`,p)}}},R=(o,i,c,l)=>{Rt&&qe()&&ee&&ee({timestamp:Date.now(),action:o,key:i,userId:G,success:c,error:l})},K=o=>{if(o){let i=S.get(o);if(i)for(let p of i)st(p);let c=_.get(o);if(c){let p=w.get(o);for(let u of c)try{u(p)}catch(d){let h=d instanceof Error?d:new Error(String(d));g?g(h,{operation:"watcher",key:o}):E||console.error(`[gState] Watcher error for "${o}":`,d)}}let l=a.get(o);if(l)for(let p of l)try{p()}catch(u){let d=u instanceof Error?u:new Error(String(u));g?g(d,{operation:"keyListener",key:o}):E||console.error(`[gState] Listener error for "${o}":`,u)}}if(De){Ie=!0;return}for(let i of s)try{i()}catch(c){let l=c instanceof Error?c:new Error(String(c));g?g(l,{operation:"listener"}):E||console.error("[gState] Global listener error: ",c)}},st=o=>{let i=y.get(o),c=new Set;if(!i)return;let l=u=>(c.add(u),y.has(u)?y.get(u).lastValue:w.get(u)),p=i.selector(l);i.deps.forEach(u=>{if(!c.has(u)){let d=S.get(u);d&&(d.delete(o),d.size===0&&S.delete(u))}}),c.forEach(u=>{i.deps.has(u)||(S.has(u)||S.set(u,new Set),S.get(u).add(o))}),i.deps=c,re(i.lastValue,p)||(i.lastValue=H&&p!==null&&typeof p=="object"?T(ne(p),!0):p,r.set(o,(r.get(o)||0)+1),K(o))},it=async()=>{if(!C)return;try{let i={};t.forEach((p,u)=>{i[u]=p});let c,l=e?.encoded;l?c=btoa(JSON.stringify(i)):c=JSON.stringify(i),C.setItem(J().replace("_",""),JSON.stringify({v:1,t:Date.now(),e:null,d:c,_sys_v:ke,_b64:l?!0:void 0})),R("set","FULL_STATE",!0)}catch(i){let c=i instanceof Error?i:new Error(String(i));g?g(c,{operation:"persist",key:"FULL_STATE"}):E||console.error("[gState] Persist failed: ",c)}let o=Array.from(B.entries());B.clear();for(let[i,c]of o)try{let l=c.value,p=c.options.encoded||c.options.secure;if(c.options.encrypted){if(!ie)throw new Error(`Encryption key missing for "${i}"`);l=await Je(c.value,ie)}else p?l=btoa(JSON.stringify(c.value)):typeof c.value=="object"&&c.value!==null&&(l=JSON.stringify(c.value));C.setItem(`${J()}${i} `,JSON.stringify({v:r.get(i)||1,t:Date.now(),e:c.options.ttl?Date.now()+c.options.ttl:null,d:l,_sys_v:ke,_enc:c.options.encrypted?!0:void 0,_b64:p?!0:void 0})),R("set",i,!0)}catch(l){let p=l instanceof Error?l:new Error(String(l));g?g(p,{operation:"persist",key:i}):E||console.error("[gState] Persist failed: ",p)}},F={},w={_setSilently:(o,i)=>{let c=n.get(o)||0,l=H&&i!==null&&typeof i=="object"?T(ne(i),!0):i,p=ze(l);O=O-c+p,n.set(o,p),t.set(o,l),r.set(o,(r.get(o)||0)+1)},_registerMethod:(o,i,c)=>{if(c!==void 0){let u=o,d=i;F[u]||(F[u]={}),F[u][d]=c;return}console.warn("[gState] _registerMethod(name, fn) is deprecated. Use _registerMethod(pluginName, methodName, fn) instead.");let l=o,p=i;F.core||(F.core={}),F.core[l]=p},set:(o,i,c={})=>{let l=t.get(o),p=H&&typeof i=="function"?vt(l,i):i;if(ot&&!Qe(o))return E||console.warn(`[gState] Invalid key: ${o}`),!1;if(!te(I,o,"write",G))return R("set",o,!1,"RBAC Denied"),E||console.error(`[gState] RBAC Denied for "${o}"`),!1;let u=ot?Z(p):p,d=n.get(o)||0;N("onBeforeSet",{key:o,value:u,store:w,version:r.get(o)||0});let h=H&&u!==null&&typeof u=="object"?T(ne(u),!0):u;if(!re(l,h)){let A=oe>0||se>0?ze(h):0;if(oe>0&&A>oe){let U=new Error(`Object size (${A} bytes) exceeds maxObjectSize (${oe} bytes)`);g?g(U,{operation:"set",key:o}):E||console.warn(`[gState] ${U.message} for "${o}"`)}if(se>0){let U=O-d+A;if(U>se){let ct=new Error(`Total store size (${U} bytes) exceeds limit (${se} bytes)`);g?g(ct,{operation:"set"}):E||console.warn(`[gState] ${ct.message}`)}}O=O-d+A,n.set(o,A),t.set(o,h),r.set(o,(r.get(o)||0)+1);let P=c.persist??kt;return P&&(B.set(o,{value:h,options:{...c,persist:P,encoded:c.encoded||e?.encoded}}),$&&clearTimeout($),$=setTimeout(it,Ot)),N("onSet",{key:o,value:h,store:w,version:r.get(o)}),R("set",o,!0),K(o),!0}return!1},get:o=>{if(!te(I,o,"read",G))return R("get",o,!1,"RBAC Denied"),null;let i=t.get(o);return N("onGet",{store:w,key:o,value:i}),R("get",o,!0),i},compute:(o,i)=>{try{return y.has(o)||(y.set(o,{selector:i,lastValue:null,deps:new Set}),st(o)),y.get(o).lastValue}catch(c){let l=c instanceof Error?c:new Error(String(c));return g?g(l,{operation:"compute",key:o}):E||console.error(`[gState] Compute error for "${o}": `,c),null}},watch:(o,i)=>{_.has(o)||_.set(o,new Set);let c=_.get(o);return c.add(i),()=>{c.delete(i),c.size===0&&_.delete(o)}},remove:o=>{if(!te(I,o,"delete",G))return R("delete",o,!1,"RBAC Denied"),!1;let i=t.get(o),c=t.delete(o);return c&&(O-=n.get(o)||0,n.delete(o),N("onRemove",{store:w,key:o,value:i})),r.set(o,(r.get(o)||0)+1),C&&C.removeItem(`${J()}${o} `),R("delete",o,!0),K(o),c},delete:o=>w.remove(o),deleteAll:()=>{if(Array.from(t.keys()).forEach(o=>w.remove(o)),C){let o=J();for(let i=0;i<(C.length||0);i++){let c=C.key(i);c?.startsWith(o)&&(C.removeItem(c),i--)}}return O=0,n.clear(),!0},list:()=>Object.fromEntries(t.entries()),use:o=>{f.add(o)},transaction:o=>{De=!0,N("onTransaction",{store:w,key:"START"});try{o()}finally{De=!1,N("onTransaction",{store:w,key:"END"}),Ie&&(Ie=!1,K())}},destroy:()=>{$&&(clearTimeout($),$=null),B.clear(),typeof window<"u"&&window.removeEventListener("beforeunload",at),N("onDestroy",{store:w}),s.clear(),a.clear(),_.clear(),y.clear(),S.clear(),x.clear(),t.clear(),n.clear(),O=0,I.clear(),V.clear(),r.clear(),Re.clear(),f.clear()},_addPlugin:o=>{try{x.set(o.name,o),o.hooks?.onInstall?.({store:w})}catch(i){let c=i instanceof Error?i:new Error(String(i));g?g(c,{operation:"plugin:install",key:o.name}):E||console.error(`[gState] Failed to install plugin "${o.name}": `,i)}},_removePlugin:o=>{x.delete(o)},_subscribe:(o,i)=>{if(i){a.has(i)||a.set(i,new Set);let c=a.get(i);return c.add(o),()=>{c.delete(o),c.size===0&&a.delete(i)}}return s.add(o),()=>s.delete(o)},_getVersion:o=>r.get(o)??0,addAccessRule:(o,i)=>Ae(I,o,i),hasPermission:(o,i,c)=>{if(I.size===0)return!0;for(let[l,p]of I){let u;if(typeof l=="function")u=l(o,c);else try{let d=Re.get(l);d||(d=new RegExp(l),Re.set(l,d)),u=d.test(o)}catch{continue}if(u)return p.includes(i)||p.includes("admin")}return!1},recordConsent:(o,i,c)=>ve(V,o,i,c),hasConsent:(o,i)=>Xe(V,o,i),getConsents:o=>Ze(V,o),revokeConsent:(o,i)=>Ye(V,o,i),exportUserData:o=>et(V,o),deleteUserData:o=>tt(V,o),get plugins(){return F},get isReady(){return ae},get namespace(){return nt},get userId(){return G},whenReady:()=>Dt};["addAccessRule","recordConsent","hasConsent","getConsents","revokeConsent","exportUserData","deleteUserData"].forEach(o=>{let i=w[o];i&&w._registerMethod("security",o,i)});let at=()=>{B.size>0&&it()};return typeof window<"u"&&window.addEventListener("beforeunload",at),C?(async()=>{try{let i={},c=J(),l=0;for(let u=0;u<(C.length||0);u++){let d=C.key(u);if(!d||!d.startsWith(c))continue;let h=C.getItem(d);if(h)try{let m=JSON.parse(h),A=d.substring(c.length);if(l=Math.max(l,m._sys_v!==void 0?m._sys_v:m.v||0),m.e&&Date.now()>m.e){C.removeItem(d),u--;continue}let P=m.d;if(m._enc&&ie)P=await Ke(P,ie);else if(typeof P=="string"){if(m._b64)try{P=JSON.parse(atob(P))}catch{}else if(P.startsWith("{")||P.startsWith("["))try{P=JSON.parse(P)}catch{}}i[A]=P,R("hydrate",A,!0)}catch(m){R("hydrate",d,!1,String(m));let A=m instanceof Error?m:new Error(String(m));g?g(A,{operation:"hydration",key:d}):E||console.error(`[gState] Hydration failed for "${d}": `,m)}}let p=l<ke&&e?.migrate?e.migrate(i,l):i;Object.entries(p).forEach(([u,d])=>{let h=H&&d!==null&&typeof d=="object"?T(ne(d),!0):d,m=ze(h),A=n.get(u)||0;O=O-A+m,n.set(u,m),t.set(u,h),r.set(u,1)}),ae=!0,ce(),K()}catch(i){ae=!0,ce();let c=i instanceof Error?i:new Error(String(i));g?g(c,{operation:"hydration"}):E||console.error("[gState] Hydration failed: ",c)}})():(ae=!0,ce()),w};var ur=(e,t)=>Oe({...t,storage:e}),lr=e=>Oe({...e,storage:xe.memory()}),fr=e=>{let t=xe.session();return t?Oe({...e,storage:t}):null};export{rt as Security,xe as StorageAdapters,lr as createMemoryStore,fr as createSessionStore,Oe as createStore,ur as createStoreWithStorage};
package/core/types.d.ts CHANGED
@@ -73,6 +73,8 @@ export interface IStore<S extends Record<string, unknown> = Record<string, unkno
73
73
  deletedConsents: number;
74
74
  };
75
75
  readonly isReady: boolean;
76
+ readonly namespace: string;
77
+ readonly userId?: string;
76
78
  whenReady(): Promise<void>;
77
79
  readonly plugins: GStatePlugins;
78
80
  }
@@ -93,7 +95,24 @@ export interface GStatePlugins {
93
95
  deletedConsents: number;
94
96
  };
95
97
  };
96
- [key: string]: Record<string, (...args: any[]) => any>;
98
+ undoRedo: {
99
+ undo: () => boolean;
100
+ redo: () => boolean;
101
+ canUndo: () => boolean;
102
+ canRedo: () => boolean;
103
+ };
104
+ immer: {
105
+ setWithProduce: <T>(key: string, updater: (draft: T) => void) => boolean;
106
+ };
107
+ cloudSync: {
108
+ sync: () => Promise<{
109
+ status: string;
110
+ stats: import('../plugins/official/cloud-sync.plugin').SyncStats;
111
+ }>;
112
+ getStats: () => import('../plugins/official/cloud-sync.plugin').SyncStats;
113
+ };
114
+ logger: Record<string, never>;
115
+ [key: string]: unknown;
97
116
  }
98
117
  export interface StoreConfig<S extends Record<string, unknown> = Record<string, unknown>> {
99
118
  namespace?: string;
@@ -104,6 +123,7 @@ export interface StoreConfig<S extends Record<string, unknown> = Record<string,
104
123
  migrate?: (oldState: Record<string, unknown>, oldVersion: number) => S;
105
124
  persistByDefault?: boolean;
106
125
  persistence?: boolean;
126
+ persist?: boolean;
107
127
  onError?: (error: Error, context: {
108
128
  operation: string;
109
129
  key?: string;
@@ -114,6 +134,7 @@ export interface StoreConfig<S extends Record<string, unknown> = Record<string,
114
134
  auditEnabled?: boolean;
115
135
  userId?: string;
116
136
  validateInput?: boolean;
137
+ encoded?: boolean;
117
138
  accessRules?: Array<{
118
139
  pattern: string | ((key: string, userId?: string) => boolean);
119
140
  permissions: Permission[];
@@ -0,0 +1,2 @@
1
+ export declare const deepClone: <T>(obj: T) => T;
2
+ export declare const isEqual: (a: unknown, b: unknown) => boolean;
@@ -0,0 +1,41 @@
1
+ # 🌌 RGS Examples & Best Practices
2
+
3
+ This folder contains functional and reusable examples of **React Globo State (RGS)** implementation.
4
+
5
+ ## 🏁 Overview: FE vs BE Recommendations
6
+
7
+ | Example | Recommendation | Primary Use Case |
8
+ | :--- | :--- | :--- |
9
+ | **[Basic Counter](./basic-counter)** | **FE Only** | Local component state, UI toggles. |
10
+ | **[Global Theme](./global-theme)** | **FE Only** | Dark mode, Layout settings, Persistence. |
11
+ | **[Persistent Cart](./persistent-cart)** | **FE Preferred** | Shopping carts, Drafts, Offline-first apps. |
12
+ | **[Secure Auth](./secure-auth)** | **FE / BE** | Session management, Tokens, User metadata. |
13
+ | **[Undo/Redo Editor](./undo-redo-editor)** | **FE Only** | Rich text editors, Canvas tools, Form history. |
14
+ | **[RBAC Dashboard](./rbac-dashboard)** | **BE / Admin FE** | Permission-based UI, Secure Admin panels. |
15
+ | **[Async Data Fetch](./async-data-fetch)** | **FE Only** | API integration, Data hydration. |
16
+ | **[Security Practices](./security-best-practices)** | **BE / Core FE** | Encryption, Audit logs, GDPR compliance. |
17
+ | **[Big Data (IndexedDB)](./big-data-indexeddb)** | **FE Specific** | High-volume storage (GBs), Large payloads. |
18
+ | **[Stress Tests](./stress-tests)** | **Validation** | Performance benchmarking & profiling. |
19
+
20
+ ---
21
+
22
+ ## 🛡️ Security Guidelines
23
+
24
+ ### 1. Sensitive Data Handling
25
+ **CRITICAL:** Never hardcode actual sensitive data (Credit Cards, Passwords, API Keys) in your JavaScript/TypeScript files.
26
+ - **Frontend:** Collect from secure `<input type="password">` and pass to RGS at runtime.
27
+ - **Backend:** Retrieve from environment variables (`process.env`) or Secret Managers.
28
+
29
+ ### 2. Encryption
30
+ For PII (Personally Identifiable Information), always use the `encryptionKey` option in `StoreConfig`.
31
+ RGS will use the Web Crypto API (or Node Crypto) to perform **AES-256-GCM** encryption before writing to storage.
32
+
33
+ ### 3. XSS Defense
34
+ Enable `validateInput: true` in your store configuration to automatically sanitize strings. This is vital for any user-generated content displayed in the DOM.
35
+
36
+ ### 4. High-Volume Storage (IndexedDB)
37
+ If your application needs to store more than 10MB (the typical localStorage limit), use the **IndexedDB Plugin**. It allows storing Gigabytes of data asynchronously without blocking the main UI thread.
38
+
39
+ ## 🛠️ Testing Environment
40
+ All examples are validated using Jest in a `jsdom` environment.
41
+ Refer to `tests/jest/tests/examples_v.test.ts` for automated verify suites.
@@ -0,0 +1,12 @@
1
+ interface User {
2
+ id: number;
3
+ name: string;
4
+ email: string;
5
+ }
6
+ export declare const fetchUser: (args: {
7
+ id: string;
8
+ }) => Promise<User>;
9
+ export declare const useUser: import("../../advanced").IStore<Record<string, import("../../core/types").AsyncState<User>>> & {
10
+ execute: () => Promise<void>;
11
+ };
12
+ export {};
@@ -0,0 +1,30 @@
1
+ import { createAsyncStore } from '../../index'
2
+
3
+ /**
4
+ * Async Data Loader Utility
5
+ * RECOMMENDED FOR: Frontend (FE)
6
+ */
7
+
8
+ interface User {
9
+ id: number
10
+ name: string
11
+ email: string
12
+ }
13
+
14
+ export const fetchUser = async (args: { id: string }) => {
15
+ const response = await fetch(`https://jsonplaceholder.typicode.com/users/${args.id}`)
16
+ if (!response.ok) throw new Error('User not found')
17
+ return response.json() as Promise<User>
18
+ }
19
+
20
+ // Basic Async Store for a specific user (Example)
21
+ export const useUser = createAsyncStore<User>(() => fetchUser({ id: '1' }), {
22
+ key: 'userData'
23
+ })
24
+
25
+ /**
26
+ * Usage in component:
27
+ *
28
+ * const [state, actions] = useUser()
29
+ * useEffect(() => { actions.execute({ id: '1' }) }, [])
30
+ */
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const CounterComponent: React.FC;
@@ -0,0 +1,22 @@
1
+ import React from 'react'
2
+ import { useCounter, increment, decrement } from './CounterStore'
3
+
4
+ /**
5
+ * Counter Component
6
+ * Demonstrates the "Magnetar" pattern where the store IS the hook.
7
+ */
8
+ export const CounterComponent: React.FC = () => {
9
+ // Subscribe to specific keys for fine-grained re-renders
10
+ const [count] = useCounter('count')
11
+ const [lastUpdated] = useCounter('lastUpdated')
12
+
13
+ return (
14
+ <div style={{ padding: '20px', border: '1px solid #ccc' }}>
15
+ <h2>Counter: {String(count)}</h2>
16
+ <p><small>Last updated: {String(lastUpdated)}</small></p>
17
+ <button onClick={increment}>+</button>
18
+ <button onClick={decrement}>-</button>
19
+ <button onClick={() => useCounter.set('count', 0)}>Reset</button>
20
+ </div>
21
+ )
22
+ }
@@ -0,0 +1,7 @@
1
+ export interface CounterState extends Record<string, unknown> {
2
+ count: number;
3
+ lastUpdated: string;
4
+ }
5
+ export declare const useCounter: import("../../advanced").IStore<CounterState> & (<K extends keyof CounterState>(key: K) => readonly [CounterState[K] | undefined, (val: CounterState[K] | ((draft: CounterState[K]) => CounterState[K]), options?: unknown) => boolean]);
6
+ export declare const increment: () => void;
7
+ export declare const decrement: () => void;
@@ -0,0 +1,25 @@
1
+ import { gstate } from '../../index'
2
+
3
+ export interface CounterState extends Record<string, unknown> {
4
+ count: number
5
+ lastUpdated: string
6
+ }
7
+
8
+ /**
9
+ * Basic Counter Store
10
+ * RECOMMENDED FOR: Frontend (FE)
11
+ */
12
+ export const useCounter = gstate<CounterState>({
13
+ count: 0,
14
+ lastUpdated: new Date().toISOString()
15
+ })
16
+
17
+ export const increment = () => {
18
+ useCounter.set('count', (d) => d + 1)
19
+ useCounter.set('lastUpdated', new Date().toISOString())
20
+ }
21
+
22
+ export const decrement = () => {
23
+ useCounter.set('count', (d) => d - 1)
24
+ useCounter.set('lastUpdated', new Date().toISOString())
25
+ }
@@ -0,0 +1,10 @@
1
+ export interface BigDataState extends Record<string, unknown> {
2
+ largeCollection: any[];
3
+ metaInfo: {
4
+ totalItems: number;
5
+ lastSync: number;
6
+ };
7
+ }
8
+ export declare const useBigData: import("../../advanced").IStore<BigDataState> & (<K extends keyof BigDataState>(key: K) => readonly [BigDataState[K] | undefined, (val: BigDataState[K] | ((draft: BigDataState[K]) => BigDataState[K]), options?: unknown) => boolean]);
9
+ export declare const populateData: (count?: number) => void;
10
+ export declare const clearBigData: () => Promise<void>;
@@ -0,0 +1,60 @@
1
+ import { gstate } from '../../index'
2
+ import { indexedDBPlugin } from '../../plugins/official/indexeddb.plugin'
3
+
4
+ /**
5
+ * Big Data Store using IndexedDB
6
+ * RECOMMENDED FOR: Frontend (FE)
7
+ *
8
+ * Demonstrates how to handle massive datasets (GBs) that would exceed
9
+ * the standard 5MB-10MB limit of localStorage.
10
+ */
11
+
12
+ export interface BigDataState extends Record<string, unknown> {
13
+ largeCollection: any[]
14
+ metaInfo: { totalItems: number, lastSync: number }
15
+ }
16
+
17
+ const initialState: BigDataState = {
18
+ largeCollection: [],
19
+ metaInfo: { totalItems: 0, lastSync: Date.now() }
20
+ }
21
+
22
+ // 1. Define the store
23
+ export const useBigData = gstate<BigDataState>(initialState, {
24
+ namespace: 'big-data-vault',
25
+ persist: false // Disable standard persistence to use IndexedDB exclusively
26
+ })
27
+
28
+ // 2. Add the IndexedDB Plugin
29
+ useBigData._addPlugin(indexedDBPlugin({
30
+ dbName: 'UserLargeStorage',
31
+ storeName: 'appStates'
32
+ }))
33
+
34
+ /**
35
+ * Action to simulate adding a large amount of data.
36
+ */
37
+ export const populateData = (count: number = 1000) => {
38
+ const data: Array<{ id: string, payload: string, timestamp: number }> = []
39
+ for (let i = 0; i < count; i++) {
40
+ data.push({
41
+ id: `item_${i}`,
42
+ payload: 'X'.repeat(1024), // 1KB per item
43
+ timestamp: Date.now()
44
+ })
45
+ }
46
+
47
+ useBigData.transaction(() => {
48
+ useBigData.set('largeCollection', data)
49
+ useBigData.set('metaInfo', { totalItems: count, lastSync: Date.now() })
50
+ })
51
+ }
52
+
53
+ /**
54
+ * Clear the database
55
+ */
56
+ export const clearBigData = async () => {
57
+ // Access plugin methods registered on the store
58
+ await (useBigData as any).plugins.indexedDB.clear()
59
+ useBigData.set('largeCollection', [])
60
+ }
@@ -0,0 +1,7 @@
1
+ export interface ThemeState extends Record<string, unknown> {
2
+ mode: 'light' | 'dark';
3
+ accent: string;
4
+ }
5
+ export declare const useTheme: import("../../advanced").IStore<ThemeState> & (<K extends keyof ThemeState>(key: K) => readonly [ThemeState[K] | undefined, (val: ThemeState[K] | ((draft: ThemeState[K]) => ThemeState[K]), options?: unknown) => boolean]);
6
+ export declare const initTheme: () => import("../../advanced").IStore<ThemeState> & (<K extends keyof ThemeState>(key: K) => readonly [ThemeState[K] | undefined, (val: ThemeState[K] | ((draft: ThemeState[K]) => ThemeState[K]), options?: unknown) => boolean]);
7
+ export declare const toggleTheme: () => void;
@@ -0,0 +1,32 @@
1
+ import { gstate, getStore } from '../../index'
2
+
3
+ // Define the shape of our theme state
4
+ export interface ThemeState extends Record<string, unknown> {
5
+ mode: 'light' | 'dark'
6
+ accent: string
7
+ }
8
+
9
+ /**
10
+ * Global Theme Manager
11
+ * RECOMMENDED FOR: Frontend (FE)
12
+ *
13
+ * Demonstrates global state using a dedicated store instance.
14
+ */
15
+ export const useTheme = gstate<ThemeState>({
16
+ mode: 'light',
17
+ accent: '#007bff'
18
+ }, {
19
+ namespace: 'theme-store',
20
+ persist: true
21
+ })
22
+
23
+ /**
24
+ * Helper to initialize the theme (useful for SSR or specific init logic)
25
+ */
26
+ export const initTheme = () => useTheme
27
+
28
+ // Reusable action to toggle theme
29
+ export const toggleTheme = () => {
30
+ const current = useTheme.get('mode')
31
+ useTheme.set('mode', current === 'light' ? 'dark' : 'light')
32
+ }
@@ -0,0 +1,19 @@
1
+ export interface AppState extends Record<string, unknown> {
2
+ userProfile: {
3
+ name: string;
4
+ preferences: any;
5
+ };
6
+ projects: Array<{
7
+ id: string;
8
+ content: string;
9
+ }>;
10
+ }
11
+ export declare const useHybridStore: import("../../advanced").IStore<AppState> & (<K extends keyof AppState>(key: K) => readonly [AppState[K] | undefined, (val: AppState[K] | ((draft: AppState[K]) => AppState[K]), options?: unknown) => boolean]);
12
+ export declare const syncNow: () => Promise<void>;
13
+ export declare const getSyncReport: () => {
14
+ lastSync: string;
15
+ count: any;
16
+ errors: any;
17
+ averageKeysPerSync: number;
18
+ };
19
+ export declare const updateName: (newName: string) => void;
@@ -0,0 +1,78 @@
1
+ import { gstate } from '../../index'
2
+ import { indexedDBPlugin } from '../../plugins/official/indexeddb.plugin'
3
+ import { cloudSyncPlugin, createMongoAdapter } from '../../plugins/official/cloud-sync.plugin'
4
+
5
+ /**
6
+ * Hybrid Cloud Sync Store
7
+ * RECOMMENDED FOR: Frontend (FE) with Cloud Backup
8
+ *
9
+ * Demonstrates a multi-layer storage strategy:
10
+ * 1. Cache: Memory (fast)
11
+ * 2. Persistent Local: IndexedDB (large capacity)
12
+ * 3. remote: MongoDB Cloud (On-demand/Scheduled backup)
13
+ */
14
+
15
+ export interface AppState extends Record<string, unknown> {
16
+ userProfile: { name: string; preferences: any }
17
+ projects: Array<{ id: string; content: string }>
18
+ }
19
+
20
+ const initialState: AppState = {
21
+ userProfile: { name: 'Dario', preferences: { theme: 'dark' } },
22
+ projects: []
23
+ }
24
+
25
+ // 1. Initialize the store
26
+ export const useHybridStore = gstate<AppState>(initialState, {
27
+ namespace: 'hybrid-app-vault',
28
+ persist: false // We use plugins for persistence
29
+ })
30
+
31
+ // 2. Add IndexedDB for local persistence (up to GBs)
32
+ useHybridStore._addPlugin(indexedDBPlugin({
33
+ dbName: 'LocalCacheDB'
34
+ }))
35
+
36
+ // 3. Add Cloud Sync for remote backup
37
+ // Configured to automatically sync every 5 minutes (300000ms)
38
+ useHybridStore._addPlugin(cloudSyncPlugin({
39
+ adapter: createMongoAdapter('https://api.mongodb.com/v1', 'YOUR_SECRET_API_KEY'),
40
+ autoSyncInterval: 300000,
41
+ onSync: (stats) => {
42
+ console.info(`[CloudSync] Success! Keys: ${stats.totalKeysSynced}, Total Bytes: ${stats.totalBytesSynced}`)
43
+ }
44
+ }))
45
+
46
+ /**
47
+ * Manual Trigger for Cloud Sync
48
+ */
49
+ export const syncNow = async () => {
50
+ const result = await (useHybridStore as any).plugins.cloudSync.sync()
51
+ if (result.status === 'success') {
52
+ alert(`Sync completed! ${result.stats.totalKeysSynced} items pushed to cloud.`)
53
+ } else if (result.status === 'no-change') {
54
+ console.log('No new changes to sync.')
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Get synchronization diagnostics
60
+ */
61
+ export const getSyncReport = () => {
62
+ const stats = (useHybridStore as any).plugins.cloudSync.getStats()
63
+ return {
64
+ lastSync: stats.lastSyncTimestamp ? new Date(stats.lastSyncTimestamp).toLocaleString() : 'Never',
65
+ count: stats.syncCount,
66
+ errors: stats.errors,
67
+ averageKeysPerSync: stats.syncCount > 0 ? stats.totalKeysSynced / stats.syncCount : 0
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Action to update profile
73
+ */
74
+ export const updateName = (newName: string) => {
75
+ useHybridStore.set('userProfile', (draft) => {
76
+ draft.name = newName
77
+ })
78
+ }
@@ -0,0 +1,13 @@
1
+ export interface CartItem {
2
+ id: string;
3
+ name: string;
4
+ price: number;
5
+ quantity: number;
6
+ }
7
+ export interface CartState extends Record<string, unknown> {
8
+ items: CartItem[];
9
+ coupon: string | null;
10
+ }
11
+ export declare const useCart: import("../../advanced").IStore<CartState> & (<K extends keyof CartState>(key: K) => readonly [CartState[K] | undefined, (val: CartState[K] | ((draft: CartState[K]) => CartState[K]), options?: unknown) => boolean]);
12
+ export declare const addToCart: (product: Omit<CartItem, "quantity">) => void;
13
+ export declare const getCartTotal: () => number;