synapse-storage 3.0.11 → 3.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.d.ts CHANGED
@@ -1,92 +1,95 @@
1
- import { Observable } from 'rxjs';
2
- import { I as ISelectorModule } from './selector.interface-CA5y-kD_.js';
3
- import { I as IStorage } from './storage.interface-Dl8SLUd1.js';
4
- import { m as ExternalStates, o as Effect } from './dispatcher.module-jd8U_ZEs.js';
1
+ import { a as SynapseStoreWithDispatcher } from './createSynapse--jDPgRKD.js';
2
+ export { A as AnySynapseStore, S as SynapseStoreBasic, b as SynapseStoreWithEffects, c as createSynapse } from './createSynapse--jDPgRKD.js';
3
+ import { j as IStorage } from './storage.interface-2HKvqdAJ.js';
4
+ import { D as DispatchFunction, g as DispatchActions } from './dispatcher.module-Dd7-DiCn.js';
5
+ import 'rxjs';
6
+ import './selector.interface-CA5y-kD_.js';
5
7
 
6
- type ExtractDispatchType<T> = T extends {
7
- dispatch: infer D;
8
- } ? D : never;
9
- type StorageCreatorFunction<T extends Record<string, any>> = () => Promise<IStorage<T>>;
10
- /**
11
- * Базовая конфигурация хранилища
12
- */
13
- type BaseSynapseConfig<TStore extends Record<string, any>, TSelectors = any, TExternalSelectors extends Record<string, any> = Record<string, any>> = ({
14
- storage: IStorage<TStore>;
15
- createStorageFn?: undefined;
16
- } | {
17
- storage?: undefined;
18
- createStorageFn: StorageCreatorFunction<TStore>;
19
- }) & {
20
- externalSelectors?: TExternalSelectors;
21
- createSelectorsFn?: (selectorModule: ISelectorModule<TStore>, externalSelectors: TExternalSelectors) => TSelectors;
22
- };
23
- /**
24
- * Конфигурация с dispatcher и effects
25
- */
26
- type CreateSynapseConfigWithEffects<TStore extends Record<string, any>, TSelectors = any, TDispatcher = any, TApi extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalSelectors extends Record<string, any> = Record<string, any>> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {
27
- createDispatcherFn: (storage: IStorage<TStore>) => TDispatcher;
28
- createEffectConfig: (dispatcher: TDispatcher) => {
29
- dispatchers: Record<string, any>;
30
- api?: TApi;
31
- config?: TConfig;
32
- externalStates?: ExternalStates;
8
+ interface EventBusEvent {
9
+ id: string;
10
+ event: string;
11
+ data: any;
12
+ metadata: {
13
+ ttl?: number | null;
14
+ priority?: 'low' | 'normal' | 'high';
15
+ [key: string]: any;
33
16
  };
34
- effects?: Effect<TStore, any, TApi, TConfig, any>[];
35
- };
36
- /**
37
- * Конфигурация только с dispatcher
38
- */
39
- type CreateSynapseConfigWithDispatcher<TStore extends Record<string, any>, TSelectors = any, TDispatcher = any, TExternalSelectors extends Record<string, any> = Record<string, any>> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {
40
- createDispatcherFn: (storage: IStorage<TStore>) => TDispatcher;
41
- createEffectConfig?: never;
42
- effects?: never;
43
- };
44
- /**
45
- * Конфигурация без dispatcher
46
- */
47
- type CreateSynapseConfigBasic<TStore extends Record<string, any>, TSelectors = any, TExternalSelectors extends Record<string, any> = Record<string, any>> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {
48
- createDispatcherFn?: never;
49
- createEffectConfig?: never;
50
- effects?: never;
51
- };
52
- /**
53
- * Результат с dispatcher и effects
54
- */
55
- interface SynapseStoreWithEffects<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions> {
56
- storage: TStorage;
57
- selectors: TSelectors;
58
- actions: TActions;
59
- state$: Observable<TStore>;
60
- dispatcher: any;
61
- destroy: () => Promise<void>;
17
+ timestamp: number;
62
18
  }
63
- /**
64
- * Результат только с dispatcher
65
- */
66
- interface SynapseStoreWithDispatcher<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions> {
67
- storage: TStorage;
68
- selectors: TSelectors;
69
- actions: TActions;
70
- dispatcher: any;
71
- destroy: () => Promise<void>;
19
+ interface EventBusState {
20
+ events: Record<string, EventBusEvent>;
21
+ subscriptions: Record<string, any>;
72
22
  }
73
- /**
74
- * Результат без dispatcher
75
- */
76
- interface SynapseStoreBasic<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors> {
77
- storage: TStorage;
78
- selectors: TSelectors;
79
- destroy: () => Promise<void>;
23
+ interface EventBusConfig {
24
+ name?: string;
25
+ autoCleanup?: boolean;
26
+ maxEvents?: number;
80
27
  }
81
28
  /**
82
- * Union-тип для всех возможных результатов createSynapse
83
- */
84
- type AnySynapseStore<TStore extends Record<string, any> = any, TStorage extends IStorage<TStore> = IStorage<any>, TSelectors = any, TActions = any> = SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions> | SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions> | SynapseStoreBasic<TStore, TStorage, TSelectors>;
85
- /**
86
- * Перегрузки функции createSynapse
29
+ * Создает EventBus для связи между модулями
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // Создание EventBus
34
+ * const eventBus = await createEventBus({
35
+ * name: 'app-events',
36
+ * autoCleanup: true,
37
+ * maxEvents: 500
38
+ * })
39
+ *
40
+ * // Использование в Synapse
41
+ * const mySynapse = await createSynapse({
42
+ * dependencies: [eventBus],
43
+ * createEffectConfig: (dispatcher) => ({
44
+ * dispatchers: {
45
+ * dispatcher,
46
+ * eventBus: eventBus.dispatcher
47
+ * }
48
+ * }),
49
+ * effects: [
50
+ * createEffect((action$, _, __, { eventBus }) => {
51
+ * // Публикация события
52
+ * eventBus.dispatch.publish({
53
+ * event: 'USER_UPDATED',
54
+ * data: { userId: 123 }
55
+ * })
56
+ *
57
+ * // Подписка на события
58
+ * eventBus.dispatch.subscribe({
59
+ * eventPattern: 'CORE_*',
60
+ * handler: (data, event) => console.log('Received:', event.event, data)
61
+ * })
62
+ * })
63
+ * ]
64
+ * })
65
+ * ```
87
66
  */
88
- declare function createSynapse<TStore extends Record<string, any>, TSelectors = any, TDispatcher = any, TApi extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalSelectors extends Record<string, any> = Record<string, any>, TStorage extends IStorage<TStore> = IStorage<TStore>>(config: CreateSynapseConfigWithEffects<TStore, TSelectors, TDispatcher, TApi, TConfig, TExternalSelectors>): Promise<SynapseStoreWithEffects<TStore, TStorage, TSelectors, ExtractDispatchType<TDispatcher>>>;
89
- declare function createSynapse<TStore extends Record<string, any>, TSelectors = any, TDispatcher = any, TExternalSelectors extends Record<string, any> = Record<string, any>, TStorage extends IStorage<TStore> = IStorage<TStore>>(config: CreateSynapseConfigWithDispatcher<TStore, TSelectors, TDispatcher, TExternalSelectors>): Promise<SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, ExtractDispatchType<TDispatcher>>>;
90
- declare function createSynapse<TStore extends Record<string, any>, TSelectors = any, TExternalSelectors extends Record<string, any> = Record<string, any>, TStorage extends IStorage<TStore> = IStorage<TStore>>(config: CreateSynapseConfigBasic<TStore, TSelectors, TExternalSelectors>): Promise<SynapseStoreBasic<TStore, TStorage, TSelectors>>;
67
+ declare const createEventBus: (config?: EventBusConfig) => Promise<SynapseStoreWithDispatcher<EventBusState, IStorage<EventBusState>, any, Record<string, DispatchFunction<any, any>> & DispatchActions<{
68
+ publish: DispatchFunction<{
69
+ event: string;
70
+ data: any;
71
+ metadata?: Record<string, any>;
72
+ }, {
73
+ eventId: string;
74
+ event: string;
75
+ data: any;
76
+ }>;
77
+ subscribe: DispatchFunction<{
78
+ eventPattern: string;
79
+ handler: (data: any, event: EventBusEvent) => void | Promise<void>;
80
+ options?: Record<string, any>;
81
+ }, {
82
+ subscriptionId: string;
83
+ unsubscribe: VoidFunction;
84
+ }>;
85
+ getEventHistory: DispatchFunction<{
86
+ eventType: string;
87
+ limit?: number;
88
+ }, EventBusEvent[]>;
89
+ clearEvents: DispatchFunction<{
90
+ olderThan?: number;
91
+ } | undefined, void>;
92
+ getActiveSubscriptions: DispatchFunction<any, any[]>;
93
+ }>>>;
91
94
 
92
- export { type AnySynapseStore, type SynapseStoreBasic, type SynapseStoreWithDispatcher, type SynapseStoreWithEffects, createSynapse };
95
+ export { type EventBusConfig, type EventBusEvent, type EventBusState, SynapseStoreWithDispatcher, createEventBus };
package/dist/utils.js CHANGED
@@ -1 +1 @@
1
- var l=!1,h=new Map;function w(n){let e=0;if(n.length===0)return e.toString(36);for(let t=0;t<n.length;t++){let r=n.charCodeAt(t);e=(e<<5)-e+r,e=e&e}return Math.abs(e).toString(36).substring(0,6)}function g(n,e){if(n===e)return!0;if(n==null||e==null)return!1;if(typeof n!="object"&&typeof n!="function"&&typeof e!="object"&&typeof e!="function")return n===e;if(typeof n!=typeof e)return!1;if(n instanceof Date&&e instanceof Date)return n.getTime()===e.getTime();if(Array.isArray(n)&&Array.isArray(e)){if(n.length!==e.length)return!1;for(let t=0;t<n.length;t++)if(!g(n[t],e[t]))return!1;return!0}if(typeof n=="object"&&typeof e=="object"){let t=Object.keys(n),r=Object.keys(e);return t.length!==r.length?!1:t.every(s=>Object.prototype.hasOwnProperty.call(e,s)?g(n[s],e[s]):!1)}return!1}function v(n,e=g){let t,r,s=!1;return function(o){if(!s||t!==o){let i=n(o);(!s||!e(i,r))&&(r=i),t=o,s=!0}return r}}var y=class{constructor(e,t,r=g,s){this.name=e;this.equals=r;this.logger=s;this.id=e,this.memoizedGetState=this.createMemoizedGetState(t),l&&console.log(`[${this.id}] \u0421\u043E\u0437\u0434\u0430\u043D new SelectorSubscription`)}id;subscribers=new Set;lastValue;memoizedGetState;createMemoizedGetState(e){let t=null,r=!1;return async()=>{if(r&&t)return t;r=!0;try{return t=e(),await t}finally{r=!1}}}async notify(){try{let e=await this.memoizedGetState();if(this.lastValue===void 0||!this.equals(e,this.lastValue)){l&&console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C, notify()`,{old:this.lastValue,new:e}),this.lastValue=e;let t=Array.from(this.subscribers).map(async r=>{try{await r.notify(e)}catch(s){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:s})}});await Promise.all(t)}else l&&console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C in notify(), \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F`)}catch(e){throw this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 notify()`,{error:e}),e}}subscribe(e){return l&&console.log(`[${this.id}] \u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u043E \u043D\u043E\u0432\u044B\u0439 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A, \u0432\u0441\u0435\u0433\u043E: ${this.subscribers.size+1}`),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})}),()=>{l&&console.log(`[${this.id}] \u041F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A \u0443\u0434\u0430\u043B\u0435\u043D, \u043E\u0441\u0442\u0430\u043B\u043E\u0441\u044C: ${this.subscribers.size-1}`),this.subscribers.delete(e)}}cleanup(){l&&console.log(`[${this.id}] \u041E\u0447\u0438\u0441\u0442\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438, \u0431\u044B\u043B\u043E ${this.subscribers.size} \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u043E\u0432`),this.subscribers.clear(),this.lastValue=void 0}getId(){return this.id}},f=class{constructor(e,t){this.source=e;this.logger=t;this.storageName=e.name,l&&console.log(`\u0421\u043E\u0437\u0434\u0430\u043D SelectorModule \u0434\u043B\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430: ${this.storageName}`),this.source.getState().then(r=>{this.cachedState=r,l&&console.log(`\u041A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0434\u043B\u044F ${this.storageName}`)})}storageName;subscriptions=new Map;cachedState;localSelectorCache=new Map;batchUpdateInProgress=!1;pendingUpdates=new Set;generateName(e,t,r){let s=e?"simple":"combined",a="";if(e){let o=t.toString();a=w(o)}else{let o=t.map(c=>c.getId()).join("_"),i=r.toString();a=w(o+i)}return`${this.storageName}_${s}_${a}`}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 r=>{let s=this.subscriptions.get(r);if(s)try{return await s.notify()}catch(a){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 ${r}`,{error:a})}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,r){let s=!Array.isArray(e),a=s?t||{}:r||{},o=a.name||this.generateName(s,e,s?void 0:t);if(this.localSelectorCache.has(o))return l&&console.log(`[${this.storageName}] Reusing cached selector: ${o}`),this.localSelectorCache.get(o).api;if(h.has(o)){let u=h.get(o);return u.refCount++,l&&console.log(`[${this.storageName}] \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440\u0430: ${o}, refCount: ${u.refCount}`),u.api}let i,c,p=[];if(s){let u=v(e,a.equals||g),d=this.createSimpleSelector(u,{...a,name:o,equals:a.equals||g});i=d.api,p=d.unsubscribeFunctions}else{c=e;let u=this.createCombinedSelector(c,t,{...a,name:o,equals:a.equals||g});i=u.api,p=u.unsubscribeFunctions}return this.localSelectorCache.set(o,{api:i,dependencies:c,unsubscribeFunctions:p}),h.set(o,{api:i,refCount:1,unsubscribeFunctions:p}),l&&console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043D\u043E\u0432\u044B\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${o}`),i}createSimpleSelector(e,t){l&&console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043F\u0440\u043E\u0441\u0442\u043E\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${t.name}`);let r=async()=>{if(this.cachedState)return e(this.cachedState);let c=await this.source.getState();return this.cachedState=c,e(c)},s=new y(t.name,r,t.equals||g,this.logger),a=s.getId();this.subscriptions.set(a,s);let i=[this.source.subscribeToAll(async c=>{c?.type==="storage:update"&&(l&&console.log(`[${a}] \u041F\u043E\u043B\u0443\u0447\u0435\u043D\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430`),this.pendingUpdates.add(a),this.processPendingUpdates())})];return{api:{select:()=>r(),subscribe:c=>s.subscribe(c),getId:()=>a},unsubscribeFunctions:i}}createCombinedSelector(e,t,r){let s=v(d=>t(...d),r.equals||g),a=async()=>{let d=await Promise.all(e.map(m=>m.select()));return s(d)},o=new y(r.name,a,r.equals||g,this.logger),i=o.getId();this.subscriptions.set(i,o);let c=null,p=()=>{c!==null&&clearTimeout(c),c=setTimeout(()=>{c=null,o.notify().catch(d=>this.logger?.error(`[${i}] \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:d}))},10)},u=e.map(d=>d.subscribe({notify:()=>{p()}}));return{api:{select:()=>a(),subscribe:d=>o.subscribe(d),getId:()=>i},unsubscribeFunctions:u}}destroy(){l&&console.log(`[${this.storageName}] \u041D\u0430\u0447\u0430\u043B\u043E\u0441\u044C \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u0438\u0435 SelectorModule`),this.subscriptions.forEach(t=>t.cleanup()),this.subscriptions.clear(),this.cachedState=void 0,this.pendingUpdates.clear(),this.localSelectorCache.forEach(t=>{t.unsubscribeFunctions.forEach(r=>r())});let e=new Set;this.localSelectorCache.forEach((t,r)=>{e.add(r)}),this.localSelectorCache.clear(),e.forEach(t=>{let r=h.get(t);r&&(r.refCount--,r.refCount<=0&&(r.unsubscribeFunctions.forEach(s=>s()),h.delete(t),l&&console.log(`[${this.storageName}] \u0423\u0434\u0430\u043B\u0435\u043D \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440 \u0438\u0437 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0430: ${t}`)))}),l&&console.log(`[${this.storageName}] \u0423\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D`)}};import{Subject as Le}from"rxjs";import{combineLatest as Ot,merge as Bt,Observable as I,of as M,pipe as Nt,Subject as C}from"rxjs";import{catchError as O,filter as Ft,map as Vt,share as B,switchMap as Ut,take as jt}from"rxjs/operators";import{of as dt}from"rxjs";import{concatAll as gt,delay as pt,mergeMap as ht,toArray as yt}from"rxjs/operators";import{forkJoin as Tt,timer as wt}from"rxjs";import{mergeMap as xt}from"rxjs/operators";var S=class{constructor(e,t={},r,s={},a={}){this.storage=e;this.externalStates=t;this.dispatchers=r;this.services=s;this.config=a;this.subscribeToDispatchers(),this.state$=new I(o=>{this.storage.getState().then(c=>o.next(c));let i=this.storage.subscribeToAll(()=>{this.storage.getState().then(c=>o.next(c))});return()=>i()}).pipe(B())}effects=[];subscriptions=[];running=!1;action$=new C;state$;subscribeToDispatchers(){for(let[e,t]of Object.entries(this.dispatchers)){let r=t.actions.subscribe(s=>{this.action$.next(s)});this.subscriptions.push(r)}}add(e){return this.effects.push(e),this.running&&this.subscribeToEffect(e),this}addEffects(e){return e.forEach(t=>this.add(t)),this}start(){return this.running?this:(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 r=e(this.action$.asObservable(),this.state$,this.externalStates,this.dispatchers,this.services,this.config).pipe(O(s=>(console.error("Error in effect:",s),M(null)))).subscribe(s=>{if(s!=null&&typeof s=="function")try{s()}catch(a){console.error("Error calling effect result function:",a)}});this.subscriptions.push(r)}catch(t){console.error("Error setting up effect:",t)}}};async function K(n){let e=n.createStorageFn?await n.createStorageFn():n.storage,t=[],r={storage:e,selectors:{},destroy:async()=>{for(let i of t)await i()}};t.push(()=>e.destroy());let s,a,o;if(n.createSelectorsFn)try{a=new f(e);let i=n.externalSelectors||{};r.selectors=n.createSelectorsFn(a,i),typeof a.destroy=="function"&&t.push(()=>a.destroy())}catch(i){console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F selectors:",i)}if(n.createDispatcherFn&&(s=n.createDispatcherFn(e),r.dispatcher=s,s&&"dispatch"in s&&(r.actions=s.dispatch,typeof s.destroy=="function"&&t.push(()=>s.destroy()))),n.createEffectConfig&&s)try{let{dispatchers:i,api:c,config:p,externalStates:u}=n.createEffectConfig(s),d=u||{};o=new S(e,d,i,c,p),Array.isArray(n.effects)&&n.effects.forEach(m=>{o&&o.add(m)}),o.start(),r.state$=o.state$,t.push(()=>{o&&o.stop()})}catch(i){console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043C\u043E\u0434\u0443\u043B\u044F \u044D\u0444\u0444\u0435\u043A\u0442\u043E\u0432:",i)}return r}export{K as createSynapse};
1
+ var f=!1,A=new Map;function N(i){let e=0;if(i.length===0)return e.toString(36);for(let t=0;t<i.length;t++){let s=i.charCodeAt(t);e=(e<<5)-e+s,e=e&e}return Math.abs(e).toString(36).substring(0,6)}function T(i,e){if(i===e)return!0;if(i==null||e==null)return!1;if(typeof i!="object"&&typeof i!="function"&&typeof e!="object"&&typeof e!="function")return i===e;if(typeof i!=typeof e)return!1;if(i instanceof Date&&e instanceof Date)return i.getTime()===e.getTime();if(Array.isArray(i)&&Array.isArray(e)){if(i.length!==e.length)return!1;for(let t=0;t<i.length;t++)if(!T(i[t],e[t]))return!1;return!0}if(typeof i=="object"&&typeof e=="object"){let t=Object.keys(i),s=Object.keys(e);return t.length!==s.length?!1:t.every(r=>Object.prototype.hasOwnProperty.call(e,r)?T(i[r],e[r]):!1)}return!1}function K(i,e=T){let t,s,r=!1;return function(a){if(!r||t!==a){let o=i(a);(!r||!e(o,s))&&(s=o),t=a,r=!0}return s}}var I=class{constructor(e,t,s=T,r){this.name=e;this.equals=s;this.logger=r;this.id=e,this.memoizedGetState=this.createMemoizedGetState(t),f&&console.log(`[${this.id}] \u0421\u043E\u0437\u0434\u0430\u043D new SelectorSubscription`)}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)){f&&console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C, notify()`,{old:this.lastValue,new:e}),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)}else f&&console.log(`[${this.id}] \u0417\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043D\u0435 \u0438\u0437\u043C\u0435\u043D\u0438\u043B\u043E\u0441\u044C in notify(), \u043F\u0440\u043E\u043F\u0443\u0441\u043A \u0443\u0432\u0435\u0434\u043E\u043C\u043B\u0435\u043D\u0438\u044F`)}catch(e){throw this.logger?.error(`[${this.id}] \u041E\u0448\u0438\u0431\u043A\u0430 \u0432 notify()`,{error:e}),e}}subscribe(e){return f&&console.log(`[${this.id}] \u0414\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u043E \u043D\u043E\u0432\u044B\u0439 \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A, \u0432\u0441\u0435\u0433\u043E: ${this.subscribers.size+1}`),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})}),()=>{f&&console.log(`[${this.id}] \u041F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A \u0443\u0434\u0430\u043B\u0435\u043D, \u043E\u0441\u0442\u0430\u043B\u043E\u0441\u044C: ${this.subscribers.size-1}`),this.subscribers.delete(e)}}cleanup(){f&&console.log(`[${this.id}] \u041E\u0447\u0438\u0441\u0442\u043A\u0430 \u043F\u043E\u0434\u043F\u0438\u0441\u043A\u0438, \u0431\u044B\u043B\u043E ${this.subscribers.size} \u043F\u043E\u0434\u043F\u0438\u0441\u0447\u0438\u043A\u043E\u0432`),this.subscribers.clear(),this.lastValue=void 0}getId(){return this.id}},C=class{constructor(e,t){this.source=e;this.logger=t;this.storageName=e.name,f&&console.log(`\u0421\u043E\u0437\u0434\u0430\u043D SelectorModule \u0434\u043B\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430: ${this.storageName}`),this.source.getState().then(s=>{this.cachedState=s,f&&console.log(`\u041A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0435 \u043D\u0430\u0447\u0430\u043B\u044C\u043D\u043E\u0435 \u0441\u043E\u0441\u0442\u043E\u044F\u043D\u0438\u0435 \u0434\u043B\u044F ${this.storageName}`)})}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 a=t.toString();n=N(a)}else{let a=t.map(c=>c.getId()).join("_"),o=s.toString();n=N(a+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||{},a=n.name||this.generateName(r,e,r?void 0:t);if(this.localSelectorCache.has(a))return f&&console.log(`[${this.storageName}] Reusing cached selector: ${a}`),this.localSelectorCache.get(a).api;if(A.has(a)){let u=A.get(a);return u.refCount++,f&&console.log(`[${this.storageName}] \u041F\u043E\u0432\u0442\u043E\u0440\u043D\u043E\u0435 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u043E\u0433\u043E \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440\u0430: ${a}, refCount: ${u.refCount}`),u.api}let o,c,d=[];if(r){let u=K(e,n.equals||T),p=this.createSimpleSelector(u,{...n,name:a,equals:n.equals||T});o=p.api,d=p.unsubscribeFunctions}else{c=e;let u=this.createCombinedSelector(c,t,{...n,name:a,equals:n.equals||T});o=u.api,d=u.unsubscribeFunctions}return this.localSelectorCache.set(a,{api:o,dependencies:c,unsubscribeFunctions:d}),A.set(a,{api:o,refCount:1,unsubscribeFunctions:d}),f&&console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043D\u043E\u0432\u044B\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${a}`),o}createSimpleSelector(e,t){f&&console.log(`[${this.storageName}] \u0421\u043E\u0437\u0434\u0430\u043D \u043F\u0440\u043E\u0441\u0442\u043E\u0439 \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440: ${t.name}`);let s=async()=>{if(this.cachedState)return e(this.cachedState);let c=await this.source.getState();return this.cachedState=c,e(c)},r=new I(t.name,s,t.equals||T,this.logger),n=r.getId();this.subscriptions.set(n,r);let o=[this.source.subscribeToAll(async c=>{c?.type==="storage:update"&&(f&&console.log(`[${n}] \u041F\u043E\u043B\u0443\u0447\u0435\u043D\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0435 \u043E\u0431\u043D\u043E\u0432\u043B\u0435\u043D\u0438\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430`),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=K(p=>t(...p),s.equals||T),n=async()=>{let p=await Promise.all(e.map(l=>l.select()));return r(p)},a=new I(s.name,n,s.equals||T,this.logger),o=a.getId();this.subscriptions.set(o,a);let c=null,d=()=>{c!==null&&clearTimeout(c),c=setTimeout(()=>{c=null,a.notify().catch(p=>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:p}))},10)},u=e.map(p=>p.subscribe({notify:()=>{d()}}));return{api:{select:()=>n(),subscribe:p=>a.subscribe(p),getId:()=>o},unsubscribeFunctions:u}}destroy(){f&&console.log(`[${this.storageName}] \u041D\u0430\u0447\u0430\u043B\u043E\u0441\u044C \u0443\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D\u0438\u0435 SelectorModule`),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=A.get(t);s&&(s.refCount--,s.refCount<=0&&(s.unsubscribeFunctions.forEach(r=>r()),A.delete(t),f&&console.log(`[${this.storageName}] \u0423\u0434\u0430\u043B\u0435\u043D \u0441\u0435\u043B\u0435\u043A\u0442\u043E\u0440 \u0438\u0437 \u0433\u043B\u043E\u0431\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u043A\u044D\u0448\u0430: ${t}`)))}),f&&console.log(`[${this.storageName}] \u0423\u043D\u0438\u0447\u0442\u043E\u0436\u0435\u043D`)}};var b=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 _=(i={})=>{let e=i.batchSize??10,t=i.batchDelay??10,s=new Map,r=new Map,n=l=>l.type==="set"||l.type==="update",a=l=>`${l.type}_${l.key?.toString()||"default"}`,o=l=>{let g=new Map;for(let h of l){let S=`${h.type}_${h.key?.toString()||"default"}`;g.set(S,h)}return Array.from(g.values())},c=l=>{let g=r.get(l);g&&(globalThis.clearTimeout(g),r.delete(l))},d=(l,g)=>{let h=globalThis.setTimeout(g,t);r.set(l,h)},u=async(l,g,h)=>{let S=s.get(l);if(!(!S||S.length===0)){s.delete(l),c(l);try{let v=S.map(y=>y.action),m=o(v);console.log(`\u{1F504} Batching ${l}: ${S.length} actions -> ${m.length} merged`,{original:v.map(y=>({type:y.type,key:y.key?.toString(),value:y.value})),merged:m.map(y=>({type:y.type,key:y.key?.toString(),value:y.value}))});for(let y of m)try{let B=await h(y);S.filter(w=>w.action.type===y.type&&w.action.key?.toString()===y.key?.toString()).forEach(w=>w.resolve(B))}catch(B){S.filter(w=>w.action.type===y.type&&w.action.key?.toString()===y.key?.toString()).forEach(w=>w.reject(B))}}catch(v){S.forEach(m=>m.reject(v))}}},p=async(l,g,h)=>new Promise((S,v)=>{let m=a(l),y=s.get(m);y||(y=[],s.set(m,y)),y.push({action:l,resolve:S,reject:v,timestamp:Date.now()}),c(m),y.length>=e?setImmediate(()=>u(m,g,h)):d(m,()=>u(m,g,h))});return{name:"batching",setup:()=>{},cleanup:async()=>{r.forEach(l=>globalThis.clearTimeout(l)),r.clear(),s.clear()},reducer:l=>g=>async h=>n(h)?p(h,l,g):g(h)}};var V=(i={})=>{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 a=Object.keys(r),o=Object.keys(n);return a.length!==o.length?!1:a.every(c=>Object.prototype.hasOwnProperty.call(n,c)&&r[c]===n[c])},segments:t=[]}=i,s=new Map;return{name:"shallow-compare",setup:r=>{},reducer:r=>n=>async a=>{if(a.type!=="set"||t.length&&!t.includes(a.metadata?.segment??"default"))return n(a);let o=a.key,c=s.get(o),d=a.value;if(c!==void 0&&e(c,d))return console.log("ShallowCompare: \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0438\u0434\u0435\u043D\u0442\u0438\u0447\u043D\u044B, \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430\u0435\u043C \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044E",{key:o,value:d}),{...c,__metadata:{valueNotChanged:!0,originalValue:c}};let u=await n(a);return s.set(o,d),u}}};var M=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 console.error("Error in middleware chain:",t),t}}};function x(i){return i instanceof b&&i.isUnparseable()?[i.toString()]:i.toString().replace(/\[/g,".").replace(/\]/g,"").split(".").filter(Boolean)}function E(i,e){return x(e).reduce((s,r)=>s===void 0?void 0:s[r],i)}function P(i,e,t){if(e==="")return t;let s=x(e);if(e instanceof b&&e.isUnparseable())return i[e.toString()]=t,i;let r=s.pop(),n=s.reduce((a,o)=>{let c=s[s.indexOf(o)+1],d=!Number.isNaN(Number(c));return o in a||(a[o]=d?[]:{}),a[o]},i);return n[r]=t,i}var R=class i{constructor(e,t,s,r){this.config=e;this.pluginExecutor=t;this.eventEmitter=s;this.logger=r;this.name=e.name,this.middlewareModule=new M({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="*";name;_initStatus={status:"idle"};statusSubscribers=new Set;selectorPathCache=new WeakMap;middlewareModule;initializedMiddlewares=null;subscribers=new Map;get initStatus(){return{...this._initStatus}}async waitForReady(){if(this._initStatus.status==="ready")return this;if(this._initStatus.status==="error")throw this._initStatus.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._initStatus.status;this._initStatus={...this._initStatus,...e},t!==this._initStatus.status&&this.logger?.debug(`Storage "${this.name}" status changed: ${t} -> ${this._initStatus.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._initStatus.status==="ready")return this;if(this._initStatus.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._initStatus.status!=="ready")throw new Error(`Storage "${this.name}" is not ready. Current status: ${this._initStatus.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={})=>V(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}),a=n?.__metadata?.valueNotChanged===!0,o;if(a&&n?.__metadata?.originalValue!==void 0?o=n.__metadata.originalValue:o=await this.pluginExecutor?.executeAfterSet(e,n,s)??n,!a){let d=[e.toString()];this.notifySubscribers(e,o),this.notifySubscribers(i.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 a=new Set;for(let l of n){let g=l.split(".")[0];a.add(g)}let o=await Promise.all(Array.from(a).map(async l=>{let g={...t,key:l},h=await this.pluginExecutor?.executeBeforeSet(r[l],g)??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 p={};u.forEach(l=>{p[l]=d[l]}),this.logger?.debug&&this.logger.debug("Notifying subscribers about changes:",{keys:u}),this.notifySubscribers(i.GLOBAL_SUBSCRIPTION_KEY,{type:"storage:update",key:u,value:p,changedPaths:Array.from(n)});for(let l of n)try{let g=l.split(".")[0];if(g in p){let h;if(l===g)h=p[g];else{let S=l.substring(g.length+1);h=E(p[g],S)}h!==void 0&&this.notifySubscribers(l,h)}}catch(g){this.logger?.error("Error notifying path subscribers",{path:l,error:g})}await this.emitEvent({type:"storage:update",payload:{state:p,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)){let s=await this.middlewareModule.dispatch({type:"delete",key:e,metadata:t});await this.pluginExecutor?.executeAfterDelete(e,t);let n=[e.toString()];this.notifySubscribers(e,void 0),this.notifySubscribers(i.GLOBAL_SUBSCRIPTION_KEY,{type:"storage:update",key:e,value:void 0,result:s,changedPaths:n}),await this.emitEvent({type:"storage:update",payload:{key:e,value:void 0,result:s,changedPaths:n}})}}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(i.GLOBAL_SUBSCRIPTION_KEY)||this.subscribers.set(i.GLOBAL_SUBSCRIPTION_KEY,new Set),this.subscribers.get(i.GLOBAL_SUBSCRIPTION_KEY).add(e),()=>{let t=this.subscribers.get(i.GLOBAL_SUBSCRIPTION_KEY);t&&(t.delete(e),t.size===0&&this.subscribers.delete(i.GLOBAL_SUBSCRIPTION_KEY))}}subscribe(e,t){return typeof e=="string"?this.subscribeByKey(e,t):this.subscribeBySelector(e,t)}async destroy(){try{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.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),a=Object.keys(t);return n.length!==a.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:(a,o)=>{if(typeof o=="symbol")return Reflect.get(a,o);let c=n?`${n}.${o}`:o;return s.push(c),new Proxy({},r(c))},has:(a,o)=>!0,ownKeys:()=>[],getOwnPropertyDescriptor:()=>({configurable:!0,enumerable:!0}),apply:(a,o,c)=>new Proxy(()=>{},r(n))});try{e(new Proxy(t,r()))}catch{}return s.length===0?"":(s.sort((n,a)=>a.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(a=>{try{a(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 a=new Set([...Object.keys(e||{}),...Object.keys(t||{})]);for(let o of a){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 a=>{try{if(a==null){let d=await this.getState(),u=e(d);t(u);return}if(typeof a!="object"||a===null){t(a);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(a)}};return r?this.subscribeByKey(r,n):this.subscribeToAll(()=>{this.getState().then(a=>{t(e(a))})})}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 D=class extends R{storage=new Map;constructor(e,t,s,r){super(e,t,s,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 b&&e.isUnparseable()?t[e.valueOf()]:E(t,e)}async doSet(e,t){let s=this.storage.get(this.name)||{};if(e instanceof b&&e.isUnparseable()){s[e.valueOf()]=t,this.storage.set(this.name,s);return}let r=P({...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 b&&e.isUnparseable()){let o=e.valueOf();return o in t?(delete t[o],this.storage.set(this.name,t),!0):!1}let s=x(e),r=s.slice(0,-1).join("."),n=s[s.length-1],a=r?E(t,r):t;return!a||!(n in a)?!1:(delete a[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 b&&r.isUnparseable()?s[r.valueOf()]=n:P(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{Subject as j}from"rxjs";var $=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 j;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(s){console.error(`Error initializing middleware [${t}]:`,s)}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,a=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 p=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 g=this.middlewareFunctions[l],h=p;p=async S=>g(async m=>h(m))(S)}u=await p(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 a._type="dispatch",Object.defineProperty(a,"actionType",{value:s,writable:!1,enumerable:!0}),e.meta&&Object.defineProperty(a,"meta",{value:e.meta,writable:!1,enumerable:!0}),a}createWatcher(e){let t=`[${this.storage.name}]${e.type}`,s=new j,r,n=this.storage.subscribe(e.selector,o=>{if(!e.shouldTrigger||e.shouldTrigger(r,o)){let c={type:t,payload:o,meta:e.meta};this.actions$.next(c),s.next(c),r=o}}),a=()=>s.asObservable();return a._type="watchers",Object.defineProperty(a,"actionType",{value:t,writable:!1,enumerable:!0}),e.meta&&Object.defineProperty(a,"meta",{value:e.meta,writable:!1,enumerable:!0}),Object.defineProperty(a,"unsubscribe",{value:n,writable:!1,enumerable:!0}),a}async executeInWorker(e,t,s,r){return new Promise((n,a)=>{let o=`${t}_${Date.now()}_${Math.random()}`,c=d=>{d.data.requestId===o&&(e.removeEventListener("message",c),d.data.error?a(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),a(new Error(`Worker execution timeout for action: ${t}`))},3e4)})}};function U(i,e){let t=new $(i),s=e(i.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 a=n._type;t[a][r]=n}return t}import{combineLatest as Jt,merge as Qt,Observable as L,of as W,pipe as Zt,Subject as H}from"rxjs";import{catchError as Y,filter as tr,map as rr,share as J,switchMap as sr,take as nr}from"rxjs/operators";import{of as Dt}from"rxjs";import{concatAll as Ct,delay as Mt,mergeMap as Ot,toArray as Bt}from"rxjs/operators";import{forkJoin as Kt,timer as Vt}from"rxjs";import{mergeMap as Ut}from"rxjs/operators";var O=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 L(a=>{this.storage.getState().then(c=>a.next(c));let o=this.storage.subscribeToAll(()=>{this.storage.getState().then(c=>a.next(c))});return()=>o()}).pipe(J())}effects=[];subscriptions=[];running=!1;action$=new H;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(Y(r=>(console.error("Error in effect:",r),W(null)))).subscribe(r=>{if(r!=null&&typeof r=="function")try{r()}catch(n){console.error("Error calling effect result function:",n)}});this.subscriptions.push(s)}catch(t){console.error("Error setting up effect:",t)}}};function Q(i){if(!i.storage&&!i.createStorageFn)throw new Error('Synapse config must have either "storage" or "createStorageFn"');if(i.storage&&i.createStorageFn)throw new Error('Synapse config cannot have both "storage" and "createStorageFn". Choose one.');if(i.effects&&!i.createDispatcherFn)throw new Error('Effects require dispatcher. Add "createDispatcherFn" to config.');if(i.createEffectConfig&&!i.createDispatcherFn)throw new Error('Effect config requires dispatcher. Add "createDispatcherFn" to config.');if(i.dependencies){if(!Array.isArray(i.dependencies))throw new Error("Dependencies must be an array");i.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(i.createStorageFn&&typeof i.createStorageFn!="function")throw new Error('"createStorageFn" must be a function');if(i.createDispatcherFn&&typeof i.createDispatcherFn!="function")throw new Error('"createDispatcherFn" must be a function');if(i.createSelectorsFn&&typeof i.createSelectorsFn!="function")throw new Error('"createSelectorsFn" must be a function');if(i.createEffectConfig&&typeof i.createEffectConfig!="function")throw new Error('"createEffectConfig" must be a function');if(i.effects){if(!Array.isArray(i.effects))throw new Error("Effects must be an array");i.effects.forEach((e,t)=>{if(typeof e!="function")throw new Error(`Effect at index ${t} must be a function`)})}if(i.externalSelectors&&typeof i.externalSelectors!="object")throw new Error("External selectors must be an object")}async function X(i=[]){i.length!==0&&(console.log(`Waiting for ${i.length} dependencies to be ready...`),await Promise.all(i.map(async(e,t)=>{try{await e.storage.waitForReady(),console.log(`Dependency ${t} (${e.storage.name||"unnamed"}) is ready`)}catch(s){throw console.error(`Dependency ${t} failed to initialize:`,s),new Error(`Dependency ${t} initialization failed: ${s}`)}})),console.log("All dependencies are ready!"))}async function F(i){try{Q(i)}catch(o){throw console.error("Synapse configuration validation failed:",o),o}await X(i.dependencies);let e=i.createStorageFn?await i.createStorageFn():i.storage;await e.waitForReady(),console.log(`Storage "${e.name}" is ready`);let t=[],s={storage:e,selectors:{},destroy:async()=>{for(let o of t)await o()}};t.push(()=>e.destroy());let r,n,a;if(i.createSelectorsFn)try{n=new C(e);let o=i.externalSelectors||{};s.selectors=i.createSelectorsFn(n,o),typeof n.destroy=="function"&&t.push(()=>n.destroy())}catch(o){console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F selectors:",o)}if(i.createDispatcherFn&&(r=i.createDispatcherFn(e),s.dispatcher=r,r&&"dispatch"in r&&(s.actions=r.dispatch,typeof r.destroy=="function"&&t.push(()=>r.destroy()))),i.createEffectConfig&&r)try{let{dispatchers:o,api:c,config:d,externalStates:u}=i.createEffectConfig(r),p=u||{};a=new O(e,p,o,c,d),Array.isArray(i.effects)&&i.effects.forEach(l=>{a&&a.add(l)}),await a.start(),s.state$=a.state$,t.push(()=>{a&&a.stop()})}catch(o){console.error("\u041E\u0448\u0438\u0431\u043A\u0430 \u0441\u043E\u0437\u0434\u0430\u043D\u0438\u044F \u043C\u043E\u0434\u0443\u043B\u044F \u044D\u0444\u0444\u0435\u043A\u0442\u043E\u0432:",o)}return s}function Z(i,e){return e==="*"?!0:e.includes("*")?new RegExp("^"+e.replace(/\*/g,".*")+"$").test(i):i===e}async function ee(i,e){let t=await i.getState(),s=Object.entries(t.events||{});if(s.length>e){let n=s.sort((a,o)=>o[1].timestamp-a[1].timestamp).slice(0,e);await i.set("events",Object.fromEntries(n))}}var te=(i={})=>F({createStorageFn:async()=>new D({name:i.name||"eventBus",initialState:{events:{},subscriptions:{}}}).initialize(),createDispatcherFn:e=>U({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:a={}})=>{let o=`${r}_${Date.now()}_${Math.random()}`;return await t.set(`events.${o}`,{id:o,event:r,data:n,metadata:{ttl:a.ttl||null,priority:a.priority||"normal",...a},timestamp:Date.now()}),i.autoCleanup&&await ee(t,i.maxEvents||1e3),console.log(`\u{1F4E2} Event published: ${r}`,n),{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:a={}})=>{let o=`sub_${Date.now()}_${Math.random()}`,c=t.subscribe(d=>d.events,d=>{Object.values(d||{}).forEach(u=>{if(Z(u.event,r)){if(a.priority&&u.metadata.priority!==a.priority)return;try{n(u.data,u)}catch(p){console.error(`Error in event handler for ${u.event}:`,p)}}})});return await t.set(`subscriptions.${o}`,{id:o,pattern:r,options:a,createdAt:Date.now()}),console.log(`\u{1F514} Subscribed to: ${r}`),{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 a=await t.getState();return Object.values(a.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(a=>{Object.keys(a.events||{}).forEach(o=>{a.events[o].timestamp<n&&delete a.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||{})}})}))});export{te as createEventBus,F as createSynapse};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synapse-storage",
3
- "version": "3.0.11",
3
+ "version": "3.0.12",
4
4
  "description": "Набор инструментов для управления состоянием и апи-запросами",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,128 +0,0 @@
1
- declare class StorageKey {
2
- private readonly value;
3
- private readonly isRawKey;
4
- constructor(value: string, isRawKey?: boolean);
5
- toString(): string;
6
- toJSON(): string;
7
- valueOf(): string;
8
- isUnparseable(): boolean;
9
- }
10
- type StorageKeyType = string | StorageKey;
11
-
12
- interface IndexedDBConfig {
13
- dbName?: string;
14
- dbVersion?: number;
15
- storeName?: string;
16
- }
17
-
18
- type StorageActionType = 'get' | 'set' | 'delete' | 'clear' | 'init' | 'keys' | 'update';
19
- type StorageAction = {
20
- type: StorageActionType;
21
- key?: StorageKeyType;
22
- value?: any;
23
- metadata?: Record<string, any>;
24
- source?: string;
25
- timestamp?: number;
26
- };
27
- type MiddlewareAPI = {
28
- dispatch: (action: StorageAction) => Promise<any>;
29
- getState: () => Promise<Record<string, any>>;
30
- storage: {
31
- doGet: (key: StorageKeyType) => Promise<any>;
32
- doSet: (key: StorageKeyType, value: any) => Promise<void>;
33
- doUpdate: (updates: Array<{
34
- key: StorageKeyType;
35
- value: any;
36
- }>) => Promise<void>;
37
- doDelete: (key: StorageKeyType) => Promise<boolean>;
38
- doClear: () => Promise<void>;
39
- doKeys: () => Promise<string[]>;
40
- notifySubscribers: (key: StorageKeyType, value: any) => void;
41
- };
42
- };
43
- type NextFunction = (action: StorageAction) => Promise<any>;
44
- type SetupEventsFunction = (api: MiddlewareAPI) => void;
45
- type Middleware = {
46
- name: string;
47
- setup?: SetupEventsFunction;
48
- cleanup?: () => Promise<void> | void;
49
- reducer: (api: MiddlewareAPI) => (next: NextFunction) => (action: StorageAction) => Promise<any>;
50
- };
51
-
52
- interface BatchingMiddlewareOptions {
53
- batchSize?: number;
54
- batchDelay?: number;
55
- }
56
-
57
- interface ShallowCompareMiddlewareOptions {
58
- segments?: string[];
59
- comparator?: <T>(prev: T, next: T) => boolean;
60
- }
61
-
62
- interface IStorage<T extends Record<string, any> = any> {
63
- name: string;
64
- get<R>(key: StorageKeyType): Promise<R | undefined>;
65
- getState(): Promise<T>;
66
- set<R>(key: StorageKeyType, value: R): Promise<void>;
67
- update(updater: (state: T) => void): Promise<void>;
68
- has(key: StorageKeyType): Promise<boolean>;
69
- delete(key: StorageKeyType): Promise<void>;
70
- clear(): Promise<void>;
71
- keys(): Promise<string[]>;
72
- destroy(): Promise<void>;
73
- subscribeToAll(callback: (event: {
74
- type: string;
75
- changedPaths?: string[];
76
- key?: StorageKeyType[] | StorageKeyType;
77
- value?: any;
78
- }) => void): VoidFunction;
79
- initialize(): Promise<this>;
80
- subscribe(key: StorageKeyType, callback: (value: any) => void): VoidFunction;
81
- subscribe<R>(pathSelector: (state: T) => R, callback: (value: R) => void): VoidFunction;
82
- }
83
- declare enum StorageEvents {
84
- STORAGE_UPDATE = "storage:update",
85
- STORAGE_DELETE = "storage:delete",
86
- STORAGE_PATCH = "storage:patch",
87
- STORAGE_SELECT = "storage:select",
88
- STORAGE_CLEAR = "storage:clear",
89
- STORAGE_DESTROY = "storage:destroy"
90
- }
91
- interface StorageEvent<T = any> {
92
- type: string;
93
- payload?: T;
94
- metadata?: Record<string, any>;
95
- }
96
- interface IEventEmitter {
97
- emit(event: StorageEvent): Promise<void>;
98
- }
99
- interface ILogger {
100
- debug(message: string, meta?: Record<string, any>): void;
101
- info(message: string, meta?: Record<string, any>): void;
102
- warn(message: string, meta?: Record<string, any>): void;
103
- error(message: string, meta?: Record<string, any>): void;
104
- }
105
- interface DefaultMiddlewares {
106
- batching: (options?: BatchingMiddlewareOptions) => Middleware;
107
- shallowCompare: (options?: ShallowCompareMiddlewareOptions) => Middleware;
108
- }
109
- type GetDefaultMiddleware = () => DefaultMiddlewares;
110
- type ConfigureMiddlewares = (getDefaultMiddleware: GetDefaultMiddleware) => Middleware[];
111
- interface StorageConfig {
112
- name: string;
113
- initialState?: Record<string, any>;
114
- middlewares?: ConfigureMiddlewares;
115
- }
116
- type StorageType = 'memory' | 'localStorage' | 'indexedDB';
117
- interface MemoryStorageConfig extends StorageConfig {
118
- type: 'memory';
119
- }
120
- interface LocalStorageConfig extends StorageConfig {
121
- type: 'localStorage';
122
- }
123
- interface IndexedDBStorageConfig extends StorageConfig {
124
- type: 'indexedDB';
125
- options: IndexedDBConfig;
126
- }
127
-
128
- export { type BatchingMiddlewareOptions as B, type ConfigureMiddlewares as C, type DefaultMiddlewares as D, type GetDefaultMiddleware as G, type IStorage as I, type LocalStorageConfig as L, type Middleware as M, type NextFunction as N, type ShallowCompareMiddlewareOptions as S, type MiddlewareAPI as a, type StorageAction as b, type StorageKeyType as c, StorageEvents as d, type StorageEvent as e, type IEventEmitter as f, type ILogger as g, type StorageConfig as h, type StorageType as i, type MemoryStorageConfig as j, type IndexedDBStorageConfig as k, StorageKey as l };