synapse-storage 3.0.2 → 3.0.3
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/api.cjs +891 -0
- package/dist/api.cjs.map +1 -0
- package/dist/api.d.cts +365 -0
- package/dist/api.d.ts +365 -0
- package/dist/api.js +860 -0
- package/dist/api.js.map +1 -0
- package/dist/core.cjs +2389 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +397 -0
- package/dist/{core/storage/modules/plugin/plugin.interface.d.ts → core.d.ts} +203 -7
- package/dist/core.js +2356 -0
- package/dist/core.js.map +1 -0
- package/dist/dispatcher.module-CdpmkplA.d.cts +363 -0
- package/dist/dispatcher.module-jd8U_ZEs.d.ts +363 -0
- package/dist/index.cjs +4148 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +4092 -13
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +268 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +74 -0
- package/dist/react.d.ts +74 -0
- package/dist/react.js +239 -0
- package/dist/react.js.map +1 -0
- package/dist/reactive.cjs +643 -0
- package/dist/reactive.cjs.map +1 -0
- package/dist/reactive.d.cts +35 -0
- package/dist/reactive.d.ts +35 -0
- package/dist/reactive.js +604 -0
- package/dist/reactive.js.map +1 -0
- package/dist/{core/selector/selector.interface.d.ts → selector.interface-CA5y-kD_.d.cts} +7 -35
- package/dist/selector.interface-CA5y-kD_.d.ts +63 -0
- package/dist/storage.interface-Dl8SLUd1.d.cts +128 -0
- package/dist/storage.interface-Dl8SLUd1.d.ts +128 -0
- package/dist/utils.cjs +601 -0
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +92 -0
- package/dist/utils.d.ts +92 -0
- package/dist/utils.js +574 -0
- package/dist/utils.js.map +1 -0
- package/package.json +54 -17
- package/dist/_utils/chunk.util.d.ts +0 -8
- package/dist/_utils/chunk.util.d.ts.map +0 -1
- package/dist/_utils/chunk.util.js +0 -21
- package/dist/_utils/chunk.util.js.map +0 -1
- package/dist/_utils/deepMerge.util.d.ts +0 -2
- package/dist/_utils/deepMerge.util.d.ts.map +0 -1
- package/dist/_utils/deepMerge.util.js +0 -16
- package/dist/_utils/deepMerge.util.js.map +0 -1
- package/dist/_utils/flatMap.util.d.ts +0 -10
- package/dist/_utils/flatMap.util.d.ts.map +0 -1
- package/dist/_utils/flatMap.util.js +0 -23
- package/dist/_utils/flatMap.util.js.map +0 -1
- package/dist/_utils/index.d.ts +0 -4
- package/dist/_utils/index.d.ts.map +0 -1
- package/dist/_utils/index.js +0 -4
- package/dist/_utils/index.js.map +0 -1
- package/dist/api/api.module.d.ts +0 -38
- package/dist/api/api.module.d.ts.map +0 -1
- package/dist/api/api.module.js +0 -82
- package/dist/api/api.module.js.map +0 -1
- package/dist/api/components/endpoint.d.ts +0 -26
- package/dist/api/components/endpoint.d.ts.map +0 -1
- package/dist/api/components/endpoint.js +0 -253
- package/dist/api/components/endpoint.js.map +0 -1
- package/dist/api/components/query-storage.d.ts +0 -84
- package/dist/api/components/query-storage.d.ts.map +0 -1
- package/dist/api/components/query-storage.js +0 -221
- package/dist/api/components/query-storage.js.map +0 -1
- package/dist/api/example.d.ts +0 -83
- package/dist/api/example.d.ts.map +0 -1
- package/dist/api/example.js +0 -85
- package/dist/api/example.js.map +0 -1
- package/dist/api/index.d.ts +0 -4
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -6
- package/dist/api/index.js.map +0 -1
- package/dist/api/types/api.interface.d.ts +0 -108
- package/dist/api/types/api.interface.d.ts.map +0 -1
- package/dist/api/types/api.interface.js +0 -19
- package/dist/api/types/api.interface.js.map +0 -1
- package/dist/api/types/endpoint.interface.d.ts +0 -116
- package/dist/api/types/endpoint.interface.d.ts.map +0 -1
- package/dist/api/types/endpoint.interface.js +0 -2
- package/dist/api/types/endpoint.interface.js.map +0 -1
- package/dist/api/types/query.interface.d.ts +0 -87
- package/dist/api/types/query.interface.d.ts.map +0 -1
- package/dist/api/types/query.interface.js +0 -2
- package/dist/api/types/query.interface.js.map +0 -1
- package/dist/api/utils/api-helpers.d.ts +0 -22
- package/dist/api/utils/api-helpers.d.ts.map +0 -1
- package/dist/api/utils/api-helpers.js +0 -44
- package/dist/api/utils/api-helpers.js.map +0 -1
- package/dist/api/utils/create-header-context.d.ts +0 -10
- package/dist/api/utils/create-header-context.d.ts.map +0 -1
- package/dist/api/utils/create-header-context.js +0 -36
- package/dist/api/utils/create-header-context.js.map +0 -1
- package/dist/api/utils/endpoint-headers.d.ts +0 -23
- package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
- package/dist/api/utils/endpoint-headers.js +0 -57
- package/dist/api/utils/endpoint-headers.js.map +0 -1
- package/dist/api/utils/fetch-base-query.d.ts +0 -9
- package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
- package/dist/api/utils/fetch-base-query.js +0 -181
- package/dist/api/utils/fetch-base-query.js.map +0 -1
- package/dist/api/utils/file-utils.d.ts +0 -43
- package/dist/api/utils/file-utils.d.ts.map +0 -1
- package/dist/api/utils/file-utils.js +0 -108
- package/dist/api/utils/file-utils.js.map +0 -1
- package/dist/api/utils/get-cacheable-headers.d.ts +0 -8
- package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
- package/dist/api/utils/get-cacheable-headers.js +0 -21
- package/dist/api/utils/get-cacheable-headers.js.map +0 -1
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -3
- package/dist/core/index.js.map +0 -1
- package/dist/core/selector/index.d.ts +0 -3
- package/dist/core/selector/index.d.ts.map +0 -1
- package/dist/core/selector/index.js +0 -2
- package/dist/core/selector/index.js.map +0 -1
- package/dist/core/selector/selector.interface.d.ts.map +0 -1
- package/dist/core/selector/selector.interface.js +0 -2
- package/dist/core/selector/selector.interface.js.map +0 -1
- package/dist/core/selector/selector.module.d.ts +0 -29
- package/dist/core/selector/selector.module.d.ts.map +0 -1
- package/dist/core/selector/selector.module.js +0 -467
- package/dist/core/selector/selector.module.js.map +0 -1
- package/dist/core/storage/adapters/base-storage.service.d.ts +0 -65
- package/dist/core/storage/adapters/base-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/base-storage.service.js +0 -660
- package/dist/core/storage/adapters/base-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.d.ts +0 -63
- package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.js +0 -595
- package/dist/core/storage/adapters/indexed-DB.service.js.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.old.d.ts +0 -38
- package/dist/core/storage/adapters/indexed-DB.service.old.d.ts.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.old.js +0 -318
- package/dist/core/storage/adapters/indexed-DB.service.old.js.map +0 -1
- package/dist/core/storage/adapters/local-storage.service.d.ts +0 -21
- package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/local-storage.service.js +0 -99
- package/dist/core/storage/adapters/local-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/memory-storage.service.d.ts +0 -22
- package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/memory-storage.service.js +0 -99
- package/dist/core/storage/adapters/memory-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/path.utils.d.ts +0 -5
- package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
- package/dist/core/storage/adapters/path.utils.js +0 -35
- package/dist/core/storage/adapters/path.utils.js.map +0 -1
- package/dist/core/storage/index.d.ts +0 -11
- package/dist/core/storage/index.d.ts.map +0 -1
- package/dist/core/storage/index.js +0 -12
- package/dist/core/storage/index.js.map +0 -1
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -9
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/broadcast.middleware.js +0 -115
- package/dist/core/storage/middlewares/broadcast.middleware.js.map +0 -1
- package/dist/core/storage/middlewares/index.d.ts +0 -4
- package/dist/core/storage/middlewares/index.d.ts.map +0 -1
- package/dist/core/storage/middlewares/index.js +0 -3
- package/dist/core/storage/middlewares/index.js.map +0 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -7
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.js +0 -36
- package/dist/core/storage/middlewares/storage-batching.middleware.js.map +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -7
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +0 -46
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.js +0 -2
- package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -25
- package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.js +0 -186
- package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
- package/dist/core/storage/storage.interface.d.ts +0 -70
- package/dist/core/storage/storage.interface.d.ts.map +0 -1
- package/dist/core/storage/storage.interface.js +0 -10
- package/dist/core/storage/storage.interface.js.map +0 -1
- package/dist/core/storage/utils/batch.utils.d.ts +0 -33
- package/dist/core/storage/utils/batch.utils.d.ts.map +0 -1
- package/dist/core/storage/utils/batch.utils.js +0 -88
- package/dist/core/storage/utils/batch.utils.js.map +0 -1
- package/dist/core/storage/utils/broadcast.util.d.ts +0 -48
- package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
- package/dist/core/storage/utils/broadcast.util.js +0 -162
- package/dist/core/storage/utils/broadcast.util.js.map +0 -1
- package/dist/core/storage/utils/cache.util.d.ts +0 -33
- package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
- package/dist/core/storage/utils/cache.util.js +0 -47
- package/dist/core/storage/utils/cache.util.js.map +0 -1
- package/dist/core/storage/utils/middleware-module.d.ts +0 -46
- package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
- package/dist/core/storage/utils/middleware-module.js +0 -109
- package/dist/core/storage/utils/middleware-module.js.map +0 -1
- package/dist/core/storage/utils/storage-key.d.ts +0 -11
- package/dist/core/storage/utils/storage-key.d.ts.map +0 -1
- package/dist/core/storage/utils/storage-key.js +0 -21
- package/dist/core/storage/utils/storage-key.js.map +0 -1
- package/dist/core/storage/utils/storage.utils.d.ts +0 -17
- package/dist/core/storage/utils/storage.utils.d.ts.map +0 -1
- package/dist/core/storage/utils/storage.utils.js +0 -57
- package/dist/core/storage/utils/storage.utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/react/hooks/index.d.ts +0 -3
- package/dist/react/hooks/index.d.ts.map +0 -1
- package/dist/react/hooks/index.js +0 -3
- package/dist/react/hooks/index.js.map +0 -1
- package/dist/react/hooks/useSelector.d.ts +0 -22
- package/dist/react/hooks/useSelector.d.ts.map +0 -1
- package/dist/react/hooks/useSelector.js +0 -104
- package/dist/react/hooks/useSelector.js.map +0 -1
- package/dist/react/hooks/useStorageSubscribe.d.ts +0 -12
- package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
- package/dist/react/hooks/useStorageSubscribe.js +0 -49
- package/dist/react/hooks/useStorageSubscribe.js.map +0 -1
- package/dist/react/index.d.ts +0 -3
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -3
- package/dist/react/index.js.map +0 -1
- package/dist/react/utils/createSynapseCtx.d.ts +0 -40
- package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
- package/dist/react/utils/createSynapseCtx.js +0 -125
- package/dist/react/utils/createSynapseCtx.js.map +0 -1
- package/dist/react/utils/index.d.ts +0 -2
- package/dist/react/utils/index.d.ts.map +0 -1
- package/dist/react/utils/index.js +0 -2
- package/dist/react/utils/index.js.map +0 -1
- package/dist/reactive/dispatcher/dispatcher.module.d.ts +0 -195
- package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
- package/dist/reactive/dispatcher/dispatcher.module.js +0 -288
- package/dist/reactive/dispatcher/dispatcher.module.js.map +0 -1
- package/dist/reactive/dispatcher/index.d.ts +0 -3
- package/dist/reactive/dispatcher/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/index.js +0 -3
- package/dist/reactive/dispatcher/index.js.map +0 -1
- package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -2
- package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/index.js +0 -2
- package/dist/reactive/dispatcher/middlewares/index.js.map +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -31
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js +0 -126
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js.map +0 -1
- package/dist/reactive/effects/effects.module.d.ts +0 -150
- package/dist/reactive/effects/effects.module.d.ts.map +0 -1
- package/dist/reactive/effects/effects.module.js +0 -277
- package/dist/reactive/effects/effects.module.js.map +0 -1
- package/dist/reactive/effects/index.d.ts +0 -2
- package/dist/reactive/effects/index.d.ts.map +0 -1
- package/dist/reactive/effects/index.js +0 -2
- package/dist/reactive/effects/index.js.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -12
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.js +0 -16
- package/dist/reactive/effects/utils/chunkRequestConsistent.js.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -12
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.js +0 -13
- package/dist/reactive/effects/utils/chunkRequestParallel.js.map +0 -1
- package/dist/reactive/effects/utils/index.d.ts +0 -3
- package/dist/reactive/effects/utils/index.d.ts.map +0 -1
- package/dist/reactive/effects/utils/index.js +0 -3
- package/dist/reactive/effects/utils/index.js.map +0 -1
- package/dist/reactive/index.d.ts +0 -3
- package/dist/reactive/index.d.ts.map +0 -1
- package/dist/reactive/index.js +0 -3
- package/dist/reactive/index.js.map +0 -1
- package/dist/utils/createSynapse.d.ts +0 -92
- package/dist/utils/createSynapse.d.ts.map +0 -1
- package/dist/utils/createSynapse.js +0 -79
- package/dist/utils/createSynapse.js.map +0 -1
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -2
- package/dist/utils/index.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kBAAkB;AAClB,cAAc,OAAO,CAAA;AACrB,cAAc,QAAQ,CAAA;AACtB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AAEvB,+DAA+D;AAC/D,+DAA+D;AAC/D,qCAAqC;AACrC,cAAc,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"sources":["../src/api/utils/api-helpers.ts","../src/api/utils/create-header-context.ts","../src/api/utils/endpoint-headers.ts","../src/api/types/api.interface.ts","../src/api/utils/file-utils.ts","../src/api/utils/fetch-base-query.ts","../src/api/utils/get-cacheable-headers.ts","../src/api/components/endpoint.ts","../src/core/storage/utils/storage-key.ts","../src/core/storage/utils/cache.util.ts","../src/api/components/query-storage.ts","../src/api/api.module.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/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","../src/reactive/dispatcher/dispatcher.module.ts","../src/reactive/dispatcher/middlewares/logger.middleware.ts","../src/reactive/effects/effects.module.ts","../src/reactive/effects/utils/chunkRequestConsistent.ts","../src/_utils/chunk.util.ts","../src/_utils/deepMerge.util.ts","../src/reactive/effects/utils/chunkRequestParallel.ts","../src/utils/createSynapse.ts","../src/react/hooks/useSelector.ts","../src/react/hooks/useStorageSubscribe.ts","../src/react/utils/createSynapseCtx.tsx"],"sourcesContent":["/**\n * Логгер для API\n */\nexport const apiLogger = {\n debug: (message: string, ...args: any[]) => {\n if (process.env.NODE_ENV !== 'production') {\n console.debug(`[API] ${message}`, ...args)\n }\n },\n\n log: (message: string, ...args: any[]) => {\n if (process.env.NODE_ENV !== 'production') {\n console.log(`[API] ${message}`, ...args)\n }\n },\n\n info: (message: string, ...args: any[]) => {\n console.info(`[API] ${message}`, ...args)\n },\n\n warn: (message: string, ...args: any[]) => {\n console.warn(`[API] ${message}`, ...args)\n },\n\n error: (message: string, ...args: any[]) => {\n console.error(`[API] ${message}`, ...args)\n },\n}\n\n/**\n * Создает уникальный идентификатор\n * @returns Строка с уникальным идентификатором\n */\nexport function createUniqueId(name?: string): string {\n return `${name ? `${name}|` : ''}${Math.random().toString(36).substring(2, 9) + Date.now().toString(36)}`\n}\n\n/**\n * Преобразует объект Headers в обычный объект\n * @param headers Объект Headers\n * @returns Обычный объект с заголовками\n */\nexport function headersToObject(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {}\n headers.forEach((value, key) => {\n result[key.toLowerCase()] = value\n })\n return result\n}\n","import { ApiContext } from '../types/api.interface'\n\n/**\n * Создает контекст для подготовки заголовков\n *\n * @param context - базовый контекст\n * @param optionContext - дополнительный контекст из опций\n * @returns - полный контекст для подготовки заголовков\n */\nexport function createHeaderContext<RequestParams extends Record<string, any>>(\n context: Partial<ApiContext> = {} as ApiContext<RequestParams>,\n optionContext: Record<string, any> = {},\n): ApiContext<RequestParams> {\n return {\n ...context,\n ...optionContext,\n getFromStorage:\n context.getFromStorage ||\n ((key: string) => {\n try {\n const item = localStorage.getItem(key)\n return item ? JSON.parse(item) : undefined\n } catch (error) {\n console.warn(`[API] Ошибка чтения из localStorage: ${error}`)\n return undefined\n }\n }),\n getCookie:\n context.getCookie ||\n ((name: string) => {\n try {\n const matches = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/([\\.$?*|{}\\(\\)\\[\\]\\\\\\/\\+^])/g, '\\\\$1')}=([^;]*)`))\n return matches ? decodeURIComponent(matches[1]) : undefined\n } catch (error) {\n console.warn(`[API] Ошибка чтения cookie: ${error}`)\n return undefined\n }\n }),\n }\n}\n","import { ApiContext } from '../types/api.interface'\nimport { createHeaderContext } from './create-header-context'\n\n/**\n * Тип функции для подготовки заголовков запроса\n */\nexport type PrepareHeadersFunction = (headers: Headers, context: ApiContext<any>) => Promise<Headers>\n\n/**\n * Подготавливает заголовки для запроса на основе контекста и пользовательских функций\n *\n * @param prepareHeadersFn - функция подготовки заголовков\n * @param context - контекст запроса\n * @returns - подготовленные заголовки\n */\nexport async function prepareRequestHeaders<RequestParams extends Record<string, any>>(\n prepareHeadersFn?: PrepareHeadersFunction,\n context?: ApiContext<RequestParams>,\n): Promise<Headers> {\n // Создаем заголовки\n let headers = new Headers()\n\n // Создаем контекст, если он не передан\n const headerContext = context || createHeaderContext({} as ApiContext<RequestParams>, {})\n\n // Применяем функцию подготовки заголовков, если она определена\n if (prepareHeadersFn) {\n try {\n headers = await Promise.resolve(prepareHeadersFn(headers, headerContext))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке заголовков', error)\n }\n }\n\n return headers\n}\n\n/**\n * Создает комбинированную функцию для подготовки заголовков, объединяющую\n * глобальные заголовки и заголовки эндпоинта\n *\n * @param globalPrepareHeaders - функция подготовки заголовков на глобальном уровне\n * @param endpointPrepareHeaders - функция подготовки заголовков на уровне эндпоинта\n * @returns - функция для подготовки заголовков\n */\nexport function createPrepareHeaders(globalPrepareHeaders?: PrepareHeadersFunction, endpointPrepareHeaders?: PrepareHeadersFunction): PrepareHeadersFunction {\n return async (headers: Headers, context: ApiContext<any>): Promise<Headers> => {\n let processedHeaders = new Headers(headers)\n\n // Применяем глобальную функцию подготовки заголовков, если она определена\n if (globalPrepareHeaders) {\n try {\n processedHeaders = await Promise.resolve(globalPrepareHeaders(processedHeaders, context))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке глобальных заголовков', error)\n }\n }\n\n // Применяем функцию подготовки заголовков эндпоинта, если она определена\n if (endpointPrepareHeaders) {\n try {\n processedHeaders = await Promise.resolve(endpointPrepareHeaders(processedHeaders, context))\n } catch (error) {\n console.warn('[API] Ошибка при подготовке заголовков эндпоинта', error)\n }\n }\n\n return processedHeaders\n }\n}\n","import { IStorage, StorageType } from '../../core'\nimport { CreateEndpoint, EndpointConfig } from './endpoint.interface'\n\n/**\n * Форматы ответа от сервера\n */\nexport enum ResponseFormat {\n /** JSON-объект (по умолчанию) */\n Json = 'json',\n /** Blob-объект для файлов */\n Blob = 'blob',\n /** ArrayBuffer для бинарных данных */\n ArrayBuffer = 'arrayBuffer',\n /** Текстовый формат */\n Text = 'text',\n /** FormData для форм */\n FormData = 'formData',\n /** Без преобразования - возвращает сырой ответ */\n Raw = 'raw',\n}\n\n/**\n * Настройки кэша\n * Может быть объектом с параметрами или boolean (true для кэширования с настройками по умолчанию, false для отключения)\n */\nexport type CacheConfig =\n | boolean\n | {\n /** Время жизни кэша в миллисекундах */\n ttl?: number\n /** Настройки периодической очистки */\n cleanup?: {\n /** Включить периодическую очистку */\n enabled: boolean\n /** Интервал очистки в миллисекундах */\n interval?: number\n }\n /** Инвалидировать кэш при ошибке */\n invalidateOnError?: boolean\n }\n\n/**\n * Определение запроса\n * Содержит всю необходимую информацию для выполнения HTTP-запроса\n */\nexport interface RequestDefinition<RequestParams extends Record<string, any>> {\n /** Путь запроса (относительный или абсолютный URL) */\n path: string\n /** HTTP-метод */\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'\n /** Тело запроса (автоматически сериализуется) */\n body?: any\n /** Параметры запроса (автоматически добавляются в URL) */\n query?: RequestParams\n /** HTTP-заголовки */\n headers?: Record<string, string>\n /** Формат ответа (по умолчанию json) */\n responseFormat?: ResponseFormat\n /** Имя файла для автоматического скачивания */\n fileName?: string\n /** Тип контента для автоматического скачивания */\n fileType?: string\n}\n\n/**\n * Контекст API для использования в prepareHeaders и других функциях\n * Содержит вспомогательные методы и информацию о запросе\n */\nexport interface ApiContext<RequestParams extends Record<string, any> = any> {\n /** Параметры запроса */\n requestParams?: RequestParams\n /** Получить значение из localStorage */\n getFromStorage: <T>(key: string) => T | undefined\n /** Получить значение cookie */\n getCookie: (name: string) => string | undefined\n /** Поддержка для дополнительных свойств */\n [key: string]: any\n}\n\n/**\n * Аргументы для создания fetch-запроса\n */\nexport interface FetchBaseQueryArgs {\n /** Базовый URL для всех запросов */\n baseUrl: string\n /** Функция для подготовки заголовков, может быть асинхронной */\n prepareHeaders?: (headers: Headers, context: ApiContext) => Promise<Headers>\n /** Таймаут запроса в миллисекундах */\n timeout?: number\n /** Пользовательская fetch-функция */\n fetchFn?: typeof fetch\n credentials?: RequestCredentials\n}\n\nexport interface CreateApiClientOptions<T extends Record<string, EndpointConfig<any, any>> = Record<string, EndpointConfig<any, any>>> {\n storage: IStorage\n /** Настройки кэша\n * если явно указан false - значит ни один запрос НЕ будет кэшироваться, даже если в эндпоинтах указаны параметры\n * */\n cache?: CacheConfig\n /** Базовый запрос или его настройки */\n baseQuery: FetchBaseQueryArgs\n /** Функция для создания эндпоинтов */\n endpoints?: (create: CreateEndpoint) => Promise<T>\n /** Глобальные заголовки, влияющие на кэш */\n cacheableHeaderKeys?: string[]\n}\n\n/**\n * Извлечение типа параметров из конфигурации эндпоинта\n */\nexport type ExtractParamsType<T> = T extends EndpointConfig<infer P, any> ? P : never\n\n/**\n * Извлечение типа результата из конфигурации эндпоинта\n */\nexport type ExtractResultType<T> = T extends EndpointConfig<any, infer R> ? R : never\n","import { ResponseFormat } from '../types/api.interface'\n\n/**\n * Получает формат ответа на основе MIME-типа\n * @param contentType MIME-тип контента\n * @returns Формат ответа\n */\nexport function getResponseFormatForMimeType(contentType: string): ResponseFormat | undefined {\n const type = contentType.toLowerCase().split(';')[0].trim()\n\n if (type.includes('application/json')) {\n return ResponseFormat.Json\n }\n\n if (type.includes('text/')) {\n return ResponseFormat.Text\n }\n\n if (type.includes('multipart/form-data')) {\n return ResponseFormat.FormData\n }\n\n if (type.includes('application/octet-stream') || type.includes('application/pdf') || type.includes('image/') || type.includes('audio/') || type.includes('video/')) {\n return ResponseFormat.Blob\n }\n\n return undefined\n}\n\n/**\n * Проверяет, является ли ответ файлом на основе заголовков\n * @param headers Заголовки ответа\n * @returns true если ответ является файлом\n */\nexport function isFileResponse(headers: Headers): boolean {\n const contentType = headers.get('content-type') || ''\n const contentDisposition = headers.get('content-disposition') || ''\n\n // Проверяем по типу контента\n const isFileContentType =\n contentType.includes('application/octet-stream') ||\n contentType.includes('application/pdf') ||\n contentType.includes('image/') ||\n contentType.includes('audio/') ||\n contentType.includes('video/')\n\n // Проверяем по заголовку content-disposition\n const isAttachment = contentDisposition.includes('attachment') || contentDisposition.includes('filename=')\n\n return isFileContentType || isAttachment\n}\n\n/**\n * Извлекает имя файла из заголовков\n * @param headers Заголовки ответа\n * @returns Имя файла\n */\nexport function extractFilenameFromHeaders(headers: Headers): string | undefined {\n const contentDisposition = headers.get('content-disposition')\n\n if (!contentDisposition) return undefined\n\n // Пытаемся извлечь имя файла из content-disposition\n const filenameMatch = contentDisposition.match(/filename[^;=\\n]*=((['\"]).*?\\2|[^;\\n]*)/)\n if (filenameMatch && filenameMatch[1]) {\n // Очищаем от кавычек\n return filenameMatch[1].replace(/['\"]/g, '').trim()\n }\n\n return undefined\n}\n\n/**\n * Извлекает метаданные файла из заголовков\n * @param headers Заголовки ответа\n * @returns Метаданные файла\n */\nexport function getFileMetadataFromHeaders(headers: Headers): Record<string, any> | undefined {\n const contentType = headers.get('content-type') || ''\n const contentDisposition = headers.get('content-disposition') || ''\n const contentLength = headers.get('content-length')\n\n if (!isFileResponse(headers)) {\n return undefined\n }\n\n const filename = extractFilenameFromHeaders(headers)\n\n return {\n filename,\n contentType,\n contentDisposition,\n size: contentLength ? parseInt(contentLength, 10) : undefined,\n }\n}\n\n/**\n * Создает blob URL для файла\n * @param blob Объект Blob или File\n * @returns URL для доступа к файлу\n */\nexport function createBlobUrl(blob: Blob): string {\n return URL.createObjectURL(blob)\n}\n\n/**\n * Освобождает blob URL\n * @param url URL для освобождения\n */\nexport function revokeBlobUrl(url: string): void {\n URL.revokeObjectURL(url)\n}\n\n/**\n * Скачивает файл в браузере\n * @param blob Объект Blob или File\n * @param filename Имя файла\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = createBlobUrl(blob)\n const link = document.createElement('a')\n link.href = url\n link.download = filename\n document.body.appendChild(link)\n link.click()\n document.body.removeChild(link)\n setTimeout(() => revokeBlobUrl(url), 100)\n}\n","import { ApiContext, FetchBaseQueryArgs, RequestDefinition, ResponseFormat } from '../types/api.interface'\nimport { FileDownloadResult, QueryOptions, QueryResult } from '../types/query.interface'\nimport { getFileMetadataFromHeaders, getResponseFormatForMimeType, isFileResponse } from './file-utils'\n\n/**\n * Извлекает данные из response в зависимости от формата\n * @param response Объект Response\n * @param format Формат ответа\n * @returns Объект с данными или ошибкой\n */\nasync function getResponseData<T, E extends Error>(response: Response, format?: ResponseFormat): Promise<{ data?: T; error?: E; fileMetadata?: FileDownloadResult }> {\n let responseFormat = format\n const contentType = response.headers.get('content-type') || ''\n\n // Если формат не указан, пытаемся определить его из MIME-типа\n if (!responseFormat && contentType) {\n // Проверка, является ли ответ файлом на основе заголовков\n if (isFileResponse(response.headers)) {\n responseFormat = ResponseFormat.Blob\n } else {\n responseFormat = getResponseFormatForMimeType(contentType)\n }\n }\n\n // Если формат всё ещё не определен, используем JSON по умолчанию\n if (!responseFormat) {\n responseFormat = ResponseFormat.Json\n }\n\n try {\n // Получение метаданных файла, если формат указывает на файл\n let fileMetadata: any\n if (responseFormat === ResponseFormat.Blob || responseFormat === ResponseFormat.ArrayBuffer) {\n fileMetadata = getFileMetadataFromHeaders(response.headers)\n }\n\n // Обработка данных в зависимости от формата\n switch (responseFormat) {\n case ResponseFormat.Json: {\n // Пробуем получить JSON-данные\n try {\n const data = await response.json()\n return response.ok ? { data: data as T, fileMetadata } : { error: data as E, fileMetadata }\n } catch (error) {\n // Если не удалось разобрать JSON, возвращаем текст\n const text = await response.text()\n return response.ok ? { data: text as unknown as T, fileMetadata } : { error: text as unknown as E, fileMetadata }\n }\n }\n\n case ResponseFormat.Text: {\n const text = await response.text()\n return response.ok ? { data: text as unknown as T, fileMetadata } : { error: text as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.Blob: {\n const blob = await response.blob()\n return response.ok ? { data: blob as unknown as T, fileMetadata } : { error: blob as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.ArrayBuffer: {\n const buffer = await response.arrayBuffer()\n return response.ok ? { data: buffer as unknown as T, fileMetadata } : { error: buffer as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.FormData: {\n const formData = await response.formData()\n return response.ok ? { data: formData as unknown as T, fileMetadata } : { error: formData as unknown as E, fileMetadata }\n }\n\n case ResponseFormat.Raw: {\n return response.ok ? { data: response as unknown as T, fileMetadata } : { error: response as unknown as E, fileMetadata }\n }\n\n default:\n // Если формат неизвестен, возвращаем blob как наиболее универсальный\n // eslint-disable-next-line no-case-declarations\n const blob = await response.blob()\n return response.ok ? { data: blob as unknown as T, fileMetadata } : { error: blob as unknown as E, fileMetadata }\n }\n } catch (err) {\n console.error(`[API] Ошибка извлечения данных из ответа (формат: ${responseFormat})`, err)\n return response.ok ? { data: undefined } : { error: err as E }\n }\n}\n\n/**\n * Создает базовый fetch-клиент для запросов с поддержкой файлов\n * @param options Настройки базового клиента\n * @returns Функция для выполнения запросов\n */\nexport function fetchBaseQuery(options: Omit<FetchBaseQueryArgs, 'prepareHeaders'>) {\n const { baseUrl, timeout = 30000, fetchFn = fetch, credentials = 'same-origin' } = options\n\n return async <RequestResult, RequestParams extends Record<string, any>, E extends Error = Error>(\n args: RequestDefinition<RequestParams>,\n queryOptions: QueryOptions = {},\n headers: Headers,\n ): Promise<QueryResult<RequestResult, E>> => {\n const { path, method, body, query, responseFormat: reqResponseFormat } = args\n\n const { signal, timeout: requestTimeout = timeout, responseFormat: optResponseFormat } = queryOptions\n\n // Определяем формат ответа с приоритетом от options\n const responseFormat = optResponseFormat || reqResponseFormat\n\n // Строим URL с учетом api параметров\n const url = new URL(path.startsWith('http') ? path : `${baseUrl}${path}`)\n\n // Добавляем query-параметры в URL\n if (query) {\n Object.entries(query).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => url.searchParams.append(key, String(item)))\n } else {\n url.searchParams.append(key, String(value))\n }\n }\n })\n }\n\n // Если body это объект, конвертируем в JSON и устанавливаем Content-Type\n let serializedBody: string | FormData | Blob | undefined\n if (body !== undefined) {\n if (body instanceof FormData || body instanceof Blob) {\n serializedBody = body\n } else if (typeof body === 'object' && body !== null) {\n try {\n serializedBody = JSON.stringify(body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n } catch (error) {\n console.error('[API] Ошибка сериализации тела запроса', error)\n serializedBody = String(body)\n }\n } else {\n serializedBody = String(body)\n }\n }\n\n // Создаем таймаут если указан\n let timeoutId: number | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n if (requestTimeout) {\n timeoutId = window.setTimeout(() => {\n reject(new Error(`Превышено время ожидания запроса (${requestTimeout}мс)`))\n }, requestTimeout)\n }\n })\n\n try {\n // Выполняем запрос\n const fetchPromise = fetchFn(url.toString(), {\n method,\n headers,\n body: serializedBody,\n signal,\n credentials,\n })\n\n // Используем Promise.race для обработки таймаута\n const response = await Promise.race([fetchPromise, timeoutPromise])\n\n // Обрабатываем ответ\n const { data, error, fileMetadata } = await getResponseData<RequestResult, E>(response, responseFormat as ResponseFormat)\n\n // Формируем результат запроса\n const result: QueryResult<RequestResult, E> = {\n data,\n error,\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n fileDownloadResult: fileMetadata,\n }\n\n return result\n } catch (err) {\n // Обрабатываем ошибки сети или таймаута\n const error = err as Error\n console.error('[API] Ошибка выполнения запроса', error)\n\n // Формируем результат с ошибкой\n return {\n error: error as E,\n ok: false,\n status: 0,\n statusText: error.message,\n headers: new Headers(),\n }\n } finally {\n // Очищаем таймер в любом случае\n if (timeoutId) {\n window.clearTimeout(timeoutId)\n }\n }\n }\n}\n","/**\n * Создает объект с заголовками для кэширования на основе списка допустимых ключей\n * @param headers Заголовки запроса\n * @param cacheableHeaders Массив ключей заголовков, которые нужно включить в кэш\n * @returns Объект с отфильтрованными заголовками\n */\nexport function getCacheableHeaders(headers: Headers, cacheableHeaders: string[] = []): Record<string, string> {\n const result: Record<string, string> = {}\n\n if (!headers || cacheableHeaders.length === 0) {\n return result\n }\n\n // Проходим по всем ключам в cacheableHeaders\n cacheableHeaders.forEach((key) => {\n // Если заголовок существует, добавляем его в результат\n if (headers.has(key)) {\n result[key] = headers.get(key) || ''\n }\n })\n\n return result\n}\n","import { CreateApiClientOptions } from '../types/api.interface'\nimport { Endpoint as EndpointType, EndpointConfig, EndpointState, RequestResponseModify, RequestState } from '../types/endpoint.interface'\nimport { QueryOptions, QueryResult, Unsubscribe } from '../types/query.interface'\nimport { createUniqueId, headersToObject } from '../utils/api-helpers'\nimport { createHeaderContext } from '../utils/create-header-context'\nimport { createPrepareHeaders, prepareRequestHeaders } from '../utils/endpoint-headers'\nimport { fetchBaseQuery } from '../utils/fetch-base-query'\nimport { getCacheableHeaders } from '../utils/get-cacheable-headers'\nimport { QueryStorage } from './query-storage'\n\nexport class EndpointClass<RequestParams extends Record<string, any>, RequestResponse> implements EndpointType<RequestParams, RequestResponse> {\n private readonly endpointSubscribers = new Set<(state: EndpointState) => void>()\n\n /** Сколько раз был вызван метод request */\n fetchCounts: number = 0\n\n meta: EndpointType['meta'] = {\n cache: false,\n invalidatesTags: [],\n name: '',\n tags: [],\n }\n\n private readonly queryFunction: ReturnType<typeof fetchBaseQuery>\n\n /** Массив заголовков, которые нужно включить в ключ кэширования */\n private readonly cacheableHeaders: string[]\n\n private readonly prepareHeaders: ReturnType<typeof createPrepareHeaders>\n\n constructor(\n private readonly name: string,\n private readonly queryStorage: QueryStorage,\n private readonly configCurrentEndpoint: EndpointConfig<RequestParams, RequestResponse>,\n private readonly cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys'],\n private readonly globalCacheConfig: CreateApiClientOptions['cache'],\n private readonly baseQueryConfig: CreateApiClientOptions['baseQuery'],\n ) {\n // 1. Создаем функцию подготовки заголовков\n this.prepareHeaders = createPrepareHeaders(baseQueryConfig.prepareHeaders, configCurrentEndpoint.prepareHeaders)\n // 2. Создаем функцию исполнения запроса\n this.queryFunction = fetchBaseQuery({\n baseUrl: baseQueryConfig.baseUrl,\n fetchFn: baseQueryConfig.fetchFn,\n timeout: baseQueryConfig.timeout,\n credentials: baseQueryConfig.credentials,\n })\n // 3. Создаем массив тех заголовков, которые нужно включить в ключ кэширования\n this.cacheableHeaders = [...(cacheableHeaderKeys || []), ...(configCurrentEndpoint.includeCacheableHeaderKeys || [])].filter(\n (key) => !configCurrentEndpoint.excludeCacheableHeaderKeys?.includes(key),\n )\n // 4. Сохраняем информацию в meta\n this.meta.name = name\n this.meta.tags = configCurrentEndpoint.tags ?? this.meta.tags\n this.meta.invalidatesTags = configCurrentEndpoint.invalidatesTags ?? this.meta.invalidatesTags\n this.meta.cache = this.queryStorage.createCacheConfig(this.configCurrentEndpoint) ?? this.meta.cache\n }\n\n public request(params: RequestParams, options?: QueryOptions): RequestResponseModify<RequestResponse> {\n // 1. Подготовка и инициализация\n this.fetchCounts++\n const requestId = createUniqueId(this.name)\n const controller = new AbortController()\n const requestSubscribers = new Set<(state: RequestState<RequestResponse, RequestParams>) => void>()\n const currentState: RequestState<RequestResponse, RequestParams> = {\n status: 'idle',\n requestParams: params,\n headers: {},\n error: undefined,\n data: undefined,\n fromCache: false,\n }\n const headerContext = createHeaderContext({ requestParams: params }, options?.context || {})\n\n // 2. Создаем функции для управления состоянием\n const notifyRequestSubscribers = (newState: Partial<RequestState<RequestResponse, RequestParams>>) => {\n Object.assign(currentState, newState)\n requestSubscribers.forEach((cb) => {\n cb({ ...currentState })\n })\n }\n\n // 3. Создаем промис для метода wait()\n const waitPromise = new Promise<QueryResult<RequestResponse, Error>>(async (resolve, reject) => {\n try {\n // Формируем заголовки\n const headers = await prepareRequestHeaders(this.prepareHeaders, headerContext)\n // Получаем заголовки для кэширования\n const headersForCache = getCacheableHeaders(headers, options?.cacheableHeaderKeys ? options.cacheableHeaderKeys : this.cacheableHeaders)\n // Проверяем включено ли кэширование\n const shouldCache = this.queryStorage.shouldCache(this.configCurrentEndpoint, options)\n // Формируем ключ кэша\n const [cacheKey, cacheParams] = this.queryStorage.createCacheKey(this.name, { ...params, ...headersForCache })\n\n // 4. Проверяем кэш до установки loading\n let cachedResult: QueryResult<RequestResponse> | undefined\n if (shouldCache) {\n cachedResult = await this.queryStorage.getCachedResult<QueryResult<RequestResponse> | undefined>(cacheKey)\n }\n\n if (cachedResult) {\n // Есть данные в кэше - сразу переходим к success\n notifyRequestSubscribers({\n fromCache: true,\n status: 'success',\n data: cachedResult.data,\n error: undefined,\n headers: cachedResult.headers,\n requestParams: params,\n })\n resolve({\n ...cachedResult,\n fromCache: true,\n })\n } else {\n // Нет данных в кэше - устанавливаем loading и делаем запрос\n notifyRequestSubscribers({\n fromCache: false,\n status: 'loading',\n })\n\n // 5. Выполняем запрос\n const requestDefinition = this.configCurrentEndpoint.request(params, options?.context)\n const mergedOptions: QueryOptions = { ...options, signal: controller.signal }\n\n const response = await this.queryFunction<RequestResponse, RequestParams>(requestDefinition, mergedOptions, headers)\n\n // 6. Обрабатываем результат запроса\n if (response.ok) {\n const { headers, ...restResponse } = response\n // Сохраняем в кэш, если нужно\n if (shouldCache) {\n const currentCacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint)\n await this.queryStorage.setCachedResult(\n cacheKey,\n { ...restResponse, headers: headersToObject(headers) },\n currentCacheConfig,\n cacheParams ?? {},\n this.configCurrentEndpoint.tags ?? [],\n this.configCurrentEndpoint.invalidatesTags ?? [],\n )\n }\n\n // Оповещаем о success\n notifyRequestSubscribers({\n fromCache: false,\n status: 'success',\n data: response.data,\n error: undefined,\n headers: response.headers,\n requestParams: params,\n })\n\n // Уведомляем подписчиков эндпоинта\n this.endpointSubscribers.forEach((cb) => {\n const endpointState: EndpointState = {\n status: 'success',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: undefined,\n }\n cb(endpointState)\n })\n resolve({\n ...response,\n fromCache: false,\n })\n } else {\n // Оповещаем об ошибке\n notifyRequestSubscribers({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: response.error,\n headers: response.headers,\n requestParams: params,\n })\n\n // Уведомляем подписчиков эндпоинта\n this.endpointSubscribers.forEach((cb) => {\n const endpointState: EndpointState = {\n status: 'error',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: response.error,\n }\n cb(endpointState)\n })\n\n reject(response.error)\n }\n }\n } catch (error) {\n // Обрабатываем неожиданные ошибки\n notifyRequestSubscribers({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: error as Error,\n headers: undefined,\n requestParams: params,\n })\n reject(error)\n }\n })\n\n // 4. Возвращаем объект с методами управления запросом\n return {\n id: requestId,\n\n subscribe(listener, options = {}) {\n const { autoUnsubscribe = true } = options\n requestSubscribers.add(listener)\n listener(currentState)\n\n const unsubscribe = () => requestSubscribers.delete(listener)\n\n if (autoUnsubscribe) {\n waitPromise.finally(() => {\n unsubscribe()\n })\n }\n\n return unsubscribe\n },\n\n wait: () => waitPromise,\n\n waitWithCallbacks(handlers = {}) {\n const { idle, loading, success, error } = handlers\n\n this.subscribe(\n (state: RequestState<RequestResponse, RequestParams>) => {\n switch (state.status) {\n case 'idle':\n idle?.(state)\n break\n case 'loading':\n loading?.(state)\n break\n case 'success':\n success?.(state.data, state)\n break\n case 'error':\n error?.(state.error, state)\n break\n }\n },\n { autoUnsubscribe: true },\n )\n\n return waitPromise\n },\n\n abort: () => {\n if (controller && !controller.signal.aborted) {\n controller.abort()\n }\n },\n\n then: (onfulfilled, onrejected) => waitPromise.then(onfulfilled, onrejected),\n catch: (onrejected) => waitPromise.catch(onrejected),\n finally: (onfinally) => waitPromise.finally(onfinally),\n }\n }\n\n public subscribe(cb: (state: EndpointState) => void): Unsubscribe {\n this.endpointSubscribers.add(cb)\n\n // Создаем объект с текущей статистикой, соответствующий интерфейсу EndpointState\n const currentState: EndpointState = {\n status: 'idle',\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error: undefined,\n }\n\n // Вызываем callback с текущим состоянием\n cb(currentState)\n\n // Возвращаем функцию отписки\n return () => this.endpointSubscribers.delete(cb)\n }\n\n public reset() {\n this.fetchCounts = 0\n return Promise.resolve()\n }\n\n public destroy() {\n this.endpointSubscribers.clear()\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 { StorageKey, StorageKeyType } from './storage-key'\n\nexport interface CacheMetadata {\n createdAt: number\n updatedAt: number\n expiresAt: number\n tags?: string[]\n createdAtDateTime: string\n updatedAtDateTime: string\n expiresAtDateTime: string\n}\n\nexport interface CacheOptions {\n ttl?: number\n cleanup?: {\n enabled: boolean\n interval?: number\n }\n invalidateOnError?: boolean\n}\n\nexport interface CacheEntry<Data, Params extends Record<string, any> = any> {\n data: Data\n metadata: CacheMetadata\n params: Params\n}\n\nexport class CacheUtils {\n static createMetadata(ttl: number = 0, tags: string[] = []): CacheMetadata {\n const now = Date.now()\n const expiresAt = ttl > 0 ? now + ttl : Infinity\n\n return {\n createdAt: now,\n updatedAt: now,\n expiresAt,\n tags,\n createdAtDateTime: this.formatDateTime(now),\n updatedAtDateTime: this.formatDateTime(now),\n expiresAtDateTime: expiresAt === Infinity ? 'never' : this.formatDateTime(expiresAt),\n }\n }\n\n private static formatDateTime(timestamp: number): string {\n return new Date(timestamp).toISOString()\n }\n\n static isExpired(metadata: CacheMetadata): boolean {\n return Date.now() > metadata.expiresAt\n }\n\n static updateMetadata(metadata: CacheMetadata): CacheMetadata {\n return {\n ...metadata,\n updatedAt: Date.now(),\n }\n }\n\n static createKey(...parts: (string | number)[]): StorageKey {\n return new StorageKey(parts.join('_'))\n }\n\n static createApiKey(endpoint: string, params?: Record<string, any>): [StorageKeyType, Record<string, any> | undefined] {\n if (!params) return [new StorageKey(endpoint, true), params]\n\n const sortedParams = Object.entries(params)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=${v}`)\n .join('&')\n\n return [new StorageKey(`${endpoint}_${sortedParams}`, true), params]\n }\n\n // Функция для проверки, есть ли у записи определенные теги\n static hasAnyTag(metadata: CacheMetadata, tags: string[] = []): boolean {\n if (!metadata.tags || !tags.length) return false\n return tags.some((tag) => metadata.tags?.includes(tag))\n }\n}\n","import { IndexedDBStorage, IStorage, LocalStorage, MemoryStorage, StorageKeyType, StorageType } from '../../core/storage'\nimport { CacheEntry, CacheUtils } from '../../core/storage/utils/cache.util'\nimport { CacheConfig, CreateApiClientOptions } from '../types/api.interface'\nimport { EndpointConfig } from '../types/endpoint.interface'\nimport { QueryOptions } from '../types/query.interface'\n\n/**\n * Менеджер хранилища для API\n * Объединяет в себе функционал хранилища и управления кэшем\n */\nexport class QueryStorage {\n /** Экземпляр хранилища */\n private storage: IStorage | null = null\n\n private cleanupInterval: NodeJS.Timeout | number | null = null\n\n /** Настройки кэша по умолчанию */\n private defaultCacheOptions: Exclude<CacheConfig, boolean> = {\n ttl: 5 * 60 * 1000, // 5 минут по умолчанию\n cleanup: {\n enabled: true,\n interval: 10 * 60 * 1000, // 10 минут\n },\n invalidateOnError: true,\n }\n\n constructor(\n private readonly storageExternal: CreateApiClientOptions['storage'],\n private readonly globalCacheConfig: CreateApiClientOptions['cache'],\n ) {}\n\n public async initialize(): Promise<this> {\n // 1. Создаем хранилище\n await this.createStorage()\n // 2. Запускаем периодическую очистку, если это указано в настройках\n this.startCleanupInterval()\n\n return this\n }\n\n private async createStorage() {\n try {\n const s: IStorage = this.storageExternal\n\n await s.initialize()\n this.storage = s\n } catch (error) {\n console.error('Ошибка инициализации хранилища', error)\n throw error\n }\n }\n\n private startCleanupInterval(): void {\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval)\n this.cleanupInterval = null\n }\n\n // Получаем настройки очистки\n const cleanupConfig = typeof this.globalCacheConfig === 'object' ? this.globalCacheConfig.cleanup : this.defaultCacheOptions.cleanup\n\n // Запускаем интервал очистки, если он включен\n if (cleanupConfig?.enabled && cleanupConfig.interval) {\n this.cleanupInterval = setInterval(() => {\n this.cleanup().catch((err) => console.error('Ошибка при очистке кэша:', err))\n }, cleanupConfig.interval)\n }\n }\n\n /**\n * Получает экземпляр хранилища\n */\n public getStorage(): IStorage | null {\n return this.storage\n }\n\n /**\n * Создает ключ кэша для запроса с учетом заголовков\n * @param endpoint Имя эндпоинта\n * @param params Параметры запроса (все что посчитаем нужным)\n */\n public createCacheKey<CacheParams extends Record<string, any>>(endpoint: string, params: CacheParams) {\n return CacheUtils.createApiKey(endpoint, params)\n }\n\n /**\n * Получает результат запроса из кэша\n */\n public async getCachedResult<T>(cacheKey: StorageKeyType): Promise<T | undefined> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n const cachedEntry = await this.storage.get<CacheEntry<T>>(cacheKey)\n if (!cachedEntry) return undefined\n\n // Проверяем срок годности кэша\n if (CacheUtils.isExpired(cachedEntry.metadata)) {\n await this.storage.delete(cacheKey)\n return undefined\n }\n\n // Обновляем метаданные кэша (счетчик доступа, время обновления)\n const updatedEntry: CacheEntry<T> = {\n ...cachedEntry,\n metadata: CacheUtils.updateMetadata(cachedEntry.metadata),\n }\n await this.storage.set(cacheKey, updatedEntry)\n\n return cachedEntry.data\n }\n\n /**\n * Сохраняет результат запроса в кэш\n * @param cacheKey Ключ кэша\n * @param data Данные для кэширования\n * @param cacheOptions Метаданные\n * @param cacheParams Параметры которые влияли на созадние ключа\n * @param tags Тэги эндпоинта\n * @param invalidatesTags Тэги которые нужно инвалидировать\n */\n public async setCachedResult<T, CacheParams extends Record<string, any>>(\n cacheKey: StorageKeyType,\n data: T,\n cacheOptions: Exclude<CacheConfig, boolean>,\n cacheParams: CacheParams,\n tags: string[],\n invalidatesTags: string[],\n ): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n // Проверяем, нужно ли инвалидировать другие кэши по тегам\n if (invalidatesTags?.length) {\n await this.invalidateCacheByTags(invalidatesTags)\n }\n\n // Создаем метаданные кэша\n const cacheMetadata = CacheUtils.createMetadata(cacheOptions.ttl, tags)\n\n // Создаем запись кэша\n const cacheEntry: CacheEntry<T> = {\n data,\n metadata: cacheMetadata,\n params: cacheParams,\n }\n\n await this.storage.set(cacheKey, cacheEntry)\n }\n\n /**\n * Проверяет, должен ли запрос быть кэширован\n * @param endpointConfig Конфигурация эндпоинта\n * @param options Опции запроса\n * @returns true если запрос должен кэшироваться\n */\n public shouldCache(endpointConfig?: EndpointConfig, options?: QueryOptions) {\n // Если глобальный кэш отключен, возвращаем false\n if (this.globalCacheConfig === false) return false\n // Если эндпоинт явно отключает кэш, возвращаем false\n if (endpointConfig?.cache === false) return false\n // Если по какой то причине указали время кэша 0\n if (typeof endpointConfig?.cache === 'object' && endpointConfig?.cache.ttl === 0) return false\n // Если при вызове самого запроса явно указали НЕ кэшировать\n if (options?.disableCache === true) return false\n // Если настройки нигде не указаны - по умолчанию НЕ кэшируем\n if (this.globalCacheConfig === undefined && endpointConfig?.cache === undefined) return false\n\n return true\n }\n\n /**\n * Создает итоговую конфигурацию кэширования для конкретного эндпоинта\n * Объединяет глабальный конфиг с текущим\n * @param endpointConfig Конфигурация эндпоинта\n */\n public createCacheConfig(endpointConfig?: EndpointConfig) {\n // Создаем опции по умолчанию\n let resultConfig = this.defaultCacheOptions\n\n // Если в глобальном конфиге кэш передан как объект а не boolean - по умолчанию станет он\n if (typeof this.globalCacheConfig === 'object') {\n resultConfig = this.globalCacheConfig\n }\n // Если в настройках эндпоинта кэш как объект - дополняем этими параметрами итоговый объект кэша\n if (typeof endpointConfig?.cache === 'object') {\n const endpointCache = endpointConfig.cache\n resultConfig = {\n // @ts-ignore\n ...resultConfig,\n ...endpointCache,\n }\n }\n\n return resultConfig\n }\n\n /**\n * Инвалидирует кэш по тегам\n * @param tags Теги для инвалидации\n */\n public async invalidateCacheByTags(tags: string[]): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n const keys = await this.storage.keys()\n for (const key of keys) {\n const cachedEntry = await this.storage.get<CacheEntry<any>>(key)\n if (cachedEntry && CacheUtils.hasAnyTag(cachedEntry.metadata, tags)) {\n await this.storage.delete(key)\n }\n }\n }\n\n /**\n * Инвалидирует кэш по ключу\n * @param cacheKey Ключ кэша\n */\n public async invalidateCache(cacheKey: StorageKeyType): Promise<void> {\n if (!this.storage) throw new Error('Хранилище не инициализировано')\n\n await this.storage.delete(cacheKey)\n }\n\n /**\n * Выполняет очистку всех просроченных записей кэша\n */\n public async cleanup(): Promise<void> {\n if (!this.storage) {\n throw new Error('Хранилище не инициализировано')\n }\n\n const keys = await this.storage.keys()\n for (const key of keys) {\n const value = await this.storage.get<CacheEntry<any>>(key)\n if (value && CacheUtils.isExpired(value.metadata)) {\n await this.storage.delete(key)\n }\n }\n }\n\n /**\n * Уничтожает хранилище и освобождает ресурсы\n */\n public async destroy(): Promise<void> {\n // Останавливаем интервал очистки\n if (this.cleanupInterval) {\n window.clearInterval(this.cleanupInterval)\n this.cleanupInterval = null\n }\n\n // Очищаем хранилище\n if (this.storage) {\n await this.storage.destroy()\n this.storage = null\n }\n }\n}\n","import { EndpointClass } from './components/endpoint'\nimport { QueryStorage } from './components/query-storage'\nimport { CreateApiClientOptions, ExtractParamsType, ExtractResultType } from './types/api.interface'\nimport { CreateEndpoint, Endpoint as EndpointType, EndpointConfig } from './types/endpoint.interface'\nimport { QueryOptions, QueryResult } from './types/query.interface'\nimport { apiLogger } from './utils/api-helpers'\n\n// Тип для извлечения типов из функции endpoints\ntype EndpointsResult<F> = F extends (create: any) => Promise<infer R> ? R : never\n\nexport class ApiClient<EndpointsFn extends (create: CreateEndpoint) => Promise<Record<string, EndpointConfig<any, any>>>> {\n /** Хранилище запросов */\n // @ts-ignore\n private queryStorage: QueryStorage\n\n private readonly cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys']\n\n private readonly globalCacheConfig: CreateApiClientOptions['cache']\n\n private readonly baseQueryConfig: CreateApiClientOptions['baseQuery']\n\n private readonly storageExternal: CreateApiClientOptions['storage']\n\n private readonly createEndpoints: EndpointsFn\n\n /** Реестр эндпоинтов */\n private endpoints: {\n [K in keyof EndpointsResult<EndpointsFn>]?: EndpointType<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>\n } = {}\n\n constructor(options: Omit<CreateApiClientOptions, 'endpoints'> & { endpoints: EndpointsFn }) {\n // Сохраняем переданные параметры\n this.cacheableHeaderKeys = options.cacheableHeaderKeys\n this.globalCacheConfig = options.cache\n this.baseQueryConfig = options.baseQuery\n this.storageExternal = options.storage\n this.createEndpoints = options.endpoints\n }\n\n public async init(): Promise<this> {\n // 1. Создаем кэшированное хранилище запросов\n this.queryStorage = await new QueryStorage(this.storageExternal, this.globalCacheConfig).initialize()\n\n // 2. Создаем эндпоинты\n await this.initializeEndpoints()\n\n return this\n }\n\n private async initializeEndpoints() {\n // Получаем конфигурацию будущих эндпоинтов\n const create: CreateEndpoint = <TParams extends Record<string, any>, TResult>(config: EndpointConfig<TParams, TResult>) => config\n // Создаем объект с конфигурациями для эндпоинтов\n const endpointsConfig = (await this.createEndpoints(create)) || {}\n\n // Создаем эндпоинты\n for (const [endpointKey, endpointConfig] of Object.entries(endpointsConfig)) {\n const key = endpointKey as keyof EndpointsResult<EndpointsFn>\n this.endpoints[key] = new EndpointClass(endpointKey, this.queryStorage, endpointConfig, this.cacheableHeaderKeys, this.globalCacheConfig, this.baseQueryConfig)\n }\n }\n\n /**\n * Получает все эндпоинты с улучшенной типизацией\n * @returns Типизированный объект эндпоинтов\n */\n public getEndpoints(): {\n [K in keyof EndpointsResult<EndpointsFn>]: EndpointType<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>\n } {\n return this.endpoints as any\n }\n\n /**\n * Выполняет запрос к API с типизацией и обработкой ошибок\n * @param endpointName Имя эндпоинта (с подсказками TypeScript)\n * @param params Параметры запроса (с типизацией)\n * @param options Опции запроса\n * @returns Promise с типизированным результатом запроса\n */\n public async request<K extends keyof EndpointsResult<EndpointsFn> & string>(\n endpointName: K,\n params: ExtractParamsType<EndpointsResult<EndpointsFn>[K]>,\n options?: QueryOptions,\n ): Promise<QueryResult<ExtractResultType<EndpointsResult<EndpointsFn>[K]>, Error>> {\n const endpoints = this.getEndpoints()\n const endpoint = endpoints[endpointName]\n\n if (!endpoint) {\n throw new Error(`Эндпоинт ${String(endpointName)} не найден`)\n }\n\n try {\n const stateRequest = endpoint.request(params, options)\n return await stateRequest.wait()\n } catch (error) {\n apiLogger.error(`Ошибка запроса к ${String(endpointName)}`, { error, params })\n throw error\n }\n }\n\n public async destroy() {\n // 1. Сначала уничтожаем каждый эндпоинт\n await Promise.all(\n Object.values(this.endpoints).map(async (endpoint) => {\n endpoint.destroy()\n return Promise.resolve()\n }),\n )\n\n // 2. Очищаем коллекцию эндпоинтов\n this.endpoints = {}\n // 3. Уничтожаем хранилище\n await this.queryStorage.destroy()\n }\n}\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","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","import { Observable, Subject } from 'rxjs'\n\nimport type { IStorage } from '../../core'\nimport { TypedAction } from '../effects'\n\n/**\n * Расширенное API для middleware\n */\nexport interface EnhancedMiddlewareAPI<T extends Record<string, any>> {\n // Базовые возможности\n getState: () => Promise<T>\n dispatch: (action: Action) => Promise<any>\n\n // Доступ к хранилищу напрямую\n storage: IStorage<T>\n\n // Доступ к потоку действий\n actions$: Observable<Action>\n\n // Доступ к зарегистрированным действиям\n actions: Record<string, DispatchFunction<any, any>>\n\n // Доступ к зарегистрированным наблюдателям\n watchers: Record<string, WatcherFunction<any>>\n\n // Вспомогательные методы\n findActionByType: (actionType: string) => DispatchFunction<any, any> | undefined\n findWatcherByType: (actionType: string) => WatcherFunction<any> | undefined\n}\n\n/**\n * Расширенное определение middleware\n */\nexport interface EnhancedMiddleware<T extends Record<string, any> = any> {\n (api: EnhancedMiddlewareAPI<T>): (next: (action: Action) => Promise<any>) => (action: Action) => Promise<any>\n}\n\n/**\n * Базовая структура действия\n */\nexport interface Action<T = unknown> {\n type: string\n payload?: T\n meta?: Record<string, any>\n}\n\n// Параметры исполнения функции действия\ninterface ActionExecutionOptions {\n // Веб-воркер для выполнения действия\n worker?: Worker\n // Функция мемоизации\n memoize?: (currentArgs: any[], previousArgs: any[], previousResult: any) => boolean\n}\n\n/**\n * Параметры для создания действия\n */\nexport interface ActionDefinition<TParams, TResult> {\n /** Тип действия для идентификации в потоке и эффектах */\n type: string\n /** Функция, выполняющая действие и возвращающая результат (payload) */\n action: (params: TParams) => Promise<TResult> | TResult\n /** Дополнительные метаданные (опционально) */\n meta?: Record<string, any>\n}\n\n/**\n * Определение типа для watcher'а\n */\ninterface WatcherDefinition<T, R> {\n type: string\n selector: (state: T) => R\n meta?: Record<string, any>\n // Опционально - функция для определения, изменилось ли значение\n shouldTrigger?: (prev: R | undefined, current: R) => boolean\n}\n\n/**\n * Тип для функции watcher\n */\nexport interface WatcherFunction<R> {\n (): Observable<TypedAction<R>>\n actionType: string\n meta?: Record<string, any>\n unsubscribe: VoidFunction\n}\n\n/**\n * Расширенный тип для функции настройки действий с поддержкой дополнительных утилит\n */\nexport type ActionsSetupWithUtils<T extends Record<string, unknown>> = (\n storage: IStorage<T>,\n utils: {\n createAction: ActionCreatorFactory\n createWatcher: <R>(config: WatcherDefinition<T, R>) => WatcherFunction<R>\n },\n) => Record<string, DispatchFunction<any, any> | WatcherFunction<any>>\n\n/**\n * Расширенная функция диспетчеризации\n */\nexport interface DispatchFunction<TParams, TResult> {\n /** Функция для вызова действия с параметрами */\n (params: TParams): Promise<TResult>\n /** Тип действия для использования в эффектах */\n actionType: string\n /** Метаданные действия */\n meta?: Record<string, any>\n /** Внутренний тип для идентификации */\n _type?: 'dispatch' | 'watchers'\n}\n\n/**\n * Тип для фабрики создателей действий\n */\ntype ActionCreatorFactory = <TParams, TResult>(config: ActionDefinition<TParams, TResult>, executionOptions?: ActionExecutionOptions) => DispatchFunction<TParams, TResult>\n\n/**\n * Тип для функции настройки действий\n */\nexport type ActionsSetup<T extends Record<string, unknown>> = (create: ActionCreatorFactory, storage: IStorage<T>) => Record<string, DispatchFunction<any, any>>\n\n/**\n * Извлекает тип результата из функции диспетчера\n */\nexport type ExtractResultType<T> = T extends DispatchFunction<any, infer R> ? R : never\n\n/**\n * Извлекает типы из функции настройки действий\n */\nexport type ActionsResult<F> = F extends (create: ActionCreatorFactory, storage: any, ...args: any[]) => infer R ? R : Record<string, DispatchFunction<any, any>>\n\n/**\n * Типизированный объект действий\n */\nexport type DispatchActions<T> = {\n [K in keyof T]: T[K] extends DispatchFunction<any, any> ? T[K] : never\n}\n\n/**\n * Типизированный объект watchers\n */\nexport type WatcherActions<T> = {\n [K in keyof T]: T[K] extends WatcherFunction<any> ? T[K] : never\n}\n\n/**\n * Параметры для Dispatcher\n */\ninterface DispatcherOptions<T extends Record<string, any>> {\n // Хранилище - обязательный параметр\n storage: IStorage<T>\n // Опциональные параметры\n worker?: Worker\n // DispatcherMiddleware для обработки действий\n middlewares?: EnhancedMiddleware<T>[]\n}\n\n/**\n * Интерфейс для API middleware\n */\nexport interface DispatcherMiddlewareAPI<T extends Record<string, any>> {\n getState: () => Promise<T>\n dispatch: (action: Action) => Promise<any>\n}\n\n/**\n * Интерфейс для middleware\n */\nexport interface DispatcherMiddleware<T extends Record<string, any> = any> {\n (api: DispatcherMiddlewareAPI<T>): (next: (action: Action) => Promise<any>) => (action: Action) => Promise<any>\n}\n\n/**\n * Класс Dispatcher для интеграции хранилищ с реактивной системой\n */\nexport class Dispatcher<T extends Record<string, any>, TActionsFn extends ActionsSetupWithUtils<T> = ActionsSetupWithUtils<T>> {\n // Поток действий\n private actions$ = new Subject<Action>()\n\n // Публичный Observable для действий\n public readonly actions: Observable<Action> = this.actions$.asObservable()\n\n // Методы диспетчеризации действий с типизацией\n public dispatch: Record<string, DispatchFunction<any, any>> = {}\n\n // Watcher'ы для реактивной подписки на изменения\n public watchers: Record<string, WatcherFunction<any>> = {}\n\n // Ссылка на хранилище\n private storage: IStorage<T>\n\n // Только один массив для хранения инициализированных middleware\n private middlewareFunctions: Array<(next: (action: Action) => Promise<any>) => (action: Action) => Promise<any>> = []\n\n // API для инициализации middleware\n private middlewareAPI: EnhancedMiddlewareAPI<T>\n\n /**\n * Создает новый экземпляр Dispatcher\n */\n constructor(private options: DispatcherOptions<T>) {\n this.storage = options.storage\n\n // Создаем API для middleware сразу\n this.middlewareAPI = {\n getState: () => this.storage.getState(),\n dispatch: async (action: Action) => {\n this.actions$.next(action)\n return action.payload\n },\n storage: this.storage,\n actions$: this.actions,\n actions: this.dispatch,\n watchers: this.watchers,\n findActionByType: (type) => this.findActionByType(type),\n findWatcherByType: (type) => this.findWatcherByType(type),\n }\n\n // Если есть middleware в options, добавляем их\n if (options.middlewares && options.middlewares.length > 0) {\n this.use(...options.middlewares)\n }\n }\n\n /**\n * Добавляет middleware в цепочку обработки\n */\n public use(...middlewares: EnhancedMiddleware<T>[]): this {\n // Инициализируем каждый middleware и добавляем только инициализированную версию\n for (let i = 0; i < middlewares.length; i++) {\n try {\n // Инициализируем middleware с API\n const initializedMiddleware = middlewares[i](this.middlewareAPI)\n this.middlewareFunctions.push(initializedMiddleware)\n } catch (error) {\n console.error(`Error initializing middleware [${i}]:`, error)\n }\n }\n return this\n }\n\n /**\n * Получает все действия с улучшенной типизацией\n */\n public getActions(): ActionsResult<TActionsFn> {\n return this.dispatch as ActionsResult<TActionsFn>\n }\n\n /**\n * Получает типизированные действия диспетчера\n */\n public getTypedDispatch<A extends Record<string, any>>(): DispatchActions<A> {\n return this.dispatch as DispatchActions<A>\n }\n\n /**\n * Получает типизированные watcher'ы\n */\n public getTypedWatchers<A extends Record<string, any>>(): WatcherActions<A> {\n return this.watchers as WatcherActions<A>\n }\n\n /**\n * Находит действие по типу\n */\n public findActionByType(actionType: string): DispatchFunction<any, any> | undefined {\n return Object.values(this.dispatch).find((action) => {\n return action.actionType.split(`[${this.storage.name}]`)[1] === actionType\n })\n }\n\n /**\n * Находит наблюдатель по типу\n */\n public findWatcherByType(actionType: string): WatcherFunction<any> | undefined {\n return Object.values(this.watchers).find((watcher) => watcher.actionType === actionType)\n }\n\n /**\n * Создает действие\n */\n public createAction<TParams, TResult>(actionConfig: ActionDefinition<TParams, TResult>, executionOptions?: ActionExecutionOptions): DispatchFunction<TParams, TResult> {\n const actionType = `[${this.storage.name}]${actionConfig.type}`\n\n // Для мемоизации храним последние аргументы и результат\n let lastArgs: TParams[] | null = null\n let lastResult: TResult | null = null\n\n // Создаем функцию диспетчеризации\n const dispatchFn = async (params: TParams): Promise<TResult> => {\n const args = [params] as TParams[]\n\n // Проверяем мемоизацию\n if (executionOptions?.memoize && lastArgs && lastResult) {\n if (executionOptions.memoize(args, lastArgs, lastResult)) {\n return lastResult\n }\n }\n\n // Создаем объект действия\n const actionObject: Action<TResult> = {\n type: actionType,\n meta: actionConfig.meta,\n }\n\n // Применяем middleware цепочку\n let result: TResult\n\n if (this.middlewareFunctions.length > 0) {\n // Базовая функция выполнения действия\n // Строим цепочку middleware в обратном порядке\n let chain = async (action: Action): Promise<TResult> => {\n if (executionOptions?.worker) {\n return this.executeInWorker(executionOptions.worker, actionType, args, actionConfig.action)\n } else {\n return Promise.resolve(actionConfig.action(params))\n }\n }\n\n // Проходим по middleware в обратном порядке\n // Важно: сначала создаем всю цепочку, затем выполняем\n for (let i = this.middlewareFunctions.length - 1; i >= 0; i--) {\n const currentMiddleware = this.middlewareFunctions[i]\n const nextChain = chain // Сохраняем предыдущую цепочку\n\n // Создаем новую цепочку, которая вызывает текущий middleware,\n // передавая предыдущую цепочку как функцию next\n chain = async (action: Action) => {\n // Создаем функцию next для передачи в middleware\n const next = async (nextAction: Action) => nextChain(nextAction)\n\n // Получаем обработчик действия и сразу вызываем его\n return currentMiddleware(next)(action)\n }\n }\n\n // Выполняем действие через цепочку middleware\n result = await chain(actionObject)\n } else {\n // Выполняем действие напрямую без middleware\n if (executionOptions?.worker) {\n result = await this.executeInWorker(executionOptions.worker, actionType, args, actionConfig.action)\n } else {\n result = await actionConfig.action(params)\n }\n }\n\n // Обновляем объект действия результатом\n actionObject.payload = result\n\n // Сохраняем аргументы и результат для мемоизации\n lastArgs = [...args]\n lastResult = result\n\n // Отправляем информацию о действии в поток\n this.actions$.next(actionObject)\n\n return result\n }\n\n dispatchFn._type = 'dispatch'\n // Добавляем тип действия как свойство функции\n Object.defineProperty(dispatchFn, 'actionType', {\n value: actionType,\n writable: false,\n enumerable: true,\n })\n\n // Добавляем метаданные, если они есть\n if (actionConfig.meta) {\n Object.defineProperty(dispatchFn, 'meta', {\n value: actionConfig.meta,\n writable: false,\n enumerable: true,\n })\n }\n\n return dispatchFn as DispatchFunction<TParams, TResult>\n }\n /**\n * Создает watcher для отслеживания изменений в хранилище\n */\n public createWatcher<R>(config: WatcherDefinition<T, R>): WatcherFunction<R> {\n // Логика остается без изменений\n const actionType = `[${this.storage.name}]${config.type}`\n\n // Создаем Subject для этого watcher'а\n const subject = new Subject<TypedAction<R>>()\n\n // Предыдущее значение для сравнения\n let prevValue: R | undefined\n\n // Подписываемся на изменения состояния\n const unsubscribe = this.storage.subscribe(config.selector, (value: R) => {\n // Проверяем, нужно ли генерировать событие\n if (!config.shouldTrigger || config.shouldTrigger(prevValue, value)) {\n // Создаем действие\n const action: TypedAction<R> = {\n type: actionType,\n payload: value,\n meta: config.meta,\n }\n\n // Отправляем в основной поток действий\n this.actions$.next(action)\n\n // Отправляем в поток этого watcher'а\n subject.next(action)\n\n // Обновляем предыдущее значение\n prevValue = value\n }\n })\n\n // Создаем функцию watcher'а\n const watcherFn = () => subject.asObservable()\n watcherFn._type = 'watchers'\n // Добавляем свойства\n Object.defineProperty(watcherFn, 'actionType', {\n value: actionType,\n writable: false,\n enumerable: true,\n })\n\n if (config.meta) {\n Object.defineProperty(watcherFn, 'meta', {\n value: config.meta,\n writable: false,\n enumerable: true,\n })\n }\n\n // Добавляем метод для отписки\n Object.defineProperty(watcherFn, 'unsubscribe', {\n value: unsubscribe,\n writable: false,\n enumerable: true,\n })\n\n //@ts-ignore\n return watcherFn as WatcherFunction<R>\n }\n\n /**\n * Выполняет действие в worker\n */\n private async executeInWorker<TParams, TResult>(\n worker: Worker,\n actionType: string,\n args: TParams[],\n fallbackAction?: (params: TParams) => Promise<TResult> | TResult,\n ): Promise<TResult> {\n // Логика остается без изменений\n return new Promise((resolve, reject) => {\n const requestId = `${actionType}_${Date.now()}_${Math.random()}`\n\n const handleMessage = (event: MessageEvent) => {\n if (event.data.requestId === requestId) {\n worker.removeEventListener('message', handleMessage)\n\n if (event.data.error) {\n reject(new Error(event.data.error))\n } else {\n resolve(event.data.result)\n }\n }\n }\n\n worker.addEventListener('message', handleMessage)\n\n worker.postMessage({\n type: actionType,\n args,\n requestId,\n })\n\n // Опционально: таймаут\n setTimeout(() => {\n worker.removeEventListener('message', handleMessage)\n reject(new Error(`Worker execution timeout for action: ${actionType}`))\n }, 30000) // 30 секунд таймаут\n })\n }\n}\n\n/**\n * Функция для создания типизированного диспетчера\n */\nexport function createDispatcher<TState extends Record<string, any>, TActions extends ActionsSetupWithUtils<TState>>(\n options: DispatcherOptions<TState>,\n actionsSetup: TActions,\n): Dispatcher<TState, TActions> & {\n dispatch: DispatchActions<ReturnType<TActions>>\n watchers: WatcherActions<ReturnType<TActions>>\n} {\n // Создаем экземпляр диспетчера\n const dispatcher = new Dispatcher<TState, TActions>(options)\n\n // Вызываем функцию настройки действий с обновленной структурой аргументов\n const actions = actionsSetup(options.storage, {\n createAction: (actionConfig, executionOptions) => dispatcher.createAction(actionConfig, executionOptions),\n createWatcher: (config) => dispatcher.createWatcher(config),\n })\n\n // Регистрируем все созданные объекты в соответствующих коллекциях\n for (const [key, fn] of Object.entries(actions)) {\n if (typeof fn === 'function') {\n const type = (fn as any)._type\n // @ts-ignore\n dispatcher[type][key] = fn\n }\n }\n\n return dispatcher as Dispatcher<TState, TActions> & {\n dispatch: DispatchActions<ReturnType<TActions>>\n watchers: WatcherActions<ReturnType<TActions>>\n }\n}\nexport type CreateDispatcherType = ReturnType<typeof createDispatcher>\n","// Определяем типы для переводов и опций\nimport type { EnhancedMiddleware } from '../dispatcher.module'\n\ninterface LoggerTranslations {\n action: string\n prevState: string\n nextState: string\n duration: string\n error: string\n diff: string\n changesCount: string\n showFullState: string\n}\n\ninterface LoggerColors {\n title: string\n prevState: string\n fullState: string\n action: string\n nextState: string\n error: string\n diff: string\n}\n\ninterface LoggerOptions {\n collapsed?: boolean\n duration?: boolean\n diff?: boolean\n showFullState?: boolean\n translations?: Partial<LoggerTranslations>\n colors?: Partial<LoggerColors>\n}\n\n// Функция для вычисления разницы между двумя объектами состояния\nfunction getStateDiff(prevState: any, nextState: any): { [key: string]: any } {\n const diff: { [key: string]: any } = {}\n\n // Проверяем изменения в свойствах верхнего уровня\n const allKeys = [...new Set([...Object.keys(prevState), ...Object.keys(nextState)])]\n\n allKeys.forEach((key) => {\n // Если ключ существует в обоих состояниях\n if (key in prevState && key in nextState) {\n // Если это объекты, рекурсивно проверяем их\n if (\n typeof prevState[key] === 'object' &&\n prevState[key] !== null &&\n typeof nextState[key] === 'object' &&\n nextState[key] !== null &&\n !Array.isArray(prevState[key]) &&\n !Array.isArray(nextState[key])\n ) {\n const nestedDiff = getStateDiff(prevState[key], nextState[key])\n if (Object.keys(nestedDiff).length > 0) {\n diff[key] = nestedDiff\n }\n }\n // Для массивов и примитивов просто сравниваем значения\n else if (JSON.stringify(prevState[key]) !== JSON.stringify(nextState[key])) {\n diff[key] = { PREV: prevState[key], NEXT: nextState[key] }\n }\n }\n // Если ключ существует только в предыдущем состоянии\n else if (key in prevState) {\n diff[key] = { PREV: prevState[key], NEXT: undefined }\n }\n // Если ключ существует только в новом состоянии\n else {\n diff[key] = { PREV: undefined, NEXT: nextState[key] }\n }\n })\n\n return diff\n}\n\nexport const loggerDispatcherMiddleware = <State extends Record<string, any>>(options: LoggerOptions = {}): EnhancedMiddleware<State> => {\n const defaultTranslations = {\n action: 'Действие',\n prevState: 'Предыдущее состояние',\n nextState: 'Следующее состояние',\n duration: 'Длительность',\n error: 'Ошибка в действии',\n diff: 'Изменения',\n changesCount: 'Количество изменений',\n showFullState: 'Полное состояние',\n }\n\n const defaultOptions = {\n collapsed: false,\n duration: true,\n diff: false,\n showFullState: true, // Показывать полное состояние по умолчанию\n translations: defaultTranslations,\n colors: {\n title: '#3498db',\n prevState: '#9E9E9E',\n fullState: '#008a15',\n action: '#03A9F4',\n nextState: '#4CAF50',\n error: '#F20404',\n diff: '#9C27B0',\n },\n }\n\n // Объединяем пользовательские настройки с настройками по умолчанию\n const mergedOptions = {\n ...defaultOptions,\n ...options,\n // Объединяем переводы отдельно, чтобы позволить частичное переопределение\n translations: {\n ...defaultTranslations,\n ...(options.translations || {}),\n },\n // Объединяем цвета отдельно, чтобы позволить частичное переопределение\n colors: {\n ...defaultOptions.colors,\n ...(options.colors || {}),\n },\n }\n\n const { collapsed, duration, colors, translations } = mergedOptions\n\n return (api) => (next) => async (action) => {\n // Собираем информацию перед выполнением\n const started = Date.now()\n const prevState = await api.getState()\n\n // Выполняем действие без группировки логов\n try {\n // Выполняем действие\n const result = await next(action)\n\n // Собираем информацию после выполнения\n const nextState = await api.getState()\n const ended = Date.now()\n const time = ended - started\n\n // Теперь выводим всю информацию в группе\n const title = `${action.type}`\n const groupMethod = collapsed ? console.groupCollapsed : console.group\n\n groupMethod(`%c ${title}`, `color: ${colors.title}; font-weight: bold`)\n\n // Выводим информацию о действии\n console.log(`%c ${translations.action}:`, `color: ${colors.action}; font-weight: bold`, action)\n\n // Если включена опция diff, вычисляем и показываем изменения\n if (mergedOptions.diff) {\n const stateDiff = getStateDiff(prevState, nextState)\n const changesCount = Object.keys(stateDiff).length\n\n console.log(`%c ${translations.diff} (${translations.changesCount}: ${changesCount}):`, `color: ${colors.diff}; font-weight: bold`, stateDiff)\n }\n\n // Если showFullState включен, показываем полные состояния\n if (mergedOptions.showFullState) {\n // Создаем подгруппу для полного состояния\n console.groupCollapsed(`%c ${translations.showFullState}`, `color: ${colors.fullState}; font-weight: bold`)\n console.log(`%c ${translations.prevState}:`, `color: ${colors.prevState}; font-weight: bold`, prevState)\n console.log(`%c ${translations.nextState}:`, `color: ${colors.nextState}; font-weight: bold`, nextState)\n console.groupEnd()\n }\n\n if (duration) {\n console.log(`%c ${translations.duration}: %c ${time}ms`, 'font-weight: bold', 'color: #4CAF50')\n }\n\n console.groupEnd()\n\n return result\n } catch (error) {\n // В случае ошибки логируем её отдельно, не в группе\n console.error(`%c ${translations.error}:`, `color: ${colors.error}; font-weight: bold`, action.type, error)\n\n // Пробрасываем ошибку дальше\n throw error\n }\n }\n}\n","import { combineLatest, merge, Observable, of, OperatorFunction, pipe, Subject } from 'rxjs'\nimport { catchError, filter, map, share, switchMap, take, withLatestFrom } from 'rxjs/operators'\n\nimport { IStorage } from '../../core'\nimport { Action, ActionsResult, Dispatcher, DispatchFunction, ExtractResultType, WatcherFunction } from '../dispatcher'\nimport { ChunkRequestConsistent, chunkRequestConsistent, ChunkRequestParallel, chunkRequestParallel } from './utils'\n\n/**\n * Тип действия с типизированным payload\n */\nexport interface TypedAction<P> extends Action<P> {\n type: string\n payload: P\n}\n\n/**\n * Тип для внешних состояний\n */\nexport type ExternalStates = Record<string, Observable<any>>\n\n/**\n * Тип для базового эффекта без доступа к состоянию\n */\nexport type EffectBase<TDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>, TServices extends Record<string, any> = Record<string, never>> = (\n action$: Observable<Action>,\n dispatchers: TDispatchers,\n services: TServices,\n) => Observable<unknown>\n\n/**\n * Тип для эффекта с доступом к состоянию и конфигурации - это основной тип, который используется по умолчанию\n */\nexport type Effect<\n TState extends Record<string, any> = any,\n TDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> = (\n action$: Observable<Action>,\n state$: Observable<TState>,\n externalStates: TExternalStates,\n dispatchers: TDispatchers,\n services: TServices,\n config: TConfig,\n) => Observable<unknown>\n\n/**\n * Тип для получения типов действий диспетчера\n */\nexport type DispatcherActions<T> = T extends Dispatcher<any, infer A> ? ActionsResult<A> : Record<string, DispatchFunction<any, any>>\n\n/**\n * Конфигурация для валидации в validateMap\n */\nexport interface ValidateConfig {\n conditions: boolean[]\n skipAction: (() => any) | any | ((() => any) | any)[]\n}\n\n/**\n * Утилиты для запросов в validateMap\n */\nexport interface ValidateMapRequestUtils {\n chunkRequest: ChunkRequestParallel\n chunkRequestConsistent: ChunkRequestConsistent\n}\n\n/**\n * Оператор для фильтрации действий по типу с сохранением типа payload\n */\nexport function ofType<T extends DispatchFunction<any, any> | WatcherFunction<any>>(\n actionFn: T,\n): OperatorFunction<Action, TypedAction<T extends WatcherFunction<infer R> ? R : ExtractResultType<T>>> {\n const { actionType } = actionFn\n\n if (!actionType) {\n console.warn('ofType: Action function does not have actionType property', actionFn)\n return filter(() => false) as any\n }\n\n // Определяем тип payload в зависимости от типа функции\n type PayloadType = T extends WatcherFunction<infer R> ? R : ExtractResultType<T>\n\n // Улучшенная реализация с явными типами\n return (source$: Observable<Action>): Observable<TypedAction<PayloadType>> => {\n return source$.pipe(filter((action): action is TypedAction<PayloadType> => action !== undefined && action.type === actionType))\n }\n}\n\n/**\n * Оператор для фильтрации действий по нескольким типам с объединением типов payload\n * @param actionFns Массив функций действий\n */\nexport function ofTypes<T extends DispatchFunction<any, any>[]>(actionFns: [...T]): OperatorFunction<Action, TypedAction<ExtractResultType<T[number]>>> {\n // Получаем типы действий\n const actionTypes = actionFns.map((fn) => fn.actionType).filter(Boolean)\n\n if (actionTypes.length === 0) {\n console.warn('ofTypes: No valid action types found in array', actionFns)\n return filter(() => false) as OperatorFunction<Action, TypedAction<ExtractResultType<T[number]>>>\n }\n\n // Union тип для payload из всех действий\n type CombinedPayloadType = ExtractResultType<T[number]>\n\n // Улучшенная реализация с явными типами\n return (source$: Observable<Action>): Observable<TypedAction<CombinedPayloadType>> => {\n return source$.pipe(filter((action): action is TypedAction<CombinedPayloadType> => action !== undefined && actionTypes.includes(action.type)))\n }\n}\n\n/**\n * Оператор для ожидания выполнения всех указанных действий\n * @param actionFns Массив функций действий\n */\nexport function ofTypesWaitAll<T extends DispatchFunction<any, any>[]>(actionFns: [...T]) {\n return (source$: Observable<Action>): Observable<{ [K in keyof T]: TypedAction<ExtractResultType<T[K]>> }> => {\n // Создаем потоки для каждого типа действия\n const actionTypes = actionFns.map((fn) => fn.actionType).filter(Boolean)\n\n if (actionTypes.length === 0) {\n console.warn('ofTypesWaitAll: No valid action types found in array', actionFns)\n return of([]) as any\n }\n\n // Для каждого типа действия создаем поток,\n // который берет первое срабатывание\n const actionStreams = actionTypes.map((type, index) =>\n source$.pipe(\n filter((action) => action.type === type),\n take(1),\n map((action) =>\n // Сохраняем ассоциацию с индексом, чтобы соответствовать\n // порядку в исходном массиве actionFns\n ({ index, action }),\n ),\n ),\n )\n\n // Ждем, пока все потоки выдадут значения, и сортируем результаты\n // по индексу для сохранения порядка\n return combineLatest(actionStreams).pipe(\n map((results) => {\n // Сортируем по индексу\n results.sort((a, b) => a.index - b.index)\n // Убираем индекс и возвращаем только действия\n return results.map((r) => r.action) as any\n }),\n )\n }\n}\n\n/**\n * Создает Observable с выбранными данными из состояния\n * @param state$ Поток состояния\n * @param selectors Селекторы для выбора частей состояния\n * @returns Observable с массивом выбранных значений\n */\nexport function selectorMap<TState, TResults extends any[]>(\n state$: Observable<TState>,\n ...selectors: { [K in keyof TResults]: (state: TState) => TResults[K] }\n): Observable<TResults> {\n return state$.pipe(\n map((state) => {\n return selectors.map((selector) => selector(state)) as TResults\n }),\n )\n}\n\n/**\n * Создает именованный объект вместо массива\n * @param state$ Поток состояния\n * @param selectors Объект с селекторами\n * @returns Observable с объектом выбранных значений\n */\nexport function selectorObject<TState, TResult extends Record<string, any>>(\n state$: Observable<TState>,\n selectors: { [K in keyof TResult]: (state: TState) => TResult[K] },\n): Observable<TResult> {\n return state$.pipe(\n map((state) => {\n const result = {} as TResult\n for (const [key, selector] of Object.entries(selectors)) {\n result[key as keyof TResult] = selector(state)\n }\n return result\n }),\n )\n}\n\n/**\n * Оператор validateMap для валидации данных и условного вызова API\n */\nexport function validateMap<T, TResult = any>({\n validator,\n apiCall,\n}: {\n validator?: (value: T) => ValidateConfig\n apiCall: (value: T, utils: ValidateMapRequestUtils) => Observable<TResult>\n}): OperatorFunction<T, any> {\n return pipe(\n switchMap((pipeData) => {\n /**\n * Функция вызова API-метода\n */\n const callApi = () =>\n apiCall(pipeData, {\n chunkRequest: chunkRequestParallel,\n chunkRequestConsistent: chunkRequestConsistent,\n })\n\n /**\n * Если валидацию не используем - сразу вызываем запрос\n */\n if (!validator) return callApi()\n\n const validateConfig = validator(pipeData)\n const { conditions, skipAction } = validateConfig\n const conditionMet = conditions.every(Boolean)\n\n /**\n * Если валидация не пройдена - вызываем экшн сброса\n */\n if (!conditionMet) {\n if (Array.isArray(skipAction)) {\n // eslint-disable-next-line no-unsafe-optional-chaining\n return of(...skipAction?.filter(Boolean).map((action) => (typeof action === 'function' ? action() : action)))\n }\n return of(typeof skipAction === 'function' ? skipAction() : skipAction)\n }\n\n return callApi()\n }),\n )\n}\n\n/**\n * Класс для управления эффектами с поддержкой доступа к состоянию и конфигурации\n * Основной класс, который следует использовать\n */\nexport class EffectsModule<\n TState extends Record<string, any> = any,\n TDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> {\n private effects: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>[] = []\n private subscriptions: Array<{ unsubscribe: VoidFunction }> = []\n private running = false\n private action$ = new Subject<Action>()\n\n /**\n * Поток состояния\n */\n public readonly state$: Observable<TState>\n\n /**\n * Создает модуль эффектов с доступом к состоянию, внешним состояниям и конфигурации\n * @param storage Хранилище состояния\n * @param externalStates Внешние состояния\n * @param dispatchers Объект с диспетчерами\n * @param services Объект с сервисами\n * @param config Глобальная конфигурация для всех эффектов\n */\n constructor(\n private storage: IStorage<TState>,\n private externalStates: TExternalStates = {} as TExternalStates,\n private dispatchers: TDispatchers,\n private services: TServices = {} as TServices,\n private config: TConfig = {} as TConfig,\n ) {\n this.subscribeToDispatchers()\n\n // Создаем поток состояния\n this.state$ = new Observable<TState>((observer) => {\n // Отправляем начальное состояние\n this.storage.getState().then((state) => observer.next(state))\n\n // Подписываемся на все изменения\n const unsubscribe = this.storage.subscribeToAll(() => {\n this.storage.getState().then((state) => observer.next(state))\n })\n\n // Отписываемся при завершении\n return () => unsubscribe()\n }).pipe(share())\n }\n\n /**\n * Подписывается на действия от всех диспетчеров\n */\n private subscribeToDispatchers() {\n for (const [_, dispatcher] of Object.entries(this.dispatchers)) {\n const subscription = dispatcher.actions.subscribe((action) => {\n this.action$.next(action)\n })\n\n this.subscriptions.push(subscription)\n }\n }\n\n add(effect: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>): this {\n this.effects.push(effect)\n\n if (this.running) {\n this.subscribeToEffect(effect)\n }\n\n return this\n }\n\n /**\n * Добавляет несколько эффектов\n * @param effects Эффекты для добавления\n * @returns Текущий модуль\n */\n addEffects(effects: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>[]): this {\n effects.forEach((effect) => this.add(effect))\n return this\n }\n\n /**\n * Запускает все эффекты\n * @returns Текущий модуль\n */\n start(): this {\n if (this.running) {\n return this\n }\n\n this.effects.forEach((effect) => this.subscribeToEffect(effect))\n this.running = true\n\n return this\n }\n\n /**\n * Останавливает все эффекты\n * @returns Текущий модуль\n */\n stop(): this {\n this.subscriptions.forEach((sub) => sub.unsubscribe())\n this.subscriptions = []\n this.running = false\n\n return this\n }\n\n /**\n * Подписывается на конкретный эффект\n * @param effect Эффект для подписки\n */\n private subscribeToEffect(effect: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>): void {\n try {\n const output$ = effect(this.action$.asObservable(), this.state$, this.externalStates, this.dispatchers, this.services, this.config).pipe(\n catchError((err) => {\n console.error('Error in effect:', err)\n return of(null)\n }),\n )\n\n const subscription = output$.subscribe((result) => {\n if (result === null || result === undefined) {\n return\n }\n\n if (typeof result === 'function') {\n try {\n result()\n } catch (callError) {\n console.error('Error calling effect result function:', callError)\n }\n }\n })\n\n this.subscriptions.push(subscription)\n } catch (setupError) {\n console.error('Error setting up effect:', setupError)\n }\n }\n}\n\n/**\n * Вспомогательная функция для создания типизированного эффекта без состояния\n * @deprecated Используйте createEffect вместо этого\n */\nexport function createEffectBase<TDispatchers extends Record<string, Dispatcher<any, any>>, TServices extends Record<string, any>>(\n effect: EffectBase<TDispatchers, TServices>,\n): EffectBase<TDispatchers, TServices> {\n return effect\n}\n\n/**\n * Вспомогательная функция для создания типизированного эффекта с состоянием и конфигурацией\n */\nexport function createEffect<\n TState extends Record<string, any>,\n TDispatchers extends Record<string, Dispatcher<any, any>>,\n TServices extends Record<string, any>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(effect: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>): Effect<TState, TDispatchers, TServices, TConfig, TExternalStates> {\n return effect\n}\n\n/**\n * Объединяет несколько эффектов в один\n * @param effects Эффекты для объединения\n * @returns Объединенный эффект\n */\nexport function combineEffects<\n TState extends Record<string, any>,\n TDispatchers extends Record<string, Dispatcher<any, any>>,\n TServices extends Record<string, any>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(...effects: Effect<TState, TDispatchers, TServices, TConfig, TExternalStates>[]): Effect<TState, TDispatchers, TServices, TConfig, TExternalStates> {\n return (action$, state$, externalStates, dispatchers, services, config) => {\n const outputs = effects.map((effect) => {\n try {\n return effect(action$, state$, externalStates, dispatchers, services, config)\n } catch (error) {\n console.error('Error in one of combined effects:', error)\n return of(null)\n }\n })\n return merge(...outputs)\n }\n}\n","import { Observable, of } from 'rxjs'\nimport { concatAll, delay, mergeMap, toArray } from 'rxjs/operators'\n\nimport { chunk } from '../../../_utils'\n\n/**\n * Разбиение запроса на порции\n * Отправляется ПОСЛЕДОВАТЕЛЬНО n-запросов и дожидается ответа от каждого\n * @param fn - функция в которую передается chunk и возвращается функция api\n * @param arr - массив который нужно поделить\n * @param size - размер порции\n * @param delayMs - задержка между запросами в миллисекундах\n */\nexport const chunkRequestConsistent = <T, R>(fn: (chunk: T[]) => Observable<R>, arr: T[], size: number, delayMs = 0): Observable<R[]> => {\n const chunks = chunk(arr, size).map((chunkItem) => of(chunkItem).pipe(delay(delayMs), mergeMap(fn)))\n return of(...chunks).pipe(concatAll(), toArray())\n}\nexport type ChunkRequestConsistent = typeof chunkRequestConsistent\n","/**\n * Разбивает массив на группы элементов указанного размера.\n * @param array - Массив для разбиения\n * @param size - Размер каждой группы\n * @returns Массив групп элементов\n */\nexport function chunk<T>(array: T[], size: number = 1): T[][] {\n if (size <= 0) throw new Error('Size must be greater than 0')\n\n if (!array || !array.length) return []\n\n const result: T[][] = []\n const length = array.length\n let index = 0\n\n while (index < length) {\n result.push(array.slice(index, index + size))\n index += size\n }\n\n return result\n}\n","export const deepMerge = (target: any, source: any) => {\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {\n if (!target[key] || typeof target[key] !== 'object') {\n target[key] = {}\n }\n deepMerge(target[key], source[key])\n } else {\n target[key] = source[key]\n }\n }\n }\n}\n","import { forkJoin, Observable, timer } from 'rxjs'\nimport { mergeMap } from 'rxjs/operators'\n\nimport { chunk } from '../../../_utils'\n\n/**\n * Разбиение запроса на порции\n * Отправляется ПАРАЛЛЕЛЬНО n-запросов и дожидается ответа от каждого\n * @param fn - функция в которую передается chunk и возвращается функция api\n * @param arr - массив который нужно поделить\n * @param size - размер порции\n * @param delayMs - задержка между запросами в миллисекундах\n */\nexport const chunkRequestParallel = <T, R>(fn: (chunk: T[]) => Observable<R>, arr: T[], size: number, delayMs = 0): Observable<R[]> =>\n forkJoin(chunk(arr, size).map((chunkItem, index) => timer(index * delayMs).pipe(mergeMap(() => fn(chunkItem)))))\nexport type ChunkRequestParallel = typeof chunkRequestParallel\n","import { Observable } from 'rxjs'\n\nimport { ISelectorModule, IStorage, SelectorModule } from '../core'\nimport { Effect, EffectsModule, ExternalStates } from '../reactive'\n\n// Вспомогательные типы для извлечения типов из других типов\nexport type ExtractPromiseType<T> = T extends Promise<infer U> ? U : T\nexport type ExtractStorageType<T> = T extends IStorage<infer U> ? U : never\nexport type ExtractDispatchType<T> = T extends { dispatch: infer D } ? D : never\n\nexport type StorageCreatorFunction<T extends Record<string, any>> = () => Promise<IStorage<T>>\n\n/**\n * Базовая конфигурация хранилища\n */\ntype BaseSynapseConfig<TStore extends Record<string, any>, TSelectors = any, TExternalSelectors extends Record<string, any> = Record<string, any>> = (\n | { storage: IStorage<TStore>; createStorageFn?: undefined }\n | { storage?: undefined; createStorageFn: StorageCreatorFunction<TStore> }\n) & {\n // Внешние селекторы\n externalSelectors?: TExternalSelectors\n // Функция создания селекторов\n createSelectorsFn?: (selectorModule: ISelectorModule<TStore>, externalSelectors: TExternalSelectors) => TSelectors\n}\n\n/**\n * Конфигурация с dispatcher и effects\n */\nexport type CreateSynapseConfigWithEffects<\n TStore extends Record<string, any>,\n TSelectors = any,\n TDispatcher = any,\n TApi extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {\n // Функция создания диспетчера (обязательная)\n createDispatcherFn: (storage: IStorage<TStore>) => TDispatcher\n // Функция создания конфигурации для эффектов (обязательная)\n createEffectConfig: (dispatcher: TDispatcher) => {\n dispatchers: Record<string, any>\n api?: TApi\n config?: TConfig\n externalStates?: ExternalStates\n }\n // Эффекты\n effects?: Effect<TStore, any, TApi, TConfig, any>[]\n}\n\n/**\n * Конфигурация только с dispatcher\n */\nexport type CreateSynapseConfigWithDispatcher<\n TStore extends Record<string, any>,\n TSelectors = any,\n TDispatcher = any,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {\n // Функция создания диспетчера (обязательная)\n createDispatcherFn: (storage: IStorage<TStore>) => TDispatcher\n // Эффекты отсутствуют\n createEffectConfig?: never\n effects?: never\n}\n\n/**\n * Конфигурация без dispatcher\n */\nexport type CreateSynapseConfigBasic<\n TStore extends Record<string, any>,\n TSelectors = any,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n> = BaseSynapseConfig<TStore, TSelectors, TExternalSelectors> & {\n // Dispatcher отсутствует\n createDispatcherFn?: never\n createEffectConfig?: never\n effects?: never\n}\n\n/**\n * Результат с dispatcher и effects\n */\nexport interface SynapseStoreWithEffects<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions> {\n storage: TStorage\n selectors: TSelectors\n actions: TActions\n state$: Observable<TStore>\n dispatcher: any\n destroy: () => Promise<void>\n}\n\n/**\n * Результат только с dispatcher\n */\nexport interface SynapseStoreWithDispatcher<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions> {\n storage: TStorage\n selectors: TSelectors\n actions: TActions\n dispatcher: any\n destroy: () => Promise<void>\n}\n\n/**\n * Результат без dispatcher\n */\nexport interface SynapseStoreBasic<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors> {\n storage: TStorage\n selectors: TSelectors\n destroy: () => Promise<void>\n}\n\n/**\n * Union-тип для всех возможных результатов createSynapse\n */\nexport type AnySynapseStore<TStore extends Record<string, any> = any, TStorage extends IStorage<TStore> = IStorage<any>, TSelectors = any, TActions = any> =\n | SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>\n | SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions>\n | SynapseStoreBasic<TStore, TStorage, TSelectors>\n\n/**\n * Перегрузки функции createSynapse\n */\n\n// Случай 1: С dispatcher и effects\nexport function createSynapse<\n TStore extends Record<string, any>,\n TSelectors = any,\n TDispatcher = any,\n TApi extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n TStorage extends IStorage<TStore> = IStorage<TStore>,\n>(\n config: CreateSynapseConfigWithEffects<TStore, TSelectors, TDispatcher, TApi, TConfig, TExternalSelectors>,\n): Promise<SynapseStoreWithEffects<TStore, TStorage, TSelectors, ExtractDispatchType<TDispatcher>>>\n\n// Случай 2: Только с dispatcher\nexport function createSynapse<\n TStore extends Record<string, any>,\n TSelectors = any,\n TDispatcher = any,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n TStorage extends IStorage<TStore> = IStorage<TStore>,\n>(\n config: CreateSynapseConfigWithDispatcher<TStore, TSelectors, TDispatcher, TExternalSelectors>,\n): Promise<SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, ExtractDispatchType<TDispatcher>>>\n\n// Случай 3: Без dispatcher\nexport function createSynapse<\n TStore extends Record<string, any>,\n TSelectors = any,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n TStorage extends IStorage<TStore> = IStorage<TStore>,\n>(config: CreateSynapseConfigBasic<TStore, TSelectors, TExternalSelectors>): Promise<SynapseStoreBasic<TStore, TStorage, TSelectors>>\n\n// Основная реализация\nexport async function createSynapse<\n TStore extends Record<string, any>,\n TSelectors = any,\n TDispatcher = any,\n TApi extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalSelectors extends Record<string, any> = Record<string, any>,\n TStorage extends IStorage<TStore> = IStorage<TStore>,\n>(config: any): Promise<any> {\n // Создаем и инициализируем хранилище\n const storageInstance = (config.createStorageFn ? await config.createStorageFn() : config.storage!) as TStorage\n\n // Создаем сборщики для последующей очистки\n const cleanupCallbacks: Array<() => Promise<void> | void> = []\n\n const result: any = {\n storage: storageInstance,\n selectors: {} as TSelectors,\n destroy: async () => {\n for (const callback of cleanupCallbacks) {\n await callback()\n }\n },\n }\n\n cleanupCallbacks.push(() => storageInstance.destroy())\n\n let dispatcher: TDispatcher | undefined\n let selectorModule: ISelectorModule<TStore>\n let effectsModule: any\n\n // Создаем модуль селекторов\n if (config.createSelectorsFn) {\n try {\n selectorModule = new SelectorModule(storageInstance)\n\n const externalSelectors = config.externalSelectors || ({} as TExternalSelectors)\n\n result.selectors = config.createSelectorsFn(selectorModule, externalSelectors)\n\n if (typeof (selectorModule as any).destroy === 'function') {\n cleanupCallbacks.push(() => selectorModule.destroy())\n }\n } catch (error) {\n console.error('Ошибка создания selectors:', error)\n }\n }\n\n // Создаем диспетчер\n if (config.createDispatcherFn) {\n dispatcher = config.createDispatcherFn(storageInstance)\n result.dispatcher = dispatcher\n\n // @ts-ignore\n if (dispatcher && 'dispatch' in dispatcher) {\n result.actions = (dispatcher as any).dispatch\n\n if (typeof (dispatcher as any).destroy === 'function') {\n cleanupCallbacks.push(() => (dispatcher as any).destroy())\n }\n }\n }\n\n // Создаем и настраиваем модуль эффектов\n if (config.createEffectConfig && dispatcher) {\n try {\n const { dispatchers, api, config: effectConfig, externalStates } = config.createEffectConfig(dispatcher)\n\n // Получаем внешние состояния из конфигурации эффектов\n const effectExternalStates = externalStates || {}\n\n // Создаем модуль эффектов с внешними состояниями\n effectsModule = new EffectsModule(storageInstance, effectExternalStates, dispatchers, api, effectConfig)\n\n // Добавляем эффекты\n if (Array.isArray(config.effects)) {\n // @ts-ignore\n config.effects.forEach((effect) => {\n if (effectsModule) effectsModule.add(effect)\n })\n }\n\n // Запускаем модуль эффектов\n effectsModule.start()\n result.state$ = effectsModule.state$\n\n // Добавляем очистку эффектов\n cleanupCallbacks.push(() => {\n if (effectsModule) effectsModule.stop()\n })\n } catch (error) {\n console.error('Ошибка создания модуля эффектов:', error)\n }\n }\n\n return result\n}\n","import { useEffect, useRef, useState } from 'react'\n\nimport type { SelectorAPI } from '../../core'\n\ninterface UseSelectorOptions<T> {\n /** Начальное значение до загрузки данных из селектора */\n initialValue?: T\n /** Функция сравнения для предотвращения лишних ререндеров */\n equals?: (a: T, b: T) => boolean\n /** Включать ли статус загрузки в возвращаемый результат */\n withLoading?: boolean\n}\n\n/**\n * Глобальный реестр селекторов с активными подписками.\n * Хранит последние значения селекторов и список callbacks для обновления всех компонентов.\n */\nconst SELECTOR_REGISTRY = new Map<\n string,\n {\n lastValue: any\n listeners: Set<(value: any) => void>\n unsubscribe: VoidFunction | null\n }\n>()\n\n/**\n * Хук для использования селекторов в компонентах React.\n * Обеспечивает согласованность значений между всеми экземплярами хука.\n */\nexport function useSelector<T>(selector: SelectorAPI<T>): T | undefined\nexport function useSelector<T>(selector: SelectorAPI<T>, options: UseSelectorOptions<T> & { withLoading?: true }): { data: T | undefined; isLoading: boolean }\nexport function useSelector<T>(selector: SelectorAPI<T>, options?: UseSelectorOptions<T>): { data: T | undefined; isLoading: boolean } | T | undefined {\n // Базовые состояния\n const [state, setState] = useState<T | undefined>(options?.initialValue)\n const [isLoading, setIsLoading] = useState<boolean>(!!options?.withLoading)\n\n // Для предотвращения лишних ререндеров\n const prevValueRef = useRef<T | undefined>(options?.initialValue)\n const equalsRef = useRef(options?.equals || ((a: T, b: T) => a === b))\n\n // Получаем ID селектора с помощью метода getId()\n const selectorId = selector.getId()\n\n // Обновляем состояние компонента при изменении значения\n const updateComponentState = (newValue: T) => {\n // Сравниваем с предыдущим значением компонента\n if (prevValueRef.current === undefined || !equalsRef.current(newValue, prevValueRef.current)) {\n prevValueRef.current = newValue\n setState(newValue)\n }\n }\n\n useEffect(() => {\n // Создаем запись в реестре, если её ещё нет\n if (!SELECTOR_REGISTRY.has(selectorId)) {\n SELECTOR_REGISTRY.set(selectorId, {\n lastValue: undefined,\n listeners: new Set(),\n unsubscribe: null,\n })\n }\n\n const registry = SELECTOR_REGISTRY.get(selectorId)!\n\n // Добавляем текущий компонент в список слушателей\n registry.listeners.add(updateComponentState)\n\n // Если у нас уже есть значение, сразу устанавливаем его\n if (registry.lastValue !== undefined) {\n updateComponentState(registry.lastValue)\n\n // Если был запрошен режим загрузки, сразу сбрасываем его\n if (options?.withLoading) {\n setIsLoading(false)\n }\n } else {\n // Запрашиваем начальное значение\n if (options?.withLoading) setIsLoading(true)\n\n selector\n .select()\n .then((initialValue) => {\n // Обновляем значение в реестре\n registry.lastValue = initialValue\n\n // Уведомляем все компоненты\n registry.listeners.forEach((listener) => listener(initialValue))\n\n if (options?.withLoading) setIsLoading(false)\n })\n .catch((error) => {\n console.error(`useSelector: Ошибка при получении начального значения для ${selectorId}`, error)\n if (options?.withLoading) setIsLoading(false)\n })\n }\n\n // Создаем подписку только один раз для селектора\n if (!registry.unsubscribe) {\n registry.unsubscribe = selector.subscribe({\n notify: (newValue: T) => {\n // Обновляем значение в реестре\n registry.lastValue = newValue\n\n // Уведомляем все компоненты\n registry.listeners.forEach((listener) => {\n try {\n listener(newValue)\n } catch (error) {\n console.error(`useSelector: Ошибка при уведомлении слушателя для ${selectorId}`, error)\n }\n })\n },\n })\n }\n\n // При размонтировании компонента\n return () => {\n const registry = SELECTOR_REGISTRY.get(selectorId)\n if (registry) {\n // Удаляем текущий компонент из списка слушателей\n registry.listeners.delete(updateComponentState)\n\n // Если больше нет слушателей, можно очистить подписку\n if (registry.listeners.size === 0) {\n if (registry.unsubscribe) {\n registry.unsubscribe()\n }\n SELECTOR_REGISTRY.delete(selectorId)\n }\n }\n }\n }, [selector, selectorId])\n\n // Возвращаем данные в нужном формате\n if (options?.withLoading) {\n return { data: state, isLoading }\n }\n\n return state\n}\n","import { useEffect, useState } from 'react'\n\nimport { IStorage } from '../../core'\n\n/**\n * Хук для подписки на изменения в хранилище\n *\n * @template S - Тип состояния хранилища\n * @template R - Тип возвращаемого значения\n * @param storage - Экземпляр хранилища\n * @param selector - Функция-селектор для выбора данных\n * @returns Значение из хранилища\n */\nexport const useStorageSubscribe = <S extends Record<string, any>, R = any>(storage: IStorage<S>, selector: (state: S) => R): R | undefined => {\n const [value, setValue] = useState<R | undefined>(undefined)\n\n useEffect(() => {\n // Флаг монтирования для предотвращения обновления состояния при размонтировании\n let isMounted = true\n\n const initializeValue = async () => {\n try {\n const state = await storage.getState()\n const selectedValue = selector(state) as R\n\n if (isMounted) {\n setValue(selectedValue)\n }\n } catch (error) {\n console.error('Failed to initialize storage value:', error)\n }\n }\n\n // Инициализируем значение\n initializeValue()\n\n let unsubscribe: VoidFunction\n try {\n unsubscribe = storage.subscribe(selector, (newValue: R) => {\n if (isMounted) {\n setValue(newValue)\n }\n })\n } catch (error) {\n console.error('Failed to subscribe to storage:', error)\n unsubscribe = () => {}\n }\n\n return () => {\n isMounted = false\n unsubscribe()\n }\n }, [storage, selector])\n\n return value\n}\n","import { ComponentType, createContext, PropsWithChildren, useContext, useEffect, useRef, useState } from 'react'\nimport { Observable } from 'rxjs'\n\nimport { deepMerge } from '../../_utils'\nimport { IStorage } from '../../core'\nimport { AnySynapseStore, SynapseStoreBasic, SynapseStoreWithDispatcher, SynapseStoreWithEffects } from '../../utils'\n\nconst ERROR_HOOK_MESSAGE = 'useSynapseActions необходимо использовать внутри компонента contextSynapse'\nconst ERROR_CONTEXT_INIT = 'Ошибка при инициализации контекста:'\n\ninterface Options<TStore extends Record<string, any>> {\n loadingComponent?: any\n mergeFn?: (target: TStore, source: Record<string, any>) => void\n}\n\n/**\n * Перегрузки для createSynapseCtx в зависимости от типа хранилища\n */\n\n// Для хранилища с effects\nexport function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions>(\n synapseStorePromise: Promise<SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>> | SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>,\n options?: Options<TStore>,\n): {\n contextSynapse: <SelfComponentProps, PublicContextProps = Record<string, any>>(\n Component: ComponentType<SelfComponentProps>,\n ) => ComponentType<SelfComponentProps & { contextProps?: PublicContextProps }>\n useSynapseStorage: () => TStorage\n useSynapseSelectors: () => TSelectors\n useSynapseActions: () => TActions\n useSynapseState$: () => Observable<TStore>\n cleanupSynapse: () => Promise<void>\n}\n\n// Для хранилища с dispatcher (без effects)\nexport function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions>(\n synapseStorePromise: Promise<SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions>> | SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions>,\n options?: Options<TStore>,\n): {\n contextSynapse: <SelfComponentProps, PublicContextProps = Record<string, any>>(\n Component: ComponentType<SelfComponentProps>,\n ) => ComponentType<SelfComponentProps & { contextProps?: PublicContextProps }>\n useSynapseStorage: () => TStorage\n useSynapseSelectors: () => TSelectors\n useSynapseActions: () => TActions\n cleanupSynapse: () => Promise<void>\n}\n\n// Для базового хранилища\nexport function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors>(\n synapseStorePromise: Promise<SynapseStoreBasic<TStore, TStorage, TSelectors>> | SynapseStoreBasic<TStore, TStorage, TSelectors>,\n options?: Options<TStore>,\n): {\n contextSynapse: <SelfComponentProps, PublicContextProps = Record<string, any>>(\n Component: ComponentType<SelfComponentProps>,\n ) => ComponentType<SelfComponentProps & { contextProps?: PublicContextProps }>\n useSynapseStorage: () => TStorage\n useSynapseSelectors: () => TSelectors\n cleanupSynapse: () => Promise<void>\n}\n\n// Основная реализация\nexport function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors = any, TActions = any>(\n synapseStorePromise: Promise<AnySynapseStore<TStore, TStorage, TSelectors, TActions>> | AnySynapseStore<TStore, TStorage, TSelectors, TActions>,\n options?: Options<TStore>,\n) {\n const { loadingComponent = null, mergeFn = deepMerge } = options || {}\n\n // Храним ссылку на store\n let synapseStore: AnySynapseStore<TStore, TStorage, TSelectors, TActions> | null = null\n\n // Флаг готовности хранилища\n let storeReady = false\n\n // Если передан Promise, начинаем его обработку\n const initPromise = (async () => {\n try {\n synapseStore = await (synapseStorePromise instanceof Promise ? synapseStorePromise : Promise.resolve(synapseStorePromise))\n storeReady = true\n } catch (error) {\n console.error('Ошибка инициализации хранилища Synapse:', error)\n }\n })()\n\n const SynapseContext = createContext<AnySynapseStore<TStore, TStorage, TSelectors, TActions> | null>(null)\n\n const useSynapseStorage = (): TStorage => {\n const context = useContext(SynapseContext)\n if (!context) throw new Error(ERROR_HOOK_MESSAGE)\n\n return context.storage\n }\n\n const useSynapseSelectors = (): TSelectors => {\n const context = useContext(SynapseContext)\n if (!context) throw new Error(ERROR_HOOK_MESSAGE)\n\n return context.selectors\n }\n\n // Условный хук для actions (только если есть dispatcher)\n const useSynapseActions = (): TActions => {\n const context = useContext(SynapseContext)\n if (!context) throw new Error(ERROR_HOOK_MESSAGE)\n\n if ('actions' in context) {\n return (context as SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions> | SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>).actions\n }\n\n throw new Error('useSynapseActions: actions недоступны для этого типа хранилища. Убедитесь, что передана функция createDispatcherFn при создании хранилища.')\n }\n\n // Условный хук для state$ (только если есть effects)\n const useSynapseState$ = (): Observable<TStore> => {\n const context = useContext(SynapseContext)\n if (!context) throw new Error(ERROR_HOOK_MESSAGE)\n\n if ('state$' in context) {\n return (context as SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>).state$\n }\n\n throw new Error('useSynapseState$: state$ недоступен для этого типа хранилища. Убедитесь, что переданы функции createDispatcherFn и createEffectConfig при создании хранилища.')\n }\n\n /**\n * Декоратор для обертывания компонентов в контекст Synapse\n */\n function contextSynapse<SelfComponentProps, PublicContextProps = Record<string, any>>(Component: ComponentType<SelfComponentProps>) {\n type WrappedComponentProps = SelfComponentProps & { contextProps?: PublicContextProps }\n\n function WrappedComponent({ contextProps, ...props }: WrappedComponentProps) {\n const [initialized, setInitialized] = useState(false)\n const [storeInitialized, setStoreInitialized] = useState(storeReady)\n const debugIdRef = useRef(`synapse-${synapseStore?.storage.name || 'initializing'}`)\n\n // Отслеживаем инициализацию хранилища, если оно еще не готово\n useEffect(() => {\n if (!storeReady) {\n initPromise.then(() => {\n setStoreInitialized(true)\n })\n }\n }, [])\n\n // Инициализируем контекст при монтировании компонента\n useEffect(() => {\n // Не начинаем инициализацию контекста, пока хранилище не готово\n if (!storeInitialized) return\n\n let mounted = true\n\n const initializeContext = async () => {\n try {\n if (synapseStore && contextProps && Object.keys(contextProps).length > 0) {\n await synapseStore.storage.update((state) => {\n mergeFn(state, contextProps)\n })\n }\n\n if (mounted) {\n setInitialized(true)\n }\n } catch (error) {\n console.error(`[${debugIdRef.current}] ${ERROR_CONTEXT_INIT}`, error)\n }\n }\n\n initializeContext()\n\n return () => {\n mounted = false\n }\n }, [contextProps, storeInitialized])\n\n // Проверяем инициализацию хранилища и контекста\n if (!storeInitialized) {\n return loadingComponent || <div>Загрузка хранилища...</div>\n }\n\n if (!initialized) {\n return loadingComponent || <div>Инициализация контекста...</div>\n }\n\n return (\n <SynapseContext.Provider value={synapseStore}>\n <Component {...(props as PropsWithChildren<SelfComponentProps>)} />\n </SynapseContext.Provider>\n )\n }\n\n // Устанавливаем отображаемое имя для отладки\n const componentName = Component.displayName || Component.name || 'Component'\n WrappedComponent.displayName = `SynapseContext(${componentName})`\n\n return WrappedComponent\n }\n\n const cleanupSynapse = async (): Promise<void> => {\n await initPromise // Ждем завершения инициализации\n return synapseStore?.destroy() || Promise.resolve()\n }\n\n return {\n contextSynapse,\n useSynapseStorage,\n useSynapseSelectors,\n useSynapseActions,\n useSynapseState$,\n cleanupSynapse,\n }\n}\n"],"mappings":"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","names":["ResponseFormat","blob","headers","options","StorageEvents","currentState","selectedValue","store","Observable","of","Subject","mergeMap","mergeMap","of","Observable","Subject","registry","useEffect","useState","useEffect","useRef","useState","useState","useRef","useEffect"]}
|