synapse-storage 3.0.3 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/index.ts","../src/core/selector/selector.module.ts","../src/core/storage/modules/plugin/plugin.service.ts","../src/core/storage/storage.interface.ts","../src/core/storage/utils/broadcast.util.ts","../src/core/storage/middlewares/broadcast.middleware.ts","../src/core/storage/utils/storage-key.ts","../src/core/storage/utils/batch.utils.ts","../src/core/storage/middlewares/storage-batching.middleware.ts","../src/core/storage/middlewares/storage-shallow-compare.middleware.ts","../src/core/storage/utils/middleware-module.ts","../src/core/storage/adapters/path.utils.ts","../src/core/storage/adapters/base-storage.service.ts","../src/core/storage/adapters/indexed-DB.service.ts","../src/core/storage/adapters/local-storage.service.ts","../src/core/storage/adapters/memory-storage.service.ts"],"sourcesContent":["export * from './selector'\nexport * from './storage'\n","import { ILogger, IStorage } from '../storage'\nimport { ISelectorModule, Selector, SelectorAPI, SelectorOptions, Subscriber } from './selector.interface'\n\n// Отладка: управление через параметр DEBUG\nconst DEBUG = false\n\n// Глобальный кеш селекторов (используем имя селектора как ключ)\nconst GLOBAL_SELECTOR_CACHE = new Map<\n string,\n {\n api: SelectorAPI<any>\n refCount: number\n unsubscribeFunctions: VoidFunction[]\n }\n>()\n\n/**\n * Получает короткий хеш строки для добавления уникальности к имени селектора\n * @param str Строка для хеширования\n * @returns Короткий хеш\n */\nfunction getStringHash(str: string): string {\n let hash = 0\n if (str.length === 0) return hash.toString(36)\n\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash\n }\n\n // Преобразуем в короткую строку в формате base36\n return Math.abs(hash).toString(36).substring(0, 6)\n}\n\n/**\n * Интеллектуальное сравнение объектов по структуре\n * Сравнивает примитивы через ===, объекты - рекурсивно по структуре\n */\nfunction defaultEquals<T>(a: T, b: T): boolean {\n // Проверяем, одинаковые ли объекты по ссылке\n if (a === b) return true\n\n // Если один из объектов null или undefined, но не оба одновременно\n if (a == null || b == null) return false\n\n // Если это не объекты или функции, значит это примитивы\n if (typeof a !== 'object' && typeof a !== 'function' && typeof b !== 'object' && typeof b !== 'function') {\n return a === b\n }\n\n // Если это разные типы\n if (typeof a !== typeof b) return false\n\n // Если это даты\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime()\n }\n\n // Если это массивы\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (!defaultEquals(a[i], b[i])) return false\n }\n return true\n }\n\n // Обычные объекты\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n\n if (keysA.length !== keysB.length) return false\n\n // Проверяем все ключи в a\n return keysA.every((key) => {\n if (!Object.prototype.hasOwnProperty.call(b, key)) return false\n return defaultEquals((a as any)[key], (b as any)[key])\n })\n }\n\n // По умолчанию считаем объекты разными\n return false\n}\n\n// Мемоизирует функцию селектора для оптимизации\nfunction memoizeSelector<S, R>(selectorFn: (state: S) => R, equals: (a: R, b: R) => boolean = defaultEquals): (state: S) => R {\n let lastState: S | undefined\n let lastResult: R | undefined\n let hasResult = false\n\n return function memoized(state: S): R {\n // Если это первый вызов или состояние изменилось\n if (!hasResult || lastState !== state) {\n const newResult = selectorFn(state)\n\n // Проверяем, изменился ли результат\n if (!hasResult || !equals(newResult, lastResult as R)) {\n lastResult = newResult\n }\n\n lastState = state\n hasResult = true\n }\n\n return lastResult as R\n }\n}\n\nclass SelectorSubscription<T> {\n private readonly id: string\n readonly subscribers = new Set<Subscriber<T>>()\n private lastValue?: T\n private readonly memoizedGetState: () => Promise<T>\n\n constructor(\n private readonly name: string,\n getState: () => Promise<T>,\n private readonly equals: (a: T, b: T) => boolean = defaultEquals,\n private readonly logger?: ILogger,\n ) {\n this.id = name\n\n // Создаем мемоизированную версию getState\n this.memoizedGetState = this.createMemoizedGetState(getState)\n\n if (DEBUG) {\n console.log(`[${this.id}] Создан new SelectorSubscription`)\n }\n }\n\n // Создает мемоизированную версию getState с кешированием результата\n private createMemoizedGetState(getState: () => Promise<T>): () => Promise<T> {\n let lastPromise: Promise<T> | null = null\n let isExecuting = false\n\n return async () => {\n // Если уже выполняется запрос, возвращаем его\n if (isExecuting && lastPromise) {\n return lastPromise\n }\n\n isExecuting = true\n\n try {\n lastPromise = getState()\n return await lastPromise\n } finally {\n isExecuting = false\n }\n }\n }\n\n async notify(): Promise<void> {\n try {\n const newValue = await this.memoizedGetState()\n\n // Проверка на изменение значения с использованием функции сравнения\n if (this.lastValue === undefined || !this.equals(newValue, this.lastValue)) {\n if (DEBUG) {\n console.log(`[${this.id}] Значение изменилось, notify()`, {\n old: this.lastValue,\n new: newValue,\n })\n }\n\n this.lastValue = newValue\n\n const promises = Array.from(this.subscribers).map(async (subscriber) => {\n try {\n await subscriber.notify(newValue)\n } catch (error) {\n this.logger?.error(`[${this.id}] Ошибка в уведомлении подписчика`, { error })\n }\n })\n\n await Promise.all(promises)\n } else if (DEBUG) {\n console.log(`[${this.id}] Значение не изменилось in notify(), пропуск уведомления`)\n }\n } catch (error: any) {\n this.logger?.error(`[${this.id}] Ошибка в notify()`, { error })\n throw error\n }\n }\n\n subscribe(subscriber: Subscriber<T>): () => void {\n if (DEBUG) {\n console.log(`[${this.id}] Добавлено новый подписчик, всего: ${this.subscribers.size + 1}`)\n }\n\n this.subscribers.add(subscriber)\n\n // Отправляем текущее значение, если оно есть\n if (this.lastValue !== undefined) {\n // Используем микротаск для асинхронности\n Promise.resolve().then(() => {\n try {\n subscriber.notify(this.lastValue as T)\n } catch (error) {\n this.logger?.error(`[${this.id}] Ошибка в первоначальном уведомлении`, { error })\n }\n })\n } else {\n // Если значения нет - запрашиваем его\n this.notify().catch((error) => {\n this.logger?.error(`[${this.id}] Ошибка в первоначальном уведомлении`, { error })\n })\n }\n\n return () => {\n if (DEBUG) {\n console.log(`[${this.id}] Подписчик удален, осталось: ${this.subscribers.size - 1}`)\n }\n this.subscribers.delete(subscriber)\n }\n }\n\n cleanup(): void {\n if (DEBUG) {\n console.log(`[${this.id}] Очистка подписки, было ${this.subscribers.size} подписчиков`)\n }\n this.subscribers.clear()\n this.lastValue = undefined\n }\n\n getId(): string {\n return this.id\n }\n}\n\nexport class SelectorModule<S extends Record<string, any>> implements ISelectorModule<S> {\n storageName: string\n\n private subscriptions = new Map<string, SelectorSubscription<any>>()\n private cachedState?: S\n\n private localSelectorCache = new Map<\n string,\n {\n api: SelectorAPI<any>\n dependencies?: SelectorAPI<any>[]\n unsubscribeFunctions: Array<() => void>\n }\n >()\n\n // Флаг для батчинга обновлений\n private batchUpdateInProgress = false\n private pendingUpdates = new Set<string>()\n\n constructor(\n private readonly source: IStorage<S>,\n private readonly logger?: ILogger,\n ) {\n this.storageName = source.name\n\n if (DEBUG) {\n console.log(`Создан SelectorModule для хранилища: ${this.storageName}`)\n }\n\n // Сразу получаем начальное состояние для кеширования\n this.source.getState().then((state) => {\n this.cachedState = state\n if (DEBUG) {\n console.log(`Кэшированное начальное состояние для ${this.storageName}`)\n }\n })\n }\n\n /**\n * Генерирует имя для селектора на основе его типа и функции\n */\n private generateName(isSimpleSelector: boolean, selectorOrDeps: any, resultFnOrOptions?: any): string {\n const type = isSimpleSelector ? 'simple' : 'combined'\n let hash = ''\n\n if (isSimpleSelector) {\n // Для простого селектора генерируем хеш на основе функции селектора\n const selectorStr = selectorOrDeps.toString()\n hash = getStringHash(selectorStr)\n } else {\n // Для комбинированного селектора генерируем хеш на основе ID зависимостей и функции результата\n const depsIds = (selectorOrDeps as SelectorAPI<any>[]).map((s) => s.getId()).join('_')\n const resultFnStr = resultFnOrOptions.toString()\n hash = getStringHash(depsIds + resultFnStr)\n }\n\n return `${this.storageName}_${type}_${hash}`\n }\n\n /**\n * Обрабатывает отложенные обновления, чтобы избежать каскадных уведомлений\n */\n private processPendingUpdates(): void {\n if (this.pendingUpdates.size === 0 || this.batchUpdateInProgress) return\n\n this.batchUpdateInProgress = true\n\n // Используем setTimeout для обеспечения асинхронности и батчинга обновлений\n setTimeout(async () => {\n try {\n // Копируем список селекторов для обновления\n const subscriptionsToUpdate = Array.from(this.pendingUpdates)\n this.pendingUpdates.clear()\n\n // Обновляем состояние один раз\n this.cachedState = await this.source.getState()\n\n // Обновляем все ожидающие селекторы\n const updatePromises = subscriptionsToUpdate.map(async (id) => {\n const subscription = this.subscriptions.get(id)\n if (subscription) {\n try {\n return await subscription.notify()\n } catch (error) {\n this.logger?.error(`Ошибка уведомления подписчика ${id}`, { error })\n }\n }\n return Promise.resolve()\n })\n\n await Promise.all(updatePromises)\n } catch (error) {\n this.logger?.error('Ошибка обработки ожидающих обновлений', { error })\n } finally {\n this.batchUpdateInProgress = false\n\n // Если появились новые обновления во время обработки, запускаем процесс снова\n if (this.pendingUpdates.size > 0) {\n this.processPendingUpdates()\n }\n }\n }, 0)\n }\n\n createSelector<T>(selector: Selector<S, T>, options?: SelectorOptions<T>): SelectorAPI<T>\n createSelector<Deps extends unknown[], T>(dependencies: { [K in keyof Deps]: SelectorAPI<Deps[K]> }, resultFn: (...args: Deps) => T, options?: SelectorOptions<T>): SelectorAPI<T>\n\n createSelector<T>(\n selectorOrDeps: Selector<S, T> | SelectorAPI<any>[],\n resultFnOrOptions?: ((...args: any[]) => T) | SelectorOptions<T>,\n optionsArg?: SelectorOptions<T>,\n ): SelectorAPI<T> {\n // Определяем, какую перегрузку используем\n const isSimpleSelector = !Array.isArray(selectorOrDeps)\n\n // Извлекаем options\n const options = isSimpleSelector ? (resultFnOrOptions as SelectorOptions<T>) || {} : optionsArg || {}\n\n // Используем предоставленное имя или генерируем новое\n const selectorId = options.name || this.generateName(isSimpleSelector, selectorOrDeps, isSimpleSelector ? undefined : resultFnOrOptions)\n\n // Проверяем локальный кеш\n if (this.localSelectorCache.has(selectorId)) {\n if (DEBUG) {\n console.log(`[${this.storageName}] Reusing cached selector: ${selectorId}`)\n }\n return this.localSelectorCache.get(selectorId)!.api\n }\n\n // Проверяем глобальный кеш\n if (GLOBAL_SELECTOR_CACHE.has(selectorId)) {\n const cached = GLOBAL_SELECTOR_CACHE.get(selectorId)!\n cached.refCount++\n if (DEBUG) {\n console.log(`[${this.storageName}] Повторное использование глобального кэшированного селектора: ${selectorId}, refCount: ${cached.refCount}`)\n }\n return cached.api\n }\n\n // Создаем новый селектор\n let result: SelectorAPI<T>\n let dependencies: SelectorAPI<any>[] | undefined\n let unsubscribeFunctions: VoidFunction[] = []\n\n if (isSimpleSelector) {\n // Простой селектор с мемоизацией\n const memoized = memoizeSelector(selectorOrDeps as Selector<S, T>, options.equals || defaultEquals)\n\n const created = this.createSimpleSelector(memoized, { ...options, name: selectorId, equals: options.equals || defaultEquals })\n\n result = created.api\n unsubscribeFunctions = created.unsubscribeFunctions\n } else {\n // Комбинированный селектор\n dependencies = selectorOrDeps as SelectorAPI<any>[]\n\n const created = this.createCombinedSelector(dependencies, resultFnOrOptions as (...args: any[]) => T, {\n ...options,\n name: selectorId,\n equals: options.equals || defaultEquals,\n })\n\n result = created.api\n unsubscribeFunctions = created.unsubscribeFunctions\n }\n\n // Сохраняем в кеши\n this.localSelectorCache.set(selectorId, {\n api: result,\n dependencies,\n unsubscribeFunctions,\n })\n\n GLOBAL_SELECTOR_CACHE.set(selectorId, {\n api: result,\n refCount: 1,\n unsubscribeFunctions,\n })\n\n if (DEBUG) {\n console.log(`[${this.storageName}] Создан новый селектор: ${selectorId}`)\n }\n\n return result\n }\n\n private createSimpleSelector<T>(\n selector: Selector<S, T>,\n options: SelectorOptions<T> & { name: string },\n ): {\n api: SelectorAPI<T>\n unsubscribeFunctions: VoidFunction[]\n } {\n if (DEBUG) {\n console.log(`[${this.storageName}] Создан простой селектор: ${options.name}`)\n }\n\n // Функция для получения данных\n const getState = async (): Promise<T> => {\n // Используем кешированное состояние, если оно доступно\n if (this.cachedState) {\n return selector(this.cachedState as S)\n }\n\n // Иначе получаем его из хранилища\n const state = await this.source.getState()\n this.cachedState = state // Обновляем кеш\n return selector(state as S)\n }\n\n const subscription = new SelectorSubscription(options.name, getState, options.equals || defaultEquals, this.logger)\n\n const id = subscription.getId()\n this.subscriptions.set(id, subscription)\n\n // Подписка на обновления хранилища с батчингом\n const unsubscribeFromStorage = this.source.subscribeToAll(async (event: any) => {\n if (event?.type === 'storage:update') {\n if (DEBUG) {\n console.log(`[${id}] Получено событие обновления хранилища`)\n }\n\n // Добавляем селектор в список ожидающих обновления\n this.pendingUpdates.add(id)\n this.processPendingUpdates()\n }\n })\n\n const unsubscribeFunctions = [unsubscribeFromStorage]\n\n return {\n api: {\n select: () => getState(),\n subscribe: (subscriber) => {\n return subscription.subscribe(subscriber)\n },\n getId: () => id,\n },\n unsubscribeFunctions,\n }\n }\n\n private createCombinedSelector<Deps extends unknown[], T>(\n selectors: { [K in keyof Deps]: SelectorAPI<Deps[K]> },\n resultFn: (...args: Deps) => T,\n options: SelectorOptions<T> & { name: string },\n ): {\n api: SelectorAPI<T>\n unsubscribeFunctions: Array<() => void>\n } {\n // Мемоизируем функцию для более эффективного вычисления\n const memoizedResultFn = memoizeSelector((args: Deps) => resultFn(...args), options.equals || defaultEquals)\n\n const getState = async () => {\n const values = await Promise.all(selectors.map((s) => s.select()))\n return memoizedResultFn(values as Deps)\n }\n\n const subscription = new SelectorSubscription(options.name, getState, options.equals || defaultEquals, this.logger)\n\n const id = subscription.getId()\n this.subscriptions.set(id, subscription)\n\n // Создаем подписки на зависимости с дебаунсингом\n let debounceTimer: any = null\n\n const triggerUpdate = () => {\n // Очищаем предыдущий таймер\n if (debounceTimer !== null) {\n clearTimeout(debounceTimer)\n }\n\n // Устанавливаем новый таймер для дебаунсинга\n debounceTimer = setTimeout(() => {\n debounceTimer = null\n\n // Вызываем уведомление только после завершения дебаунса\n subscription.notify().catch((error) => this.logger?.error(`[${id}] Ошибка в объединенном уведомлении:`, { error }))\n }, 10) // Короткая задержка для дебаунсинга\n }\n\n const unsubscribeFunctions = selectors.map((selector) =>\n selector.subscribe({\n notify: () => {\n triggerUpdate()\n },\n }),\n )\n\n return {\n api: {\n select: () => getState(),\n subscribe: (subscriber) => {\n return subscription.subscribe(subscriber)\n },\n getId: () => id,\n },\n unsubscribeFunctions,\n }\n }\n\n destroy(): void {\n if (DEBUG) {\n console.log(`[${this.storageName}] Началось уничтожение SelectorModule`)\n }\n\n // Очищаем все подписки\n this.subscriptions.forEach((sub) => sub.cleanup())\n this.subscriptions.clear()\n\n // Очищаем кеш состояния\n this.cachedState = undefined\n\n // Очищаем список ожидающих обновлений\n this.pendingUpdates.clear()\n\n // Очищаем подписки из локального кеша\n this.localSelectorCache.forEach((cached) => {\n cached.unsubscribeFunctions.forEach((unsub) => unsub())\n })\n\n // Собираем ключи для глобального кеша\n const keysToCheck = new Set<string>()\n this.localSelectorCache.forEach((_, key) => {\n keysToCheck.add(key)\n })\n this.localSelectorCache.clear()\n\n // Уменьшаем счетчики ссылок в глобальном кеше\n keysToCheck.forEach((key) => {\n const globalCached = GLOBAL_SELECTOR_CACHE.get(key)\n if (globalCached) {\n globalCached.refCount--\n if (globalCached.refCount <= 0) {\n globalCached.unsubscribeFunctions.forEach((unsub) => unsub())\n GLOBAL_SELECTOR_CACHE.delete(key)\n\n if (DEBUG) {\n console.log(`[${this.storageName}] Удален селектор из глобального кэша: ${key}`)\n }\n }\n }\n })\n if (DEBUG) {\n console.log(`[${this.storageName}] Уничтожен`)\n }\n }\n}\n","import { ILogger } from '../../storage.interface'\nimport { StorageKeyType } from '../../utils/storage-key'\nimport { IPluginExecutor, IPluginManager, IStoragePlugin, PluginContext } from './plugin.interface'\n\nexport class StoragePluginModule implements IPluginManager<IStoragePlugin>, IPluginExecutor {\n private plugins = new Map<string, IStoragePlugin>()\n\n constructor(\n protected readonly parentExecutor?: IPluginExecutor,\n protected readonly logger?: ILogger,\n protected readonly storageName: string = 'default',\n ) {}\n\n private createContext(metadata?: Record<string, any>): PluginContext {\n return {\n storageName: this.storageName,\n timestamp: Date.now(),\n metadata,\n }\n }\n\n public async add(plugin: IStoragePlugin): Promise<void> {\n if (this.plugins.has(plugin.name)) {\n this.logger?.warn(`Плагин ${plugin.name} уже был зарегистрирован`)\n return\n }\n\n try {\n await plugin.initialize?.()\n this.plugins.set(plugin.name, plugin)\n this.logger?.info('Плагин добавлен', { name: plugin.name })\n } catch (error) {\n throw error\n }\n }\n\n public async remove(name: string): Promise<void> {\n const plugin = this.plugins.get(name)\n if (plugin) {\n await plugin.destroy?.()\n this.plugins.delete(name)\n this.logger?.info('Плагин удален', { name })\n }\n }\n\n public get(name: string): IStoragePlugin | undefined {\n return this.plugins.get(name)\n }\n\n public getAll(): IStoragePlugin[] {\n return Array.from(this.plugins.values())\n }\n\n public async initialize(): Promise<void> {\n for (const plugin of this.plugins.values()) {\n await plugin.initialize?.()\n }\n }\n\n public async destroy(): Promise<void> {\n await Promise.all(Array.from(this.plugins.values()).map((plugin) => plugin.destroy?.() ?? Promise.resolve()))\n this.plugins.clear()\n }\n\n public async executeBeforeSet<T>(value: T, metadata?: Record<string, any>): Promise<T> {\n let result = value\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n result = await this.parentExecutor.executeBeforeSet(result, context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onBeforeSet) {\n try {\n result = await plugin.onBeforeSet(result, context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onBeforeSet`, { error })\n throw error\n }\n }\n }\n\n return result\n }\n\n public async executeAfterSet<T>(key: StorageKeyType, value: T, metadata?: Record<string, any>): Promise<T> {\n let result = value\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n result = await this.parentExecutor.executeAfterSet(key, result, context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onAfterSet) {\n try {\n result = await plugin.onAfterSet(key, result, context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onAfterSet`, { key, error })\n throw error\n }\n }\n }\n\n return result\n }\n\n public async executeBeforeGet(key: StorageKeyType, metadata?: Record<string, any>): Promise<StorageKeyType> {\n let processedKey = key\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n processedKey = await this.parentExecutor.executeBeforeGet(processedKey, context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onBeforeGet) {\n try {\n processedKey = await plugin.onBeforeGet(processedKey, context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onBeforeGet`, { key, error })\n throw error\n }\n }\n }\n\n return processedKey\n }\n\n public async executeAfterGet<T>(key: StorageKeyType, value: T | undefined, metadata?: Record<string, any>): Promise<T | undefined> {\n let result = value\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n result = await this.parentExecutor.executeAfterGet(key, result, context)\n }\n console.log('executeAfterGet', key, value, metadata)\n for (const plugin of this.plugins.values()) {\n if (plugin.onAfterGet) {\n try {\n result = await plugin.onAfterGet(key, result, context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onAfterGet`, { key, error })\n throw error\n }\n }\n }\n\n return result\n }\n\n public async executeBeforeDelete(key: StorageKeyType, metadata?: Record<string, any>): Promise<boolean> {\n let canDelete = true\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n canDelete = await this.parentExecutor.executeBeforeDelete(key, context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onBeforeDelete) {\n try {\n canDelete = (await plugin.onBeforeDelete(key, context)) && canDelete\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onBeforeDelete`, { key, error })\n throw error\n }\n }\n }\n\n return canDelete\n }\n\n public async executeAfterDelete(key: StorageKeyType, metadata?: Record<string, any>): Promise<void> {\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n await this.parentExecutor.executeAfterDelete(key, context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onAfterDelete) {\n try {\n await plugin.onAfterDelete(key, context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onAfterDelete`, { key, error })\n throw error\n }\n }\n }\n }\n\n public async executeOnClear(metadata?: Record<string, any>): Promise<void> {\n const context = this.createContext(metadata)\n\n if (this.parentExecutor) {\n await this.parentExecutor.executeOnClear(context)\n }\n\n for (const plugin of this.plugins.values()) {\n if (plugin.onClear) {\n try {\n await plugin.onClear(context)\n } catch (error) {\n this.logger?.error(`Ошибка в плагине ${plugin.name} onClear`, { error })\n throw error\n }\n }\n }\n }\n}\n","// storage.interface.ts\nimport { IndexedDBConfig } from './adapters/indexed-DB.service.old'\nimport { BatchingMiddlewareOptions, ShallowCompareMiddlewareOptions } from './middlewares'\nimport { Middleware } from './utils/middleware-module'\nimport { StorageKeyType } from './utils/storage-key'\n\nexport interface IStorage<T extends Record<string, any> = any> {\n name: string\n get<R>(key: StorageKeyType): Promise<R | undefined>\n getState(): Promise<T>\n set<R>(key: StorageKeyType, value: R): Promise<void>\n update(updater: (state: T) => void): Promise<void>\n has(key: StorageKeyType): Promise<boolean>\n delete(key: StorageKeyType): Promise<void>\n clear(): Promise<void>\n keys(): Promise<string[]>\n destroy(): Promise<void>\n subscribeToAll(callback: (event: { type: string; changedPaths?: string[]; key?: StorageKeyType[] | StorageKeyType; value?: any }) => void): VoidFunction\n initialize(): Promise<this>\n subscribe(key: StorageKeyType, callback: (value: any) => void): VoidFunction\n subscribe<R>(pathSelector: (state: T) => R, callback: (value: R) => void): VoidFunction\n}\n\nexport enum StorageEvents {\n STORAGE_UPDATE = 'storage:update',\n STORAGE_DELETE = 'storage:delete',\n STORAGE_PATCH = 'storage:patch',\n STORAGE_SELECT = 'storage:select',\n STORAGE_CLEAR = 'storage:clear',\n STORAGE_DESTROY = 'storage:destroy',\n}\n\nexport interface StorageEvent<T = any> {\n type: string\n payload?: T\n metadata?: Record<string, any>\n}\n\nexport interface IEventEmitter {\n emit(event: StorageEvent): Promise<void>\n}\n\nexport interface ILogger {\n debug(message: string, meta?: Record<string, any>): void\n info(message: string, meta?: Record<string, any>): void\n warn(message: string, meta?: Record<string, any>): void\n error(message: string, meta?: Record<string, any>): void\n}\n\n// Функции-создатели дефолтных middleware\nexport interface DefaultMiddlewares {\n batching: (options?: BatchingMiddlewareOptions) => Middleware\n shallowCompare: (options?: ShallowCompareMiddlewareOptions) => Middleware\n}\n\n// Функция для получения дефолтных middleware\nexport type GetDefaultMiddleware = () => DefaultMiddlewares\n\n// Функция настройки middleware\nexport type ConfigureMiddlewares = (getDefaultMiddleware: GetDefaultMiddleware) => Middleware[]\n\n// Основной интерфейс конфигурации\nexport interface StorageConfig {\n name: string\n initialState?: Record<string, any>\n middlewares?: ConfigureMiddlewares\n}\n\nexport type StorageType = 'memory' | 'localStorage' | 'indexedDB'\n\n// Уточним специфичные конфиги для разных типов хранилищ\nexport interface MemoryStorageConfig extends StorageConfig {\n type: 'memory'\n}\n\nexport interface LocalStorageConfig extends StorageConfig {\n type: 'localStorage'\n}\n\nexport interface IndexedDBStorageConfig extends StorageConfig {\n type: 'indexedDB'\n options: IndexedDBConfig\n}\n","interface BroadcastMessage<T = unknown> {\n type: string\n payload?: T\n senderId: string\n timestamp: number\n}\n\ntype MessageHandler<T> = (message: BroadcastMessage<T>) => void | Promise<void>\ntype SyncRequestHandler<T> = () => T | Promise<T>\n\ninterface SyncBroadcastChannelOptions {\n debug?: boolean\n}\n\nexport class SyncBroadcastChannel<T = unknown> {\n private channel: BroadcastChannel\n\n private readonly tabId: string\n\n private messageHandlers: Set<MessageHandler<T>>\n\n private syncHandler?: SyncRequestHandler<T>\n\n private debug: boolean\n\n private syncTimeoutMs = 1000\n\n private pendingSyncRequests: Map<\n string,\n {\n resolve: (value: T | null) => void\n reject: (reason?: any) => void\n timeout: NodeJS.Timeout\n }\n >\n\n constructor(channelName: string, options: SyncBroadcastChannelOptions = {}) {\n this.channel = new BroadcastChannel(channelName)\n this.tabId = crypto.randomUUID()\n this.messageHandlers = new Set()\n this.debug = options.debug ?? false\n this.pendingSyncRequests = new Map()\n\n this.channel.onmessage = this.handleMessage.bind(this)\n this.channel.onmessageerror = this.handleError.bind(this)\n }\n\n private log(...args: any[]) {\n if (this.debug) {\n console.log(`[SyncBroadcastChannel][${this.tabId}]`, ...args)\n }\n }\n\n private error(...args: any[]) {\n console.error(`[SyncBroadcastChannel][${this.tabId}]`, ...args)\n }\n\n private async handleMessage(event: MessageEvent<BroadcastMessage<T>>): Promise<void> {\n const message = event.data\n\n // Игнорируем собственные сообщения\n if (message.senderId === this.tabId) {\n return\n }\n\n // Обработка запроса на синхронизацию\n if (message.type === 'SYNC_REQUEST') {\n if (this.syncHandler) {\n try {\n const state = await this.syncHandler()\n this.postMessage('SYNC_RESPONSE', state, message.senderId)\n } catch (error) {\n this.error('Error handling sync request:', error)\n }\n }\n return\n }\n\n // Обработка ответа на запрос синхронизации\n if (message.type === 'SYNC_RESPONSE') {\n const request = this.pendingSyncRequests.get(this.tabId)\n if (request) {\n clearTimeout(request.timeout)\n this.pendingSyncRequests.delete(this.tabId)\n //@ts-ignore\n request.resolve(message.payload)\n }\n return\n }\n\n // Уведомляем всех подписчиков о сообщении\n for (const handler of this.messageHandlers) {\n try {\n await handler(message)\n } catch (error) {\n this.error('Error in message handler:', error)\n }\n }\n }\n\n private handleError(event: MessageEvent) {\n this.error('Channel error:', event)\n }\n\n private postMessage(type: string, payload: T, targetId?: string): void {\n const message: BroadcastMessage<T> = {\n type,\n payload,\n senderId: this.tabId,\n timestamp: Date.now(),\n }\n\n this.channel.postMessage(message)\n }\n\n /**\n * Подписка на сообщения канала\n */\n public subscribe(handler: MessageHandler<T>) {\n this.messageHandlers.add(handler)\n return () => this.messageHandlers.delete(handler)\n }\n\n /**\n * Установка обработчика запросов на синхронизацию\n */\n public setSyncHandler(handler: SyncRequestHandler<T>) {\n this.syncHandler = handler\n }\n\n /**\n * Отправка сообщения всем подписчикам\n */\n public broadcast(type: string, payload?: T) {\n //@ts-ignore\n this.postMessage(type, payload)\n }\n\n /**\n * Запрос синхронизации данных с других вкладок\n */\n public async requestSync(): Promise<T | null> {\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pendingSyncRequests.delete(this.tabId)\n resolve(null)\n }, this.syncTimeoutMs)\n\n this.pendingSyncRequests.set(this.tabId, { resolve, reject, timeout })\n\n this.postMessage('SYNC_REQUEST', { type: 'sync' } as T)\n })\n }\n\n /**\n * Закрытие канала\n */\n public close() {\n // Очищаем все pending запросы\n for (const [, request] of this.pendingSyncRequests) {\n clearTimeout(request.timeout)\n request.reject(new Error('Channel closed'))\n }\n this.pendingSyncRequests.clear()\n\n // Очищаем обработчики\n this.messageHandlers.clear()\n this.syncHandler = undefined\n\n // Закрываем канал\n this.channel.close()\n }\n}\n\n// Пример использования:\nconst example = () => {\n // Создаем канал\n const channel = new SyncBroadcastChannel<{ data: any }>('app-state', { debug: true })\n\n // Устанавливаем обработчик синхронизации\n channel.setSyncHandler(async () => ({\n data: {\n /* текущее состояние */\n },\n }))\n\n // Подписываемся на сообщения\n const unsubscribe = channel.subscribe(async (message) => {\n console.log('Получено сообщение:', message)\n })\n\n // Запрашиваем синхронизацию при инициализации\n const init = async () => {\n const syncedState = await channel.requestSync()\n if (syncedState) {\n // Обновляем локальное состояние\n console.log('Получено синхронизированное состояние:', syncedState)\n }\n }\n\n // Отправляем сообщение об обновлении\n channel.broadcast('STATE_UPDATED', {\n data: {\n /* обновленное состояние */\n },\n })\n\n // Очистка при размонтировании\n const cleanup = () => {\n unsubscribe()\n channel.close()\n }\n}\n","import { StorageEvents, StorageType } from '../storage.interface'\nimport { SyncBroadcastChannel } from '../utils/broadcast.util'\nimport { Middleware, MiddlewareAPI, NextFunction, StorageAction } from '../utils/middleware-module'\n\ninterface SharedStateMiddlewareProps {\n storageType: StorageType\n storageName: string\n}\n\nexport const broadcastMiddleware = (props: SharedStateMiddlewareProps): Middleware => {\n const { storageName, storageType } = props\n const channelName = `${storageType}-${storageName}`\n const channel = new SyncBroadcastChannel<StorageAction>(channelName, { debug: true })\n\n return {\n name: 'sync',\n setup: (api: MiddlewareAPI) => {\n if (storageType === 'memory') {\n channel.setSyncHandler(async () => {\n const state = await api.getState()\n\n const updates = Object.entries(state).map(([key, value]) => ({\n key,\n value,\n }))\n\n const action: StorageAction = {\n type: 'update',\n key: '*',\n value: updates,\n metadata: {\n batchUpdate: true,\n timestamp: Date.now(),\n },\n }\n return action\n })\n\n // Запрашиваем начальную синхронизацию\n channel.requestSync().then(async (action) => {\n if (action?.type === 'update' && Array.isArray(action.value)) {\n try {\n // Проверяем структуру обновлений\n const validUpdates = action.value.every((update) => update && typeof update === 'object' && 'key' in update && 'value' in update)\n\n if (!validUpdates) {\n console.error('[Sync Response] Invalid updates structure:', action.value)\n return\n }\n\n await api.storage.doUpdate(action.value)\n\n // Уведомляем подписчиков о каждом обновленном значении\n action.value.forEach(({ key, value }) => {\n api.storage.notifySubscribers(key, value)\n })\n\n // Уведомляем глобальных подписчиков\n api.storage.notifySubscribers('*', {\n type: StorageEvents.STORAGE_UPDATE,\n value: action.value,\n source: 'broadcast',\n })\n } catch (error) {\n console.error('[Sync Response] Error applying updates:', error)\n }\n }\n })\n }\n\n return channel.subscribe(async (message) => {\n const { type, payload } = message\n\n if (storageType === 'memory') {\n switch (type) {\n case 'set':\n // @ts-ignore\n await api.storage.doSet(payload.key, payload.value)\n // @ts-ignore\n api.storage.notifySubscribers(payload.key, payload.value)\n break\n\n case 'update':\n // @ts-ignore\n if (Array.isArray(payload.value)) {\n // @ts-ignore\n await api.storage.doUpdate(payload.value)\n // @ts-ignore\n payload.value.forEach(({ key, value }) => {\n api.storage.notifySubscribers(key, value)\n })\n //FIXME: Еще нужно настроить корректное уведомление глобальных подписчиков\n // Чтобы передавался масив ключей которые были изменены\n }\n break\n\n case 'delete':\n // @ts-ignore\n await api.storage.doDelete(payload.key)\n // @ts-ignore\n api.storage.notifySubscribers(payload.key, undefined)\n break\n\n case 'clear':\n await api.storage.doClear()\n api.storage.notifySubscribers('*', {\n type: StorageEvents.STORAGE_UPDATE,\n value: {},\n source: 'broadcast',\n })\n break\n }\n\n api.storage.notifySubscribers('*', {\n type: StorageEvents.STORAGE_UPDATE,\n key: payload?.key,\n value: payload?.value,\n source: 'broadcast',\n })\n }\n })\n },\n\n reducer: (api: MiddlewareAPI) => (next: NextFunction) => async (action: StorageAction) => {\n const result = await next(action)\n\n if (['set', 'delete', 'clear', 'update'].includes(action.type)) {\n channel.broadcast(action.type, action)\n }\n\n return result\n },\n\n cleanup: () => {\n channel.close()\n },\n }\n}\n","export class StorageKey {\n constructor(\n private readonly value: string,\n private readonly isRawKey: boolean = false,\n ) {}\n\n toString(): string {\n return this.value\n }\n\n toJSON(): string {\n return this.value\n }\n\n valueOf(): string {\n return this.value\n }\n\n isUnparseable(): boolean {\n return this.isRawKey\n }\n}\n\n// Тип, который может быть либо строкой, либо StorageKey\nexport type StorageKeyType = string | StorageKey\n","import { StorageAction } from './middleware-module'\nimport { StorageKeyType } from './storage-key'\n\nexport interface BatchOptions<T> {\n batchSize?: number\n batchDelay?: number\n onBatch?: (items: T[]) => Promise<void>\n // Ключ для группировки элементов в разные очереди\n getSegmentKey?: (item: T) => StorageKeyType\n // Функция для определения можно ли элемент батчить\n shouldBatch?: (item: T) => boolean\n // Функция для объединения элементов с одинаковым ключом\n mergeItems?: (items: T[]) => T[]\n}\n\nexport interface BatchQueueItem<T extends StorageAction> {\n action: T\n baseOperation: () => Promise<any>\n resolve: (value: any) => void\n reject: (error: any) => void\n}\n\nexport class BatchProcessor<T extends StorageAction> {\n private readonly options: Required<BatchOptions<T>>\n\n private queues = new Map<StorageKeyType, BatchQueueItem<T>[]>()\n\n private timeouts = new Map<StorageKeyType, NodeJS.Timeout>()\n\n constructor(options: BatchOptions<T>) {\n this.options = {\n batchSize: options.batchSize ?? 10,\n batchDelay: options.batchDelay ?? 300,\n onBatch: options.onBatch ?? (async () => {}),\n getSegmentKey: options.getSegmentKey ?? (() => 'default'),\n shouldBatch: options.shouldBatch ?? (() => true),\n mergeItems: options.mergeItems ?? ((items) => items),\n }\n }\n\n public async add(action: T, baseOperation: () => Promise<any>): Promise<any> {\n if (!this.options.shouldBatch(action)) {\n return baseOperation()\n }\n\n return new Promise((resolve, reject) => {\n const segment = this.options.getSegmentKey(action)\n this.addToQueue(segment, { action, baseOperation, resolve, reject })\n })\n }\n\n private addToQueue(segment: StorageKeyType, queueItem: BatchQueueItem<T>): void {\n let queue = this.queues.get(segment)\n if (!queue) {\n queue = []\n this.queues.set(segment, queue)\n }\n\n queue.push(queueItem)\n this.clearSegmentTimeout(segment)\n\n if (queue.length >= this.options.batchSize) {\n this.processBatch(segment)\n } else {\n this.setSegmentTimeout(segment)\n }\n }\n\n private async processBatch(segment: StorageKeyType): Promise<void> {\n const queue = this.queues.get(segment)\n if (!queue?.length) return\n\n this.queues.delete(segment)\n this.clearSegmentTimeout(segment)\n\n try {\n // Объединяем похожие действия\n const mergedActions = this.options.mergeItems(queue.map((item) => item.action))\n\n // Выполняем операции последовательно\n for (let i = 0; i < mergedActions.length; i++) {\n const result = await queue[i].baseOperation()\n queue[i].resolve(result)\n }\n } catch (error) {\n queue.forEach(({ reject }) => reject(error))\n }\n }\n\n private clearSegmentTimeout(segment: StorageKeyType): void {\n const timeout = this.timeouts.get(segment)\n if (timeout) {\n clearTimeout(timeout)\n this.timeouts.delete(segment)\n }\n }\n\n private setSegmentTimeout(segment: StorageKeyType): void {\n const timeout = setTimeout(() => {\n this.processBatch(segment)\n }, this.options.batchDelay)\n\n this.timeouts.set(segment, timeout)\n }\n\n public async flush(): Promise<void> {\n const segments = Array.from(this.queues.keys())\n await Promise.all(segments.map((segment) => this.processBatch(segment)))\n }\n\n public clear(): void {\n this.queues.clear()\n Array.from(this.timeouts.values()).forEach(clearTimeout)\n this.timeouts.clear()\n }\n\n public getState(): { [segment: string]: number } {\n const state: { [segment: string]: number } = {}\n this.queues.forEach((queue, segment) => {\n state[segment as string] = queue.length\n })\n return state\n }\n}\n","import { BatchProcessor } from '../utils/batch.utils'\nimport { Middleware, MiddlewareAPI, NextFunction, StorageAction } from '../utils/middleware-module'\n\nexport interface BatchingMiddlewareOptions {\n batchSize?: number\n batchDelay?: number\n}\n\nexport const batchingMiddleware = (options: BatchingMiddlewareOptions = {}): Middleware => {\n const batchProcessor = new BatchProcessor<StorageAction>({\n batchSize: options.batchSize,\n batchDelay: options.batchDelay,\n shouldBatch: (action) => {\n if (action.type === 'get' || action.type === 'keys') return false\n return true\n },\n getSegmentKey: (action) => action.key || 'default',\n mergeItems: (actions) => {\n return actions.reduce((acc, action) => {\n if (action.type === 'set') {\n const existingIndex = acc.findIndex((existing) => existing.type === 'set' && existing.key === action.key)\n if (existingIndex !== -1) {\n acc[existingIndex] = action\n } else {\n acc.push(action)\n }\n } else {\n acc.push(action)\n }\n return acc\n }, [] as StorageAction[])\n },\n })\n\n return {\n name: 'batching',\n setup: () => {},\n reducer: (api: MiddlewareAPI) => (next: NextFunction) => (action: StorageAction) => batchProcessor.add(action, () => next(action)),\n }\n}\n","import { Middleware, MiddlewareAPI, NextFunction, StorageAction } from '../utils/middleware-module'\nimport { StorageKey } from '../utils/storage-key'\n\nexport interface ShallowCompareMiddlewareOptions {\n segments?: string[]\n comparator?: <T>(prev: T, next: T) => boolean\n}\n\nexport const shallowCompareMiddleware = (options: ShallowCompareMiddlewareOptions = {}): Middleware => {\n const {\n comparator = (prev: any, next: any) => {\n if (prev === next) return true\n\n if (typeof prev !== 'object' || typeof next !== 'object' || prev === null || next === null) {\n return prev === next\n }\n\n const keysA = Object.keys(prev)\n const keysB = Object.keys(next)\n\n if (keysA.length !== keysB.length) return false\n\n return keysA.every((key) => Object.prototype.hasOwnProperty.call(next, key) && prev[key] === next[key])\n },\n segments = [],\n } = options\n\n // Кэш последних значений\n const valueCache = new Map<string | StorageKey, any>()\n\n return {\n name: 'shallow-compare',\n setup: (api: MiddlewareAPI) => {},\n reducer: (api: MiddlewareAPI) => (next: NextFunction) => async (action: StorageAction) => {\n // Пропускаем действия кроме set\n if (action.type !== 'set' || (segments.length && !segments.includes(action.metadata?.segment ?? 'default'))) {\n return next(action)\n }\n\n const cacheKey = action.key!\n const prevValue = valueCache.get(cacheKey)\n const nextValue = action.value\n\n // Если значения равны, пропускаем операцию\n if (prevValue !== undefined && comparator(prevValue, nextValue)) {\n console.log('ShallowCompare: значения идентичны, пропускаем операцию', { key: cacheKey, value: nextValue })\n\n // Добавляем специальный флаг в метаданные, чтобы BaseStorage знал, что значение не изменилось\n return {\n ...prevValue,\n __metadata: {\n valueNotChanged: true, // Этот флаг будет проверяться в BaseStorage перед notifySubscribers\n originalValue: prevValue,\n },\n }\n }\n\n // Иначе обновляем кэш и продолжаем\n const result = await next(action)\n valueCache.set(cacheKey, nextValue)\n return result\n },\n }\n}\n","import { StorageKeyType } from './storage-key'\n\nexport type StorageActionType = 'get' | 'set' | 'delete' | 'clear' | 'init' | 'keys' | 'update'\n\nexport type StorageAction = {\n type: StorageActionType\n key?: StorageKeyType\n value?: any\n metadata?: Record<string, any>\n source?: string\n timestamp?: number\n}\n\nexport type MiddlewareAPI = {\n dispatch: (action: StorageAction) => Promise<any>\n getState: () => Promise<Record<string, any>>\n storage: {\n doGet: (key: StorageKeyType) => Promise<any>\n doSet: (key: StorageKeyType, value: any) => Promise<void>\n doUpdate: (updates: Array<{ key: StorageKeyType; value: any }>) => Promise<void>\n doDelete: (key: StorageKeyType) => Promise<boolean>\n doClear: () => Promise<void>\n doKeys: () => Promise<string[]>\n notifySubscribers: (key: StorageKeyType, value: any) => void\n }\n}\n\nexport type NextFunction = (action: StorageAction) => Promise<any>\n\nexport type SetupEventsFunction = (api: MiddlewareAPI) => void\n\nexport type Middleware = {\n name: string\n setup?: SetupEventsFunction\n cleanup?: () => Promise<void> | void\n reducer: (api: MiddlewareAPI) => (next: NextFunction) => (action: StorageAction) => Promise<any>\n}\n\nexport class MiddlewareModule {\n private middlewares: Middleware[] = []\n\n private api: MiddlewareAPI\n\n private initialized = false\n\n private dispatchFn!: (action: StorageAction) => Promise<any>\n\n constructor(storage: any) {\n this.api = {\n dispatch: async (action: StorageAction) => this.dispatch(action),\n getState: () => storage.getState(),\n storage: {\n doGet: storage.doGet.bind(storage),\n doSet: storage.doSet.bind(storage),\n doUpdate: storage.doUpdate.bind(storage),\n doDelete: storage.doDelete.bind(storage),\n doClear: storage.doClear.bind(storage),\n doKeys: storage.doKeys.bind(storage),\n notifySubscribers: storage.notifySubscribers.bind(storage),\n },\n }\n }\n\n private async baseOperation(action: StorageAction): Promise<any> {\n // Деструктурируем с подчеркиванием для неиспользуемых переменных\n const { processed: _, ...metadata } = action.metadata || {}\n const cleanAction = { ...action, metadata }\n\n switch (cleanAction.type) {\n case 'get': {\n return this.api.storage.doGet(cleanAction.key!)\n }\n\n case 'set': {\n await this.api.storage.doSet(cleanAction.key!, cleanAction.value)\n return this.api.storage.doGet(cleanAction.key!)\n }\n\n case 'update': {\n if (Array.isArray(cleanAction.value)) {\n await this.api.storage.doUpdate(cleanAction.value)\n return this.api.storage.doGet('')\n }\n return cleanAction.value\n }\n\n case 'delete': {\n return this.api.storage.doDelete(cleanAction.key!)\n }\n\n case 'clear': {\n return this.api.storage.doClear()\n }\n\n case 'init': {\n const currentState = await this.api.storage.doGet('')\n if (Object.keys(currentState || {}).length > 0) {\n return currentState\n }\n if (cleanAction.value) {\n await this.api.storage.doSet('', cleanAction.value)\n return this.api.storage.doGet('')\n }\n return currentState\n }\n\n case 'keys': {\n return this.api.storage.doKeys()\n }\n\n default: {\n throw new Error(`Unknown action type: ${cleanAction.type}`)\n }\n }\n }\n\n private initializeMiddlewares() {\n if (this.initialized) return\n\n let chain = this.baseOperation.bind(this)\n\n for (const middleware of [...this.middlewares].reverse()) {\n const nextChain = chain\n chain = async (action) => {\n if (action.metadata?.processed) {\n return nextChain(action)\n }\n\n const actionWithMeta = {\n ...action,\n metadata: {\n ...action.metadata,\n processed: true,\n timestamp: action.metadata?.timestamp || Date.now(),\n },\n }\n\n return middleware.reducer(this.api)(nextChain)(actionWithMeta)\n }\n }\n\n this.dispatchFn = chain // Используем новое имя\n this.initialized = true\n }\n\n use(middleware: Middleware): void {\n if (middleware.setup) {\n middleware.setup(this.api)\n }\n\n this.middlewares.push(middleware)\n this.initialized = false\n }\n\n async dispatch(action: StorageAction): Promise<any> {\n if (!this.initialized) {\n this.initializeMiddlewares()\n }\n\n try {\n return this.dispatchFn(action)\n } catch (error) {\n console.error('Error in middleware chain:', error)\n throw error\n }\n }\n}\n","import { StorageKey } from '../utils/storage-key'\n\nexport function parsePath(path: string | StorageKey): string[] {\n // Если это StorageKey и он помечен как непарсируемый\n if (path instanceof StorageKey && path.isUnparseable()) {\n return [path.toString()]\n }\n\n const pathStr = path.toString()\n return pathStr.replace(/\\[/g, '.').replace(/\\]/g, '').split('.').filter(Boolean)\n}\n\nexport function getValueByPath(obj: any, path: string | StorageKey) {\n const parts = parsePath(path)\n return parts.reduce((curr, key) => (curr === undefined ? undefined : curr[key]), obj)\n}\n\nexport function setValueByPath(obj: any, path: string | StorageKey, value: any): any {\n if (path === '') return value\n\n const parts = parsePath(path)\n\n // Если путь - это StorageKey и он непарсируемый, используем его как есть\n if (path instanceof StorageKey && path.isUnparseable()) {\n obj[path.toString()] = value\n return obj\n }\n\n const lastKey = parts.pop()!\n const target = parts.reduce((curr, key) => {\n const nextKey = parts[parts.indexOf(key) + 1]\n const shouldBeArray = !Number.isNaN(Number(nextKey))\n\n if (!(key in curr)) {\n curr[key] = shouldBeArray ? [] : {}\n }\n return curr[key]\n }, obj)\n\n target[lastKey] = value\n return obj\n}\n","import { batchingMiddleware } from '../middlewares/storage-batching.middleware'\nimport { shallowCompareMiddleware } from '../middlewares/storage-shallow-compare.middleware'\nimport { IPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { DefaultMiddlewares, IEventEmitter, ILogger, IStorage, StorageConfig, StorageEvent, StorageEvents } from '../storage.interface'\nimport { Middleware, MiddlewareModule } from '../utils/middleware-module'\nimport { StorageKeyType } from '../utils/storage-key'\nimport { getValueByPath } from './path.utils'\n\ntype PathSelector<T, R> = (state: T) => R\n\nexport abstract class BaseStorage<T extends Record<string, any>> implements IStorage<T> {\n // Константа для глобальной подписки\n protected static readonly GLOBAL_SUBSCRIPTION_KEY = '*'\n\n name: string\n\n private selectorPathCache = new WeakMap<PathSelector<any, any>, string>()\n\n private middlewareModule: MiddlewareModule\n\n private initializedMiddlewares: Middleware[] | null = null\n\n protected subscribers = new Map<StorageKeyType, Set<(value: any) => void>>()\n\n constructor(\n protected readonly config: StorageConfig,\n protected readonly pluginExecutor?: IPluginExecutor,\n protected readonly eventEmitter?: IEventEmitter,\n protected readonly logger?: ILogger,\n ) {\n this.name = config.name\n this.middlewareModule = new MiddlewareModule({\n getState: this.getState.bind(this),\n // Предоставляем базовые операции хранилища\n doGet: this.doGet.bind(this),\n doSet: this.doSet.bind(this),\n doUpdate: this.doUpdate.bind(this),\n doDelete: this.doDelete.bind(this),\n doClear: this.doClear.bind(this),\n doKeys: this.doKeys.bind(this),\n // Предоставляем методы для работы с подписчиками\n notifySubscribers: this.notifySubscribers.bind(this),\n // Предоставляем плагины и эмиттер\n pluginExecutor: this.pluginExecutor,\n eventEmitter: this.eventEmitter,\n logger: this.logger,\n })\n\n this.initializeMiddlewares()\n }\n\n protected initializeMiddlewares(): void {\n if (this.config.middlewares && !this.initializedMiddlewares) {\n // Создаем middleware только один раз\n this.initializedMiddlewares = this.config.middlewares(() => this.getDefaultMiddleware())\n\n // Применяем их\n this.initializedMiddlewares.forEach((middleware) => this.middlewareModule.use(middleware))\n }\n }\n\n protected getDefaultMiddleware(): DefaultMiddlewares {\n return {\n batching: (options = {}) => batchingMiddleware(options),\n shallowCompare: (options = {}) => shallowCompareMiddleware(options),\n }\n }\n\n protected async initializeWithMiddlewares(): Promise<void> {\n try {\n const state = await this.getState()\n const hasExistingState = Object.keys(state).length > 0\n\n if (!hasExistingState && this.config.initialState) {\n // Только если нет существующих данных и есть initialState,\n // делаем dispatch для установки начального состояния\n await this.middlewareModule.dispatch({\n type: 'init',\n value: this.config.initialState,\n })\n }\n } catch (error) {\n this.logger?.error('Ошибка инициализации хранилища', { error })\n throw error\n }\n }\n\n public abstract initialize(): Promise<this>\n\n protected abstract doGet(key: StorageKeyType): Promise<any>\n\n protected abstract doSet(key: StorageKeyType, value: any): Promise<void>\n\n protected abstract doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): Promise<void>\n\n protected abstract doDelete(key: StorageKeyType): Promise<boolean>\n\n protected abstract doClear(): Promise<void>\n\n protected abstract doKeys(): Promise<string[]>\n\n protected abstract doHas(key: StorageKeyType): Promise<boolean>\n\n protected abstract doDestroy(): Promise<void>\n\n public async get<R>(key: StorageKeyType): Promise<R | undefined> {\n try {\n const metadata = { operation: 'get', timestamp: Date.now(), key }\n\n // Передаем в middleware chain\n const middlewareResult = await this.middlewareModule.dispatch({\n type: 'get',\n key,\n metadata,\n })\n\n // Обрабатываем значение через плагины\n const finalResult = (await this.pluginExecutor?.executeAfterGet(key, middlewareResult, metadata)) ?? middlewareResult\n\n await this.emitEvent({\n type: StorageEvents.STORAGE_SELECT,\n payload: { key, value: finalResult },\n })\n\n return finalResult\n } catch (error) {\n this.logger?.error('Error getting value', { key, error })\n throw error\n }\n }\n\n public async set<R>(key: StorageKeyType, value: R): Promise<void> {\n try {\n const metadata = { operation: 'set', timestamp: Date.now(), key }\n\n // Обрабатываем значение через плагины\n const processedValue = (await this.pluginExecutor?.executeBeforeSet(value, metadata)) ?? value\n\n // Передаем в middleware chain\n const middlewareResult = await this.middlewareModule.dispatch({\n type: 'set',\n key,\n value: processedValue,\n metadata,\n })\n\n // Проверяем метаданные, добавленные shallowCompare middleware\n const valueNotChanged = middlewareResult?.__metadata?.valueNotChanged === true\n // Финальная обработка значения, передаем оригинальный ключ\n let finalResult\n\n if (valueNotChanged && middlewareResult?.__metadata?.originalValue !== undefined) {\n // Если значение не изменилось, используем оригинальное значение без метаданных\n finalResult = middlewareResult.__metadata.originalValue\n } else {\n finalResult = (await this.pluginExecutor?.executeAfterSet(key, middlewareResult, metadata)) ?? middlewareResult\n }\n\n // Уведомляем подписчиков только если значение изменилось\n if (!valueNotChanged) {\n // Просто берем путь из первого параметра\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n // Уведомляем подписчиков конкретного ключа\n this.notifySubscribers(key, finalResult)\n\n // Уведомляем глобальных подписчиков с информацией о пути\n this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: finalResult,\n changedPaths,\n })\n\n await this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: {\n key,\n value: finalResult,\n changedPaths,\n },\n })\n }\n } catch (error) {\n this.logger?.error('Error setting value', { key, error })\n throw error\n }\n }\n\n public async update(updater: (state: T) => void): Promise<void> {\n try {\n const metadata = { operation: 'update', timestamp: Date.now() }\n\n // Получаем текущее состояние\n const currentState = (await this.getState()) as T\n\n // Используем structuredClone для создания глубокой копии\n const newState = structuredClone(currentState) as T\n\n // Применяем обновление\n updater(newState)\n\n // Находим все изменившиеся пути\n const changedPaths = this.findChangedPaths(currentState, newState)\n\n // Если нет изменений, завершаем метод\n if (changedPaths.size === 0) {\n if (this.logger?.debug) {\n this.logger.debug('No changes detected in update')\n }\n return\n }\n\n if (this.logger?.debug) {\n this.logger.debug('Changed paths:', { paths: Array.from(changedPaths) })\n }\n\n // Определяем изменившиеся верхнеуровневые ключи для middleware\n const changedTopLevelKeys = new Set<string>()\n for (const path of changedPaths) {\n const topLevelKey = path.split('.')[0]\n changedTopLevelKeys.add(topLevelKey)\n }\n\n // Подготавливаем обновления для middleware (только верхнеуровневые ключи)\n const updates = await Promise.all(\n Array.from(changedTopLevelKeys).map(async (key: string) => {\n const keyMetadata = { ...metadata, key }\n\n // Обрабатываем значение через плагины\n const processedValue = (await this.pluginExecutor?.executeBeforeSet(newState[key], keyMetadata)) ?? newState[key]\n return { key, value: processedValue }\n }),\n )\n\n // Делаем dispatch для batch-обновления\n const result = await this.middlewareModule.dispatch({\n type: 'update',\n value: updates,\n metadata: {\n ...metadata,\n batchUpdate: true,\n changedPaths: Array.from(changedPaths),\n },\n })\n\n // Преобразуем результат в объект\n let updatedValues: Record<string, any> = {}\n\n if (Array.isArray(result)) {\n result.forEach((update) => {\n if (update && typeof update === 'object' && 'key' in update && 'value' in update) {\n updatedValues[update.key as string] = update.value\n }\n })\n } else if (result && typeof result === 'object') {\n updatedValues = { ...result }\n }\n\n // Определяем действительно измененные ключи после middleware\n const actuallyChangedKeys = Object.keys(updatedValues).filter((key) => !this.isEqual(currentState[key], updatedValues[key]))\n\n if (actuallyChangedKeys.length === 0) {\n if (this.logger?.debug) {\n this.logger.debug('No actual changes after middleware processing')\n }\n return\n }\n\n // Создаем объект с измененными значениями\n const finalUpdates: Record<string, any> = {}\n actuallyChangedKeys.forEach((key) => {\n finalUpdates[key] = updatedValues[key]\n })\n\n if (this.logger?.debug) {\n this.logger.debug('Notifying subscribers about changes:', { keys: actuallyChangedKeys })\n }\n\n // Уведомляем о глобальном обновлении\n this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key: actuallyChangedKeys,\n value: finalUpdates,\n changedPaths: Array.from(changedPaths), // Добавляем информацию о всех изменившихся путях\n })\n\n // Уведомляем подписчиков на ТОЧНЫЕ ИЗМЕНИВШИЕСЯ ПУТИ\n // Важное отличие от предыдущей реализации - уведомляем только о тех путях, которые\n // действительно изменились, а не обо всех вложенных объектах\n for (const path of changedPaths) {\n try {\n // Находим верхнеуровневый ключ\n const topLevelKey = path.split('.')[0]\n\n // Если верхнеуровневый ключ был изменен, используем его обновленное значение\n if (topLevelKey in finalUpdates) {\n let value\n\n if (path === topLevelKey) {\n // Если это верхнеуровневый ключ, используем его напрямую\n value = finalUpdates[topLevelKey]\n } else {\n // Иначе получаем значение по вложенному пути\n const restPath = path.substring(topLevelKey.length + 1)\n value = getValueByPath(finalUpdates[topLevelKey], restPath)\n }\n\n // Уведомляем подписчиков для этого конкретного пути\n if (value !== undefined) {\n this.notifySubscribers(path, value)\n }\n }\n } catch (error) {\n this.logger?.error('Error notifying path subscribers', { path, error })\n }\n }\n\n // Отправляем событие\n await this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: {\n state: finalUpdates,\n key: actuallyChangedKeys,\n changedPaths: Array.from(changedPaths),\n },\n })\n } catch (error) {\n this.logger?.error('Error updating state', { error })\n throw error\n }\n }\n\n public async delete(key: StorageKeyType): Promise<void> {\n try {\n const metadata = { operation: 'delete', timestamp: Date.now(), key }\n\n // Проверяем возможность удаления\n if (await this.pluginExecutor?.executeBeforeDelete(key, metadata)) {\n const middlewareResult = await this.middlewareModule.dispatch({\n type: 'delete',\n key,\n metadata,\n })\n\n // Выполняем afterDelete с оригинальным ключом\n await this.pluginExecutor?.executeAfterDelete(key, metadata)\n\n // Определяем путь изменения (по аналогии с set)\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n // Уведомляем подписчиков используя оригинальный ключ\n this.notifySubscribers(key, undefined)\n this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: undefined,\n result: middlewareResult,\n changedPaths,\n })\n\n await this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: {\n key,\n value: undefined,\n result: middlewareResult,\n changedPaths,\n },\n })\n }\n } catch (error) {\n this.logger?.error('Error deleting value', { key, error })\n throw error\n }\n }\n\n public async clear(): Promise<void> {\n try {\n this.pluginExecutor?.executeOnClear()\n\n await this.middlewareModule.dispatch({\n type: 'clear',\n })\n } catch (error) {\n this.logger?.error('Error clearing storage', { error })\n throw error\n }\n }\n\n public async keys(): Promise<string[]> {\n try {\n return await this.middlewareModule.dispatch({\n type: 'keys',\n })\n } catch (error) {\n this.logger?.error('Error getting keys', { error })\n throw error\n }\n }\n\n public async has(key: StorageKeyType): Promise<boolean> {\n try {\n return await this.doHas(key)\n } catch (error) {\n this.logger?.error('Error checking value existence', { key, error })\n throw error\n }\n }\n\n public async getState(): Promise<T> {\n try {\n const value = await this.doGet('')\n return value || {}\n } catch (error) {\n this.logger?.error('Error getting state', { error })\n throw error\n }\n }\n\n // Вспомогательный метод для подписки на все изменения\n public subscribeToAll(callback: (event: { type: string; key?: StorageKeyType[] | StorageKeyType; value?: any; changedPaths?: string[] }) => void): VoidFunction {\n // Подписываемся на глобальный ключ, который получает уведомления обо всех изменениях\n if (!this.subscribers.has(BaseStorage.GLOBAL_SUBSCRIPTION_KEY)) {\n this.subscribers.set(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, new Set())\n }\n\n // Добавляем колбэк в набор подписчиков для глобального ключа\n this.subscribers.get(BaseStorage.GLOBAL_SUBSCRIPTION_KEY)!.add(callback)\n\n // Возвращаем функцию отписки\n return () => {\n const subscribers = this.subscribers.get(BaseStorage.GLOBAL_SUBSCRIPTION_KEY)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(BaseStorage.GLOBAL_SUBSCRIPTION_KEY)\n }\n }\n }\n }\n\n public subscribe(key: string, callback: (value: any) => void): VoidFunction\n\n public subscribe<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction\n\n public subscribe<R>(keyOrSelector: string | PathSelector<T, R>, callback: (value: any) => void): VoidFunction {\n if (typeof keyOrSelector === 'string') {\n // Существующая логика для строкового ключа\n return this.subscribeByKey(keyOrSelector, callback)\n }\n // Новая логика для селектора пути\n return this.subscribeBySelector(keyOrSelector, callback)\n }\n\n public async destroy(): Promise<void> {\n try {\n await this.clear()\n await this.doDestroy()\n\n // Очищаем middleware и соединения\n if (this.initializedMiddlewares) {\n // Если у middleware есть метод cleanup/destroy - вызываем его\n await Promise.all(\n this.initializedMiddlewares.map(async (middleware) => {\n if ('cleanup' in middleware) {\n await middleware.cleanup?.()\n }\n }),\n )\n this.initializedMiddlewares = null\n }\n\n await this.emitEvent({\n type: StorageEvents.STORAGE_DESTROY,\n })\n } catch (error) {\n this.logger?.error('Error destroying storage', { error })\n throw error\n }\n }\n\n // Вспомогательные методы\n\n private subscribeByKey(key: string, callback: (value: any) => void): VoidFunction {\n // Создаем коллекцию подписчиков, если ее еще нет\n if (!this.subscribers.has(key)) {\n this.subscribers.set(key, new Set())\n }\n\n // Флаг для отслеживания отправки начального значения\n let initialValueSent = false\n\n // Добавляем колбэк в набор подписчиков\n this.subscribers.get(key)!.add(callback)\n\n // Получаем и отправляем начальное значение, но только один раз\n this.get(key).then((value) => {\n try {\n if (!initialValueSent) {\n initialValueSent = true\n callback(value)\n }\n } catch (error) {\n this.logger?.error('Error in initial callback', { key, error })\n }\n })\n\n // Возвращаем функцию отписки\n return () => {\n const subscribers = this.subscribers.get(key)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(key)\n }\n }\n }\n }\n\n private createDummyState(): T {\n const handler = {\n get: (target: any, prop: string) => {\n target[prop] = target[prop] || new Proxy({}, handler)\n return target[prop]\n },\n }\n return new Proxy({} as T, handler)\n }\n\n private isEqual(a: any, b: any): boolean {\n // Если ссылки одинаковые, объекты равны\n if (a === b) return true\n\n // Если хотя бы один из объектов null/undefined, они равны только если оба null/undefined\n if (a == null || b == null) return a === b\n\n // Если типы различаются, объекты не равны\n const typeA = typeof a\n const typeB = typeof b\n if (typeA !== typeB) return false\n\n // Обработка примитивных типов\n if (typeA !== 'object') return a === b\n\n // Обработка различных типов объектов\n\n // Обработка Date объектов\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime()\n }\n\n // Обработка массивов\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n\n for (let i = 0; i < a.length; i++) {\n if (!this.isEqual(a[i], b[i])) return false\n }\n\n return true\n }\n\n // Обработка обычных объектов\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n\n if (keysA.length !== keysB.length) return false\n\n return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && this.isEqual(a[key], b[key]))\n }\n\n /**\n * Возвращает полный путь, а не только корневой ключ\n */\n private extractPath(selector: (state: T) => any, dummyState: T): string {\n // Проверяем кэш\n if (this.selectorPathCache.has(selector)) {\n return this.selectorPathCache.get(selector)!\n }\n\n const accessedPaths: string[] = []\n\n // Создаем прокси с рекурсивным обработчиком для отслеживания доступа к свойствам\n const createProxyHandler = (path = ''): ProxyHandler<any> => ({\n get: (target: any, prop: string) => {\n // Игнорируем служебные свойства Symbol\n if (typeof prop === 'symbol') {\n return Reflect.get(target, prop)\n }\n\n // Формируем текущий путь\n const currentPath = path ? `${path}.${prop}` : prop\n\n // Сохраняем путь в список\n accessedPaths.push(currentPath)\n\n // Возвращаем новый прокси для вложенного свойства\n return new Proxy({}, createProxyHandler(currentPath))\n },\n\n // Обработка опциональной цепочки (?.)\n has: (target: any, prop: string) => {\n // Симулируем, что свойство существует для работы опциональной цепочки\n return true\n },\n\n // Поддержка для Array.prototype.map и других операций над массивами\n ownKeys: () => [],\n getOwnPropertyDescriptor: () => ({\n configurable: true,\n enumerable: true,\n }),\n\n apply: (target: any, thisArg: any, args: any[]) => {\n // Обработка вызова функций (например, массивы могут иметь методы)\n return new Proxy(() => {}, createProxyHandler(path))\n },\n })\n\n try {\n // Применяем селектор к прокси для отслеживания пути\n selector(new Proxy(dummyState, createProxyHandler()))\n } catch (error) {\n // Игнорируем ошибки - они могут возникать из-за доступа к несуществующим свойствам\n }\n\n // Если нет доступа к путям, возвращаем пустую строку\n if (accessedPaths.length === 0) return ''\n\n // Сортируем пути по длине (самый длинный первым), так мы получим самый специфичный путь\n accessedPaths.sort((a, b) => b.length - a.length)\n\n // Возвращаем наиболее специфичный путь (самый длинный)\n this.selectorPathCache.set(selector, accessedPaths[0])\n return accessedPaths[0]\n }\n\n protected notifySubscribers(key: StorageKeyType, value: any): void {\n const keyStr = key.toString()\n\n // 1. Точное соответствие - уведомляем подписчиков для этого конкретного ключа\n const exactSubscribers = this.subscribers.get(keyStr)\n if (exactSubscribers?.size) {\n // Создаем безопасную копию подписчиков для итерации\n const subscribersCopy = new Set(exactSubscribers)\n subscribersCopy.forEach((callback) => {\n try {\n callback(value)\n } catch (error) {\n this.logger?.error('Ошибка в подписчике на колбэк', { key: keyStr, error })\n }\n })\n }\n }\n\n /**\n * Метод для определения изменившихся путей между двумя объектами\n */\n private findChangedPaths(oldObj: any, newObj: any, prefix = '', changedPaths: Set<string> = new Set<string>(), visited = new WeakMap()): Set<string> {\n // Если ссылки идентичны, нет изменений\n if (oldObj === newObj) return changedPaths\n\n // Если один из объектов не является объектом или null, проверяем на изменения\n if (typeof oldObj !== 'object' || typeof newObj !== 'object' || oldObj === null || newObj === null) {\n if (oldObj !== newObj) {\n changedPaths.add(prefix || '')\n }\n return changedPaths\n }\n\n // Проверка на циклические ссылки\n if (visited.has(oldObj)) return changedPaths\n\n visited.set(oldObj, true)\n\n // Собираем все ключи из обоих объектов\n const allKeys = new Set([...Object.keys(oldObj || {}), ...Object.keys(newObj || {})])\n\n // Для каждого ключа проверяем изменения\n for (const key of allKeys) {\n const oldValue = oldObj[key]\n const newValue = newObj[key]\n\n // Если значения идентичны, пропускаем\n if (oldValue === newValue) continue\n\n const path = prefix ? `${prefix}.${key}` : key\n\n // Если оба значения - объекты (но не массивы), рекурсивно проверяем их\n if (oldValue && newValue && typeof oldValue === 'object' && typeof newValue === 'object' && !Array.isArray(oldValue) && !Array.isArray(newValue)) {\n this.findChangedPaths(oldValue, newValue, path, changedPaths, visited)\n }\n // Если оба значения - массивы, используем isEqual для сравнения\n else if (Array.isArray(oldValue) && Array.isArray(newValue)) {\n if (!this.isEqual(oldValue, newValue)) {\n changedPaths.add(path)\n }\n }\n // Для остальных типов данных - просто сравниваем\n else if (!this.isEqual(oldValue, newValue)) {\n changedPaths.add(path)\n }\n }\n\n return changedPaths\n }\n\n private subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction {\n // Получаем полный путь из селектора (не только корневой ключ)\n const dummyState = this.createDummyState()\n const fullPath = this.extractPath(pathSelector, dummyState)\n\n if (this.logger?.debug) {\n this.logger.debug('Subscribing to path:', { path: fullPath })\n }\n\n // Создаем обертку для колбэка, которая применяет оригинальный селектор к текущему состоянию\n const wrappedCallback = async (value: any) => {\n try {\n // Для значений undefined или null, нам нужно получить текущее состояние\n if (value === undefined || value === null) {\n const currentState = (await this.getState()) as T\n const selectedValue = pathSelector(currentState)\n callback(selectedValue as R)\n return\n }\n\n // Если значение не объект или точно соответствует ожидаемому типу,\n // передаем его напрямую\n if (typeof value !== 'object' || value === null) {\n callback(value as R)\n return\n }\n\n // Для объектов запускаем селектор, чтобы получить точное значение\n const currentState = (await this.getState()) as T\n const selectedValue = pathSelector(currentState)\n callback(selectedValue as R)\n } catch (error) {\n this.logger?.error('Error in selector callback', { path: fullPath, error })\n // В случае ошибки передаем исходное значение\n callback(value as R)\n }\n }\n\n // Если путь не удалось извлечь, подписываемся на глобальные изменения\n if (!fullPath) {\n return this.subscribeToAll(() => {\n this.getState().then((state) => {\n callback(pathSelector(state as T))\n })\n })\n }\n\n // Подписываемся на полный путь, а не только на корневой ключ\n return this.subscribeByKey(fullPath, wrappedCallback)\n }\n\n protected async emitEvent(event: StorageEvent): Promise<void> {\n try {\n await this.eventEmitter?.emit({\n ...event,\n metadata: {\n ...(event.metadata || {}),\n timestamp: Date.now(),\n storageName: this.name,\n },\n })\n } catch (error) {\n this.logger?.error('Error emitting event', { event, error })\n }\n }\n}\n","import { IPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { ConfigureMiddlewares, IEventEmitter, ILogger, StorageConfig } from '../storage.interface'\nimport { StorageKey, StorageKeyType } from '../utils/storage-key'\nimport { BaseStorage } from './base-storage.service'\nimport { getValueByPath, parsePath, setValueByPath } from './path.utils'\n\nexport interface IndexedDBConfig {\n dbName?: string\n dbVersion: number\n}\n\n// Управляет соединением с базой данных\nexport class IndexedDBManager {\n private static instances = new Map<string, IndexedDBManager>()\n private db: IDBDatabase | null = null\n private initPromise: Promise<IDBDatabase> | null = null\n private storeNames: Set<string> = new Set()\n private dbVersion: number\n\n private constructor(\n private readonly dbName: string,\n dbVersion: number,\n private readonly logger?: ILogger,\n ) {\n this.dbVersion = dbVersion\n }\n\n static getInstance(dbName: string, dbVersion: number = 1, logger?: ILogger): IndexedDBManager {\n if (!IndexedDBManager.instances.has(dbName)) {\n IndexedDBManager.instances.set(dbName, new IndexedDBManager(dbName, dbVersion, logger))\n }\n\n const instance = IndexedDBManager.instances.get(dbName)!\n\n // Update version if higher version is requested\n if (dbVersion > instance.dbVersion) {\n instance.dbVersion = dbVersion\n }\n\n return instance\n }\n\n async initialize(): Promise<IDBDatabase> {\n if (this.db) {\n return this.db\n }\n\n if (!this.initPromise) {\n this.initPromise = this.openDatabase()\n }\n\n return this.initPromise\n }\n\n async ensureStoreExists(storeName: string): Promise<IDBDatabase> {\n await this.initialize()\n\n if (this.db!.objectStoreNames.contains(storeName)) {\n this.storeNames.add(storeName)\n return this.db!\n }\n\n this.logger?.debug(`Store \"${storeName}\" not found, upgrading database`, {\n dbName: this.dbName,\n currentStores: Array.from(this.db!.objectStoreNames),\n })\n\n this.db!.close()\n this.db = null\n\n this.dbVersion++\n this.initPromise = this.openDatabase([storeName])\n\n const newDb = await this.initPromise\n this.storeNames.add(storeName)\n return newDb\n }\n\n private async openDatabase(newStores: string[] = []): Promise<IDBDatabase> {\n return new Promise<IDBDatabase>((resolve, reject) => {\n this.logger?.debug(`Opening database \"${this.dbName}\" with version ${this.dbVersion}`)\n\n const request = indexedDB.open(this.dbName, this.dbVersion)\n\n request.onerror = () => {\n this.logger?.error(`Failed to open database \"${this.dbName}\"`, { error: request.error })\n reject(request.error)\n }\n\n request.onsuccess = () => {\n this.db = request.result\n\n // Add existing stores to our set\n for (let i = 0; i < this.db.objectStoreNames.length; i++) {\n this.storeNames.add(this.db.objectStoreNames[i])\n }\n\n this.logger?.debug(`Database \"${this.dbName}\" opened successfully`, {\n version: this.db.version,\n stores: Array.from(this.db.objectStoreNames),\n })\n\n resolve(this.db)\n }\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result\n this.logger?.debug(`Upgrading database \"${this.dbName}\" to version ${this.dbVersion}`)\n\n // Create new stores that don't exist yet\n for (const storeName of newStores) {\n if (!db.objectStoreNames.contains(storeName)) {\n this.logger?.debug(`Creating store \"${storeName}\"`)\n db.createObjectStore(storeName)\n }\n }\n }\n })\n }\n\n closeDatabase(): void {\n if (this.db) {\n this.db.close()\n this.db = null\n this.initPromise = null\n }\n }\n\n async deleteDatabase(): Promise<void> {\n this.closeDatabase()\n\n return new Promise<void>((resolve, reject) => {\n const request = indexedDB.deleteDatabase(this.dbName)\n request.onsuccess = () => {\n this.logger?.debug(`Database \"${this.dbName}\" deleted successfully`)\n IndexedDBManager.instances.delete(this.dbName)\n this.storeNames.clear()\n resolve()\n }\n request.onerror = () => {\n this.logger?.error(`Failed to delete database \"${this.dbName}\"`, { error: request.error })\n reject(request.error)\n }\n })\n }\n async ensureStoresExist(storeNames: string[]): Promise<IDBDatabase> {\n // Сначала инициализируем базу\n await this.initialize()\n\n // Проверяем, какие хранилища уже существуют\n const missingStores = storeNames.filter((name) => !this.db!.objectStoreNames.contains(name))\n\n // Если все хранилища уже существуют, просто возвращаем базу\n if (missingStores.length === 0) {\n return this.db!\n }\n\n // Иначе нам нужно обновить базу для создания новых хранилищ\n this.logger?.debug(`Создание недостающих хранилищ: ${missingStores.join(', ')}`, {\n dbName: this.dbName,\n currentStores: Array.from(this.db!.objectStoreNames),\n })\n\n // Закрываем текущее соединение\n this.db!.close()\n this.db = null\n\n // Увеличиваем версию один раз для всех новых хранилищ\n this.dbVersion++\n this.initPromise = this.openDatabase(missingStores)\n\n return this.initPromise\n }\n\n // Метод для получения текущей версии\n getCurrentVersion(): number {\n return this.dbVersion\n }\n}\n\n/**\n * Менеджер для управления версией базы данных IndexedDB\n * и создания хранилищ\n */\nclass DBVersionManager {\n private db: IDBDatabase | null = null\n private version: number\n\n constructor(\n private readonly dbName: string,\n initialVersion: number = 1,\n private readonly logger?: ILogger,\n ) {\n this.version = initialVersion\n }\n\n /**\n * Получает текущую версию базы данных\n */\n getCurrentVersion(): number {\n return this.version\n }\n\n /**\n * Открывает базу данных с заданной версией\n */\n private openDatabase(version: number, newStores: string[] = []): Promise<IDBDatabase> {\n return new Promise<IDBDatabase>((resolve, reject) => {\n this.logger?.debug(`Открытие базы данных \"${this.dbName}\" с версией ${version}`)\n\n const request = indexedDB.open(this.dbName, version)\n\n request.onerror = () => {\n this.logger?.error(`Ошибка при открытии базы данных \"${this.dbName}\"`, { error: request.error })\n reject(request.error)\n }\n\n request.onsuccess = () => {\n this.db = request.result\n this.version = this.db.version\n\n this.logger?.debug(`База данных \"${this.dbName}\" успешно открыта`, {\n version: this.db.version,\n stores: Array.from(this.db.objectStoreNames),\n })\n\n resolve(this.db)\n }\n\n request.onupgradeneeded = (event) => {\n const db = (event.target as IDBOpenDBRequest).result\n this.logger?.debug(`Обновление базы данных \"${this.dbName}\" до версии ${version}`)\n\n // Создаем все новые хранилища\n for (const storeName of newStores) {\n if (!db.objectStoreNames.contains(storeName)) {\n this.logger?.debug(`Создание хранилища \"${storeName}\"`)\n db.createObjectStore(storeName)\n }\n }\n }\n })\n }\n\n /**\n * Убеждается, что все указанные хранилища существуют в базе данных\n */\n async ensureStoresExist(storeNames: string[]): Promise<IDBDatabase> {\n // Если база еще не открыта, открываем ее\n if (!this.db) {\n this.db = await this.openDatabase(this.version)\n }\n\n // Проверяем, какие хранилища отсутствуют\n const missingStores = storeNames.filter((name) => !this.db!.objectStoreNames.contains(name))\n\n // Если все хранилища уже существуют, просто возвращаем базу\n if (missingStores.length === 0) {\n return this.db\n }\n\n // Иначе нам нужно обновить базу данных\n this.logger?.debug(`Необходимо создать отсутствующие хранилища: ${missingStores.join(', ')}`, {\n dbName: this.dbName,\n currentVersion: this.version,\n })\n\n // Закрываем текущее соединение\n this.db.close()\n this.db = null\n\n // Увеличиваем версию и открываем базу с новыми хранилищами\n this.version++\n this.db = await this.openDatabase(this.version, missingStores)\n\n return this.db\n }\n\n /**\n * Закрывает соединение с базой данных\n */\n close(): void {\n if (this.db) {\n this.db.close()\n this.db = null\n }\n }\n}\n\nexport class IndexedDBStorage<T extends Record<string, any>> extends BaseStorage<T> {\n private readonly DB_NAME: string\n private readonly STORE_NAME: string\n private readonly DB_VERSION: number\n private dbManager: IndexedDBManager\n\n constructor(\n config: StorageConfig & {\n options: IndexedDBConfig\n },\n pluginExecutor?: IPluginExecutor,\n eventEmitter?: IEventEmitter,\n logger?: ILogger,\n ) {\n super(config, pluginExecutor, eventEmitter, logger)\n\n const options = config.options\n this.DB_NAME = options.dbName || 'app_storage'\n this.STORE_NAME = config.name\n this.DB_VERSION = options.dbVersion || 1\n\n // Get database manager instance\n this.dbManager = IndexedDBManager.getInstance(this.DB_NAME, this.DB_VERSION, logger)\n }\n\n async initialize(): Promise<this> {\n try {\n this.logger?.debug(`Initializing IndexedDB storage \"${this.STORE_NAME}\"`)\n\n await this.dbManager.ensureStoreExists(this.STORE_NAME)\n\n // Проверим еще раз, что хранилище доступно перед инициализацией middleware\n try {\n const db = await this.dbManager.initialize()\n if (!db.objectStoreNames.contains(this.STORE_NAME)) {\n throw new Error(`Store \"${this.STORE_NAME}\" not found after initialization`)\n }\n } catch (error) {\n this.logger?.error(`Error verifying store \"${this.STORE_NAME}\" exists:`, { error })\n throw error\n }\n\n // Initialize middlewares from BaseStorage\n this.initializeMiddlewares()\n\n try {\n await this.initializeWithMiddlewares()\n this.logger?.debug(`IndexedDB storage \"${this.STORE_NAME}\" initialized successfully`)\n } catch (error) {\n this.logger?.error(`Failed to initialize middleware for store \"${this.STORE_NAME}\"`, { error })\n // Продолжаем работу даже при ошибке middleware\n }\n\n return this\n } catch (error) {\n this.logger?.error(`Ошибка инициализации IndexedDB \"${this.name}\"`, { error })\n throw error\n }\n }\n\n static async getCurrentDBVersion(dbName: string): Promise<number> {\n return new Promise((resolve) => {\n try {\n const request = indexedDB.open(dbName)\n\n request.onsuccess = () => {\n const version = request.result.version\n request.result.close() // Важно закрыть соединение\n resolve(version)\n }\n\n request.onerror = () => {\n console.warn(`Ошибка при определении версии БД ${dbName}`, request.error)\n resolve(0) // В случае ошибки возвращаем 0\n }\n } catch (error) {\n console.warn(`Исключение при определении версии БД ${dbName}`, error)\n resolve(0)\n }\n })\n }\n\n static async createStorages<S extends Record<string, any>>(\n dbName: string,\n configs: {\n [K in keyof S]: {\n name: string\n initialState?: S[K]\n middlewares?: ConfigureMiddlewares\n pluginExecutor?: IPluginExecutor\n eventEmitter?: IEventEmitter\n }\n },\n logger?: ILogger,\n ): Promise<{ [K in keyof S]: IndexedDBStorage<S[K]> }> {\n // Получаем текущую версию базы данных\n const currentVersion = await this.getCurrentDBVersion(dbName)\n const initialVersion = currentVersion || 1\n\n // Создаем менеджер для управления базой данных\n const dbManager = new DBVersionManager(dbName, initialVersion, logger)\n\n // Получаем имена всех хранилищ, которые нужно создать\n const storeNames = Object.values(configs).map((config) => config.name)\n\n // Предварительно создаем все хранилища в рамках одной операции\n await dbManager.ensureStoresExist(storeNames)\n\n // Создаем и инициализируем все хранилища\n const result: Record<string, IndexedDBStorage<any>> = {}\n\n for (const [key, config] of Object.entries(configs)) {\n const storage = new IndexedDBStorage(\n {\n ...config,\n options: {\n dbName,\n dbVersion: dbManager.getCurrentVersion(),\n },\n },\n config.pluginExecutor,\n config.eventEmitter,\n logger,\n )\n\n // Инициализируем хранилище\n result[key] = await storage.initialize()\n }\n\n return result as { [K in keyof S]: IndexedDBStorage<S[K]> }\n }\n\n private async getTransaction(mode: IDBTransactionMode = 'readonly'): Promise<IDBTransaction> {\n try {\n // Ensure database is open and our store exists\n const db = await this.dbManager.ensureStoreExists(this.STORE_NAME)\n\n // Проверяем существование хранилища перед созданием транзакции\n if (!db.objectStoreNames.contains(this.STORE_NAME)) {\n // Попытка исправить проблему - закрываем и снова открываем\n this.logger?.warn(`Object store \"${this.STORE_NAME}\" not found, attempting to repair`)\n\n db.close()\n this.dbManager.closeDatabase()\n\n // Пробуем заново создать хранилище с инкрементом версии\n const newDb = await this.dbManager.ensureStoreExists(this.STORE_NAME)\n\n if (!newDb.objectStoreNames.contains(this.STORE_NAME)) {\n throw new Error(`Object store \"${this.STORE_NAME}\" still doesn't exist after repair attempt`)\n }\n\n return newDb.transaction(this.STORE_NAME, mode)\n }\n\n return db.transaction(this.STORE_NAME, mode)\n } catch (error) {\n this.logger?.error(`Failed to create transaction for store \"${this.STORE_NAME}\"`, { error })\n throw error\n }\n }\n\n private async getObjectStore(mode: IDBTransactionMode = 'readonly'): Promise<IDBObjectStore> {\n const transaction = await this.getTransaction(mode)\n return transaction.objectStore(this.STORE_NAME)\n }\n\n protected async doGet(key: StorageKeyType): Promise<any> {\n const store = await this.getObjectStore()\n\n // Для пустого ключа возвращаем все состояние\n if (key === '') {\n return new Promise((resolve, reject) => {\n const request = store.getAll()\n request.onerror = () => reject(request.error)\n request.onsuccess = () => {\n const allValues = request.result\n const allKeys = store.getAllKeys()\n\n allKeys.onsuccess = () => {\n const state = allKeys.result.reduce(\n (acc, k, index) => {\n if (k !== 'root') {\n acc[k as string] = allValues[index]\n }\n return acc\n },\n {} as Record<string, any>,\n )\n resolve(state)\n }\n allKeys.onerror = () => reject(allKeys.error)\n }\n })\n }\n\n // Проверяем, является ли ключ \"сырым\"\n if (key instanceof StorageKey && key.isUnparseable()) {\n return new Promise((resolve, reject) => {\n const request = store.get(key.valueOf())\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(request.result)\n })\n }\n\n // Для вложенного пути\n const parts = parsePath(key)\n if (parts.length > 1) {\n const rootKey = parts[0]\n return new Promise((resolve, reject) => {\n const request = store.get(rootKey)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => {\n const rootValue = request.result\n if (!rootValue) {\n resolve(undefined)\n return\n }\n const value = getValueByPath(rootValue, parts.slice(1).join('.'))\n resolve(value)\n }\n })\n }\n\n // Для простого ключа\n return new Promise((resolve, reject) => {\n const request = store.get(parts[0])\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(request.result)\n })\n }\n\n protected async doSet(key: StorageKeyType, value: any): Promise<void> {\n // Для пустого ключа устанавливаем все состояние\n if (key === '') {\n const store = await this.getObjectStore('readwrite')\n return new Promise((resolve, reject) => {\n const tx = store.transaction\n\n tx.oncomplete = () => {\n resolve()\n }\n\n tx.onerror = () => {\n reject(tx.error)\n }\n\n const clearRequest = store.clear()\n\n clearRequest.onsuccess = () => {\n const entries = Object.entries(value)\n for (const [entryKey, entryValue] of entries) {\n store.put(entryValue, entryKey)\n }\n }\n\n clearRequest.onerror = () => {\n reject(clearRequest.error)\n }\n })\n }\n\n const store = await this.getObjectStore('readwrite')\n\n // Для \"сырого\" ключа\n if (key instanceof StorageKey && key.isUnparseable()) {\n await this.putValueInStore(store, key.valueOf(), value)\n return\n }\n\n // Для вложенного пути\n const parts = parsePath(key)\n if (parts.length > 1) {\n const rootKey = parts[0]\n return new Promise((resolve, reject) => {\n const request = store.get(rootKey)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => {\n const rootValue = request.result || {}\n const updatedValue = setValueByPath(rootValue, parts.slice(1).join('.'), value)\n const putRequest = store.put(updatedValue, rootKey)\n putRequest.onerror = () => reject(putRequest.error)\n putRequest.onsuccess = () => resolve()\n }\n })\n }\n\n // Для простого ключа\n await this.putValueInStore(store, parts[0], value)\n }\n\n private async putValueInStore(store: IDBObjectStore, key: StorageKeyType, value: any): Promise<void> {\n return new Promise((resolve, reject) => {\n const request = store.put(value, key.valueOf())\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve()\n })\n }\n\n protected async doUpdate(updates: Array<{ key: string | StorageKey; value: any }>): Promise<void> {\n // Группируем обновления\n const updatesByRoot = new Map<string, Array<{ path: string[]; value: any }>>()\n const rawUpdates: Array<{ key: string; value: any }> = []\n\n // Разделяем обновления на \"сырые\" и обычные\n for (const { key, value } of updates) {\n if (key instanceof StorageKey && key.isUnparseable()) {\n rawUpdates.push({ key: key.valueOf(), value })\n continue\n }\n\n const parts = parsePath(key)\n const rootKey = parts[0]\n const path = parts.slice(1)\n\n if (!updatesByRoot.has(rootKey)) {\n updatesByRoot.set(rootKey, [])\n }\n updatesByRoot.get(rootKey)!.push({ path, value })\n }\n\n try {\n // Обрабатываем \"сырые\" обновления\n for (const { key, value } of rawUpdates) {\n const store = await this.getObjectStore('readwrite')\n await this.putValueInStore(store, key, value)\n }\n\n // Обрабатываем сгруппированные обновления\n for (const [rootKey, pathUpdates] of updatesByRoot) {\n const rootValue = (await this.doGet(rootKey)) || {}\n let updatedValue = { ...rootValue }\n\n for (const { path, value } of pathUpdates) {\n if (path.length === 0) {\n updatedValue = value\n } else {\n updatedValue = setValueByPath(updatedValue, path.join('.'), value)\n }\n }\n\n const store = await this.getObjectStore('readwrite')\n await this.putValueInStore(store, rootKey, updatedValue)\n }\n } catch (error) {\n this.logger?.error('Error during update:', { error })\n throw error\n }\n }\n\n protected async doDelete(key: StorageKeyType): Promise<boolean> {\n const store = await this.getObjectStore('readwrite')\n\n // Для \"сырого\" ключа\n if (key instanceof StorageKey && key.isUnparseable()) {\n return new Promise((resolve, reject) => {\n const request = store.delete(key.valueOf())\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(true)\n })\n }\n\n const parts = parsePath(key)\n\n // Для простого ключа\n if (parts.length === 1) {\n return new Promise((resolve, reject) => {\n const request = store.delete(parts[0])\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(true)\n })\n }\n\n // Для вложенного пути\n const rootKey = parts[0]\n return new Promise((resolve, reject) => {\n const getRequest = store.get(rootKey)\n getRequest.onerror = () => reject(getRequest.error)\n getRequest.onsuccess = () => {\n const rootValue = getRequest.result\n if (!rootValue) {\n resolve(false)\n return\n }\n\n const parent = getValueByPath(rootValue, parts.slice(0, -1).join('.'))\n const lastKey = parts[parts.length - 1]\n\n if (!parent || !(lastKey in parent)) {\n resolve(false)\n return\n }\n\n if (Array.isArray(parent)) {\n const index = parseInt(lastKey, 10)\n if (!isNaN(index)) {\n parent.splice(index, 1)\n } else {\n // @ts-ignore\n delete parent[lastKey]\n }\n } else {\n delete parent[lastKey]\n }\n\n const putRequest = store.put(rootValue, rootKey)\n putRequest.onerror = () => reject(putRequest.error)\n putRequest.onsuccess = () => resolve(true)\n }\n })\n }\n\n protected async doClear(): Promise<void> {\n const store = await this.getObjectStore('readwrite')\n return new Promise((resolve, reject) => {\n const request = store.clear()\n request.onsuccess = () => resolve()\n request.onerror = () => reject(request.error)\n })\n }\n\n protected async doKeys(): Promise<string[]> {\n const store = await this.getObjectStore()\n const request = store.getAllKeys()\n return new Promise((resolve, reject) => {\n request.onsuccess = () => {\n resolve(request.result as string[])\n }\n request.onerror = () => reject(request.error)\n })\n }\n\n protected async doHas(key: StorageKeyType): Promise<boolean> {\n const value = await this.doGet(key)\n return value !== undefined\n }\n\n protected async doDestroy(): Promise<void> {\n try {\n await this.doClear()\n\n // Note: We don't actually delete the object store from the database\n // as that would require reopening the DB with a higher version.\n // An empty object store takes minimal space.\n } catch (error) {\n this.logger?.error(`Error destroying store \"${this.STORE_NAME}\"`, { error })\n throw error\n }\n }\n}\n","import { IPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { IEventEmitter, ILogger, StorageConfig } from '../storage.interface'\nimport { StorageKey, StorageKeyType } from '../utils/storage-key'\nimport { BaseStorage } from './base-storage.service'\nimport { getValueByPath, parsePath, setValueByPath } from './path.utils'\n\nexport class LocalStorage<T extends Record<string, any>> extends BaseStorage<T> {\n constructor(config: StorageConfig, pluginExecutor?: IPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger) {\n super(config, pluginExecutor, eventEmitter, logger)\n }\n\n async initialize(): Promise<this> {\n try {\n await this.initializeWithMiddlewares()\n return this\n } catch (error) {\n this.logger?.error('Error initializing LocalStorage', { error })\n throw error\n }\n }\n\n protected async doGet(key: StorageKeyType): Promise<any> {\n const storageData = localStorage.getItem(this.name)\n if (!storageData) return undefined\n\n const state = JSON.parse(storageData)\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n return state[key.valueOf()]\n }\n\n return getValueByPath(state, key)\n }\n\n protected async doSet(key: StorageKeyType, value: any): Promise<void> {\n const storageData = localStorage.getItem(this.name)\n const state = storageData ? JSON.parse(storageData) : {}\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n state[key.valueOf()] = value\n localStorage.setItem(this.name, JSON.stringify(state))\n return\n }\n\n const newState = setValueByPath({ ...state }, key, value)\n localStorage.setItem(this.name, JSON.stringify(newState))\n }\n\n protected async doDelete(key: StorageKeyType): Promise<boolean> {\n const storageData = localStorage.getItem(this.name)\n if (!storageData) return false\n\n const state = JSON.parse(storageData)\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n const rawKey = key.valueOf()\n if (!(rawKey in state)) return false\n delete state[rawKey]\n localStorage.setItem(this.name, JSON.stringify(state))\n return true\n }\n\n const pathParts = parsePath(key)\n const parentPath = pathParts.slice(0, -1).join('.')\n const lastKey = pathParts[pathParts.length - 1]\n\n const parent = parentPath ? getValueByPath(state, parentPath) : state\n\n if (!parent || !(lastKey in parent)) return false\n\n delete parent[lastKey]\n localStorage.setItem(this.name, JSON.stringify(state))\n return true\n }\n\n protected async doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): Promise<void> {\n const storageData = localStorage.getItem(this.name)\n const state = storageData ? JSON.parse(storageData) : {}\n\n for (const { key, value } of updates) {\n if (key instanceof StorageKey && key.isUnparseable()) {\n state[key.valueOf()] = value\n } else {\n setValueByPath(state, key, value)\n }\n }\n\n localStorage.setItem(this.name, JSON.stringify(state))\n }\n\n protected async doClear(): Promise<void> {\n localStorage.removeItem(this.name)\n }\n\n protected async doKeys(): Promise<string[]> {\n const storageData = localStorage.getItem(this.name)\n if (!storageData) return []\n\n const state = JSON.parse(storageData)\n return this.getAllKeys(state)\n }\n\n protected async doHas(key: StorageKeyType): Promise<boolean> {\n const value = await this.doGet(key)\n return value !== undefined\n }\n\n private getAllKeys(obj: any): string[] {\n return Object.keys(obj)\n }\n\n protected async doDestroy(): Promise<void> {\n await this.doClear()\n }\n}\n","import { IPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { IEventEmitter, ILogger, StorageConfig } from '../storage.interface'\nimport { StorageKey, StorageKeyType } from '../utils/storage-key'\nimport { BaseStorage } from './base-storage.service'\nimport { getValueByPath, parsePath, setValueByPath } from './path.utils'\n\nexport class MemoryStorage<T extends Record<string, any>> extends BaseStorage<T> {\n private storage = new Map<string, any>()\n\n constructor(config: StorageConfig, pluginExecutor?: IPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger) {\n super(config, pluginExecutor, eventEmitter, logger)\n }\n\n async initialize() {\n try {\n this.initializeMiddlewares()\n await this.initializeWithMiddlewares()\n return this\n } catch (error) {\n this.logger?.error('Error initializing MemoryStorage', { error })\n throw error\n }\n }\n\n protected async doGet(key: StorageKeyType): Promise<any> {\n const state = this.storage.get(this.name)\n if (!state) return undefined\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n return state[key.valueOf()]\n }\n\n return getValueByPath(state, key)\n }\n\n protected async doSet(key: StorageKeyType, value: any): Promise<void> {\n const state = this.storage.get(this.name) || {}\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n state[key.valueOf()] = value\n this.storage.set(this.name, state)\n return\n }\n\n const newState = setValueByPath({ ...state }, key, value)\n this.storage.set(this.name, newState)\n }\n\n protected async doDelete(key: StorageKeyType): Promise<boolean> {\n const state = this.storage.get(this.name)\n if (!state) return false\n\n // Добавляем проверку на \"сырой\" ключ\n if (key instanceof StorageKey && key.isUnparseable()) {\n const rawKey = key.valueOf()\n if (!(rawKey in state)) return false\n delete state[rawKey]\n this.storage.set(this.name, state)\n return true\n }\n\n const pathParts = parsePath(key)\n const parentPath = pathParts.slice(0, -1).join('.')\n const lastKey = pathParts[pathParts.length - 1]\n const parent = parentPath ? getValueByPath(state, parentPath) : state\n\n if (!parent || !(lastKey in parent)) return false\n\n delete parent[lastKey]\n this.storage.set(this.name, state)\n return true\n }\n\n protected async doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): Promise<void> {\n const currentState = this.storage.get(this.name) || {}\n // Создаем копию текущего состояния\n const newState = { ...currentState }\n\n for (const { key, value } of updates) {\n if (key instanceof StorageKey && key.isUnparseable()) {\n newState[key.valueOf()] = value\n } else {\n setValueByPath(newState, key, value)\n }\n }\n\n // Сохраняем новое состояние\n this.storage.set(this.name, newState)\n }\n\n protected async doClear(): Promise<void> {\n this.storage.delete(this.name)\n }\n\n protected async doKeys(): Promise<string[]> {\n const state = this.storage.get(this.name)\n if (!state) return []\n return this.getAllKeys(state)\n }\n\n protected async doHas(key: StorageKeyType): Promise<boolean> {\n const value = await this.doGet(key)\n return value !== undefined\n }\n\n protected async doDestroy(): Promise<void> {\n this.storage.delete(this.name)\n }\n\n private getAllKeys(obj: any): string[] {\n return Object.keys(obj)\n }\n}\n"],"mappings":"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","names":["StorageEvents","currentState","selectedValue","store"]}