synapse-storage 4.1.2 → 5.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/README.md +142 -12
- package/dist/_utils/chunk.util.d.ts +0 -1
- package/dist/_utils/deepMerge.util.d.ts +0 -1
- package/dist/_utils/error-handling.util.d.ts +0 -1
- package/dist/_utils/flatMap.util.d.ts +0 -1
- package/dist/_utils/index.d.ts +0 -1
- package/dist/_utils/logger-console.util.d.ts +0 -1
- package/dist/api/api.module.d.ts +0 -1
- package/dist/api/components/endpoint.d.ts +11 -12
- package/dist/api/components/endpoint.js.map +1 -1
- package/dist/api/components/query-storage.d.ts +0 -1
- package/dist/api/components/query-storage.js +1 -1
- package/dist/api/components/query-storage.js.map +1 -1
- package/dist/api/index.d.ts +0 -1
- package/dist/api/types/api.interface.d.ts +0 -1
- package/dist/api/types/endpoint.interface.d.ts +0 -1
- package/dist/api/types/query.interface.d.ts +0 -1
- package/dist/api/utils/api-helpers.d.ts +0 -1
- package/dist/{core/storage → api}/utils/cache.util.d.ts +3 -6
- package/dist/{core/storage → api}/utils/cache.util.js +4 -7
- package/dist/api/utils/cache.util.js.map +1 -0
- package/dist/api/utils/create-header-context.d.ts +0 -1
- package/dist/api/utils/endpoint-headers.d.ts +0 -1
- package/dist/api/utils/fetch-base-query.d.ts +0 -1
- package/dist/api/utils/file-utils.d.ts +0 -1
- package/dist/api/utils/get-cacheable-headers.d.ts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/selector/index.d.ts +1 -1
- package/dist/core/selector/index.js +2 -0
- package/dist/core/selector/index.js.map +1 -1
- package/dist/core/selector/selector.interface.d.ts +15 -30
- package/dist/core/selector/selector.interface.js +2 -2
- package/dist/core/selector/selector.interface.js.map +1 -1
- package/dist/core/selector/selector.module.d.ts +16 -1
- package/dist/core/selector/selector.module.js +82 -20
- package/dist/core/selector/selector.module.js.map +1 -1
- package/dist/core/selector/selectors.base.d.ts +56 -0
- package/dist/core/selector/selectors.base.js +118 -0
- package/dist/core/selector/selectors.base.js.map +1 -0
- package/dist/core/storage/adapters/async-base-storage.service.d.ts +15 -4
- package/dist/core/storage/adapters/async-base-storage.service.js +106 -36
- package/dist/core/storage/adapters/async-base-storage.service.js.map +1 -1
- package/dist/core/storage/adapters/indexed-DB.service.d.ts +4 -5
- package/dist/core/storage/adapters/indexed-DB.service.js +66 -14
- package/dist/core/storage/adapters/indexed-DB.service.js.map +1 -1
- package/dist/core/storage/adapters/local-storage.service.d.ts +9 -4
- package/dist/core/storage/adapters/local-storage.service.js +25 -5
- package/dist/core/storage/adapters/local-storage.service.js.map +1 -1
- package/dist/core/storage/adapters/memory-storage.service.d.ts +2 -4
- package/dist/core/storage/adapters/memory-storage.service.js +5 -5
- package/dist/core/storage/adapters/memory-storage.service.js.map +1 -1
- package/dist/core/storage/adapters/path.utils.d.ts +0 -1
- package/dist/core/storage/adapters/storage-core.d.ts +6 -2
- package/dist/core/storage/adapters/storage-core.js +6 -3
- package/dist/core/storage/adapters/storage-core.js.map +1 -1
- package/dist/core/storage/adapters/sync-base-storage.service.d.ts +20 -4
- package/dist/core/storage/adapters/sync-base-storage.service.js +110 -35
- package/dist/core/storage/adapters/sync-base-storage.service.js.map +1 -1
- package/dist/core/storage/index.d.ts +2 -5
- package/dist/core/storage/index.js +1 -5
- package/dist/core/storage/index.js.map +1 -1
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/index.d.ts +3 -1
- package/dist/core/storage/middlewares/index.js +6 -0
- package/dist/core/storage/middlewares/index.js.map +1 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/storage-logger.middleware.d.ts +20 -0
- package/dist/core/storage/middlewares/storage-logger.middleware.js +53 -0
- package/dist/core/storage/middlewares/storage-logger.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +4 -10
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +1 -1
- package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/sync-storage-logger.middleware.d.ts +7 -0
- package/dist/core/storage/middlewares/sync-storage-logger.middleware.js +48 -0
- package/dist/core/storage/middlewares/sync-storage-logger.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts +0 -1
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js +4 -10
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js.map +1 -1
- package/dist/core/storage/modules/singleton/mixin.util.d.ts +0 -1
- package/dist/core/storage/modules/singleton/models.d.ts +0 -1
- package/dist/core/storage/modules/singleton/singleton.util.d.ts +0 -1
- package/dist/core/storage/storage.interface.d.ts +59 -4
- package/dist/core/storage/storage.interface.js +0 -2
- package/dist/core/storage/storage.interface.js.map +1 -1
- package/dist/core/storage/utils/broadcast.util.d.ts +0 -1
- package/dist/core/storage/utils/middleware-module.d.ts +0 -3
- package/dist/core/storage/utils/middleware-module.js +0 -8
- package/dist/core/storage/utils/middleware-module.js.map +1 -1
- package/dist/core/storage/utils/migration.util.d.ts +38 -0
- package/dist/core/storage/utils/migration.util.js +48 -0
- package/dist/core/storage/utils/migration.util.js.map +1 -0
- package/dist/core/storage/utils/path-selector.util.d.ts +0 -1
- package/dist/core/storage/utils/state-diff.util.d.ts +8 -1
- package/dist/core/storage/utils/state-diff.util.js +17 -1
- package/dist/core/storage/utils/state-diff.util.js.map +1 -1
- package/dist/core/storage/utils/storage-factory.util.d.ts +7 -9
- package/dist/core/storage/utils/storage-factory.util.js +10 -10
- package/dist/core/storage/utils/storage-factory.util.js.map +1 -1
- package/dist/core/storage/utils/storage-key.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/react/hooks/index.d.ts +2 -1
- package/dist/react/hooks/index.js +4 -0
- package/dist/react/hooks/index.js.map +1 -1
- package/dist/react/hooks/useCreateStorage.d.ts +5 -6
- package/dist/react/hooks/useCreateStorage.js +2 -2
- package/dist/react/hooks/useCreateStorage.js.map +1 -1
- package/dist/react/hooks/useObservable.d.ts +17 -0
- package/dist/react/hooks/useObservable.js +38 -0
- package/dist/react/hooks/useObservable.js.map +1 -0
- package/dist/react/hooks/useSelector.d.ts +0 -1
- package/dist/react/hooks/useSelector.js +5 -2
- package/dist/react/hooks/useSelector.js.map +1 -1
- package/dist/react/hooks/useStorage.d.ts +0 -1
- package/dist/react/hooks/useStorageSubscribe.d.ts +0 -1
- package/dist/react/hooks/useSubscription.d.ts +13 -0
- package/dist/react/hooks/useSubscription.js +23 -0
- package/dist/react/hooks/useSubscription.js.map +1 -0
- package/dist/react/index.d.ts +0 -1
- package/dist/react/utils/awaitSynapse.d.ts +9 -10
- package/dist/react/utils/awaitSynapse.js +3 -2
- package/dist/react/utils/awaitSynapse.js.map +1 -1
- package/dist/react/utils/createSynapseCtx.d.ts +18 -23
- package/dist/react/utils/createSynapseCtx.js +64 -39
- package/dist/react/utils/createSynapseCtx.js.map +1 -1
- package/dist/react/utils/index.d.ts +0 -1
- package/dist/reactive/dispatcher/dispatcher.base.d.ts +122 -0
- package/dist/reactive/dispatcher/dispatcher.base.js +294 -0
- package/dist/reactive/dispatcher/dispatcher.base.js.map +1 -0
- package/dist/reactive/dispatcher/dispatcher.module.d.ts +12 -67
- package/dist/reactive/dispatcher/dispatcher.module.js +13 -72
- package/dist/reactive/dispatcher/dispatcher.module.js.map +1 -1
- package/dist/reactive/dispatcher/index.d.ts +1 -1
- package/dist/reactive/dispatcher/index.js +2 -0
- package/dist/reactive/dispatcher/index.js.map +1 -1
- package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -1
- package/dist/reactive/dispatcher/path.util.d.ts +15 -0
- package/dist/reactive/dispatcher/path.util.js +34 -0
- package/dist/reactive/dispatcher/path.util.js.map +1 -0
- package/dist/reactive/dispatcher/standalone.d.ts +1 -150
- package/dist/reactive/dispatcher/standalone.js +6 -217
- package/dist/reactive/dispatcher/standalone.js.map +1 -1
- package/dist/reactive/effects/effects.base.d.ts +62 -0
- package/dist/reactive/effects/effects.base.js +90 -0
- package/dist/reactive/effects/effects.base.js.map +1 -0
- package/dist/reactive/effects/effects.module.d.ts +122 -11
- package/dist/reactive/effects/effects.module.js +129 -17
- package/dist/reactive/effects/effects.module.js.map +1 -1
- package/dist/reactive/effects/index.d.ts +1 -1
- package/dist/reactive/effects/index.js +2 -0
- package/dist/reactive/effects/index.js.map +1 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -1
- package/dist/reactive/effects/utils/fromRequest.d.ts +0 -1
- package/dist/reactive/effects/utils/index.d.ts +0 -1
- package/dist/reactive/effects/utils/toObservable.d.ts +0 -1
- package/dist/reactive/index.d.ts +0 -1
- package/dist/utils/createEventBus.d.ts +47 -46
- package/dist/utils/createEventBus.js +152 -174
- package/dist/utils/createEventBus.js.map +1 -1
- package/dist/utils/createSynapse/createSynapse.d.ts +25 -7
- package/dist/utils/createSynapse/createSynapse.js +28 -98
- package/dist/utils/createSynapse/createSynapse.js.map +1 -1
- package/dist/utils/createSynapse/factory.d.ts +6 -0
- package/dist/utils/createSynapse/factory.js +256 -0
- package/dist/utils/createSynapse/factory.js.map +1 -0
- package/dist/utils/createSynapse/index.d.ts +2 -2
- package/dist/utils/createSynapse/index.js.map +1 -1
- package/dist/utils/createSynapse/synapse.types.d.ts +87 -0
- package/dist/utils/createSynapse/synapse.types.js +11 -0
- package/dist/utils/createSynapse/synapse.types.js.map +1 -0
- package/dist/utils/createSynapse/types.d.ts +6 -85
- package/dist/utils/createSynapse/types.js +2 -1
- package/dist/utils/createSynapse/types.js.map +1 -1
- package/dist/utils/createSynapse/waitForDependencies.d.ts +0 -1
- package/dist/utils/createSynapse/waitForDependencies.js +1 -1
- package/dist/utils/createSynapse/waitForDependencies.js.map +1 -1
- package/dist/utils/createSynapseAwaiter.d.ts +13 -10
- package/dist/utils/createSynapseAwaiter.js +30 -3
- package/dist/utils/createSynapseAwaiter.js.map +1 -1
- package/dist/utils/dehydrateModule.d.ts +6 -0
- package/dist/utils/dehydrateModule.js +43 -0
- package/dist/utils/dehydrateModule.js.map +1 -0
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -1
- package/package.json +12 -2
- package/dist/_utils/chunk.util.d.ts.map +0 -1
- package/dist/_utils/deepMerge.util.d.ts.map +0 -1
- package/dist/_utils/error-handling.util.d.ts.map +0 -1
- package/dist/_utils/flatMap.util.d.ts.map +0 -1
- package/dist/_utils/index.d.ts.map +0 -1
- package/dist/_utils/logger-console.util.d.ts.map +0 -1
- package/dist/api/api.module.d.ts.map +0 -1
- package/dist/api/components/endpoint.d.ts.map +0 -1
- package/dist/api/components/query-storage.d.ts.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 -90
- package/dist/api/example.js.map +0 -1
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/types/api.interface.d.ts.map +0 -1
- package/dist/api/types/endpoint.interface.d.ts.map +0 -1
- package/dist/api/types/query.interface.d.ts.map +0 -1
- package/dist/api/utils/api-helpers.d.ts.map +0 -1
- package/dist/api/utils/create-header-context.d.ts.map +0 -1
- package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
- package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
- package/dist/api/utils/file-utils.d.ts.map +0 -1
- package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/selector/index.d.ts.map +0 -1
- package/dist/core/selector/selector.interface.d.ts.map +0 -1
- package/dist/core/selector/selector.module.d.ts.map +0 -1
- package/dist/core/storage/adapters/async-base-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
- package/dist/core/storage/adapters/storage-core.d.ts.map +0 -1
- package/dist/core/storage/adapters/sync-base-storage.service.d.ts.map +0 -1
- package/dist/core/storage/index.d.ts.map +0 -1
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/index.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts +0 -101
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.js +0 -8
- package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -49
- package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.js +0 -406
- package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
- package/dist/core/storage/modules/singleton/mixin.util.d.ts.map +0 -1
- package/dist/core/storage/modules/singleton/models.d.ts.map +0 -1
- package/dist/core/storage/modules/singleton/singleton.util.d.ts.map +0 -1
- package/dist/core/storage/storage.interface.d.ts.map +0 -1
- package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
- package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
- package/dist/core/storage/utils/cache.util.js.map +0 -1
- package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
- package/dist/core/storage/utils/path-selector.util.d.ts.map +0 -1
- package/dist/core/storage/utils/state-diff.util.d.ts.map +0 -1
- package/dist/core/storage/utils/storage-factory.util.d.ts.map +0 -1
- package/dist/core/storage/utils/storage-key.d.ts.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.map +0 -1
- package/dist/react/hooks/useCreateStorage.d.ts.map +0 -1
- package/dist/react/hooks/useSelector.d.ts.map +0 -1
- package/dist/react/hooks/useStorage.d.ts.map +0 -1
- package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/utils/awaitSynapse.d.ts.map +0 -1
- package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
- package/dist/react/utils/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
- package/dist/reactive/dispatcher/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
- package/dist/reactive/dispatcher/standalone.d.ts.map +0 -1
- package/dist/reactive/effects/effects.module.d.ts.map +0 -1
- package/dist/reactive/effects/index.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
- package/dist/reactive/effects/utils/fromRequest.d.ts.map +0 -1
- package/dist/reactive/effects/utils/index.d.ts.map +0 -1
- package/dist/reactive/effects/utils/toObservable.d.ts.map +0 -1
- package/dist/reactive/index.d.ts.map +0 -1
- package/dist/utils/createEventBus.d.ts.map +0 -1
- package/dist/utils/createSynapse/createSynapse.d.ts.map +0 -1
- package/dist/utils/createSynapse/index.d.ts.map +0 -1
- package/dist/utils/createSynapse/types.d.ts.map +0 -1
- package/dist/utils/createSynapse/validate.d.ts +0 -2
- package/dist/utils/createSynapse/validate.d.ts.map +0 -1
- package/dist/utils/createSynapse/validate.js +0 -76
- package/dist/utils/createSynapse/validate.js.map +0 -1
- package/dist/utils/createSynapse/waitForDependencies.d.ts.map +0 -1
- package/dist/utils/createSynapseAwaiter.d.ts.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable, OperatorFunction } from 'rxjs';
|
|
2
2
|
import { IStorage, IStorageBase } from '../../core';
|
|
3
|
-
import { Action, ActionsResult,
|
|
3
|
+
import { Action, ActionsResult, DispatcherCore, DispatchFunction, ExtractResultType, WatcherFunction } from '../dispatcher';
|
|
4
4
|
import { ChunkRequestConsistent, ChunkRequestParallel } from './utils';
|
|
5
5
|
/**
|
|
6
6
|
* Тип действия с типизированным payload
|
|
@@ -16,7 +16,7 @@ export type ExternalStates = Record<string, Observable<any> | IStorageBase<any>>
|
|
|
16
16
|
/**
|
|
17
17
|
* Контекст эффекта — объект с зависимостями, передаваемый третьим аргументом
|
|
18
18
|
*/
|
|
19
|
-
export interface EffectContext<TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string,
|
|
19
|
+
export interface EffectContext<TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>, TExternalStates extends ExternalStates = Record<string, never>> {
|
|
20
20
|
/** Основной dispatcher текущего synapse */
|
|
21
21
|
dispatcher: TDispatcher;
|
|
22
22
|
/** Внешние dispatcher'ы из других synapse */
|
|
@@ -31,17 +31,54 @@ export interface EffectContext<TDispatcher = any, TServices extends Record<strin
|
|
|
31
31
|
/**
|
|
32
32
|
* Тип для эффекта с доступом к состоянию и контексту — основной тип
|
|
33
33
|
*/
|
|
34
|
-
export type Effect<TState extends Record<string, any> = any, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string,
|
|
34
|
+
export type Effect<TState extends Record<string, any> = any, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>, TExternalStates extends ExternalStates = Record<string, never>> = (action$: Observable<Action>, state$: Observable<TState>, context: EffectContext<TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>) => Observable<unknown>;
|
|
35
|
+
/**
|
|
36
|
+
* Опции конкретного эффекта. Прикрепляются к функции-эффекту через {@link EFFECT_OPTIONS}
|
|
37
|
+
* (это делает `Effects.effect(fn, options)` из базового класса). EffectsModule читает их
|
|
38
|
+
* при подписке.
|
|
39
|
+
*/
|
|
40
|
+
export interface EffectOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Переподписаться на поток при непойманной ошибке вместо терминального завершения.
|
|
43
|
+
*
|
|
44
|
+
* - `true` — бесконечный немедленный resubscribe;
|
|
45
|
+
* - `{ count, delay }` — лимит ретраев и задержка (мс) между ними (см. rxjs `retry`).
|
|
46
|
+
*
|
|
47
|
+
* По умолчанию (опция не задана) — текущее поведение: ошибка завершает эффект,
|
|
48
|
+
* остальные продолжают работать.
|
|
49
|
+
*/
|
|
50
|
+
resubscribeOnError?: boolean | {
|
|
51
|
+
count?: number;
|
|
52
|
+
delay?: number;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Symbol-маркер, под которым опции эффекта ({@link EffectOptions}) хранятся на функции-эффекте.
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
export declare const EFFECT_OPTIONS: unique symbol;
|
|
60
|
+
/**
|
|
61
|
+
* Symbol-маркер с именем эффекта (имя поля class-слоя `Effects`). Проставляется
|
|
62
|
+
* `Effects.getEffects()` для диагностики — EffectsModule использует его, чтобы в
|
|
63
|
+
* предупреждении об упавшем эффекте назвать конкретный эффект.
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
export declare const EFFECT_NAME: unique symbol;
|
|
35
67
|
/**
|
|
36
68
|
* Тип для получения типов действий диспетчера
|
|
37
69
|
*/
|
|
38
|
-
export type DispatcherActions<T> = T extends
|
|
70
|
+
export type DispatcherActions<T> = T extends DispatcherCore<any, infer A> ? ActionsResult<A> : Record<string, DispatchFunction<any, any>>;
|
|
39
71
|
/**
|
|
40
72
|
* Конфигурация для валидации в validateMap
|
|
41
73
|
*/
|
|
42
74
|
export interface ValidateConfig {
|
|
43
75
|
conditions: boolean[];
|
|
44
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Что сделать, если валидация не прошла. Необязательно: если не задано — эффект просто
|
|
78
|
+
* ничего не делает (поток завершается без эмита). Это убирает повторяющийся бойлерплейт
|
|
79
|
+
* `skipAction: () => d.loadX.reset()` там, где сбрасывать нечего.
|
|
80
|
+
*/
|
|
81
|
+
skipAction?: (() => any) | any | ((() => any) | any)[];
|
|
45
82
|
}
|
|
46
83
|
/**
|
|
47
84
|
* Утилиты для запросов в validateMap
|
|
@@ -90,16 +127,91 @@ export declare function selectorObject<TState, TResult extends Record<string, an
|
|
|
90
127
|
[K in keyof TResult]: (state: TState) => TResult[K];
|
|
91
128
|
}): Observable<TResult>;
|
|
92
129
|
/**
|
|
93
|
-
* Оператор
|
|
130
|
+
* Оператор наложения (flattening) для {@link requestMap} / {@link mutationMap}: задаёт стратегию
|
|
131
|
+
* конкуренции между перекрывающимися срабатываниями (switchMap / exhaustMap / mergeMap / concatMap).
|
|
132
|
+
* Сигнатура совпадает с rxjs-операторами, поэтому их можно передавать напрямую.
|
|
133
|
+
*/
|
|
134
|
+
export type FlattenOperator = <A, R>(project: (value: A) => Observable<R>) => OperatorFunction<A, R>;
|
|
135
|
+
/**
|
|
136
|
+
* Общая конфигурация обработки запроса. Используется и для чтения ({@link validateMap}),
|
|
137
|
+
* и для записи ({@link mutationMap}) — единый словарь.
|
|
94
138
|
*/
|
|
95
|
-
export
|
|
139
|
+
export interface RequestMapConfig<T, Body, TResult> {
|
|
140
|
+
/** Гейт перед запросом: `conditions` все true → запрос; иначе `skipAction` (или no-op). */
|
|
96
141
|
validator?: (value: T) => ValidateConfig;
|
|
142
|
+
/**
|
|
143
|
+
* Асинхронная сборка тела запроса ПЕРЕД apiCall (FormData, blob'ы, теги). Результат приходит
|
|
144
|
+
* вторым аргументом в apiCall. Нет prepare → body = undefined. Для чтения обычно не нужен.
|
|
145
|
+
*/
|
|
146
|
+
prepare?: (value: T) => Body | Promise<Body>;
|
|
97
147
|
/** Вызывается после успешной валидации, перед apiCall. Типичное использование — dispatch loading-статуса. */
|
|
98
148
|
loadingAction?: (value: T) => void;
|
|
99
149
|
/** Вызывается при ошибке в apiCall (catchError). Получает ошибку + те же данные что loadingAction/apiCall. */
|
|
100
150
|
errorAction?: (error: any, value: T) => void;
|
|
151
|
+
/** Сам запрос: из value (+ собранного prepare тела) строим поток. Успех обрабатывается внутри через apiResult. */
|
|
152
|
+
apiCall: (value: T, body: Body, utils: ValidateMapRequestUtils) => Observable<TResult>;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Оператор для ЧТЕНИЯ (запросов-ресурсов): валидация → loading → apiCall, стратегия switchMap
|
|
156
|
+
* («последний выигрывает», отменяет устаревший in-flight запрос). Для записи используйте
|
|
157
|
+
* {@link mutationMap} — switchMap отменял бы in-flight мутацию (потеря ответа уже закоммиченной
|
|
158
|
+
* записи, отмена первого сабмита вместо игнора дубля).
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* ```ts
|
|
162
|
+
* action$.pipe(
|
|
163
|
+
* ofType(d.loadPosts),
|
|
164
|
+
* validateMap({
|
|
165
|
+
* validator: ([, { status }]) => ({ conditions: [status !== ApiStatus.Loading] }),
|
|
166
|
+
* loadingAction: () => d.loadPosts.loading(),
|
|
167
|
+
* errorAction: (err) => d.loadPosts.failure(getErrorMessage(err)),
|
|
168
|
+
* apiCall: ([action]) =>
|
|
169
|
+
* fromRequest(api.getPosts.request(action.payload)).pipe(
|
|
170
|
+
* apiResult((page) => { d.applyPosts(page); d.loadPosts.success() }),
|
|
171
|
+
* ),
|
|
172
|
+
* }),
|
|
173
|
+
* )
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export declare function validateMap<T, TResult = any>(config: {
|
|
177
|
+
validator?: (value: T) => ValidateConfig;
|
|
178
|
+
loadingAction?: (value: T) => void;
|
|
179
|
+
errorAction?: (error: any, value: T) => void;
|
|
101
180
|
apiCall: (value: T, utils: ValidateMapRequestUtils) => Observable<TResult>;
|
|
102
181
|
}): OperatorFunction<T, any>;
|
|
182
|
+
/**
|
|
183
|
+
* Оператор для ЗАПИСИ (мутаций). Тот же словарь, что у {@link validateMap}, плюс два понятия:
|
|
184
|
+
* - `flatten` — стратегия конкуренции (rxjs-оператор). У записи нет одного правильного варианта,
|
|
185
|
+
* поэтому его выбирает вызывающий под смысл операции:
|
|
186
|
+
* • `exhaustMap` — одиночная операция (форма create/update): дабл-сабмит игнорируется,
|
|
187
|
+
* in-flight НЕ отменяется;
|
|
188
|
+
* • `mergeMap` — операции над разными сущностями (delete/toggle/repost): параллельность;
|
|
189
|
+
* • `concatMap` — строго по очереди.
|
|
190
|
+
* - `prepare` — асинхронная сборка тела (FormData, blob'ы) перед запросом; результат приходит
|
|
191
|
+
* вторым аргументом в apiCall.
|
|
192
|
+
*
|
|
193
|
+
* Успех/статусы ведутся ВНУТРИ apiCall через apiResult — единообразно с {@link validateMap}.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* action$.pipe(
|
|
198
|
+
* ofType(d.createPost),
|
|
199
|
+
* mutationMap({
|
|
200
|
+
* flatten: exhaustMap,
|
|
201
|
+
* loadingAction: () => d.createPost.loading(),
|
|
202
|
+
* errorAction: (err) => d.createPost.failure(getErrorMessage(err)),
|
|
203
|
+
* prepare: (payload) => buildCreateBody(api, payload),
|
|
204
|
+
* apiCall: (_payload, body) =>
|
|
205
|
+
* fromRequest(api.createPost.request({ body })).pipe(
|
|
206
|
+
* apiResult((post) => { d.createPost.success(); d.prependPost(post) }),
|
|
207
|
+
* ),
|
|
208
|
+
* }),
|
|
209
|
+
* )
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export declare function mutationMap<T, Body = void, TResult = any>({ flatten, validator, prepare, loadingAction, errorAction, apiCall, }: {
|
|
213
|
+
flatten: FlattenOperator;
|
|
214
|
+
} & RequestMapConfig<T, Body, TResult>): OperatorFunction<T, any>;
|
|
103
215
|
/**
|
|
104
216
|
* Метаданные ответа API, доступные в колбэках apiResult.
|
|
105
217
|
*/
|
|
@@ -154,7 +266,7 @@ export declare function apiResult<TData, TResult = void>(onSuccess: (data: TData
|
|
|
154
266
|
* Класс для управления эффектами с поддержкой доступа к состоянию и контексту
|
|
155
267
|
* Основной класс, который следует использовать
|
|
156
268
|
*/
|
|
157
|
-
export declare class EffectsModule<TState extends Record<string, any> = any, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string,
|
|
269
|
+
export declare class EffectsModule<TState extends Record<string, any> = any, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>, TExternalStates extends ExternalStates = Record<string, never>> {
|
|
158
270
|
private storage;
|
|
159
271
|
private dispatcher;
|
|
160
272
|
private externalDispatchers;
|
|
@@ -215,11 +327,10 @@ export declare class EffectsModule<TState extends Record<string, any> = any, TDi
|
|
|
215
327
|
/**
|
|
216
328
|
* Вспомогательная функция для создания типизированного эффекта
|
|
217
329
|
*/
|
|
218
|
-
export declare function createEffect<TState extends Record<string, any>, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string,
|
|
330
|
+
export declare function createEffect<TState extends Record<string, any>, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>, TExternalStates extends ExternalStates = Record<string, never>>(effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>;
|
|
219
331
|
/**
|
|
220
332
|
* Объединяет несколько эффектов в один
|
|
221
333
|
* @param effects Эффекты для объединения
|
|
222
334
|
* @returns Объединенный эффект
|
|
223
335
|
*/
|
|
224
|
-
export declare function combineEffects<TState extends Record<string, any>, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string,
|
|
225
|
-
//# sourceMappingURL=effects.module.d.ts.map
|
|
336
|
+
export declare function combineEffects<TState extends Record<string, any>, TDispatcher = any, TServices extends Record<string, any> = Record<string, never>, TConfig extends Record<string, any> = Record<string, never>, TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>, TExternalStates extends ExternalStates = Record<string, never>>(...effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[]): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EMPTY, Observable, Subject, combineLatest, from, merge, of, pipe } from "rxjs";
|
|
2
|
-
import { catchError, filter, map, share, switchMap, take } from "rxjs/operators";
|
|
2
|
+
import { catchError, filter, map, mergeMap, retry, share, switchMap, take } from "rxjs/operators";
|
|
3
3
|
import { handleCallbackError, logError } from "../../_utils/error-handling.util.js";
|
|
4
4
|
import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable } from "./utils/index.js";
|
|
5
5
|
|
|
@@ -11,6 +11,16 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Symbol-маркер, под которым опции эффекта ({@link EffectOptions}) хранятся на функции-эффекте.
|
|
16
|
+
* @internal
|
|
17
|
+
*/ const EFFECT_OPTIONS = Symbol('synapse.effect.options');
|
|
18
|
+
/**
|
|
19
|
+
* Symbol-маркер с именем эффекта (имя поля class-слоя `Effects`). Проставляется
|
|
20
|
+
* `Effects.getEffects()` для диагностики — EffectsModule использует его, чтобы в
|
|
21
|
+
* предупреждении об упавшем эффекте назвать конкретный эффект.
|
|
22
|
+
* @internal
|
|
23
|
+
*/ const EFFECT_NAME = Symbol('synapse.effect.name');
|
|
14
24
|
/**
|
|
15
25
|
* Оператор для фильтрации действий по типу с сохранением типа payload
|
|
16
26
|
*/ function ofType(actionFn) {
|
|
@@ -100,17 +110,30 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
100
110
|
}));
|
|
101
111
|
}
|
|
102
112
|
/**
|
|
103
|
-
*
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
* Общее ядро обработки запроса. Накладывает на поток триггеров единый пайп:
|
|
114
|
+
* [validator] → loadingAction → [prepare] → apiCall → (apiResult success) / errorAction.
|
|
115
|
+
*
|
|
116
|
+
* Стратегию конкуренции задаёт `flatten`:
|
|
117
|
+
* - `switchMap` — последний выигрывает, отменяет in-flight (ЧТЕНИЕ, см. {@link validateMap});
|
|
118
|
+
* - `exhaustMap` — одиночная операция, дабл-сабмит игнорируется, in-flight НЕ отменяется (формы);
|
|
119
|
+
* - `mergeMap` — независимые операции над разными сущностями (реальная параллельность);
|
|
120
|
+
* - `concatMap` — строго по очереди.
|
|
121
|
+
*
|
|
122
|
+
* catchError стоит ВНУТРИ проекции flatten — ошибка одного запроса не валит весь поток эффекта
|
|
123
|
+
* (важно для mergeMap: падение одного удаления не убивает остальные).
|
|
124
|
+
* @internal
|
|
125
|
+
*/ function requestMap(flatten, { validator, prepare, loadingAction, errorAction, apiCall }) {
|
|
126
|
+
return pipe(flatten((pipeData)=>{
|
|
106
127
|
/**
|
|
107
128
|
* Функция вызова API-метода
|
|
108
129
|
*/ const callApi = ()=>{
|
|
109
130
|
if (loadingAction) loadingAction(pipeData);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
131
|
+
// нет prepare → пустое тело; иначе резол body (sync/async) перед запросом
|
|
132
|
+
const body$ = prepare ? from(Promise.resolve(prepare(pipeData))) : of(undefined);
|
|
133
|
+
const apiCall$ = body$.pipe(mergeMap((body)=>apiCall(pipeData, body, {
|
|
134
|
+
chunkRequest: chunkRequestParallel,
|
|
135
|
+
chunkRequestConsistent: chunkRequestConsistent
|
|
136
|
+
})));
|
|
114
137
|
if (!errorAction) return apiCall$;
|
|
115
138
|
return apiCall$.pipe(catchError((err)=>{
|
|
116
139
|
errorAction(err, pipeData);
|
|
@@ -124,17 +147,86 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
124
147
|
const { conditions, skipAction } = validateConfig;
|
|
125
148
|
const conditionMet = conditions.every(Boolean);
|
|
126
149
|
/**
|
|
127
|
-
* Если валидация не пройдена - вызываем экшн
|
|
150
|
+
* Если валидация не пройдена - вызываем экшн сброса.
|
|
151
|
+
* skipAction не задан → ничего не делаем (no-op по умолчанию).
|
|
128
152
|
*/ if (!conditionMet) {
|
|
153
|
+
if (skipAction === undefined) return EMPTY;
|
|
129
154
|
if (Array.isArray(skipAction)) {
|
|
130
|
-
|
|
131
|
-
return of(...skipAction?.filter(Boolean).map((action)=>typeof action === 'function' ? action() : action));
|
|
155
|
+
return of(...skipAction.filter(Boolean).map((action)=>typeof action === 'function' ? action() : action));
|
|
132
156
|
}
|
|
133
157
|
return of(typeof skipAction === 'function' ? skipAction() : skipAction);
|
|
134
158
|
}
|
|
135
159
|
return callApi();
|
|
136
160
|
}));
|
|
137
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Оператор для ЧТЕНИЯ (запросов-ресурсов): валидация → loading → apiCall, стратегия switchMap
|
|
164
|
+
* («последний выигрывает», отменяет устаревший in-flight запрос). Для записи используйте
|
|
165
|
+
* {@link mutationMap} — switchMap отменял бы in-flight мутацию (потеря ответа уже закоммиченной
|
|
166
|
+
* записи, отмена первого сабмита вместо игнора дубля).
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```ts
|
|
170
|
+
* action$.pipe(
|
|
171
|
+
* ofType(d.loadPosts),
|
|
172
|
+
* validateMap({
|
|
173
|
+
* validator: ([, { status }]) => ({ conditions: [status !== ApiStatus.Loading] }),
|
|
174
|
+
* loadingAction: () => d.loadPosts.loading(),
|
|
175
|
+
* errorAction: (err) => d.loadPosts.failure(getErrorMessage(err)),
|
|
176
|
+
* apiCall: ([action]) =>
|
|
177
|
+
* fromRequest(api.getPosts.request(action.payload)).pipe(
|
|
178
|
+
* apiResult((page) => { d.applyPosts(page); d.loadPosts.success() }),
|
|
179
|
+
* ),
|
|
180
|
+
* }),
|
|
181
|
+
* )
|
|
182
|
+
* ```
|
|
183
|
+
*/ function validateMap(config) {
|
|
184
|
+
return requestMap(switchMap, {
|
|
185
|
+
validator: config.validator,
|
|
186
|
+
loadingAction: config.loadingAction,
|
|
187
|
+
errorAction: config.errorAction,
|
|
188
|
+
// adapter: публичный apiCall чтения принимает (value, utils); ядро зовёт (value, body, utils)
|
|
189
|
+
apiCall: (value, _body, utils)=>config.apiCall(value, utils)
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Оператор для ЗАПИСИ (мутаций). Тот же словарь, что у {@link validateMap}, плюс два понятия:
|
|
194
|
+
* - `flatten` — стратегия конкуренции (rxjs-оператор). У записи нет одного правильного варианта,
|
|
195
|
+
* поэтому его выбирает вызывающий под смысл операции:
|
|
196
|
+
* • `exhaustMap` — одиночная операция (форма create/update): дабл-сабмит игнорируется,
|
|
197
|
+
* in-flight НЕ отменяется;
|
|
198
|
+
* • `mergeMap` — операции над разными сущностями (delete/toggle/repost): параллельность;
|
|
199
|
+
* • `concatMap` — строго по очереди.
|
|
200
|
+
* - `prepare` — асинхронная сборка тела (FormData, blob'ы) перед запросом; результат приходит
|
|
201
|
+
* вторым аргументом в apiCall.
|
|
202
|
+
*
|
|
203
|
+
* Успех/статусы ведутся ВНУТРИ apiCall через apiResult — единообразно с {@link validateMap}.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* action$.pipe(
|
|
208
|
+
* ofType(d.createPost),
|
|
209
|
+
* mutationMap({
|
|
210
|
+
* flatten: exhaustMap,
|
|
211
|
+
* loadingAction: () => d.createPost.loading(),
|
|
212
|
+
* errorAction: (err) => d.createPost.failure(getErrorMessage(err)),
|
|
213
|
+
* prepare: (payload) => buildCreateBody(api, payload),
|
|
214
|
+
* apiCall: (_payload, body) =>
|
|
215
|
+
* fromRequest(api.createPost.request({ body })).pipe(
|
|
216
|
+
* apiResult((post) => { d.createPost.success(); d.prependPost(post) }),
|
|
217
|
+
* ),
|
|
218
|
+
* }),
|
|
219
|
+
* )
|
|
220
|
+
* ```
|
|
221
|
+
*/ function mutationMap({ flatten, validator, prepare, loadingAction, errorAction, apiCall }) {
|
|
222
|
+
return requestMap(flatten, {
|
|
223
|
+
validator,
|
|
224
|
+
prepare,
|
|
225
|
+
loadingAction,
|
|
226
|
+
errorAction,
|
|
227
|
+
apiCall
|
|
228
|
+
});
|
|
229
|
+
}
|
|
138
230
|
/**
|
|
139
231
|
* Ошибка API-запроса. Бросается apiResult при !result.ok.
|
|
140
232
|
* Ловится errorAction в validateMap.
|
|
@@ -256,7 +348,7 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
256
348
|
add(effect) {
|
|
257
349
|
this.effects.push(effect);
|
|
258
350
|
if (this.running) {
|
|
259
|
-
this.subscribeToEffect(effect);
|
|
351
|
+
this.subscribeToEffect(effect, this.effects.length - 1);
|
|
260
352
|
}
|
|
261
353
|
return this;
|
|
262
354
|
}
|
|
@@ -279,7 +371,7 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
279
371
|
await this.storage.waitForReady();
|
|
280
372
|
// Переподписываемся на dispatchers (подписки были очищены в stop())
|
|
281
373
|
this.subscribeToDispatchers();
|
|
282
|
-
this.effects.forEach((effect)=>this.subscribeToEffect(effect));
|
|
374
|
+
this.effects.forEach((effect, index)=>this.subscribeToEffect(effect, index));
|
|
283
375
|
this.running = true;
|
|
284
376
|
return this;
|
|
285
377
|
}
|
|
@@ -297,7 +389,7 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
297
389
|
/**
|
|
298
390
|
* Подписывается на конкретный эффект
|
|
299
391
|
* @param effect Эффект для подписки
|
|
300
|
-
*/ subscribeToEffect(effect) {
|
|
392
|
+
*/ subscribeToEffect(effect, index = 0) {
|
|
301
393
|
try {
|
|
302
394
|
const context = {
|
|
303
395
|
dispatcher: this.dispatcher,
|
|
@@ -306,8 +398,28 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
306
398
|
services: this.services,
|
|
307
399
|
config: this.config
|
|
308
400
|
};
|
|
309
|
-
|
|
310
|
-
|
|
401
|
+
let stream$ = effect(this.action$.asObservable(), this.state$, context);
|
|
402
|
+
// resubscribeOnError: переподписываемся на поток вместо терминального завершения.
|
|
403
|
+
// Лимит ретраев исчерпан → ошибка уходит в терминальный catchError ниже
|
|
404
|
+
// (эффект умирает, остальные продолжают работать).
|
|
405
|
+
const options = effect[EFFECT_OPTIONS];
|
|
406
|
+
const resubscribeOnError = options?.resubscribeOnError;
|
|
407
|
+
const resubscribes = !!resubscribeOnError;
|
|
408
|
+
if (resubscribeOnError) {
|
|
409
|
+
const config = resubscribeOnError === true ? {} : resubscribeOnError;
|
|
410
|
+
stream$ = stream$.pipe(retry({
|
|
411
|
+
count: config.count ?? Infinity,
|
|
412
|
+
delay: config.delay,
|
|
413
|
+
resetOnSuccess: true
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
// Имя эффекта (поле class-слоя Effects) — для понятного предупреждения; иначе индекс.
|
|
417
|
+
const effectLabel = effect[EFFECT_NAME] ?? `#${index}`;
|
|
418
|
+
const output$ = stream$.pipe(catchError((err)=>{
|
|
419
|
+
// Поток эффекта дошёл до терминальной ошибки → этот эффект БОЛЬШЕ не реагирует
|
|
420
|
+
// на экшены (остальные живы). Громкое сообщение, чтобы это не прошло незаметно.
|
|
421
|
+
const tail = resubscribes ? 'resubscribeOnError исчерпал лимит ретраев.' : 'Чтобы эффект переподписывался после ошибки, добавьте { resubscribeOnError: true } в this.effect(fn, …).';
|
|
422
|
+
handleCallbackError(`EffectsModule: эффект "${effectLabel}" УПАЛ и больше не будет реагировать на экшены (поток завершён). ${tail}`, err);
|
|
311
423
|
return of(null);
|
|
312
424
|
}));
|
|
313
425
|
const subscription = output$.subscribe((result)=>{
|
|
@@ -351,6 +463,6 @@ import { chunkRequestConsistent, chunkRequestParallel, isStorage, toObservable }
|
|
|
351
463
|
};
|
|
352
464
|
}
|
|
353
465
|
|
|
354
|
-
export { ApiError, EffectsModule, apiResult, combineEffects, createEffect, ofType, ofTypes, ofTypesWaitAll, selectorMap, selectorObject, validateMap };
|
|
466
|
+
export { ApiError, EFFECT_NAME, EFFECT_OPTIONS, EffectsModule, apiResult, combineEffects, createEffect, mutationMap, ofType, ofTypes, ofTypesWaitAll, selectorMap, selectorObject, validateMap };
|
|
355
467
|
|
|
356
468
|
//# sourceMappingURL=effects.module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactive/effects/effects.module.js","sources":["../../../src/reactive/effects/effects.module.ts"],"sourcesContent":["import { combineLatest, EMPTY, from, merge, Observable, of, OperatorFunction, pipe, Subject } from 'rxjs'\nimport { catchError, filter, map, share, switchMap, take } from 'rxjs/operators'\n\nimport { handleCallbackError, logError } from '../../_utils/error-handling.util'\nimport { IStorage, IStorageBase } from '../../core'\nimport { Action, ActionsResult, Dispatcher, DispatchFunction, ExtractResultType, WatcherFunction } from '../dispatcher'\nimport { ChunkRequestConsistent, chunkRequestConsistent, ChunkRequestParallel, chunkRequestParallel, isStorage, toObservable } from './utils'\n\n/**\n * Тип действия с типизированным payload\n */\nexport interface TypedAction<P> extends Action<P> {\n type: string\n payload: P\n}\n\n/**\n * Тип для внешних состояний — Observable или хранилище (IStorageBase), которое автоматически конвертируется в Observable\n */\nexport type ExternalStates = Record<string, Observable<any> | IStorageBase<any>>\n\n/**\n * Контекст эффекта — объект с зависимостями, передаваемый третьим аргументом\n */\nexport interface EffectContext<\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> {\n /** Основной dispatcher текущего synapse */\n dispatcher: TDispatcher\n /** Внешние dispatcher'ы из других synapse */\n externalDispatchers: TExternalDispatchers\n /** Внешние состояния — Observable'ы от других хранилищ (Synapse.state$, или любой Observable) */\n externalStates: TExternalStates\n /** Сервисы (API-клиенты и т.д.) */\n services: TServices\n /** Глобальная конфигурация для эффектов */\n config: TConfig\n}\n\n/**\n * Тип для эффекта с доступом к состоянию и контексту — основной тип\n */\nexport type Effect<\n TState extends Record<string, any> = any,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> = (action$: Observable<Action>, state$: Observable<TState>, context: EffectContext<TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>) => 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 logError('ofType: action function does not have actionType property', actionFn, null, 'warn')\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 logError('ofTypes: no valid action types found in array', actionFns, null, 'warn')\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 *\n * **Важно:** Использует `combineLatest` — Observable не эмитит, пока КАЖДЫЙ из\n * указанных action не будет диспатчнут хотя бы один раз. Если хотя бы один action\n * никогда не будет вызван, поток зависнет навсегда без уведомления.\n * Убедитесь, что все указанные actions гарантированно будут диспатчнуты,\n * либо используйте `ofTypes` с ручной агрегацией при необходимости таймаута.\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 logError('ofTypesWaitAll: no valid action types found in array', actionFns, null, 'warn')\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 loadingAction,\n errorAction,\n apiCall,\n}: {\n validator?: (value: T) => ValidateConfig\n /** Вызывается после успешной валидации, перед apiCall. Типичное использование — dispatch loading-статуса. */\n loadingAction?: (value: T) => void\n /** Вызывается при ошибке в apiCall (catchError). Получает ошибку + те же данные что loadingAction/apiCall. */\n errorAction?: (error: any, value: T) => void\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 if (loadingAction) loadingAction(pipeData)\n\n const apiCall$ = apiCall(pipeData, {\n chunkRequest: chunkRequestParallel,\n chunkRequestConsistent: chunkRequestConsistent,\n })\n\n if (!errorAction) return apiCall$\n\n return apiCall$.pipe(\n catchError((err) => {\n errorAction(err, pipeData)\n return EMPTY\n }),\n )\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 * Метаданные ответа API, доступные в колбэках apiResult.\n */\nexport interface ApiResultMeta {\n status: number\n statusText: string\n headers: Headers\n fromCache?: boolean\n}\n\n/**\n * Ошибка API-запроса. Бросается apiResult при !result.ok.\n * Ловится errorAction в validateMap.\n */\nexport class ApiError extends Error {\n constructor(\n public readonly originalError: any,\n public readonly meta: ApiResultMeta,\n ) {\n super(typeof originalError === 'string' ? originalError : (originalError?.message ?? 'API request failed'))\n this.name = 'ApiError'\n }\n}\n\n/**\n * Оператор для обработки успешного результата API-запроса (QueryResult).\n *\n * При `result.ok` — вызывает callback с `data` и `meta`.\n * При `!result.ok` — бросает `ApiError`, который ловится `errorAction` в `validateMap`.\n *\n * @example\n * ```ts\n * // Простой случай\n * validateMap({\n * errorAction: (err) => dispatcher.dispatch.loadError(String(err)),\n * apiCall: () => from(api.request('getList', params)).pipe(\n * apiResult((data) => dispatcher.dispatch.loadSuccess(data)),\n * ),\n * })\n *\n * // С доступом к headers (пагинация)\n * apiResult((data, meta) => {\n * const total = Number(meta.headers.get('X-Total-Count'))\n * dispatcher.dispatch.loadSuccess({ items: data, total })\n * })\n * ```\n */\nexport function apiResult<TData, TResult = void>(\n onSuccess: (data: TData, meta: ApiResultMeta) => TResult | Promise<TResult>,\n): OperatorFunction<{ ok: boolean; data?: TData; error?: any; status?: number; statusText?: string; headers?: Headers; fromCache?: boolean }, TResult> {\n return pipe(\n switchMap((result) => {\n const meta: ApiResultMeta = {\n status: result.status ?? 0,\n statusText: result.statusText ?? '',\n headers: result.headers ?? new Headers(),\n fromCache: result.fromCache,\n }\n if (result.ok && result.data !== undefined) {\n const out = onSuccess(result.data, meta)\n return from(Promise.resolve(out))\n }\n throw new ApiError(result.error ?? 'Unknown error', meta)\n }),\n )\n}\n\n/**\n * Класс для управления эффектами с поддержкой доступа к состоянию и контексту\n * Основной класс, который следует использовать\n */\nexport class EffectsModule<\n TState extends Record<string, any> = any,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> {\n private effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[] = []\n private subscriptions: Array<{ unsubscribe: VoidFunction }> = []\n private running = false\n private action$ = new Subject<Action>()\n private externalStates: TExternalStates\n\n /**\n * Поток состояния\n */\n public readonly state$: Observable<TState>\n\n /**\n * Создает модуль эффектов\n * @param storage Хранилище состояния\n * @param dispatcher Основной dispatcher текущего synapse\n * @param externalDispatchers Внешние dispatcher'ы из других synapse\n * @param services Сервисы (API-клиенты и т.д.)\n * @param config Глобальная конфигурация для всех эффектов\n * @param externalStates Внешние состояния (Observable'ы от других хранилищ)\n */\n constructor(\n private storage: IStorage<TState>,\n private dispatcher: TDispatcher & { actions: Observable<Action> },\n private externalDispatchers: TExternalDispatchers = {} as TExternalDispatchers,\n private services: TServices = {} as TServices,\n private config: TConfig = {} as TConfig,\n externalStates: TExternalStates = {} as TExternalStates,\n ) {\n // Нормализуем externalStates: конвертируем storage → Observable\n this.externalStates = this.normalizeExternalStates(externalStates)\n\n // Создаем поток состояния\n this.state$ = new Observable<TState>((observer) => {\n // Отправляем начальное состояние\n Promise.resolve(this.storage.getState()).then((state: TState) => observer.next(state))\n\n // Подписываемся на все изменения\n const unsubscribe = this.storage.subscribeToAll(() => {\n Promise.resolve(this.storage.getState()).then((state: TState) => observer.next(state))\n })\n\n // Отписываемся при завершении\n return () => unsubscribe()\n }).pipe(share())\n }\n\n /**\n * Нормализует externalStates: конвертирует IStorageBase в Observable, пропускает Observable как есть\n */\n private normalizeExternalStates(states: TExternalStates): TExternalStates {\n const normalized = {} as Record<string, Observable<any>>\n for (const [key, value] of Object.entries(states)) {\n normalized[key] = isStorage(value) ? toObservable(value) : value\n }\n return normalized as TExternalStates\n }\n\n /**\n * Подписывается на действия от основного dispatcher'а и внешних dispatcher'ов\n */\n private subscribeToDispatchers() {\n // Основной dispatcher\n const mainSub = this.dispatcher.actions.subscribe((action) => {\n this.action$.next(action)\n })\n this.subscriptions.push(mainSub)\n\n // Внешние dispatcher'ы\n for (const [_, dispatcher] of Object.entries(this.externalDispatchers)) {\n const subscription = dispatcher.actions.subscribe((action) => {\n this.action$.next(action)\n })\n this.subscriptions.push(subscription)\n }\n }\n\n add(effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, 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, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[]): this {\n effects.forEach((effect) => this.add(effect))\n return this\n }\n\n /**\n * Запускает все эффекты\n * @returns Текущий модуль\n */\n async start(): Promise<this> {\n if (this.running) {\n return this\n }\n // Ждем готовности основного хранилища\n await this.storage.waitForReady()\n\n // Переподписываемся на dispatchers (подписки были очищены в stop())\n this.subscribeToDispatchers()\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.action$.complete()\n this.action$ = new Subject<Action>()\n this.running = false\n\n return this\n }\n\n /**\n * Подписывается на конкретный эффект\n * @param effect Эффект для подписки\n */\n private subscribeToEffect(effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>): void {\n try {\n const context: EffectContext<TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> = {\n dispatcher: this.dispatcher,\n externalDispatchers: this.externalDispatchers,\n externalStates: this.externalStates,\n services: this.services,\n config: this.config,\n }\n\n const output$ = effect(this.action$.asObservable(), this.state$, context).pipe(\n catchError((err) => {\n handleCallbackError('EffectsModule: 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 handleCallbackError('EffectsModule: error calling effect result function', callError)\n }\n }\n })\n\n this.subscriptions.push(subscription)\n } catch (setupError) {\n handleCallbackError('EffectsModule: error setting up effect', setupError)\n }\n }\n}\n\n/**\n * Вспомогательная функция для создания типизированного эффекта\n */\nexport function createEffect<\n TState extends Record<string, any>,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(\n effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>,\n): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> {\n return effect\n}\n\n/**\n * Объединяет несколько эффектов в один\n * @param effects Эффекты для объединения\n * @returns Объединенный эффект\n */\nexport function combineEffects<\n TState extends Record<string, any>,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, Dispatcher<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(\n ...effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[]\n): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> {\n return (action$, state$, context) => {\n const outputs = effects.map((effect) => {\n try {\n return effect(action$, state$, context)\n } catch (error) {\n handleCallbackError('combineEffects: error in one of combined effects', error)\n return of(null)\n }\n })\n return merge(...outputs)\n }\n}\n"],"names":["combineLatest","EMPTY","from","merge","Observable","of","pipe","Subject","catchError","filter","map","share","switchMap","take","handleCallbackError","logError","chunkRequestConsistent","chunkRequestParallel","isStorage","toObservable","ofType","actionFn","actionType","source$","action","undefined","ofTypes","actionFns","actionTypes","fn","Boolean","ofTypesWaitAll","actionStreams","type","index","results","a","b","r","selectorMap","state$","selectors","state","selector","selectorObject","result","key","Object","validateMap","validator","loadingAction","errorAction","apiCall","pipeData","callApi","apiCall$","err","validateConfig","conditions","skipAction","conditionMet","Array","ApiError","Error","originalError","meta","apiResult","onSuccess","Headers","out","Promise","EffectsModule","storage","dispatcher","externalDispatchers","services","config","externalStates","observer","unsubscribe","states","normalized","value","mainSub","_","subscription","effect","effects","sub","context","output$","callError","setupError","createEffect","combineEffects","action$","outputs","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reactive/effects/effects.module.js","sources":["../../../src/reactive/effects/effects.module.ts"],"sourcesContent":["import { combineLatest, EMPTY, from, merge, Observable, of, OperatorFunction, pipe, Subject } from 'rxjs'\nimport { catchError, filter, map, mergeMap, retry, share, switchMap, take } from 'rxjs/operators'\n\nimport { handleCallbackError, logError } from '../../_utils/error-handling.util'\nimport { IStorage, IStorageBase } from '../../core'\nimport { Action, ActionsResult, DispatcherCore, DispatchFunction, ExtractResultType, WatcherFunction } from '../dispatcher'\nimport { ChunkRequestConsistent, chunkRequestConsistent, ChunkRequestParallel, chunkRequestParallel, isStorage, toObservable } from './utils'\n\n/**\n * Тип действия с типизированным payload\n */\nexport interface TypedAction<P> extends Action<P> {\n type: string\n payload: P\n}\n\n/**\n * Тип для внешних состояний — Observable или хранилище (IStorageBase), которое автоматически конвертируется в Observable\n */\nexport type ExternalStates = Record<string, Observable<any> | IStorageBase<any>>\n\n/**\n * Контекст эффекта — объект с зависимостями, передаваемый третьим аргументом\n */\nexport interface EffectContext<\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> {\n /** Основной dispatcher текущего synapse */\n dispatcher: TDispatcher\n /** Внешние dispatcher'ы из других synapse */\n externalDispatchers: TExternalDispatchers\n /** Внешние состояния — Observable'ы от других хранилищ (Synapse.state$, или любой Observable) */\n externalStates: TExternalStates\n /** Сервисы (API-клиенты и т.д.) */\n services: TServices\n /** Глобальная конфигурация для эффектов */\n config: TConfig\n}\n\n/**\n * Тип для эффекта с доступом к состоянию и контексту — основной тип\n */\nexport type Effect<\n TState extends Record<string, any> = any,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> = (action$: Observable<Action>, state$: Observable<TState>, context: EffectContext<TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>) => Observable<unknown>\n\n/**\n * Опции конкретного эффекта. Прикрепляются к функции-эффекту через {@link EFFECT_OPTIONS}\n * (это делает `Effects.effect(fn, options)` из базового класса). EffectsModule читает их\n * при подписке.\n */\nexport interface EffectOptions {\n /**\n * Переподписаться на поток при непойманной ошибке вместо терминального завершения.\n *\n * - `true` — бесконечный немедленный resubscribe;\n * - `{ count, delay }` — лимит ретраев и задержка (мс) между ними (см. rxjs `retry`).\n *\n * По умолчанию (опция не задана) — текущее поведение: ошибка завершает эффект,\n * остальные продолжают работать.\n */\n resubscribeOnError?: boolean | { count?: number; delay?: number }\n}\n\n/**\n * Symbol-маркер, под которым опции эффекта ({@link EffectOptions}) хранятся на функции-эффекте.\n * @internal\n */\nexport const EFFECT_OPTIONS = Symbol('synapse.effect.options')\n\n/**\n * Symbol-маркер с именем эффекта (имя поля class-слоя `Effects`). Проставляется\n * `Effects.getEffects()` для диагностики — EffectsModule использует его, чтобы в\n * предупреждении об упавшем эффекте назвать конкретный эффект.\n * @internal\n */\nexport const EFFECT_NAME = Symbol('synapse.effect.name')\n\n/**\n * Тип для получения типов действий диспетчера\n */\nexport type DispatcherActions<T> = T extends DispatcherCore<any, infer A> ? ActionsResult<A> : Record<string, DispatchFunction<any, any>>\n\n/**\n * Конфигурация для валидации в validateMap\n */\nexport interface ValidateConfig {\n conditions: boolean[]\n /**\n * Что сделать, если валидация не прошла. Необязательно: если не задано — эффект просто\n * ничего не делает (поток завершается без эмита). Это убирает повторяющийся бойлерплейт\n * `skipAction: () => d.loadX.reset()` там, где сбрасывать нечего.\n */\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 logError('ofType: action function does not have actionType property', actionFn, null, 'warn')\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 logError('ofTypes: no valid action types found in array', actionFns, null, 'warn')\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 *\n * **Важно:** Использует `combineLatest` — Observable не эмитит, пока КАЖДЫЙ из\n * указанных action не будет диспатчнут хотя бы один раз. Если хотя бы один action\n * никогда не будет вызван, поток зависнет навсегда без уведомления.\n * Убедитесь, что все указанные actions гарантированно будут диспатчнуты,\n * либо используйте `ofTypes` с ручной агрегацией при необходимости таймаута.\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 logError('ofTypesWaitAll: no valid action types found in array', actionFns, null, 'warn')\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 * Оператор наложения (flattening) для {@link requestMap} / {@link mutationMap}: задаёт стратегию\n * конкуренции между перекрывающимися срабатываниями (switchMap / exhaustMap / mergeMap / concatMap).\n * Сигнатура совпадает с rxjs-операторами, поэтому их можно передавать напрямую.\n */\nexport type FlattenOperator = <A, R>(project: (value: A) => Observable<R>) => OperatorFunction<A, R>\n\n/**\n * Общая конфигурация обработки запроса. Используется и для чтения ({@link validateMap}),\n * и для записи ({@link mutationMap}) — единый словарь.\n */\nexport interface RequestMapConfig<T, Body, TResult> {\n /** Гейт перед запросом: `conditions` все true → запрос; иначе `skipAction` (или no-op). */\n validator?: (value: T) => ValidateConfig\n /**\n * Асинхронная сборка тела запроса ПЕРЕД apiCall (FormData, blob'ы, теги). Результат приходит\n * вторым аргументом в apiCall. Нет prepare → body = undefined. Для чтения обычно не нужен.\n */\n prepare?: (value: T) => Body | Promise<Body>\n /** Вызывается после успешной валидации, перед apiCall. Типичное использование — dispatch loading-статуса. */\n loadingAction?: (value: T) => void\n /** Вызывается при ошибке в apiCall (catchError). Получает ошибку + те же данные что loadingAction/apiCall. */\n errorAction?: (error: any, value: T) => void\n /** Сам запрос: из value (+ собранного prepare тела) строим поток. Успех обрабатывается внутри через apiResult. */\n apiCall: (value: T, body: Body, utils: ValidateMapRequestUtils) => Observable<TResult>\n}\n\n/**\n * Общее ядро обработки запроса. Накладывает на поток триггеров единый пайп:\n * [validator] → loadingAction → [prepare] → apiCall → (apiResult success) / errorAction.\n *\n * Стратегию конкуренции задаёт `flatten`:\n * - `switchMap` — последний выигрывает, отменяет in-flight (ЧТЕНИЕ, см. {@link validateMap});\n * - `exhaustMap` — одиночная операция, дабл-сабмит игнорируется, in-flight НЕ отменяется (формы);\n * - `mergeMap` — независимые операции над разными сущностями (реальная параллельность);\n * - `concatMap` — строго по очереди.\n *\n * catchError стоит ВНУТРИ проекции flatten — ошибка одного запроса не валит весь поток эффекта\n * (важно для mergeMap: падение одного удаления не убивает остальные).\n * @internal\n */\nfunction requestMap<T, Body, TResult>(\n flatten: FlattenOperator,\n { validator, prepare, loadingAction, errorAction, apiCall }: RequestMapConfig<T, Body, TResult>,\n): OperatorFunction<T, any> {\n return pipe(\n flatten((pipeData: T) => {\n /**\n * Функция вызова API-метода\n */\n const callApi = () => {\n if (loadingAction) loadingAction(pipeData)\n\n // нет prepare → пустое тело; иначе резол body (sync/async) перед запросом\n const body$: Observable<Body> = prepare ? from(Promise.resolve(prepare(pipeData))) : of(undefined as Body)\n\n const apiCall$ = body$.pipe(\n mergeMap((body) =>\n apiCall(pipeData, body, {\n chunkRequest: chunkRequestParallel,\n chunkRequestConsistent: chunkRequestConsistent,\n }),\n ),\n )\n\n if (!errorAction) return apiCall$\n\n return apiCall$.pipe(\n catchError((err) => {\n errorAction(err, pipeData)\n return EMPTY\n }),\n )\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 * skipAction не задан → ничего не делаем (no-op по умолчанию).\n */\n if (!conditionMet) {\n if (skipAction === undefined) return EMPTY\n if (Array.isArray(skipAction)) {\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 * Оператор для ЧТЕНИЯ (запросов-ресурсов): валидация → loading → apiCall, стратегия switchMap\n * («последний выигрывает», отменяет устаревший in-flight запрос). Для записи используйте\n * {@link mutationMap} — switchMap отменял бы in-flight мутацию (потеря ответа уже закоммиченной\n * записи, отмена первого сабмита вместо игнора дубля).\n *\n * @example\n * ```ts\n * action$.pipe(\n * ofType(d.loadPosts),\n * validateMap({\n * validator: ([, { status }]) => ({ conditions: [status !== ApiStatus.Loading] }),\n * loadingAction: () => d.loadPosts.loading(),\n * errorAction: (err) => d.loadPosts.failure(getErrorMessage(err)),\n * apiCall: ([action]) =>\n * fromRequest(api.getPosts.request(action.payload)).pipe(\n * apiResult((page) => { d.applyPosts(page); d.loadPosts.success() }),\n * ),\n * }),\n * )\n * ```\n */\nexport function validateMap<T, TResult = any>(config: {\n validator?: (value: T) => ValidateConfig\n loadingAction?: (value: T) => void\n errorAction?: (error: any, value: T) => void\n apiCall: (value: T, utils: ValidateMapRequestUtils) => Observable<TResult>\n}): OperatorFunction<T, any> {\n return requestMap(switchMap, {\n validator: config.validator,\n loadingAction: config.loadingAction,\n errorAction: config.errorAction,\n // adapter: публичный apiCall чтения принимает (value, utils); ядро зовёт (value, body, utils)\n apiCall: (value, _body, utils) => config.apiCall(value, utils),\n })\n}\n\n/**\n * Оператор для ЗАПИСИ (мутаций). Тот же словарь, что у {@link validateMap}, плюс два понятия:\n * - `flatten` — стратегия конкуренции (rxjs-оператор). У записи нет одного правильного варианта,\n * поэтому его выбирает вызывающий под смысл операции:\n * • `exhaustMap` — одиночная операция (форма create/update): дабл-сабмит игнорируется,\n * in-flight НЕ отменяется;\n * • `mergeMap` — операции над разными сущностями (delete/toggle/repost): параллельность;\n * • `concatMap` — строго по очереди.\n * - `prepare` — асинхронная сборка тела (FormData, blob'ы) перед запросом; результат приходит\n * вторым аргументом в apiCall.\n *\n * Успех/статусы ведутся ВНУТРИ apiCall через apiResult — единообразно с {@link validateMap}.\n *\n * @example\n * ```ts\n * action$.pipe(\n * ofType(d.createPost),\n * mutationMap({\n * flatten: exhaustMap,\n * loadingAction: () => d.createPost.loading(),\n * errorAction: (err) => d.createPost.failure(getErrorMessage(err)),\n * prepare: (payload) => buildCreateBody(api, payload),\n * apiCall: (_payload, body) =>\n * fromRequest(api.createPost.request({ body })).pipe(\n * apiResult((post) => { d.createPost.success(); d.prependPost(post) }),\n * ),\n * }),\n * )\n * ```\n */\nexport function mutationMap<T, Body = void, TResult = any>({\n flatten,\n validator,\n prepare,\n loadingAction,\n errorAction,\n apiCall,\n}: {\n flatten: FlattenOperator\n} & RequestMapConfig<T, Body, TResult>): OperatorFunction<T, any> {\n return requestMap(flatten, { validator, prepare, loadingAction, errorAction, apiCall })\n}\n\n/**\n * Метаданные ответа API, доступные в колбэках apiResult.\n */\nexport interface ApiResultMeta {\n status: number\n statusText: string\n headers: Headers\n fromCache?: boolean\n}\n\n/**\n * Ошибка API-запроса. Бросается apiResult при !result.ok.\n * Ловится errorAction в validateMap.\n */\nexport class ApiError extends Error {\n constructor(\n public readonly originalError: any,\n public readonly meta: ApiResultMeta,\n ) {\n super(typeof originalError === 'string' ? originalError : (originalError?.message ?? 'API request failed'))\n this.name = 'ApiError'\n }\n}\n\n/**\n * Оператор для обработки успешного результата API-запроса (QueryResult).\n *\n * При `result.ok` — вызывает callback с `data` и `meta`.\n * При `!result.ok` — бросает `ApiError`, который ловится `errorAction` в `validateMap`.\n *\n * @example\n * ```ts\n * // Простой случай\n * validateMap({\n * errorAction: (err) => dispatcher.dispatch.loadError(String(err)),\n * apiCall: () => from(api.request('getList', params)).pipe(\n * apiResult((data) => dispatcher.dispatch.loadSuccess(data)),\n * ),\n * })\n *\n * // С доступом к headers (пагинация)\n * apiResult((data, meta) => {\n * const total = Number(meta.headers.get('X-Total-Count'))\n * dispatcher.dispatch.loadSuccess({ items: data, total })\n * })\n * ```\n */\nexport function apiResult<TData, TResult = void>(\n onSuccess: (data: TData, meta: ApiResultMeta) => TResult | Promise<TResult>,\n): OperatorFunction<{ ok: boolean; data?: TData; error?: any; status?: number; statusText?: string; headers?: Headers; fromCache?: boolean }, TResult> {\n return pipe(\n switchMap((result) => {\n const meta: ApiResultMeta = {\n status: result.status ?? 0,\n statusText: result.statusText ?? '',\n headers: result.headers ?? new Headers(),\n fromCache: result.fromCache,\n }\n if (result.ok && result.data !== undefined) {\n const out = onSuccess(result.data, meta)\n return from(Promise.resolve(out))\n }\n throw new ApiError(result.error ?? 'Unknown error', meta)\n }),\n )\n}\n\n/**\n * Класс для управления эффектами с поддержкой доступа к состоянию и контексту\n * Основной класс, который следует использовать\n */\nexport class EffectsModule<\n TState extends Record<string, any> = any,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n> {\n private effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[] = []\n private subscriptions: Array<{ unsubscribe: VoidFunction }> = []\n private running = false\n private action$ = new Subject<Action>()\n private externalStates: TExternalStates\n\n /**\n * Поток состояния\n */\n public readonly state$: Observable<TState>\n\n /**\n * Создает модуль эффектов\n * @param storage Хранилище состояния\n * @param dispatcher Основной dispatcher текущего synapse\n * @param externalDispatchers Внешние dispatcher'ы из других synapse\n * @param services Сервисы (API-клиенты и т.д.)\n * @param config Глобальная конфигурация для всех эффектов\n * @param externalStates Внешние состояния (Observable'ы от других хранилищ)\n */\n constructor(\n private storage: IStorage<TState>,\n private dispatcher: TDispatcher & { actions: Observable<Action> },\n private externalDispatchers: TExternalDispatchers = {} as TExternalDispatchers,\n private services: TServices = {} as TServices,\n private config: TConfig = {} as TConfig,\n externalStates: TExternalStates = {} as TExternalStates,\n ) {\n // Нормализуем externalStates: конвертируем storage → Observable\n this.externalStates = this.normalizeExternalStates(externalStates)\n\n // Создаем поток состояния\n this.state$ = new Observable<TState>((observer) => {\n // Отправляем начальное состояние\n Promise.resolve(this.storage.getState()).then((state: TState) => observer.next(state))\n\n // Подписываемся на все изменения\n const unsubscribe = this.storage.subscribeToAll(() => {\n Promise.resolve(this.storage.getState()).then((state: TState) => observer.next(state))\n })\n\n // Отписываемся при завершении\n return () => unsubscribe()\n }).pipe(share())\n }\n\n /**\n * Нормализует externalStates: конвертирует IStorageBase в Observable, пропускает Observable как есть\n */\n private normalizeExternalStates(states: TExternalStates): TExternalStates {\n const normalized = {} as Record<string, Observable<any>>\n for (const [key, value] of Object.entries(states)) {\n normalized[key] = isStorage(value) ? toObservable(value) : value\n }\n return normalized as TExternalStates\n }\n\n /**\n * Подписывается на действия от основного dispatcher'а и внешних dispatcher'ов\n */\n private subscribeToDispatchers() {\n // Основной dispatcher\n const mainSub = this.dispatcher.actions.subscribe((action) => {\n this.action$.next(action)\n })\n this.subscriptions.push(mainSub)\n\n // Внешние dispatcher'ы\n for (const [_, dispatcher] of Object.entries(this.externalDispatchers)) {\n const subscription = dispatcher.actions.subscribe((action) => {\n this.action$.next(action)\n })\n this.subscriptions.push(subscription)\n }\n }\n\n add(effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>): this {\n this.effects.push(effect)\n\n if (this.running) {\n this.subscribeToEffect(effect, this.effects.length - 1)\n }\n\n return this\n }\n\n /**\n * Добавляет несколько эффектов\n * @param effects Эффекты для добавления\n * @returns Текущий модуль\n */\n addEffects(effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[]): this {\n effects.forEach((effect) => this.add(effect))\n return this\n }\n\n /**\n * Запускает все эффекты\n * @returns Текущий модуль\n */\n async start(): Promise<this> {\n if (this.running) {\n return this\n }\n // Ждем готовности основного хранилища\n await this.storage.waitForReady()\n\n // Переподписываемся на dispatchers (подписки были очищены в stop())\n this.subscribeToDispatchers()\n\n this.effects.forEach((effect, index) => this.subscribeToEffect(effect, index))\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.action$.complete()\n this.action$ = new Subject<Action>()\n this.running = false\n\n return this\n }\n\n /**\n * Подписывается на конкретный эффект\n * @param effect Эффект для подписки\n */\n private subscribeToEffect(effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>, index = 0): void {\n try {\n const context: EffectContext<TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> = {\n dispatcher: this.dispatcher,\n externalDispatchers: this.externalDispatchers,\n externalStates: this.externalStates,\n services: this.services,\n config: this.config,\n }\n\n let stream$ = effect(this.action$.asObservable(), this.state$, context)\n\n // resubscribeOnError: переподписываемся на поток вместо терминального завершения.\n // Лимит ретраев исчерпан → ошибка уходит в терминальный catchError ниже\n // (эффект умирает, остальные продолжают работать).\n const options = (effect as { [EFFECT_OPTIONS]?: EffectOptions })[EFFECT_OPTIONS]\n const resubscribeOnError = options?.resubscribeOnError\n const resubscribes = !!resubscribeOnError\n if (resubscribeOnError) {\n const config = resubscribeOnError === true ? {} : resubscribeOnError\n stream$ = stream$.pipe(retry({ count: config.count ?? Infinity, delay: config.delay, resetOnSuccess: true }))\n }\n\n // Имя эффекта (поле class-слоя Effects) — для понятного предупреждения; иначе индекс.\n const effectLabel = (effect as { [EFFECT_NAME]?: string })[EFFECT_NAME] ?? `#${index}`\n\n const output$ = stream$.pipe(\n catchError((err) => {\n // Поток эффекта дошёл до терминальной ошибки → этот эффект БОЛЬШЕ не реагирует\n // на экшены (остальные живы). Громкое сообщение, чтобы это не прошло незаметно.\n const tail = resubscribes\n ? 'resubscribeOnError исчерпал лимит ретраев.'\n : 'Чтобы эффект переподписывался после ошибки, добавьте { resubscribeOnError: true } в this.effect(fn, …).'\n handleCallbackError(`EffectsModule: эффект \"${effectLabel}\" УПАЛ и больше не будет реагировать на экшены (поток завершён). ${tail}`, 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 handleCallbackError('EffectsModule: error calling effect result function', callError)\n }\n }\n })\n\n this.subscriptions.push(subscription)\n } catch (setupError) {\n handleCallbackError('EffectsModule: error setting up effect', setupError)\n }\n }\n}\n\n/**\n * Вспомогательная функция для создания типизированного эффекта\n */\nexport function createEffect<\n TState extends Record<string, any>,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(\n effect: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>,\n): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> {\n return effect\n}\n\n/**\n * Объединяет несколько эффектов в один\n * @param effects Эффекты для объединения\n * @returns Объединенный эффект\n */\nexport function combineEffects<\n TState extends Record<string, any>,\n TDispatcher = any,\n TServices extends Record<string, any> = Record<string, never>,\n TConfig extends Record<string, any> = Record<string, never>,\n TExternalDispatchers extends Record<string, DispatcherCore<any, any>> = Record<string, never>,\n TExternalStates extends ExternalStates = Record<string, never>,\n>(\n ...effects: Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates>[]\n): Effect<TState, TDispatcher, TServices, TConfig, TExternalDispatchers, TExternalStates> {\n return (action$, state$, context) => {\n const outputs = effects.map((effect) => {\n try {\n return effect(action$, state$, context)\n } catch (error) {\n handleCallbackError('combineEffects: error in one of combined effects', error)\n return of(null)\n }\n })\n return merge(...outputs)\n }\n}\n"],"names":["combineLatest","EMPTY","from","merge","Observable","of","pipe","Subject","catchError","filter","map","mergeMap","retry","share","switchMap","take","handleCallbackError","logError","chunkRequestConsistent","chunkRequestParallel","isStorage","toObservable","EFFECT_OPTIONS","Symbol","EFFECT_NAME","ofType","actionFn","actionType","source$","action","undefined","ofTypes","actionFns","actionTypes","fn","Boolean","ofTypesWaitAll","actionStreams","type","index","results","a","b","r","selectorMap","state$","selectors","state","selector","selectorObject","result","key","Object","requestMap","flatten","validator","prepare","loadingAction","errorAction","apiCall","pipeData","callApi","body$","Promise","apiCall$","body","err","validateConfig","conditions","skipAction","conditionMet","Array","validateMap","config","value","_body","utils","mutationMap","ApiError","Error","originalError","meta","apiResult","onSuccess","Headers","out","EffectsModule","storage","dispatcher","externalDispatchers","services","externalStates","observer","unsubscribe","states","normalized","mainSub","_","subscription","effect","effects","sub","context","stream$","options","resubscribeOnError","resubscribes","Infinity","effectLabel","output$","tail","callError","setupError","createEffect","combineEffects","action$","outputs","error"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactive/effects/index.js","sources":["../../../src/reactive/effects/index.ts"],"sourcesContent":["export * from './effects.module'\nexport { fromRequest } from './utils/fromRequest'\nexport { toObservable } from './utils/toObservable'\n"],"names":["fromRequest","toObservable"],"mappings":"
|
|
1
|
+
{"version":3,"file":"reactive/effects/index.js","sources":["../../../src/reactive/effects/index.ts"],"sourcesContent":["export * from './effects.base'\nexport * from './effects.module'\nexport { fromRequest } from './utils/fromRequest'\nexport { toObservable } from './utils/toObservable'\n"],"names":["fromRequest","toObservable"],"mappings":";;;;AAA8B;AACE;AACiB;AACE"}
|