UNPKG

synapse-storage

Version:

Набор инструментов для управления состоянием и апи-запросами

2 lines (1 loc) 37.5 kB
var y=!1,D=new Map;function U(a){let e=0;if(a.length===0)return e.toString(36);for(let t=0;t<a.length;t++){let s=a.charCodeAt(t);e=(e<<5)-e+s,e=e&e}return Math.abs(e).toString(36).substring(0,6)}function b(a,e){if(a===e)return!0;if(a==null||e==null)return!1;if(typeof a!="object"&&typeof a!="function"&&typeof e!="object"&&typeof e!="function")return a===e;if(typeof a!=typeof e)return!1;if(a instanceof Date&&e instanceof Date)return a.getTime()===e.getTime();if(Array.isArray(a)&&Array.isArray(e)){if(a.length!==e.length)return!1;for(let t=0;t<a.length;t++)if(!b(a[t],e[t]))return!1;return!0}if(typeof a=="object"&&typeof e=="object"){let t=Object.keys(a),s=Object.keys(e);return t.length!==s.length?!1:t.every(r=>Object.prototype.hasOwnProperty.call(e,r)?b(a[r],e[r]):!1)}return!1}function V(a,e=b){let t,s,r=!1;return function(i){if(!r||t!==i){let o=a(i);(!r||!e(o,s))&&(s=o),t=i,r=!0}return s}}var O=class{constructor(e,t,s=b,r){this.name=e;this.equals=s;this.logger=r;this.id=e,this.memoizedGetState=this.createMemoizedGetState(t)}id;subscribers=new Set;lastValue;memoizedGetState;createMemoizedGetState(e){let t=null,s=!1;return async()=>{if(s&&t)return t;s=!0;try{return t=e(),await t}finally{s=!1}}}async notify(){try{let e=await this.memoizedGetState();if(this.lastValue===void 0||!this.equals(e,this.lastValue)){this.lastValue=e;let t=Array.from(this.subscribers).map(async s=>{try{await s.notify(e)}catch(r){this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u0430`,{error:r})}});await Promise.all(t)}}catch(e){throw this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 notify()`,{error:e}),e}}subscribe(e){return this.subscribers.add(e),this.lastValue!==void 0?Promise.resolve().then(()=>{try{e.notify(this.lastValue)}catch(t){this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043F\u0435\u0440\u0432\u043E\u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438`,{error:t})}}):this.notify().catch(t=>{this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043F\u0435\u0440\u0432\u043E\u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438`,{error:t})}),()=>{this.subscribers.delete(e)}}cleanup(){this.subscribers.clear(),this.lastValue=void 0}getId(){return this.id}},B=class{constructor(e,t){this.source=e;this.logger=t;this.storageName=e.name,this.source.getState().then(s=>{this.cachedState=s})}storageName;subscriptions=new Map;cachedState;localSelectorCache=new Map;batchUpdateInProgress=!1;pendingUpdates=new Set;generateName(e,t,s){let r=e?"simple":"combined",n="";if(e){let i=t.toString();n=U(i)}else{let i=t.map(c=>c.getId()).join("_"),o=s.toString();n=U(i+o)}return`${this.storageName}_${r}_${n}`}processPendingUpdates(){this.pendingUpdates.size===0||this.batchUpdateInProgress||(this.batchUpdateInProgress=!0,setTimeout(async()=>{try{let e=Array.from(this.pendingUpdates);this.pendingUpdates.clear(),this.cachedState=await this.source.getState();let t=e.map(async s=>{let r=this.subscriptions.get(s);if(r)try{return await r.notify()}catch(n){this.logger?.error(`\u041E\u0448\u0438\u0431\u043A\u0430 \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u0430 ${s}`,{error:n})}return Promise.resolve()});await Promise.all(t)}catch(e){this.logger?.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0438 \u043E\u0436\u0438\u0434\u0430\u044E\u0449\u0438\u0445 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u0439",{error:e})}finally{this.batchUpdateInProgress=!1,this.pendingUpdates.size>0&&this.processPendingUpdates()}},0))}createSelector(e,t,s){let r=!Array.isArray(e),n=r?t||{}:s||{},i=n.name||this.generateName(r,e,r?void 0:t);if(this.localSelectorCache.has(i))return this.localSelectorCache.get(i).api;if(D.has(i)){let u=D.get(i);return u.refCount++,u.api}let o,c,d=[];if(r){let u=V(e,n.equals||b),g=this.createSimpleSelector(u,{...n,name:i,equals:n.equals||b});o=g.api,d=g.unsubscribeFunctions}else{c=e;let u=this.createCombinedSelector(c,t,{...n,name:i,equals:n.equals||b});o=u.api,d=u.unsubscribeFunctions}return this.localSelectorCache.set(i,{api:o,dependencies:c,unsubscribeFunctions:d}),D.set(i,{api:o,refCount:1,unsubscribeFunctions:d}),o}createSimpleSelector(e,t){let s=async()=>{if(this.cachedState)return e(this.cachedState);let c=await this.source.getState();return this.cachedState=c,e(c)},r=new O(t.name,s,t.equals||b,this.logger),n=r.getId();this.subscriptions.set(n,r);let o=[this.source.subscribeToAll(async c=>{c?.type==="storage:update"&&(this.pendingUpdates.add(n),this.processPendingUpdates())})];return{api:{select:()=>s(),subscribe:c=>r.subscribe(c),getId:()=>n},unsubscribeFunctions:o}}createCombinedSelector(e,t,s){let r=V(g=>t(...g),s.equals||b),n=async()=>{let g=await Promise.all(e.map(l=>l.select()));return r(g)},i=new O(s.name,n,s.equals||b,this.logger),o=i.getId();this.subscriptions.set(o,i);let c=null,d=()=>{c!==null&&clearTimeout(c),c=setTimeout(()=>{c=null,i.notify().catch(g=>this.logger?.error(`[${o}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043E\u0431\u044A\u0435\u0434\u0438\u043D\u0435\u043D\u043D\u043E\u043C \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u0438:`,{error:g}))},10)},u=e.map(g=>g.subscribe({notify:()=>{d()}}));return{api:{select:()=>n(),subscribe:g=>i.subscribe(g),getId:()=>o},unsubscribeFunctions:u}}destroy(){this.subscriptions.forEach(t=>t.cleanup()),this.subscriptions.clear(),this.cachedState=void 0,this.pendingUpdates.clear(),this.localSelectorCache.forEach(t=>{t.unsubscribeFunctions.forEach(s=>s())});let e=new Set;this.localSelectorCache.forEach((t,s)=>{e.add(s)}),this.localSelectorCache.clear(),e.forEach(t=>{let s=D.get(t);s&&(s.refCount--,s.refCount<=0&&(s.unsubscribeFunctions.forEach(r=>r()),D.delete(t)))})}};var v=class{static instances=new Map;static configs=new Map;static logger;static setLogger(e){this.logger=e}static getOrCreate(e,t,s){let r=this.configs.get(e),n=this.instances.get(e);if(n&&r){let o=this.mergeConfigurations(r,t);return{instance:n,isNewInstance:!1,appliedConfig:o.finalConfig,conflicts:o.conflicts}}let i=s(t);return this.instances.set(e,i),this.configs.set(e,{...t}),this.logger?.debug(`Created new singleton instance: ${e}`),{instance:i,isNewInstance:!0,appliedConfig:t,conflicts:[]}}static exists(e){return this.instances.has(e)}static getConfig(e){return this.configs.get(e)}static remove(e){let t=this.instances.get(e);return t?(typeof t.destroy=="function"&&t.destroy(),this.instances.delete(e),this.configs.delete(e),this.logger?.debug(`Removed singleton instance: ${e}`),!0):!1}static clear(){for(let[e,t]of this.instances)typeof t.destroy=="function"&&t.destroy();this.instances.clear(),this.configs.clear(),this.logger?.debug("Cleared all singleton instances")}static getStats(){return{instanceCount:this.instances.size,instances:Array.from(this.instances.keys())}}static mergeConfigurations(e,t){let s=t.singleton?.mergeStrategy||"first_wins",r=t.singleton?.warnOnConflict??!0;switch(s){case"strict":return this.strictMerge(e,t);case"first_wins":return this.firstWinsMerge(e,t,r);case"deep_merge":return this.deepMerge(e,t);case"override":return this.overrideMerge(e,t);case"warn_and_use_first":return this.warnAndUseFirst(e,t);default:return this.firstWinsMerge(e,t,r)}}static strictMerge(e,t){let s=this.findConflicts(e,t);if(s.length>0)throw new Error(`Strict singleton validation failed for "${e.name}". Conflicts: ${s.join(", ")}`);return{finalConfig:e,conflicts:[]}}static firstWinsMerge(e,t,s){let r=this.findConflicts(e,t);return s&&r.length>0&&(this.logger?.warn(`Singleton config conflicts for "${e.name}":`,r),this.logger?.warn("Using existing configuration")),{finalConfig:e,conflicts:r}}static deepMerge(e,t){let s=this.findConflicts(e,t),r={...e,initialState:this.deepMergeObjects(e.initialState||{},t.initialState||{})};return this.logger?.debug(`Deep merged singleton config for "${e.name}"`),{finalConfig:r,conflicts:s}}static overrideMerge(e,t){let s=this.findConflicts(e,t),r={...t,name:e.name};return this.logger?.warn(`Overriding singleton config for "${e.name}"`),{finalConfig:r,conflicts:s}}static warnAndUseFirst(e,t){let s=this.findConflicts(e,t);return s.length>0&&(this.logger?.warn(`Configuration conflicts detected for singleton "${e.name}":`),this.logger?.warn("Existing config:",e),this.logger?.warn("Incoming config:",t),this.logger?.warn("Using existing configuration")),{finalConfig:e,conflicts:s}}static findConflicts(e,t){let s=[];if(e.initialState&&t.initialState){let r=this.findObjectConflicts(e.initialState,t.initialState,"initialState");s.push(...r)}else e.initialState!==t.initialState&&s.push("initialState: one is undefined");return!!e.middlewares!=!!t.middlewares&&s.push("middlewares: configuration differs"),s}static findObjectConflicts(e,t,s){let r=[],n=new Set([...Object.keys(e||{}),...Object.keys(t||{})]);for(let i of n){let o=`${s}.${i}`,c=e?.[i],d=t?.[i];c!==d&&(c===void 0||d===void 0?r.push(`${o}: missing in one config`):typeof c!=typeof d?r.push(`${o}: type mismatch (${typeof c} vs ${typeof d})`):typeof c=="object"&&c!==null&&d!==null?r.push(...this.findObjectConflicts(c,d,o)):r.push(`${o}: value mismatch (${c} vs ${d})`))}return r}static deepMergeObjects(e,t){let s={...e};for(let r in t)t[r]!==null&&typeof t[r]=="object"&&!Array.isArray(t[r])?s[r]=this.deepMergeObjects(e[r]||{},t[r]):s[r]=t[r];return s}},R=class{static generate(e,t){return e.singleton?.key?e.singleton.key:`${t}_${e.name}`}};var A=class{static handleSingletonCreation(e,t,s,r){if(!e.singleton?.enabled)return s(e);r&&v.setLogger(r);let n=R.generate(e,t),i=v.getOrCreate(n,e,s);return i.isNewInstance?r?.debug(`Created new singleton storage: ${n}`):(r?.debug(`Reusing existing singleton storage: ${n}`),i.conflicts&&i.conflicts.length>0&&r?.debug(`Configuration conflicts detected: ${i.conflicts.join(", ")}`)),i.instance}};var T=class{constructor(e,t=!1){this.value=e;this.isRawKey=t}toString(){return this.value}toJSON(){return this.value}valueOf(){return this.value}isUnparseable(){return this.isRawKey}};var _=(a={})=>{let e=a.batchSize??10,t=a.batchDelay??10,s=new Map,r=new Map,n=l=>l.type==="set"||l.type==="update",i=l=>`${l.type}_${l.key?.toString()||"default"}`,o=l=>{let p=new Map;for(let h of l){let S=`${h.type}_${h.key?.toString()||"default"}`;p.set(S,h)}return Array.from(p.values())},c=l=>{let p=r.get(l);p&&(globalThis.clearTimeout(p),r.delete(l))},d=(l,p)=>{let h=globalThis.setTimeout(p,t);r.set(l,h)},u=async(l,p,h)=>{let S=s.get(l);if(!(!S||S.length===0)){s.delete(l),c(l);try{let x=S.map(f=>f.action),m=o(x);for(let f of m)try{let N=await h(f);S.filter(w=>w.action.type===f.type&&w.action.key?.toString()===f.key?.toString()).forEach(w=>w.resolve(N))}catch(N){S.filter(w=>w.action.type===f.type&&w.action.key?.toString()===f.key?.toString()).forEach(w=>w.reject(N))}}catch(x){S.forEach(m=>m.reject(x))}}},g=async(l,p,h)=>new Promise((S,x)=>{let m=i(l),f=s.get(m);f||(f=[],s.set(m,f)),f.push({action:l,resolve:S,reject:x,timestamp:Date.now()}),c(m),f.length>=e?setImmediate(()=>u(m,p,h)):d(m,()=>u(m,p,h))});return{name:"batching",setup:()=>{},cleanup:async()=>{r.forEach(l=>globalThis.clearTimeout(l)),r.clear(),s.clear()},reducer:l=>p=>async h=>n(h)?g(h,l,p):p(h)}};var k=(a={})=>{let{comparator:e=(r,n)=>{if(r===n)return!0;if(typeof r!="object"||typeof n!="object"||r===null||n===null)return r===n;let i=Object.keys(r),o=Object.keys(n);return i.length!==o.length?!1:i.every(c=>Object.prototype.hasOwnProperty.call(n,c)&&r[c]===n[c])},segments:t=[]}=a,s=new Map;return{name:"shallow-compare",setup:r=>{},reducer:r=>n=>async i=>{if(i.type!=="set"||t.length&&!t.includes(i.metadata?.segment??"default"))return n(i);let o=i.key,c=s.get(o),d=i.value;if(c!==void 0&&e(c,d))return{...c,t:{valueNotChanged:!0,originalValue:c}};let u=await n(i);return s.set(o,d),u}}};var $=class{middlewares=[];api;initialized=!1;dispatchFn;constructor(e){this.api={dispatch:async t=>this.dispatch(t),getState:()=>e.getState(),storage:{doGet:e.doGet.bind(e),doSet:e.doSet.bind(e),doUpdate:e.doUpdate.bind(e),doDelete:e.doDelete.bind(e),doClear:e.doClear.bind(e),doKeys:e.doKeys.bind(e),notifySubscribers:e.notifySubscribers.bind(e)}}}async baseOperation(e){let{processed:t,...s}=e.metadata||{},r={...e,metadata:s};switch(r.type){case"get":return this.api.storage.doGet(r.key);case"set":return await this.api.storage.doSet(r.key,r.value),this.api.storage.doGet(r.key);case"update":return Array.isArray(r.value)?(await this.api.storage.doUpdate(r.value),this.api.storage.doGet("")):r.value;case"delete":return this.api.storage.doDelete(r.key);case"clear":return this.api.storage.doClear();case"init":{let n=await this.api.storage.doGet("");return Object.keys(n||{}).length>0?n:r.value?(await this.api.storage.doSet("",r.value),this.api.storage.doGet("")):n}case"keys":return this.api.storage.doKeys();default:throw new Error(`Unknown action type: ${r.type}`)}}initializeMiddlewares(){if(this.initialized)return;let e=this.baseOperation.bind(this);for(let t of[...this.middlewares].reverse()){let s=e;e=async r=>{if(r.metadata?.processed)return s(r);let n={...r,metadata:{...r.metadata,processed:!0,timestamp:r.metadata?.timestamp||Date.now()}};return t.reducer(this.api)(s)(n)}}this.dispatchFn=e,this.initialized=!0}use(e){e.setup&&e.setup(this.api),this.middlewares.push(e),this.initialized=!1}async dispatch(e){this.initialized||this.initializeMiddlewares();try{return this.dispatchFn(e)}catch(t){throw t}}};function P(a){return a instanceof T&&a.isUnparseable()?[a.toString()]:a.toString().replace(/\[/g,".").replace(/\]/g,"").split(".").filter(Boolean)}function E(a,e){return P(e).reduce((s,r)=>s===void 0?void 0:s[r],a)}function M(a,e,t){if(e==="")return t;let s=P(e);if(e instanceof T&&e.isUnparseable())return a[e.toString()]=t,a;let r=s.pop(),n=s.reduce((i,o)=>{let c=s[s.indexOf(o)+1],d=!Number.isNaN(Number(c));return o in i||(i[o]=d?[]:{}),i[o]},a);return n[r]=t,a}var I=class a{constructor(e,t,s,r){this.config=e;this.pluginExecutor=t;this.eventEmitter=s;this.logger=r;this.name=e.name,this.middlewareModule=new $({getState:this.getState.bind(this),doGet:this.doGet.bind(this),doSet:this.doSet.bind(this),doUpdate:this.doUpdate.bind(this),doDelete:this.doDelete.bind(this),doClear:this.doClear.bind(this),doKeys:this.doKeys.bind(this),notifySubscribers:this.notifySubscribers.bind(this),pluginExecutor:this.pluginExecutor,eventEmitter:this.eventEmitter,logger:this.logger}),this.initializeMiddlewares()}static GLOBAL_SUBSCRIPTION_KEY="*";static STORAGE_TYPE;name;e={status:"idle"};statusSubscribers=new Set;selectorPathCache=new WeakMap;middlewareModule;initializedMiddlewares=null;subscribers=new Map;get initStatus(){return{...this.e}}async waitForReady(){if(this.e.status==="ready")return this;if(this.e.status==="error")throw this.e.error||new Error("Storage initialization failed");return new Promise((e,t)=>{let s=this.onStatusChange(r=>{r.status==="ready"?(s(),e(this)):r.status==="error"&&(s(),t(r.error||new Error("Storage initialization failed")))})})}onStatusChange(e){return this.statusSubscribers.add(e),e(this.initStatus),()=>{this.statusSubscribers.delete(e)}}updateInitStatus(e){let t=this.e.status;this.e={...this.e,...e},t!==this.e.status&&this.logger?.debug(`Storage "${this.name}" status changed: ${t} -> ${this.e.status}`);let s=this.initStatus;this.statusSubscribers.forEach(r=>{try{r(s)}catch(n){this.logger?.error("Error in status change callback",{error:n})}})}async initialize(){if(this.e.status==="ready")return this;if(this.e.status==="loading")return this.waitForReady();this.updateInitStatus({status:"loading",error:void 0});try{let e=await this.doInitialize();return this.updateInitStatus({status:"ready",error:void 0}),e}catch(e){throw this.updateInitStatus({status:"error",error:e instanceof Error?e:new Error(String(e))}),e}}ensureReady(){if(this.e.status!=="ready")throw new Error(`Storage "${this.name}" is not ready. Current status: ${this.e.status}`)}initializeMiddlewares(){this.config.middlewares&&!this.initializedMiddlewares&&(this.initializedMiddlewares=this.config.middlewares(()=>this.getDefaultMiddleware()),this.initializedMiddlewares.forEach(e=>this.middlewareModule.use(e)))}getDefaultMiddleware(){return{batching:(e={})=>_(e),shallowCompare:(e={})=>k(e)}}async initializeWithMiddlewares(){try{let e=await this.getState();!(Object.keys(e).length>0)&&this.config.initialState&&await this.middlewareModule.dispatch({type:"init",value:this.config.initialState})}catch(e){throw this.logger?.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0438\u043D\u0438\u0446\u0438\u0430\u043B\u0438\u0437\u0430\u0446\u0438\u0438 \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430",{error:e}),e}}async get(e){this.ensureReady();try{let t={operation:"get",timestamp:Date.now(),key:e},s=await this.middlewareModule.dispatch({type:"get",key:e,metadata:t}),r=await this.pluginExecutor?.executeAfterGet(e,s,t)??s;return await this.emitEvent({type:"storage:select",payload:{key:e,value:r}}),r}catch(t){throw this.logger?.error("Error getting value",{key:e,error:t}),t}}async set(e,t){this.ensureReady();try{let s={operation:"set",timestamp:Date.now(),key:e},r=await this.pluginExecutor?.executeBeforeSet(t,s)??t,n=await this.middlewareModule.dispatch({type:"set",key:e,value:r,metadata:s}),i=n?.t?.valueNotChanged===!0,o;if(i&&n?.t?.originalValue!==void 0?o=n.t.originalValue:o=await this.pluginExecutor?.executeAfterSet(e,n,s)??n,!i){let d=[e.toString()];this.notifySubscribers(e,o),this.notifySubscribers(a.GLOBAL_SUBSCRIPTION_KEY,{type:"storage:update",key:e,value:o,changedPaths:d}),await this.emitEvent({type:"storage:update",payload:{key:e,value:o,changedPaths:d}})}}catch(s){throw this.logger?.error("Error setting value",{key:e,error:s}),s}}async update(e){this.ensureReady();try{let t={operation:"update",timestamp:Date.now()},s=await this.getState(),r=structuredClone(s);e(r);let n=this.findChangedPaths(s,r);if(n.size===0){this.logger?.debug&&this.logger.debug("No changes detected in update");return}this.logger?.debug&&this.logger.debug("Changed paths:",{paths:Array.from(n)});let i=new Set;for(let l of n){let p=l.split(".")[0];i.add(p)}let o=await Promise.all(Array.from(i).map(async l=>{let p={...t,key:l},h=await this.pluginExecutor?.executeBeforeSet(r[l],p)??r[l];return{key:l,value:h}})),c=await this.middlewareModule.dispatch({type:"update",value:o,metadata:{...t,batchUpdate:!0,changedPaths:Array.from(n)}}),d={};Array.isArray(c)?c.forEach(l=>{l&&typeof l=="object"&&"key"in l&&"value"in l&&(d[l.key]=l.value)}):c&&typeof c=="object"&&(d={...c});let u=Object.keys(d).filter(l=>!this.isEqual(s[l],d[l]));if(u.length===0){this.logger?.debug&&this.logger.debug("No actual changes after middleware processing");return}let g={};u.forEach(l=>{g[l]=d[l]}),this.logger?.debug&&this.logger.debug("Notifying subscribers about changes:",{keys:u}),this.notifySubscribers(a.GLOBAL_SUBSCRIPTION_KEY,{type:"storage:update",key:u,value:g,changedPaths:Array.from(n)});for(let l of n)try{let p=l.split(".")[0];if(p in g){let h;if(l===p)h=g[p];else{let S=l.substring(p.length+1);h=E(g[p],S)}h!==void 0&&this.notifySubscribers(l,h)}}catch(p){this.logger?.error("Error notifying path subscribers",{path:l,error:p})}await this.emitEvent({type:"storage:update",payload:{state:g,key:u,changedPaths:Array.from(n)}})}catch(t){throw this.logger?.error("Error updating state",{error:t}),t}}async delete(e){this.ensureReady();try{let t={operation:"delete",timestamp:Date.now(),key:e};if(await this.pluginExecutor?.executeBeforeDelete(e,t)===!1)return;let r=await this.middlewareModule.dispatch({type:"delete",key:e,metadata:t});if(r===!1)return;await this.pluginExecutor?.executeAfterDelete(e,t);let i=[e.toString()];this.notifySubscribers(e,void 0),this.notifySubscribers(a.GLOBAL_SUBSCRIPTION_KEY,{type:"storage:update",key:e,value:void 0,result:r,changedPaths:i}),await this.emitEvent({type:"storage:update",payload:{key:e,value:void 0,result:r,changedPaths:i}})}catch(t){throw this.logger?.error("Error deleting value",{key:e,error:t}),t}}async clear(){this.ensureReady();try{this.pluginExecutor?.executeOnClear(),await this.middlewareModule.dispatch({type:"clear"})}catch(e){throw this.logger?.error("Error clearing storage",{error:e}),e}}async keys(){this.ensureReady();try{return await this.middlewareModule.dispatch({type:"keys"})}catch(e){throw this.logger?.error("Error getting keys",{error:e}),e}}async has(e){this.ensureReady();try{return await this.doHas(e)}catch(t){throw this.logger?.error("Error checking value existence",{key:e,error:t}),t}}async getState(){try{return await this.doGet("")||{}}catch(e){throw this.logger?.error("Error getting state",{error:e}),e}}subscribeToAll(e){return this.subscribers.has(a.GLOBAL_SUBSCRIPTION_KEY)||this.subscribers.set(a.GLOBAL_SUBSCRIPTION_KEY,new Set),this.subscribers.get(a.GLOBAL_SUBSCRIPTION_KEY).add(e),()=>{let t=this.subscribers.get(a.GLOBAL_SUBSCRIPTION_KEY);t&&(t.delete(e),t.size===0&&this.subscribers.delete(a.GLOBAL_SUBSCRIPTION_KEY))}}subscribe(e,t){return typeof e=="string"?this.subscribeByKey(e,t):this.subscribeBySelector(e,t)}async destroy(){try{if(await this.clear(),await this.doDestroy(),this.initializedMiddlewares&&(await Promise.all(this.initializedMiddlewares.map(async e=>{"cleanup"in e&&await e.cleanup?.()})),this.initializedMiddlewares=null),this.statusSubscribers.clear(),this.config.singleton?.enabled){let e=this.constructor.STORAGE_TYPE,t=R.generate(this.config,e);v.remove(t)}this.updateInitStatus({status:"idle"}),await this.emitEvent({type:"storage:destroy"})}catch(e){throw this.logger?.error("Error destroying storage",{error:e}),e}}subscribeByKey(e,t){this.subscribers.has(e)||this.subscribers.set(e,new Set);let s=!1;return this.subscribers.get(e).add(t),this.get(e).then(r=>{try{s||(s=!0,t(r))}catch(n){this.logger?.error("Error in initial callback",{key:e,error:n})}}),()=>{let r=this.subscribers.get(e);r&&(r.delete(t),r.size===0&&this.subscribers.delete(e))}}createDummyState(){let e={get:(t,s)=>(t[s]=t[s]||new Proxy({},e),t[s])};return new Proxy({},e)}isEqual(e,t){if(e===t)return!0;if(e==null||t==null)return e===t;let s=typeof e;if(s!==typeof t)return!1;if(s!=="object")return e===t;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let o=0;o<e.length;o++)if(!this.isEqual(e[o],t[o]))return!1;return!0}let n=Object.keys(e),i=Object.keys(t);return n.length!==i.length?!1:n.every(o=>Object.prototype.hasOwnProperty.call(t,o)&&this.isEqual(e[o],t[o]))}extractPath(e,t){if(this.selectorPathCache.has(e))return this.selectorPathCache.get(e);let s=[],r=(n="")=>({get:(i,o)=>{if(typeof o=="symbol")return Reflect.get(i,o);let c=n?`${n}.${o}`:o;return s.push(c),new Proxy({},r(c))},has:(i,o)=>!0,ownKeys:()=>[],getOwnPropertyDescriptor:()=>({configurable:!0,enumerable:!0}),apply:(i,o,c)=>new Proxy(()=>{},r(n))});try{e(new Proxy(t,r()))}catch{}return s.length===0?"":(s.sort((n,i)=>i.length-n.length),this.selectorPathCache.set(e,s[0]),s[0])}notifySubscribers(e,t){let s=e.toString(),r=this.subscribers.get(s);r?.size&&new Set(r).forEach(i=>{try{i(t)}catch(o){this.logger?.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0432 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u0435 \u043D\u0430 \u043A\u043E\u043B\u0431\u044D\u043A",{key:s,error:o})}})}findChangedPaths(e,t,s="",r=new Set,n=new WeakMap){if(e===t)return r;if(typeof e!="object"||typeof t!="object"||e===null||t===null)return e!==t&&r.add(s||""),r;if(n.has(e))return r;n.set(e,!0);let i=new Set([...Object.keys(e||{}),...Object.keys(t||{})]);for(let o of i){let c=e[o],d=t[o];if(c===d)continue;let u=s?`${s}.${o}`:o;c&&d&&typeof c=="object"&&typeof d=="object"&&!Array.isArray(c)&&!Array.isArray(d)?this.findChangedPaths(c,d,u,r,n):Array.isArray(c)&&Array.isArray(d)?this.isEqual(c,d)||r.add(u):this.isEqual(c,d)||r.add(u)}return r}subscribeBySelector(e,t){let s=this.createDummyState(),r=this.extractPath(e,s);this.logger?.debug&&this.logger.debug("Subscribing to path:",{path:r});let n=async i=>{try{if(i==null){let d=await this.getState(),u=e(d);t(u);return}if(typeof i!="object"||i===null){t(i);return}let o=await this.getState(),c=e(o);t(c)}catch(o){this.logger?.error("Error in selector callback",{path:r,error:o}),t(i)}};return r?this.subscribeByKey(r,n):this.subscribeToAll(()=>{this.getState().then(i=>{t(e(i))})})}async emitEvent(e){try{await this.eventEmitter?.emit({...e,metadata:{...e.metadata||{},timestamp:Date.now(),storageName:this.name}})}catch(t){this.logger?.error("Error emitting event",{event:e,error:t})}}};var C=class a extends I{static STORAGE_TYPE="memory";storage=new Map;constructor(e,t,s,r){super(e,t,s,r)}static create(e,t,s,r){return A.handleSingletonCreation(e,this.STORAGE_TYPE,n=>new a(n,t,s,r),r)}async doInitialize(){try{return this.logger?.debug(`Initializing MemoryStorage "${this.name}"`),this.initializeMiddlewares(),await this.initializeWithMiddlewares(),this.logger?.debug(`MemoryStorage "${this.name}" initialized successfully`),this}catch(e){throw this.logger?.error("Error initializing MemoryStorage",{error:e}),e}}async doGet(e){let t=this.storage.get(this.name);if(t)return e instanceof T&&e.isUnparseable()?t[e.valueOf()]:E(t,e)}async doSet(e,t){let s=this.storage.get(this.name)||{};if(e instanceof T&&e.isUnparseable()){s[e.valueOf()]=t,this.storage.set(this.name,s);return}let r=M({...s},e,t);this.storage.set(this.name,r)}async doDelete(e){let t=this.storage.get(this.name);if(!t)return!1;if(e instanceof T&&e.isUnparseable()){let o=e.valueOf();return o in t?(delete t[o],this.storage.set(this.name,t),!0):!1}let s=P(e),r=s.slice(0,-1).join("."),n=s[s.length-1],i=r?E(t,r):t;return!i||!(n in i)?!1:(delete i[n],this.storage.set(this.name,t),!0)}async doUpdate(e){let s={...this.storage.get(this.name)||{}};for(let{key:r,value:n}of e)r instanceof T&&r.isUnparseable()?s[r.valueOf()]=n:M(s,r,n);this.storage.set(this.name,s)}async doClear(){this.storage.delete(this.name)}async doKeys(){let e=this.storage.get(this.name);return e?this.getAllKeys(e):[]}async doHas(e){return await this.doGet(e)!==void 0}async doDestroy(){this.storage.delete(this.name)}getAllKeys(e){return Object.keys(e)}};import{Observable as Q,Subject as L}from"rxjs";var K=class{constructor(e){this.options=e;this.storage=e.storage,this.middlewareAPI={getState:()=>this.storage.getState(),dispatch:async t=>(this.actions$.next(t),t.payload),storage:this.storage,actions$:this.actions,actions:this.dispatch,watchers:this.watchers,findActionByType:t=>this.findActionByType(t),findWatcherByType:t=>this.findWatcherByType(t)},e.middlewares&&e.middlewares.length>0&&this.use(...e.middlewares)}actions$=new L;actions=this.actions$.asObservable();dispatch={};watchers={};storage;middlewareFunctions=[];middlewareAPI;use(...e){for(let t=0;t<e.length;t++)try{let s=e[t](this.middlewareAPI);this.middlewareFunctions.push(s)}catch{}return this}getActions(){return this.dispatch}getTypedDispatch(){return this.dispatch}getTypedWatchers(){return this.watchers}findActionByType(e){return Object.values(this.dispatch).find(t=>t.actionType.split(`[${this.storage.name}]`)[1]===e)}findWatcherByType(e){return Object.values(this.watchers).find(t=>t.actionType===e)}createAction(e,t){let s=`[${this.storage.name}]${e.type}`,r=null,n=null,i=async o=>{let c=[o];if(t?.memoize&&r&&n&&t.memoize(c,r,n))return n;let d={type:s,meta:e.meta},u;if(this.middlewareFunctions.length>0){let g=async l=>t?.worker?this.executeInWorker(t.worker,s,c,e.action):Promise.resolve(e.action(o));for(let l=this.middlewareFunctions.length-1;l>=0;l--){let p=this.middlewareFunctions[l],h=g;g=async S=>p(async m=>h(m))(S)}u=await g(d)}else t?.worker?u=await this.executeInWorker(t.worker,s,c,e.action):u=await e.action(o);return d.payload=u,r=[...c],n=u,this.actions$.next(d),u};return i.r="dispatch",Object.defineProperty(i,"actionType",{value:s,writable:!1,enumerable:!0}),e.meta&&Object.defineProperty(i,"meta",{value:e.meta,writable:!1,enumerable:!0}),i}createWatcher(e){let t=`[${this.storage.name}]${e.type}`,s=new L,r,n=async()=>{let c=await this.storage.getState();return e.selector(c)},i=this.storage.subscribe(e.selector,c=>{if(!e.shouldTrigger||e.shouldTrigger(r,c)){let d={type:t,payload:c,meta:e.meta};this.actions$.next(d),s.next(d),r=c}}),o=()=>{let c=s.asObservable();return e.notifyAfterSubscribe?new Q(d=>{let u=!1;n().then(l=>{if(!e.shouldTrigger||e.shouldTrigger(void 0,l)){let p={type:t,payload:l,meta:{...e.meta,isInitial:!0}};d.next(p),r=l,u=!0}}).catch(l=>{d.error(l)});let g=c.subscribe({next:l=>{u&&l.payload===r||d.next(l)},error:l=>d.error(l),complete:()=>d.complete()});return()=>{g.unsubscribe()}}):c};return o.r="watchers",Object.defineProperty(o,"actionType",{value:t,writable:!1,enumerable:!0}),e.meta&&Object.defineProperty(o,"meta",{value:e.meta,writable:!1,enumerable:!0}),Object.defineProperty(o,"unsubscribe",{value:i,writable:!1,enumerable:!0}),o}async executeInWorker(e,t,s,r){return new Promise((n,i)=>{let o=`${t}_${Date.now()}_${Math.random()}`,c=d=>{d.data.requestId===o&&(e.removeEventListener("message",c),d.data.error?i(new Error(d.data.error)):n(d.data.result))};e.addEventListener("message",c),e.postMessage({type:t,args:s,requestId:o}),setTimeout(()=>{e.removeEventListener("message",c),i(new Error(`Worker execution timeout for action: ${t}`))},3e4)})}};function G(a,e){let t=new K(a),s=e(a.storage,{createAction:(r,n)=>t.createAction(r,n),createWatcher:r=>t.createWatcher(r)});for(let[r,n]of Object.entries(s))if(typeof n=="function"){let i=n.r;t[i][r]=n}return t}var jt=globalThis.console;import{combineLatest as Er,merge as xr,Observable as Z,of as ee,pipe as Ar,Subject as te}from"rxjs";import{catchError as re,filter as Ir,map as Cr,share as se,switchMap as Dr,take as Mr}from"rxjs/operators";import{of as tr}from"rxjs";import{concatAll as sr,delay as nr,mergeMap as or,toArray as ir}from"rxjs/operators";import{forkJoin as dr,timer as gr}from"rxjs";import{mergeMap as hr}from"rxjs/operators";var F=class{constructor(e,t={},s,r={},n={}){this.storage=e;this.externalStates=t;this.dispatchers=s;this.services=r;this.config=n;this.subscribeToDispatchers(),this.state$=new Z(i=>{this.storage.getState().then(c=>i.next(c));let o=this.storage.subscribeToAll(()=>{this.storage.getState().then(c=>i.next(c))});return()=>o()}).pipe(se())}effects=[];subscriptions=[];running=!1;action$=new te;state$;subscribeToDispatchers(){for(let[e,t]of Object.entries(this.dispatchers)){let s=t.actions.subscribe(r=>{this.action$.next(r)});this.subscriptions.push(s)}}add(e){return this.effects.push(e),this.running&&this.subscribeToEffect(e),this}addEffects(e){return e.forEach(t=>this.add(t)),this}async start(){return this.running?this:(await this.storage.waitForReady(),this.effects.forEach(e=>this.subscribeToEffect(e)),this.running=!0,this)}stop(){return this.subscriptions.forEach(e=>e.unsubscribe()),this.subscriptions=[],this.running=!1,this}subscribeToEffect(e){try{let s=e(this.action$.asObservable(),this.state$,this.externalStates,this.dispatchers,this.services,this.config).pipe(re(r=>ee(null))).subscribe(r=>{if(r!=null&&typeof r=="function")try{r()}catch{}});this.subscriptions.push(s)}catch{}}};function ne(a){if(!a.storage&&!a.createStorageFn)throw new Error('Synapse config must have either "storage" or "createStorageFn"');if(a.storage&&a.createStorageFn)throw new Error('Synapse config cannot have both "storage" and "createStorageFn". Choose one.');if(a.effects&&!a.createDispatcherFn)throw new Error('Effects require dispatcher. Add "createDispatcherFn" to config.');if(a.createEffectConfig&&!a.createDispatcherFn)throw new Error('Effect config requires dispatcher. Add "createDispatcherFn" to config.');if(a.dependencies){if(!Array.isArray(a.dependencies))throw new Error("Dependencies must be an array");a.dependencies.forEach((e,t)=>{if(!e||typeof e!="object")throw new Error(`Dependency at index ${t} must be an object`);if(!e.storage||typeof e.storage.waitForReady!="function")throw new Error(`Dependency at index ${t} must have a storage with waitForReady method`)})}if(a.createStorageFn&&typeof a.createStorageFn!="function")throw new Error('"createStorageFn" must be a function');if(a.createDispatcherFn&&typeof a.createDispatcherFn!="function")throw new Error('"createDispatcherFn" must be a function');if(a.createSelectorsFn&&typeof a.createSelectorsFn!="function")throw new Error('"createSelectorsFn" must be a function');if(a.createEffectConfig&&typeof a.createEffectConfig!="function")throw new Error('"createEffectConfig" must be a function');if(a.effects){if(!Array.isArray(a.effects))throw new Error("Effects must be an array");a.effects.forEach((e,t)=>{if(typeof e!="function")throw new Error(`Effect at index ${t} must be a function`)})}if(a.externalSelectors&&typeof a.externalSelectors!="object")throw new Error("External selectors must be an object")}async function oe(a=[]){a.length!==0&&await Promise.all(a.map(async(e,t)=>{try{await e.storage.waitForReady()}catch(s){throw new Error(`Dependency ${t} initialization failed: ${s}`)}}))}async function j(a){try{ne(a)}catch(o){throw o}await oe(a.dependencies);let e=a.createStorageFn?await a.createStorageFn():a.storage;await e.waitForReady();let t=[],s={storage:e,selectors:{},destroy:async()=>{for(let o of t)await o()}};t.push(()=>e.destroy());let r,n,i;if(a.createSelectorsFn)try{n=new B(e);let o=a.externalSelectors||{};s.selectors=a.createSelectorsFn(n,o),typeof n.destroy=="function"&&t.push(()=>n.destroy())}catch{}if(a.createDispatcherFn&&(r=a.createDispatcherFn(e),s.dispatcher=r,r&&"dispatch"in r&&(s.actions=r.dispatch,typeof r.destroy=="function"&&t.push(()=>r.destroy()))),a.createEffectConfig&&r)try{let{dispatchers:o,api:c,config:d,externalStates:u}=a.createEffectConfig(r),g=u||{};i=new F(e,g,o,c,d),Array.isArray(a.effects)&&a.effects.forEach(l=>{i&&i.add(l)}),await i.start(),s.state$=i.state$,t.push(()=>{i&&i.stop()})}catch{}return s}function ie(a,e){return e==="*"?!0:e.includes("*")?new RegExp("^"+e.replace(/\*/g,".*")+"$").test(a):a===e}async function ae(a,e){let t=await a.getState(),s=Object.entries(t.events||{});if(s.length>e){let n=s.sort((i,o)=>o[1].timestamp-i[1].timestamp).slice(0,e);await a.set("events",Object.fromEntries(n))}}var ce=(a={})=>j({createStorageFn:async()=>new C({name:a.name||"eventBus",initialState:{events:{},subscriptions:{}}}).initialize(),createDispatcherFn:e=>G({storage:e},(t,{createAction:s})=>({publish:s({type:"PUBLISH_EVENT",meta:{description:"\u041F\u0443\u0431\u043B\u0438\u043A\u0430\u0446\u0438\u044F \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u0432 EventBus"},action:async({event:r,data:n,metadata:i={}})=>{let o=`${r}_${Date.now()}_${Math.random()}`;return await t.set(`events.${o}`,{id:o,event:r,data:n,metadata:{ttl:i.ttl||null,priority:i.priority||"normal",...i},timestamp:Date.now()}),a.autoCleanup&&await ae(t,a.maxEvents||1e3),{eventId:o,event:r,data:n}}}),subscribe:s({type:"SUBSCRIBE_TO_EVENT",meta:{description:"\u041F\u043E\u0434\u043F\u0438\u0441\u043A\u0430 \u043D\u0430 \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u0432 EventBus"},action:async({eventPattern:r,handler:n,options:i={}})=>{let o=`sub_${Date.now()}_${Math.random()}`,c=t.subscribe(d=>d.events,d=>{Object.values(d||{}).forEach(u=>{if(ie(u.event,r)){if(i.priority&&u.metadata.priority!==i.priority)return;try{n(u.data,u)}catch{}}})});return await t.set(`subscriptions.${o}`,{id:o,pattern:r,options:i,createdAt:Date.now()}),{subscriptionId:o,unsubscribe:c}}}),getEventHistory:s({type:"GET_EVENT_HISTORY",meta:{description:"\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435 \u0438\u0441\u0442\u043E\u0440\u0438\u0438 \u0441\u043E\u0431\u044B\u0442\u0438\u0439"},action:async({eventType:r,limit:n=100})=>{let i=await t.getState();return Object.values(i.events||{}).filter(o=>o.event===r).sort((o,c)=>c.timestamp-o.timestamp).slice(0,n)}}),clearEvents:s({type:"CLEAR_EVENTS",meta:{description:"\u041E\u0447\u0438\u0441\u0442\u043A\u0430 \u0441\u043E\u0431\u044B\u0442\u0438\u0439"},action:async({olderThan:r}={})=>{if(r){let n=Date.now()-r;await t.update(i=>{Object.keys(i.events||{}).forEach(o=>{i.events[o].timestamp<n&&delete i.events[o]})})}else await t.set("events",{})}}),getActiveSubscriptions:s({type:"GET_SUBSCRIPTIONS",meta:{description:"\u041F\u043E\u043B\u0443\u0447\u0435\u043D\u0438\u0435 \u0430\u043A\u0442\u0438\u0432\u043D\u044B\u0445 \u043F\u043E\u0434\u043F\u0438\u0441\u043E\u043A"},action:async()=>{let r=await t.getState();return Object.values(r.subscriptions||{})}})}))});function le(a){let e="pending",t,s=null,r=new Set,n=new Set,i=(async()=>{try{let o=await(a instanceof Promise?a:Promise.resolve(a));return await o.storage.waitForReady(),t=o,e="ready",r.forEach(c=>{try{c(t)}catch{}}),o}catch(o){let c=o instanceof Error?o:new Error(String(o));throw s=c,e="error",n.forEach(d=>{try{d(c)}catch{}}),c}})();return{waitForReady:()=>i,isReady:()=>e==="ready",getStoreIfReady:()=>t,onReady:o=>{if(e==="ready"&&t)try{o(t)}catch{}else r.add(o);return()=>{r.delete(o)}},onError:o=>{if(e==="error"&&s)try{o(s)}catch{}else n.add(o);return()=>{n.delete(o)}},getStatus:()=>e,getError:()=>s,destroy:()=>{r.clear(),n.clear(),t=void 0,s=null,e="pending"}}}export{ce as createEventBus,j as createSynapse,le as createSynapseAwaiter};