synapse-storage 3.0.19 → 4.0.1
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 +28 -168
- package/dist/_utils/chunk.util.d.ts +8 -0
- package/dist/_utils/chunk.util.d.ts.map +1 -0
- package/dist/_utils/chunk.util.js +21 -0
- package/dist/_utils/chunk.util.js.map +1 -0
- package/dist/_utils/deepMerge.util.d.ts +2 -0
- package/dist/_utils/deepMerge.util.d.ts.map +1 -0
- package/dist/_utils/deepMerge.util.js +19 -0
- package/dist/_utils/deepMerge.util.js.map +1 -0
- package/dist/_utils/error-handling.util.d.ts +50 -0
- package/dist/_utils/error-handling.util.d.ts.map +1 -0
- package/dist/_utils/error-handling.util.js +67 -0
- package/dist/_utils/error-handling.util.js.map +1 -0
- package/dist/_utils/flatMap.util.d.ts +10 -0
- package/dist/_utils/flatMap.util.d.ts.map +1 -0
- package/dist/_utils/flatMap.util.js +23 -0
- package/dist/_utils/flatMap.util.js.map +1 -0
- package/dist/_utils/index.d.ts +6 -0
- package/dist/_utils/index.d.ts.map +1 -0
- package/dist/_utils/index.js +13 -0
- package/dist/_utils/index.js.map +1 -0
- package/dist/_utils/logger-console.util.d.ts +9 -0
- package/dist/_utils/logger-console.util.d.ts.map +1 -0
- package/dist/_utils/logger-console.util.js +14 -0
- package/dist/_utils/logger-console.util.js.map +1 -0
- package/dist/api/api.module.d.ts +46 -0
- package/dist/api/api.module.d.ts.map +1 -0
- package/dist/api/api.module.js +121 -0
- package/dist/api/api.module.js.map +1 -0
- package/dist/api/components/endpoint.d.ts +57 -0
- package/dist/api/components/endpoint.d.ts.map +1 -0
- package/dist/api/components/endpoint.js +385 -0
- package/dist/api/components/endpoint.js.map +1 -0
- package/dist/api/components/query-storage.d.ts +100 -0
- package/dist/api/components/query-storage.d.ts.map +1 -0
- package/dist/api/components/query-storage.js +293 -0
- package/dist/api/components/query-storage.js.map +1 -0
- package/dist/api/example.d.ts +83 -0
- package/dist/api/example.d.ts.map +1 -0
- package/dist/api/example.js +90 -0
- package/dist/api/example.js.map +1 -0
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +11 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/types/api.interface.d.ts +126 -0
- package/dist/api/types/api.interface.d.ts.map +1 -0
- package/dist/api/types/api.interface.js +15 -0
- package/dist/api/types/api.interface.js.map +1 -0
- package/dist/api/types/endpoint.interface.d.ts +118 -0
- package/dist/api/types/endpoint.interface.d.ts.map +1 -0
- package/dist/api/types/endpoint.interface.js +6 -0
- package/dist/api/types/endpoint.interface.js.map +1 -0
- package/dist/api/types/query.interface.d.ts +85 -0
- package/dist/api/types/query.interface.d.ts.map +1 -0
- package/dist/api/types/query.interface.js +6 -0
- package/dist/api/types/query.interface.js.map +1 -0
- package/dist/api/utils/api-helpers.d.ts +22 -0
- package/dist/api/utils/api-helpers.d.ts.map +1 -0
- package/dist/api/utils/api-helpers.js +44 -0
- package/dist/api/utils/api-helpers.js.map +1 -0
- package/dist/api/utils/create-header-context.d.ts +10 -0
- package/dist/api/utils/create-header-context.d.ts.map +1 -0
- package/dist/api/utils/create-header-context.js +40 -0
- package/dist/api/utils/create-header-context.js.map +1 -0
- package/dist/api/utils/endpoint-headers.d.ts +23 -0
- package/dist/api/utils/endpoint-headers.d.ts.map +1 -0
- package/dist/api/utils/endpoint-headers.js +61 -0
- package/dist/api/utils/endpoint-headers.js.map +1 -0
- package/dist/api/utils/fetch-base-query.d.ts +9 -0
- package/dist/api/utils/fetch-base-query.d.ts.map +1 -0
- package/dist/api/utils/fetch-base-query.js +242 -0
- package/dist/api/utils/fetch-base-query.js.map +1 -0
- package/dist/api/utils/file-utils.d.ts +43 -0
- package/dist/api/utils/file-utils.d.ts.map +1 -0
- package/dist/api/utils/file-utils.js +102 -0
- package/dist/api/utils/file-utils.js.map +1 -0
- package/dist/api/utils/get-cacheable-headers.d.ts +8 -0
- package/dist/api/utils/get-cacheable-headers.d.ts.map +1 -0
- package/dist/api/utils/get-cacheable-headers.js +23 -0
- package/dist/api/utils/get-cacheable-headers.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/selector/index.d.ts +3 -0
- package/dist/core/selector/index.d.ts.map +1 -0
- package/dist/core/selector/index.js +5 -0
- package/dist/core/selector/index.js.map +1 -0
- package/dist/{selector.interface-CA5y-kD_.d.ts → core/selector/selector.interface.d.ts} +41 -8
- package/dist/core/selector/selector.interface.d.ts.map +1 -0
- package/dist/core/selector/selector.interface.js +7 -0
- package/dist/core/selector/selector.interface.js.map +1 -0
- package/dist/core/selector/selector.module.d.ts +36 -0
- package/dist/core/selector/selector.module.d.ts.map +1 -0
- package/dist/core/selector/selector.module.js +412 -0
- package/dist/core/selector/selector.module.js.map +1 -0
- package/dist/core/storage/adapters/async-base-storage.service.d.ts +49 -0
- package/dist/core/storage/adapters/async-base-storage.service.d.ts.map +1 -0
- package/dist/core/storage/adapters/async-base-storage.service.js +505 -0
- package/dist/core/storage/adapters/async-base-storage.service.js.map +1 -0
- package/dist/core/storage/adapters/indexed-DB.service.d.ts +89 -0
- package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +1 -0
- package/dist/core/storage/adapters/indexed-DB.service.js +596 -0
- package/dist/core/storage/adapters/indexed-DB.service.js.map +1 -0
- package/dist/core/storage/adapters/local-storage.service.d.ts +23 -0
- package/dist/core/storage/adapters/local-storage.service.d.ts.map +1 -0
- package/dist/core/storage/adapters/local-storage.service.js +111 -0
- package/dist/core/storage/adapters/local-storage.service.js.map +1 -0
- package/dist/core/storage/adapters/memory-storage.service.d.ts +24 -0
- package/dist/core/storage/adapters/memory-storage.service.d.ts.map +1 -0
- package/dist/core/storage/adapters/memory-storage.service.js +110 -0
- package/dist/core/storage/adapters/memory-storage.service.js.map +1 -0
- package/dist/core/storage/adapters/path.utils.d.ts +5 -0
- package/dist/core/storage/adapters/path.utils.d.ts.map +1 -0
- package/dist/core/storage/adapters/path.utils.js +42 -0
- package/dist/core/storage/adapters/path.utils.js.map +1 -0
- package/dist/core/storage/adapters/storage-core.d.ts +61 -0
- package/dist/core/storage/adapters/storage-core.d.ts.map +1 -0
- package/dist/core/storage/adapters/storage-core.js +221 -0
- package/dist/core/storage/adapters/storage-core.js.map +1 -0
- package/dist/core/storage/adapters/sync-base-storage.service.d.ts +56 -0
- package/dist/core/storage/adapters/sync-base-storage.service.d.ts.map +1 -0
- package/dist/core/storage/adapters/sync-base-storage.service.js +481 -0
- package/dist/core/storage/adapters/sync-base-storage.service.js.map +1 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +38 -0
- package/dist/core/storage/index.js.map +1 -0
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts +9 -0
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/broadcast.middleware.js +197 -0
- package/dist/core/storage/middlewares/broadcast.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/index.d.ts +9 -0
- package/dist/core/storage/middlewares/index.d.ts.map +1 -0
- package/dist/core/storage/middlewares/index.js +17 -0
- package/dist/core/storage/middlewares/index.js.map +1 -0
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +7 -0
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/storage-batching.middleware.js +108 -0
- package/dist/core/storage/middlewares/storage-batching.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +7 -0
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +43 -0
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts +9 -0
- package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/sync-broadcast.middleware.js +177 -0
- package/dist/core/storage/middlewares/sync-broadcast.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts +6 -0
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.js +56 -0
- package/dist/core/storage/middlewares/sync-storage-batching.middleware.js.map +1 -0
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts +7 -0
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts.map +1 -0
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js +39 -0
- package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js.map +1 -0
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts +101 -0
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +1 -0
- package/dist/core/storage/modules/plugin/plugin.interface.js +8 -0
- package/dist/core/storage/modules/plugin/plugin.interface.js.map +1 -0
- package/dist/core/storage/modules/plugin/plugin.service.d.ts +49 -0
- package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +1 -0
- package/dist/core/storage/modules/plugin/plugin.service.js +406 -0
- package/dist/core/storage/modules/plugin/plugin.service.js.map +1 -0
- package/dist/core/storage/modules/singleton/mixin.util.d.ts +6 -0
- package/dist/core/storage/modules/singleton/mixin.util.d.ts.map +1 -0
- package/dist/core/storage/modules/singleton/mixin.util.js +30 -0
- package/dist/core/storage/modules/singleton/mixin.util.js.map +1 -0
- package/dist/core/storage/modules/singleton/models.d.ts +143 -0
- package/dist/core/storage/modules/singleton/models.d.ts.map +1 -0
- package/dist/core/storage/modules/singleton/models.js +60 -0
- package/dist/core/storage/modules/singleton/models.js.map +1 -0
- package/dist/core/storage/modules/singleton/singleton.util.d.ts +36 -0
- package/dist/core/storage/modules/singleton/singleton.util.d.ts.map +1 -0
- package/dist/core/storage/modules/singleton/singleton.util.js +216 -0
- package/dist/core/storage/modules/singleton/singleton.util.js.map +1 -0
- package/dist/core/storage/storage.interface.d.ts +168 -0
- package/dist/core/storage/storage.interface.d.ts.map +1 -0
- package/dist/core/storage/storage.interface.js +23 -0
- package/dist/core/storage/storage.interface.js.map +1 -0
- package/dist/core/storage/utils/broadcast.util.d.ts +49 -0
- package/dist/core/storage/utils/broadcast.util.d.ts.map +1 -0
- package/dist/core/storage/utils/broadcast.util.js +141 -0
- package/dist/core/storage/utils/broadcast.util.js.map +1 -0
- package/dist/core/storage/utils/cache.util.d.ts +33 -0
- package/dist/core/storage/utils/cache.util.d.ts.map +1 -0
- package/dist/core/storage/utils/cache.util.js +54 -0
- package/dist/core/storage/utils/cache.util.js.map +1 -0
- package/dist/core/storage/utils/middleware-module.d.ts +94 -0
- package/dist/core/storage/utils/middleware-module.d.ts.map +1 -0
- package/dist/core/storage/utils/middleware-module.js +258 -0
- package/dist/core/storage/utils/middleware-module.js.map +1 -0
- package/dist/core/storage/utils/path-selector.util.d.ts +15 -0
- package/dist/core/storage/utils/path-selector.util.d.ts.map +1 -0
- package/dist/core/storage/utils/path-selector.util.js +58 -0
- package/dist/core/storage/utils/path-selector.util.js.map +1 -0
- package/dist/core/storage/utils/state-diff.util.d.ts +14 -0
- package/dist/core/storage/utils/state-diff.util.d.ts.map +1 -0
- package/dist/core/storage/utils/state-diff.util.js +88 -0
- package/dist/core/storage/utils/state-diff.util.js.map +1 -0
- package/dist/core/storage/utils/storage-factory.util.d.ts +21 -0
- package/dist/core/storage/utils/storage-factory.util.d.ts.map +1 -0
- package/dist/core/storage/utils/storage-factory.util.js +40 -0
- package/dist/core/storage/utils/storage-factory.util.js.map +1 -0
- package/dist/core/storage/utils/storage-key.d.ts +11 -0
- package/dist/core/storage/utils/storage-key.d.ts.map +1 -0
- package/dist/core/storage/utils/storage-key.js +24 -0
- package/dist/core/storage/utils/storage-key.js.map +1 -0
- package/dist/core/storage/utils/storage.utils.d.ts +17 -0
- package/dist/core/storage/utils/storage.utils.d.ts.map +1 -0
- package/dist/core/storage/utils/storage.utils.js +57 -0
- package/dist/core/storage/utils/storage.utils.js.map +1 -0
- package/dist/index.d.ts +10 -12
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -0
- package/dist/react/hooks/index.d.ts +5 -0
- package/dist/react/hooks/index.d.ts.map +1 -0
- package/dist/react/hooks/index.js +11 -0
- package/dist/react/hooks/index.js.map +1 -0
- package/dist/react/hooks/useCreateStorage.d.ts +39 -0
- package/dist/react/hooks/useCreateStorage.d.ts.map +1 -0
- package/dist/react/hooks/useCreateStorage.js +137 -0
- package/dist/react/hooks/useCreateStorage.js.map +1 -0
- package/dist/react/hooks/useSelector.d.ts +21 -0
- package/dist/react/hooks/useSelector.d.ts.map +1 -0
- package/dist/react/hooks/useSelector.js +56 -0
- package/dist/react/hooks/useSelector.js.map +1 -0
- package/dist/react/hooks/useStorage.d.ts +39 -0
- package/dist/react/hooks/useStorage.d.ts.map +1 -0
- package/dist/react/hooks/useStorage.js +78 -0
- package/dist/react/hooks/useStorage.js.map +1 -0
- package/dist/react/hooks/useStorageSubscribe.d.ts +16 -0
- package/dist/react/hooks/useStorageSubscribe.d.ts.map +1 -0
- package/dist/react/hooks/useStorageSubscribe.js +55 -0
- package/dist/react/hooks/useStorageSubscribe.js.map +1 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +7 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/utils/awaitSynapse.d.ts +34 -0
- package/dist/react/utils/awaitSynapse.d.ts.map +1 -0
- package/dist/react/utils/awaitSynapse.js +87 -0
- package/dist/react/utils/awaitSynapse.js.map +1 -0
- package/dist/react/utils/createSynapseCtx.d.ts +33 -0
- package/dist/react/utils/createSynapseCtx.d.ts.map +1 -0
- package/dist/react/utils/createSynapseCtx.js +139 -0
- package/dist/react/utils/createSynapseCtx.js.map +1 -0
- package/dist/react/utils/index.d.ts +3 -0
- package/dist/react/utils/index.d.ts.map +1 -0
- package/dist/react/utils/index.js +9 -0
- package/dist/react/utils/index.js.map +1 -0
- package/dist/reactive/dispatcher/dispatcher.module.d.ts +216 -0
- package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +1 -0
- package/dist/reactive/dispatcher/dispatcher.module.js +384 -0
- package/dist/reactive/dispatcher/dispatcher.module.js.map +1 -0
- package/dist/reactive/dispatcher/index.d.ts +4 -0
- package/dist/reactive/dispatcher/index.d.ts.map +1 -0
- package/dist/reactive/dispatcher/index.js +9 -0
- package/dist/reactive/dispatcher/index.js.map +1 -0
- package/dist/reactive/dispatcher/middlewares/index.d.ts +2 -0
- package/dist/reactive/dispatcher/middlewares/index.d.ts.map +1 -0
- package/dist/reactive/dispatcher/middlewares/index.js +5 -0
- package/dist/reactive/dispatcher/middlewares/index.js.map +1 -0
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +37 -0
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +1 -0
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js +188 -0
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js.map +1 -0
- package/dist/reactive/dispatcher/standalone.d.ts +112 -0
- package/dist/reactive/dispatcher/standalone.d.ts.map +1 -0
- package/dist/reactive/dispatcher/standalone.js +142 -0
- package/dist/reactive/dispatcher/standalone.js.map +1 -0
- package/dist/reactive/effects/effects.module.d.ts +225 -0
- package/dist/reactive/effects/effects.module.d.ts.map +1 -0
- package/dist/reactive/effects/effects.module.js +356 -0
- package/dist/reactive/effects/effects.module.js.map +1 -0
- package/dist/reactive/effects/index.d.ts +4 -0
- package/dist/reactive/effects/index.d.ts.map +1 -0
- package/dist/reactive/effects/index.js +11 -0
- package/dist/reactive/effects/index.js.map +1 -0
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +12 -0
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +1 -0
- package/dist/reactive/effects/utils/chunkRequestConsistent.js +25 -0
- package/dist/reactive/effects/utils/chunkRequestConsistent.js.map +1 -0
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +12 -0
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +1 -0
- package/dist/reactive/effects/utils/chunkRequestParallel.js +22 -0
- package/dist/reactive/effects/utils/chunkRequestParallel.js.map +1 -0
- package/dist/reactive/effects/utils/fromRequest.d.ts +40 -0
- package/dist/reactive/effects/utils/fromRequest.d.ts.map +1 -0
- package/dist/reactive/effects/utils/fromRequest.js +64 -0
- package/dist/reactive/effects/utils/fromRequest.js.map +1 -0
- package/dist/reactive/effects/utils/index.d.ts +5 -0
- package/dist/reactive/effects/utils/index.d.ts.map +1 -0
- package/dist/reactive/effects/utils/index.js +11 -0
- package/dist/reactive/effects/utils/index.js.map +1 -0
- package/dist/reactive/effects/utils/toObservable.d.ts +23 -0
- package/dist/reactive/effects/utils/toObservable.d.ts.map +1 -0
- package/dist/reactive/effects/utils/toObservable.js +39 -0
- package/dist/reactive/effects/utils/toObservable.js.map +1 -0
- package/dist/reactive/index.d.ts +3 -0
- package/dist/reactive/index.d.ts.map +1 -0
- package/dist/reactive/index.js +7 -0
- package/dist/reactive/index.js.map +1 -0
- package/dist/utils/createEventBus.d.ts +87 -0
- package/dist/utils/createEventBus.d.ts.map +1 -0
- package/dist/utils/createEventBus.js +215 -0
- package/dist/utils/createEventBus.js.map +1 -0
- package/dist/utils/createSynapse/createSynapse.d.ts +9 -0
- package/dist/utils/createSynapse/createSynapse.d.ts.map +1 -0
- package/dist/utils/createSynapse/createSynapse.js +103 -0
- package/dist/utils/createSynapse/createSynapse.js.map +1 -0
- package/dist/utils/createSynapse/index.d.ts +3 -0
- package/dist/utils/createSynapse/index.d.ts.map +1 -0
- package/dist/utils/createSynapse/index.js +6 -0
- package/dist/utils/createSynapse/index.js.map +1 -0
- package/dist/utils/createSynapse/types.d.ts +93 -0
- package/dist/utils/createSynapse/types.d.ts.map +1 -0
- package/dist/utils/createSynapse/types.js +6 -0
- package/dist/utils/createSynapse/types.js.map +1 -0
- package/dist/utils/createSynapse/validate.d.ts +2 -0
- package/dist/utils/createSynapse/validate.d.ts.map +1 -0
- package/dist/utils/createSynapse/validate.js +76 -0
- package/dist/utils/createSynapse/validate.js.map +1 -0
- package/dist/utils/createSynapse/waitForDependencies.d.ts +3 -0
- package/dist/utils/createSynapse/waitForDependencies.d.ts.map +1 -0
- package/dist/utils/createSynapse/waitForDependencies.js +40 -0
- package/dist/utils/createSynapse/waitForDependencies.js.map +1 -0
- package/dist/utils/createSynapseAwaiter.d.ts +46 -0
- package/dist/utils/createSynapseAwaiter.d.ts.map +1 -0
- package/dist/utils/createSynapseAwaiter.js +102 -0
- package/dist/utils/createSynapseAwaiter.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +17 -21
- package/dist/api.d.ts +0 -365
- package/dist/api.js +0 -1
- package/dist/core.d.ts +0 -106
- package/dist/core.js +0 -1
- package/dist/createSynapse-vkfKjRob.d.ts +0 -97
- package/dist/dispatcher.module-BOsMHbD5.d.ts +0 -360
- package/dist/react.d.ts +0 -119
- package/dist/react.js +0 -1
- package/dist/reactive.d.ts +0 -35
- package/dist/reactive.js +0 -1
- package/dist/storage.interface-BA_ktyDz.d.ts +0 -591
- package/dist/utils.d.ts +0 -139
- package/dist/utils.js +0 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { EndpointClass } from "./components/endpoint.js";
|
|
2
|
+
import { QueryStorage } from "./components/query-storage.js";
|
|
3
|
+
import { apiLogger } from "./utils/api-helpers.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ApiClient {
|
|
12
|
+
/** Хранилище запросов */ queryStorage;
|
|
13
|
+
/** Флаг завершённой инициализации */ _initialized = false;
|
|
14
|
+
/** Промис текущей инициализации (для дедупликации параллельных вызовов) */ _initPromise = null;
|
|
15
|
+
cacheableHeaderKeys;
|
|
16
|
+
globalCacheConfig;
|
|
17
|
+
baseQueryConfig;
|
|
18
|
+
storageExternal;
|
|
19
|
+
globalRetryConfig;
|
|
20
|
+
createEndpoints;
|
|
21
|
+
/** Реестр эндпоинтов */ endpoints = {};
|
|
22
|
+
constructor(options){
|
|
23
|
+
// Сохраняем переданные параметры
|
|
24
|
+
this.cacheableHeaderKeys = options.cacheableHeaderKeys;
|
|
25
|
+
this.globalCacheConfig = options.cache;
|
|
26
|
+
this.baseQueryConfig = options.baseQuery;
|
|
27
|
+
this.storageExternal = options.storage;
|
|
28
|
+
this.globalRetryConfig = options.retry;
|
|
29
|
+
this.createEndpoints = options.endpoints;
|
|
30
|
+
}
|
|
31
|
+
async init() {
|
|
32
|
+
if (this._initialized) return this;
|
|
33
|
+
if (this._initPromise) return this._initPromise;
|
|
34
|
+
this._initPromise = this._doInit();
|
|
35
|
+
return this._initPromise;
|
|
36
|
+
}
|
|
37
|
+
async _doInit() {
|
|
38
|
+
try {
|
|
39
|
+
// 1. Создаем кэшированное хранилище запросов (storage инициализируется внутри QueryStorage)
|
|
40
|
+
this.queryStorage = await new QueryStorage(this.storageExternal, this.globalCacheConfig).initialize();
|
|
41
|
+
// 2. Создаем эндпоинты
|
|
42
|
+
await this.initializeEndpoints();
|
|
43
|
+
this._initialized = true;
|
|
44
|
+
return this;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
this._initPromise = null;
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async initializeEndpoints() {
|
|
51
|
+
// Получаем конфигурацию будущих эндпоинтов
|
|
52
|
+
const create = (config)=>config;
|
|
53
|
+
// Создаем объект с конфигурациями для эндпоинтов
|
|
54
|
+
const endpointsConfig = await this.createEndpoints(create);
|
|
55
|
+
// Создаем эндпоинты
|
|
56
|
+
for (const [endpointKey, endpointConfig] of Object.entries(endpointsConfig)){
|
|
57
|
+
const key = endpointKey;
|
|
58
|
+
this.endpoints[key] = new EndpointClass({
|
|
59
|
+
name: endpointKey,
|
|
60
|
+
queryStorage: this.queryStorage,
|
|
61
|
+
config: endpointConfig,
|
|
62
|
+
cacheableHeaderKeys: this.cacheableHeaderKeys,
|
|
63
|
+
globalCacheConfig: this.globalCacheConfig,
|
|
64
|
+
globalRetryConfig: this.globalRetryConfig,
|
|
65
|
+
baseQueryConfig: this.baseQueryConfig
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
ensureInitialized() {
|
|
70
|
+
if (!this._initialized) {
|
|
71
|
+
throw new Error('ApiClient не инициализирован. Вызовите await api.init() перед использованием.');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Получает все эндпоинты с улучшенной типизацией
|
|
76
|
+
* @returns Типизированный объект эндпоинтов
|
|
77
|
+
*/ getEndpoints() {
|
|
78
|
+
this.ensureInitialized();
|
|
79
|
+
return this.endpoints;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Выполняет запрос к API с типизацией и обработкой ошибок
|
|
83
|
+
* @param endpointName Имя эндпоинта (с подсказками TypeScript)
|
|
84
|
+
* @param params Параметры запроса (с типизацией)
|
|
85
|
+
* @param options Опции запроса
|
|
86
|
+
* @returns Promise с типизированным результатом запроса
|
|
87
|
+
*/ async request(endpointName, params, options) {
|
|
88
|
+
this.ensureInitialized();
|
|
89
|
+
const endpoints = this.getEndpoints();
|
|
90
|
+
const endpoint = endpoints[endpointName];
|
|
91
|
+
if (!endpoint) {
|
|
92
|
+
throw new Error(`Эндпоинт ${String(endpointName)} не найден`);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const stateRequest = endpoint.request(params, options);
|
|
96
|
+
return await stateRequest.wait();
|
|
97
|
+
} catch (error) {
|
|
98
|
+
apiLogger.error(`Ошибка запроса к ${String(endpointName)}`, {
|
|
99
|
+
error,
|
|
100
|
+
params
|
|
101
|
+
});
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async destroy() {
|
|
106
|
+
if (!this._initialized) return;
|
|
107
|
+
// 1. Уничтожаем каждый эндпоинт
|
|
108
|
+
Object.values(this.endpoints).forEach((endpoint)=>endpoint.destroy());
|
|
109
|
+
// 2. Очищаем коллекцию эндпоинтов
|
|
110
|
+
this.endpoints = {};
|
|
111
|
+
// 3. Уничтожаем хранилище
|
|
112
|
+
await this.queryStorage.destroy();
|
|
113
|
+
// 4. Сбрасываем состояние инициализации (позволяет повторный init)
|
|
114
|
+
this._initialized = false;
|
|
115
|
+
this._initPromise = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { ApiClient };
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=api.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/api.module.js","sources":["../../src/api/api.module.ts"],"sourcesContent":["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\n// Тип для готовой карты эндпоинтов (без optional)\ntype EndpointsMap<EndpointsFn> = {\n [K in keyof EndpointsResult<EndpointsFn>]: EndpointType<ExtractParamsType<EndpointsResult<EndpointsFn>[K]>, ExtractResultType<EndpointsResult<EndpointsFn>[K]>>\n}\n\nexport class ApiClient<EndpointsFn extends (create: CreateEndpoint) => Promise<Record<string, EndpointConfig<any, any>>>> {\n /** Хранилище запросов */\n private queryStorage!: QueryStorage\n\n /** Флаг завершённой инициализации */\n private _initialized = false\n\n /** Промис текущей инициализации (для дедупликации параллельных вызовов) */\n private _initPromise: Promise<this> | null = null\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 globalRetryConfig: CreateApiClientOptions['retry']\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.globalRetryConfig = options.retry\n this.createEndpoints = options.endpoints\n }\n\n public async init(): Promise<this> {\n if (this._initialized) return this\n if (this._initPromise) return this._initPromise\n\n this._initPromise = this._doInit()\n return this._initPromise\n }\n\n private async _doInit(): Promise<this> {\n try {\n // 1. Создаем кэшированное хранилище запросов (storage инициализируется внутри QueryStorage)\n this.queryStorage = await new QueryStorage(this.storageExternal, this.globalCacheConfig).initialize()\n\n // 2. Создаем эндпоинты\n await this.initializeEndpoints()\n\n this._initialized = true\n return this\n } catch (error) {\n this._initPromise = null\n throw error\n }\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({\n name: endpointKey,\n queryStorage: this.queryStorage,\n config: endpointConfig,\n cacheableHeaderKeys: this.cacheableHeaderKeys,\n globalCacheConfig: this.globalCacheConfig,\n globalRetryConfig: this.globalRetryConfig,\n baseQueryConfig: this.baseQueryConfig,\n })\n }\n }\n\n private ensureInitialized(): void {\n if (!this._initialized) {\n throw new Error('ApiClient не инициализирован. Вызовите await api.init() перед использованием.')\n }\n }\n\n /**\n * Получает все эндпоинты с улучшенной типизацией\n * @returns Типизированный объект эндпоинтов\n */\n public getEndpoints(): EndpointsMap<EndpointsFn> {\n this.ensureInitialized()\n return this.endpoints as EndpointsMap<EndpointsFn>\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 this.ensureInitialized()\n\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 if (!this._initialized) return\n\n // 1. Уничтожаем каждый эндпоинт\n Object.values(this.endpoints).forEach((endpoint) => endpoint.destroy())\n\n // 2. Очищаем коллекцию эндпоинтов\n this.endpoints = {}\n // 3. Уничтожаем хранилище\n await this.queryStorage.destroy()\n\n // 4. Сбрасываем состояние инициализации (позволяет повторный init)\n this._initialized = false\n this._initPromise = null\n }\n}\n"],"names":["EndpointClass","QueryStorage","apiLogger","ApiClient","options","error","create","config","endpointsConfig","endpointKey","endpointConfig","Object","key","Error","endpointName","params","endpoints","endpoint","String","stateRequest"],"mappings":";;;;;;;AAAqD;AACI;AAIV;AAUxC,MAAMG,SAASA;IACpB,uBAAuB,GACf,aAA2B;IAEnC,mCAAmC,GAC3B,eAAe,MAAK;IAE5B,yEAAyE,GACjE,eAAqC,KAAI;IAEhC,oBAAkE;IAElE,kBAAkD;IAElD,gBAAoD;IAEpD,gBAAkD;IAElD,kBAAkD;IAElD,gBAA4B;IAE7C,sBAAsB,GACd,YAEJ,CAAC,EAAC;IAEN,YAAYC,OAA+E,CAAE;QAC3F,iCAAiC;QACjC,IAAI,CAAC,mBAAmB,GAAGA,QAAQ,mBAAmB;QACtD,IAAI,CAAC,iBAAiB,GAAGA,QAAQ,KAAK;QACtC,IAAI,CAAC,eAAe,GAAGA,QAAQ,SAAS;QACxC,IAAI,CAAC,eAAe,GAAGA,QAAQ,OAAO;QACtC,IAAI,CAAC,iBAAiB,GAAGA,QAAQ,KAAK;QACtC,IAAI,CAAC,eAAe,GAAGA,QAAQ,SAAS;IAC1C;IAEA,MAAa,OAAsB;QACjC,IAAI,IAAI,CAAC,YAAY,EAAE,OAAO,IAAI;QAClC,IAAI,IAAI,CAAC,YAAY,EAAE,OAAO,IAAI,CAAC,YAAY;QAE/C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO;QAChC,OAAO,IAAI,CAAC,YAAY;IAC1B;IAEA,MAAc,UAAyB;QACrC,IAAI;YACF,4FAA4F;YAC5F,IAAI,CAAC,YAAY,GAAG,MAAM,IAAIH,YAAYA,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU;YAEnG,uBAAuB;YACvB,MAAM,IAAI,CAAC,mBAAmB;YAE9B,IAAI,CAAC,YAAY,GAAG;YACpB,OAAO,IAAI;QACb,EAAE,OAAOI,OAAO;YACd,IAAI,CAAC,YAAY,GAAG;YACpB,MAAMA;QACR;IACF;IAEA,MAAc,sBAAsB;QAClC,2CAA2C;QAC3C,MAAMC,SAAyB,CAA+CC,SAA6CA;QAC3H,iDAAiD;QACjD,MAAMC,kBAAkB,MAAM,IAAI,CAAC,eAAe,CAACF;QAEnD,oBAAoB;QACpB,KAAK,MAAM,CAACG,aAAaC,eAAe,IAAIC,OAAO,OAAO,CAACH,iBAAkB;YAC3E,MAAMI,MAAMH;YACZ,IAAI,CAAC,SAAS,CAACG,IAAI,GAAG,IAAIZ,aAAaA,CAAC;gBACtC,MAAMS;gBACN,cAAc,IAAI,CAAC,YAAY;gBAC/B,QAAQC;gBACR,qBAAqB,IAAI,CAAC,mBAAmB;gBAC7C,mBAAmB,IAAI,CAAC,iBAAiB;gBACzC,mBAAmB,IAAI,CAAC,iBAAiB;gBACzC,iBAAiB,IAAI,CAAC,eAAe;YACvC;QACF;IACF;IAEQ,oBAA0B;QAChC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;YACtB,MAAM,IAAIG,MAAM;QAClB;IACF;IAEA;;;GAGC,GACM,eAA0C;QAC/C,IAAI,CAAC,iBAAiB;QACtB,OAAO,IAAI,CAAC,SAAS;IACvB;IAEA;;;;;;GAMC,GACD,MAAa,QACXC,YAAe,EACfC,MAA0D,EAC1DX,OAAsB,EAC2D;QACjF,IAAI,CAAC,iBAAiB;QAEtB,MAAMY,YAAY,IAAI,CAAC,YAAY;QACnC,MAAMC,WAAWD,SAAS,CAACF,aAAa;QAExC,IAAI,CAACG,UAAU;YACb,MAAM,IAAIJ,MAAM,CAAC,SAAS,EAAEK,OAAOJ,cAAc,UAAU,CAAC;QAC9D;QAEA,IAAI;YACF,MAAMK,eAAeF,SAAS,OAAO,CAACF,QAAQX;YAC9C,OAAO,MAAMe,aAAa,IAAI;QAChC,EAAE,OAAOd,OAAO;YACdH,eAAe,CAAC,CAAC,iBAAiB,EAAEgB,OAAOJ,eAAe,EAAE;gBAAET;gBAAOU;YAAO;YAC5E,MAAMV;QACR;IACF;IAEA,MAAa,UAAU;QACrB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;QAExB,gCAAgC;QAChCM,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAACM,WAAaA,SAAS,OAAO;QAEpE,kCAAkC;QAClC,IAAI,CAAC,SAAS,GAAG,CAAC;QAClB,0BAA0B;QAC1B,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO;QAE/B,mEAAmE;QACnE,IAAI,CAAC,YAAY,GAAG;QACpB,IAAI,CAAC,YAAY,GAAG;IACtB;AACF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CreateApiClientOptions } from '../types/api.interface';
|
|
2
|
+
import { Endpoint as EndpointType, EndpointConfig, EndpointState, RequestResponseModify } from '../types/endpoint.interface';
|
|
3
|
+
import { QueryOptions, Unsubscribe } from '../types/query.interface';
|
|
4
|
+
import { QueryStorage } from './query-storage';
|
|
5
|
+
export interface EndpointClassOptions<RequestParams extends Record<string, any>, RequestResponse> {
|
|
6
|
+
name: string;
|
|
7
|
+
queryStorage: QueryStorage;
|
|
8
|
+
config: EndpointConfig<RequestParams, RequestResponse>;
|
|
9
|
+
cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys'];
|
|
10
|
+
globalCacheConfig: CreateApiClientOptions['cache'];
|
|
11
|
+
globalRetryConfig: CreateApiClientOptions['retry'];
|
|
12
|
+
baseQueryConfig: CreateApiClientOptions['baseQuery'];
|
|
13
|
+
}
|
|
14
|
+
export declare class EndpointClass<RequestParams extends Record<string, any>, RequestResponse> implements EndpointType<RequestParams, RequestResponse> {
|
|
15
|
+
private readonly endpointSubscribers;
|
|
16
|
+
/** Сколько раз был вызван метод request */
|
|
17
|
+
fetchCounts: number;
|
|
18
|
+
meta: EndpointType['meta'];
|
|
19
|
+
private readonly name;
|
|
20
|
+
private readonly queryStorage;
|
|
21
|
+
private readonly configCurrentEndpoint;
|
|
22
|
+
private readonly cacheableHeaderKeys;
|
|
23
|
+
private readonly globalRetryConfig;
|
|
24
|
+
private readonly baseQueryConfig;
|
|
25
|
+
private readonly queryFunction;
|
|
26
|
+
/** Массив заголовков, которые нужно включить в ключ кэширования */
|
|
27
|
+
private readonly cacheableHeaders;
|
|
28
|
+
private readonly prepareHeaders;
|
|
29
|
+
/** Карта in-flight запросов для дедупликации (cacheKey → Promise) */
|
|
30
|
+
private readonly inflightRequests;
|
|
31
|
+
constructor(options: EndpointClassOptions<RequestParams, RequestResponse>);
|
|
32
|
+
request(params: RequestParams, options?: QueryOptions): RequestResponseModify<RequestResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Определяет итоговую конфигурацию retry: вызов → эндпоинт → глобальная
|
|
35
|
+
*/
|
|
36
|
+
private resolveRetryConfig;
|
|
37
|
+
/**
|
|
38
|
+
* Выполняет сетевой запрос с кэшированием, дедупликацией и retry
|
|
39
|
+
*/
|
|
40
|
+
private executeRequest;
|
|
41
|
+
/**
|
|
42
|
+
* Выполняет HTTP-запрос с retry, инвалидацией тегов и кэшированием результата
|
|
43
|
+
*/
|
|
44
|
+
private executeFetch;
|
|
45
|
+
/**
|
|
46
|
+
* Выполняет HTTP-запрос с повторными попытками
|
|
47
|
+
*/
|
|
48
|
+
private fetchWithRetry;
|
|
49
|
+
/**
|
|
50
|
+
* Уведомляет подписчиков эндпоинта об изменении состояния
|
|
51
|
+
*/
|
|
52
|
+
private notifyEndpointSubscribers;
|
|
53
|
+
subscribe(cb: (state: EndpointState) => void): Unsubscribe;
|
|
54
|
+
reset(): Promise<void>;
|
|
55
|
+
destroy(): void;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=endpoint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../../src/api/components/endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAe,MAAM,wBAAwB,CAAA;AAC5E,OAAO,EAAE,QAAQ,IAAI,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,qBAAqB,EAAgB,MAAM,6BAA6B,CAAA;AAC1I,OAAO,EAAE,YAAY,EAAe,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAMjF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAK9C,MAAM,WAAW,oBAAoB,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,eAAe;IAC9F,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,EAAE,cAAc,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;IACtD,mBAAmB,EAAE,sBAAsB,CAAC,qBAAqB,CAAC,CAAA;IAClE,iBAAiB,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAClD,iBAAiB,EAAE,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAClD,eAAe,EAAE,sBAAsB,CAAC,WAAW,CAAC,CAAA;CACrD;AAED,qBAAa,aAAa,CAAC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,eAAe,CAAE,YAAW,YAAY,CAAC,aAAa,EAAE,eAAe,CAAC;IAC5I,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA4C;IAEhF,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAI;IAEvB,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,CAKzB;IAED,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAQ;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAc;IAC3C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAgD;IACtF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA+C;IACnF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiC;IACnE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqC;IAErE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IAEjE,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAE3C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyC;IAExE,qEAAqE;IACrE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAkE;gBAEvF,OAAO,EAAE,oBAAoB,CAAC,aAAa,EAAE,eAAe,CAAC;IA4BlE,OAAO,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,qBAAqB,CAAC,eAAe,CAAC;IA2FrG;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAI1B;;OAEG;YACW,cAAc;IA0H5B;;OAEG;YACW,YAAY;IAsC1B;;OAEG;YACW,cAAc;IA+C5B;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAW1B,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GAAG,WAAW;IAepD,KAAK;IASX,OAAO;CAIf"}
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { createUniqueId, headersToObject } from "../utils/api-helpers.js";
|
|
2
|
+
import { createHeaderContext } from "../utils/create-header-context.js";
|
|
3
|
+
import { createPrepareHeaders, prepareRequestHeaders } from "../utils/endpoint-headers.js";
|
|
4
|
+
import { fetchBaseQuery } from "../utils/fetch-base-query.js";
|
|
5
|
+
import { getCacheableHeaders } from "../utils/get-cacheable-headers.js";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/** HTTP-статусы, при которых делать retry по умолчанию */ const DEFAULT_RETRY_ON = [
|
|
18
|
+
0,
|
|
19
|
+
408,
|
|
20
|
+
429,
|
|
21
|
+
500,
|
|
22
|
+
502,
|
|
23
|
+
503,
|
|
24
|
+
504
|
|
25
|
+
];
|
|
26
|
+
class EndpointClass {
|
|
27
|
+
endpointSubscribers = new Set();
|
|
28
|
+
/** Сколько раз был вызван метод request */ fetchCounts = 0;
|
|
29
|
+
meta = {
|
|
30
|
+
cache: false,
|
|
31
|
+
invalidatesTags: [],
|
|
32
|
+
name: '',
|
|
33
|
+
tags: []
|
|
34
|
+
};
|
|
35
|
+
name;
|
|
36
|
+
queryStorage;
|
|
37
|
+
configCurrentEndpoint;
|
|
38
|
+
cacheableHeaderKeys;
|
|
39
|
+
globalRetryConfig;
|
|
40
|
+
baseQueryConfig;
|
|
41
|
+
queryFunction;
|
|
42
|
+
/** Массив заголовков, которые нужно включить в ключ кэширования */ cacheableHeaders;
|
|
43
|
+
prepareHeaders;
|
|
44
|
+
/** Карта in-flight запросов для дедупликации (cacheKey → Promise) */ inflightRequests = new Map();
|
|
45
|
+
constructor(options){
|
|
46
|
+
this.name = options.name;
|
|
47
|
+
this.queryStorage = options.queryStorage;
|
|
48
|
+
this.configCurrentEndpoint = options.config;
|
|
49
|
+
this.cacheableHeaderKeys = options.cacheableHeaderKeys;
|
|
50
|
+
this.globalRetryConfig = options.globalRetryConfig;
|
|
51
|
+
this.baseQueryConfig = options.baseQueryConfig;
|
|
52
|
+
// 1. Создаем функцию подготовки заголовков
|
|
53
|
+
this.prepareHeaders = createPrepareHeaders(this.baseQueryConfig.prepareHeaders, this.configCurrentEndpoint.prepareHeaders);
|
|
54
|
+
// 2. Создаем функцию исполнения запроса
|
|
55
|
+
this.queryFunction = fetchBaseQuery({
|
|
56
|
+
baseUrl: this.baseQueryConfig.baseUrl,
|
|
57
|
+
fetchFn: this.baseQueryConfig.fetchFn,
|
|
58
|
+
timeout: this.baseQueryConfig.timeout,
|
|
59
|
+
credentials: this.baseQueryConfig.credentials
|
|
60
|
+
});
|
|
61
|
+
// 3. Создаем массив тех заголовков, которые нужно включить в ключ кэширования
|
|
62
|
+
this.cacheableHeaders = [
|
|
63
|
+
...this.cacheableHeaderKeys || [],
|
|
64
|
+
...this.configCurrentEndpoint.includeCacheableHeaderKeys || []
|
|
65
|
+
].filter((key)=>!this.configCurrentEndpoint.excludeCacheableHeaderKeys?.includes(key));
|
|
66
|
+
// 4. Сохраняем информацию в meta
|
|
67
|
+
this.meta.name = this.name;
|
|
68
|
+
this.meta.tags = this.configCurrentEndpoint.tags ?? this.meta.tags;
|
|
69
|
+
this.meta.invalidatesTags = this.configCurrentEndpoint.invalidatesTags ?? this.meta.invalidatesTags;
|
|
70
|
+
this.meta.cache = this.queryStorage.createCacheConfig(this.configCurrentEndpoint) ?? this.meta.cache;
|
|
71
|
+
}
|
|
72
|
+
request(params, options) {
|
|
73
|
+
// 1. Подготовка и инициализация
|
|
74
|
+
this.fetchCounts++;
|
|
75
|
+
const requestId = createUniqueId(this.name);
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const requestSubscribers = new Set();
|
|
78
|
+
const currentState = {
|
|
79
|
+
status: 'idle',
|
|
80
|
+
requestParams: params,
|
|
81
|
+
headers: {},
|
|
82
|
+
error: undefined,
|
|
83
|
+
data: undefined,
|
|
84
|
+
fromCache: false
|
|
85
|
+
};
|
|
86
|
+
// Связываем пользовательский signal с внутренним controller
|
|
87
|
+
if (options?.signal) {
|
|
88
|
+
if (options.signal.aborted) {
|
|
89
|
+
controller.abort();
|
|
90
|
+
} else {
|
|
91
|
+
options.signal.addEventListener('abort', ()=>controller.abort(), {
|
|
92
|
+
once: true
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// 2. Функция нотификации подписчиков запроса
|
|
97
|
+
const notifyRequestSubscribers = (newState)=>{
|
|
98
|
+
Object.assign(currentState, newState);
|
|
99
|
+
requestSubscribers.forEach((cb)=>cb({
|
|
100
|
+
...currentState
|
|
101
|
+
}));
|
|
102
|
+
};
|
|
103
|
+
// 3. Запускаем выполнение запроса
|
|
104
|
+
const waitPromise = this.executeRequest(params, options, controller, notifyRequestSubscribers);
|
|
105
|
+
// 4. Возвращаем объект с методами управления запросом
|
|
106
|
+
return {
|
|
107
|
+
id: requestId,
|
|
108
|
+
subscribe (listener, subscribeOptions = {}) {
|
|
109
|
+
const { autoUnsubscribe = true } = subscribeOptions;
|
|
110
|
+
requestSubscribers.add(listener);
|
|
111
|
+
listener(currentState);
|
|
112
|
+
const unsubscribe = ()=>requestSubscribers.delete(listener);
|
|
113
|
+
if (autoUnsubscribe) {
|
|
114
|
+
waitPromise.finally(()=>unsubscribe());
|
|
115
|
+
}
|
|
116
|
+
return unsubscribe;
|
|
117
|
+
},
|
|
118
|
+
wait: ()=>waitPromise,
|
|
119
|
+
waitWithCallbacks (handlers = {}) {
|
|
120
|
+
const { idle, loading, success, error } = handlers;
|
|
121
|
+
this.subscribe((state)=>{
|
|
122
|
+
switch(state.status){
|
|
123
|
+
case 'idle':
|
|
124
|
+
idle?.(state);
|
|
125
|
+
break;
|
|
126
|
+
case 'loading':
|
|
127
|
+
loading?.(state);
|
|
128
|
+
break;
|
|
129
|
+
case 'success':
|
|
130
|
+
success?.(state.data, state);
|
|
131
|
+
break;
|
|
132
|
+
case 'error':
|
|
133
|
+
error?.(state.error, state);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}, {
|
|
137
|
+
autoUnsubscribe: true
|
|
138
|
+
});
|
|
139
|
+
return waitPromise;
|
|
140
|
+
},
|
|
141
|
+
abort: ()=>{
|
|
142
|
+
if (!controller.signal.aborted) {
|
|
143
|
+
controller.abort();
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
then: (onfulfilled, onrejected)=>waitPromise.then(onfulfilled, onrejected),
|
|
147
|
+
catch: (onrejected)=>waitPromise.catch(onrejected),
|
|
148
|
+
finally: (onfinally)=>waitPromise.finally(onfinally)
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Определяет итоговую конфигурацию retry: вызов → эндпоинт → глобальная
|
|
153
|
+
*/ resolveRetryConfig(options) {
|
|
154
|
+
return options?.retry ?? this.configCurrentEndpoint.retry ?? this.globalRetryConfig;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Выполняет сетевой запрос с кэшированием, дедупликацией и retry
|
|
158
|
+
*/ async executeRequest(params, options, controller, notify) {
|
|
159
|
+
const headerContext = createHeaderContext({
|
|
160
|
+
requestParams: params
|
|
161
|
+
}, options?.context || {});
|
|
162
|
+
try {
|
|
163
|
+
// 1. Формируем заголовки
|
|
164
|
+
const headers = await prepareRequestHeaders(this.prepareHeaders, headerContext);
|
|
165
|
+
const headersForCache = getCacheableHeaders(headers, options?.cacheableHeaderKeys ? options.cacheableHeaderKeys : this.cacheableHeaders);
|
|
166
|
+
// 2. Формируем requestDefinition для определения метода
|
|
167
|
+
const requestDefinition = this.configCurrentEndpoint.request(params, options?.context);
|
|
168
|
+
// 3. Проверяем кэширование (с учётом HTTP-метода)
|
|
169
|
+
const shouldCache = this.queryStorage.shouldCache(this.configCurrentEndpoint, options, requestDefinition.method);
|
|
170
|
+
const [cacheKey, cacheParams] = this.queryStorage.createCacheKey(this.name, {
|
|
171
|
+
...params,
|
|
172
|
+
...headersForCache
|
|
173
|
+
});
|
|
174
|
+
const cacheKeyStr = String(cacheKey);
|
|
175
|
+
// 4. Проверяем кэш
|
|
176
|
+
if (shouldCache) {
|
|
177
|
+
const cachedResult = await this.queryStorage.getCachedResult(cacheKey);
|
|
178
|
+
if (cachedResult) {
|
|
179
|
+
notify({
|
|
180
|
+
fromCache: true,
|
|
181
|
+
status: 'success',
|
|
182
|
+
data: cachedResult.data,
|
|
183
|
+
error: undefined,
|
|
184
|
+
headers: cachedResult.headers,
|
|
185
|
+
requestParams: params
|
|
186
|
+
});
|
|
187
|
+
return {
|
|
188
|
+
...cachedResult,
|
|
189
|
+
fromCache: true
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// 5. Дедупликация: если запрос с таким же ключом уже летит — ждём его
|
|
194
|
+
if (shouldCache && this.inflightRequests.has(cacheKeyStr)) {
|
|
195
|
+
notify({
|
|
196
|
+
fromCache: false,
|
|
197
|
+
status: 'loading'
|
|
198
|
+
});
|
|
199
|
+
const result = await this.inflightRequests.get(cacheKeyStr);
|
|
200
|
+
if (!result.ok) {
|
|
201
|
+
notify({
|
|
202
|
+
fromCache: true,
|
|
203
|
+
status: 'error',
|
|
204
|
+
data: undefined,
|
|
205
|
+
error: result.error,
|
|
206
|
+
headers: result.headers,
|
|
207
|
+
requestParams: params
|
|
208
|
+
});
|
|
209
|
+
return {
|
|
210
|
+
...result,
|
|
211
|
+
fromCache: true
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
notify({
|
|
215
|
+
fromCache: true,
|
|
216
|
+
status: 'success',
|
|
217
|
+
data: result.data,
|
|
218
|
+
error: undefined,
|
|
219
|
+
headers: result.headers,
|
|
220
|
+
requestParams: params
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
...result,
|
|
224
|
+
fromCache: true
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
// 6. Выполняем запрос (с retry и post-processing)
|
|
228
|
+
notify({
|
|
229
|
+
fromCache: false,
|
|
230
|
+
status: 'loading'
|
|
231
|
+
});
|
|
232
|
+
const retryConfig = this.resolveRetryConfig(options);
|
|
233
|
+
const fetchPromise = this.executeFetch(requestDefinition, options, controller, headers, retryConfig, shouldCache, cacheKey, cacheParams ?? {});
|
|
234
|
+
// Регистрируем в inflight для дедупликации (только для кэшируемых)
|
|
235
|
+
if (shouldCache) {
|
|
236
|
+
this.inflightRequests.set(cacheKeyStr, fetchPromise);
|
|
237
|
+
fetchPromise.finally(()=>this.inflightRequests.delete(cacheKeyStr)).catch(()=>{});
|
|
238
|
+
}
|
|
239
|
+
const response = await fetchPromise;
|
|
240
|
+
// 7. Обрабатываем результат
|
|
241
|
+
if (response.ok) {
|
|
242
|
+
notify({
|
|
243
|
+
fromCache: false,
|
|
244
|
+
status: 'success',
|
|
245
|
+
data: response.data,
|
|
246
|
+
error: undefined,
|
|
247
|
+
headers: response.headers,
|
|
248
|
+
requestParams: params
|
|
249
|
+
});
|
|
250
|
+
this.notifyEndpointSubscribers('success');
|
|
251
|
+
return {
|
|
252
|
+
...response,
|
|
253
|
+
fromCache: false
|
|
254
|
+
};
|
|
255
|
+
} else {
|
|
256
|
+
// invalidateOnError: инвалидируем кэш при ошибке если включено
|
|
257
|
+
if (shouldCache) {
|
|
258
|
+
const cacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint);
|
|
259
|
+
if (cacheConfig.invalidateOnError !== false) {
|
|
260
|
+
await this.queryStorage.invalidateCache(cacheKey);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
notify({
|
|
264
|
+
fromCache: false,
|
|
265
|
+
status: 'error',
|
|
266
|
+
data: undefined,
|
|
267
|
+
error: response.error,
|
|
268
|
+
headers: response.headers,
|
|
269
|
+
requestParams: params
|
|
270
|
+
});
|
|
271
|
+
this.notifyEndpointSubscribers('error', response.error);
|
|
272
|
+
throw response.error;
|
|
273
|
+
}
|
|
274
|
+
} catch (error) {
|
|
275
|
+
notify({
|
|
276
|
+
fromCache: false,
|
|
277
|
+
status: 'error',
|
|
278
|
+
data: undefined,
|
|
279
|
+
error: error,
|
|
280
|
+
headers: undefined,
|
|
281
|
+
requestParams: params
|
|
282
|
+
});
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Выполняет HTTP-запрос с retry, инвалидацией тегов и кэшированием результата
|
|
288
|
+
*/ async executeFetch(requestDefinition, options, controller, headers, retryConfig, shouldCache, cacheKey, cacheParams) {
|
|
289
|
+
// Выполняем HTTP-запрос (с retry если настроен)
|
|
290
|
+
const response = await this.fetchWithRetry(requestDefinition, options, controller, headers, retryConfig);
|
|
291
|
+
// Post-processing при успешном ответе
|
|
292
|
+
if (response.ok) {
|
|
293
|
+
const { headers: responseHeaders, ...restResponse } = response;
|
|
294
|
+
// Инвалидируем кэш по тегам
|
|
295
|
+
if (this.configCurrentEndpoint.invalidatesTags?.length) {
|
|
296
|
+
await this.queryStorage.invalidateCacheByTags(this.configCurrentEndpoint.invalidatesTags);
|
|
297
|
+
}
|
|
298
|
+
// Сохраняем в кэш
|
|
299
|
+
if (shouldCache) {
|
|
300
|
+
const currentCacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint);
|
|
301
|
+
await this.queryStorage.setCachedResult(cacheKey, {
|
|
302
|
+
...restResponse,
|
|
303
|
+
headers: headersToObject(responseHeaders)
|
|
304
|
+
}, currentCacheConfig, cacheParams, this.configCurrentEndpoint.tags ?? []);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return response;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Выполняет HTTP-запрос с повторными попытками
|
|
311
|
+
*/ async fetchWithRetry(requestDefinition, options, controller, headers, retryConfig) {
|
|
312
|
+
const maxAttempts = (retryConfig?.count ?? 0) + 1;
|
|
313
|
+
const retryOn = retryConfig?.retryOn ?? DEFAULT_RETRY_ON;
|
|
314
|
+
const getDelay = (attempt)=>{
|
|
315
|
+
if (typeof retryConfig?.delay === 'function') return retryConfig.delay(attempt);
|
|
316
|
+
return retryConfig?.delay ?? 1000;
|
|
317
|
+
};
|
|
318
|
+
let lastResponse;
|
|
319
|
+
for(let attempt = 0; attempt < maxAttempts; attempt++){
|
|
320
|
+
// Если запрос отменён — бросаем ошибку (перехватывается в executeRequest)
|
|
321
|
+
if (controller.signal.aborted) throw new DOMException('The operation was aborted.', 'AbortError');
|
|
322
|
+
const mergedOptions = {
|
|
323
|
+
...options,
|
|
324
|
+
signal: controller.signal
|
|
325
|
+
};
|
|
326
|
+
lastResponse = await this.queryFunction(requestDefinition, mergedOptions, headers);
|
|
327
|
+
// Успех или не-retryable статус — возвращаем сразу
|
|
328
|
+
if (lastResponse.ok || !retryOn.includes(lastResponse.status) || attempt === maxAttempts - 1) {
|
|
329
|
+
return lastResponse;
|
|
330
|
+
}
|
|
331
|
+
// Ждём перед следующей попыткой
|
|
332
|
+
const delay = getDelay(attempt);
|
|
333
|
+
await new Promise((resolve)=>{
|
|
334
|
+
const timer = setTimeout(resolve, delay);
|
|
335
|
+
// Если запрос отменили во время ожидания — прерываем delay
|
|
336
|
+
controller.signal.addEventListener('abort', ()=>{
|
|
337
|
+
clearTimeout(timer);
|
|
338
|
+
resolve();
|
|
339
|
+
}, {
|
|
340
|
+
once: true
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
return lastResponse;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Уведомляет подписчиков эндпоинта об изменении состояния
|
|
348
|
+
*/ notifyEndpointSubscribers(status, error) {
|
|
349
|
+
const endpointState = {
|
|
350
|
+
status,
|
|
351
|
+
fetchCounts: this.fetchCounts,
|
|
352
|
+
meta: this.meta,
|
|
353
|
+
cacheableHeaders: this.cacheableHeaders,
|
|
354
|
+
error
|
|
355
|
+
};
|
|
356
|
+
this.endpointSubscribers.forEach((cb)=>cb(endpointState));
|
|
357
|
+
}
|
|
358
|
+
subscribe(cb) {
|
|
359
|
+
this.endpointSubscribers.add(cb);
|
|
360
|
+
const currentState = {
|
|
361
|
+
status: 'idle',
|
|
362
|
+
fetchCounts: this.fetchCounts,
|
|
363
|
+
meta: this.meta,
|
|
364
|
+
cacheableHeaders: this.cacheableHeaders,
|
|
365
|
+
error: undefined
|
|
366
|
+
};
|
|
367
|
+
cb(currentState);
|
|
368
|
+
return ()=>this.endpointSubscribers.delete(cb);
|
|
369
|
+
}
|
|
370
|
+
async reset() {
|
|
371
|
+
this.fetchCounts = 0;
|
|
372
|
+
// Инвалидируем кэш по тегам эндпоинта
|
|
373
|
+
if (this.meta.tags.length) {
|
|
374
|
+
await this.queryStorage.invalidateCacheByTags(this.meta.tags);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
destroy() {
|
|
378
|
+
this.endpointSubscribers.clear();
|
|
379
|
+
this.inflightRequests.clear();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export { EndpointClass };
|
|
384
|
+
|
|
385
|
+
//# sourceMappingURL=endpoint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api/components/endpoint.js","sources":["../../../src/api/components/endpoint.ts"],"sourcesContent":["import { CreateApiClientOptions, RetryConfig } 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\n/** HTTP-статусы, при которых делать retry по умолчанию */\nconst DEFAULT_RETRY_ON = [0, 408, 429, 500, 502, 503, 504]\n\nexport interface EndpointClassOptions<RequestParams extends Record<string, any>, RequestResponse> {\n name: string\n queryStorage: QueryStorage\n config: EndpointConfig<RequestParams, RequestResponse>\n cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys']\n globalCacheConfig: CreateApiClientOptions['cache']\n globalRetryConfig: CreateApiClientOptions['retry']\n baseQueryConfig: CreateApiClientOptions['baseQuery']\n}\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 name: string\n private readonly queryStorage: QueryStorage\n private readonly configCurrentEndpoint: EndpointConfig<RequestParams, RequestResponse>\n private readonly cacheableHeaderKeys: CreateApiClientOptions['cacheableHeaderKeys']\n private readonly globalRetryConfig: CreateApiClientOptions['retry']\n private readonly baseQueryConfig: CreateApiClientOptions['baseQuery']\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 /** Карта in-flight запросов для дедупликации (cacheKey → Promise) */\n private readonly inflightRequests = new Map<string, Promise<QueryResult<RequestResponse, Error>>>()\n\n constructor(options: EndpointClassOptions<RequestParams, RequestResponse>) {\n this.name = options.name\n this.queryStorage = options.queryStorage\n this.configCurrentEndpoint = options.config\n this.cacheableHeaderKeys = options.cacheableHeaderKeys\n this.globalRetryConfig = options.globalRetryConfig\n this.baseQueryConfig = options.baseQueryConfig\n\n // 1. Создаем функцию подготовки заголовков\n this.prepareHeaders = createPrepareHeaders(this.baseQueryConfig.prepareHeaders, this.configCurrentEndpoint.prepareHeaders)\n // 2. Создаем функцию исполнения запроса\n this.queryFunction = fetchBaseQuery({\n baseUrl: this.baseQueryConfig.baseUrl,\n fetchFn: this.baseQueryConfig.fetchFn,\n timeout: this.baseQueryConfig.timeout,\n credentials: this.baseQueryConfig.credentials,\n })\n // 3. Создаем массив тех заголовков, которые нужно включить в ключ кэширования\n this.cacheableHeaders = [...(this.cacheableHeaderKeys || []), ...(this.configCurrentEndpoint.includeCacheableHeaderKeys || [])].filter(\n (key) => !this.configCurrentEndpoint.excludeCacheableHeaderKeys?.includes(key),\n )\n // 4. Сохраняем информацию в meta\n this.meta.name = this.name\n this.meta.tags = this.configCurrentEndpoint.tags ?? this.meta.tags\n this.meta.invalidatesTags = this.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\n // Связываем пользовательский signal с внутренним controller\n if (options?.signal) {\n if (options.signal.aborted) {\n controller.abort()\n } else {\n options.signal.addEventListener('abort', () => controller.abort(), { once: true })\n }\n }\n\n // 2. Функция нотификации подписчиков запроса\n const notifyRequestSubscribers = (newState: Partial<RequestState<RequestResponse, RequestParams>>) => {\n Object.assign(currentState, newState)\n requestSubscribers.forEach((cb) => cb({ ...currentState }))\n }\n\n // 3. Запускаем выполнение запроса\n const waitPromise = this.executeRequest(params, options, controller, notifyRequestSubscribers)\n\n // 4. Возвращаем объект с методами управления запросом\n return {\n id: requestId,\n\n subscribe(listener, subscribeOptions = {}) {\n const { autoUnsubscribe = true } = subscribeOptions\n requestSubscribers.add(listener)\n listener(currentState)\n\n const unsubscribe = () => requestSubscribers.delete(listener)\n\n if (autoUnsubscribe) {\n waitPromise.finally(() => unsubscribe())\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.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 /**\n * Определяет итоговую конфигурацию retry: вызов → эндпоинт → глобальная\n */\n private resolveRetryConfig(options?: QueryOptions): RetryConfig | undefined {\n return options?.retry ?? this.configCurrentEndpoint.retry ?? this.globalRetryConfig\n }\n\n /**\n * Выполняет сетевой запрос с кэшированием, дедупликацией и retry\n */\n private async executeRequest(\n params: RequestParams,\n options: QueryOptions | undefined,\n controller: AbortController,\n notify: (state: Partial<RequestState<RequestResponse, RequestParams>>) => void,\n ): Promise<QueryResult<RequestResponse, Error>> {\n const headerContext = createHeaderContext({ requestParams: params }, options?.context || {})\n\n try {\n // 1. Формируем заголовки\n const headers = await prepareRequestHeaders(this.prepareHeaders, headerContext)\n const headersForCache = getCacheableHeaders(headers, options?.cacheableHeaderKeys ? options.cacheableHeaderKeys : this.cacheableHeaders)\n\n // 2. Формируем requestDefinition для определения метода\n const requestDefinition = this.configCurrentEndpoint.request(params, options?.context)\n\n // 3. Проверяем кэширование (с учётом HTTP-метода)\n const shouldCache = this.queryStorage.shouldCache(this.configCurrentEndpoint, options, requestDefinition.method)\n const [cacheKey, cacheParams] = this.queryStorage.createCacheKey(this.name, { ...params, ...headersForCache })\n const cacheKeyStr = String(cacheKey)\n\n // 4. Проверяем кэш\n if (shouldCache) {\n const cachedResult = await this.queryStorage.getCachedResult<QueryResult<RequestResponse>>(cacheKey)\n if (cachedResult) {\n notify({\n fromCache: true,\n status: 'success',\n data: cachedResult.data,\n error: undefined,\n headers: cachedResult.headers,\n requestParams: params,\n })\n return { ...cachedResult, fromCache: true }\n }\n }\n\n // 5. Дедупликация: если запрос с таким же ключом уже летит — ждём его\n if (shouldCache && this.inflightRequests.has(cacheKeyStr)) {\n notify({ fromCache: false, status: 'loading' })\n const result = await this.inflightRequests.get(cacheKeyStr)!\n if (!result.ok) {\n notify({\n fromCache: true,\n status: 'error',\n data: undefined,\n error: result.error,\n headers: result.headers,\n requestParams: params,\n })\n return { ...result, fromCache: true }\n }\n notify({\n fromCache: true,\n status: 'success',\n data: result.data,\n error: undefined,\n headers: result.headers,\n requestParams: params,\n })\n return { ...result, fromCache: true }\n }\n\n // 6. Выполняем запрос (с retry и post-processing)\n notify({ fromCache: false, status: 'loading' })\n\n const retryConfig = this.resolveRetryConfig(options)\n const fetchPromise = this.executeFetch(requestDefinition, options, controller, headers, retryConfig, shouldCache, cacheKey, cacheParams ?? {})\n\n // Регистрируем в inflight для дедупликации (только для кэшируемых)\n if (shouldCache) {\n this.inflightRequests.set(cacheKeyStr, fetchPromise)\n fetchPromise.finally(() => this.inflightRequests.delete(cacheKeyStr)).catch(() => {})\n }\n\n const response = await fetchPromise\n\n // 7. Обрабатываем результат\n if (response.ok) {\n notify({\n fromCache: false,\n status: 'success',\n data: response.data,\n error: undefined,\n headers: response.headers,\n requestParams: params,\n })\n this.notifyEndpointSubscribers('success')\n return { ...response, fromCache: false }\n } else {\n // invalidateOnError: инвалидируем кэш при ошибке если включено\n if (shouldCache) {\n const cacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint)\n if (cacheConfig.invalidateOnError !== false) {\n await this.queryStorage.invalidateCache(cacheKey)\n }\n }\n\n notify({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: response.error,\n headers: response.headers,\n requestParams: params,\n })\n this.notifyEndpointSubscribers('error', response.error)\n throw response.error\n }\n } catch (error) {\n notify({\n fromCache: false,\n status: 'error',\n data: undefined,\n error: error as Error,\n headers: undefined,\n requestParams: params,\n })\n throw error\n }\n }\n\n /**\n * Выполняет HTTP-запрос с retry, инвалидацией тегов и кэшированием результата\n */\n private async executeFetch(\n requestDefinition: ReturnType<EndpointConfig<RequestParams, RequestResponse>['request']>,\n options: QueryOptions | undefined,\n controller: AbortController,\n headers: Headers,\n retryConfig: RetryConfig | undefined,\n shouldCache: boolean,\n cacheKey: ReturnType<QueryStorage['createCacheKey']>[0],\n cacheParams: Record<string, any>,\n ): Promise<QueryResult<RequestResponse, Error>> {\n // Выполняем HTTP-запрос (с retry если настроен)\n const response = await this.fetchWithRetry(requestDefinition, options, controller, headers, retryConfig)\n\n // Post-processing при успешном ответе\n if (response.ok) {\n const { headers: responseHeaders, ...restResponse } = response\n\n // Инвалидируем кэш по тегам\n if (this.configCurrentEndpoint.invalidatesTags?.length) {\n await this.queryStorage.invalidateCacheByTags(this.configCurrentEndpoint.invalidatesTags)\n }\n\n // Сохраняем в кэш\n if (shouldCache) {\n const currentCacheConfig = this.queryStorage.createCacheConfig(this.configCurrentEndpoint)\n await this.queryStorage.setCachedResult(\n cacheKey,\n { ...restResponse, headers: headersToObject(responseHeaders) },\n currentCacheConfig,\n cacheParams,\n this.configCurrentEndpoint.tags ?? [],\n )\n }\n }\n\n return response\n }\n\n /**\n * Выполняет HTTP-запрос с повторными попытками\n */\n private async fetchWithRetry(\n requestDefinition: ReturnType<EndpointConfig<RequestParams, RequestResponse>['request']>,\n options: QueryOptions | undefined,\n controller: AbortController,\n headers: Headers,\n retryConfig?: RetryConfig,\n ): Promise<QueryResult<RequestResponse, Error>> {\n const maxAttempts = (retryConfig?.count ?? 0) + 1\n const retryOn = retryConfig?.retryOn ?? DEFAULT_RETRY_ON\n const getDelay = (attempt: number): number => {\n if (typeof retryConfig?.delay === 'function') return retryConfig.delay(attempt)\n return retryConfig?.delay ?? 1000\n }\n\n let lastResponse!: QueryResult<RequestResponse, Error>\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n // Если запрос отменён — бросаем ошибку (перехватывается в executeRequest)\n if (controller.signal.aborted) throw new DOMException('The operation was aborted.', 'AbortError')\n\n const mergedOptions: QueryOptions = { ...options, signal: controller.signal }\n lastResponse = await this.queryFunction<RequestResponse, RequestParams>(requestDefinition, mergedOptions, headers)\n\n // Успех или не-retryable статус — возвращаем сразу\n if (lastResponse.ok || !retryOn.includes(lastResponse.status) || attempt === maxAttempts - 1) {\n return lastResponse\n }\n\n // Ждём перед следующей попыткой\n const delay = getDelay(attempt)\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delay)\n // Если запрос отменили во время ожидания — прерываем delay\n controller.signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer)\n resolve()\n },\n { once: true },\n )\n })\n }\n\n return lastResponse\n }\n\n /**\n * Уведомляет подписчиков эндпоинта об изменении состояния\n */\n private notifyEndpointSubscribers(status: 'success' | 'error', error?: Error): void {\n const endpointState: EndpointState = {\n status,\n fetchCounts: this.fetchCounts,\n meta: this.meta,\n cacheableHeaders: this.cacheableHeaders,\n error,\n }\n this.endpointSubscribers.forEach((cb) => cb(endpointState))\n }\n\n public subscribe(cb: (state: EndpointState) => void): Unsubscribe {\n this.endpointSubscribers.add(cb)\n\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 cb(currentState)\n return () => this.endpointSubscribers.delete(cb)\n }\n\n public async reset() {\n this.fetchCounts = 0\n\n // Инвалидируем кэш по тегам эндпоинта\n if (this.meta.tags.length) {\n await this.queryStorage.invalidateCacheByTags(this.meta.tags)\n }\n }\n\n public destroy() {\n this.endpointSubscribers.clear()\n this.inflightRequests.clear()\n }\n}\n"],"names":["createUniqueId","headersToObject","createHeaderContext","createPrepareHeaders","prepareRequestHeaders","fetchBaseQuery","getCacheableHeaders","DEFAULT_RETRY_ON","EndpointClass","Set","Map","options","key","params","requestId","controller","AbortController","requestSubscribers","currentState","undefined","notifyRequestSubscribers","newState","Object","cb","waitPromise","listener","subscribeOptions","autoUnsubscribe","unsubscribe","handlers","idle","loading","success","error","state","onfulfilled","onrejected","onfinally","notify","headerContext","headers","headersForCache","requestDefinition","shouldCache","cacheKey","cacheParams","cacheKeyStr","String","cachedResult","result","retryConfig","fetchPromise","response","cacheConfig","responseHeaders","restResponse","currentCacheConfig","maxAttempts","retryOn","getDelay","attempt","lastResponse","DOMException","mergedOptions","delay","Promise","resolve","timer","setTimeout","clearTimeout","status","endpointState"],"mappings":";;;;;;;;;;;AAGsE;AACF;AACmB;AAC7B;AACU;AAGpE,wDAAwD,GACxD,MAAMO,gBAAgBA,GAAG;IAAC;IAAG;IAAK;IAAK;IAAK;IAAK;IAAK;CAAI;AAYnD,MAAMC,aAAaA;IACP,sBAAsB,IAAIC,MAAqC;IAEhF,yCAAyC,GACzC,cAAsB,EAAC;IAEvB,OAA6B;QAC3B,OAAO;QACP,iBAAiB,EAAE;QACnB,MAAM;QACN,MAAM,EAAE;IACV,EAAC;IAEgB,KAAY;IACZ,aAA0B;IAC1B,sBAAqE;IACrE,oBAAkE;IAClE,kBAAkD;IAClD,gBAAoD;IAEpD,cAAgD;IAEjE,iEAAiE,GAChD,iBAA0B;IAE1B,eAAuD;IAExE,mEAAmE,GAClD,mBAAmB,IAAIC,MAA2D;IAEnG,YAAYC,OAA6D,CAAE;QACzE,IAAI,CAAC,IAAI,GAAGA,QAAQ,IAAI;QACxB,IAAI,CAAC,YAAY,GAAGA,QAAQ,YAAY;QACxC,IAAI,CAAC,qBAAqB,GAAGA,QAAQ,MAAM;QAC3C,IAAI,CAAC,mBAAmB,GAAGA,QAAQ,mBAAmB;QACtD,IAAI,CAAC,iBAAiB,GAAGA,QAAQ,iBAAiB;QAClD,IAAI,CAAC,eAAe,GAAGA,QAAQ,eAAe;QAE9C,2CAA2C;QAC3C,IAAI,CAAC,cAAc,GAAGR,oBAAoBA,CAAC,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,IAAI,CAAC,qBAAqB,CAAC,cAAc;QACzH,wCAAwC;QACxC,IAAI,CAAC,aAAa,GAAGE,cAAcA,CAAC;YAClC,SAAS,IAAI,CAAC,eAAe,CAAC,OAAO;YACrC,SAAS,IAAI,CAAC,eAAe,CAAC,OAAO;YACrC,SAAS,IAAI,CAAC,eAAe,CAAC,OAAO;YACrC,aAAa,IAAI,CAAC,eAAe,CAAC,WAAW;QAC/C;QACA,8EAA8E;QAC9E,IAAI,CAAC,gBAAgB,GAAG;eAAK,IAAI,CAAC,mBAAmB,IAAI,EAAE;eAAO,IAAI,CAAC,qBAAqB,CAAC,0BAA0B,IAAI,EAAE;SAAE,CAAC,MAAM,CACpI,CAACO,MAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,0BAA0B,EAAE,SAASA;QAE5E,iCAAiC;QACjC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI;QAC1B,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI;QAClE,IAAI,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,eAAe;QACnG,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,qBAAqB,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK;IACtG;IAEO,QAAQC,MAAqB,EAAEF,OAAsB,EAA0C;QACpG,gCAAgC;QAChC,IAAI,CAAC,WAAW;QAChB,MAAMG,YAAYd,cAAcA,CAAC,IAAI,CAAC,IAAI;QAC1C,MAAMe,aAAa,IAAIC;QACvB,MAAMC,qBAAqB,IAAIR;QAC/B,MAAMS,eAA6D;YACjE,QAAQ;YACR,eAAeL;YACf,SAAS,CAAC;YACV,OAAOM;YACP,MAAMA;YACN,WAAW;QACb;QAEA,4DAA4D;QAC5D,IAAIR,SAAS,QAAQ;YACnB,IAAIA,QAAQ,MAAM,CAAC,OAAO,EAAE;gBAC1BI,WAAW,KAAK;YAClB,OAAO;gBACLJ,QAAQ,MAAM,CAAC,gBAAgB,CAAC,SAAS,IAAMI,WAAW,KAAK,IAAI;oBAAE,MAAM;gBAAK;YAClF;QACF;QAEA,6CAA6C;QAC7C,MAAMK,2BAA2B,CAACC;YAChCC,OAAO,MAAM,CAACJ,cAAcG;YAC5BJ,mBAAmB,OAAO,CAAC,CAACM,KAAOA,GAAG;oBAAE,GAAGL,YAAY;gBAAC;QAC1D;QAEA,kCAAkC;QAClC,MAAMM,cAAc,IAAI,CAAC,cAAc,CAACX,QAAQF,SAASI,YAAYK;QAErE,sDAAsD;QACtD,OAAO;YACL,IAAIN;YAEJ,WAAUW,QAAQ,EAAEC,mBAAmB,CAAC,CAAC;gBACvC,MAAM,EAAEC,kBAAkB,IAAI,EAAE,GAAGD;gBACnCT,mBAAmB,GAAG,CAACQ;gBACvBA,SAASP;gBAET,MAAMU,cAAc,IAAMX,mBAAmB,MAAM,CAACQ;gBAEpD,IAAIE,iBAAiB;oBACnBH,YAAY,OAAO,CAAC,IAAMI;gBAC5B;gBAEA,OAAOA;YACT;YAEA,MAAM,IAAMJ;YAEZ,mBAAkBK,WAAW,CAAC,CAAC;gBAC7B,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,OAAO,EAAEC,KAAK,EAAE,GAAGJ;gBAE1C,IAAI,CAAC,SAAS,CACZ,CAACK;oBACC,OAAQA,MAAM,MAAM;wBAClB,KAAK;4BACHJ,OAAOI;4BACP;wBACF,KAAK;4BACHH,UAAUG;4BACV;wBACF,KAAK;4BACHF,UAAUE,MAAM,IAAI,EAAEA;4BACtB;wBACF,KAAK;4BACHD,QAAQC,MAAM,KAAK,EAAEA;4BACrB;oBACJ;gBACF,GACA;oBAAE,iBAAiB;gBAAK;gBAG1B,OAAOV;YACT;YAEA,OAAO;gBACL,IAAI,CAACT,WAAW,MAAM,CAAC,OAAO,EAAE;oBAC9BA,WAAW,KAAK;gBAClB;YACF;YAEA,MAAM,CAACoB,aAAaC,aAAeZ,YAAY,IAAI,CAACW,aAAaC;YACjE,OAAO,CAACA,aAAeZ,YAAY,KAAK,CAACY;YACzC,SAAS,CAACC,YAAcb,YAAY,OAAO,CAACa;QAC9C;IACF;IAEA;;GAEC,GACO,mBAAmB1B,OAAsB,EAA2B;QAC1E,OAAOA,SAAS,SAAS,IAAI,CAAC,qBAAqB,CAAC,KAAK,IAAI,IAAI,CAAC,iBAAiB;IACrF;IAEA;;GAEC,GACD,MAAc,eACZE,MAAqB,EACrBF,OAAiC,EACjCI,UAA2B,EAC3BuB,MAA8E,EAChC;QAC9C,MAAMC,gBAAgBrC,mBAAmBA,CAAC;YAAE,eAAeW;QAAO,GAAGF,SAAS,WAAW,CAAC;QAE1F,IAAI;YACF,yBAAyB;YACzB,MAAM6B,UAAU,MAAMpC,qBAAqBA,CAAC,IAAI,CAAC,cAAc,EAAEmC;YACjE,MAAME,kBAAkBnC,mBAAmBA,CAACkC,SAAS7B,SAAS,sBAAsBA,QAAQ,mBAAmB,GAAG,IAAI,CAAC,gBAAgB;YAEvI,wDAAwD;YACxD,MAAM+B,oBAAoB,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC7B,QAAQF,SAAS;YAE9E,kDAAkD;YAClD,MAAMgC,cAAc,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,qBAAqB,EAAEhC,SAAS+B,kBAAkB,MAAM;YAC/G,MAAM,CAACE,UAAUC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE;gBAAE,GAAGhC,MAAM;gBAAE,GAAG4B,eAAe;YAAC;YAC5G,MAAMK,cAAcC,OAAOH;YAE3B,mBAAmB;YACnB,IAAID,aAAa;gBACf,MAAMK,eAAe,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAA+BJ;gBAC3F,IAAII,cAAc;oBAChBV,OAAO;wBACL,WAAW;wBACX,QAAQ;wBACR,MAAMU,aAAa,IAAI;wBACvB,OAAO7B;wBACP,SAAS6B,aAAa,OAAO;wBAC7B,eAAenC;oBACjB;oBACA,OAAO;wBAAE,GAAGmC,YAAY;wBAAE,WAAW;oBAAK;gBAC5C;YACF;YAEA,sEAAsE;YACtE,IAAIL,eAAe,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACG,cAAc;gBACzDR,OAAO;oBAAE,WAAW;oBAAO,QAAQ;gBAAU;gBAC7C,MAAMW,SAAS,MAAM,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACH;gBAC/C,IAAI,CAACG,OAAO,EAAE,EAAE;oBACdX,OAAO;wBACL,WAAW;wBACX,QAAQ;wBACR,MAAMnB;wBACN,OAAO8B,OAAO,KAAK;wBACnB,SAASA,OAAO,OAAO;wBACvB,eAAepC;oBACjB;oBACA,OAAO;wBAAE,GAAGoC,MAAM;wBAAE,WAAW;oBAAK;gBACtC;gBACAX,OAAO;oBACL,WAAW;oBACX,QAAQ;oBACR,MAAMW,OAAO,IAAI;oBACjB,OAAO9B;oBACP,SAAS8B,OAAO,OAAO;oBACvB,eAAepC;gBACjB;gBACA,OAAO;oBAAE,GAAGoC,MAAM;oBAAE,WAAW;gBAAK;YACtC;YAEA,kDAAkD;YAClDX,OAAO;gBAAE,WAAW;gBAAO,QAAQ;YAAU;YAE7C,MAAMY,cAAc,IAAI,CAAC,kBAAkB,CAACvC;YAC5C,MAAMwC,eAAe,IAAI,CAAC,YAAY,CAACT,mBAAmB/B,SAASI,YAAYyB,SAASU,aAAaP,aAAaC,UAAUC,eAAe,CAAC;YAE5I,mEAAmE;YACnE,IAAIF,aAAa;gBACf,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAACG,aAAaK;gBACvCA,aAAa,OAAO,CAAC,IAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAACL,cAAc,KAAK,CAAC,KAAO;YACrF;YAEA,MAAMM,WAAW,MAAMD;YAEvB,4BAA4B;YAC5B,IAAIC,SAAS,EAAE,EAAE;gBACfd,OAAO;oBACL,WAAW;oBACX,QAAQ;oBACR,MAAMc,SAAS,IAAI;oBACnB,OAAOjC;oBACP,SAASiC,SAAS,OAAO;oBACzB,eAAevC;gBACjB;gBACA,IAAI,CAAC,yBAAyB,CAAC;gBAC/B,OAAO;oBAAE,GAAGuC,QAAQ;oBAAE,WAAW;gBAAM;YACzC,OAAO;gBACL,+DAA+D;gBAC/D,IAAIT,aAAa;oBACf,MAAMU,cAAc,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,qBAAqB;oBAClF,IAAIA,YAAY,iBAAiB,KAAK,OAAO;wBAC3C,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAACT;oBAC1C;gBACF;gBAEAN,OAAO;oBACL,WAAW;oBACX,QAAQ;oBACR,MAAMnB;oBACN,OAAOiC,SAAS,KAAK;oBACrB,SAASA,SAAS,OAAO;oBACzB,eAAevC;gBACjB;gBACA,IAAI,CAAC,yBAAyB,CAAC,SAASuC,SAAS,KAAK;gBACtD,MAAMA,SAAS,KAAK;YACtB;QACF,EAAE,OAAOnB,OAAO;YACdK,OAAO;gBACL,WAAW;gBACX,QAAQ;gBACR,MAAMnB;gBACN,OAAOc;gBACP,SAASd;gBACT,eAAeN;YACjB;YACA,MAAMoB;QACR;IACF;IAEA;;GAEC,GACD,MAAc,aACZS,iBAAwF,EACxF/B,OAAiC,EACjCI,UAA2B,EAC3ByB,OAAgB,EAChBU,WAAoC,EACpCP,WAAoB,EACpBC,QAAuD,EACvDC,WAAgC,EACc;QAC9C,gDAAgD;QAChD,MAAMO,WAAW,MAAM,IAAI,CAAC,cAAc,CAACV,mBAAmB/B,SAASI,YAAYyB,SAASU;QAE5F,sCAAsC;QACtC,IAAIE,SAAS,EAAE,EAAE;YACf,MAAM,EAAE,SAASE,eAAe,EAAE,GAAGC,cAAc,GAAGH;YAEtD,4BAA4B;YAC5B,IAAI,IAAI,CAAC,qBAAqB,CAAC,eAAe,EAAE,QAAQ;gBACtD,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,qBAAqB,CAAC,eAAe;YAC1F;YAEA,kBAAkB;YAClB,IAAIT,aAAa;gBACf,MAAMa,qBAAqB,IAAI,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,qBAAqB;gBACzF,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CACrCZ,UACA;oBAAE,GAAGW,YAAY;oBAAE,SAAStD,eAAeA,CAACqD;gBAAiB,GAC7DE,oBACAX,aACA,IAAI,CAAC,qBAAqB,CAAC,IAAI,IAAI,EAAE;YAEzC;QACF;QAEA,OAAOO;IACT;IAEA;;GAEC,GACD,MAAc,eACZV,iBAAwF,EACxF/B,OAAiC,EACjCI,UAA2B,EAC3ByB,OAAgB,EAChBU,WAAyB,EACqB;QAC9C,MAAMO,cAAeP,CAAAA,aAAa,SAAS,KAAK;QAChD,MAAMQ,UAAUR,aAAa,WAAW3C,gBAAgBA;QACxD,MAAMoD,WAAW,CAACC;YAChB,IAAI,OAAOV,aAAa,UAAU,YAAY,OAAOA,YAAY,KAAK,CAACU;YACvE,OAAOV,aAAa,SAAS;QAC/B;QAEA,IAAIW;QAEJ,IAAK,IAAID,UAAU,GAAGA,UAAUH,aAAaG,UAAW;YACtD,0EAA0E;YAC1E,IAAI7C,WAAW,MAAM,CAAC,OAAO,EAAE,MAAM,IAAI+C,aAAa,8BAA8B;YAEpF,MAAMC,gBAA8B;gBAAE,GAAGpD,OAAO;gBAAE,QAAQI,WAAW,MAAM;YAAC;YAC5E8C,eAAe,MAAM,IAAI,CAAC,aAAa,CAAiCnB,mBAAmBqB,eAAevB;YAE1G,mDAAmD;YACnD,IAAIqB,aAAa,EAAE,IAAI,CAACH,QAAQ,QAAQ,CAACG,aAAa,MAAM,KAAKD,YAAYH,cAAc,GAAG;gBAC5F,OAAOI;YACT;YAEA,gCAAgC;YAChC,MAAMG,QAAQL,SAASC;YACvB,MAAM,IAAIK,QAAc,CAACC;gBACvB,MAAMC,QAAQC,WAAWF,SAASF;gBAClC,2DAA2D;gBAC3DjD,WAAW,MAAM,CAAC,gBAAgB,CAChC,SACA;oBACEsD,aAAaF;oBACbD;gBACF,GACA;oBAAE,MAAM;gBAAK;YAEjB;QACF;QAEA,OAAOL;IACT;IAEA;;GAEC,GACO,0BAA0BS,MAA2B,EAAErC,KAAa,EAAQ;QAClF,MAAMsC,gBAA+B;YACnCD;YACA,aAAa,IAAI,CAAC,WAAW;YAC7B,MAAM,IAAI,CAAC,IAAI;YACf,kBAAkB,IAAI,CAAC,gBAAgB;YACvCrC;QACF;QACA,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAACV,KAAOA,GAAGgD;IAC9C;IAEO,UAAUhD,EAAkC,EAAe;QAChE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAACA;QAE7B,MAAML,eAA8B;YAClC,QAAQ;YACR,aAAa,IAAI,CAAC,WAAW;YAC7B,MAAM,IAAI,CAAC,IAAI;YACf,kBAAkB,IAAI,CAAC,gBAAgB;YACvC,OAAOC;QACT;QAEAI,GAAGL;QACH,OAAO,IAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAACK;IAC/C;IAEA,MAAa,QAAQ;QACnB,IAAI,CAAC,WAAW,GAAG;QAEnB,sCAAsC;QACtC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;YACzB,MAAM,IAAI,CAAC,YAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;QAC9D;IACF;IAEO,UAAU;QACf,IAAI,CAAC,mBAAmB,CAAC,KAAK;QAC9B,IAAI,CAAC,gBAAgB,CAAC,KAAK;IAC7B;AACF"}
|