@biglogic/rgs 3.5.3 → 3.7.2

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/index.d.ts DELETED
@@ -1,41 +0,0 @@
1
- import { createStore as baseCreateStore } from "./core/store";
2
- import { useStore as baseUseStore } from "./core/hooks";
3
- import * as Security from "./core/security";
4
- import type { IStore, StoreConfig } from "./core/types";
5
- export declare const gstate: <S extends Record<string, unknown>>(initialState: S, configOrNamespace?: string | StoreConfig<S>) => IStore<S> & (<K extends keyof S>(key: K) => readonly [S[K] | undefined, (val: S[K] | ((draft: S[K]) => S[K]), options?: unknown) => boolean]);
6
- export { baseCreateStore as createStore };
7
- export { useStore, useIsStoreReady, initState, getStore, destroyState, useStore as useGState, useStore as useSimpleState } from "./core/hooks";
8
- export { createAsyncStore } from "./core/async";
9
- export { SyncEngine, createSyncEngine } from "./core/sync";
10
- export type { SyncConfig, SyncState, SyncResult, SyncStrategy, ConflictInfo, ConflictResolution } from "./core/sync";
11
- export { initSync, destroySync, useSyncedState, useSyncStatus, triggerSync } from "./core/hooks";
12
- export * from "./plugins/index";
13
- export { generateEncryptionKey, exportKey, importKey, isCryptoAvailable, setAuditLogger, logAudit, validateKey, sanitizeValue } from "./core/security";
14
- export declare const addAccessRule: (pattern: string | ((key: string, userId?: string) => boolean), perms: Security.Permission[]) => void | undefined;
15
- export declare const hasPermission: (key: string, action: Security.Permission, uid?: string) => boolean;
16
- export declare const recordConsent: (uid: string, p: string, g: boolean) => Security.ConsentRecord;
17
- export declare const hasConsent: (uid: string, p: string) => boolean;
18
- export declare const getConsents: (uid: string) => Security.ConsentRecord[];
19
- export declare const revokeConsent: (uid: string, p: string) => Security.ConsentRecord | null | undefined;
20
- export declare const exportUserData: (uid: string) => {
21
- userId: string;
22
- exportedAt: number;
23
- consents: import("./core/security").ConsentRecord[];
24
- };
25
- export declare const deleteUserData: (uid: string) => {
26
- success: boolean;
27
- deletedConsents: number;
28
- };
29
- export declare const clearAccessRules: () => void;
30
- export declare const clearAllConsents: () => void;
31
- export type { EncryptionKey, AuditEntry, Permission, AccessRule, ConsentRecord } from "./core/security";
32
- export type { IStore, StoreConfig, PersistOptions, StateUpdater, ComputedSelector, WatcherCallback } from "./core/types";
33
- declare global {
34
- var createStore: typeof baseCreateStore;
35
- var gstate: <S extends Record<string, unknown>>(initialState: S, configOrNamespace?: string | StoreConfig<S>) => IStore<S> & ((key: string) => unknown);
36
- var initState: typeof import("./core/hooks").initState;
37
- var destroyState: typeof import("./core/hooks").destroyState;
38
- var gState: IStore<Record<string, unknown>>;
39
- var rgs: IStore<Record<string, unknown>>;
40
- var useStore: typeof baseUseStore;
41
- }
package/index.js DELETED
@@ -1,2 +0,0 @@
1
- import{produce as ht,freeze as Ne}from"immer";var D=typeof crypto<"u"&&typeof crypto.subtle<"u"&&typeof crypto.subtle.generateKey=="function",V=async()=>{if(!D)throw new Error("Web Crypto API not available");let t=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),e=crypto.getRandomValues(new Uint8Array(12));return{key:t,iv:e}},j=async t=>{let e=await crypto.subtle.exportKey("raw",t.key);return{key:btoa(String.fromCharCode(...new Uint8Array(e))),iv:btoa(String.fromCharCode(...t.iv))}},$=async(t,e)=>{let n=Uint8Array.from(atob(t),i=>i.charCodeAt(0)),r=Uint8Array.from(atob(e),i=>i.charCodeAt(0));return{key:await crypto.subtle.importKey("raw",n,{name:"AES-GCM",length:256},!0,["encrypt","decrypt"]),iv:r}},Qe=async(t,e)=>{let n=new TextEncoder,r=n.encode(JSON.stringify(t)),s=await crypto.subtle.encrypt({name:"AES-GCM",iv:e.iv},e.key,r),i=new Uint8Array(e.iv.length+s.byteLength);return i.set(e.iv),i.set(new Uint8Array(s),e.iv.length),btoa(String.fromCharCode(...i))},He=async(t,e)=>{let n=Uint8Array.from(atob(t),a=>a.charCodeAt(0)),r=n.slice(0,12),s=n.slice(12),i=await crypto.subtle.decrypt({name:"AES-GCM",iv:r},e.key,s);return JSON.parse(new TextDecoder().decode(i))},Ie=null,z=t=>{Ie=t},Ge=()=>Ie!==null,P=t=>{Ie&&Ie(t)},$e=(t,e,n)=>{t.set(e instanceof RegExp?e.source:e,n)},Ae=(t,e,n,r)=>{if(t.size===0)return!0;for(let[s,i]of t){let a;if(typeof s=="function")a=s(e,r);else try{a=new RegExp(s).test(e)}catch{continue}if(a)return i.includes(n)||i.includes("admin")}return!1},R=t=>{if(typeof t=="string"){let e=t.replace(/&#[xX]?[0-9a-fA-F]+;?/g,r=>{let s=r.match(/&amp;#x([0-9a-fA-F]+);?/i);if(s&&s[1])return String.fromCharCode(parseInt(s[1],16));let i=r.match(/&amp;#([0-9]+);?/);return i&&i[1]?String.fromCharCode(parseInt(i[1],10)):""});try{e=decodeURIComponent(e)}catch{}return e.replace(/\b(javascript|vbscript|data:text\/html|about:blank|chrome:)/gi,"[SEC-REMOVED]").replace(/<script\b[^>]*>[\s\S]*?<\s*\/\s*script\b[^>]*>/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]")}if(t&&typeof t=="object"&&!Array.isArray(t)){if(Object.getPrototypeOf(t)===Object.prototype){let e={};for(let[n,r]of Object.entries(t))e[n]=R(r);return e}return t}return Array.isArray(t)?t.map(e=>R(e)):t},A=t=>/^[a-zA-Z0-9_.-]+$/.test(t)&&t.length<=256,ze=(t,e,n,r)=>{let s={id:crypto.randomUUID(),purpose:n,granted:r,timestamp:Date.now()},i=t.get(e)||[];return i.push(s),t.set(e,i),P({timestamp:Date.now(),action:"set",key:`consent:${n}`,userId:e,success:!0}),s},Xe=(t,e,n)=>{let r=t.get(e);if(!r)return!1;for(let s=r.length-1;s>=0;s--){let i=r[s];if(i&&i.purpose===n)return i.granted}return!1},Ze=(t,e,n)=>ze(t,e,n,!1),Ye=(t,e)=>t.get(e)||[],et=(t,e)=>({userId:e,exportedAt:Date.now(),consents:t.get(e)||[]}),tt=(t,e)=>{let n=t.get(e)?.length||0;return t.delete(e),{success:!0,deletedConsents:n}};var ye=t=>{if(t===null||typeof t!="object")return t;if(typeof structuredClone=="function")try{return structuredClone(t)}catch{}let e=new WeakMap,n=r=>{if(r===null||typeof r!="object"||typeof r=="function")return r;if(e.has(r))return e.get(r);if(r instanceof Date)return new Date(r.getTime());if(r instanceof RegExp)return new RegExp(r.source,r.flags);if(r instanceof Map){let a=new Map;return e.set(r,a),r.forEach((l,f)=>a.set(n(f),n(l))),a}if(r instanceof Set){let a=new Set;return e.set(r,a),r.forEach(l=>a.add(n(l))),a}let s=Array.isArray(r)?[]:Object.create(Object.getPrototypeOf(r));e.set(r,s);let i=[...Object.keys(r),...Object.getOwnPropertySymbols(r)];for(let a of i)s[a]=n(r[a]);return s};return n(t)},xe=(t,e)=>{if(t===e)return!0;if(t===null||e===null||typeof t!="object"||typeof e!="object")return t===e;if(Array.isArray(t)&&Array.isArray(e)){if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(!xe(t[s],e[s]))return!1;return!0}let n=Object.keys(t),r=Object.keys(e);if(n.length!==r.length)return!1;for(let s=0;s<n.length;s++){let i=n[s];if(!(i in e)||!xe(t[i],e[i]))return!1}return!0};import{freeze as yt}from"immer";var rt=t=>`${t}_`,st=async t=>{if(!t.storage)return;let{store:e,config:n,diskQueue:r,storage:s,encryptionKey:i,audit:a,onError:l,silent:f,currentVersion:p}=t,b=rt(n.namespace||"gstate");try{let w={};e.forEach((h,k)=>{w[k]=h});let u,S=n?.encoded;S?u=btoa(JSON.stringify(w)):u=JSON.stringify(w),s.setItem(b.replace("_",""),JSON.stringify({v:1,t:Date.now(),e:null,d:u,_sys_v:p,_b64:S?!0:void 0})),a("set","FULL_STATE",!0)}catch(w){let u=w instanceof Error?w:new Error(String(w));l?l(u,{operation:"persist",key:"FULL_STATE"}):f||console.error("[gState] Persist failed: ",u)}let m=Array.from(r.entries());r.clear();for(let[w,u]of m)try{let S=u.value,h=u.options.encoded||u.options.secure;if(u.options.encrypted){if(!i)throw new Error(`Encryption key missing for "${w}"`);S=await Qe(u.value,i)}else h?S=btoa(JSON.stringify(u.value)):typeof u.value=="object"&&u.value!==null&&(S=JSON.stringify(u.value));s.setItem(`${b}${w}`,JSON.stringify({v:t.versions.get(w)||1,t:Date.now(),e:u.options.ttl?Date.now()+u.options.ttl:null,d:S,_sys_v:p,_enc:u.options.encrypted?!0:void 0,_b64:h?!0:void 0})),a("set",w,!0)}catch(S){let h=S instanceof Error?S:new Error(String(S));l?l(h,{operation:"persist",key:w}):f||console.error("[gState] Persist failed: ",h)}},ot=async(t,e,n)=>{let{storage:r,config:s,encryptionKey:i,audit:a,onError:l,silent:f,currentVersion:p,store:b,sizes:m,versions:w}=t,u=rt(s.namespace||"gstate"),S=s.immer??!0;if(r)try{let h={},k=0;for(let ae=0;ae<(r.length||0);ae++){let I=r.key(ae);if(!I||!I.startsWith(u))continue;let M=r.getItem(I);if(M)try{let _=JSON.parse(M),ce=I.substring(u.length);if(k=Math.max(k,_._sys_v!==void 0?_._sys_v:_.v||0),_.e&&Date.now()>_.e){r.removeItem(I),ae--;continue}let ue=_.d;if(_._enc&&i)ue=await He(ue,i);else if(typeof ue=="string"){if(_._b64)try{ue=JSON.parse(atob(ue))}catch{}else if(ue.startsWith("{")||ue.startsWith("["))try{ue=JSON.parse(ue)}catch{}}h[ce]=ue,a("hydrate",ce,!0)}catch(_){a("hydrate",I,!1,String(_));let ce=_ instanceof Error?_:new Error(String(_));l?l(ce,{operation:"hydration",key:I}):f||console.error(`[gState] Hydration failed for "${I}": `,_)}}let Se=k<p&&s.migrate?s.migrate(h,k):h;Object.entries(Se).forEach(([ae,I])=>{let M=S&&I!==null&&typeof I=="object"?yt(ye(I),!0):I,_=e(M),ce=m.get(ae)||0;t.totalSize=t.totalSize-ce+_,m.set(ae,_),b.set(ae,M),w.set(ae,1)}),n()}catch(h){let k=h instanceof Error?h:new Error(String(h));l?l(k,{operation:"hydration"}):f||console.error("[gState] Hydration failed: ",k)}};var it=(t,e,n)=>{if(t.plugins.size!==0)for(let r of t.plugins.values()){let s=r.hooks?.[e];if(s)try{s(n)}catch(i){let a=i instanceof Error?i:new Error(String(i));t.onError?t.onError(a,{operation:`plugin:${r.name}:${e}`,key:n.key}):t.silent||console.error(`[gState] Plugin "${r.name}" error:`,i)}}},at=(t,e,n)=>{try{t.plugins.set(e.name,e),e.hooks?.onInstall?.({store:n})}catch(r){let s=r instanceof Error?r:new Error(String(r));t.onError?t.onError(s,{operation:"plugin:install",key:e.name}):t.silent||console.error(`[gState] Failed to install plugin "${e.name}": `,r)}};var E=class{store;config;pendingQueue=new Map;remoteVersions=new Map;syncTimer=null;onlineStatusListeners=new Set;syncStateListeners=new Set;_isOnline=!0;_isSyncing=!1;constructor(e,n){this.store=e,this.config={endpoint:n.endpoint,authToken:n.authToken||"",strategy:n.strategy||"last-write-wins",autoSyncInterval:n.autoSyncInterval??3e4,syncOnReconnect:n.syncOnReconnect??!0,debounceTime:n.debounceTime??1e3,fetch:n.fetch||fetch,onSync:n.onSync||(()=>{}),onConflict:n.onConflict||(()=>({action:"accept-local"})),maxRetries:n.maxRetries??3},this._isOnline=typeof navigator<"u"?navigator.onLine:!0,this._setupOnlineListener(),this._setupStoreListener(),this.config.autoSyncInterval>0&&this._startAutoSync()}_setupOnlineListener(){typeof window>"u"||(window.addEventListener("online",()=>{this._isOnline=!0,this._notifyOnlineChange(!0),this.config.syncOnReconnect&&this.sync()}),window.addEventListener("offline",()=>{this._isOnline=!1,this._notifyOnlineChange(!1)}))}_setupStoreListener(){this.store._subscribe(()=>{})}_startAutoSync(){setInterval(()=>{this._isOnline&&!this._isSyncing&&this.pendingQueue.size>0&&this.sync()},this.config.autoSyncInterval)}_notifyOnlineChange(e){this.onlineStatusListeners.forEach(n=>n(e)),this._notifyStateChange()}_notifyStateChange(){let e=this.getState();this.syncStateListeners.forEach(n=>n(e))}queueChange(e,n){let r=this.store._getVersion(e)||1;this.pendingQueue.set(e,{key:e,value:ye(n),timestamp:Date.now(),version:r}),this._notifyStateChange(),this.syncTimer&&clearTimeout(this.syncTimer),this.syncTimer=setTimeout(()=>{this._isOnline&&this.sync()},this.config.debounceTime)}async sync(){if(this._isSyncing)return{success:!1,syncedKeys:[],conflicts:[],errors:["Sync already in progress"],timestamp:Date.now(),duration:0};this._isSyncing=!0,this._notifyStateChange();let e=Date.now(),n=[],r=[],s=[];try{let i=Array.from(this.pendingQueue.values());if(i.length===0)return this._isSyncing=!1,this._notifyStateChange(),{success:!0,syncedKeys:[],conflicts:[],errors:[],timestamp:Date.now(),duration:Date.now()-e};await this._fetchRemoteVersions(i.map(l=>l.key));for(let l of i)try{let f=this.remoteVersions.get(l.key);if(!f)await this._pushChange(l),n.push(l.key),this.pendingQueue.delete(l.key);else if(f.version>=l.version){let p={key:l.key,localValue:l.value,remoteValue:f.value,localVersion:l.version,remoteVersion:f.version,timestamp:l.timestamp};r.push(p);let b=this.config.onConflict(p);await this._resolveConflict(l,f,b),n.push(l.key),this.pendingQueue.delete(l.key)}else await this._pushChange(l),n.push(l.key),this.pendingQueue.delete(l.key)}catch(f){s.push(`Failed to sync "${l.key}": ${f}`)}let a={success:s.length===0,syncedKeys:n,conflicts:r,errors:s,timestamp:Date.now(),duration:Date.now()-e};return this.config.onSync(a),a}catch(i){let a=`Sync failed: ${i}`;return s.push(a),{success:!1,syncedKeys:n,conflicts:r,errors:s,timestamp:Date.now(),duration:Date.now()-e}}finally{this._isSyncing=!1,this._notifyStateChange()}}async _fetchRemoteVersions(e){try{let n=await this.config.fetch(`${this.config.endpoint}/versions`,{method:"POST",headers:{"Content-Type":"application/json",...this.config.authToken&&{Authorization:`Bearer ${this.config.authToken}`}},body:JSON.stringify({keys:e})});if(n.ok){let r=await n.json();if(r.versions)for(let[s,i]of Object.entries(r.versions))this.remoteVersions.set(s,i)}}catch(n){console.warn("[SyncEngine] Failed to fetch remote versions:",n)}}async _pushChange(e){let n=0;for(;n<this.config.maxRetries;)try{let r=await this.config.fetch(`${this.config.endpoint}/sync`,{method:"POST",headers:{"Content-Type":"application/json",...this.config.authToken&&{Authorization:`Bearer ${this.config.authToken}`}},body:JSON.stringify({key:e.key,value:e.value,version:e.version,timestamp:e.timestamp})});if(r.ok){let s=await r.json();s.version&&this.remoteVersions.set(e.key,{version:s.version,timestamp:s.timestamp||Date.now(),value:e.value});return}n++}catch(r){if(n++,n>=this.config.maxRetries)throw r}}async _resolveConflict(e,n,r){switch(r.action){case"accept-local":await this._pushChange({...e,version:n.version+1,timestamp:Date.now()});break;case"accept-remote":this.store.set(e.key,n.value);break;case"merge":this.store.set(e.key,r.value),await this._pushChange({key:e.key,value:r.value,version:Math.max(e.version,n.version)+1,timestamp:Date.now()});break;case"discard":break}}getState(){return{isOnline:this._isOnline,isSyncing:this._isSyncing,lastSyncTimestamp:null,pendingChanges:this.pendingQueue.size,conflicts:0}}onOnlineChange(e){return this.onlineStatusListeners.add(e),()=>this.onlineStatusListeners.delete(e)}onStateChange(e){return this.syncStateListeners.add(e),()=>this.syncStateListeners.delete(e)}async flush(){return this.sync()}destroy(){this.syncTimer&&clearTimeout(this.syncTimer),this.pendingQueue.clear(),this.onlineStatusListeners.clear(),this.syncStateListeners.clear()}},N=(t,e)=>new E(t,e);var wt={local:()=>typeof window<"u"?window.localStorage:null,session:()=>typeof window<"u"?window.sessionStorage:null,memory:()=>{let t=new Map;return{getItem:e=>t.get(e)||null,setItem:(e,n)=>t.set(e,n),removeItem:e=>t.delete(e),key:e=>Array.from(t.keys())[e]||null,get length(){return t.size}}}},T=t=>{let e=new Map,n=new Map,r=new Map,s=new Set,i=new Map,a=new Set,l=new Map,f=new Map,p=new Map,b=new Map,m=new Map,w=new Map,u=new Map,S=new Map,h=t?.namespace||"gstate",k=t?.silent??!1,Se=t?.debounceTime??150,ae=t?.version??0,I=t?.storage||wt.local(),M=t?.onError,_=t?.maxObjectSize??0,ce=t?.maxTotalSize??0,ue=t?.encryptionKey??null,_e=t?.validateInput??!0,dt=t?.auditEnabled??!0,be=t?.userId,Re=t?.immer??!0,gt=t?.persistByDefault??t?.persistence??t?.persist??!1;t?.accessRules&&t.accessRules.forEach(o=>$e(u,o.pattern,o.permissions));let Oe=!1,De=!1,Me=!1,ge=0,we=null,fe=null,Ve,pt=new Promise(o=>{Ve=o}),ft=()=>`${h}_`,Ue=()=>({store:e,versions:n,sizes:r,totalSize:ge,storage:I,config:t||{},diskQueue:m,encryptionKey:ue,audit:he,onError:M,silent:k,debounceTime:Se,currentVersion:ae}),Ke=()=>({plugins:b,onError:M,silent:k}),je=o=>{if(o==null)return 0;let c=typeof o;if(c==="boolean")return 4;if(c==="number")return 8;if(c==="string")return o.length*2;if(c!=="object")return 0;let g=0,v=[o],x=new WeakSet;for(;v.length>0;){let y=v.pop();if(typeof y=="boolean")g+=4;else if(typeof y=="number")g+=8;else if(typeof y=="string")g+=y.length*2;else if(typeof y=="object"&&y!==null){let O=y;if(x.has(O))continue;if(x.add(O),Array.isArray(O))for(let le=0;le<O.length;le++)v.push(O[le]);else for(let le of Object.keys(O))g+=le.length*2,v.push(O[le])}}return g},me=(o,c)=>{it(Ke(),o,c)},he=(o,c,g,v)=>{dt&&Ge()&&P&&P({timestamp:Date.now(),action:o,key:c,userId:be,success:g,error:v})},Be=o=>{let c=f.get(o);if(!c)return;let g=new Set,v=y=>(g.add(y),f.has(y)?f.get(y).lastValue:Z.get(y)),x=c.selector(v);c.deps.forEach(y=>{if(!g.has(y)){let O=p.get(y);O&&(O.delete(o),O.size===0&&p.delete(y))}}),g.forEach(y=>{c.deps.has(y)||(p.has(y)||p.set(y,new Set),p.get(y).add(o))}),c.deps=g,xe(c.lastValue,x)||(c.lastValue=Re&&x!==null&&typeof x=="object"?Ne(ye(x),!0):x,n.set(o,(n.get(o)||0)+1),ve(o))},ve=o=>{if(o){if(p.has(o)){let v=p.get(o);for(let x of v)Be(x)}let c=l.get(o);if(c){let v=Z.get(o);for(let x of c)try{x(v)}catch(y){let O=y instanceof Error?y:new Error(String(y));M?M(O,{operation:"watcher",key:o}):k||console.error(`[gState] Watcher error for "${o}":`,y)}}let g=i.get(o);if(g)for(let v of g)try{v()}catch(x){let y=x instanceof Error?x:new Error(String(x));M?M(y,{operation:"keyListener",key:o}):k||console.error(`[gState] Listener error for "${o}":`,x)}}if(Oe){De=!0;return}for(let c of s)try{c()}catch(g){let v=g instanceof Error?g:new Error(String(g));M?M(v,{operation:"listener"}):k||console.error("[gState] Global listener error: ",g)}},Fe=async()=>{st(Ue())},Pe={},Z={_setSilently:(o,c)=>{let g=r.get(o)||0,v=Re&&c!==null&&typeof c=="object"?Ne(ye(c),!0):c,y=(_>0||ce>0)&&!1?je(v):0;ge=ge-g+y,r.set(o,y),e.set(o,v),n.set(o,(n.get(o)||0)+1),fe=null},_registerMethod:(o,c,g)=>{let v=x=>x==="__proto__"||x==="constructor"||x==="prototype";if(v(o)||v(c)){console.warn("[gState] Refusing to register method with unsafe key:",o,c);return}Pe[o]||(Pe[o]={}),Pe[o][c]=g},set:(o,c,g={})=>{let v=e.get(o),x=Re&&typeof c=="function"?ht(v,c):c;if(_e&&!A(o))return k||console.warn(`[gState] Invalid key: ${o}`),!1;if(!Ae(u,o,"write",be))return he("set",o,!1,"RBAC Denied"),k||console.error(`[gState] RBAC Denied for "${o}"`),!1;let y=_e?R(x):x,O=r.get(o)||0;me("onBeforeSet",{key:o,value:y,store:Z,version:n.get(o)||0});let le=Re&&y!==null&&typeof y=="object"?Ne(ye(y),!0):y;if(!xe(v,le)){let ke=(_>0||ce>0)&&!1?je(le):0;if(_>0&&ke>_){let Ce=new Error(`Object size (${ke} bytes) exceeds maxObjectSize (${_} bytes)`);M?M(Ce,{operation:"set",key:o}):k||console.warn(`[gState] ${Ce.message} for "${o}"`)}if(ce>0){let Ce=ge-O+ke;if(Ce>ce){let qe=new Error(`Total store size (${Ce} bytes) exceeds limit (${ce} bytes)`);M?M(qe,{operation:"set"}):k||console.warn(`[gState] ${qe.message}`)}}ge=ge-O+ke,r.set(o,ke),e.set(o,le),n.set(o,(n.get(o)||0)+1),fe=null;let We=g.persist??gt;return We&&(m.set(o,{value:le,options:{...g,persist:We,encoded:g.encoded||t?.encoded}}),we&&clearTimeout(we),we=setTimeout(Fe,Se)),me("onSet",{key:o,value:le,store:Z,version:n.get(o)}),he("set",o,!0),ve(o),!0}return!1},get:o=>{if(!Ae(u,o,"read",be))return he("get",o,!1,"RBAC Denied"),null;let c=e.get(o);return me("onGet",{store:Z,key:o,value:c}),he("get",o,!0),c},compute:(o,c)=>{try{return f.has(o)||(f.set(o,{selector:c,lastValue:null,deps:new Set}),Be(o)),f.get(o).lastValue}catch(g){let v=g instanceof Error?g:new Error(String(g));return M?M(v,{operation:"compute",key:o}):k||console.error(`[gState] Compute error for "${o}": `,g),null}},watch:(o,c)=>{l.has(o)||l.set(o,new Set);let g=l.get(o);return g.add(c),()=>{g.delete(c),g.size===0&&l.delete(o)}},remove:o=>{if(!Ae(u,o,"delete",be))return he("delete",o,!1,"RBAC Denied"),!1;let c=e.get(o),g=e.delete(o);return g&&(ge-=r.get(o)||0,r.delete(o),me("onRemove",{store:Z,key:o,value:c}),fe=null),n.set(o,(n.get(o)||0)+1),I&&I.removeItem(`${ft()}${o}`),he("delete",o,!0),ve(o),g},delete:o=>Z.remove(o),deleteAll:()=>{if(Array.from(e.keys()).forEach(o=>Z.remove(o)),I){let o=h+"_";for(let c=0;c<(I.length||0);c++){let g=I.key(c);g?.startsWith(o)&&(I.removeItem(g),c--)}}return ge=0,r.clear(),fe=null,!0},list:()=>Object.fromEntries(e.entries()),use:o=>{a.add(o)},transaction:o=>{Oe=!0,me("onTransaction",{store:Z,key:"START"});try{o()}finally{Oe=!1,me("onTransaction",{store:Z,key:"END"}),De&&(De=!1,ve())}},destroy:()=>{we&&(clearTimeout(we),we=null),m.clear(),typeof window<"u"&&window.removeEventListener("beforeunload",Je),me("onDestroy",{store:Z}),s.clear(),i.clear(),l.clear(),f.clear(),p.clear(),b.clear(),e.clear(),r.clear(),ge=0,u.clear(),S.clear(),n.clear(),w.clear(),a.clear()},_addPlugin:o=>{at(Ke(),o,Z)},_removePlugin:o=>{b.delete(o)},_subscribe:(o,c)=>{if(c){i.has(c)||i.set(c,new Set);let g=i.get(c);return g.add(o),()=>{g.delete(o),g.size===0&&i.delete(c)}}return s.add(o),()=>s.delete(o)},_getVersion:o=>n.get(o)??0,addAccessRule:(o,c)=>$e(u,o,c),hasPermission:(o,c,g)=>{if(u.size===0)return!0;for(let[v,x]of u){let y;if(typeof v=="function")y=v(o,g);else try{let O=w.get(v);O||(O=new RegExp(v),w.set(v,O)),y=O.test(o)}catch{continue}if(y)return x.includes(c)||x.includes("admin")}return!1},recordConsent:(o,c,g)=>ze(S,o,c,g),hasConsent:(o,c)=>Xe(S,o,c),getConsents:o=>Ye(S,o),revokeConsent:(o,c)=>Ze(S,o,c),exportUserData:o=>et(S,o),deleteUserData:o=>tt(S,o),getSnapshot:()=>(fe||(fe=Object.fromEntries(e.entries())),fe),get plugins(){return Pe},get isReady(){return Me},get namespace(){return h},get userId(){return be},whenReady:()=>pt};["addAccessRule","recordConsent","hasConsent","getConsents","revokeConsent","exportUserData","deleteUserData"].forEach(o=>{let c=Z[o];c&&Z._registerMethod("security",o,c)});let Je=()=>{m.size>0&&Fe()};typeof window<"u"&&window.addEventListener("beforeunload",Je),I?ot(Ue(),o=>(_>0||ce>0)&&!1?je(o):0,()=>{Me=!0,fe=null,Ve(),ve()}).then(()=>{}):(Me=!0,Ve());let Te=null;return t?.sync&&(Te=new E(Z,t.sync),Z._registerMethod("sync","flush",()=>Te?.flush()),Z._registerMethod("sync","getState",()=>Te?.getState()),Z._registerMethod("sync","onStateChange",o=>Te?.onStateChange(o))),Z};import{useSyncExternalStore as ct,useDebugValue as bt,useMemo as Le,useCallback as Ee,useEffect as ut,useState as lt}from"react";var de=null,L=t=>{de&&!t?.namespace&&(t?.silent||console.warn("[gState] Store already exists. Pass a unique namespace to create additional stores."));let e=T(t);return de=e,e},U=()=>{de&&(de.destroy(),de=null)},K=t=>{let e=t||de,n=Le(()=>r=>e?e._subscribe(r):()=>{},[e]);return ct(n,()=>e?e.isReady:!1,()=>!0)},C=()=>de;function d(t,e){let n=Le(()=>e||de,[e]),r=Le(()=>{let u=()=>{},S=()=>!1,h=()=>null;return{set:S,get:h,remove:S,delete:S,deleteAll:S,list:()=>({}),compute:h,watch:()=>()=>{},use:u,transaction:u,destroy:u,_subscribe:()=>()=>{},_setSilently:u,_registerMethod:u,_addPlugin:u,_removePlugin:u,_getVersion:()=>0,get isReady(){return!1},whenReady:()=>Promise.resolve(),get plugins(){return{}},getSnapshot:()=>({}),get namespace(){return"ghost"},get userId(){}}},[]),s=n||r,i=typeof t=="function",a=i?null:t,l=i?t:null,f=Ee(u=>i?s._subscribe(u):s._subscribe(u,a),[s,i,a]),p=Ee(()=>i?l(s.getSnapshot()):s.get(a)??void 0,[s,i,a,l]),b=Ee(()=>{if(i)try{return l({})}catch{return}else return},[l,i]),m=ct(f,p,b),w=Ee((u,S)=>i?!1:s.set(a,u,S),[s,i,a]);return bt(m,u=>i?`Selector: ${JSON.stringify(u)}`:`${a}: ${JSON.stringify(u)}`),i?m:[m,w]}var pe=new Map,B=(t,e)=>{let n=t.namespace;if(pe.has(n))return console.warn(`[gState] Sync engine already exists for namespace "${n}". Call destroySync first.`),pe.get(n);let r=new E(t,e);return pe.set(n,r),r},F=t=>{let e=pe.get(t);e&&(e.destroy(),pe.delete(t))};function J(t,e){let n=e||de,r=n?.namespace||"default",s=pe.get(r),i=d(t,n),a=i[0],l=i[1],[f,p]=lt(()=>s?.getState()||{isOnline:!0,isSyncing:!1,lastSyncTimestamp:null,pendingChanges:0,conflicts:0});ut(()=>s?s.onStateChange(p):void 0,[s]);let b=Ee((m,w)=>{let u=l(m,w);if(u&&s){let S=n?.get(t);s.queueChange(t,S)}return u},[l,s,t,n]);return[a,b,f]}var W=()=>{let[t,e]=lt({isOnline:!0,isSyncing:!1,lastSyncTimestamp:null,pendingChanges:0,conflicts:0});return ut(()=>{let n=()=>{let s=!0,i=!1,a=0,l=0;pe.forEach(f=>{let p=f.getState();s=s&&p.isOnline,i=i||p.isSyncing,a+=p.pendingChanges,l+=p.conflicts}),e({isOnline:s,isSyncing:i,lastSyncTimestamp:null,pendingChanges:a,conflicts:l})};n();let r=Array.from(pe.values()).map(s=>s.onStateChange(n));return()=>r.forEach(s=>s())},[]),t},q=async t=>{let e=t||de?.namespace;if(!e)return;let n=pe.get(e);n&&await n.flush()};var Q=(t,e)=>{let n=e?.key||"async_data",r=e?.store||T({namespace:`async_${n}`,silent:!0});return r.get(n)==null&&r.set(n,{data:null,loading:!1,error:null,updatedAt:null}),Object.assign(r,{execute:async()=>{let i=r.get(n);r.set(n,{...i||{data:null,loading:!1,error:null,updatedAt:null},loading:!0,error:null}),"whenReady"in r&&!r.isReady&&await r.whenReady();try{let a=await t(),l=r.get(n);r.set(n,{...l||{data:null,loading:!1,error:null,updatedAt:null},data:a,loading:!1,updatedAt:Date.now()},{persist:e?.persist})}catch(a){let l=r.get(n);r.set(n,{...l||{data:null,loading:!1,error:null,updatedAt:null},error:a instanceof Error?a:new Error(String(a)),loading:!1})}}})};var vt=()=>({name:"gstate-immer",hooks:{onInstall:({store:t})=>{t._registerMethod("immer","setWithProduce",((e,n)=>t.set(e,n)))}}});var kt=t=>{let e=[],n=-1,r=!1,s=t?.limit||50;return{name:"gstate-undo-redo",hooks:{onInstall:({store:i})=>{e.push(i.list()),n=0,i._registerMethod("undoRedo","undo",()=>{if(n>0){r=!0,n--;let a=e[n];return a?(Object.entries(a).forEach(([l,f])=>{i._setSilently(l,f)}),r=!1,!0):!1}return!1}),i._registerMethod("undoRedo","redo",()=>{if(n<e.length-1){r=!0,n++;let a=e[n];return a?(Object.entries(a).forEach(([l,f])=>{i._setSilently(l,f)}),r=!1,!0):!1}return!1}),i._registerMethod("undoRedo","canUndo",()=>n>0),i._registerMethod("undoRedo","canRedo",()=>n<e.length-1)},onSet:({store:i})=>{r||(n<e.length-1&&(e=e.slice(0,n+1)),e.push(i.list()),e.length>s?e.shift():n++)}}}};var Ct=t=>({name:"gstate-schema",hooks:{onSet:({key:e,value:n})=>{if(!e)return;let r=t[e];if(r){let s=r(n);if(s!==!0)throw new Error(`[Schema Error] Validation failed for key "${e}": ${s===!1?"Invalid type":s}`)}}}});var xt=t=>{let r=globalThis.__REDUX_DEVTOOLS_EXTENSION__;if(!r?.connect)return{name:"gstate-devtools-noop",hooks:{}};let s=null;return{name:"gstate-devtools",hooks:{onInstall:({store:i})=>{s=r.connect({name:t?.name||"Magnetar Store"}),s.init(i.list())},onSet:({key:i,store:a})=>{!i||!s||s.send(`SET_${i.toUpperCase()}`,a.list())},onRemove:({key:i,store:a})=>{!i||!s||s.send(`REMOVE_${i.toUpperCase()}`,a.list())}}}};var Et=()=>{let t=new Map;return{name:"gstate-snapshot",hooks:{onInstall:({store:e})=>{e._registerMethod("snapshot","takeSnapshot",(n=>{t.set(n,e.list())})),e._registerMethod("snapshot","restoreSnapshot",(n=>{let r=t.get(n);return r?(e.transaction(()=>{Object.entries(r).forEach(([s,i])=>{e.set(s,i)})}),!0):!1})),e._registerMethod("snapshot","listSnapshots",(()=>Array.from(t.keys()))),e._registerMethod("snapshot","deleteSnapshot",(n=>t.delete(n))),e._registerMethod("snapshot","clearSnapshots",(()=>t.clear()))}}}};var _t=t=>({name:"gstate-guard",hooks:{onBeforeSet:({key:e,value:n,store:r})=>{if(!e)return;let s=t[e];if(s){let i=s(n)}}}});var Rt=t=>({name:"gstate-analytics",hooks:{onSet:({key:e,value:n})=>{e&&(!t.keys||t.keys.includes(e))&&t.provider({key:e,value:n,action:"SET"})},onRemove:({key:e})=>{e&&(!t.keys||t.keys.includes(e))&&t.provider({key:e,value:null,action:"REMOVE"})}}});var Pt=t=>{let e=new BroadcastChannel(t?.channelName||"gstate_sync"),n=!1;return{name:"gstate-sync",hooks:{onInstall:({store:r})=>{e.onmessage=s=>{let{key:i,value:a,action:l}=s.data;i&&(n=!0,l==="REMOVE"?r.remove(i):r.set(i,a),n=!1)}},onSet:({key:r,value:s})=>{!r||n||e.postMessage({key:r,value:s,action:"SET"})},onRemove:({key:r})=>{!r||n||e.postMessage({key:r,action:"REMOVE"})},onDestroy:()=>{e.close()}}}};var Tt=()=>({name:"gstate-debug-noop",hooks:{}});var It=(t={})=>{let e=t.dbName||"rgs-db",n=t.storeName||"states",r=t.version||1,s=null,i=()=>new Promise((p,b)=>{if(s)return p(s);let m=indexedDB.open(e,r);m.onerror=()=>b(m.error),m.onsuccess=()=>{s=m.result,p(s)},m.onupgradeneeded=w=>{let u=w.target.result;u.objectStoreNames.contains(n)||u.createObjectStore(n)}}),a=async(p,b)=>{let m=await i();return new Promise((w,u)=>{let k=m.transaction(n,"readwrite").objectStore(n).put(b,p);k.onsuccess=()=>w(),k.onerror=()=>u(k.error)})},l=async p=>{let b=await i();return new Promise((m,w)=>{let h=b.transaction(n,"readonly").objectStore(n).get(p);h.onsuccess=()=>m(h.result),h.onerror=()=>w(h.error)})},f=async p=>{let b=await i();return new Promise((m,w)=>{let h=b.transaction(n,"readwrite").objectStore(n).delete(p);h.onsuccess=()=>m(),h.onerror=()=>w(h.error)})};return{name:"indexedDB",hooks:{onInstall:({store:p})=>{p._registerMethod("indexedDB","clear",async()=>{(await i()).transaction(n,"readwrite").objectStore(n).clear()})},onInit:async({store:p})=>{let u=(await i()).transaction(n,"readonly").objectStore(n).getAllKeys();u.onsuccess=async()=>{let S=u.result,h=p.namespace+"_";for(let k of S)if(k.startsWith(h)){let Se=await l(k);if(Se){let ae=k.substring(h.length);p._setSilently(ae,Se.d)}}}},onSet:async({key:p,value:b,store:m})=>{if(!p)return;let w=m.namespace+"_",u={d:b,t:Date.now(),v:m._getVersion?.(p)||1};await a(`${w}${p}`,u)},onRemove:async({key:p,store:b})=>{if(!p)return;let m=b.namespace+"_";await f(`${m}${p}`)}}}};var At=t=>{let{adapter:e,autoSyncInterval:n}=t,r=new Map,s={lastSyncTimestamp:null,totalKeysSynced:0,totalBytesSynced:0,syncCount:0,lastDuration:0,errors:0},i=null;return{name:"cloudSync",hooks:{onInstall:({store:a})=>{a._registerMethod("cloudSync","sync",async()=>{let l=performance.now(),f={},p=0;try{let b=a.list(),m=Object.keys(b);for(let u of m){let S=a._getVersion?.(u)||0,h=r.get(u)||0;if(S>h){let k=b[u];f[u]=k,p+=JSON.stringify(k).length,r.set(u,S)}}if(Object.keys(f).length===0)return{status:"no-change",stats:s};if(await e.save(f))return s.lastSyncTimestamp=Date.now(),s.totalKeysSynced+=Object.keys(f).length,s.totalBytesSynced+=p,s.syncCount++,s.lastDuration=performance.now()-l,t.onSync&&t.onSync(s),{status:"success",stats:s};throw new Error(`Adapter ${e.name} failed to save.`)}catch(b){return s.errors++,console.error(`[gState] Cloud Sync Failed (${e.name}):`,b),{status:"error",error:String(b),stats:s}}}),a._registerMethod("cloudSync","getStats",()=>s),n&&n>0&&(i=setInterval(()=>{let f=a.plugins.cloudSync;f&&f.sync()},n))},onDestroy:()=>{i&&clearInterval(i)}}}},Ot=(t,e)=>({name:"MongoDB-Atlas",save:async n=>(await fetch(`${t}/action/updateOne`,{method:"POST",headers:{"Content-Type":"application/json","api-key":e},body:JSON.stringify({dataSource:"Cluster0",database:"rgs_cloud",collection:"user_states",filter:{id:"global_state"},update:{$set:{data:n,updatedAt:Date.now()}},upsert:!0})})).ok}),Dt=(t,e)=>({name:"Firebase-Firestore",save:async n=>{try{return((...i)=>{})("[Mock] Firestore Syncing:",n),!0}catch{return!1}}}),Mt=(t,e)=>({name:"SQL-REST-API",save:async n=>(await fetch(t,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify(n)})).ok});var On=t=>({name:"gstate-logger",hooks:{onSet:({key:e,value:n,version:r})=>{let s=new Date().toLocaleTimeString(),i=`[gState] SET: ${e} (v${r}) @ ${s}`;t?.collapsed?console.groupCollapsed(i):console.group(i),console.info("%c Value:","color: #4CAF50; font-weight: bold;",n),console.groupEnd()},onRemove:({key:e})=>{console.warn(`[gState] REMOVED: ${e}`)},onTransaction:({key:e})=>{e==="START"?console.group("\u2500\u2500 TRANSACTION START \u2500\u2500"):console.groupEnd()}}});var H=(t,e)=>{let r=T(typeof e=="string"?{namespace:e}:e);t&&Object.entries(t).forEach(([i,a])=>{r.get(i)===null&&r._setSilently(i,a)});let s=i=>d(i,r);return typeof window<"u"&&(window.gState=r,window.rgs=r),Object.assign(s,r)};var Y=(t,e)=>C()?.addAccessRule(t,e),ee=(t,e,n)=>C()?.hasPermission(t,e,n)??!0,te=(t,e,n)=>{let r=C();if(!r)throw new Error("[gState] recordConsent failed: No store found. call initState() first.");return r.recordConsent(t,e,n)},ne=(t,e)=>C()?.hasConsent(t,e)??!1,re=t=>C()?.getConsents(t)??[],se=(t,e)=>C()?.revokeConsent(t,e),oe=t=>{let e=C();if(!e)throw new Error("[gState] exportUserData failed: No store found.");return e.exportUserData(t)},ie=t=>{let e=C();if(!e)throw new Error("[gState] deleteUserData failed: No store found.");return e.deleteUserData(t)},G=()=>{},X=()=>{};export{E as SyncEngine,Y as addAccessRule,Rt as analyticsPlugin,G as clearAccessRules,X as clearAllConsents,At as cloudSyncPlugin,Q as createAsyncStore,Dt as createFirestoreAdapter,Ot as createMongoAdapter,Mt as createSqlRestAdapter,T as createStore,N as createSyncEngine,Tt as debugPlugin,ie as deleteUserData,U as destroyState,F as destroySync,xt as devToolsPlugin,j as exportKey,oe as exportUserData,V as generateEncryptionKey,re as getConsents,C as getStore,H as gstate,_t as guardPlugin,ne as hasConsent,ee as hasPermission,vt as immerPlugin,$ as importKey,It as indexedDBPlugin,L as initState,B as initSync,D as isCryptoAvailable,P as logAudit,On as loggerPlugin,te as recordConsent,se as revokeConsent,R as sanitizeValue,Ct as schemaPlugin,z as setAuditLogger,Et as snapshotPlugin,Pt as syncPlugin,q as triggerSync,kt as undoRedoPlugin,d as useGState,K as useIsStoreReady,d as useSimpleState,d as useStore,W as useSyncStatus,J as useSyncedState,A as validateKey};
2
- //# sourceMappingURL=index.js.map
package/index.js.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../core/store.ts", "../core/security.ts", "../core/utils.ts", "../core/persistence.ts", "../core/plugins.ts", "../core/sync.ts", "../core/hooks.ts", "../core/async.ts", "../plugins/official/immer.plugin.ts", "../plugins/official/undo-redo.plugin.ts", "../plugins/official/schema.plugin.ts", "../plugins/official/devtools.plugin.ts", "../plugins/official/snapshot.plugin.ts", "../plugins/official/guard.plugin.ts", "../plugins/official/analytics.plugin.ts", "../plugins/official/sync.plugin.ts", "../plugins/official/debug.plugin.ts", "../plugins/official/indexeddb.plugin.ts", "../plugins/official/cloud-sync.plugin.ts", "../plugins/index.ts", "../index.ts"],
4
- "sourcesContent": ["import { produce as _immerProduce, freeze as _immerFreeze } from 'immer'\r\n\r\nimport * as Security from \"./security\"\r\nimport * as Persistence from \"./persistence\"\r\nimport * as Plugins from \"./plugins\"\r\nimport { deepClone, isEqual } from './utils'\r\nimport { SyncEngine } from './sync'\r\n\r\nimport type {\r\n IStore, StoreConfig, PersistOptions, StoreSubscriber,\r\n ComputedSelector, WatcherCallback, IPlugin, PluginHookName,\r\n PluginContext, Middleware, CustomStorage, GStatePlugins\r\n} from './types'\r\n\r\n/**\r\n * Enterprise Storage Adapters\r\n */\r\nexport const StorageAdapters = {\r\n local: (): CustomStorage | null => (typeof window !== \"undefined\" ? window.localStorage : null),\r\n session: (): CustomStorage | null => (typeof window !== \"undefined\" ? window.sessionStorage : null),\r\n memory: (): CustomStorage => {\r\n const _m = new Map<string, string>()\r\n return {\r\n getItem: (k: string) => _m.get(k) || null,\r\n setItem: (k: string, v: string) => _m.set(k, v),\r\n removeItem: (k: string) => _m.delete(k),\r\n key: (i: number) => Array.from(_m.keys())[i] || null,\r\n get length() { return _m.size }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Creates an enterprise-grade state management store.\r\n */\r\nexport const createStore = <S extends Record<string, unknown> = Record<string, unknown>>(config?: StoreConfig<S>): IStore<S> => {\r\n const\r\n _store = new Map<string, unknown>(),\r\n _versions = new Map<string, number>(),\r\n _sizes = new Map<string, number>(), // Internal cache for key sizes\r\n _listeners = new Set<StoreSubscriber>(),\r\n _keyListeners = new Map<string, Set<StoreSubscriber>>(),\r\n _middlewares = new Set<Middleware>(),\r\n _watchers = new Map<string, Set<WatcherCallback<unknown>>>(),\r\n _computed = new Map<string, { selector: ComputedSelector<unknown>, lastValue: unknown, deps: Set<string> }>(),\r\n _computedDeps = new Map<string, Set<string>>(),\r\n _plugins = new Map<string, IPlugin<S>>(),\r\n _diskQueue = new Map<string, { value: unknown, options: PersistOptions }>(),\r\n _regexCache = new Map<string, RegExp>(), // Performance: Cache for RBAC regexes\r\n\r\n // Multi-store isolation for Security\r\n _accessRules: Security.AccessRulesMap = new Map(),\r\n _consents: Security.ConsentsMap = new Map(),\r\n\r\n _namespace = config?.namespace || \"gstate\",\r\n _silent = config?.silent ?? false,\r\n _debounceTime = config?.debounceTime ?? 150,\r\n _currentVersion = config?.version ?? 0,\r\n _storage = config?.storage || StorageAdapters.local(),\r\n _onError = config?.onError,\r\n _maxObjectSize = config?.maxObjectSize ?? 0,\r\n _maxTotalSize = config?.maxTotalSize ?? 0,\r\n _encryptionKey = config?.encryptionKey ?? null,\r\n _validateInput = config?.validateInput ?? true,\r\n _auditEnabled = config?.auditEnabled ?? true,\r\n _userId = config?.userId,\r\n _immer = config?.immer ?? true,\r\n _persistByDefault = config?.persistByDefault ?? config?.persistence ?? config?.persist ?? false\r\n\r\n if (config?.accessRules) {\r\n config.accessRules.forEach(rule => Security.addAccessRule(_accessRules, rule.pattern, rule.permissions))\r\n }\r\n\r\n let\r\n _isTransaction = false, _pendingEmit = false, _isReady = false, _totalSize = 0,\r\n _diskTimer: ReturnType<typeof setTimeout> | null = null,\r\n _snapshot: S | null = null // Cache for stable state snapshot\r\n\r\n let _readyResolver: () => void\r\n const _readyPromise = new Promise<void>(resolve => { _readyResolver = resolve })\r\n\r\n // --- Context Helpers ---\r\n\r\n const _getPrefix = () => `${_namespace}_`\r\n\r\n const getPersistenceContext = (): Persistence.PersistenceContext => ({\r\n store: _store, versions: _versions, sizes: _sizes, totalSize: _totalSize,\r\n storage: _storage, config: config || {}, diskQueue: _diskQueue,\r\n encryptionKey: _encryptionKey, audit: _audit,\r\n onError: _onError as unknown as ((error: Error, metadata?: Record<string, unknown>) => void) | undefined,\r\n silent: _silent, debounceTime: _debounceTime, currentVersion: _currentVersion\r\n })\r\n\r\n const getPluginContext = (): Plugins.PluginManagerContext<S> => ({\r\n plugins: _plugins,\r\n onError: _onError as unknown as ((error: Error, metadata?: Record<string, unknown>) => void) | undefined,\r\n silent: _silent\r\n })\r\n\r\n /**\r\n * Enterprise-grade iterative walker for precise memory estimation.\r\n * Faster than JSON.stringify and handles circular references accurately.\r\n */\r\n const _calculateSize = (val: unknown): number => {\r\n if (val === null || val === undefined) return 0\r\n const type = typeof val\r\n if (type === 'boolean') return 4\r\n if (type === 'number') return 8\r\n if (type === 'string') return (val as string).length * 2\r\n if (type !== 'object') return 0\r\n\r\n let bytes = 0\r\n const stack: unknown[] = [val]\r\n const seen = new WeakSet<object>()\r\n\r\n while (stack.length > 0) {\r\n const value = stack.pop()\r\n if (typeof value === 'boolean') { bytes += 4 }\r\n else if (typeof value === 'number') { bytes += 8 }\r\n else if (typeof value === 'string') { bytes += value.length * 2 }\r\n else if (typeof value === 'object' && value !== null) {\r\n const obj = value as Record<string, unknown>\r\n if (seen.has(obj)) continue\r\n seen.add(obj)\r\n if (Array.isArray(obj)) {\r\n for (let i = 0; i < obj.length; i++) stack.push(obj[i])\r\n } else {\r\n for (const key of Object.keys(obj)) {\r\n bytes += key.length * 2\r\n stack.push(obj[key])\r\n }\r\n }\r\n }\r\n }\r\n return bytes\r\n }\r\n\r\n const _runHook = (name: PluginHookName, context: PluginContext<S>) => {\r\n Plugins.runHook(getPluginContext(), name, context)\r\n }\r\n\r\n const _audit = (action: 'set' | 'get' | 'delete' | 'hydrate', key: string, success: boolean, error?: string) => {\r\n if (_auditEnabled && Security.isAuditActive() && Security.logAudit) {\r\n Security.logAudit({ timestamp: Date.now(), action, key, userId: _userId, success, error })\r\n }\r\n }\r\n\r\n // --- Reactivity ---\r\n\r\n const _updateComputed = (key: string) => {\r\n const comp = _computed.get(key)\r\n if (!comp) return\r\n\r\n const depsFound = new Set<string>()\r\n const getter = <V>(k: string): V | null => {\r\n depsFound.add(k)\r\n if (_computed.has(k)) return _computed.get(k)!.lastValue as V\r\n return instance.get(k) as V | null\r\n }\r\n\r\n const newValue = comp.selector(getter)\r\n\r\n // Update dependencies\r\n comp.deps.forEach(d => {\r\n if (!depsFound.has(d)) {\r\n const dependents = _computedDeps.get(d)\r\n if (dependents) { dependents.delete(key); if (dependents.size === 0) _computedDeps.delete(d) }\r\n }\r\n })\r\n depsFound.forEach(d => {\r\n if (!comp.deps.has(d)) {\r\n if (!_computedDeps.has(d)) _computedDeps.set(d, new Set())\r\n _computedDeps.get(d)!.add(key)\r\n }\r\n })\r\n comp.deps = depsFound\r\n\r\n if (!isEqual(comp.lastValue, newValue)) {\r\n comp.lastValue = (_immer && newValue !== null && typeof newValue === 'object') ? _immerFreeze(deepClone(newValue), true) : newValue\r\n _versions.set(key, (_versions.get(key) || 0) + 1)\r\n _emit(key)\r\n }\r\n }\r\n\r\n const _emit = (changedKey?: string) => {\r\n if (changedKey) {\r\n // 1. Update computed dependent on this key\r\n if (_computedDeps.has(changedKey)) {\r\n const dependents = _computedDeps.get(changedKey)!\r\n for (const dependentKey of dependents) {\r\n _updateComputed(dependentKey)\r\n }\r\n }\r\n\r\n // 2. Notify Watchers\r\n const watchers = _watchers.get(changedKey)\r\n if (watchers) {\r\n const val = instance.get(changedKey)\r\n for (const w of watchers) {\r\n try { w(val) }\r\n catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (_onError) _onError(error, { operation: 'watcher', key: changedKey })\r\n else if (!_silent) console.error(`[gState] Watcher error for \"${changedKey}\":`, e)\r\n }\r\n }\r\n }\r\n\r\n // 3. Notify Key Listeners\r\n const keyListeners = _keyListeners.get(changedKey)\r\n if (keyListeners) {\r\n for (const l of keyListeners) {\r\n try { l() }\r\n catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (_onError) _onError(error, { operation: 'keyListener', key: changedKey })\r\n else if (!_silent) console.error(`[gState] Listener error for \"${changedKey}\":`, e)\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (_isTransaction) { _pendingEmit = true; return }\r\n\r\n // 4. Notify Global Listeners\r\n for (const l of _listeners) {\r\n try { l() }\r\n catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (_onError) _onError(error, { operation: 'listener' })\r\n else if (!_silent) console.error(`[gState] Global listener error: `, e)\r\n }\r\n }\r\n }\r\n\r\n const _flushDisk = async () => {\r\n // We pass current values to the persistence module\r\n // Note: totalSize update is not handled here as flush doesn't change memory size\r\n Persistence.flushDisk(getPersistenceContext())\r\n }\r\n\r\n /**\r\n * Plugin namespace for safely storing plugin methods.\r\n */\r\n const _methodNamespace: Record<string, Record<string, unknown>> = {}\r\n\r\n const instance: IStore<S> = {\r\n _setSilently: (key: string, value: unknown) => {\r\n const oldSize = _sizes.get(key) || 0, frozen = (_immer && value !== null && typeof value === 'object') ? _immerFreeze!(deepClone(value), true) : value\r\n const hasLimits = (_maxObjectSize > 0 || _maxTotalSize > 0) && process.env.NODE_ENV !== 'production'\r\n const newSize = hasLimits ? _calculateSize(frozen) : 0\r\n\r\n _totalSize = _totalSize - oldSize + newSize\r\n _sizes.set(key, newSize)\r\n _store.set(key, frozen); _versions.set(key, (_versions.get(key) || 0) + 1)\r\n _snapshot = null // Invalidate snapshot\r\n },\r\n /**\r\n * Registers a custom method on the store instance.\r\n * @param pluginName - Plugin name\r\n * @param methodName - Method name\r\n * @param fn - Method function\r\n */\r\n _registerMethod: (pluginName: string, methodName: string, fn: (...args: unknown[]) => unknown) => {\r\n const isUnsafeKey = (key: string): boolean =>\r\n key === '__proto__' || key === 'constructor' || key === 'prototype'\r\n\r\n if (isUnsafeKey(pluginName) || isUnsafeKey(methodName)) {\r\n console.warn('[gState] Refusing to register method with unsafe key:', pluginName, methodName)\r\n return\r\n }\r\n\r\n if (!_methodNamespace[pluginName]) _methodNamespace[pluginName] = {}\r\n _methodNamespace[pluginName]![methodName] = fn\r\n },\r\n set: (key: string, valOrUp: unknown, options: PersistOptions = {}): boolean => {\r\n const oldVal = _store.get(key), newVal = _immer && typeof valOrUp === 'function' ? _immerProduce!(oldVal, valOrUp as (draft: unknown) => void) : valOrUp\r\n if (_validateInput && !Security.validateKey(key)) { if (!_silent) console.warn(`[gState] Invalid key: ${key}`); return false }\r\n if (!Security.hasPermission(_accessRules, key, 'write', _userId)) { _audit('set', key, false, 'RBAC Denied'); if (!_silent) console.error(`[gState] RBAC Denied for \"${key}\"`); return false }\r\n\r\n const sani = _validateInput ? Security.sanitizeValue(newVal) : newVal\r\n const oldSize = _sizes.get(key) || 0\r\n _runHook('onBeforeSet', { key, value: sani, store: instance, version: _versions.get(key) || 0 })\r\n\r\n const frozen = (_immer && sani !== null && typeof sani === 'object') ? _immerFreeze(deepClone(sani), true) : sani\r\n\r\n if (!isEqual(oldVal, frozen)) {\r\n const hasLimits = (_maxObjectSize > 0 || _maxTotalSize > 0) && process.env.NODE_ENV !== 'production'\r\n const finalSize = hasLimits ? _calculateSize(frozen) : 0\r\n\r\n if (_maxObjectSize > 0 && finalSize > _maxObjectSize) {\r\n const error = new Error(`Object size (${finalSize} bytes) exceeds maxObjectSize (${_maxObjectSize} bytes)`)\r\n if (_onError) _onError(error, { operation: 'set', key })\r\n else if (!_silent) console.warn(`[gState] ${error.message} for \"${key}\"`)\r\n }\r\n\r\n if (_maxTotalSize > 0) {\r\n const est = _totalSize - oldSize + finalSize\r\n if (est > _maxTotalSize) {\r\n const error = new Error(`Total store size (${est} bytes) exceeds limit (${_maxTotalSize} bytes)`)\r\n if (_onError) _onError(error, { operation: 'set' })\r\n else if (!_silent) console.warn(`[gState] ${error.message}`)\r\n }\r\n }\r\n\r\n _totalSize = _totalSize - oldSize + finalSize\r\n _sizes.set(key, finalSize)\r\n _store.set(key, frozen); _versions.set(key, (_versions.get(key) || 0) + 1)\r\n\r\n _snapshot = null // Invalidate snapshot\r\n\r\n const shouldPersist = options.persist ?? _persistByDefault\r\n if (shouldPersist) {\r\n _diskQueue.set(key, { value: frozen, options: { ...options, persist: shouldPersist, encoded: options.encoded || config?.encoded } }); if (_diskTimer) clearTimeout(_diskTimer); _diskTimer = setTimeout(_flushDisk, _debounceTime)\r\n }\r\n _runHook('onSet', { key, value: frozen, store: instance, version: _versions.get(key) })\r\n _audit('set', key, true)\r\n _emit(key)\r\n return true\r\n }\r\n return false\r\n },\r\n get: <T>(key: string): T | null => {\r\n if (!Security.hasPermission(_accessRules, key, 'read', _userId)) {\r\n _audit('get', key, false, 'RBAC Denied')\r\n return null\r\n }\r\n const val = _store.get(key)\r\n _runHook('onGet', { store: instance, key, value: val })\r\n _audit('get', key, true)\r\n return val as T\r\n },\r\n compute: <T>(key: string, selector: ComputedSelector<T>): T => {\r\n try {\r\n if (!_computed.has(key)) { _computed.set(key, { selector: selector as ComputedSelector<unknown>, lastValue: null, deps: new Set() }); _updateComputed(key) }\r\n return _computed.get(key)!.lastValue as T\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (_onError) _onError(error, { operation: 'compute', key })\r\n else if (!_silent) console.error(`[gState] Compute error for \"${key}\": `, e)\r\n return null as unknown as T\r\n }\r\n },\r\n watch: <T>(key: string, callback: WatcherCallback<T>) => {\r\n if (!_watchers.has(key)) _watchers.set(key, new Set())\r\n const set = _watchers.get(key)!; set.add(callback as WatcherCallback<unknown>)\r\n return () => { set.delete(callback as WatcherCallback<unknown>); if (set.size === 0) _watchers.delete(key) }\r\n },\r\n remove: (key: string): boolean => {\r\n if (!Security.hasPermission(_accessRules, key, 'delete', _userId)) {\r\n _audit('delete', key, false, 'RBAC Denied')\r\n return false\r\n }\r\n const old = _store.get(key), deleted = _store.delete(key)\r\n if (deleted) {\r\n _totalSize -= (_sizes.get(key) || 0)\r\n _sizes.delete(key)\r\n _runHook('onRemove', { store: instance, key, value: old })\r\n _snapshot = null // Invalidate snapshot\r\n }\r\n _versions.set(key, (_versions.get(key) || 0) + 1)\r\n if (_storage) _storage.removeItem(`${_getPrefix()}${key}`)\r\n\r\n _audit('delete', key, true)\r\n _emit(key); return deleted\r\n },\r\n delete: (key: string) => instance.remove(key),\r\n deleteAll: () => {\r\n Array.from(_store.keys()).forEach(k => instance.remove(k))\r\n if (_storage) {\r\n const prefix = _namespace + \"_\"\r\n for (let i = 0; i < (_storage.length || 0); i++) {\r\n const k = _storage.key(i); if (k?.startsWith(prefix)) { _storage.removeItem(k); i-- }\r\n }\r\n }\r\n _totalSize = 0\r\n _sizes.clear()\r\n _snapshot = null // Invalidate snapshot\r\n return true\r\n },\r\n list: () => Object.fromEntries(_store.entries()),\r\n use: (m: Middleware) => { _middlewares.add(m) },\r\n transaction: (fn: () => void) => {\r\n _isTransaction = true; _runHook('onTransaction', { store: instance, key: 'START' })\r\n try { fn() } finally { _isTransaction = false; _runHook('onTransaction', { store: instance, key: 'END' }); if (_pendingEmit) { _pendingEmit = false; _emit() } }\r\n },\r\n destroy: () => {\r\n if (_diskTimer) { clearTimeout(_diskTimer); _diskTimer = null }\r\n _diskQueue.clear()\r\n if (typeof window !== 'undefined') window.removeEventListener('beforeunload', _unloadHandler)\r\n _runHook('onDestroy', { store: instance })\r\n _listeners.clear(); _keyListeners.clear(); _watchers.clear(); _computed.clear()\r\n _computedDeps.clear(); _plugins.clear(); _store.clear(); _sizes.clear(); _totalSize = 0\r\n _accessRules.clear(); _consents.clear(); _versions.clear(); _regexCache.clear(); _middlewares.clear()\r\n },\r\n _addPlugin: (p: IPlugin<S>) => {\r\n Plugins.installPlugin(getPluginContext(), p, instance)\r\n },\r\n _removePlugin: (name: string) => { _plugins.delete(name) },\r\n _subscribe: (cb: StoreSubscriber, key?: string) => {\r\n if (key) {\r\n if (!_keyListeners.has(key)) _keyListeners.set(key, new Set())\r\n const set = _keyListeners.get(key)!; set.add(cb)\r\n return () => { set.delete(cb); if (set.size === 0) _keyListeners.delete(key) }\r\n }\r\n _listeners.add(cb); return () => _listeners.delete(cb)\r\n },\r\n _getVersion: (key: string) => _versions.get(key) ?? 0,\r\n\r\n // Enterprise Security & Compliance\r\n addAccessRule: (pattern, permissions) => Security.addAccessRule(_accessRules, pattern, permissions),\r\n hasPermission: (key, action, userId) => {\r\n if (_accessRules.size === 0) return true\r\n for (const [pattern, perms] of _accessRules) {\r\n let matches: boolean\r\n if (typeof pattern === 'function') {\r\n matches = pattern(key, userId)\r\n } else {\r\n try {\r\n let re = _regexCache.get(pattern)\r\n if (!re) { re = new RegExp(pattern); _regexCache.set(pattern, re) }\r\n matches = re.test(key)\r\n } catch { continue }\r\n }\r\n if (matches) return perms.includes(action) || perms.includes('admin')\r\n }\r\n return false\r\n },\r\n recordConsent: (userId, purpose, granted) => Security.recordConsent(_consents, userId, purpose, granted),\r\n hasConsent: (userId, purpose) => Security.hasConsent(_consents, userId, purpose),\r\n getConsents: (userId) => Security.getConsents(_consents, userId),\r\n revokeConsent: (userId, purpose) => Security.revokeConsent(_consents, userId, purpose),\r\n exportUserData: (userId) => Security.exportUserData(_consents, userId),\r\n deleteUserData: (userId) => Security.deleteUserData(_consents, userId),\r\n\r\n getSnapshot: (): S => {\r\n if (!_snapshot) {\r\n _snapshot = Object.fromEntries(_store.entries()) as S\r\n }\r\n return _snapshot\r\n },\r\n\r\n get plugins() { return _methodNamespace as unknown as GStatePlugins },\r\n get isReady() { return _isReady },\r\n get namespace() { return _namespace },\r\n get userId() { return _userId },\r\n whenReady: () => _readyPromise\r\n }\r\n\r\n const secMethods = ['addAccessRule', 'recordConsent', 'hasConsent', 'getConsents', 'revokeConsent', 'exportUserData', 'deleteUserData']\r\n secMethods.forEach(m => {\r\n const fn = (instance as unknown as Record<string, (...args: unknown[]) => unknown>)[m]\r\n if (fn) instance._registerMethod('security', m, fn)\r\n })\r\n\r\n const _unloadHandler = () => { if (_diskQueue.size > 0) _flushDisk() }\r\n if (typeof window !== 'undefined') window.addEventListener('beforeunload', _unloadHandler)\r\n\r\n if (_storage) {\r\n Persistence.hydrateStore(\r\n getPersistenceContext(),\r\n // We pass the calculateSize function to update memory usage correctly after hydration\r\n (val) => {\r\n const hasLimits = (_maxObjectSize > 0 || _maxTotalSize > 0) && process.env.NODE_ENV !== 'production'\r\n return hasLimits ? _calculateSize(val) : 0\r\n },\r\n () => { _isReady = true; _snapshot = null; _readyResolver(); _emit() }\r\n ).then(() => {\r\n // Hydration logic handles isReady and emit internally via callback or promise resolution if needed\r\n // But here we rely on the callback passed to hydrateStore\r\n })\r\n } else { _isReady = true; _readyResolver!() }\r\n\r\n // Initialize sync engine if configured\r\n let _syncEngine: SyncEngine<S> | null = null\r\n if ((config as StoreConfig<S>)?.sync) {\r\n _syncEngine = new SyncEngine(instance, (config as StoreConfig<S>).sync!)\r\n // Register sync methods on the store\r\n instance._registerMethod('sync', 'flush', () => _syncEngine?.flush())\r\n instance._registerMethod('sync', 'getState', () => _syncEngine?.getState())\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n instance._registerMethod('sync', 'onStateChange', (cb: any) => _syncEngine?.onStateChange(cb))\r\n }\r\n\r\n return instance\r\n}\r\n", "/**\r\n * Enterprise Security Module - AES-256-GCM\r\n * RBAC, Audit Logging, GDPR Compliance, and Input Validation\r\n */\r\n\r\n// --- Infrastructure ---\r\n\r\n/**\r\n * Checks if Web Crypto API is available in the current environment\r\n */\r\nexport const isCryptoAvailable = typeof crypto !== 'undefined' &&\r\n typeof crypto.subtle !== 'undefined' &&\r\n typeof crypto.subtle.generateKey === 'function'\r\n\r\nexport interface EncryptionKey {\r\n key: CryptoKey\r\n iv: Uint8Array\r\n}\r\n\r\n// --- AES-256-GCM Encryption ---\r\n\r\n/**\r\n * Generates a secure AES-256-GCM key and IV\r\n * @returns Promise<EncryptionKey>\r\n */\r\nexport const generateEncryptionKey = async (): Promise<EncryptionKey> => {\r\n if (!isCryptoAvailable) throw new Error('Web Crypto API not available')\r\n\r\n const\r\n key = await crypto.subtle.generateKey(\r\n { name: 'AES-GCM', length: 256 },\r\n true,\r\n ['encrypt', 'decrypt']\r\n ),\r\n iv = crypto.getRandomValues(new Uint8Array(12))\r\n\r\n return { key, iv }\r\n}\r\n\r\n/**\r\n * Exports an encryption key to base64 strings\r\n * @param encryptionKey Key and IV to export\r\n * @returns Promise<{ key: string, iv: string }>\r\n */\r\nexport const exportKey = async (encryptionKey: EncryptionKey): Promise<{ key: string, iv: string }> => {\r\n const exportedKey = await crypto.subtle.exportKey('raw', encryptionKey.key)\r\n\r\n return {\r\n key: btoa(String.fromCharCode(...new Uint8Array(exportedKey))),\r\n iv: btoa(String.fromCharCode(...encryptionKey.iv))\r\n }\r\n}\r\n\r\n/**\r\n * Imports an encryption key from base64 strings\r\n * @param keyData Base64 encoded key\r\n * @param ivData Base64 encoded IV\r\n * @returns Promise<EncryptionKey>\r\n */\r\nexport const importKey = async (keyData: string, ivData: string): Promise<EncryptionKey> => {\r\n const\r\n keyBytes = Uint8Array.from(atob(keyData), c => c.charCodeAt(0)),\r\n ivBytes = Uint8Array.from(atob(ivData), c => c.charCodeAt(0)),\r\n key = await crypto.subtle.importKey(\r\n 'raw', keyBytes, { name: 'AES-GCM', length: 256 }, true, ['encrypt', 'decrypt']\r\n )\r\n\r\n return { key, iv: ivBytes }\r\n}\r\n\r\n/**\r\n * Encrypts data using AES-256-GCM\r\n * @param data Data to encrypt\r\n * @param encryptionKey Key and IV\r\n * @returns Promise<string> Base64 combined IV + ciphertext\r\n */\r\nexport const encrypt = async (data: unknown, encryptionKey: EncryptionKey): Promise<string> => {\r\n const\r\n encoder = new TextEncoder(),\r\n encoded = encoder.encode(JSON.stringify(data)),\r\n encrypted = await crypto.subtle.encrypt(\r\n { name: 'AES-GCM', iv: encryptionKey.iv as unknown as BufferSource },\r\n encryptionKey.key,\r\n encoded\r\n ),\r\n combined = new Uint8Array(encryptionKey.iv.length + encrypted.byteLength)\r\n\r\n combined.set(encryptionKey.iv)\r\n combined.set(new Uint8Array(encrypted), encryptionKey.iv.length)\r\n\r\n return btoa(String.fromCharCode(...combined))\r\n}\r\n\r\n/**\r\n * Decrypts AES-256-GCM encrypted data\r\n * @param encryptedData Base64 combined IV + ciphertext\r\n * @param encryptionKey Expected key\r\n * @returns Promise<T> Decrypted data\r\n */\r\nexport const decrypt = async <T>(encryptedData: string, encryptionKey: EncryptionKey): Promise<T> => {\r\n const\r\n combined = Uint8Array.from(atob(encryptedData), c => c.charCodeAt(0)),\r\n iv = combined.slice(0, 12),\r\n ciphertext = combined.slice(12),\r\n decrypted = await crypto.subtle.decrypt(\r\n { name: 'AES-GCM', iv: iv as unknown as BufferSource },\r\n encryptionKey.key,\r\n ciphertext\r\n )\r\n\r\n return JSON.parse(new TextDecoder().decode(decrypted))\r\n}\r\n\r\n// --- AUDIT LOGGING ---\r\n\r\nexport interface AuditEntry {\r\n timestamp: number\r\n action: 'set' | 'get' | 'delete' | 'hydrate'\r\n key: string\r\n userId?: string\r\n success: boolean\r\n error?: string\r\n}\r\n\r\nlet _auditLogger: ((entry: AuditEntry) => void) | null = null\r\n\r\n/**\r\n * Configures the global audit logger\r\n * @param logger Callback for audit entries\r\n */\r\nexport const setAuditLogger = (logger: (entry: AuditEntry) => void) => { _auditLogger = logger }\r\n\r\n/**\r\n * Checks if audit logging is currently active (has a logger configured)\r\n */\r\nexport const isAuditActive = () => _auditLogger !== null\r\n\r\n/**\r\n * Records an audit entry\r\n * @param entry Entry to log\r\n */\r\nexport const logAudit = (entry: AuditEntry) => { if (_auditLogger) _auditLogger(entry) }\r\n\r\n// --- ENTERPRISE SECURITY SYSTEM ---\r\n\r\n/**\r\n * Permission levels for Role-Based Access Control\r\n */\r\nexport type Permission = 'read' | 'write' | 'delete' | 'admin'\r\n\r\n/**\r\n * Access control rules\r\n */\r\nexport interface AccessRule {\r\n /** Regex pattern for matching keys, or a function for dynamic checks */\r\n pattern: string | ((key: string, userId?: string) => boolean)\r\n /** Permissions granted by this rule */\r\n permissions: Permission[]\r\n}\r\n\r\n/**\r\n * Global access rules registry\r\n * Supports both string patterns and function-based rules\r\n */\r\nexport type AccessRulesMap = Map<string | ((key: string, userId?: string) => boolean), Permission[]>\r\n\r\n/**\r\n * Adds an access rule for a key pattern\r\n * @param rules Map of rules to update\r\n * @param pattern Regex pattern or function for keys\r\n * @param perms Allowed permissions\r\n */\r\nexport const addAccessRule = (rules: AccessRulesMap, pattern: string | ((key: string, userId?: string) => boolean), perms: Permission[]) => {\r\n rules.set(pattern instanceof RegExp ? pattern.source : pattern, perms)\r\n}\r\n\r\n/**\r\n * Checks if a user has permission for an action on a key\r\n * @param rules Map of access rules\r\n * @param key Store key\r\n * @param action Requested action\r\n * @param _userId User identifier (optional)\r\n * @returns boolean - True if permission granted\r\n */\r\nexport const hasPermission = (rules: AccessRulesMap, key: string, action: Permission, _userId?: string): boolean => {\r\n // Default allow ONLY if no rules are defined at all\r\n if (rules.size === 0) return true\r\n\r\n // Check each rule pattern\r\n for (const [pattern, perms] of rules) {\r\n let matches: boolean\r\n\r\n // Check if pattern is a function\r\n if (typeof pattern === 'function') {\r\n matches = pattern(key, _userId)\r\n } else {\r\n // It's a regex string\r\n try {\r\n matches = new RegExp(pattern).test(key)\r\n } catch {\r\n // Invalid regex, skip\r\n continue\r\n }\r\n }\r\n\r\n if (matches) {\r\n // User has permission if requested action is in allowed permissions\r\n // Or if 'admin' permission is granted (full access)\r\n return perms.includes(action) || perms.includes('admin')\r\n }\r\n }\r\n\r\n // No matching rule found but rules EXIST = default DENY (Fail-Closed)\r\n return false\r\n}\r\n\r\n/**\r\n * Sanitizes values against common XSS patterns.\r\n * WARNING: While this provides a baseline defense, for applications requiring\r\n * high-security HTML sanitization, consider using an external library like DOMPurify.\r\n * @param value Value to sanitize\r\n * @returns Sanitized value\r\n */\r\nexport const sanitizeValue = (value: unknown): unknown => {\r\n if (typeof value === 'string') {\r\n // First, decode HTML entities to catch encoded schemes like &#106;avascript:\r\n // This must happen BEFORE scheme checks to catch encoded attacks\r\n let decoded = value.replace(/&#[xX]?[0-9a-fA-F]+;?/g, (match) => {\r\n // Decode HTML entity to character\r\n const hexMatch = match.match(/&amp;#x([0-9a-fA-F]+);?/i)\r\n if (hexMatch && hexMatch[1]) {\r\n return String.fromCharCode(parseInt(hexMatch[1], 16))\r\n }\r\n const decMatch = match.match(/&amp;#([0-9]+);?/)\r\n if (decMatch && decMatch[1]) {\r\n return String.fromCharCode(parseInt(decMatch[1], 10))\r\n }\r\n return ''\r\n })\r\n\r\n // Also decode URL-encoded characters to catch %6Aavascript: style bypasses\r\n try {\r\n decoded = decodeURIComponent(decoded)\r\n } catch {\r\n // Invalid URL encoding, continue with original\r\n }\r\n\r\n // Now check for dangerous URL schemes with word boundary (\\b) to prevent partial matches\r\n // The scheme must be at word boundary to avoid matching \"somejavascript:\" incorrectly\r\n const schemeCheck = decoded.replace(/\\b(javascript|vbscript|data:text\\/html|about:blank|chrome:)/gi, '[SEC-REMOVED]')\r\n\r\n // Prevent XSS vectors using a more robust script tag pattern\r\n return schemeCheck\r\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\s*\\/\\s*script\\b[^>]*>/gi, '[SEC-REMOVED]')\r\n .replace(/on\\w+\\s*=/gi, '[SEC-REMOVED]=')\r\n .replace(/<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi, '[SEC-REMOVED]')\r\n .replace(/<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi, '[SEC-REMOVED]')\r\n .replace(/<embed\\b[^<]*(?:(?!<\\/embed>)<[^<]*)*<\\/embed>/gi, '[SEC-REMOVED]')\r\n .replace(/<svg\\b[^<]*(?:(?!<\\/svg>)<[^<]*)*<\\/svg>/gi, '[SEC-REMOVED]')\r\n .replace(/<form\\b[^<]*(?:(?!<\\/form>)<[^<]*)*<\\/form>/gi, '[SEC-REMOVED]')\r\n .replace(/<base\\b[^<]*(?:(?!<\\/base>)<[^<]*)*<\\/base>/gi, '[SEC-REMOVED]')\r\n .replace(/<link\\b[^<]*(?:(?!<\\/link>)<[^<]*)*<\\/link>/gi, '[SEC-REMOVED]')\r\n .replace(/<meta\\b[^<]*(?:(?!<\\/meta>)<[^<]*)*<\\/meta>/gi, '[SEC-REMOVED]')\r\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '[SEC-REMOVED]')\r\n }\r\n\r\n // Deep clone and sanitize nested objects\r\n if (value && typeof value === 'object' && !Array.isArray(value)) {\r\n // Check if it's a plain object or something else (like Date, Map, etc.)\r\n if (Object.getPrototypeOf(value) === Object.prototype) {\r\n const sanitized: Record<string, unknown> = {}\r\n for (const [k, v] of Object.entries(value)) {\r\n sanitized[k] = sanitizeValue(v)\r\n }\r\n return sanitized\r\n }\r\n return value // For non-plain objects, we return as is (security should be handled at the source)\r\n }\r\n\r\n // Array sanitization\r\n if (Array.isArray(value)) {\r\n return value.map(v => sanitizeValue(v))\r\n }\r\n\r\n // Primitive values\r\n return value\r\n}\r\n\r\n/**\r\n * Validates store key format and length\r\n * @param key Key to validate\r\n * @returns boolean - True if valid\r\n */\r\nexport const validateKey = (key: string): boolean => /^[a-zA-Z0-9_.-]+$/.test(key) && key.length <= 256\r\n\r\n// --- GDPR COMPLIANCE ---\r\n\r\nexport interface ConsentRecord { id: string, purpose: string, granted: boolean, timestamp: number }\r\nexport type ConsentsMap = Map<string, ConsentRecord[]>\r\n\r\n/**\r\n * Records user consent for a specific purpose\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @param purpose Purpose of data processing\r\n * @param granted Whether consent is granted\r\n * @returns ConsentRecord\r\n */\r\nexport const recordConsent = (consents: ConsentsMap, userId: string, purpose: string, granted: boolean): ConsentRecord => {\r\n const\r\n record = { id: crypto.randomUUID(), purpose, granted, timestamp: Date.now() },\r\n user = consents.get(userId) || []\r\n\r\n user.push(record)\r\n consents.set(userId, user)\r\n\r\n logAudit({ timestamp: Date.now(), action: 'set', key: `consent:${purpose}`, userId, success: true })\r\n\r\n return record\r\n}\r\n\r\n/**\r\n * Checks if a user has granted consent for a purpose\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @param purpose Purpose to check\r\n * @returns boolean\r\n */\r\nexport const hasConsent = (consents: ConsentsMap, userId: string, purpose: string): boolean => {\r\n const userConsents = consents.get(userId)\r\n if (!userConsents) return false\r\n\r\n // Find the latest record for this purpose (insertion order is reliable)\r\n for (let i = userConsents.length - 1; i >= 0; i--) {\r\n const record = userConsents[i]\r\n if (record && record.purpose === purpose) {\r\n return record.granted\r\n }\r\n }\r\n\r\n return false\r\n}\r\n\r\n/**\r\n * Revokes user consent for a specific purpose\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @param purpose Purpose of data processing\r\n * @returns ConsentRecord | null\r\n */\r\nexport const revokeConsent = (consents: ConsentsMap, userId: string, purpose: string): ConsentRecord | null => {\r\n return recordConsent(consents, userId, purpose, false)\r\n}\r\n\r\n/**\r\n * Retrieves all consent records for a user\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @returns ConsentRecord[]\r\n */\r\nexport const getConsents = (consents: ConsentsMap, userId: string) => consents.get(userId) || []\r\n\r\n/**\r\n * Exports all data associated with a user\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @returns Exported data object\r\n */\r\nexport const exportUserData = (consents: ConsentsMap, userId: string) => ({ userId, exportedAt: Date.now(), consents: consents.get(userId) || [] })\r\n\r\n/**\r\n * Deletes all user data (Right to be Forgotten)\r\n * @param consents Map of consents\r\n * @param userId User identifier\r\n * @returns Result status\r\n */\r\nexport const deleteUserData = (consents: ConsentsMap, userId: string) => {\r\n const count = consents.get(userId)?.length || 0\r\n consents.delete(userId)\r\n\r\n return { success: true, deletedConsents: count }\r\n}\r\n", "/**\r\n * Utility functions for the store.\r\n * Extracted from store.ts to reduce file size.\r\n */\r\n\r\n/**\r\n * Deep clone using structuredClone (native) with fallback.\r\n * Handles circular references safely and preserves common types.\r\n * @param obj - Object to clone\r\n * @returns Deep cloned object\r\n */\r\nexport const deepClone = <T>(obj: T): T => {\r\n if (obj === null || typeof obj !== 'object') return obj\r\n\r\n // Optimization: use native structuredClone if available\r\n if (typeof structuredClone === 'function') {\r\n try {\r\n return structuredClone(obj)\r\n } catch (_e) {\r\n // Fallback for non-serializable objects (functions, prototypes, etc.)\r\n }\r\n }\r\n\r\n const seen = new WeakMap<object, unknown>()\r\n\r\n const clone = <V>(value: V): V => {\r\n if (value === null || typeof value !== 'object') return value\r\n if (typeof value === 'function') return value as unknown as V // Functions cannot be deep cloned easily\r\n\r\n // Check for circular references\r\n if (seen.has(value as object)) return seen.get(value as object) as V\r\n\r\n if (value instanceof Date) return new Date(value.getTime()) as unknown as V\r\n if (value instanceof RegExp) return new RegExp(value.source, value.flags) as unknown as V\r\n if (value instanceof Map) {\r\n const result = new Map()\r\n seen.set(value as object, result)\r\n value.forEach((v, k) => result.set(clone(k), clone(v)))\r\n return result as unknown as V\r\n }\r\n if (value instanceof Set) {\r\n const result = new Set()\r\n seen.set(value as object, result)\r\n value.forEach((v) => result.add(clone(v)))\r\n return result as unknown as V\r\n }\r\n\r\n // Handle Plain Objects and Arrays\r\n const result = (Array.isArray(value)\r\n ? []\r\n : Object.create(Object.getPrototypeOf(value))) as Record<string | symbol, unknown>\r\n\r\n seen.set(value as object, result)\r\n\r\n const keys = [...Object.keys(value as object), ...Object.getOwnPropertySymbols(value as object)]\r\n for (const key of keys) {\r\n result[key as string] = clone((value as Record<string | symbol, unknown>)[key])\r\n }\r\n\r\n return result as V\r\n }\r\n\r\n return clone(obj)\r\n}\r\n\r\n/**\r\n * Compares two values for deep equality.\r\n * @param a - First value\r\n * @param b - Second value\r\n * @returns True if values are equal\r\n */\r\nexport const isEqual = (a: unknown, b: unknown): boolean => {\r\n if (a === b) return true\r\n if (a === null || b === null) return a === b\r\n if (typeof a !== 'object' || typeof b !== 'object') return a === b\r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false\r\n for (let i = 0; i < a.length; i++) if (!isEqual(a[i], b[i])) return false\r\n return true\r\n }\r\n const keysA = Object.keys(a as object)\r\n const keysB = Object.keys(b as object)\r\n if (keysA.length !== keysB.length) return false\r\n\r\n for (let i = 0; i < keysA.length; i++) {\r\n const key = keysA[i] as string\r\n if (!(key in (b as object)) || !isEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key])) return false\r\n }\r\n return true\r\n}\r\n", "import { StorageAdapters } from \"./store\"\r\nimport * as Security from \"./security\"\r\nimport { deepClone } from \"./utils\"\r\nimport type { StoreConfig, PersistOptions } from \"./types\"\r\nimport { produce as _immerProduce, freeze as _immerFreeze } from 'immer'\r\n\r\n/**\r\n * Enterprise-grade persistence layer for RGS store.\r\n * Handles serialization, encryption, and storage adapter abstraction.\r\n */\r\n\r\n// Helper to get prefix\r\nconst _getPrefix = (namespace: string) => `${namespace}_`\r\n\r\nexport interface PersistenceContext {\r\n store: Map<string, unknown>\r\n versions: Map<string, number>\r\n sizes: Map<string, number>\r\n totalSize: number\r\n storage: ReturnType<typeof StorageAdapters.local>\r\n config: StoreConfig<Record<string, unknown>>\r\n diskQueue: Map<string, { value: unknown, options: PersistOptions }>\r\n encryptionKey: Security.EncryptionKey | null\r\n audit: (action: 'set' | 'get' | 'delete' | 'hydrate', key: string, success: boolean, error?: string) => void\r\n onError?: (error: Error, metadata?: Record<string, unknown>) => void\r\n silent: boolean\r\n debounceTime: number\r\n currentVersion: number\r\n}\r\n\r\n\r\n/**\r\n * Flushes the disk queue to persistent storage.\r\n */\r\nexport const flushDisk = async (ctx: PersistenceContext) => {\r\n if (!ctx.storage) return\r\n\r\n const { store, config, diskQueue, storage, encryptionKey, audit, onError, silent, currentVersion } = ctx\r\n const prefix = _getPrefix(config.namespace || 'gstate')\r\n\r\n // Save entire state under namespace key for simpler loading if needed by some adapters\r\n // This logic seems redundant if we save individual keys, but was in original store. keeping for compatibility.\r\n try {\r\n const stateObj: Record<string, unknown> = {}\r\n store.forEach((v, k) => { stateObj[k] = v })\r\n\r\n let dataValue: unknown\r\n const isEncoded = config?.encoded\r\n if (isEncoded) {\r\n dataValue = btoa(JSON.stringify(stateObj))\r\n } else {\r\n dataValue = JSON.stringify(stateObj)\r\n }\r\n\r\n storage.setItem(prefix.replace('_', ''), JSON.stringify({\r\n v: 1, t: Date.now(), e: null,\r\n d: dataValue, _sys_v: currentVersion, _b64: isEncoded ? true : undefined\r\n }))\r\n audit('set', 'FULL_STATE', true)\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (onError) onError(error, { operation: 'persist', key: 'FULL_STATE' })\r\n else if (!silent) console.error(`[gState] Persist failed: `, error)\r\n }\r\n\r\n const queue = Array.from(diskQueue.entries()); diskQueue.clear()\r\n for (const [key, data] of queue) {\r\n try {\r\n let dataValue: unknown = data.value\r\n const isEncoded = data.options.encoded || data.options.secure\r\n if (data.options.encrypted) {\r\n if (!encryptionKey) throw new Error(`Encryption key missing for \"${key}\"`)\r\n dataValue = await Security.encrypt(data.value, encryptionKey)\r\n } else if (isEncoded) {\r\n dataValue = btoa(JSON.stringify(data.value))\r\n } else if (typeof data.value === 'object' && data.value !== null) {\r\n dataValue = JSON.stringify(data.value)\r\n }\r\n\r\n storage.setItem(`${prefix}${key}`, JSON.stringify({\r\n v: (ctx.versions.get(key) || 1), t: Date.now(), e: data.options.ttl ? Date.now() + data.options.ttl : null,\r\n d: dataValue, _sys_v: currentVersion, _enc: data.options.encrypted ? true : undefined, _b64: isEncoded ? true : undefined\r\n }))\r\n audit('set', key, true)\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (onError) onError(error, { operation: 'persist', key })\r\n else if (!silent) console.error(`[gState] Persist failed: `, error)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Hydrates the store from persistent storage.\r\n */\r\nexport const hydrateStore = async (\r\n ctx: PersistenceContext,\r\n calculateSize: (val: unknown) => number,\r\n emit: () => void\r\n): Promise<void> => {\r\n const { storage, config, encryptionKey, audit, onError, silent, currentVersion, store, sizes, versions } = ctx\r\n const prefix = _getPrefix(config.namespace || 'gstate')\r\n const immer = config.immer ?? true\r\n\r\n if (!storage) return\r\n\r\n try {\r\n const persisted: Record<string, unknown> = {}\r\n let savedV = 0\r\n for (let i = 0; i < (storage.length || 0); i++) {\r\n const k = storage.key(i)\r\n if (!k || !k.startsWith(prefix)) continue\r\n const raw = storage.getItem(k)\r\n if (!raw) continue\r\n try {\r\n const meta = JSON.parse(raw), key = k.substring(prefix.length)\r\n\r\n // Version fallback for older stores where _sys_v was v\r\n savedV = Math.max(savedV, meta._sys_v !== undefined ? meta._sys_v : (meta.v || 0))\r\n\r\n if (meta.e && Date.now() > meta.e) { storage.removeItem(k); i--; continue }\r\n let d = meta.d\r\n if (meta._enc && encryptionKey) {\r\n d = await Security.decrypt(d, encryptionKey)\r\n } else if (typeof d === \"string\") {\r\n if (meta._b64) { try { d = JSON.parse(atob(d)) } catch (_e) { } }\r\n else if (d.startsWith(\"{\") || d.startsWith(\"[\")) { try { d = JSON.parse(d) } catch (_e) { } }\r\n }\r\n persisted[key] = d; audit('hydrate', key, true)\r\n } catch (err) {\r\n audit('hydrate', k, false, String(err))\r\n const error = err instanceof Error ? err : new Error(String(err))\r\n if (onError) onError(error, { operation: 'hydration', key: k })\r\n else if (!silent) console.error(`[gState] Hydration failed for \"${k}\": `, err)\r\n }\r\n }\r\n const final = (savedV < currentVersion && config.migrate) ? config.migrate(persisted, savedV) : persisted\r\n\r\n Object.entries(final).forEach(([k, v]) => {\r\n // Re-freeze loaded state if immer is enabled\r\n const frozen = (immer && v !== null && typeof v === 'object') ? _immerFreeze(deepClone(v as object), true) : v\r\n\r\n const size = calculateSize(frozen)\r\n const oldSize = sizes.get(k) || 0\r\n ctx.totalSize = ctx.totalSize - oldSize + size\r\n sizes.set(k, size)\r\n store.set(k, frozen); versions.set(k, 1)\r\n })\r\n emit()\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (onError) onError(error, { operation: 'hydration' })\r\n else if (!silent) console.error(`[gState] Hydration failed: `, error)\r\n }\r\n}\r\n", "import { IStore, PluginHookName, PluginContext, IPlugin } from \"./types\"\r\n\r\n/**\r\n * Manages plugins and their lifecycle hooks.\r\n */\r\n\r\nexport interface PluginManagerContext<S extends Record<string, unknown>> {\r\n plugins: Map<string, IPlugin<S>>\r\n onError?: (error: Error, metadata?: Record<string, unknown>) => void\r\n silent: boolean\r\n}\r\n\r\nexport const runHook = <S extends Record<string, unknown>>(\r\n ctx: PluginManagerContext<S>,\r\n name: PluginHookName,\r\n hookContext: PluginContext<S>\r\n) => {\r\n if (ctx.plugins.size === 0) return\r\n for (const p of ctx.plugins.values()) {\r\n const hook = p.hooks?.[name]\r\n if (hook) {\r\n try { hook(hookContext) }\r\n catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (ctx.onError) ctx.onError(error, { operation: `plugin:${p.name}:${name}`, key: hookContext.key })\r\n else if (!ctx.silent) console.error(`[gState] Plugin \"${p.name}\" error:`, e)\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport const installPlugin = <S extends Record<string, unknown>>(\r\n ctx: PluginManagerContext<S>,\r\n plugin: IPlugin<S>,\r\n storeInstance: IStore<S>\r\n) => {\r\n try {\r\n ctx.plugins.set(plugin.name, plugin)\r\n plugin.hooks?.onInstall?.({ store: storeInstance })\r\n } catch (e) {\r\n const error = e instanceof Error ? e : new Error(String(e))\r\n if (ctx.onError) ctx.onError(error, { operation: 'plugin:install', key: plugin.name })\r\n else if (!ctx.silent) console.error(`[gState] Failed to install plugin \"${plugin.name}\": `, e)\r\n }\r\n}\r\n", "import { IStore } from \"./types\"\r\nimport { deepClone } from \"./utils\"\r\nimport { freeze as _immerFreeze } from 'immer'\r\n\r\n/**\r\n * Local-First Sync Engine for RGS\r\n *\r\n * Provides offline-by-default functionality with automatic synchronization\r\n * when connectivity is restored. Supports multiple conflict resolution strategies.\r\n */\r\n\r\n// --- Types ---\r\n\r\nexport type SyncStrategy = 'last-write-wins' | 'merge' | 'crdt' | 'server-wins' | 'client-wins'\r\n\r\nexport interface SyncConfig {\r\n /** Remote endpoint for synchronization */\r\n endpoint: string\r\n /** Authentication token */\r\n authToken?: string\r\n /** Conflict resolution strategy (default: 'last-write-wins') */\r\n strategy?: SyncStrategy\r\n /** Auto-sync interval in ms (default: 30000 = 30s) */\r\n autoSyncInterval?: number\r\n /** Enable auto-sync on reconnect (default: true) */\r\n syncOnReconnect?: boolean\r\n /** Debounce time for batch sync (default: 1000ms) */\r\n debounceTime?: number\r\n /** Custom fetch function */\r\n fetch?: typeof fetch\r\n /** Callback on sync complete */\r\n onSync?: (result: SyncResult) => void\r\n /** Callback on conflict */\r\n onConflict?: (conflict: ConflictInfo) => ConflictResolution\r\n /** Maximum retries on failure (default: 3) */\r\n maxRetries?: number\r\n}\r\n\r\nexport interface SyncResult {\r\n success: boolean\r\n syncedKeys: string[]\r\n conflicts: ConflictInfo[]\r\n errors: string[]\r\n timestamp: number\r\n duration: number\r\n}\r\n\r\nexport interface ConflictInfo {\r\n key: string\r\n localValue: unknown\r\n remoteValue: unknown\r\n localVersion: number\r\n remoteVersion: number\r\n timestamp: number\r\n}\r\n\r\nexport type ConflictResolution =\r\n | { action: 'accept-local' }\r\n | { action: 'accept-remote' }\r\n | { action: 'merge'; value: unknown }\r\n | { action: 'discard' }\r\n\r\nexport interface SyncState {\r\n isOnline: boolean\r\n isSyncing: boolean\r\n lastSyncTimestamp: number | null\r\n pendingChanges: number\r\n conflicts: number\r\n}\r\n\r\n// --- Sync Engine ---\r\n\r\ninterface PendingChange {\r\n key: string\r\n value: unknown\r\n timestamp: number\r\n version: number\r\n}\r\n\r\ninterface RemoteVersion {\r\n version: number\r\n timestamp: number\r\n value: unknown\r\n}\r\n\r\nexport class SyncEngine<S extends Record<string, unknown> = Record<string, unknown>> {\r\n private store: IStore<S>\r\n private config: Required<SyncConfig>\r\n private pendingQueue: Map<string, PendingChange> = new Map()\r\n private remoteVersions: Map<string, RemoteVersion> = new Map()\r\n private syncTimer: ReturnType<typeof setTimeout> | null = null\r\n private onlineStatusListeners: Set<(online: boolean) => void> = new Set()\r\n private syncStateListeners: Set<(state: SyncState) => void> = new Set()\r\n private _isOnline: boolean = true\r\n private _isSyncing: boolean = false\r\n\r\n constructor(store: IStore<S>, config: SyncConfig) {\r\n this.store = store\r\n this.config = {\r\n endpoint: config.endpoint,\r\n authToken: config.authToken || '',\r\n strategy: config.strategy || 'last-write-wins',\r\n autoSyncInterval: config.autoSyncInterval ?? 30000,\r\n syncOnReconnect: config.syncOnReconnect ?? true,\r\n debounceTime: config.debounceTime ?? 1000,\r\n fetch: config.fetch || fetch,\r\n onSync: config.onSync || (() => { }),\r\n onConflict: config.onConflict || (() => ({ action: 'accept-local' })),\r\n maxRetries: config.maxRetries ?? 3\r\n }\r\n\r\n this._isOnline = typeof navigator !== 'undefined' ? navigator.onLine : true\r\n this._setupOnlineListener()\r\n this._setupStoreListener()\r\n\r\n // Start auto-sync if enabled\r\n if (this.config.autoSyncInterval > 0) {\r\n this._startAutoSync()\r\n }\r\n }\r\n\r\n private _setupOnlineListener(): void {\r\n if (typeof window === 'undefined') return\r\n\r\n window.addEventListener('online', () => {\r\n this._isOnline = true\r\n this._notifyOnlineChange(true)\r\n if (this.config.syncOnReconnect) {\r\n this.sync()\r\n }\r\n })\r\n\r\n window.addEventListener('offline', () => {\r\n this._isOnline = false\r\n this._notifyOnlineChange(false)\r\n })\r\n }\r\n\r\n private _setupStoreListener(): void {\r\n // Listen to all store changes to queue for sync\r\n this.store._subscribe(() => {\r\n // This will be called on every change - we track pending changes differently\r\n })\r\n }\r\n\r\n private _startAutoSync(): void {\r\n setInterval(() => {\r\n if (this._isOnline && !this._isSyncing && this.pendingQueue.size > 0) {\r\n this.sync()\r\n }\r\n }, this.config.autoSyncInterval)\r\n }\r\n\r\n private _notifyOnlineChange(online: boolean): void {\r\n this.onlineStatusListeners.forEach(cb => cb(online))\r\n this._notifyStateChange()\r\n }\r\n\r\n private _notifyStateChange(): void {\r\n const state = this.getState()\r\n this.syncStateListeners.forEach(cb => cb(state))\r\n }\r\n\r\n /**\r\n * Queue a change for synchronization\r\n */\r\n queueChange(key: string, value: unknown): void {\r\n const version = this.store._getVersion(key) || 1\r\n this.pendingQueue.set(key, {\r\n key,\r\n value: deepClone(value),\r\n timestamp: Date.now(),\r\n version\r\n })\r\n this._notifyStateChange()\r\n\r\n // Debounced sync\r\n if (this.syncTimer) clearTimeout(this.syncTimer)\r\n this.syncTimer = setTimeout(() => {\r\n if (this._isOnline) this.sync()\r\n }, this.config.debounceTime)\r\n }\r\n\r\n /**\r\n * Perform synchronization with remote server\r\n */\r\n async sync(): Promise<SyncResult> {\r\n if (this._isSyncing) {\r\n return {\r\n success: false,\r\n syncedKeys: [],\r\n conflicts: [],\r\n errors: ['Sync already in progress'],\r\n timestamp: Date.now(),\r\n duration: 0\r\n }\r\n }\r\n\r\n this._isSyncing = true\r\n this._notifyStateChange()\r\n\r\n const startTime = Date.now()\r\n const syncedKeys: string[] = []\r\n const conflicts: ConflictInfo[] = []\r\n const errors: string[] = []\r\n\r\n try {\r\n // Get pending changes\r\n const pendingChanges = Array.from(this.pendingQueue.values())\r\n\r\n if (pendingChanges.length === 0) {\r\n this._isSyncing = false\r\n this._notifyStateChange()\r\n return {\r\n success: true,\r\n syncedKeys: [],\r\n conflicts: [],\r\n errors: [],\r\n timestamp: Date.now(),\r\n duration: Date.now() - startTime\r\n }\r\n }\r\n\r\n // Fetch remote versions for conflict detection\r\n await this._fetchRemoteVersions(pendingChanges.map(p => p.key))\r\n\r\n // Process each change\r\n for (const change of pendingChanges) {\r\n try {\r\n const remoteVersion = this.remoteVersions.get(change.key)\r\n\r\n if (!remoteVersion) {\r\n // No remote version - first time sync, just push\r\n await this._pushChange(change)\r\n syncedKeys.push(change.key)\r\n this.pendingQueue.delete(change.key)\r\n } else if (remoteVersion.version >= change.version) {\r\n // Remote is newer - conflict!\r\n const conflict: ConflictInfo = {\r\n key: change.key,\r\n localValue: change.value,\r\n remoteValue: remoteVersion.value,\r\n localVersion: change.version,\r\n remoteVersion: remoteVersion.version,\r\n timestamp: change.timestamp\r\n }\r\n conflicts.push(conflict)\r\n\r\n // Resolve conflict\r\n const resolution = this.config.onConflict(conflict)\r\n await this._resolveConflict(change, remoteVersion, resolution)\r\n syncedKeys.push(change.key)\r\n this.pendingQueue.delete(change.key)\r\n } else {\r\n // Local is newer - push to remote\r\n await this._pushChange(change)\r\n syncedKeys.push(change.key)\r\n this.pendingQueue.delete(change.key)\r\n }\r\n } catch (err) {\r\n errors.push(`Failed to sync \"${change.key}\": ${err}`)\r\n }\r\n }\r\n\r\n const result: SyncResult = {\r\n success: errors.length === 0,\r\n syncedKeys,\r\n conflicts,\r\n errors,\r\n timestamp: Date.now(),\r\n duration: Date.now() - startTime\r\n }\r\n\r\n this.config.onSync(result)\r\n return result\r\n } catch (err) {\r\n const errorMsg = `Sync failed: ${err}`\r\n errors.push(errorMsg)\r\n\r\n return {\r\n success: false,\r\n syncedKeys,\r\n conflicts,\r\n errors,\r\n timestamp: Date.now(),\r\n duration: Date.now() - startTime\r\n }\r\n } finally {\r\n this._isSyncing = false\r\n this._notifyStateChange()\r\n }\r\n }\r\n\r\n private async _fetchRemoteVersions(keys: string[]): Promise<void> {\r\n try {\r\n const response = await this.config.fetch(`${this.config.endpoint}/versions`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { 'Authorization': `Bearer ${this.config.authToken}` })\r\n },\r\n body: JSON.stringify({ keys })\r\n })\r\n\r\n if (response.ok) {\r\n const data = await response.json()\r\n if (data.versions) {\r\n for (const [key, version] of Object.entries(data.versions)) {\r\n this.remoteVersions.set(key, version as RemoteVersion)\r\n }\r\n }\r\n }\r\n } catch (err) {\r\n console.warn('[SyncEngine] Failed to fetch remote versions:', err)\r\n }\r\n }\r\n\r\n private async _pushChange(change: PendingChange): Promise<void> {\r\n let retries = 0\r\n\r\n while (retries < this.config.maxRetries) {\r\n try {\r\n const response = await this.config.fetch(`${this.config.endpoint}/sync`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...(this.config.authToken && { 'Authorization': `Bearer ${this.config.authToken}` })\r\n },\r\n body: JSON.stringify({\r\n key: change.key,\r\n value: change.value,\r\n version: change.version,\r\n timestamp: change.timestamp\r\n })\r\n })\r\n\r\n if (response.ok) {\r\n const data = await response.json()\r\n if (data.version) {\r\n this.remoteVersions.set(change.key, {\r\n version: data.version,\r\n timestamp: data.timestamp || Date.now(),\r\n value: change.value\r\n })\r\n }\r\n return\r\n }\r\n\r\n retries++\r\n } catch (err) {\r\n retries++\r\n if (retries >= this.config.maxRetries) throw err\r\n }\r\n }\r\n }\r\n\r\n private async _resolveConflict(\r\n localChange: PendingChange,\r\n remoteVersion: RemoteVersion,\r\n resolution: ConflictResolution\r\n ): Promise<void> {\r\n switch (resolution.action) {\r\n case 'accept-local':\r\n // Force push local value\r\n await this._pushChange({\r\n ...localChange,\r\n version: remoteVersion.version + 1,\r\n timestamp: Date.now()\r\n })\r\n break\r\n\r\n case 'accept-remote':\r\n // Keep remote value, update local store\r\n this.store.set(localChange.key, remoteVersion.value)\r\n break\r\n\r\n case 'merge':\r\n // Use merged value\r\n this.store.set(localChange.key, resolution.value)\r\n await this._pushChange({\r\n key: localChange.key,\r\n value: resolution.value,\r\n version: Math.max(localChange.version, remoteVersion.version) + 1,\r\n timestamp: Date.now()\r\n })\r\n break\r\n\r\n case 'discard':\r\n // Do nothing, keep local but don't sync\r\n break\r\n }\r\n }\r\n\r\n /**\r\n * Get current sync state\r\n */\r\n getState(): SyncState {\r\n return {\r\n isOnline: this._isOnline,\r\n isSyncing: this._isSyncing,\r\n lastSyncTimestamp: null, // Could track this\r\n pendingChanges: this.pendingQueue.size,\r\n conflicts: 0 // Could track unresolved conflicts\r\n }\r\n }\r\n\r\n /**\r\n * Subscribe to online status changes\r\n */\r\n onOnlineChange(callback: (online: boolean) => void): () => void {\r\n this.onlineStatusListeners.add(callback)\r\n return () => this.onlineStatusListeners.delete(callback)\r\n }\r\n\r\n /**\r\n * Subscribe to sync state changes\r\n */\r\n onStateChange(callback: (state: SyncState) => void): () => void {\r\n this.syncStateListeners.add(callback)\r\n return () => this.syncStateListeners.delete(callback)\r\n }\r\n\r\n /**\r\n * Force push all pending changes\r\n */\r\n async flush(): Promise<SyncResult> {\r\n return this.sync()\r\n }\r\n\r\n /**\r\n * Destroy the sync engine\r\n */\r\n destroy(): void {\r\n if (this.syncTimer) clearTimeout(this.syncTimer)\r\n this.pendingQueue.clear()\r\n this.onlineStatusListeners.clear()\r\n this.syncStateListeners.clear()\r\n }\r\n}\r\n\r\n/**\r\n * Create a configured SyncEngine instance\r\n */\r\nexport const createSyncEngine = <S extends Record<string, unknown>>(\r\n store: IStore<S>,\r\n config: SyncConfig\r\n): SyncEngine<S> => {\r\n return new SyncEngine(store, config)\r\n}\r\n", "import { useSyncExternalStore, useDebugValue, useMemo, useCallback, useEffect, useState } from \"react\"\r\nimport { createStore } from \"./store\"\r\nimport type { IStore, StoreConfig, PersistOptions, StateUpdater } from \"./types\"\r\nimport { SyncEngine, SyncConfig, SyncState } from \"./sync\"\r\n\r\nlet _defaultStore: IStore<Record<string, unknown>> | null = null\r\n\r\n/**\r\n * Initialize a global store instance.\r\n * @param config Optional store configuration\r\n * @returns IStore instance\r\n * @throws Error if store already exists (prevents accidental overwrites)\r\n */\r\nexport const initState = <S extends Record<string, unknown>>(\r\n config?: StoreConfig<S>\r\n): IStore<S> => {\r\n if (_defaultStore && !config?.namespace) {\r\n if (!config?.silent) {\r\n console.warn(\r\n \"[gState] Store already exists. Pass a unique namespace to create additional stores.\"\r\n )\r\n }\r\n }\r\n\r\n const store = createStore<S>(config)\r\n _defaultStore = store as IStore<Record<string, unknown>>\r\n return store\r\n}\r\n\r\n/**\r\n * Cleanup the global state.\r\n * Safe to call multiple times.\r\n */\r\nexport const destroyState = (): void => {\r\n if (_defaultStore) {\r\n _defaultStore.destroy()\r\n _defaultStore = null\r\n }\r\n}\r\n\r\n/**\r\n * Hook to check if the store has finished hydration.\r\n * @param store Optional store instance\r\n * @returns boolean\r\n */\r\nexport const useIsStoreReady = (store?: IStore<Record<string, unknown>>): boolean => {\r\n const targetStore = store || _defaultStore\r\n\r\n const subscribe = useMemo(() =>\r\n (callback: () => void) => targetStore ? targetStore._subscribe(callback) : () => { },\r\n [targetStore]\r\n )\r\n\r\n return useSyncExternalStore(\r\n subscribe,\r\n () => targetStore ? targetStore.isReady : false,\r\n () => true // SSR is always \"ready\" as it doesn't hydrate from local storage\r\n )\r\n}\r\n\r\n/**\r\n * Get the current default store (for advanced use cases).\r\n * Returns null if no store has been initialized.\r\n */\r\nexport const getStore = (): IStore<Record<string, unknown>> | null => _defaultStore\r\n\r\n/**\r\n * Check if running in a server-side environment.\r\n */\r\nconst _isServer = (): boolean =>\r\n typeof window === 'undefined' ||\r\n typeof window.document === 'undefined'\r\n\r\n/**\r\n * Reactive Hook for state management.\r\n *\r\n * Supports two modes:\r\n * 1. String Key: `useStore('count')` -> Returns [value, setter]\r\n * 2. Type-Safe Selector: `useStore(state => state.count)` -> Returns value (Read-only)\r\n */\r\nexport function useStore<T, S extends Record<string, unknown> = Record<string, unknown>>(\r\n selector: (state: S) => T,\r\n store?: IStore<S>\r\n): T\r\nexport function useStore<T = unknown, S extends Record<string, unknown> = Record<string, unknown>>(\r\n key: string,\r\n store?: IStore<S>\r\n): readonly [T | undefined, (val: T | StateUpdater<T>, options?: PersistOptions) => boolean]\r\nexport function useStore<T = unknown, S extends Record<string, unknown> = Record<string, unknown>>(\r\n keyOrSelector: string | ((state: S) => T),\r\n store?: IStore<S>\r\n): T | readonly [T | undefined, (val: T | StateUpdater<T>, options?: PersistOptions) => boolean] {\r\n // Memoize store reference\r\n const targetStore = useMemo(() =>\r\n (store || _defaultStore) as IStore<S> | null,\r\n [store]\r\n )\r\n\r\n // Ghost store fallback\r\n const ghostStore = useMemo(() => {\r\n const noop = () => { }\r\n const noopFalse = () => false\r\n const noopNull = () => null\r\n return {\r\n set: noopFalse, get: noopNull, remove: noopFalse, delete: noopFalse,\r\n deleteAll: noopFalse, list: () => ({}), compute: noopNull,\r\n watch: () => () => { }, use: noop, transaction: noop, destroy: noop,\r\n _subscribe: () => () => { }, _setSilently: noop, _registerMethod: noop,\r\n _addPlugin: noop, _removePlugin: noop, _getVersion: () => 0,\r\n get isReady() { return false }, whenReady: () => Promise.resolve(),\r\n get plugins() { return {} },\r\n getSnapshot: () => ({} as S), // Ghost snapshot\r\n get namespace() { return \"ghost\" }, get userId() { return undefined }\r\n } as unknown as IStore<S>\r\n }, [])\r\n\r\n const safeStore = targetStore || ghostStore\r\n\r\n const isSelector = typeof keyOrSelector === 'function'\r\n const key = !isSelector ? (keyOrSelector as string) : null\r\n const selector = isSelector ? (keyOrSelector as (state: S) => T) : null\r\n\r\n // 1. Subscribe\r\n const subscribe = useCallback(\r\n (callback: () => void) => {\r\n if (isSelector) {\r\n // Selector mode: subscribe to all changes\r\n return safeStore._subscribe(callback)\r\n } else {\r\n // Key mode: subscribe to key changes\r\n return safeStore._subscribe(callback, key!)\r\n }\r\n },\r\n [safeStore, isSelector, key]\r\n )\r\n\r\n // 2. Get Snapshot (Client)\r\n const getSnapshot = useCallback(() => {\r\n if (isSelector) {\r\n return selector!(safeStore.getSnapshot())\r\n } else {\r\n return safeStore.get<T>(key!) ?? undefined\r\n }\r\n }, [safeStore, isSelector, key, selector])\r\n\r\n // 3. Get Snapshot (Server)\r\n const getServerSnapshot = useCallback(() => {\r\n if (isSelector) {\r\n try { return selector!({} as S) } catch { return undefined }\r\n } else {\r\n return undefined\r\n }\r\n }, [selector, isSelector])\r\n\r\n const value = useSyncExternalStore(\r\n subscribe,\r\n getSnapshot as () => T | undefined, // Cast needed for union types\r\n getServerSnapshot as () => T | undefined\r\n )\r\n\r\n // 4. Setter (Only for Key Mode)\r\n const setter = useCallback(\r\n (val: T | StateUpdater<T>, options?: PersistOptions) => {\r\n if (isSelector) {\r\n if (process.env.NODE_ENV !== 'production') {\r\n console.warn('[gState] Cannot set value when using a selector.')\r\n }\r\n return false\r\n }\r\n return safeStore.set<T>(key!, val, options)\r\n },\r\n [safeStore, isSelector, key]\r\n )\r\n\r\n // Debug value\r\n useDebugValue(value, v => isSelector ? `Selector: ${JSON.stringify(v)}` : `${key}: ${JSON.stringify(v)}`)\r\n\r\n if (isSelector) {\r\n return value as T\r\n }\r\n\r\n return [value, setter] as const\r\n}\r\n\r\n// Store map for sync engines - using any to avoid complex generic issues\r\nconst _syncEngines = new Map<string, SyncEngine<Record<string, unknown>>>()\r\n\r\n/**\r\n * Initialize sync engine for a store\r\n * @param store - The store to sync\r\n * @param config - Sync configuration\r\n * @returns SyncEngine instance\r\n */\r\nexport const initSync = (\r\n store: IStore<Record<string, unknown>>,\r\n config: SyncConfig\r\n): SyncEngine<Record<string, unknown>> => {\r\n const key = store.namespace\r\n if (_syncEngines.has(key)) {\r\n console.warn(`[gState] Sync engine already exists for namespace \"${key}\". Call destroySync first.`)\r\n return _syncEngines.get(key)!\r\n }\r\n\r\n const engine = new SyncEngine(store, config)\r\n _syncEngines.set(key, engine)\r\n return engine\r\n}\r\n\r\n/**\r\n * Destroy sync engine for a namespace\r\n */\r\nexport const destroySync = (namespace: string): void => {\r\n const engine = _syncEngines.get(namespace)\r\n if (engine) {\r\n engine.destroy()\r\n _syncEngines.delete(namespace)\r\n }\r\n}\r\n\r\n/**\r\n * Hook for synchronized state management.\r\n * Provides offline-by-default functionality with automatic sync.\r\n *\r\n * @param key - State key\r\n * @param store - Optional store instance (uses default if not provided)\r\n * @returns [value, setter, syncState]\r\n *\r\n * @example\r\n * const [count, setCount, syncState] = useSyncedState('count')\r\n *\r\n * // syncState contains:\r\n * // - isOnline: boolean\r\n * // - isSyncing: boolean\r\n * // - pendingChanges: number\r\n * // - conflicts: number\r\n */\r\nexport function useSyncedState<T = unknown>(\r\n key: string,\r\n store?: IStore<Record<string, unknown>>\r\n): readonly [\r\n T | undefined,\r\n (val: T | StateUpdater<T>, options?: PersistOptions) => boolean,\r\n SyncState\r\n] {\r\n const targetStore = store || _defaultStore\r\n const namespace = targetStore?.namespace || 'default'\r\n\r\n // Get or create sync engine\r\n const engine = _syncEngines.get(namespace)\r\n\r\n // Use useStore with any cast to handle generics\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n const result = useStore(key, targetStore as any) as readonly [T | undefined, (val: any, options?: PersistOptions) => boolean]\r\n const value = result[0] as T | undefined\r\n const setter = result[1]\r\n\r\n // Track sync state\r\n const [syncState, setSyncState] = useState<SyncState>(() => engine?.getState() || {\r\n isOnline: true,\r\n isSyncing: false,\r\n lastSyncTimestamp: null,\r\n pendingChanges: 0,\r\n conflicts: 0\r\n })\r\n\r\n // Subscribe to sync state changes\r\n useEffect(() => {\r\n if (!engine) return\r\n\r\n const unsubscribe = engine.onStateChange(setSyncState)\r\n return unsubscribe\r\n }, [engine])\r\n\r\n // Wrapper setter that queues changes for sync\r\n const syncedSetter = useCallback(\r\n (val: T | StateUpdater<T>, options?: PersistOptions) => {\r\n const result = setter(val, options)\r\n\r\n if (result && engine) {\r\n // Get the current value and queue for sync\r\n const currentValue = targetStore?.get(key)\r\n engine.queueChange(key, currentValue)\r\n }\r\n\r\n return result\r\n },\r\n [setter, engine, key, targetStore]\r\n )\r\n\r\n return [value, syncedSetter, syncState] as const\r\n}\r\n\r\n/**\r\n * Hook to get global sync status\r\n *\r\n * @example\r\n * const status = useSyncStatus()\r\n * // status.isOnline, status.isSyncing, status.pendingChanges\r\n */\r\nexport const useSyncStatus = (): SyncState => {\r\n const [state, setState] = useState<SyncState>({\r\n isOnline: true,\r\n isSyncing: false,\r\n lastSyncTimestamp: null,\r\n pendingChanges: 0,\r\n conflicts: 0\r\n })\r\n\r\n useEffect(() => {\r\n // Aggregate state from all sync engines\r\n const updateState = () => {\r\n let isOnline = true\r\n let isSyncing = false\r\n let pendingChanges = 0\r\n let conflicts = 0\r\n\r\n _syncEngines.forEach(engine => {\r\n const s = engine.getState()\r\n isOnline = isOnline && s.isOnline\r\n isSyncing = isSyncing || s.isSyncing\r\n pendingChanges += s.pendingChanges\r\n conflicts += s.conflicts\r\n })\r\n\r\n setState({\r\n isOnline,\r\n isSyncing,\r\n lastSyncTimestamp: null,\r\n pendingChanges,\r\n conflicts\r\n })\r\n }\r\n\r\n updateState()\r\n\r\n // Subscribe to all engines\r\n const unsubscribes = Array.from(_syncEngines.values()).map(engine =>\r\n engine.onStateChange(updateState)\r\n )\r\n\r\n return () => unsubscribes.forEach(fn => fn())\r\n }, [])\r\n\r\n return state\r\n}\r\n\r\n/**\r\n * Trigger manual sync for a specific namespace\r\n */\r\nexport const triggerSync = async (namespace?: string): Promise<void> => {\r\n const targetNamespace = namespace || _defaultStore?.namespace\r\n if (!targetNamespace) return\r\n\r\n const engine = _syncEngines.get(targetNamespace)\r\n if (engine) {\r\n await engine.flush()\r\n }\r\n}\r\n", "import { createStore } from \"./store\"\r\nimport type { IStore, AsyncState } from \"./types\"\r\n\r\n/**\r\n * Creates an async store that automatically manages the data/loading/error lifecycle.\r\n * @template T The type of data being fetched\r\n * @param resolver - Async function that returns the data\r\n * @param options - Configuration options\r\n * @returns Store instance with execute method\r\n *\r\n * @example\r\n * const store = createAsyncStore(async () => {\r\n * const response = await fetch('/api/data');\r\n * return response.json();\r\n * }, { key: 'userData', persist: true });\r\n *\r\n * // Execute the fetch\r\n * await store.execute();\r\n *\r\n * // Use in React\r\n * const { data, loading, error } = store.get('userData');\r\n */\r\nexport const createAsyncStore = <T>(\r\n resolver: () => Promise<T>,\r\n options?: { key?: string, persist?: boolean, store?: IStore<Record<string, AsyncState<T>>> }\r\n): IStore<Record<string, AsyncState<T>>> & { execute: () => Promise<void> } => {\r\n /**\r\n * Key used to store the async state in the store\r\n */\r\n const key = options?.key || 'async_data'\r\n\r\n /**\r\n * Store instance - uses existing or creates new one\r\n */\r\n const store = options?.store || createStore<Record<string, AsyncState<T>>>({\r\n namespace: `async_${key}`,\r\n silent: true\r\n })\r\n\r\n // Initial State if not present\r\n if (store.get(key) == null) {\r\n store.set(key, { data: null, loading: false, error: null, updatedAt: null })\r\n }\r\n\r\n /**\r\n * Executes the async resolver and updates store state\r\n */\r\n const run = async () => {\r\n const current = store.get(key) as AsyncState<T> | null\r\n store.set(key, {\r\n ...(current || { data: null, loading: false, error: null, updatedAt: null }),\r\n loading: true,\r\n error: null\r\n })\r\n\r\n // Wait for store to be ready if it's hydrating\r\n if ('whenReady' in store && !store.isReady) await store.whenReady()\r\n\r\n try {\r\n const result = await resolver()\r\n const prev = store.get(key) as AsyncState<T> | null\r\n store.set(key, {\r\n ...(prev || { data: null, loading: false, error: null, updatedAt: null }),\r\n data: result,\r\n loading: false,\r\n updatedAt: Date.now()\r\n }, { persist: options?.persist })\r\n } catch (e: unknown) {\r\n const prev = store.get(key) as AsyncState<T> | null\r\n store.set(key, {\r\n ...(prev || { data: null, loading: false, error: null, updatedAt: null }),\r\n error: e instanceof Error ? e : new Error(String(e)),\r\n loading: false\r\n })\r\n }\r\n }\r\n\r\n return Object.assign(store, { execute: run })\r\n}\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Immer Plugin: Adds syntactic sugar for functional updates.\r\n * Leverages the core's native Immer support.\r\n * @returns IPlugin\r\n */\r\nexport const immerPlugin = <S extends Record<string, unknown>>(): IPlugin<S> => ({\r\n name: 'gstate-immer',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n // Add sugar method to store instance using the formal registration API\r\n store._registerMethod('immer', 'setWithProduce', ((key: string, updater: (draft: unknown) => void) => {\r\n return store.set(key, updater)\r\n }) as (...args: unknown[]) => unknown)\r\n }\r\n }\r\n})\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Undo/Redo Plugin: Multi-level history management for the store.\r\n * Snapshots the entire store state for simple, robust rollbacks.\r\n * @param options Configuration for history limit\r\n * @returns IPlugin\r\n */\r\nexport const undoRedoPlugin = <S extends Record<string, unknown>>(options?: { limit?: number }): IPlugin<S> => {\r\n /** History array storing snapshots of store state */\r\n let _history: Record<string, unknown>[] = []\r\n /** Current position in the history array */\r\n let _cursor = -1\r\n /** Flag to prevent recording changes during restore operations */\r\n let _isRestoring = false\r\n\r\n /** Maximum number of history snapshots to keep */\r\n const _limit = options?.limit || 50\r\n\r\n return {\r\n name: 'gstate-undo-redo',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n // Initial Snapshot (Baseline)\r\n _history.push(store.list())\r\n _cursor = 0\r\n\r\n // Formally register methods via the core API with explicit plugin name\r\n store._registerMethod('undoRedo', 'undo', () => {\r\n if (_cursor > 0) {\r\n _isRestoring = true\r\n _cursor--\r\n const snapshot = _history[_cursor]\r\n if (!snapshot) return false\r\n\r\n // Restore snapshot using the silent internal API\r\n Object.entries(snapshot).forEach(([k, v]) => {\r\n store._setSilently(k, v)\r\n })\r\n\r\n _isRestoring = false\r\n return true\r\n }\r\n return false\r\n })\r\n\r\n store._registerMethod('undoRedo', 'redo', () => {\r\n if (_cursor < _history.length - 1) {\r\n _isRestoring = true\r\n _cursor++\r\n const snapshot = _history[_cursor]\r\n if (!snapshot) return false\r\n\r\n Object.entries(snapshot).forEach(([k, v]) => {\r\n store._setSilently(k, v)\r\n })\r\n\r\n _isRestoring = false\r\n return true\r\n }\r\n return false\r\n })\r\n\r\n store._registerMethod('undoRedo', 'canUndo', () => _cursor > 0)\r\n store._registerMethod('undoRedo', 'canRedo', () => _cursor < _history.length - 1)\r\n },\r\n\r\n onSet: ({ store }) => {\r\n if (_isRestoring) return\r\n\r\n // Wipe forward history on new manual change\r\n if (_cursor < _history.length - 1) {\r\n _history = _history.slice(0, _cursor + 1)\r\n }\r\n\r\n // Push new snapshot\r\n _history.push(store.list())\r\n\r\n if (_history.length > _limit) {\r\n _history.shift()\r\n } else {\r\n _cursor++\r\n }\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Schema Plugin: Validates state changes against a validator function.\r\n * @param schemas Map of keys to validation functions\r\n * @returns IPlugin\r\n */\r\nexport const schemaPlugin = (schemas: Record<string, (val: unknown) => boolean | string>): IPlugin => ({\r\n name: 'gstate-schema',\r\n hooks: {\r\n onSet: ({ key, value }) => {\r\n if (!key) return\r\n const validator = schemas[key]\r\n\r\n if (validator) {\r\n const result = validator(value)\r\n\r\n if (result !== true) {\r\n throw new Error(`[Schema Error] Validation failed for key \"${key}\": ${result === false ? 'Invalid type' : result}`)\r\n }\r\n }\r\n }\r\n }\r\n})\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Redux DevTools extension interface\r\n */\r\ninterface DevToolsExtension {\r\n /** Connects to the DevTools extension */\r\n connect: (options: { name: string }) => DevToolsInstance\r\n}\r\n\r\n/**\r\n * Redux DevTools instance interface\r\n */\r\ninterface DevToolsInstance {\r\n /** Initializes the DevTools with initial state */\r\n init: (state: Record<string, unknown>) => void\r\n /** Sends an action to the DevTools */\r\n send: (action: string, state: Record<string, unknown>) => void\r\n}\r\n\r\n/**\r\n * DevTools Plugin: Connects the store to Redux DevTools.\r\n * @param options Configuration for the extension\r\n * @returns IPlugin\r\n */\r\nexport const devToolsPlugin = (options?: { name?: string }): IPlugin => {\r\n const ext = globalThis as unknown\r\n const global = ext as Record<string, unknown>\r\n const extension = global.__REDUX_DEVTOOLS_EXTENSION__ as DevToolsExtension | undefined\r\n\r\n if (!extension?.connect) {\r\n return { name: 'gstate-devtools-noop', hooks: {} }\r\n }\r\n\r\n /** Reference to the DevTools instance */\r\n let _devTools: DevToolsInstance | null = null\r\n\r\n return {\r\n name: 'gstate-devtools',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n _devTools = extension.connect({ name: options?.name || 'Magnetar Store' })\r\n _devTools.init(store.list())\r\n },\r\n onSet: ({ key, store }) => {\r\n if (!key || !_devTools) return\r\n // Send full state to DevTools to enable time-travel/snapshots\r\n _devTools.send(`SET_${key.toUpperCase()}`, store.list())\r\n },\r\n onRemove: ({ key, store }) => {\r\n if (!key || !_devTools) return\r\n _devTools.send(`REMOVE_${key.toUpperCase()}`, store.list())\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Snapshot Plugin: Allows taking and restoring full store snapshots manually.\r\n * @returns IPlugin\r\n */\r\nexport const snapshotPlugin = (): IPlugin => {\r\n /** Internal storage for snapshots */\r\n const _snapshots = new Map<string, unknown>()\r\n\r\n return {\r\n name: 'gstate-snapshot',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n store._registerMethod('snapshot', 'takeSnapshot', ((name: string) => {\r\n _snapshots.set(name, store.list())\r\n }) as (...args: unknown[]) => unknown)\r\n\r\n store._registerMethod('snapshot', 'restoreSnapshot', ((name: string) => {\r\n const snap = _snapshots.get(name)\r\n if (!snap) return false\r\n\r\n store.transaction(() => {\r\n Object.entries(snap).forEach(([k, v]) => {\r\n store.set(k, v)\r\n })\r\n })\r\n return true\r\n }) as (...args: unknown[]) => unknown)\r\n\r\n store._registerMethod('snapshot', 'listSnapshots', (() => Array.from(_snapshots.keys())) as (...args: unknown[]) => unknown)\r\n store._registerMethod('snapshot', 'deleteSnapshot', ((name: string) => _snapshots.delete(name)) as (...args: unknown[]) => unknown)\r\n store._registerMethod('snapshot', 'clearSnapshots', (() => _snapshots.clear()) as (...args: unknown[]) => unknown)\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Guard Plugin: Intercepts values before they hit the store.\r\n * @param guards Map of keys to guard/transform functions\r\n * @returns IPlugin\r\n */\r\nexport const guardPlugin = (guards: Record<string, (val: unknown) => unknown>): IPlugin => ({\r\n name: 'gstate-guard',\r\n hooks: {\r\n onBeforeSet: ({ key, value, store: _store }) => {\r\n if (!key) return\r\n const guard = guards[key]\r\n\r\n if (guard) {\r\n const transformed = guard(value)\r\n\r\n // Note: Core currently doesn't support value interception for transformation\r\n // in onBeforeSet, but this serves as a placeholder for validation/logging.\r\n if (transformed !== value) {\r\n // Future: core.set could accept the transformed value\r\n }\r\n }\r\n }\r\n }\r\n})\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Analytics Plugin: Tracks state changes and sends them to a provider.\r\n * @param options Provider and filtering configuration\r\n * @returns IPlugin\r\n */\r\nexport const analyticsPlugin = (options: {\r\n provider: (event: { key: string, value: unknown, action: string }) => void,\r\n keys?: string[]\r\n}): IPlugin => ({\r\n name: 'gstate-analytics',\r\n hooks: {\r\n onSet: ({ key, value }) => {\r\n if (!key) return\r\n if (!options.keys || options.keys.includes(key)) {\r\n options.provider({ key, value, action: 'SET' })\r\n }\r\n },\r\n onRemove: ({ key }) => {\r\n if (!key) return\r\n if (!options.keys || options.keys.includes(key)) {\r\n options.provider({ key, value: null, action: 'REMOVE' })\r\n }\r\n }\r\n }\r\n})\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Sync Plugin: Synchronizes state across multiple browser tabs.\r\n * @param options Configuration for the broadcast channel\r\n * @returns IPlugin\r\n */\r\nexport const syncPlugin = (options?: { channelName?: string }): IPlugin => {\r\n /** BroadcastChannel for cross-tab communication */\r\n const _channel = new BroadcastChannel(options?.channelName || 'gstate_sync')\r\n\r\n /** Flag to prevent infinite loops when syncing from other tabs */\r\n let _isSyncing = false\r\n\r\n return {\r\n name: 'gstate-sync',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n _channel.onmessage = (event) => {\r\n const { key, value, action } = event.data\r\n if (!key) return\r\n _isSyncing = true\r\n if (action === 'REMOVE') {\r\n store.remove(key)\r\n } else {\r\n store.set(key, value)\r\n }\r\n _isSyncing = false\r\n }\r\n },\r\n onSet: ({ key, value }) => {\r\n if (!key || _isSyncing) return\r\n _channel.postMessage({ key, value, action: 'SET' })\r\n },\r\n onRemove: ({ key }) => {\r\n if (!key || _isSyncing) return\r\n _channel.postMessage({ key, action: 'REMOVE' })\r\n },\r\n onDestroy: () => {\r\n _channel.close()\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin } from '../../core/types'\r\n\r\n/**\r\n * Debug Plugin: Exposes the store to the browser console.\r\n * \u26A0\uFE0F FOR DEV/DEBUG ONLY - Never use in production!\r\n *\r\n * @example\r\n * ```typescript\r\n * if (process.env.NODE_ENV === 'development') {\r\n * store._addPlugin(debugPlugin())\r\n * }\r\n *\r\n * // In browser console:\r\n * > gstate.list()\r\n * > gstate.get('myKey')\r\n * > gstate.set('myKey', 'newValue')\r\n * ```\r\n */\r\nexport const debugPlugin = (): IPlugin => {\r\n // Security: Only run in development\r\n if (process.env.NODE_ENV === 'production') {\r\n return { name: 'gstate-debug-noop', hooks: {} }\r\n }\r\n\r\n const isDev = process.env.NODE_ENV !== 'production'\r\n\r\n const debugLog = (...args: unknown[]) => {\r\n if (isDev) console.debug(...args)\r\n }\r\n\r\n return {\r\n name: 'gstate-debug',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n // Expose store to global window object for console access\r\n if (typeof window !== 'undefined') {\r\n (window as unknown as Record<string, unknown>).gstate = {\r\n /** Get all state */\r\n list: () => {\r\n return store.list()\r\n },\r\n /** Get a specific key */\r\n get: (key: string) => {\r\n const val = store.get(key)\r\n debugLog(`[gState] get('${key}'):`, val)\r\n return val\r\n },\r\n /** Set a value */\r\n set: (key: string, value: unknown) => {\r\n const result = store.set(key, value)\r\n debugLog(`[gState] set('${key}', ${JSON.stringify(value)}):`, result)\r\n return result\r\n },\r\n /** Watch a key */\r\n watch: (key: string, callback: (val: unknown) => void) => {\r\n const unwatch = store.watch(key, callback)\r\n debugLog(`[gState] watching '${key}'`)\r\n return unwatch\r\n },\r\n /** Get store info */\r\n info: () => {\r\n const info = {\r\n namespace: store.namespace,\r\n isReady: store.isReady,\r\n keys: Object.keys(store.list()),\r\n size: Object.keys(store.list()).length\r\n }\r\n debugLog('[gState] Store Info:', info)\r\n return info\r\n },\r\n /** Clear console and show banner */\r\n banner: () => {\r\n debugLog(`\r\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\r\n\u2551 \uD83E\uDDF2 gState Debug \u2551\r\n\u2551 Type: gstate.list() \u2551\r\n\u2551 gstate.get(key) \u2551\r\n\u2551 gstate.set(key, value) \u2551\r\n\u2551 gstate.info() \u2551\r\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\r\n `)\r\n }\r\n }\r\n\r\n // Auto-show banner on install\r\n debugLog('[gState] Debug plugin installed. Type gstate.banner() for help.')\r\n }\r\n },\r\n onDestroy: () => {\r\n // Cleanup global reference\r\n if (typeof window !== 'undefined') {\r\n delete (window as unknown as Record<string, unknown>).gstate\r\n }\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin, PluginContext } from '../../core/types'\r\n\r\n/**\r\n * IndexedDB Plugin for RGS\r\n * Allows storing large amounts of data (GBs) by leveraging IndexedDB.\r\n * This plugin can be used as a replacement for standard localStorage persistence.\r\n */\r\n\r\nexport interface IndexedDBOptions {\r\n dbName?: string\r\n storeName?: string\r\n version?: number\r\n}\r\n\r\nexport const indexedDBPlugin = <S extends Record<string, unknown>>(options: IndexedDBOptions = {}): IPlugin<S> => {\r\n const dbName = options.dbName || 'rgs-db'\r\n const storeName = options.storeName || 'states'\r\n const dbVersion = options.version || 1\r\n let db: IDBDatabase | null = null\r\n\r\n const getDB = (): Promise<IDBDatabase> => {\r\n return new Promise((resolve, reject) => {\r\n if (db) return resolve(db)\r\n const request = indexedDB.open(dbName, dbVersion)\r\n request.onerror = () => reject(request.error)\r\n request.onsuccess = () => {\r\n db = request.result\r\n resolve(db)\r\n }\r\n request.onupgradeneeded = (event: IDBVersionChangeEvent) => {\r\n const database = (event.target as IDBOpenDBRequest).result\r\n if (!database.objectStoreNames.contains(storeName)) {\r\n database.createObjectStore(storeName)\r\n }\r\n }\r\n })\r\n }\r\n\r\n const save = async (key: string, value: unknown) => {\r\n const database = await getDB()\r\n return new Promise<void>((resolve, reject) => {\r\n const tx = database.transaction(storeName, 'readwrite')\r\n const store = tx.objectStore(storeName)\r\n const request = store.put(value, key)\r\n request.onsuccess = () => resolve()\r\n request.onerror = () => reject(request.error)\r\n })\r\n }\r\n\r\n const load = async (key: string): Promise<unknown> => {\r\n const database = await getDB()\r\n return new Promise((resolve, reject) => {\r\n const tx = database.transaction(storeName, 'readonly')\r\n const store = tx.objectStore(storeName)\r\n const request = store.get(key)\r\n request.onsuccess = () => resolve(request.result)\r\n request.onerror = () => reject(request.error)\r\n })\r\n }\r\n\r\n const remove = async (key: string) => {\r\n const database = await getDB()\r\n return new Promise<void>((resolve, reject) => {\r\n const tx = database.transaction(storeName, 'readwrite')\r\n const store = tx.objectStore(storeName)\r\n const request = store.delete(key)\r\n request.onsuccess = () => resolve()\r\n request.onerror = () => reject(request.error)\r\n })\r\n }\r\n\r\n return {\r\n name: 'indexedDB',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n // Register utility methods\r\n store._registerMethod('indexedDB', 'clear', async () => {\r\n const database = await getDB()\r\n const tx = database.transaction(storeName, 'readwrite')\r\n tx.objectStore(storeName).clear()\r\n })\r\n },\r\n\r\n onInit: async ({ store }) => {\r\n // Hydrate from IndexedDB\r\n // We look for all keys that start with the store namespace\r\n const database = await getDB()\r\n const tx = database.transaction(storeName, 'readonly')\r\n const objectStore = tx.objectStore(storeName)\r\n const request = objectStore.getAllKeys()\r\n\r\n request.onsuccess = async () => {\r\n const keys = request.result as string[]\r\n const prefix = (store as import('../../core/types').IStore<S>).namespace + '_'\r\n\r\n for (const key of keys) {\r\n if (key.startsWith(prefix)) {\r\n const val = await load(key)\r\n if (val) {\r\n const storeKey = key.substring(prefix.length);\r\n // Use a silent set to avoid re-triggering persistence during hydration\r\n (store as import('../../core/types').IStore<S>)._setSilently(storeKey, (val as { d: unknown }).d)\r\n }\r\n }\r\n }\r\n }\r\n },\r\n\r\n onSet: async ({ key, value, store }) => {\r\n if (!key) return\r\n const prefix = (store as import('../../core/types').IStore<S>).namespace + '_'\r\n // We wrap the value in a structure similar to what RGS does for storage\r\n const data = {\r\n d: value,\r\n t: Date.now(),\r\n v: (store as import('../../core/types').IStore<S>)._getVersion?.(key) || 1\r\n }\r\n await save(`${prefix}${key}`, data)\r\n },\r\n\r\n onRemove: async ({ key, store }) => {\r\n if (!key) return\r\n const prefix = (store as import('../../core/types').IStore<S>).namespace + '_'\r\n await remove(`${prefix}${key}`)\r\n }\r\n }\r\n }\r\n}\r\n", "import type { IPlugin, PluginContext } from '../../core/types'\r\n\r\n/**\r\n * Sync Stats interface for reporting and analytics.\r\n */\r\nexport interface SyncStats {\r\n lastSyncTimestamp: number | null\r\n totalKeysSynced: number\r\n totalBytesSynced: number\r\n syncCount: number\r\n lastDuration: number\r\n errors: number\r\n}\r\n\r\n/**\r\n * Cloud Adapter interface.\r\n * Implement this to support different backends (MongoDB, Firebase, SQL, etc.)\r\n */\r\nexport interface CloudSyncAdapter {\r\n name: string\r\n /**\r\n * Save dirty keys to the remote database\r\n * @param data Object containing key-value pairs to sync\r\n */\r\n save: (data: Record<string, unknown>) => Promise<boolean>\r\n}\r\n\r\nexport interface CloudSyncOptions {\r\n adapter: CloudSyncAdapter\r\n autoSyncInterval?: number // ms (e.g. 60000 for 1 minute)\r\n onSync?: (stats: SyncStats) => void\r\n}\r\n\r\n/**\r\n * Cloud Sync Plugin for RGS\r\n * Allows on-demand or scheduled synchronization of local state to a remote database.\r\n * Uses internal versioning to only sync modified data (Differential Sync).\r\n */\r\nexport const cloudSyncPlugin = <S extends Record<string, unknown>>(options: CloudSyncOptions): IPlugin<S> => {\r\n const { adapter, autoSyncInterval } = options\r\n\r\n // Track last synced version for each key to perform differential sync\r\n const lastSyncedVersions = new Map<string, number>()\r\n const stats: SyncStats = {\r\n lastSyncTimestamp: null,\r\n totalKeysSynced: 0,\r\n totalBytesSynced: 0,\r\n syncCount: 0,\r\n lastDuration: 0,\r\n errors: 0\r\n }\r\n\r\n let timer: ReturnType<typeof setInterval> | null = null\r\n\r\n return {\r\n name: 'cloudSync',\r\n hooks: {\r\n onInstall: ({ store }) => {\r\n /**\r\n * Manual Sync Method\r\n * Triggers a differential sync to the cloud.\r\n */\r\n store._registerMethod('cloudSync', 'sync', async () => {\r\n const startTime = performance.now()\r\n const dirtyData: Record<string, unknown> = {}\r\n let bytesCount = 0\r\n\r\n try {\r\n const allData = store.list()\r\n const keys = Object.keys(allData)\r\n\r\n for (const key of keys) {\r\n const currentVersion = (store as import('../../core/types').IStore<S>)._getVersion?.(key) || 0\r\n const lastVersion = lastSyncedVersions.get(key) || 0\r\n\r\n if (currentVersion > lastVersion) {\r\n const val = allData[key]\r\n dirtyData[key] = val\r\n bytesCount += JSON.stringify(val).length // Rough byte estimation\r\n lastSyncedVersions.set(key, currentVersion)\r\n }\r\n }\r\n\r\n if (Object.keys(dirtyData).length === 0) return { status: 'no-change', stats }\r\n\r\n const success = await adapter.save(dirtyData)\r\n\r\n if (success) {\r\n stats.lastSyncTimestamp = Date.now()\r\n stats.totalKeysSynced += Object.keys(dirtyData).length\r\n stats.totalBytesSynced += bytesCount\r\n stats.syncCount++\r\n stats.lastDuration = performance.now() - startTime\r\n if (options.onSync) options.onSync(stats)\r\n return { status: 'success', stats }\r\n } else {\r\n throw new Error(`Adapter ${adapter.name} failed to save.`)\r\n }\r\n } catch (err) {\r\n stats.errors++\r\n console.error(`[gState] Cloud Sync Failed (${adapter.name}):`, err)\r\n return { status: 'error', error: String(err), stats }\r\n }\r\n })\r\n\r\n /**\r\n * Get Stats Method\r\n */\r\n store._registerMethod('cloudSync', 'getStats', () => stats)\r\n\r\n // Start Auto-Sync Timer if configured\r\n if (autoSyncInterval && autoSyncInterval > 0) {\r\n timer = setInterval(() => {\r\n const plugins = (store as import('../../core/types').IStore<S>).plugins\r\n const cs = plugins.cloudSync as unknown as { sync: () => Promise<unknown> }\r\n if (cs) cs.sync()\r\n }, autoSyncInterval)\r\n }\r\n },\r\n\r\n onDestroy: () => {\r\n if (timer) clearInterval(timer)\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * --- CLOUD ADAPTER TEMPLATES ---\r\n */\r\n\r\n/**\r\n * Template for MongoDB (REST API / Atlas Data API)\r\n */\r\nexport const createMongoAdapter = (apiUrl: string, apiKey: string): CloudSyncAdapter => ({\r\n name: 'MongoDB-Atlas',\r\n save: async (data: Record<string, unknown>) => {\r\n const response = await fetch(`${apiUrl}/action/updateOne`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json', 'api-key': apiKey },\r\n body: JSON.stringify({\r\n dataSource: 'Cluster0',\r\n database: 'rgs_cloud',\r\n collection: 'user_states',\r\n filter: { id: 'global_state' }, // Or specific user ID\r\n update: { $set: { data, updatedAt: Date.now() } },\r\n upsert: true\r\n })\r\n })\r\n return response.ok\r\n }\r\n})\r\n\r\n/**\r\n * Template for Firebase Firestore\r\n */\r\nexport const createFirestoreAdapter = (db: unknown, docPath: string): CloudSyncAdapter => ({\r\n name: 'Firebase-Firestore',\r\n save: async (data: Record<string, unknown>) => {\r\n // Assuming Firebase SDK is already initialized\r\n try {\r\n // In a real scenario, you'd use updateDoc from firebase/firestore\r\n // await updateDoc(doc(db, docPath), { ...data, updatedAt: serverTimestamp() });\r\n const isDev = process.env.NODE_ENV !== 'production'\r\n const debugLog = (...args: unknown[]) => { if (isDev) console.debug(...args) }\r\n\r\n // await updateDoc(doc(db, docPath), { ...data, updatedAt: serverTimestamp() });\r\n debugLog('[Mock] Firestore Syncing:', data)\r\n return true\r\n } catch (e) {\r\n return false\r\n }\r\n }\r\n})\r\n\r\n/**\r\n * Template for generic SQL/PostgreSQL (via standard REST API)\r\n */\r\nexport const createSqlRestAdapter = (endpoint: string, authToken: string): CloudSyncAdapter => ({\r\n name: 'SQL-REST-API',\r\n save: async (data: Record<string, unknown>) => {\r\n const response = await fetch(endpoint, {\r\n method: 'PATCH',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'Authorization': `Bearer ${authToken}`\r\n },\r\n body: JSON.stringify(data)\r\n })\r\n return response.ok\r\n }\r\n})\r\n", "/**\n * Argis (RGS) - Reactive Global State - Official Plugins\n * Performance-optimized extensions for the core engine.\n */\n\nexport { immerPlugin } from \"./official/immer.plugin\"\nexport { undoRedoPlugin } from \"./official/undo-redo.plugin\"\nexport { schemaPlugin } from \"./official/schema.plugin\"\nexport { devToolsPlugin } from \"./official/devtools.plugin\"\nexport { snapshotPlugin } from \"./official/snapshot.plugin\"\nexport { guardPlugin } from \"./official/guard.plugin\"\nexport { analyticsPlugin } from \"./official/analytics.plugin\"\nexport { syncPlugin } from \"./official/sync.plugin\"\nexport { debugPlugin } from \"./official/debug.plugin\"\nexport { indexedDBPlugin } from \"./official/indexeddb.plugin\"\nexport {\n cloudSyncPlugin,\n createMongoAdapter,\n createFirestoreAdapter,\n createSqlRestAdapter\n} from \"./official/cloud-sync.plugin\"\n\nimport type { PluginContext, IPlugin } from \"../core/types\"\n\n/**\n * Official Logger Plugin: Professional change tracking.\n * @param options Styling options for the logger\n * @returns IPlugin\n */\nexport const loggerPlugin = <S extends Record<string, unknown>>(options?: { collapsed?: boolean }): IPlugin<S> => ({\n name: 'gstate-logger',\n hooks: {\n onSet: ({ key, value, version }: PluginContext<S>) => {\n const\n time = new Date().toLocaleTimeString(),\n groupLabel = `[gState] SET: ${key} (v${version}) @ ${time}`\n\n if (options?.collapsed) console.groupCollapsed(groupLabel)\n else console.group(groupLabel)\n\n console.info('%c Value:', 'color: #4CAF50; font-weight: bold;', value)\n console.groupEnd()\n },\n onRemove: ({ key }) => {\n console.warn(`[gState] REMOVED: ${key}`)\n },\n onTransaction: ({ key }) => {\n if (key === 'START') console.group('\u2500\u2500 TRANSACTION START \u2500\u2500')\n else console.groupEnd()\n }\n }\n})\n", "/**\r\n * Argis (RGS) - Reactive Global State\r\n * Simple, secure, scalable state management for React\r\n *\r\n * @see https://github.com/dpassariello/rgs\r\n */\r\n\r\nimport { createStore as baseCreateStore } from \"./core/store\"\r\nimport { useStore as baseUseStore, getStore } from \"./core/hooks\"\r\nimport * as Security from \"./core/security\"\r\nimport type { IStore, StoreConfig } from \"./core/types\"\r\n\r\n// ============================================================================\r\n// Core API - The Magnetar Way\r\n// ============================================================================\r\n\r\n/**\r\n * Creates a reactive store with a built-in hook.\r\n * This is the primary entry point for RGS - \"The Magnetar Way\".\r\n *\r\n * @param initialState - Initial state object\r\n * @param configOrNamespace - String for namespace (enables persistence) or full StoreConfig\r\n */\r\nexport const gstate = <S extends Record<string, unknown>>(\r\n initialState: S,\r\n configOrNamespace?: string | StoreConfig<S>\r\n) => {\r\n const config = typeof configOrNamespace === 'string'\r\n ? { namespace: configOrNamespace }\r\n : configOrNamespace\r\n\r\n // Initialize core store\r\n const store = baseCreateStore<S>(config)\r\n\r\n // Initialize state if store is empty or needs defaults\r\n if (initialState) {\r\n Object.entries(initialState).forEach(([k, v]) => {\r\n // Only set if not already hydrated/loaded from storage\r\n if (store.get(k) === null) {\r\n store._setSilently(k, v)\r\n }\r\n })\r\n }\r\n\r\n // Magic function that returns a typed hook when called with a key\r\n const magic = <K extends keyof S>(key: K) => baseUseStore<S[K], S>(key as string, store)\r\n\r\n // Expose as global for debugging purposes in dev environments\r\n if (typeof window !== 'undefined') {\r\n (window as unknown as Record<string, unknown>).gState = store;\r\n (window as unknown as Record<string, unknown>).rgs = store\r\n }\r\n\r\n return Object.assign(magic, store) as IStore<S> & (<K extends keyof S>(key: K) => readonly [S[K] | undefined, (val: S[K] | ((draft: S[K]) => S[K]), options?: unknown) => boolean])\r\n}\r\n\r\nexport { baseCreateStore as createStore }\r\n\r\nexport {\r\n useStore,\r\n useIsStoreReady,\r\n initState,\r\n getStore,\r\n destroyState,\r\n useStore as useGState,\r\n useStore as useSimpleState\r\n} from \"./core/hooks\"\r\n\r\nexport { createAsyncStore } from \"./core/async\"\r\n\r\n// ============================================================================\r\n// Local-First Sync Engine\r\n// ============================================================================\r\n\r\nexport { SyncEngine, createSyncEngine } from \"./core/sync\"\r\nexport type {\r\n SyncConfig,\r\n SyncState,\r\n SyncResult,\r\n SyncStrategy,\r\n ConflictInfo,\r\n ConflictResolution\r\n} from \"./core/sync\"\r\n\r\nexport { initSync, destroySync, useSyncedState, useSyncStatus, triggerSync } from \"./core/hooks\"\r\n\r\n// ============================================================================\r\n// Plugins\r\n// ============================================================================\r\n\r\nexport * from \"./plugins/index\"\r\n\r\n// ============================================================================\r\n// Security & Compliance (Unified)\r\n// ============================================================================\r\n\r\n// Stateless Utilities\r\nexport {\r\n generateEncryptionKey,\r\n exportKey,\r\n importKey,\r\n isCryptoAvailable,\r\n setAuditLogger,\r\n logAudit,\r\n validateKey,\r\n sanitizeValue\r\n} from \"./core/security\"\r\n\r\n// Store-aware Wrappers for Global Convenience\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const addAccessRule = (pattern: string | ((key: string, userId?: string) => boolean), perms: Security.Permission[]) => getStore()?.addAccessRule(pattern, perms)\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const hasPermission = (key: string, action: Security.Permission, uid?: string) => getStore()?.hasPermission(key, action, uid) ?? true\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const recordConsent = (uid: string, p: string, g: boolean) => {\r\n const s = getStore()\r\n if (!s) throw new Error('[gState] recordConsent failed: No store found. call initState() first.')\r\n return s.recordConsent(uid, p, g)\r\n}\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const hasConsent = (uid: string, p: string) => getStore()?.hasConsent(uid, p) ?? false\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const getConsents = (uid: string) => getStore()?.getConsents(uid) ?? []\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const revokeConsent = (uid: string, p: string) => getStore()?.revokeConsent(uid, p)\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const exportUserData = (uid: string) => {\r\n const s = getStore()\r\n if (!s) throw new Error('[gState] exportUserData failed: No store found.')\r\n return s.exportUserData(uid)\r\n}\r\n/** @deprecated Use store instance methods for better isolation in multi-store scenarios */\r\nexport const deleteUserData = (uid: string) => {\r\n const s = getStore()\r\n if (!s) throw new Error('[gState] deleteUserData failed: No store found.')\r\n return s.deleteUserData(uid)\r\n}\r\n\r\n// Legacy cleanup helpers (now handled by destroyState / destroy())\r\n/** @deprecated Logic now tied to store lifecycle. Use destroyState() or store.destroy() */\r\nexport const clearAccessRules = () => { /* No-op globally */ }\r\n/** @deprecated Logic now tied to store lifecycle. Use destroyState() or store.destroy() */\r\nexport const clearAllConsents = () => { /* No-op globally */ }\r\n\r\nexport type { EncryptionKey, AuditEntry, Permission, AccessRule, ConsentRecord } from \"./core/security\"\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type {\r\n IStore,\r\n StoreConfig,\r\n PersistOptions,\r\n StateUpdater,\r\n ComputedSelector,\r\n WatcherCallback\r\n} from \"./core/types\"\r\n\r\n// ============================================================================\r\n// Global Augmentation\r\n// ============================================================================\r\n\r\n/* eslint-disable no-var */\r\ndeclare global {\r\n var createStore: typeof baseCreateStore\r\n var gstate: <S extends Record<string, unknown>>(initialState: S, configOrNamespace?: string | StoreConfig<S>) => IStore<S> & ((key: string) => unknown)\r\n var initState: typeof import(\"./core/hooks\").initState\r\n var destroyState: typeof import(\"./core/hooks\").destroyState\r\n var gState: IStore<Record<string, unknown>>\r\n var rgs: IStore<Record<string, unknown>>\r\n var useStore: typeof baseUseStore\r\n}\r\n"],
5
- "mappings": "AAAA,OAAS,WAAWA,GAAe,UAAUC,OAAoB,QCU1D,IAAMC,EAAoB,OAAO,OAAW,KACjD,OAAO,OAAO,OAAW,KACzB,OAAO,OAAO,OAAO,aAAgB,WAa1BC,EAAwB,SAAoC,CACvE,GAAI,CAACD,EAAmB,MAAM,IAAI,MAAM,8BAA8B,EAEtE,IACEE,EAAM,MAAM,OAAO,OAAO,YACxB,CAAE,KAAM,UAAW,OAAQ,GAAI,EAC/B,GACA,CAAC,UAAW,SAAS,CACvB,EACAC,EAAK,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC,EAEhD,MAAO,CAAE,IAAAD,EAAK,GAAAC,CAAG,CACnB,EAOaC,EAAY,MAAOC,GAAuE,CACrG,IAAMC,EAAc,MAAM,OAAO,OAAO,UAAU,MAAOD,EAAc,GAAG,EAE1E,MAAO,CACL,IAAK,KAAK,OAAO,aAAa,GAAG,IAAI,WAAWC,CAAW,CAAC,CAAC,EAC7D,GAAI,KAAK,OAAO,aAAa,GAAGD,EAAc,EAAE,CAAC,CACnD,CACF,EAQaE,EAAY,MAAOC,EAAiBC,IAA2C,CAC1F,IACEC,EAAW,WAAW,KAAK,KAAKF,CAAO,EAAGG,GAAKA,EAAE,WAAW,CAAC,CAAC,EAC9DC,EAAU,WAAW,KAAK,KAAKH,CAAM,EAAGE,GAAKA,EAAE,WAAW,CAAC,CAAC,EAK9D,MAAO,CAAE,IAJD,MAAM,OAAO,OAAO,UACxB,MAAOD,EAAU,CAAE,KAAM,UAAW,OAAQ,GAAI,EAAG,GAAM,CAAC,UAAW,SAAS,CAChF,EAEY,GAAIE,CAAQ,CAC5B,EAQaC,GAAU,MAAOC,EAAeT,IAAkD,CAC7F,IACEU,EAAU,IAAI,YACdC,EAAUD,EAAQ,OAAO,KAAK,UAAUD,CAAI,CAAC,EAC7CG,EAAY,MAAM,OAAO,OAAO,QAC9B,CAAE,KAAM,UAAW,GAAIZ,EAAc,EAA8B,EACnEA,EAAc,IACdW,CACF,EACAE,EAAW,IAAI,WAAWb,EAAc,GAAG,OAASY,EAAU,UAAU,EAE1E,OAAAC,EAAS,IAAIb,EAAc,EAAE,EAC7Ba,EAAS,IAAI,IAAI,WAAWD,CAAS,EAAGZ,EAAc,GAAG,MAAM,EAExD,KAAK,OAAO,aAAa,GAAGa,CAAQ,CAAC,CAC9C,EAQaC,GAAU,MAAUC,EAAuBf,IAA6C,CACnG,IACEa,EAAW,WAAW,KAAK,KAAKE,CAAa,EAAGT,GAAKA,EAAE,WAAW,CAAC,CAAC,EACpER,EAAKe,EAAS,MAAM,EAAG,EAAE,EACzBG,EAAaH,EAAS,MAAM,EAAE,EAC9BI,EAAY,MAAM,OAAO,OAAO,QAC9B,CAAE,KAAM,UAAW,GAAInB,CAA8B,EACrDE,EAAc,IACdgB,CACF,EAEF,OAAO,KAAK,MAAM,IAAI,YAAY,EAAE,OAAOC,CAAS,CAAC,CACvD,EAaIC,GAAqD,KAM5CC,EAAkBC,GAAwC,CAAEF,GAAeE,CAAO,EAKlFC,GAAgB,IAAMH,KAAiB,KAMvCI,EAAYC,GAAsB,CAAML,IAAcA,GAAaK,CAAK,CAAE,EA+B1EC,GAAgB,CAACC,EAAuBC,EAA+DC,IAAwB,CAC1IF,EAAM,IAAIC,aAAmB,OAASA,EAAQ,OAASA,EAASC,CAAK,CACvE,EAUaC,GAAgB,CAACH,EAAuB5B,EAAagC,EAAoBC,IAA8B,CAElH,GAAIL,EAAM,OAAS,EAAG,MAAO,GAG7B,OAAW,CAACC,EAASC,CAAK,IAAKF,EAAO,CACpC,IAAIM,EAGJ,GAAI,OAAOL,GAAY,WACrBK,EAAUL,EAAQ7B,EAAKiC,CAAO,MAG9B,IAAI,CACFC,EAAU,IAAI,OAAOL,CAAO,EAAE,KAAK7B,CAAG,CACxC,MAAQ,CAEN,QACF,CAGF,GAAIkC,EAGF,OAAOJ,EAAM,SAASE,CAAM,GAAKF,EAAM,SAAS,OAAO,CAE3D,CAGA,MAAO,EACT,EASaK,EAAiBC,GAA4B,CACxD,GAAI,OAAOA,GAAU,SAAU,CAG7B,IAAIC,EAAUD,EAAM,QAAQ,yBAA2BE,GAAU,CAE/D,IAAMC,EAAWD,EAAM,MAAM,0BAA0B,EACvD,GAAIC,GAAYA,EAAS,CAAC,EACxB,OAAO,OAAO,aAAa,SAASA,EAAS,CAAC,EAAG,EAAE,CAAC,EAEtD,IAAMC,EAAWF,EAAM,MAAM,kBAAkB,EAC/C,OAAIE,GAAYA,EAAS,CAAC,EACjB,OAAO,aAAa,SAASA,EAAS,CAAC,EAAG,EAAE,CAAC,EAE/C,EACT,CAAC,EAGD,GAAI,CACFH,EAAU,mBAAmBA,CAAO,CACtC,MAAQ,CAER,CAOA,OAHoBA,EAAQ,QAAQ,gEAAiE,eAAe,EAIjH,QAAQ,mDAAoD,eAAe,EAC3E,QAAQ,cAAe,gBAAgB,EACvC,QAAQ,sDAAuD,eAAe,EAC9E,QAAQ,sDAAuD,eAAe,EAC9E,QAAQ,mDAAoD,eAAe,EAC3E,QAAQ,6CAA8C,eAAe,EACrE,QAAQ,gDAAiD,eAAe,EACxE,QAAQ,gDAAiD,eAAe,EACxE,QAAQ,gDAAiD,eAAe,EACxE,QAAQ,gDAAiD,eAAe,EACxE,QAAQ,mDAAoD,eAAe,CAChF,CAGA,GAAID,GAAS,OAAOA,GAAU,UAAY,CAAC,MAAM,QAAQA,CAAK,EAAG,CAE/D,GAAI,OAAO,eAAeA,CAAK,IAAM,OAAO,UAAW,CACrD,IAAMK,EAAqC,CAAC,EAC5C,OAAW,CAACC,EAAGC,CAAC,IAAK,OAAO,QAAQP,CAAK,EACvCK,EAAUC,CAAC,EAAIP,EAAcQ,CAAC,EAEhC,OAAOF,CACT,CACA,OAAOL,CACT,CAGA,OAAI,MAAM,QAAQA,CAAK,EACdA,EAAM,IAAIO,GAAKR,EAAcQ,CAAC,CAAC,EAIjCP,CACT,EAOaQ,EAAe5C,GAAyB,oBAAoB,KAAKA,CAAG,GAAKA,EAAI,QAAU,IAevF6C,GAAgB,CAACC,EAAuBC,EAAgBC,EAAiBC,IAAoC,CACxH,IACEC,EAAS,CAAE,GAAI,OAAO,WAAW,EAAG,QAAAF,EAAS,QAAAC,EAAS,UAAW,KAAK,IAAI,CAAE,EAC5EE,EAAOL,EAAS,IAAIC,CAAM,GAAK,CAAC,EAElC,OAAAI,EAAK,KAAKD,CAAM,EAChBJ,EAAS,IAAIC,EAAQI,CAAI,EAEzB1B,EAAS,CAAE,UAAW,KAAK,IAAI,EAAG,OAAQ,MAAO,IAAK,WAAWuB,CAAO,GAAI,OAAAD,EAAQ,QAAS,EAAK,CAAC,EAE5FG,CACT,EASaE,GAAa,CAACN,EAAuBC,EAAgBC,IAA6B,CAC7F,IAAMK,EAAeP,EAAS,IAAIC,CAAM,EACxC,GAAI,CAACM,EAAc,MAAO,GAG1B,QAASC,EAAID,EAAa,OAAS,EAAGC,GAAK,EAAGA,IAAK,CACjD,IAAMJ,EAASG,EAAaC,CAAC,EAC7B,GAAIJ,GAAUA,EAAO,UAAYF,EAC/B,OAAOE,EAAO,OAElB,CAEA,MAAO,EACT,EASaK,GAAgB,CAACT,EAAuBC,EAAgBC,IAC5DH,GAAcC,EAAUC,EAAQC,EAAS,EAAK,EAS1CQ,GAAc,CAACV,EAAuBC,IAAmBD,EAAS,IAAIC,CAAM,GAAK,CAAC,EAQlFU,GAAiB,CAACX,EAAuBC,KAAoB,CAAE,OAAAA,EAAQ,WAAY,KAAK,IAAI,EAAG,SAAUD,EAAS,IAAIC,CAAM,GAAK,CAAC,CAAE,GAQpIW,GAAiB,CAACZ,EAAuBC,IAAmB,CACvE,IAAMY,EAAQb,EAAS,IAAIC,CAAM,GAAG,QAAU,EAC9C,OAAAD,EAAS,OAAOC,CAAM,EAEf,CAAE,QAAS,GAAM,gBAAiBY,CAAM,CACjD,EClXO,IAAMC,GAAgBC,GAAc,CACzC,GAAIA,IAAQ,MAAQ,OAAOA,GAAQ,SAAU,OAAOA,EAGpD,GAAI,OAAO,iBAAoB,WAC7B,GAAI,CACF,OAAO,gBAAgBA,CAAG,CAC5B,MAAa,CAEb,CAGF,IAAMC,EAAO,IAAI,QAEXC,EAAYC,GAAgB,CAEhC,GADIA,IAAU,MAAQ,OAAOA,GAAU,UACnC,OAAOA,GAAU,WAAY,OAAOA,EAGxC,GAAIF,EAAK,IAAIE,CAAe,EAAG,OAAOF,EAAK,IAAIE,CAAe,EAE9D,GAAIA,aAAiB,KAAM,OAAO,IAAI,KAAKA,EAAM,QAAQ,CAAC,EAC1D,GAAIA,aAAiB,OAAQ,OAAO,IAAI,OAAOA,EAAM,OAAQA,EAAM,KAAK,EACxE,GAAIA,aAAiB,IAAK,CACxB,IAAMC,EAAS,IAAI,IACnB,OAAAH,EAAK,IAAIE,EAAiBC,CAAM,EAChCD,EAAM,QAAQ,CAACE,EAAGC,IAAMF,EAAO,IAAIF,EAAMI,CAAC,EAAGJ,EAAMG,CAAC,CAAC,CAAC,EAC/CD,CACT,CACA,GAAID,aAAiB,IAAK,CACxB,IAAMC,EAAS,IAAI,IACnB,OAAAH,EAAK,IAAIE,EAAiBC,CAAM,EAChCD,EAAM,QAASE,GAAMD,EAAO,IAAIF,EAAMG,CAAC,CAAC,CAAC,EAClCD,CACT,CAGA,IAAMA,EAAU,MAAM,QAAQD,CAAK,EAC/B,CAAC,EACD,OAAO,OAAO,OAAO,eAAeA,CAAK,CAAC,EAE9CF,EAAK,IAAIE,EAAiBC,CAAM,EAEhC,IAAMG,EAAO,CAAC,GAAG,OAAO,KAAKJ,CAAe,EAAG,GAAG,OAAO,sBAAsBA,CAAe,CAAC,EAC/F,QAAWK,KAAOD,EAChBH,EAAOI,CAAa,EAAIN,EAAOC,EAA2CK,CAAG,CAAC,EAGhF,OAAOJ,CACT,EAEA,OAAOF,EAAMF,CAAG,CAClB,EAQaS,GAAU,CAACC,EAAYC,IAAwB,CAC1D,GAAID,IAAMC,EAAG,MAAO,GAEpB,GADID,IAAM,MAAQC,IAAM,MACpB,OAAOD,GAAM,UAAY,OAAOC,GAAM,SAAU,OAAOD,IAAMC,EACjE,GAAI,MAAM,QAAQD,CAAC,GAAK,MAAM,QAAQC,CAAC,EAAG,CACxC,GAAID,EAAE,SAAWC,EAAE,OAAQ,MAAO,GAClC,QAASC,EAAI,EAAGA,EAAIF,EAAE,OAAQE,IAAK,GAAI,CAACH,GAAQC,EAAEE,CAAC,EAAGD,EAAEC,CAAC,CAAC,EAAG,MAAO,GACpE,MAAO,EACT,CACA,IAAMC,EAAQ,OAAO,KAAKH,CAAW,EAC/BI,EAAQ,OAAO,KAAKH,CAAW,EACrC,GAAIE,EAAM,SAAWC,EAAM,OAAQ,MAAO,GAE1C,QAASF,EAAI,EAAGA,EAAIC,EAAM,OAAQD,IAAK,CACrC,IAAMJ,EAAMK,EAAMD,CAAC,EACnB,GAAI,EAAEJ,KAAQG,IAAiB,CAACF,GAASC,EAA8BF,CAAG,EAAIG,EAA8BH,CAAG,CAAC,EAAG,MAAO,EAC5H,CACA,MAAO,EACT,ECrFA,OAAmC,UAAUO,OAAoB,QAQjE,IAAMC,GAAcC,GAAsB,GAAGA,CAAS,IAsBzCC,GAAY,MAAOC,GAA4B,CAC1D,GAAI,CAACA,EAAI,QAAS,OAElB,GAAM,CAAE,MAAAC,EAAO,OAAAC,EAAQ,UAAAC,EAAW,QAAAC,EAAS,cAAAC,EAAe,MAAAC,EAAO,QAAAC,EAAS,OAAAC,EAAQ,eAAAC,CAAe,EAAIT,EAC/FU,EAASb,GAAWK,EAAO,WAAa,QAAQ,EAItD,GAAI,CACF,IAAMS,EAAoC,CAAC,EAC3CV,EAAM,QAAQ,CAACW,EAAG,IAAM,CAAED,EAAS,CAAC,EAAIC,CAAE,CAAC,EAE3C,IAAIC,EACEC,EAAYZ,GAAQ,QACtBY,EACFD,EAAY,KAAK,KAAK,UAAUF,CAAQ,CAAC,EAEzCE,EAAY,KAAK,UAAUF,CAAQ,EAGrCP,EAAQ,QAAQM,EAAO,QAAQ,IAAK,EAAE,EAAG,KAAK,UAAU,CACtD,EAAG,EAAG,EAAG,KAAK,IAAI,EAAG,EAAG,KACxB,EAAGG,EAAW,OAAQJ,EAAgB,KAAMK,EAAY,GAAO,MACjE,CAAC,CAAC,EACFR,EAAM,MAAO,aAAc,EAAI,CACjC,OAASS,EAAG,CACV,IAAMC,EAAQD,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtDR,EAASA,EAAQS,EAAO,CAAE,UAAW,UAAW,IAAK,YAAa,CAAC,EAC7DR,GAAQ,QAAQ,MAAM,4BAA6BQ,CAAK,CACpE,CAEA,IAAMC,EAAQ,MAAM,KAAKd,EAAU,QAAQ,CAAC,EAAGA,EAAU,MAAM,EAC/D,OAAW,CAACe,EAAKC,CAAI,IAAKF,EACxB,GAAI,CACF,IAAIJ,EAAqBM,EAAK,MACxBL,EAAYK,EAAK,QAAQ,SAAWA,EAAK,QAAQ,OACvD,GAAIA,EAAK,QAAQ,UAAW,CAC1B,GAAI,CAACd,EAAe,MAAM,IAAI,MAAM,+BAA+Ba,CAAG,GAAG,EACzEL,EAAY,MAAeO,GAAQD,EAAK,MAAOd,CAAa,CAC9D,MAAWS,EACTD,EAAY,KAAK,KAAK,UAAUM,EAAK,KAAK,CAAC,EAClC,OAAOA,EAAK,OAAU,UAAYA,EAAK,QAAU,OAC1DN,EAAY,KAAK,UAAUM,EAAK,KAAK,GAGvCf,EAAQ,QAAQ,GAAGM,CAAM,GAAGQ,CAAG,GAAI,KAAK,UAAU,CAChD,EAAIlB,EAAI,SAAS,IAAIkB,CAAG,GAAK,EAAI,EAAG,KAAK,IAAI,EAAG,EAAGC,EAAK,QAAQ,IAAM,KAAK,IAAI,EAAIA,EAAK,QAAQ,IAAM,KACtG,EAAGN,EAAW,OAAQJ,EAAgB,KAAMU,EAAK,QAAQ,UAAY,GAAO,OAAW,KAAML,EAAY,GAAO,MAClH,CAAC,CAAC,EACFR,EAAM,MAAOY,EAAK,EAAI,CACxB,OAASH,EAAG,CACV,IAAMC,EAAQD,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtDR,EAASA,EAAQS,EAAO,CAAE,UAAW,UAAW,IAAAE,CAAI,CAAC,EAC/CV,GAAQ,QAAQ,MAAM,4BAA6BQ,CAAK,CACpE,CAEJ,EAKaK,GAAe,MAC1BrB,EACAsB,EACAC,IACkB,CAClB,GAAM,CAAE,QAAAnB,EAAS,OAAAF,EAAQ,cAAAG,EAAe,MAAAC,EAAO,QAAAC,EAAS,OAAAC,EAAQ,eAAAC,EAAgB,MAAAR,EAAO,MAAAuB,EAAO,SAAAC,CAAS,EAAIzB,EACrGU,EAASb,GAAWK,EAAO,WAAa,QAAQ,EAChDwB,EAAQxB,EAAO,OAAS,GAE9B,GAAKE,EAEL,GAAI,CACF,IAAMuB,EAAqC,CAAC,EACxCC,EAAS,EACb,QAASC,GAAI,EAAGA,IAAKzB,EAAQ,QAAU,GAAIyB,KAAK,CAC9C,IAAMC,EAAI1B,EAAQ,IAAIyB,EAAC,EACvB,GAAI,CAACC,GAAK,CAACA,EAAE,WAAWpB,CAAM,EAAG,SACjC,IAAMqB,EAAM3B,EAAQ,QAAQ0B,CAAC,EAC7B,GAAKC,EACL,GAAI,CACF,IAAMC,EAAO,KAAK,MAAMD,CAAG,EAAGb,GAAMY,EAAE,UAAUpB,EAAO,MAAM,EAK7D,GAFAkB,EAAS,KAAK,IAAIA,EAAQI,EAAK,SAAW,OAAYA,EAAK,OAAUA,EAAK,GAAK,CAAE,EAE7EA,EAAK,GAAK,KAAK,IAAI,EAAIA,EAAK,EAAG,CAAE5B,EAAQ,WAAW0B,CAAC,EAAGD,KAAK,QAAS,CAC1E,IAAII,GAAID,EAAK,EACb,GAAIA,EAAK,MAAQ3B,EACf4B,GAAI,MAAeC,GAAQD,GAAG5B,CAAa,UAClC,OAAO4B,IAAM,UACtB,GAAID,EAAK,KAAQ,GAAI,CAAEC,GAAI,KAAK,MAAM,KAAKA,EAAC,CAAC,CAAE,MAAa,CAAE,SACrDA,GAAE,WAAW,GAAG,GAAKA,GAAE,WAAW,GAAG,EAAK,GAAI,CAAEA,GAAI,KAAK,MAAMA,EAAC,CAAE,MAAa,CAAE,EAE5FN,EAAUT,EAAG,EAAIe,GAAG3B,EAAM,UAAWY,GAAK,EAAI,CAChD,OAASiB,EAAK,CACZ7B,EAAM,UAAWwB,EAAG,GAAO,OAAOK,CAAG,CAAC,EACtC,IAAMnB,GAAQmB,aAAe,MAAQA,EAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,EAC5D5B,EAASA,EAAQS,GAAO,CAAE,UAAW,YAAa,IAAKc,CAAE,CAAC,EACpDtB,GAAQ,QAAQ,MAAM,kCAAkCsB,CAAC,MAAOK,CAAG,CAC/E,CACF,CACA,IAAMC,GAASR,EAASnB,GAAkBP,EAAO,QAAWA,EAAO,QAAQyB,EAAWC,CAAM,EAAID,EAEhG,OAAO,QAAQS,EAAK,EAAE,QAAQ,CAAC,CAACN,GAAGlB,CAAC,IAAM,CAExC,IAAMyB,EAAUX,GAASd,IAAM,MAAQ,OAAOA,GAAM,SAAYhB,GAAa0C,GAAU1B,CAAW,EAAG,EAAI,EAAIA,EAEvG2B,EAAOjB,EAAce,CAAM,EAC3BG,GAAUhB,EAAM,IAAIM,EAAC,GAAK,EAChC9B,EAAI,UAAYA,EAAI,UAAYwC,GAAUD,EAC1Cf,EAAM,IAAIM,GAAGS,CAAI,EACjBtC,EAAM,IAAI6B,GAAGO,CAAM,EAAGZ,EAAS,IAAIK,GAAG,CAAC,CACzC,CAAC,EACDP,EAAK,CACP,OAASR,EAAG,CACV,IAAMC,EAAQD,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtDR,EAASA,EAAQS,EAAO,CAAE,UAAW,WAAY,CAAC,EAC5CR,GAAQ,QAAQ,MAAM,8BAA+BQ,CAAK,CACtE,CACF,EC9IO,IAAMyB,GAAU,CACrBC,EACAC,EACAC,IACG,CACH,GAAIF,EAAI,QAAQ,OAAS,EACzB,QAAWG,KAAKH,EAAI,QAAQ,OAAO,EAAG,CACpC,IAAMI,EAAOD,EAAE,QAAQF,CAAI,EAC3B,GAAIG,EACF,GAAI,CAAEA,EAAKF,CAAW,CAAE,OACjBG,EAAG,CACR,IAAMC,EAAQD,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtDL,EAAI,QAASA,EAAI,QAAQM,EAAO,CAAE,UAAW,UAAUH,EAAE,IAAI,IAAIF,CAAI,GAAI,IAAKC,EAAY,GAAI,CAAC,EACzFF,EAAI,QAAQ,QAAQ,MAAM,oBAAoBG,EAAE,IAAI,WAAYE,CAAC,CAC7E,CAEJ,CACF,EAEaE,GAAgB,CAC3BP,EACAQ,EACAC,IACG,CACH,GAAI,CACFT,EAAI,QAAQ,IAAIQ,EAAO,KAAMA,CAAM,EACnCA,EAAO,OAAO,YAAY,CAAE,MAAOC,CAAc,CAAC,CACpD,OAASJ,EAAG,CACV,IAAMC,EAAQD,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtDL,EAAI,QAASA,EAAI,QAAQM,EAAO,CAAE,UAAW,iBAAkB,IAAKE,EAAO,IAAK,CAAC,EAC3ER,EAAI,QAAQ,QAAQ,MAAM,sCAAsCQ,EAAO,IAAI,MAAOH,CAAC,CAC/F,CACF,ECyCO,IAAMK,EAAN,KAA8E,CAC3E,MACA,OACA,aAA2C,IAAI,IAC/C,eAA6C,IAAI,IACjD,UAAkD,KAClD,sBAAwD,IAAI,IAC5D,mBAAsD,IAAI,IAC1D,UAAqB,GACrB,WAAsB,GAE9B,YAAYC,EAAkBC,EAAoB,CAChD,KAAK,MAAQD,EACb,KAAK,OAAS,CACZ,SAAUC,EAAO,SACjB,UAAWA,EAAO,WAAa,GAC/B,SAAUA,EAAO,UAAY,kBAC7B,iBAAkBA,EAAO,kBAAoB,IAC7C,gBAAiBA,EAAO,iBAAmB,GAC3C,aAAcA,EAAO,cAAgB,IACrC,MAAOA,EAAO,OAAS,MACvB,OAAQA,EAAO,SAAW,IAAM,CAAE,GAClC,WAAYA,EAAO,aAAe,KAAO,CAAE,OAAQ,cAAe,IAClE,WAAYA,EAAO,YAAc,CACnC,EAEA,KAAK,UAAY,OAAO,UAAc,IAAc,UAAU,OAAS,GACvE,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAGrB,KAAK,OAAO,iBAAmB,GACjC,KAAK,eAAe,CAExB,CAEQ,sBAA6B,CAC/B,OAAO,OAAW,MAEtB,OAAO,iBAAiB,SAAU,IAAM,CACtC,KAAK,UAAY,GACjB,KAAK,oBAAoB,EAAI,EACzB,KAAK,OAAO,iBACd,KAAK,KAAK,CAEd,CAAC,EAED,OAAO,iBAAiB,UAAW,IAAM,CACvC,KAAK,UAAY,GACjB,KAAK,oBAAoB,EAAK,CAChC,CAAC,EACH,CAEQ,qBAA4B,CAElC,KAAK,MAAM,WAAW,IAAM,CAE5B,CAAC,CACH,CAEQ,gBAAuB,CAC7B,YAAY,IAAM,CACZ,KAAK,WAAa,CAAC,KAAK,YAAc,KAAK,aAAa,KAAO,GACjE,KAAK,KAAK,CAEd,EAAG,KAAK,OAAO,gBAAgB,CACjC,CAEQ,oBAAoBC,EAAuB,CACjD,KAAK,sBAAsB,QAAQC,GAAMA,EAAGD,CAAM,CAAC,EACnD,KAAK,mBAAmB,CAC1B,CAEQ,oBAA2B,CACjC,IAAME,EAAQ,KAAK,SAAS,EAC5B,KAAK,mBAAmB,QAAQD,GAAMA,EAAGC,CAAK,CAAC,CACjD,CAKA,YAAYC,EAAaC,EAAsB,CAC7C,IAAMC,EAAU,KAAK,MAAM,YAAYF,CAAG,GAAK,EAC/C,KAAK,aAAa,IAAIA,EAAK,CACzB,IAAAA,EACA,MAAOG,GAAUF,CAAK,EACtB,UAAW,KAAK,IAAI,EACpB,QAAAC,CACF,CAAC,EACD,KAAK,mBAAmB,EAGpB,KAAK,WAAW,aAAa,KAAK,SAAS,EAC/C,KAAK,UAAY,WAAW,IAAM,CAC5B,KAAK,WAAW,KAAK,KAAK,CAChC,EAAG,KAAK,OAAO,YAAY,CAC7B,CAKA,MAAM,MAA4B,CAChC,GAAI,KAAK,WACP,MAAO,CACL,QAAS,GACT,WAAY,CAAC,EACb,UAAW,CAAC,EACZ,OAAQ,CAAC,0BAA0B,EACnC,UAAW,KAAK,IAAI,EACpB,SAAU,CACZ,EAGF,KAAK,WAAa,GAClB,KAAK,mBAAmB,EAExB,IAAME,EAAY,KAAK,IAAI,EACrBC,EAAuB,CAAC,EACxBC,EAA4B,CAAC,EAC7BC,EAAmB,CAAC,EAE1B,GAAI,CAEF,IAAMC,EAAiB,MAAM,KAAK,KAAK,aAAa,OAAO,CAAC,EAE5D,GAAIA,EAAe,SAAW,EAC5B,YAAK,WAAa,GAClB,KAAK,mBAAmB,EACjB,CACL,QAAS,GACT,WAAY,CAAC,EACb,UAAW,CAAC,EACZ,OAAQ,CAAC,EACT,UAAW,KAAK,IAAI,EACpB,SAAU,KAAK,IAAI,EAAIJ,CACzB,EAIF,MAAM,KAAK,qBAAqBI,EAAe,IAAIC,GAAKA,EAAE,GAAG,CAAC,EAG9D,QAAWC,KAAUF,EACnB,GAAI,CACF,IAAMG,EAAgB,KAAK,eAAe,IAAID,EAAO,GAAG,EAExD,GAAI,CAACC,EAEH,MAAM,KAAK,YAAYD,CAAM,EAC7BL,EAAW,KAAKK,EAAO,GAAG,EAC1B,KAAK,aAAa,OAAOA,EAAO,GAAG,UAC1BC,EAAc,SAAWD,EAAO,QAAS,CAElD,IAAME,EAAyB,CAC7B,IAAKF,EAAO,IACZ,WAAYA,EAAO,MACnB,YAAaC,EAAc,MAC3B,aAAcD,EAAO,QACrB,cAAeC,EAAc,QAC7B,UAAWD,EAAO,SACpB,EACAJ,EAAU,KAAKM,CAAQ,EAGvB,IAAMC,EAAa,KAAK,OAAO,WAAWD,CAAQ,EAClD,MAAM,KAAK,iBAAiBF,EAAQC,EAAeE,CAAU,EAC7DR,EAAW,KAAKK,EAAO,GAAG,EAC1B,KAAK,aAAa,OAAOA,EAAO,GAAG,CACrC,MAEE,MAAM,KAAK,YAAYA,CAAM,EAC7BL,EAAW,KAAKK,EAAO,GAAG,EAC1B,KAAK,aAAa,OAAOA,EAAO,GAAG,CAEvC,OAASI,EAAK,CACZP,EAAO,KAAK,mBAAmBG,EAAO,GAAG,MAAMI,CAAG,EAAE,CACtD,CAGF,IAAMC,EAAqB,CACzB,QAASR,EAAO,SAAW,EAC3B,WAAAF,EACA,UAAAC,EACA,OAAAC,EACA,UAAW,KAAK,IAAI,EACpB,SAAU,KAAK,IAAI,EAAIH,CACzB,EAEA,YAAK,OAAO,OAAOW,CAAM,EAClBA,CACT,OAASD,EAAK,CACZ,IAAME,EAAW,gBAAgBF,CAAG,GACpC,OAAAP,EAAO,KAAKS,CAAQ,EAEb,CACL,QAAS,GACT,WAAAX,EACA,UAAAC,EACA,OAAAC,EACA,UAAW,KAAK,IAAI,EACpB,SAAU,KAAK,IAAI,EAAIH,CACzB,CACF,QAAE,CACA,KAAK,WAAa,GAClB,KAAK,mBAAmB,CAC1B,CACF,CAEA,MAAc,qBAAqBa,EAA+B,CAChE,GAAI,CACF,IAAMC,EAAW,MAAM,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,QAAQ,YAAa,CAC3E,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,GAAI,KAAK,OAAO,WAAa,CAAE,cAAiB,UAAU,KAAK,OAAO,SAAS,EAAG,CACpF,EACA,KAAM,KAAK,UAAU,CAAE,KAAAD,CAAK,CAAC,CAC/B,CAAC,EAED,GAAIC,EAAS,GAAI,CACf,IAAMC,EAAO,MAAMD,EAAS,KAAK,EACjC,GAAIC,EAAK,SACP,OAAW,CAACnB,EAAKE,CAAO,IAAK,OAAO,QAAQiB,EAAK,QAAQ,EACvD,KAAK,eAAe,IAAInB,EAAKE,CAAwB,CAG3D,CACF,OAASY,EAAK,CACZ,QAAQ,KAAK,gDAAiDA,CAAG,CACnE,CACF,CAEA,MAAc,YAAYJ,EAAsC,CAC9D,IAAIU,EAAU,EAEd,KAAOA,EAAU,KAAK,OAAO,YAC3B,GAAI,CACF,IAAMF,EAAW,MAAM,KAAK,OAAO,MAAM,GAAG,KAAK,OAAO,QAAQ,QAAS,CACvE,OAAQ,OACR,QAAS,CACP,eAAgB,mBAChB,GAAI,KAAK,OAAO,WAAa,CAAE,cAAiB,UAAU,KAAK,OAAO,SAAS,EAAG,CACpF,EACA,KAAM,KAAK,UAAU,CACnB,IAAKR,EAAO,IACZ,MAAOA,EAAO,MACd,QAASA,EAAO,QAChB,UAAWA,EAAO,SACpB,CAAC,CACH,CAAC,EAED,GAAIQ,EAAS,GAAI,CACf,IAAMC,EAAO,MAAMD,EAAS,KAAK,EAC7BC,EAAK,SACP,KAAK,eAAe,IAAIT,EAAO,IAAK,CAClC,QAASS,EAAK,QACd,UAAWA,EAAK,WAAa,KAAK,IAAI,EACtC,MAAOT,EAAO,KAChB,CAAC,EAEH,MACF,CAEAU,GACF,OAASN,EAAK,CAEZ,GADAM,IACIA,GAAW,KAAK,OAAO,WAAY,MAAMN,CAC/C,CAEJ,CAEA,MAAc,iBACZO,EACAV,EACAE,EACe,CACf,OAAQA,EAAW,OAAQ,CACzB,IAAK,eAEH,MAAM,KAAK,YAAY,CACrB,GAAGQ,EACH,QAASV,EAAc,QAAU,EACjC,UAAW,KAAK,IAAI,CACtB,CAAC,EACD,MAEF,IAAK,gBAEH,KAAK,MAAM,IAAIU,EAAY,IAAKV,EAAc,KAAK,EACnD,MAEF,IAAK,QAEH,KAAK,MAAM,IAAIU,EAAY,IAAKR,EAAW,KAAK,EAChD,MAAM,KAAK,YAAY,CACrB,IAAKQ,EAAY,IACjB,MAAOR,EAAW,MAClB,QAAS,KAAK,IAAIQ,EAAY,QAASV,EAAc,OAAO,EAAI,EAChE,UAAW,KAAK,IAAI,CACtB,CAAC,EACD,MAEF,IAAK,UAEH,KACJ,CACF,CAKA,UAAsB,CACpB,MAAO,CACL,SAAU,KAAK,UACf,UAAW,KAAK,WAChB,kBAAmB,KACnB,eAAgB,KAAK,aAAa,KAClC,UAAW,CACb,CACF,CAKA,eAAeW,EAAiD,CAC9D,YAAK,sBAAsB,IAAIA,CAAQ,EAChC,IAAM,KAAK,sBAAsB,OAAOA,CAAQ,CACzD,CAKA,cAAcA,EAAkD,CAC9D,YAAK,mBAAmB,IAAIA,CAAQ,EAC7B,IAAM,KAAK,mBAAmB,OAAOA,CAAQ,CACtD,CAKA,MAAM,OAA6B,CACjC,OAAO,KAAK,KAAK,CACnB,CAKA,SAAgB,CACV,KAAK,WAAW,aAAa,KAAK,SAAS,EAC/C,KAAK,aAAa,MAAM,EACxB,KAAK,sBAAsB,MAAM,EACjC,KAAK,mBAAmB,MAAM,CAChC,CACF,EAKaC,EAAmB,CAC9B5B,EACAC,IAEO,IAAIF,EAAWC,EAAOC,CAAM,EL9a9B,IAAM4B,GAAkB,CAC7B,MAAO,IAA6B,OAAO,OAAW,IAAc,OAAO,aAAe,KAC1F,QAAS,IAA6B,OAAO,OAAW,IAAc,OAAO,eAAiB,KAC9F,OAAQ,IAAqB,CAC3B,IAAMC,EAAK,IAAI,IACf,MAAO,CACL,QAAUC,GAAcD,EAAG,IAAIC,CAAC,GAAK,KACrC,QAAS,CAACA,EAAWC,IAAcF,EAAG,IAAIC,EAAGC,CAAC,EAC9C,WAAaD,GAAcD,EAAG,OAAOC,CAAC,EACtC,IAAME,GAAc,MAAM,KAAKH,EAAG,KAAK,CAAC,EAAEG,CAAC,GAAK,KAChD,IAAI,QAAS,CAAE,OAAOH,EAAG,IAAK,CAChC,CACF,CACF,EAKaI,EAA4EC,GAAuC,CAC9H,IACEC,EAAS,IAAI,IACbC,EAAY,IAAI,IAChBC,EAAS,IAAI,IACbC,EAAa,IAAI,IACjBC,EAAgB,IAAI,IACpBC,EAAe,IAAI,IACnBC,EAAY,IAAI,IAChBC,EAAY,IAAI,IAChBC,EAAgB,IAAI,IACpBC,EAAW,IAAI,IACfC,EAAa,IAAI,IACjBC,EAAc,IAAI,IAGlBC,EAAwC,IAAI,IAC5CC,EAAkC,IAAI,IAEtCC,EAAaf,GAAQ,WAAa,SAClCgB,EAAUhB,GAAQ,QAAU,GAC5BiB,GAAgBjB,GAAQ,cAAgB,IACxCkB,GAAkBlB,GAAQ,SAAW,EACrCmB,EAAWnB,GAAQ,SAAWN,GAAgB,MAAM,EACpD0B,EAAWpB,GAAQ,QACnBqB,EAAiBrB,GAAQ,eAAiB,EAC1CsB,GAAgBtB,GAAQ,cAAgB,EACxCuB,GAAiBvB,GAAQ,eAAiB,KAC1CwB,GAAiBxB,GAAQ,eAAiB,GAC1CyB,GAAgBzB,GAAQ,cAAgB,GACxC0B,GAAU1B,GAAQ,OAClB2B,GAAS3B,GAAQ,OAAS,GAC1B4B,GAAoB5B,GAAQ,kBAAoBA,GAAQ,aAAeA,GAAQ,SAAW,GAExFA,GAAQ,aACVA,EAAO,YAAY,QAAQ6B,GAAiBC,GAAcjB,EAAcgB,EAAK,QAASA,EAAK,WAAW,CAAC,EAGzG,IACEE,GAAiB,GAAOC,GAAe,GAAOC,GAAW,GAAOC,GAAa,EAC7EC,GAAmD,KACnDC,GAAsB,KAEpBC,GACEC,GAAgB,IAAI,QAAcC,GAAW,CAAEF,GAAiBE,CAAQ,CAAC,EAIzEC,GAAa,IAAM,GAAGzB,CAAU,IAEhC0B,GAAwB,KAAuC,CACnE,MAAOxC,EAAQ,SAAUC,EAAW,MAAOC,EAAQ,UAAW+B,GAC9D,QAASf,EAAU,OAAQnB,GAAU,CAAC,EAAG,UAAWW,EACpD,cAAeY,GAAgB,MAAOmB,GACtC,QAAStB,EACT,OAAQJ,EAAS,aAAcC,GAAe,eAAgBC,EAChE,GAEMyB,GAAmB,KAAwC,CAC/D,QAASjC,EACT,QAASU,EACT,OAAQJ,CACV,GAMM4B,GAAkBC,GAAyB,CAC/C,GAAIA,GAAQ,KAA2B,MAAO,GAC9C,IAAMC,EAAO,OAAOD,EACpB,GAAIC,IAAS,UAAW,MAAO,GAC/B,GAAIA,IAAS,SAAU,MAAO,GAC9B,GAAIA,IAAS,SAAU,OAAQD,EAAe,OAAS,EACvD,GAAIC,IAAS,SAAU,MAAO,GAE9B,IAAIC,EAAQ,EACNC,EAAmB,CAACH,CAAG,EACvBI,EAAO,IAAI,QAEjB,KAAOD,EAAM,OAAS,GAAG,CACvB,IAAME,EAAQF,EAAM,IAAI,EACxB,GAAI,OAAOE,GAAU,UAAaH,GAAS,UAClC,OAAOG,GAAU,SAAYH,GAAS,UACtC,OAAOG,GAAU,SAAYH,GAASG,EAAM,OAAS,UACrD,OAAOA,GAAU,UAAYA,IAAU,KAAM,CACpD,IAAMC,EAAMD,EACZ,GAAID,EAAK,IAAIE,CAAG,EAAG,SAEnB,GADAF,EAAK,IAAIE,CAAG,EACR,MAAM,QAAQA,CAAG,EACnB,QAASrD,GAAI,EAAGA,GAAIqD,EAAI,OAAQrD,KAAKkD,EAAM,KAAKG,EAAIrD,EAAC,CAAC,MAEtD,SAAWsD,MAAO,OAAO,KAAKD,CAAG,EAC/BJ,GAASK,GAAI,OAAS,EACtBJ,EAAM,KAAKG,EAAIC,EAAG,CAAC,CAGzB,CACF,CACA,OAAOL,CACT,EAEMM,GAAW,CAACC,EAAsBC,IAA8B,CAC5DC,GAAQb,GAAiB,EAAGW,EAAMC,CAAO,CACnD,EAEMb,GAAS,CAACe,EAA8CL,EAAaM,EAAkBC,IAAmB,CAC1GlC,IAA0BmC,GAAc,GAAcC,GAC/CA,EAAS,CAAE,UAAW,KAAK,IAAI,EAAG,OAAAJ,EAAQ,IAAAL,EAAK,OAAQ1B,GAAS,QAAAgC,EAAS,MAAAC,CAAM,CAAC,CAE7F,EAIMG,GAAmBV,GAAgB,CACvC,IAAMW,EAAOvD,EAAU,IAAI4C,CAAG,EAC9B,GAAI,CAACW,EAAM,OAEX,IAAMC,EAAY,IAAI,IAChBC,EAAarE,IACjBoE,EAAU,IAAIpE,CAAC,EACXY,EAAU,IAAIZ,CAAC,EAAUY,EAAU,IAAIZ,CAAC,EAAG,UACxCsE,EAAS,IAAItE,CAAC,GAGjBuE,EAAWJ,EAAK,SAASE,CAAM,EAGrCF,EAAK,KAAK,QAAQK,GAAK,CACrB,GAAI,CAACJ,EAAU,IAAII,CAAC,EAAG,CACrB,IAAMC,EAAa5D,EAAc,IAAI2D,CAAC,EAClCC,IAAcA,EAAW,OAAOjB,CAAG,EAAOiB,EAAW,OAAS,GAAG5D,EAAc,OAAO2D,CAAC,EAC7F,CACF,CAAC,EACDJ,EAAU,QAAQI,GAAK,CAChBL,EAAK,KAAK,IAAIK,CAAC,IACb3D,EAAc,IAAI2D,CAAC,GAAG3D,EAAc,IAAI2D,EAAG,IAAI,GAAK,EACzD3D,EAAc,IAAI2D,CAAC,EAAG,IAAIhB,CAAG,EAEjC,CAAC,EACDW,EAAK,KAAOC,EAEPM,GAAQP,EAAK,UAAWI,CAAQ,IACnCJ,EAAK,UAAapC,IAAUwC,IAAa,MAAQ,OAAOA,GAAa,SAAYI,GAAaC,GAAUL,CAAQ,EAAG,EAAI,EAAIA,EAC3HjE,EAAU,IAAIkD,GAAMlD,EAAU,IAAIkD,CAAG,GAAK,GAAK,CAAC,EAChDqB,GAAMrB,CAAG,EAEb,EAEMqB,GAASC,GAAwB,CACrC,GAAIA,EAAY,CAEd,GAAIjE,EAAc,IAAIiE,CAAU,EAAG,CACjC,IAAML,EAAa5D,EAAc,IAAIiE,CAAU,EAC/C,QAAWC,KAAgBN,EACzBP,GAAgBa,CAAY,CAEhC,CAGA,IAAMC,EAAWrE,EAAU,IAAImE,CAAU,EACzC,GAAIE,EAAU,CACZ,IAAM/B,EAAMqB,EAAS,IAAIQ,CAAU,EACnC,QAAWG,KAAKD,EACd,GAAI,CAAEC,EAAEhC,CAAG,CAAE,OACNiC,EAAG,CACR,IAAMnB,EAAQmB,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtD1D,EAAUA,EAASuC,EAAO,CAAE,UAAW,UAAW,IAAKe,CAAW,CAAC,EAC7D1D,GAAS,QAAQ,MAAM,+BAA+B0D,CAAU,KAAMI,CAAC,CACnF,CAEJ,CAGA,IAAMC,EAAe1E,EAAc,IAAIqE,CAAU,EACjD,GAAIK,EACF,QAAWC,KAAKD,EACd,GAAI,CAAEC,EAAE,CAAE,OACHF,EAAG,CACR,IAAMnB,EAAQmB,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtD1D,EAAUA,EAASuC,EAAO,CAAE,UAAW,cAAe,IAAKe,CAAW,CAAC,EACjE1D,GAAS,QAAQ,MAAM,gCAAgC0D,CAAU,KAAMI,CAAC,CACpF,CAGN,CAEA,GAAI/C,GAAgB,CAAEC,GAAe,GAAM,MAAO,CAGlD,QAAWgD,KAAK5E,EACd,GAAI,CAAE4E,EAAE,CAAE,OACHF,EAAG,CACR,IAAMnB,EAAQmB,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACtD1D,EAAUA,EAASuC,EAAO,CAAE,UAAW,UAAW,CAAC,EAC7C3C,GAAS,QAAQ,MAAM,mCAAoC8D,CAAC,CACxE,CAEJ,EAEMG,GAAa,SAAY,CAGjBC,GAAUzC,GAAsB,CAAC,CAC/C,EAKM0C,GAA4D,CAAC,EAE7DjB,EAAsB,CAC1B,aAAc,CAACd,EAAaF,IAAmB,CAC7C,IAAMkC,EAAUjF,EAAO,IAAIiD,CAAG,GAAK,EAAGiC,EAAU1D,IAAUuB,IAAU,MAAQ,OAAOA,GAAU,SAAYqB,GAAcC,GAAUtB,CAAK,EAAG,EAAI,EAAIA,EAE3IoC,GADajE,EAAiB,GAAKC,GAAgB,IAAM,GACnCsB,GAAeyC,CAAM,EAAI,EAErDnD,GAAaA,GAAakD,EAAUE,EACpCnF,EAAO,IAAIiD,EAAKkC,CAAO,EACvBrF,EAAO,IAAImD,EAAKiC,CAAM,EAAGnF,EAAU,IAAIkD,GAAMlD,EAAU,IAAIkD,CAAG,GAAK,GAAK,CAAC,EACzEhB,GAAY,IACd,EAOA,gBAAiB,CAACmD,EAAoBC,EAAoBC,IAAwC,CAChG,IAAMC,EAAetC,GACnBA,IAAQ,aAAeA,IAAQ,eAAiBA,IAAQ,YAE1D,GAAIsC,EAAYH,CAAU,GAAKG,EAAYF,CAAU,EAAG,CACtD,QAAQ,KAAK,wDAAyDD,EAAYC,CAAU,EAC5F,MACF,CAEKL,GAAiBI,CAAU,IAAGJ,GAAiBI,CAAU,EAAI,CAAC,GACnEJ,GAAiBI,CAAU,EAAGC,CAAU,EAAIC,CAC9C,EACA,IAAK,CAACrC,EAAauC,EAAkBC,EAA0B,CAAC,IAAe,CAC7E,IAAMC,EAAS5F,EAAO,IAAImD,CAAG,EAAG0C,EAASnE,IAAU,OAAOgE,GAAY,WAAaI,GAAeF,EAAQF,CAAmC,EAAIA,EACjJ,GAAInE,IAAkB,CAAUwE,EAAY5C,CAAG,EAAK,OAAKpC,GAAS,QAAQ,KAAK,yBAAyBoC,CAAG,EAAE,EAAU,GACvH,GAAI,CAAU6C,GAAcpF,EAAcuC,EAAK,QAAS1B,EAAO,EAAK,OAAAgB,GAAO,MAAOU,EAAK,GAAO,aAAa,EAAQpC,GAAS,QAAQ,MAAM,6BAA6BoC,CAAG,GAAG,EAAU,GAEvL,IAAM8C,EAAO1E,GAA0B2E,EAAcL,CAAM,EAAIA,EACzDV,EAAUjF,EAAO,IAAIiD,CAAG,GAAK,EACnCC,GAAS,cAAe,CAAE,IAAAD,EAAK,MAAO8C,EAAM,MAAOhC,EAAU,QAAShE,EAAU,IAAIkD,CAAG,GAAK,CAAE,CAAC,EAE/F,IAAMiC,GAAU1D,IAAUuE,IAAS,MAAQ,OAAOA,GAAS,SAAY3B,GAAaC,GAAU0B,CAAI,EAAG,EAAI,EAAIA,EAE7G,GAAI,CAAC5B,GAAQuB,EAAQR,EAAM,EAAG,CAE5B,IAAMe,IADa/E,EAAiB,GAAKC,GAAgB,IAAM,GACjCsB,GAAeyC,EAAM,EAAI,EAEvD,GAAIhE,EAAiB,GAAK+E,GAAY/E,EAAgB,CACpD,IAAMsC,GAAQ,IAAI,MAAM,gBAAgByC,EAAS,kCAAkC/E,CAAc,SAAS,EACtGD,EAAUA,EAASuC,GAAO,CAAE,UAAW,MAAO,IAAAP,CAAI,CAAC,EAC7CpC,GAAS,QAAQ,KAAK,YAAY2C,GAAM,OAAO,SAASP,CAAG,GAAG,CAC1E,CAEA,GAAI9B,GAAgB,EAAG,CACrB,IAAM+E,GAAMnE,GAAakD,EAAUgB,GACnC,GAAIC,GAAM/E,GAAe,CACvB,IAAMqC,GAAQ,IAAI,MAAM,qBAAqB0C,EAAG,0BAA0B/E,EAAa,SAAS,EAC5FF,EAAUA,EAASuC,GAAO,CAAE,UAAW,KAAM,CAAC,EACxC3C,GAAS,QAAQ,KAAK,YAAY2C,GAAM,OAAO,EAAE,CAC7D,CACF,CAEAzB,GAAaA,GAAakD,EAAUgB,GACpCjG,EAAO,IAAIiD,EAAKgD,EAAS,EACzBnG,EAAO,IAAImD,EAAKiC,EAAM,EAAGnF,EAAU,IAAIkD,GAAMlD,EAAU,IAAIkD,CAAG,GAAK,GAAK,CAAC,EAEzEhB,GAAY,KAEZ,IAAMkE,GAAgBV,EAAQ,SAAWhE,GACzC,OAAI0E,KACF3F,EAAW,IAAIyC,EAAK,CAAE,MAAOiC,GAAQ,QAAS,CAAE,GAAGO,EAAS,QAASU,GAAe,QAASV,EAAQ,SAAW5F,GAAQ,OAAQ,CAAE,CAAC,EAAOmC,IAAY,aAAaA,EAAU,EAAGA,GAAa,WAAW8C,GAAYhE,EAAa,GAEnOoC,GAAS,QAAS,CAAE,IAAAD,EAAK,MAAOiC,GAAQ,MAAOnB,EAAU,QAAShE,EAAU,IAAIkD,CAAG,CAAE,CAAC,EACtFV,GAAO,MAAOU,EAAK,EAAI,EACvBqB,GAAMrB,CAAG,EACF,EACT,CACA,MAAO,EACT,EACA,IAASA,GAA0B,CACjC,GAAI,CAAU6C,GAAcpF,EAAcuC,EAAK,OAAQ1B,EAAO,EAC5D,OAAAgB,GAAO,MAAOU,EAAK,GAAO,aAAa,EAChC,KAET,IAAMP,EAAM5C,EAAO,IAAImD,CAAG,EAC1B,OAAAC,GAAS,QAAS,CAAE,MAAOa,EAAU,IAAAd,EAAK,MAAOP,CAAI,CAAC,EACtDH,GAAO,MAAOU,EAAK,EAAI,EAChBP,CACT,EACA,QAAS,CAAIO,EAAamD,IAAqC,CAC7D,GAAI,CACF,OAAK/F,EAAU,IAAI4C,CAAG,IAAK5C,EAAU,IAAI4C,EAAK,CAAE,SAAUmD,EAAuC,UAAW,KAAM,KAAM,IAAI,GAAM,CAAC,EAAGzC,GAAgBV,CAAG,GAClJ5C,EAAU,IAAI4C,CAAG,EAAG,SAC7B,OAAS0B,EAAG,CACV,IAAMnB,EAAQmB,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EAC1D,OAAI1D,EAAUA,EAASuC,EAAO,CAAE,UAAW,UAAW,IAAAP,CAAI,CAAC,EACjDpC,GAAS,QAAQ,MAAM,+BAA+BoC,CAAG,MAAO0B,CAAC,EACpE,IACT,CACF,EACA,MAAO,CAAI1B,EAAaoD,IAAiC,CAClDjG,EAAU,IAAI6C,CAAG,GAAG7C,EAAU,IAAI6C,EAAK,IAAI,GAAK,EACrD,IAAMqD,EAAMlG,EAAU,IAAI6C,CAAG,EAAI,OAAAqD,EAAI,IAAID,CAAoC,EACtE,IAAM,CAAEC,EAAI,OAAOD,CAAoC,EAAOC,EAAI,OAAS,GAAGlG,EAAU,OAAO6C,CAAG,CAAE,CAC7G,EACA,OAASA,GAAyB,CAChC,GAAI,CAAU6C,GAAcpF,EAAcuC,EAAK,SAAU1B,EAAO,EAC9D,OAAAgB,GAAO,SAAUU,EAAK,GAAO,aAAa,EACnC,GAET,IAAMsD,EAAMzG,EAAO,IAAImD,CAAG,EAAGuD,EAAU1G,EAAO,OAAOmD,CAAG,EACxD,OAAIuD,IACFzE,IAAe/B,EAAO,IAAIiD,CAAG,GAAK,EAClCjD,EAAO,OAAOiD,CAAG,EACjBC,GAAS,WAAY,CAAE,MAAOa,EAAU,IAAAd,EAAK,MAAOsD,CAAI,CAAC,EACzDtE,GAAY,MAEdlC,EAAU,IAAIkD,GAAMlD,EAAU,IAAIkD,CAAG,GAAK,GAAK,CAAC,EAC5CjC,GAAUA,EAAS,WAAW,GAAGqB,GAAW,CAAC,GAAGY,CAAG,EAAE,EAEzDV,GAAO,SAAUU,EAAK,EAAI,EAC1BqB,GAAMrB,CAAG,EAAUuD,CACrB,EACA,OAASvD,GAAgBc,EAAS,OAAOd,CAAG,EAC5C,UAAW,IAAM,CAEf,GADA,MAAM,KAAKnD,EAAO,KAAK,CAAC,EAAE,QAAQL,GAAKsE,EAAS,OAAOtE,CAAC,CAAC,EACrDuB,EAAU,CACZ,IAAMyF,EAAS7F,EAAa,IAC5B,QAASjB,EAAI,EAAGA,GAAKqB,EAAS,QAAU,GAAIrB,IAAK,CAC/C,IAAMF,EAAIuB,EAAS,IAAIrB,CAAC,EAAOF,GAAG,WAAWgH,CAAM,IAAKzF,EAAS,WAAWvB,CAAC,EAAGE,IAClF,CACF,CACA,OAAAoC,GAAa,EACb/B,EAAO,MAAM,EACbiC,GAAY,KACL,EACT,EACA,KAAM,IAAM,OAAO,YAAYnC,EAAO,QAAQ,CAAC,EAC/C,IAAM4G,GAAkB,CAAEvG,EAAa,IAAIuG,CAAC,CAAE,EAC9C,YAAcpB,GAAmB,CAC/B1D,GAAiB,GAAMsB,GAAS,gBAAiB,CAAE,MAAOa,EAAU,IAAK,OAAQ,CAAC,EAClF,GAAI,CAAEuB,EAAG,CAAE,QAAE,CAAU1D,GAAiB,GAAOsB,GAAS,gBAAiB,CAAE,MAAOa,EAAU,IAAK,KAAM,CAAC,EAAOlC,KAAgBA,GAAe,GAAOyC,GAAM,EAAI,CACjK,EACA,QAAS,IAAM,CACTtC,KAAc,aAAaA,EAAU,EAAGA,GAAa,MACzDxB,EAAW,MAAM,EACb,OAAO,OAAW,KAAa,OAAO,oBAAoB,eAAgBmG,EAAc,EAC5FzD,GAAS,YAAa,CAAE,MAAOa,CAAS,CAAC,EACzC9D,EAAW,MAAM,EAAGC,EAAc,MAAM,EAAGE,EAAU,MAAM,EAAGC,EAAU,MAAM,EAC9EC,EAAc,MAAM,EAAGC,EAAS,MAAM,EAAGT,EAAO,MAAM,EAAGE,EAAO,MAAM,EAAG+B,GAAa,EACtFrB,EAAa,MAAM,EAAGC,EAAU,MAAM,EAAGZ,EAAU,MAAM,EAAGU,EAAY,MAAM,EAAGN,EAAa,MAAM,CACtG,EACA,WAAayG,GAAkB,CACrBC,GAAcrE,GAAiB,EAAGoE,EAAG7C,CAAQ,CACvD,EACA,cAAgBZ,GAAiB,CAAE5C,EAAS,OAAO4C,CAAI,CAAE,EACzD,WAAY,CAAC2D,EAAqB7D,IAAiB,CACjD,GAAIA,EAAK,CACF/C,EAAc,IAAI+C,CAAG,GAAG/C,EAAc,IAAI+C,EAAK,IAAI,GAAK,EAC7D,IAAMqD,EAAMpG,EAAc,IAAI+C,CAAG,EAAI,OAAAqD,EAAI,IAAIQ,CAAE,EACxC,IAAM,CAAER,EAAI,OAAOQ,CAAE,EAAOR,EAAI,OAAS,GAAGpG,EAAc,OAAO+C,CAAG,CAAE,CAC/E,CACA,OAAAhD,EAAW,IAAI6G,CAAE,EAAU,IAAM7G,EAAW,OAAO6G,CAAE,CACvD,EACA,YAAc7D,GAAgBlD,EAAU,IAAIkD,CAAG,GAAK,EAGpD,cAAe,CAAC8D,EAASC,IAAyBrF,GAAcjB,EAAcqG,EAASC,CAAW,EAClG,cAAe,CAAC/D,EAAKK,EAAQ2D,IAAW,CACtC,GAAIvG,EAAa,OAAS,EAAG,MAAO,GACpC,OAAW,CAACqG,EAASG,CAAK,IAAKxG,EAAc,CAC3C,IAAIyG,EACJ,GAAI,OAAOJ,GAAY,WACrBI,EAAUJ,EAAQ9D,EAAKgE,CAAM,MAE7B,IAAI,CACF,IAAIG,EAAK3G,EAAY,IAAIsG,CAAO,EAC3BK,IAAMA,EAAK,IAAI,OAAOL,CAAO,EAAGtG,EAAY,IAAIsG,EAASK,CAAE,GAChED,EAAUC,EAAG,KAAKnE,CAAG,CACvB,MAAQ,CAAE,QAAS,CAErB,GAAIkE,EAAS,OAAOD,EAAM,SAAS5D,CAAM,GAAK4D,EAAM,SAAS,OAAO,CACtE,CACA,MAAO,EACT,EACA,cAAe,CAACD,EAAQI,EAASC,IAAqBC,GAAc5G,EAAWsG,EAAQI,EAASC,CAAO,EACvG,WAAY,CAACL,EAAQI,IAAqBG,GAAW7G,EAAWsG,EAAQI,CAAO,EAC/E,YAAcJ,GAAoBQ,GAAY9G,EAAWsG,CAAM,EAC/D,cAAe,CAACA,EAAQI,IAAqBK,GAAc/G,EAAWsG,EAAQI,CAAO,EACrF,eAAiBJ,GAAoBU,GAAehH,EAAWsG,CAAM,EACrE,eAAiBA,GAAoBW,GAAejH,EAAWsG,CAAM,EAErE,YAAa,KACNhF,KACHA,GAAY,OAAO,YAAYnC,EAAO,QAAQ,CAAC,GAE1CmC,IAGT,IAAI,SAAU,CAAE,OAAO+C,EAA6C,EACpE,IAAI,SAAU,CAAE,OAAOlD,EAAS,EAChC,IAAI,WAAY,CAAE,OAAOlB,CAAW,EACpC,IAAI,QAAS,CAAE,OAAOW,EAAQ,EAC9B,UAAW,IAAMY,EACnB,EAEmB,CAAC,gBAAiB,gBAAiB,aAAc,cAAe,gBAAiB,iBAAkB,gBAAgB,EAC3H,QAAQuE,GAAK,CACtB,IAAMpB,EAAMvB,EAAwE2C,CAAC,EACjFpB,GAAIvB,EAAS,gBAAgB,WAAY2C,EAAGpB,CAAE,CACpD,CAAC,EAED,IAAMqB,GAAiB,IAAM,CAAMnG,EAAW,KAAO,GAAGsE,GAAW,CAAE,EACjE,OAAO,OAAW,KAAa,OAAO,iBAAiB,eAAgB6B,EAAc,EAErF3F,EACU6G,GACVvF,GAAsB,EAErBI,IACoBxB,EAAiB,GAAKC,GAAgB,IAAM,GAC5CsB,GAAeC,CAAG,EAAI,EAE3C,IAAM,CAAEZ,GAAW,GAAMG,GAAY,KAAMC,GAAe,EAAGoC,GAAM,CAAE,CACvE,EAAE,KAAK,IAAM,CAGb,CAAC,GACMxC,GAAW,GAAMI,GAAgB,GAG1C,IAAI4F,GAAoC,KACxC,OAAKjI,GAA2B,OAC9BiI,GAAc,IAAIC,EAAWhE,EAAWlE,EAA0B,IAAK,EAEvEkE,EAAS,gBAAgB,OAAQ,QAAS,IAAM+D,IAAa,MAAM,CAAC,EACpE/D,EAAS,gBAAgB,OAAQ,WAAY,IAAM+D,IAAa,SAAS,CAAC,EAE1E/D,EAAS,gBAAgB,OAAQ,gBAAkB+C,GAAYgB,IAAa,cAAchB,CAAE,CAAC,GAGxF/C,CACT,EMreA,OAAS,wBAAAiE,GAAsB,iBAAAC,GAAe,WAAAC,GAAS,eAAAC,GAAa,aAAAC,GAAW,YAAAC,OAAgB,QAK/F,IAAIC,GAAwD,KAQ/CC,EACXC,GACc,CACVF,IAAiB,CAACE,GAAQ,YACvBA,GAAQ,QACX,QAAQ,KACN,qFACF,GAIJ,IAAMC,EAAQC,EAAeF,CAAM,EACnC,OAAAF,GAAgBG,EACTA,CACT,EAMaE,EAAe,IAAY,CAClCL,KACFA,GAAc,QAAQ,EACtBA,GAAgB,KAEpB,EAOaM,EAAmBH,GAAqD,CACnF,IAAMI,EAAcJ,GAASH,GAEvBQ,EAAYC,GAAQ,IACvBC,GAAyBH,EAAcA,EAAY,WAAWG,CAAQ,EAAI,IAAM,CAAE,EACnF,CAACH,CAAW,CACd,EAEA,OAAOI,GACLH,EACA,IAAMD,EAAcA,EAAY,QAAU,GAC1C,IAAM,EACR,CACF,EAMaK,EAAW,IAA8CZ,GAwB/D,SAASa,EACdC,EACAC,EAC+F,CAE/F,IAAMC,EAAcC,GAAQ,IACzBF,GAASG,GACV,CAACH,CAAK,CACR,EAGMI,EAAaF,GAAQ,IAAM,CAC/B,IAAMG,EAAO,IAAM,CAAE,EACfC,EAAY,IAAM,GAClBC,EAAW,IAAM,KACvB,MAAO,CACL,IAAKD,EAAW,IAAKC,EAAU,OAAQD,EAAW,OAAQA,EAC1D,UAAWA,EAAW,KAAM,KAAO,CAAC,GAAI,QAASC,EACjD,MAAO,IAAM,IAAM,CAAE,EAAG,IAAKF,EAAM,YAAaA,EAAM,QAASA,EAC/D,WAAY,IAAM,IAAM,CAAE,EAAG,aAAcA,EAAM,gBAAiBA,EAClE,WAAYA,EAAM,cAAeA,EAAM,YAAa,IAAM,EAC1D,IAAI,SAAU,CAAE,MAAO,EAAM,EAAG,UAAW,IAAM,QAAQ,QAAQ,EACjE,IAAI,SAAU,CAAE,MAAO,CAAC,CAAE,EAC1B,YAAa,KAAO,CAAC,GACrB,IAAI,WAAY,CAAE,MAAO,OAAQ,EAAG,IAAI,QAAS,CAAmB,CACtE,CACF,EAAG,CAAC,CAAC,EAECG,EAAYP,GAAeG,EAE3BK,EAAa,OAAOV,GAAkB,WACtCW,EAAOD,EAAyC,KAA3BV,EACrBY,EAAWF,EAAcV,EAAoC,KAG7Da,EAAYC,GACfC,GACKL,EAEKD,EAAU,WAAWM,CAAQ,EAG7BN,EAAU,WAAWM,EAAUJ,CAAI,EAG9C,CAACF,EAAWC,EAAYC,CAAG,CAC7B,EAGMK,EAAcF,GAAY,IAC1BJ,EACKE,EAAUH,EAAU,YAAY,CAAC,EAEjCA,EAAU,IAAOE,CAAI,GAAK,OAElC,CAACF,EAAWC,EAAYC,EAAKC,CAAQ,CAAC,EAGnCK,EAAoBH,GAAY,IAAM,CAC1C,GAAIJ,EACF,GAAI,CAAE,OAAOE,EAAU,CAAC,CAAM,CAAE,MAAQ,CAAE,MAAiB,KAE3D,OAEJ,EAAG,CAACA,EAAUF,CAAU,CAAC,EAEnBQ,EAAQC,GACZN,EACAG,EACAC,CACF,EAGMG,EAASN,GACb,CAACO,EAA0BC,IACrBZ,EAIK,GAEFD,EAAU,IAAOE,EAAMU,EAAKC,CAAO,EAE5C,CAACb,EAAWC,EAAYC,CAAG,CAC7B,EAKA,OAFAY,GAAcL,EAAOM,GAAKd,EAAa,aAAa,KAAK,UAAUc,CAAC,CAAC,GAAK,GAAGb,CAAG,KAAK,KAAK,UAAUa,CAAC,CAAC,EAAE,EAEpGd,EACKQ,EAGF,CAACA,EAAOE,CAAM,CACvB,CAGA,IAAMK,GAAe,IAAI,IAQZC,EAAW,CACtBzB,EACA0B,IACwC,CACxC,IAAMhB,EAAMV,EAAM,UAClB,GAAIwB,GAAa,IAAId,CAAG,EACtB,eAAQ,KAAK,sDAAsDA,CAAG,4BAA4B,EAC3Fc,GAAa,IAAId,CAAG,EAG7B,IAAMiB,EAAS,IAAIC,EAAW5B,EAAO0B,CAAM,EAC3C,OAAAF,GAAa,IAAId,EAAKiB,CAAM,EACrBA,CACT,EAKaE,EAAeC,GAA4B,CACtD,IAAMH,EAASH,GAAa,IAAIM,CAAS,EACrCH,IACFA,EAAO,QAAQ,EACfH,GAAa,OAAOM,CAAS,EAEjC,EAmBO,SAASC,EACdrB,EACAV,EAKA,CACA,IAAMC,EAAcD,GAASG,GACvB2B,EAAY7B,GAAa,WAAa,UAGtC0B,EAASH,GAAa,IAAIM,CAAS,EAInCE,EAASlC,EAASY,EAAKT,CAAkB,EACzCgB,EAAQe,EAAO,CAAC,EAChBb,EAASa,EAAO,CAAC,EAGjB,CAACC,EAAWC,CAAY,EAAIC,GAAoB,IAAMR,GAAQ,SAAS,GAAK,CAChF,SAAU,GACV,UAAW,GACX,kBAAmB,KACnB,eAAgB,EAChB,UAAW,CACb,CAAC,EAGDS,GAAU,IACHT,EAEeA,EAAO,cAAcO,CAAY,EAFxC,OAIZ,CAACP,CAAM,CAAC,EAGX,IAAMU,EAAexB,GACnB,CAACO,EAA0BC,IAA6B,CACtD,IAAMW,EAASb,EAAOC,EAAKC,CAAO,EAElC,GAAIW,GAAUL,EAAQ,CAEpB,IAAMW,EAAerC,GAAa,IAAIS,CAAG,EACzCiB,EAAO,YAAYjB,EAAK4B,CAAY,CACtC,CAEA,OAAON,CACT,EACA,CAACb,EAAQQ,EAAQjB,EAAKT,CAAW,CACnC,EAEA,MAAO,CAACgB,EAAOoB,EAAcJ,CAAS,CACxC,CASO,IAAMM,EAAgB,IAAiB,CAC5C,GAAM,CAACC,EAAOC,CAAQ,EAAIN,GAAoB,CAC5C,SAAU,GACV,UAAW,GACX,kBAAmB,KACnB,eAAgB,EAChB,UAAW,CACb,CAAC,EAED,OAAAC,GAAU,IAAM,CAEd,IAAMM,EAAc,IAAM,CACxB,IAAIC,EAAW,GACXC,EAAY,GACZC,EAAiB,EACjBC,EAAY,EAEhBtB,GAAa,QAAQG,GAAU,CAC7B,IAAMoB,EAAIpB,EAAO,SAAS,EAC1BgB,EAAWA,GAAYI,EAAE,SACzBH,EAAYA,GAAaG,EAAE,UAC3BF,GAAkBE,EAAE,eACpBD,GAAaC,EAAE,SACjB,CAAC,EAEDN,EAAS,CACP,SAAAE,EACA,UAAAC,EACA,kBAAmB,KACnB,eAAAC,EACA,UAAAC,CACF,CAAC,CACH,EAEAJ,EAAY,EAGZ,IAAMM,EAAe,MAAM,KAAKxB,GAAa,OAAO,CAAC,EAAE,IAAIG,GACzDA,EAAO,cAAce,CAAW,CAClC,EAEA,MAAO,IAAMM,EAAa,QAAQC,GAAMA,EAAG,CAAC,CAC9C,EAAG,CAAC,CAAC,EAEET,CACT,EAKaU,EAAc,MAAOpB,GAAsC,CACtE,IAAMqB,EAAkBrB,GAAa3B,IAAe,UACpD,GAAI,CAACgD,EAAiB,OAEtB,IAAMxB,EAASH,GAAa,IAAI2B,CAAe,EAC3CxB,GACF,MAAMA,EAAO,MAAM,CAEvB,EC/UO,IAAMyB,EAAmB,CAC9BC,EACAC,IAC6E,CAI7E,IAAMC,EAAMD,GAAS,KAAO,aAKtBE,EAAQF,GAAS,OAASG,EAA2C,CACzE,UAAW,SAASF,CAAG,GACvB,OAAQ,EACV,CAAC,EAGD,OAAIC,EAAM,IAAID,CAAG,GAAK,MACpBC,EAAM,IAAID,EAAK,CAAE,KAAM,KAAM,QAAS,GAAO,MAAO,KAAM,UAAW,IAAK,CAAC,EAoCtE,OAAO,OAAOC,EAAO,CAAE,QA9BlB,SAAY,CACtB,IAAME,EAAUF,EAAM,IAAID,CAAG,EAC7BC,EAAM,IAAID,EAAK,CACb,GAAIG,GAAW,CAAE,KAAM,KAAM,QAAS,GAAO,MAAO,KAAM,UAAW,IAAK,EAC1E,QAAS,GACT,MAAO,IACT,CAAC,EAGG,cAAeF,GAAS,CAACA,EAAM,SAAS,MAAMA,EAAM,UAAU,EAElE,GAAI,CACF,IAAMG,EAAS,MAAMN,EAAS,EACxBO,EAAOJ,EAAM,IAAID,CAAG,EAC1BC,EAAM,IAAID,EAAK,CACb,GAAIK,GAAQ,CAAE,KAAM,KAAM,QAAS,GAAO,MAAO,KAAM,UAAW,IAAK,EACvE,KAAMD,EACN,QAAS,GACT,UAAW,KAAK,IAAI,CACtB,EAAG,CAAE,QAASL,GAAS,OAAQ,CAAC,CAClC,OAASO,EAAY,CACnB,IAAMD,EAAOJ,EAAM,IAAID,CAAG,EAC1BC,EAAM,IAAID,EAAK,CACb,GAAIK,GAAQ,CAAE,KAAM,KAAM,QAAS,GAAO,MAAO,KAAM,UAAW,IAAK,EACvE,MAAOC,aAAa,MAAQA,EAAI,IAAI,MAAM,OAAOA,CAAC,CAAC,EACnD,QAAS,EACX,CAAC,CACH,CACF,CAE2C,CAAC,CAC9C,ECvEO,IAAMC,GAAc,KAAsD,CAC/E,KAAM,eACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAC,CAAM,IAAM,CAExBA,EAAM,gBAAgB,QAAS,kBAAmB,CAACC,EAAaC,IACvDF,EAAM,IAAIC,EAAKC,CAAO,EACM,CACvC,CACF,CACF,GCTO,IAAMC,GAAqDC,GAA6C,CAE7G,IAAIC,EAAsC,CAAC,EAEvCC,EAAU,GAEVC,EAAe,GAGbC,EAASJ,GAAS,OAAS,GAEjC,MAAO,CACL,KAAM,mBACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAK,CAAM,IAAM,CAExBJ,EAAS,KAAKI,EAAM,KAAK,CAAC,EAC1BH,EAAU,EAGVG,EAAM,gBAAgB,WAAY,OAAQ,IAAM,CAC9C,GAAIH,EAAU,EAAG,CACfC,EAAe,GACfD,IACA,IAAMI,EAAWL,EAASC,CAAO,EACjC,OAAKI,GAGL,OAAO,QAAQA,CAAQ,EAAE,QAAQ,CAAC,CAACC,EAAGC,CAAC,IAAM,CAC3CH,EAAM,aAAaE,EAAGC,CAAC,CACzB,CAAC,EAEDL,EAAe,GACR,IARe,EASxB,CACA,MAAO,EACT,CAAC,EAEDE,EAAM,gBAAgB,WAAY,OAAQ,IAAM,CAC9C,GAAIH,EAAUD,EAAS,OAAS,EAAG,CACjCE,EAAe,GACfD,IACA,IAAMI,EAAWL,EAASC,CAAO,EACjC,OAAKI,GAEL,OAAO,QAAQA,CAAQ,EAAE,QAAQ,CAAC,CAACC,EAAGC,CAAC,IAAM,CAC3CH,EAAM,aAAaE,EAAGC,CAAC,CACzB,CAAC,EAEDL,EAAe,GACR,IAPe,EAQxB,CACA,MAAO,EACT,CAAC,EAEDE,EAAM,gBAAgB,WAAY,UAAW,IAAMH,EAAU,CAAC,EAC9DG,EAAM,gBAAgB,WAAY,UAAW,IAAMH,EAAUD,EAAS,OAAS,CAAC,CAClF,EAEA,MAAO,CAAC,CAAE,MAAAI,CAAM,IAAM,CAChBF,IAGAD,EAAUD,EAAS,OAAS,IAC9BA,EAAWA,EAAS,MAAM,EAAGC,EAAU,CAAC,GAI1CD,EAAS,KAAKI,EAAM,KAAK,CAAC,EAEtBJ,EAAS,OAASG,EACpBH,EAAS,MAAM,EAEfC,IAEJ,CACF,CACF,CACF,EC/EO,IAAMO,GAAgBC,IAA0E,CACrG,KAAM,gBACN,MAAO,CACL,MAAO,CAAC,CAAE,IAAAC,EAAK,MAAAC,CAAM,IAAM,CACzB,GAAI,CAACD,EAAK,OACV,IAAME,EAAYH,EAAQC,CAAG,EAE7B,GAAIE,EAAW,CACb,IAAMC,EAASD,EAAUD,CAAK,EAE9B,GAAIE,IAAW,GACb,MAAM,IAAI,MAAM,6CAA6CH,CAAG,MAAMG,IAAW,GAAQ,eAAiBA,CAAM,EAAE,CAEtH,CACF,CACF,CACF,GCEO,IAAMC,GAAkBC,GAAyC,CAGtE,IAAMC,EAFM,WAEa,6BAEzB,GAAI,CAACA,GAAW,QACd,MAAO,CAAE,KAAM,uBAAwB,MAAO,CAAC,CAAE,EAInD,IAAIC,EAAqC,KAEzC,MAAO,CACL,KAAM,kBACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAC,CAAM,IAAM,CACxBD,EAAYD,EAAU,QAAQ,CAAE,KAAMD,GAAS,MAAQ,gBAAiB,CAAC,EACzEE,EAAU,KAAKC,EAAM,KAAK,CAAC,CAC7B,EACA,MAAO,CAAC,CAAE,IAAAC,EAAK,MAAAD,CAAM,IAAM,CACrB,CAACC,GAAO,CAACF,GAEbA,EAAU,KAAK,OAAOE,EAAI,YAAY,CAAC,GAAID,EAAM,KAAK,CAAC,CACzD,EACA,SAAU,CAAC,CAAE,IAAAC,EAAK,MAAAD,CAAM,IAAM,CACxB,CAACC,GAAO,CAACF,GACbA,EAAU,KAAK,UAAUE,EAAI,YAAY,CAAC,GAAID,EAAM,KAAK,CAAC,CAC5D,CACF,CACF,CACF,ECjDO,IAAME,GAAiB,IAAe,CAE3C,IAAMC,EAAa,IAAI,IAEvB,MAAO,CACL,KAAM,kBACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAC,CAAM,IAAM,CACxBA,EAAM,gBAAgB,WAAY,gBAAkBC,GAAiB,CACnEF,EAAW,IAAIE,EAAMD,EAAM,KAAK,CAAC,CACnC,EAAqC,EAErCA,EAAM,gBAAgB,WAAY,mBAAqBC,GAAiB,CACtE,IAAMC,EAAOH,EAAW,IAAIE,CAAI,EAChC,OAAKC,GAELF,EAAM,YAAY,IAAM,CACtB,OAAO,QAAQE,CAAI,EAAE,QAAQ,CAAC,CAACC,EAAGC,CAAC,IAAM,CACvCJ,EAAM,IAAIG,EAAGC,CAAC,CAChB,CAAC,CACH,CAAC,EACM,IAPW,EAQpB,EAAqC,EAErCJ,EAAM,gBAAgB,WAAY,iBAAkB,IAAM,MAAM,KAAKD,EAAW,KAAK,CAAC,EAAqC,EAC3HC,EAAM,gBAAgB,WAAY,kBAAoBC,GAAiBF,EAAW,OAAOE,CAAI,EAAqC,EAClID,EAAM,gBAAgB,WAAY,kBAAmB,IAAMD,EAAW,MAAM,EAAqC,CACnH,CACF,CACF,CACF,EC7BO,IAAMM,GAAeC,IAAgE,CAC1F,KAAM,eACN,MAAO,CACL,YAAa,CAAC,CAAE,IAAAC,EAAK,MAAAC,EAAO,MAAOC,CAAO,IAAM,CAC9C,GAAI,CAACF,EAAK,OACV,IAAMG,EAAQJ,EAAOC,CAAG,EAExB,GAAIG,EAAO,CACT,IAAMC,EAAcD,EAAMF,CAAK,CAOjC,CACF,CACF,CACF,GClBO,IAAMI,GAAmBC,IAGhB,CACd,KAAM,mBACN,MAAO,CACL,MAAO,CAAC,CAAE,IAAAC,EAAK,MAAAC,CAAM,IAAM,CACpBD,IACD,CAACD,EAAQ,MAAQA,EAAQ,KAAK,SAASC,CAAG,IAC5CD,EAAQ,SAAS,CAAE,IAAAC,EAAK,MAAAC,EAAO,OAAQ,KAAM,CAAC,CAElD,EACA,SAAU,CAAC,CAAE,IAAAD,CAAI,IAAM,CAChBA,IACD,CAACD,EAAQ,MAAQA,EAAQ,KAAK,SAASC,CAAG,IAC5CD,EAAQ,SAAS,CAAE,IAAAC,EAAK,MAAO,KAAM,OAAQ,QAAS,CAAC,CAE3D,CACF,CACF,GCnBO,IAAME,GAAcC,GAAgD,CAEzE,IAAMC,EAAW,IAAI,iBAAiBD,GAAS,aAAe,aAAa,EAGvEE,EAAa,GAEjB,MAAO,CACL,KAAM,cACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAC,CAAM,IAAM,CACxBF,EAAS,UAAaG,GAAU,CAC9B,GAAM,CAAE,IAAAC,EAAK,MAAAC,EAAO,OAAAC,CAAO,EAAIH,EAAM,KAChCC,IACLH,EAAa,GACTK,IAAW,SACbJ,EAAM,OAAOE,CAAG,EAEhBF,EAAM,IAAIE,EAAKC,CAAK,EAEtBJ,EAAa,GACf,CACF,EACA,MAAO,CAAC,CAAE,IAAAG,EAAK,MAAAC,CAAM,IAAM,CACrB,CAACD,GAAOH,GACZD,EAAS,YAAY,CAAE,IAAAI,EAAK,MAAAC,EAAO,OAAQ,KAAM,CAAC,CACpD,EACA,SAAU,CAAC,CAAE,IAAAD,CAAI,IAAM,CACjB,CAACA,GAAOH,GACZD,EAAS,YAAY,CAAE,IAAAI,EAAK,OAAQ,QAAS,CAAC,CAChD,EACA,UAAW,IAAM,CACfJ,EAAS,MAAM,CACjB,CACF,CACF,CACF,ECzBO,IAAMO,GAAc,KAGhB,CAAE,KAAM,oBAAqB,MAAO,CAAC,CAAE,GCP3C,IAAMC,GAAkB,CAAoCC,EAA4B,CAAC,IAAkB,CAChH,IAAMC,EAASD,EAAQ,QAAU,SAC3BE,EAAYF,EAAQ,WAAa,SACjCG,EAAYH,EAAQ,SAAW,EACjCI,EAAyB,KAEvBC,EAAQ,IACL,IAAI,QAAQ,CAACC,EAASC,IAAW,CACtC,GAAIH,EAAI,OAAOE,EAAQF,CAAE,EACzB,IAAMI,EAAU,UAAU,KAAKP,EAAQE,CAAS,EAChDK,EAAQ,QAAU,IAAMD,EAAOC,EAAQ,KAAK,EAC5CA,EAAQ,UAAY,IAAM,CACxBJ,EAAKI,EAAQ,OACbF,EAAQF,CAAE,CACZ,EACAI,EAAQ,gBAAmBC,GAAiC,CAC1D,IAAMC,EAAYD,EAAM,OAA4B,OAC/CC,EAAS,iBAAiB,SAASR,CAAS,GAC/CQ,EAAS,kBAAkBR,CAAS,CAExC,CACF,CAAC,EAGGS,EAAO,MAAOC,EAAaC,IAAmB,CAClD,IAAMH,EAAW,MAAML,EAAM,EAC7B,OAAO,IAAI,QAAc,CAACC,EAASC,IAAW,CAG5C,IAAMC,EAFKE,EAAS,YAAYR,EAAW,WAAW,EACrC,YAAYA,CAAS,EAChB,IAAIW,EAAOD,CAAG,EACpCJ,EAAQ,UAAY,IAAMF,EAAQ,EAClCE,EAAQ,QAAU,IAAMD,EAAOC,EAAQ,KAAK,CAC9C,CAAC,CACH,EAEMM,EAAO,MAAOF,GAAkC,CACpD,IAAMF,EAAW,MAAML,EAAM,EAC7B,OAAO,IAAI,QAAQ,CAACC,EAASC,IAAW,CAGtC,IAAMC,EAFKE,EAAS,YAAYR,EAAW,UAAU,EACpC,YAAYA,CAAS,EAChB,IAAIU,CAAG,EAC7BJ,EAAQ,UAAY,IAAMF,EAAQE,EAAQ,MAAM,EAChDA,EAAQ,QAAU,IAAMD,EAAOC,EAAQ,KAAK,CAC9C,CAAC,CACH,EAEMO,EAAS,MAAOH,GAAgB,CACpC,IAAMF,EAAW,MAAML,EAAM,EAC7B,OAAO,IAAI,QAAc,CAACC,EAASC,IAAW,CAG5C,IAAMC,EAFKE,EAAS,YAAYR,EAAW,WAAW,EACrC,YAAYA,CAAS,EAChB,OAAOU,CAAG,EAChCJ,EAAQ,UAAY,IAAMF,EAAQ,EAClCE,EAAQ,QAAU,IAAMD,EAAOC,EAAQ,KAAK,CAC9C,CAAC,CACH,EAEA,MAAO,CACL,KAAM,YACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAQ,CAAM,IAAM,CAExBA,EAAM,gBAAgB,YAAa,QAAS,SAAY,EACrC,MAAMX,EAAM,GACT,YAAYH,EAAW,WAAW,EACnD,YAAYA,CAAS,EAAE,MAAM,CAClC,CAAC,CACH,EAEA,OAAQ,MAAO,CAAE,MAAAc,CAAM,IAAM,CAM3B,IAAMR,GAHW,MAAMH,EAAM,GACT,YAAYH,EAAW,UAAU,EAC9B,YAAYA,CAAS,EAChB,WAAW,EAEvCM,EAAQ,UAAY,SAAY,CAC9B,IAAMS,EAAOT,EAAQ,OACfU,EAAUF,EAA+C,UAAY,IAE3E,QAAWJ,KAAOK,EAChB,GAAIL,EAAI,WAAWM,CAAM,EAAG,CAC1B,IAAMC,GAAM,MAAML,EAAKF,CAAG,EAC1B,GAAIO,GAAK,CACP,IAAMC,GAAWR,EAAI,UAAUM,EAAO,MAAM,EAE3CF,EAA+C,aAAaI,GAAWD,GAAuB,CAAC,CAClG,CACF,CAEJ,CACF,EAEA,MAAO,MAAO,CAAE,IAAAP,EAAK,MAAAC,EAAO,MAAAG,CAAM,IAAM,CACtC,GAAI,CAACJ,EAAK,OACV,IAAMM,EAAUF,EAA+C,UAAY,IAErEK,EAAO,CACX,EAAGR,EACH,EAAG,KAAK,IAAI,EACZ,EAAIG,EAA+C,cAAcJ,CAAG,GAAK,CAC3E,EACA,MAAMD,EAAK,GAAGO,CAAM,GAAGN,CAAG,GAAIS,CAAI,CACpC,EAEA,SAAU,MAAO,CAAE,IAAAT,EAAK,MAAAI,CAAM,IAAM,CAClC,GAAI,CAACJ,EAAK,OACV,IAAMM,EAAUF,EAA+C,UAAY,IAC3E,MAAMD,EAAO,GAAGG,CAAM,GAAGN,CAAG,EAAE,CAChC,CACF,CACF,CACF,ECzFO,IAAMU,GAAsDC,GAA0C,CAC3G,GAAM,CAAE,QAAAC,EAAS,iBAAAC,CAAiB,EAAIF,EAGhCG,EAAqB,IAAI,IACzBC,EAAmB,CACvB,kBAAmB,KACnB,gBAAiB,EACjB,iBAAkB,EAClB,UAAW,EACX,aAAc,EACd,OAAQ,CACV,EAEIC,EAA+C,KAEnD,MAAO,CACL,KAAM,YACN,MAAO,CACL,UAAW,CAAC,CAAE,MAAAC,CAAM,IAAM,CAKxBA,EAAM,gBAAgB,YAAa,OAAQ,SAAY,CACrD,IAAMC,EAAY,YAAY,IAAI,EAC5BC,EAAqC,CAAC,EACxCC,EAAa,EAEjB,GAAI,CACF,IAAMC,EAAUJ,EAAM,KAAK,EACrBK,EAAO,OAAO,KAAKD,CAAO,EAEhC,QAAWE,KAAOD,EAAM,CACtB,IAAME,EAAkBP,EAA+C,cAAcM,CAAG,GAAK,EACvFE,EAAcX,EAAmB,IAAIS,CAAG,GAAK,EAEnD,GAAIC,EAAiBC,EAAa,CAChC,IAAMC,EAAML,EAAQE,CAAG,EACvBJ,EAAUI,CAAG,EAAIG,EACjBN,GAAc,KAAK,UAAUM,CAAG,EAAE,OAClCZ,EAAmB,IAAIS,EAAKC,CAAc,CAC5C,CACF,CAEA,GAAI,OAAO,KAAKL,CAAS,EAAE,SAAW,EAAG,MAAO,CAAE,OAAQ,YAAa,MAAAJ,CAAM,EAI7E,GAFgB,MAAMH,EAAQ,KAAKO,CAAS,EAG1C,OAAAJ,EAAM,kBAAoB,KAAK,IAAI,EACnCA,EAAM,iBAAmB,OAAO,KAAKI,CAAS,EAAE,OAChDJ,EAAM,kBAAoBK,EAC1BL,EAAM,YACNA,EAAM,aAAe,YAAY,IAAI,EAAIG,EACrCP,EAAQ,QAAQA,EAAQ,OAAOI,CAAK,EACjC,CAAE,OAAQ,UAAW,MAAAA,CAAM,EAElC,MAAM,IAAI,MAAM,WAAWH,EAAQ,IAAI,kBAAkB,CAE7D,OAASe,EAAK,CACZ,OAAAZ,EAAM,SACN,QAAQ,MAAM,+BAA+BH,EAAQ,IAAI,KAAMe,CAAG,EAC3D,CAAE,OAAQ,QAAS,MAAO,OAAOA,CAAG,EAAG,MAAAZ,CAAM,CACtD,CACF,CAAC,EAKDE,EAAM,gBAAgB,YAAa,WAAY,IAAMF,CAAK,EAGtDF,GAAoBA,EAAmB,IACzCG,EAAQ,YAAY,IAAM,CAExB,IAAMY,EADWX,EAA+C,QAC7C,UACfW,GAAIA,EAAG,KAAK,CAClB,EAAGf,CAAgB,EAEvB,EAEA,UAAW,IAAM,CACXG,GAAO,cAAcA,CAAK,CAChC,CACF,CACF,CACF,EASaa,GAAqB,CAACC,EAAgBC,KAAsC,CACvF,KAAM,gBACN,KAAM,MAAOC,IACM,MAAM,MAAM,GAAGF,CAAM,oBAAqB,CACzD,OAAQ,OACR,QAAS,CAAE,eAAgB,mBAAoB,UAAWC,CAAO,EACjE,KAAM,KAAK,UAAU,CACnB,WAAY,WACZ,SAAU,YACV,WAAY,cACZ,OAAQ,CAAE,GAAI,cAAe,EAC7B,OAAQ,CAAE,KAAM,CAAE,KAAAC,EAAM,UAAW,KAAK,IAAI,CAAE,CAAE,EAChD,OAAQ,EACV,CAAC,CACH,CAAC,GACe,EAEpB,GAKaC,GAAyB,CAACC,EAAaC,KAAuC,CACzF,KAAM,qBACN,KAAM,MAAOH,GAAkC,CAE7C,GAAI,CAOF,OAHiB,IAAII,IAAoB,CAAoC,GAGpE,4BAA6BJ,CAAI,EACnC,EACT,MAAY,CACV,MAAO,EACT,CACF,CACF,GAKaK,GAAuB,CAACC,EAAkBC,KAAyC,CAC9F,KAAM,eACN,KAAM,MAAOP,IACM,MAAM,MAAMM,EAAU,CACrC,OAAQ,QACR,QAAS,CACP,eAAgB,mBAChB,cAAiB,UAAUC,CAAS,EACtC,EACA,KAAM,KAAK,UAAUP,CAAI,CAC3B,CAAC,GACe,EAEpB,GClKO,IAAMQ,GAAmDC,IAAmD,CACjH,KAAM,gBACN,MAAO,CACL,MAAO,CAAC,CAAE,IAAAC,EAAK,MAAAC,EAAO,QAAAC,CAAQ,IAAwB,CACpD,IACEC,EAAO,IAAI,KAAK,EAAE,mBAAmB,EACrCC,EAAa,iBAAiBJ,CAAG,MAAME,CAAO,OAAOC,CAAI,GAEvDJ,GAAS,UAAW,QAAQ,eAAeK,CAAU,EACpD,QAAQ,MAAMA,CAAU,EAE7B,QAAQ,KAAK,YAAa,qCAAsCH,CAAK,EACrE,QAAQ,SAAS,CACnB,EACA,SAAU,CAAC,CAAE,IAAAD,CAAI,IAAM,CACrB,QAAQ,KAAK,qBAAqBA,CAAG,EAAE,CACzC,EACA,cAAe,CAAC,CAAE,IAAAA,CAAI,IAAM,CACtBA,IAAQ,QAAS,QAAQ,MAAM,6CAAyB,EACvD,QAAQ,SAAS,CACxB,CACF,CACF,GC5BO,IAAMK,EAAS,CACpBC,EACAC,IACG,CAMH,IAAMC,EAAQC,EALC,OAAOF,GAAsB,SACxC,CAAE,UAAWA,CAAkB,EAC/BA,CAGmC,EAGnCD,GACF,OAAO,QAAQA,CAAY,EAAE,QAAQ,CAAC,CAACI,EAAGC,CAAC,IAAM,CAE3CH,EAAM,IAAIE,CAAC,IAAM,MACnBF,EAAM,aAAaE,EAAGC,CAAC,CAE3B,CAAC,EAIH,IAAMC,EAA4BC,GAAWC,EAAsBD,EAAeL,CAAK,EAGvF,OAAI,OAAO,OAAW,MACnB,OAA8C,OAASA,EACvD,OAA8C,IAAMA,GAGhD,OAAO,OAAOI,EAAOJ,CAAK,CACnC,EAwDO,IAAMO,EAAgB,CAACC,EAA+DC,IAAiCC,EAAS,GAAG,cAAcF,EAASC,CAAK,EAEzJE,GAAgB,CAACC,EAAaC,EAA6BC,IAAiBJ,EAAS,GAAG,cAAcE,EAAKC,EAAQC,CAAG,GAAK,GAE3HC,GAAgB,CAACD,EAAaE,EAAWC,IAAe,CACnE,IAAMC,EAAIR,EAAS,EACnB,GAAI,CAACQ,EAAG,MAAM,IAAI,MAAM,wEAAwE,EAChG,OAAOA,EAAE,cAAcJ,EAAKE,EAAGC,CAAC,CAClC,EAEaE,GAAa,CAACL,EAAaE,IAAcN,EAAS,GAAG,WAAWI,EAAKE,CAAC,GAAK,GAE3EI,GAAeN,GAAgBJ,EAAS,GAAG,YAAYI,CAAG,GAAK,CAAC,EAEhEO,GAAgB,CAACP,EAAaE,IAAcN,EAAS,GAAG,cAAcI,EAAKE,CAAC,EAE5EM,GAAkBR,GAAgB,CAC7C,IAAMI,EAAIR,EAAS,EACnB,GAAI,CAACQ,EAAG,MAAM,IAAI,MAAM,iDAAiD,EACzE,OAAOA,EAAE,eAAeJ,CAAG,CAC7B,EAEaS,GAAkBT,GAAgB,CAC7C,IAAMI,EAAIR,EAAS,EACnB,GAAI,CAACQ,EAAG,MAAM,IAAI,MAAM,iDAAiD,EACzE,OAAOA,EAAE,eAAeJ,CAAG,CAC7B,EAIaU,EAAmB,IAAM,CAAuB,EAEhDC,EAAmB,IAAM,CAAuB",
6
- "names": ["_immerProduce", "_immerFreeze", "isCryptoAvailable", "generateEncryptionKey", "key", "iv", "exportKey", "encryptionKey", "exportedKey", "importKey", "keyData", "ivData", "keyBytes", "c", "ivBytes", "encrypt", "data", "encoder", "encoded", "encrypted", "combined", "decrypt", "encryptedData", "ciphertext", "decrypted", "_auditLogger", "setAuditLogger", "logger", "isAuditActive", "logAudit", "entry", "addAccessRule", "rules", "pattern", "perms", "hasPermission", "action", "_userId", "matches", "sanitizeValue", "value", "decoded", "match", "hexMatch", "decMatch", "sanitized", "k", "v", "validateKey", "recordConsent", "consents", "userId", "purpose", "granted", "record", "user", "hasConsent", "userConsents", "i", "revokeConsent", "getConsents", "exportUserData", "deleteUserData", "count", "deepClone", "obj", "seen", "clone", "value", "result", "v", "k", "keys", "key", "isEqual", "a", "b", "i", "keysA", "keysB", "_immerFreeze", "_getPrefix", "namespace", "flushDisk", "ctx", "store", "config", "diskQueue", "storage", "encryptionKey", "audit", "onError", "silent", "currentVersion", "prefix", "stateObj", "v", "dataValue", "isEncoded", "e", "error", "queue", "key", "data", "encrypt", "hydrateStore", "calculateSize", "emit", "sizes", "versions", "immer", "persisted", "savedV", "i", "k", "raw", "meta", "d", "decrypt", "err", "final", "frozen", "deepClone", "size", "oldSize", "runHook", "ctx", "name", "hookContext", "p", "hook", "e", "error", "installPlugin", "plugin", "storeInstance", "SyncEngine", "store", "config", "online", "cb", "state", "key", "value", "version", "deepClone", "startTime", "syncedKeys", "conflicts", "errors", "pendingChanges", "p", "change", "remoteVersion", "conflict", "resolution", "err", "result", "errorMsg", "keys", "response", "data", "retries", "localChange", "callback", "createSyncEngine", "StorageAdapters", "_m", "k", "v", "i", "createStore", "config", "_store", "_versions", "_sizes", "_listeners", "_keyListeners", "_middlewares", "_watchers", "_computed", "_computedDeps", "_plugins", "_diskQueue", "_regexCache", "_accessRules", "_consents", "_namespace", "_silent", "_debounceTime", "_currentVersion", "_storage", "_onError", "_maxObjectSize", "_maxTotalSize", "_encryptionKey", "_validateInput", "_auditEnabled", "_userId", "_immer", "_persistByDefault", "rule", "addAccessRule", "_isTransaction", "_pendingEmit", "_isReady", "_totalSize", "_diskTimer", "_snapshot", "_readyResolver", "_readyPromise", "resolve", "_getPrefix", "getPersistenceContext", "_audit", "getPluginContext", "_calculateSize", "val", "type", "bytes", "stack", "seen", "value", "obj", "key", "_runHook", "name", "context", "runHook", "action", "success", "error", "isAuditActive", "logAudit", "_updateComputed", "comp", "depsFound", "getter", "instance", "newValue", "d", "dependents", "isEqual", "_immerFreeze", "deepClone", "_emit", "changedKey", "dependentKey", "watchers", "w", "e", "keyListeners", "l", "_flushDisk", "flushDisk", "_methodNamespace", "oldSize", "frozen", "newSize", "pluginName", "methodName", "fn", "isUnsafeKey", "valOrUp", "options", "oldVal", "newVal", "_immerProduce", "validateKey", "hasPermission", "sani", "sanitizeValue", "finalSize", "est", "shouldPersist", "selector", "callback", "set", "old", "deleted", "prefix", "m", "_unloadHandler", "p", "installPlugin", "cb", "pattern", "permissions", "userId", "perms", "matches", "re", "purpose", "granted", "recordConsent", "hasConsent", "getConsents", "revokeConsent", "exportUserData", "deleteUserData", "hydrateStore", "_syncEngine", "SyncEngine", "useSyncExternalStore", "useDebugValue", "useMemo", "useCallback", "useEffect", "useState", "_defaultStore", "initState", "config", "store", "createStore", "destroyState", "useIsStoreReady", "targetStore", "subscribe", "useMemo", "callback", "useSyncExternalStore", "getStore", "useStore", "keyOrSelector", "store", "targetStore", "useMemo", "_defaultStore", "ghostStore", "noop", "noopFalse", "noopNull", "safeStore", "isSelector", "key", "selector", "subscribe", "useCallback", "callback", "getSnapshot", "getServerSnapshot", "value", "useSyncExternalStore", "setter", "val", "options", "useDebugValue", "v", "_syncEngines", "initSync", "config", "engine", "SyncEngine", "destroySync", "namespace", "useSyncedState", "result", "syncState", "setSyncState", "useState", "useEffect", "syncedSetter", "currentValue", "useSyncStatus", "state", "setState", "updateState", "isOnline", "isSyncing", "pendingChanges", "conflicts", "s", "unsubscribes", "fn", "triggerSync", "targetNamespace", "createAsyncStore", "resolver", "options", "key", "store", "createStore", "current", "result", "prev", "e", "immerPlugin", "store", "key", "updater", "undoRedoPlugin", "options", "_history", "_cursor", "_isRestoring", "_limit", "store", "snapshot", "k", "v", "schemaPlugin", "schemas", "key", "value", "validator", "result", "devToolsPlugin", "options", "extension", "_devTools", "store", "key", "snapshotPlugin", "_snapshots", "store", "name", "snap", "k", "v", "guardPlugin", "guards", "key", "value", "_store", "guard", "transformed", "analyticsPlugin", "options", "key", "value", "syncPlugin", "options", "_channel", "_isSyncing", "store", "event", "key", "value", "action", "debugPlugin", "indexedDBPlugin", "options", "dbName", "storeName", "dbVersion", "db", "getDB", "resolve", "reject", "request", "event", "database", "save", "key", "value", "load", "remove", "store", "keys", "prefix", "val", "storeKey", "data", "cloudSyncPlugin", "options", "adapter", "autoSyncInterval", "lastSyncedVersions", "stats", "timer", "store", "startTime", "dirtyData", "bytesCount", "allData", "keys", "key", "currentVersion", "lastVersion", "val", "err", "cs", "createMongoAdapter", "apiUrl", "apiKey", "data", "createFirestoreAdapter", "db", "docPath", "args", "createSqlRestAdapter", "endpoint", "authToken", "loggerPlugin", "options", "key", "value", "version", "time", "groupLabel", "gstate", "initialState", "configOrNamespace", "store", "createStore", "k", "v", "magic", "key", "useStore", "addAccessRule", "pattern", "perms", "getStore", "hasPermission", "key", "action", "uid", "recordConsent", "p", "g", "s", "hasConsent", "getConsents", "revokeConsent", "exportUserData", "deleteUserData", "clearAccessRules", "clearAllConsents"]
7
- }
@@ -1,15 +0,0 @@
1
- export { immerPlugin } from "./official/immer.plugin";
2
- export { undoRedoPlugin } from "./official/undo-redo.plugin";
3
- export { schemaPlugin } from "./official/schema.plugin";
4
- export { devToolsPlugin } from "./official/devtools.plugin";
5
- export { snapshotPlugin } from "./official/snapshot.plugin";
6
- export { guardPlugin } from "./official/guard.plugin";
7
- export { analyticsPlugin } from "./official/analytics.plugin";
8
- export { syncPlugin } from "./official/sync.plugin";
9
- export { debugPlugin } from "./official/debug.plugin";
10
- export { indexedDBPlugin } from "./official/indexeddb.plugin";
11
- export { cloudSyncPlugin, createMongoAdapter, createFirestoreAdapter, createSqlRestAdapter } from "./official/cloud-sync.plugin";
12
- import type { IPlugin } from "../core/types";
13
- export declare const loggerPlugin: <S extends Record<string, unknown>>(options?: {
14
- collapsed?: boolean;
15
- }) => IPlugin<S>;
@@ -1,9 +0,0 @@
1
- import type { IPlugin } from '../../core/types';
2
- export declare const analyticsPlugin: (options: {
3
- provider: (event: {
4
- key: string;
5
- value: unknown;
6
- action: string;
7
- }) => void;
8
- keys?: string[];
9
- }) => IPlugin;
@@ -1,22 +0,0 @@
1
- import type { IPlugin } from '../../core/types';
2
- export interface SyncStats {
3
- lastSyncTimestamp: number | null;
4
- totalKeysSynced: number;
5
- totalBytesSynced: number;
6
- syncCount: number;
7
- lastDuration: number;
8
- errors: number;
9
- }
10
- export interface CloudSyncAdapter {
11
- name: string;
12
- save: (data: Record<string, unknown>) => Promise<boolean>;
13
- }
14
- export interface CloudSyncOptions {
15
- adapter: CloudSyncAdapter;
16
- autoSyncInterval?: number;
17
- onSync?: (stats: SyncStats) => void;
18
- }
19
- export declare const cloudSyncPlugin: <S extends Record<string, unknown>>(options: CloudSyncOptions) => IPlugin<S>;
20
- export declare const createMongoAdapter: (apiUrl: string, apiKey: string) => CloudSyncAdapter;
21
- export declare const createFirestoreAdapter: (db: unknown, docPath: string) => CloudSyncAdapter;
22
- export declare const createSqlRestAdapter: (endpoint: string, authToken: string) => CloudSyncAdapter;
@@ -1,2 +0,0 @@
1
- import type { IPlugin } from '../../core/types';
2
- export declare const debugPlugin: () => IPlugin;
@@ -1,4 +0,0 @@
1
- import type { IPlugin } from '../../core/types';
2
- export declare const devToolsPlugin: (options?: {
3
- name?: string;
4
- }) => IPlugin;
@@ -1,2 +0,0 @@
1
- import type { IPlugin } from '../../core/types';
2
- export declare const guardPlugin: (guards: Record<string, (val: unknown) => unknown>) => IPlugin;