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,56 @@
|
|
|
1
|
+
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
function useSelector(selector, options) {
|
|
6
|
+
const equalsRef = useRef(options?.equals);
|
|
7
|
+
// Кеш для мемоизации результата getSnapshot (предотвращает лишние ререндеры)
|
|
8
|
+
const cachedRef = useRef(undefined);
|
|
9
|
+
const subscribe = useCallback((onStoreChange)=>{
|
|
10
|
+
return selector.subscribe({
|
|
11
|
+
notify: ()=>{
|
|
12
|
+
onStoreChange();
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}, [
|
|
16
|
+
selector
|
|
17
|
+
]);
|
|
18
|
+
const getSnapshot = useCallback(()=>{
|
|
19
|
+
const value = selector.selectSync();
|
|
20
|
+
// Если есть пользовательская функция сравнения — мемоизируем
|
|
21
|
+
const equals = equalsRef.current;
|
|
22
|
+
if (equals && cachedRef.current !== undefined && equals(cachedRef.current, value)) {
|
|
23
|
+
return cachedRef.current;
|
|
24
|
+
}
|
|
25
|
+
cachedRef.current = value;
|
|
26
|
+
return value;
|
|
27
|
+
}, [
|
|
28
|
+
selector
|
|
29
|
+
]);
|
|
30
|
+
const value = useSyncExternalStore(subscribe, getSnapshot);
|
|
31
|
+
// Подписка на статус готовности storage (используется только при withLoading)
|
|
32
|
+
const subscribeToStatus = useCallback((onStoreChange)=>{
|
|
33
|
+
return selector.onSourceStatusChange(()=>{
|
|
34
|
+
onStoreChange();
|
|
35
|
+
});
|
|
36
|
+
}, [
|
|
37
|
+
selector
|
|
38
|
+
]);
|
|
39
|
+
const getStatusSnapshot = useCallback(()=>{
|
|
40
|
+
return !selector.isSourceReady();
|
|
41
|
+
}, [
|
|
42
|
+
selector
|
|
43
|
+
]);
|
|
44
|
+
const isLoading = useSyncExternalStore(subscribeToStatus, getStatusSnapshot);
|
|
45
|
+
if (options?.withLoading) {
|
|
46
|
+
return {
|
|
47
|
+
data: value,
|
|
48
|
+
isLoading
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { useSelector };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=useSelector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react/hooks/useSelector.js","sources":["../../../src/react/hooks/useSelector.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport type { SelectorAPI } from '../../core'\n\ninterface UseSelectorOptions<T> {\n /** Функция сравнения для предотвращения лишних ререндеров */\n equals?: (a: T, b: T) => boolean\n /** Включать ли статус загрузки в возвращаемый результат */\n withLoading?: boolean\n}\n\n/**\n * Хук для использования селекторов в компонентах React.\n * Использует useSyncExternalStore для корректной работы в Concurrent Mode.\n * Подписывается напрямую через selector.subscribe() — без глобального реестра.\n */\nexport function useSelector<T>(selector: SelectorAPI<T>): T\nexport function useSelector<T>(selector: SelectorAPI<T>, options: UseSelectorOptions<T> & { withLoading: true }): { data: T; isLoading: boolean }\nexport function useSelector<T>(selector: SelectorAPI<T>, options?: UseSelectorOptions<T>): { data: T; isLoading: boolean } | T {\n const equalsRef = useRef(options?.equals)\n\n // Кеш для мемоизации результата getSnapshot (предотвращает лишние ререндеры)\n const cachedRef = useRef<T | undefined>(undefined)\n\n const subscribe = useCallback(\n (onStoreChange: VoidFunction) => {\n return selector.subscribe({\n notify: () => {\n onStoreChange()\n },\n })\n },\n [selector],\n )\n\n const getSnapshot = useCallback((): T => {\n const value = selector.selectSync()\n\n // Если есть пользовательская функция сравнения — мемоизируем\n const equals = equalsRef.current\n if (equals && cachedRef.current !== undefined && equals(cachedRef.current, value)) {\n return cachedRef.current\n }\n\n cachedRef.current = value\n return value\n }, [selector])\n\n const value = useSyncExternalStore(subscribe, getSnapshot)\n\n // Подписка на статус готовности storage (используется только при withLoading)\n const subscribeToStatus = useCallback(\n (onStoreChange: VoidFunction) => {\n return selector.onSourceStatusChange(() => {\n onStoreChange()\n })\n },\n [selector],\n )\n\n const getStatusSnapshot = useCallback((): boolean => {\n return !selector.isSourceReady()\n }, [selector])\n\n const isLoading = useSyncExternalStore(subscribeToStatus, getStatusSnapshot)\n\n if (options?.withLoading) {\n return { data: value, isLoading }\n }\n\n return value\n}\n"],"names":["useCallback","useRef","useSyncExternalStore","useSelector","selector","options","equalsRef","cachedRef","undefined","subscribe","onStoreChange","getSnapshot","value","equals","subscribeToStatus","getStatusSnapshot","isLoading"],"mappings":";;;AAAiE;AAkB1D,SAASG,WAAWA,CAAIC,QAAwB,EAAEC,OAA+B;IACtF,MAAMC,YAAYL,MAAMA,CAACI,SAAS;IAElC,6EAA6E;IAC7E,MAAME,YAAYN,MAAMA,CAAgBO;IAExC,MAAMC,YAAYT,WAAWA,CAC3B,CAACU;QACC,OAAON,SAAS,SAAS,CAAC;YACxB,QAAQ;gBACNM;YACF;QACF;IACF,GACA;QAACN;KAAS;IAGZ,MAAMO,cAAcX,WAAWA,CAAC;QAC9B,MAAMY,QAAQR,SAAS,UAAU;QAEjC,6DAA6D;QAC7D,MAAMS,SAASP,UAAU,OAAO;QAChC,IAAIO,UAAUN,UAAU,OAAO,KAAKC,aAAaK,OAAON,UAAU,OAAO,EAAEK,QAAQ;YACjF,OAAOL,UAAU,OAAO;QAC1B;QAEAA,UAAU,OAAO,GAAGK;QACpB,OAAOA;IACT,GAAG;QAACR;KAAS;IAEb,MAAMQ,QAAQV,oBAAoBA,CAACO,WAAWE;IAE9C,8EAA8E;IAC9E,MAAMG,oBAAoBd,WAAWA,CACnC,CAACU;QACC,OAAON,SAAS,oBAAoB,CAAC;YACnCM;QACF;IACF,GACA;QAACN;KAAS;IAGZ,MAAMW,oBAAoBf,WAAWA,CAAC;QACpC,OAAO,CAACI,SAAS,aAAa;IAChC,GAAG;QAACA;KAAS;IAEb,MAAMY,YAAYd,oBAAoBA,CAACY,mBAAmBC;IAE1D,IAAIV,SAAS,aAAa;QACxB,OAAO;YAAE,MAAMO;YAAOI;QAAU;IAClC;IAEA,OAAOJ;AACT"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { IStorageBase, StorageInitStatus } from '../../core';
|
|
2
|
+
export interface UseStorageOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Автоматически инициализировать при монтировании (по умолчанию true)
|
|
5
|
+
*/
|
|
6
|
+
autoInitialize?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export type UseStorageReturn<S> = {
|
|
9
|
+
storage: S;
|
|
10
|
+
status: StorageInitStatus;
|
|
11
|
+
initialize: () => Promise<void>;
|
|
12
|
+
isReady: true;
|
|
13
|
+
isLoading: false;
|
|
14
|
+
hasError: false;
|
|
15
|
+
} | {
|
|
16
|
+
storage: S;
|
|
17
|
+
status: StorageInitStatus;
|
|
18
|
+
initialize: () => Promise<void>;
|
|
19
|
+
isReady: false;
|
|
20
|
+
isLoading: boolean;
|
|
21
|
+
hasError: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Хук для управления lifecycle внешнего хранилища.
|
|
25
|
+
*
|
|
26
|
+
* В отличие от useCreateStorage, не создаёт и не уничтожает хранилище —
|
|
27
|
+
* только инициализирует и отслеживает статус.
|
|
28
|
+
*
|
|
29
|
+
* Предназначен для хранилищ, созданных вне компонентов (на уровне модуля):
|
|
30
|
+
* ```ts
|
|
31
|
+
* // stores.ts
|
|
32
|
+
* export const todoStorage = new IndexedDBStorage({ name: 'todos', ... })
|
|
33
|
+
*
|
|
34
|
+
* // Component.tsx
|
|
35
|
+
* const { isReady } = useStorage(todoStorage)
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function useStorage<S extends IStorageBase<any>>(storage: S, options?: UseStorageOptions): UseStorageReturn<S>;
|
|
39
|
+
//# sourceMappingURL=useStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorage.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useStorage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAiB,MAAM,YAAY,CAAA;AAE3E,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IACE,OAAO,EAAE,CAAC,CAAA;IACV,MAAM,EAAE,iBAAiB,CAAA;IACzB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/B,OAAO,EAAE,IAAI,CAAA;IACb,SAAS,EAAE,KAAK,CAAA;IAChB,QAAQ,EAAE,KAAK,CAAA;CAChB,GACD;IACE,OAAO,EAAE,CAAC,CAAA;IACV,MAAM,EAAE,iBAAiB,CAAA;IACzB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/B,OAAO,EAAE,KAAK,CAAA;IACd,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAEL;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,YAAY,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAAC,CAAC,CAAC,CAgDxH"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { StorageStatus } from "../../core/index.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Хук для управления lifecycle внешнего хранилища.
|
|
10
|
+
*
|
|
11
|
+
* В отличие от useCreateStorage, не создаёт и не уничтожает хранилище —
|
|
12
|
+
* только инициализирует и отслеживает статус.
|
|
13
|
+
*
|
|
14
|
+
* Предназначен для хранилищ, созданных вне компонентов (на уровне модуля):
|
|
15
|
+
* ```ts
|
|
16
|
+
* // stores.ts
|
|
17
|
+
* export const todoStorage = new IndexedDBStorage({ name: 'todos', ... })
|
|
18
|
+
*
|
|
19
|
+
* // Component.tsx
|
|
20
|
+
* const { isReady } = useStorage(todoStorage)
|
|
21
|
+
* ```
|
|
22
|
+
*/ function useStorage(storage, options = {}) {
|
|
23
|
+
const { autoInitialize = true } = options;
|
|
24
|
+
const [status, setStatus] = useState({
|
|
25
|
+
status: StorageStatus.IDLE
|
|
26
|
+
});
|
|
27
|
+
const initialize = useCallback(async ()=>{
|
|
28
|
+
try {
|
|
29
|
+
await storage.initialize();
|
|
30
|
+
} catch {
|
|
31
|
+
// Ошибка будет отражена через onStatusChange
|
|
32
|
+
}
|
|
33
|
+
}, [
|
|
34
|
+
storage
|
|
35
|
+
]);
|
|
36
|
+
// Подписка на изменения статуса
|
|
37
|
+
useEffect(()=>{
|
|
38
|
+
return storage.onStatusChange(setStatus);
|
|
39
|
+
}, [
|
|
40
|
+
storage
|
|
41
|
+
]);
|
|
42
|
+
// Автоинициализация
|
|
43
|
+
useEffect(()=>{
|
|
44
|
+
if (autoInitialize && status.status === StorageStatus.IDLE) {
|
|
45
|
+
initialize();
|
|
46
|
+
}
|
|
47
|
+
}, [
|
|
48
|
+
autoInitialize,
|
|
49
|
+
storage,
|
|
50
|
+
status.status,
|
|
51
|
+
initialize
|
|
52
|
+
]);
|
|
53
|
+
const isReady = status.status === StorageStatus.READY;
|
|
54
|
+
const isLoading = status.status === StorageStatus.LOADING;
|
|
55
|
+
const hasError = status.status === StorageStatus.ERROR;
|
|
56
|
+
if (isReady) {
|
|
57
|
+
return {
|
|
58
|
+
storage,
|
|
59
|
+
status,
|
|
60
|
+
initialize,
|
|
61
|
+
isReady: true,
|
|
62
|
+
isLoading: false,
|
|
63
|
+
hasError: false
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
storage,
|
|
68
|
+
status,
|
|
69
|
+
initialize,
|
|
70
|
+
isReady: false,
|
|
71
|
+
isLoading,
|
|
72
|
+
hasError
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { useStorage };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=useStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react/hooks/useStorage.js","sources":["../../../src/react/hooks/useStorage.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react'\n\nimport { IStorageBase, StorageInitStatus, StorageStatus } from '../../core'\n\nexport interface UseStorageOptions {\n /**\n * Автоматически инициализировать при монтировании (по умолчанию true)\n */\n autoInitialize?: boolean\n}\n\nexport type UseStorageReturn<S> =\n | {\n storage: S\n status: StorageInitStatus\n initialize: () => Promise<void>\n isReady: true\n isLoading: false\n hasError: false\n }\n | {\n storage: S\n status: StorageInitStatus\n initialize: () => Promise<void>\n isReady: false\n isLoading: boolean\n hasError: boolean\n }\n\n/**\n * Хук для управления lifecycle внешнего хранилища.\n *\n * В отличие от useCreateStorage, не создаёт и не уничтожает хранилище —\n * только инициализирует и отслеживает статус.\n *\n * Предназначен для хранилищ, созданных вне компонентов (на уровне модуля):\n * ```ts\n * // stores.ts\n * export const todoStorage = new IndexedDBStorage({ name: 'todos', ... })\n *\n * // Component.tsx\n * const { isReady } = useStorage(todoStorage)\n * ```\n */\nexport function useStorage<S extends IStorageBase<any>>(storage: S, options: UseStorageOptions = {}): UseStorageReturn<S> {\n const { autoInitialize = true } = options\n\n const [status, setStatus] = useState<StorageInitStatus>({ status: StorageStatus.IDLE })\n\n const initialize = useCallback(async () => {\n try {\n await storage.initialize()\n } catch {\n // Ошибка будет отражена через onStatusChange\n }\n }, [storage])\n\n // Подписка на изменения статуса\n useEffect(() => {\n return storage.onStatusChange(setStatus)\n }, [storage])\n\n // Автоинициализация\n useEffect(() => {\n if (autoInitialize && status.status === StorageStatus.IDLE) {\n initialize()\n }\n }, [autoInitialize, storage, status.status, initialize])\n\n const isReady = status.status === StorageStatus.READY\n const isLoading = status.status === StorageStatus.LOADING\n const hasError = status.status === StorageStatus.ERROR\n\n if (isReady) {\n return {\n storage,\n status,\n initialize,\n isReady: true as const,\n isLoading: false as const,\n hasError: false as const,\n }\n }\n\n return {\n storage,\n status,\n initialize,\n isReady: false as const,\n isLoading,\n hasError,\n }\n}\n"],"names":["useCallback","useEffect","useState","StorageStatus","useStorage","storage","options","autoInitialize","status","setStatus","initialize","isReady","isLoading","hasError"],"mappings":";;;;;AAAwD;AAEmB;AA2B3E;;;;;;;;;;;;;;CAcC,GACM,SAASI,UAAUA,CAA8BC,OAAU,EAAEC,UAA6B,CAAC,CAAC;IACjG,MAAM,EAAEC,iBAAiB,IAAI,EAAE,GAAGD;IAElC,MAAM,CAACE,QAAQC,UAAU,GAAGP,QAAQA,CAAoB;QAAE,QAAQC,kBAAkB;IAAC;IAErF,MAAMO,aAAaV,WAAWA,CAAC;QAC7B,IAAI;YACF,MAAMK,QAAQ,UAAU;QAC1B,EAAE,OAAM;QACN,6CAA6C;QAC/C;IACF,GAAG;QAACA;KAAQ;IAEZ,gCAAgC;IAChCJ,SAASA,CAAC;QACR,OAAOI,QAAQ,cAAc,CAACI;IAChC,GAAG;QAACJ;KAAQ;IAEZ,oBAAoB;IACpBJ,SAASA,CAAC;QACR,IAAIM,kBAAkBC,OAAO,MAAM,KAAKL,kBAAkB,EAAE;YAC1DO;QACF;IACF,GAAG;QAACH;QAAgBF;QAASG,OAAO,MAAM;QAAEE;KAAW;IAEvD,MAAMC,UAAUH,OAAO,MAAM,KAAKL,mBAAmB;IACrD,MAAMS,YAAYJ,OAAO,MAAM,KAAKL,qBAAqB;IACzD,MAAMU,WAAWL,OAAO,MAAM,KAAKL,mBAAmB;IAEtD,IAAIQ,SAAS;QACX,OAAO;YACLN;YACAG;YACAE;YACA,SAAS;YACT,WAAW;YACX,UAAU;QACZ;IACF;IAEA,OAAO;QACLL;QACAG;QACAE;QACA,SAAS;QACTE;QACAC;IACF;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IStorageBase } from '../../core';
|
|
2
|
+
/**
|
|
3
|
+
* Хук для подписки на изменения в хранилище.
|
|
4
|
+
* Использует useSyncExternalStore для корректной работы в Concurrent Mode.
|
|
5
|
+
*
|
|
6
|
+
* Принимает IStorageBase (общий интерфейс для sync и async хранилищ),
|
|
7
|
+
* так как подписки одинаковы для всех типов.
|
|
8
|
+
*
|
|
9
|
+
* @template S - Тип состояния хранилища
|
|
10
|
+
* @template R - Тип возвращаемого значения
|
|
11
|
+
* @param storage - Экземпляр хранилища или null (до инициализации)
|
|
12
|
+
* @param selector - Функция-селектор для выбора данных
|
|
13
|
+
* @returns Значение из хранилища
|
|
14
|
+
*/
|
|
15
|
+
export declare const useStorageSubscribe: <S extends Record<string, any>, R = any>(storage: IStorageBase<S> | null, selector: (state: S) => R) => R | undefined;
|
|
16
|
+
//# sourceMappingURL=useStorageSubscribe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorageSubscribe.d.ts","sourceRoot":"","sources":["../../../src/react/hooks/useStorageSubscribe.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAEzC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,SAAS,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,KAAG,CAAC,GAAG,SAmC5I,CAAA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useCallback, useRef, useSyncExternalStore } from "react";
|
|
2
|
+
import { logError } from "../../_utils/error-handling.util.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Хук для подписки на изменения в хранилище.
|
|
10
|
+
* Использует useSyncExternalStore для корректной работы в Concurrent Mode.
|
|
11
|
+
*
|
|
12
|
+
* Принимает IStorageBase (общий интерфейс для sync и async хранилищ),
|
|
13
|
+
* так как подписки одинаковы для всех типов.
|
|
14
|
+
*
|
|
15
|
+
* @template S - Тип состояния хранилища
|
|
16
|
+
* @template R - Тип возвращаемого значения
|
|
17
|
+
* @param storage - Экземпляр хранилища или null (до инициализации)
|
|
18
|
+
* @param selector - Функция-селектор для выбора данных
|
|
19
|
+
* @returns Значение из хранилища
|
|
20
|
+
*/ const useStorageSubscribe = (storage, selector)=>{
|
|
21
|
+
// Храним selector в ref, чтобы не пересоздавать subscribe/getSnapshot при изменении ссылки
|
|
22
|
+
const selectorRef = useRef(selector);
|
|
23
|
+
selectorRef.current = selector;
|
|
24
|
+
const subscribe = useCallback((onStoreChange)=>{
|
|
25
|
+
if (!storage) return ()=>{};
|
|
26
|
+
// Подписка на все изменения storage + на смену статуса (для момента инициализации)
|
|
27
|
+
const unsubData = storage.subscribeToAll(()=>onStoreChange());
|
|
28
|
+
const unsubStatus = storage.onStatusChange(()=>onStoreChange());
|
|
29
|
+
return ()=>{
|
|
30
|
+
unsubData();
|
|
31
|
+
unsubStatus();
|
|
32
|
+
};
|
|
33
|
+
}, [
|
|
34
|
+
storage
|
|
35
|
+
]);
|
|
36
|
+
const getSnapshot = useCallback(()=>{
|
|
37
|
+
if (!storage) return undefined;
|
|
38
|
+
try {
|
|
39
|
+
const state = storage.getStateSync();
|
|
40
|
+
return selectorRef.current(state);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
43
|
+
logError('useStorageSubscribe: selector error', error, null, 'warn');
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}, [
|
|
48
|
+
storage
|
|
49
|
+
]);
|
|
50
|
+
return useSyncExternalStore(subscribe, getSnapshot);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export { useStorageSubscribe };
|
|
54
|
+
|
|
55
|
+
//# sourceMappingURL=useStorageSubscribe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react/hooks/useStorageSubscribe.js","sources":["../../../src/react/hooks/useStorageSubscribe.ts"],"sourcesContent":["import { useCallback, useRef, useSyncExternalStore } from 'react'\n\nimport { logError } from '../../_utils/error-handling.util'\nimport { IStorageBase } from '../../core'\n\n/**\n * Хук для подписки на изменения в хранилище.\n * Использует useSyncExternalStore для корректной работы в Concurrent Mode.\n *\n * Принимает IStorageBase (общий интерфейс для sync и async хранилищ),\n * так как подписки одинаковы для всех типов.\n *\n * @template S - Тип состояния хранилища\n * @template R - Тип возвращаемого значения\n * @param storage - Экземпляр хранилища или null (до инициализации)\n * @param selector - Функция-селектор для выбора данных\n * @returns Значение из хранилища\n */\nexport const useStorageSubscribe = <S extends Record<string, any>, R = any>(storage: IStorageBase<S> | null, selector: (state: S) => R): R | undefined => {\n // Храним selector в ref, чтобы не пересоздавать subscribe/getSnapshot при изменении ссылки\n const selectorRef = useRef(selector)\n selectorRef.current = selector\n\n const subscribe = useCallback(\n (onStoreChange: VoidFunction) => {\n if (!storage) return () => {}\n\n // Подписка на все изменения storage + на смену статуса (для момента инициализации)\n const unsubData = storage.subscribeToAll(() => onStoreChange())\n const unsubStatus = storage.onStatusChange(() => onStoreChange())\n return () => {\n unsubData()\n unsubStatus()\n }\n },\n [storage],\n )\n\n const getSnapshot = useCallback((): R | undefined => {\n if (!storage) return undefined\n\n try {\n const state = storage.getStateSync()\n return selectorRef.current(state)\n } catch (error) {\n if (process.env.NODE_ENV !== 'production') {\n logError('useStorageSubscribe: selector error', error, null, 'warn')\n }\n return undefined\n }\n }, [storage])\n\n return useSyncExternalStore(subscribe, getSnapshot)\n}\n"],"names":["useCallback","useRef","useSyncExternalStore","logError","useStorageSubscribe","storage","selector","selectorRef","subscribe","onStoreChange","unsubData","unsubStatus","getSnapshot","undefined","state","error","process"],"mappings":";;;;;AAAiE;AAEN;AAG3D;;;;;;;;;;;;CAYC,GACM,MAAMI,mBAAmBA,GAAG,CAAyCC,SAAiCC;IAC3G,2FAA2F;IAC3F,MAAMC,cAAcN,MAAMA,CAACK;IAC3BC,YAAY,OAAO,GAAGD;IAEtB,MAAME,YAAYR,WAAWA,CAC3B,CAACS;QACC,IAAI,CAACJ,SAAS,OAAO,KAAO;QAE5B,mFAAmF;QACnF,MAAMK,YAAYL,QAAQ,cAAc,CAAC,IAAMI;QAC/C,MAAME,cAAcN,QAAQ,cAAc,CAAC,IAAMI;QACjD,OAAO;YACLC;YACAC;QACF;IACF,GACA;QAACN;KAAQ;IAGX,MAAMO,cAAcZ,WAAWA,CAAC;QAC9B,IAAI,CAACK,SAAS,OAAOQ;QAErB,IAAI;YACF,MAAMC,QAAQT,QAAQ,YAAY;YAClC,OAAOE,YAAY,OAAO,CAACO;QAC7B,EAAE,OAAOC,OAAO;YACd,IAAIC,QAAQ,GAAG,CAAC,QAAQ,KAAK,cAAc;gBACzCb,QAAQA,CAAC,uCAAuCY,OAAO,MAAM;YAC/D;YACA,OAAOF;QACT;IACF,GAAG;QAACR;KAAQ;IAEZ,OAAOH,oBAAoBA,CAACM,WAAWI;AACzC,EAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react/index.js","sources":["../../src/react/index.ts"],"sourcesContent":["export * from './hooks'\nexport * from './utils'\n"],"names":[],"mappings":";;AAAuB;AACA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import { IStorage } from '../../core';
|
|
3
|
+
import { AnySynapseStore } from '../../utils';
|
|
4
|
+
interface ReactAwaitSynapseOptions {
|
|
5
|
+
loadingComponent?: ReactNode;
|
|
6
|
+
errorComponent?: (error: Error) => ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* React-обертка для фреймворк-независимой утилиты ожидания Synapse
|
|
10
|
+
* Добавляет React-специфичные методы поверх createSynapseAwaiter
|
|
11
|
+
*/
|
|
12
|
+
export declare function awaitSynapse<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors = any, TActions = any>(synapseStorePromise: Promise<AnySynapseStore<TStore, TStorage, TSelectors, TActions>> | AnySynapseStore<TStore, TStorage, TSelectors, TActions>, options?: ReactAwaitSynapseOptions): {
|
|
13
|
+
withSynapseReady: <ComponentProps>(Component: ComponentType<ComponentProps>) => {
|
|
14
|
+
(props: ComponentProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
displayName: string;
|
|
16
|
+
};
|
|
17
|
+
useSynapseReady: () => {
|
|
18
|
+
isReady: boolean;
|
|
19
|
+
isError: boolean;
|
|
20
|
+
isPending: boolean;
|
|
21
|
+
store: AnySynapseStore<TStore, TStorage, TSelectors, TActions> | undefined;
|
|
22
|
+
error: Error | null;
|
|
23
|
+
};
|
|
24
|
+
waitForReady: () => Promise<AnySynapseStore<TStore, TStorage, TSelectors, TActions>>;
|
|
25
|
+
isReady: () => boolean;
|
|
26
|
+
getStoreIfReady: () => AnySynapseStore<TStore, TStorage, TSelectors, TActions> | undefined;
|
|
27
|
+
onReady: (cb: Parameters<(callback: (store: AnySynapseStore<TStore, TStorage, TSelectors, TActions>) => void) => VoidFunction>[0]) => VoidFunction;
|
|
28
|
+
onError: (cb: Parameters<(callback: (error: Error) => void) => VoidFunction>[0]) => VoidFunction;
|
|
29
|
+
getStatus: () => "error" | "ready" | "pending";
|
|
30
|
+
getError: () => Error | null;
|
|
31
|
+
destroy: () => void;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=awaitSynapse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"awaitSynapse.d.ts","sourceRoot":"","sources":["../../../src/react/utils/awaitSynapse.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAqB,SAAS,EAAuB,MAAM,OAAO,CAAA;AAExF,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAE,eAAe,EAAwB,MAAM,aAAa,CAAA;AAEnE,UAAU,wBAAwB;IAChC,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,SAAS,CAAA;CAC7C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,GAAG,EAAE,QAAQ,GAAG,GAAG,EAClI,mBAAmB,EAAE,OAAO,CAAC,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,EAC/I,OAAO,CAAC,EAAE,wBAAwB;uBAuDR,cAAc,aAAa,aAAa,CAAC,cAAc,CAAC;gBAC/C,cAAc;;;;;;;;;;;;;kBA6BjC,UAAU,sGAAwB,CAAC,CAAC,CAAC;kBACrC,UAAU,oDAAwB,CAAC,CAAC,CAAC;;;;EAKtD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { createSynapseAwaiter } from "../../utils/index.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* React-обертка для фреймворк-независимой утилиты ожидания Synapse
|
|
10
|
+
* Добавляет React-специфичные методы поверх createSynapseAwaiter
|
|
11
|
+
*/ function awaitSynapse(synapseStorePromise, options) {
|
|
12
|
+
const { loadingComponent = /*#__PURE__*/ React.createElement("div", null, "Инициализация..."), errorComponent = (error)=>/*#__PURE__*/ React.createElement("div", null, "Ошибка инициализации: ", error.message) } = options || {};
|
|
13
|
+
const awaiter = createSynapseAwaiter(synapseStorePromise);
|
|
14
|
+
/**
|
|
15
|
+
* Хук для получения текущего состояния готовности
|
|
16
|
+
*/ function useSynapseReady() {
|
|
17
|
+
const [status, setStatus] = useState(()=>awaiter.getStatus());
|
|
18
|
+
const [store, setStore] = useState(()=>awaiter.getStoreIfReady());
|
|
19
|
+
const [error, setError] = useState(()=>awaiter.getError());
|
|
20
|
+
useEffect(()=>{
|
|
21
|
+
// Проверяем текущее состояние при монтировании
|
|
22
|
+
const currentStatus = awaiter.getStatus();
|
|
23
|
+
const currentStore = awaiter.getStoreIfReady();
|
|
24
|
+
const currentError = awaiter.getError();
|
|
25
|
+
setStatus(currentStatus);
|
|
26
|
+
setStore(currentStore);
|
|
27
|
+
setError(currentError);
|
|
28
|
+
// Подписываемся на изменения
|
|
29
|
+
const unsubscribeReady = awaiter.onReady((readyStore)=>{
|
|
30
|
+
setStatus('ready');
|
|
31
|
+
setStore(readyStore);
|
|
32
|
+
setError(null);
|
|
33
|
+
});
|
|
34
|
+
const unsubscribeError = awaiter.onError((err)=>{
|
|
35
|
+
setStatus('error');
|
|
36
|
+
setStore(undefined);
|
|
37
|
+
setError(err);
|
|
38
|
+
});
|
|
39
|
+
return ()=>{
|
|
40
|
+
unsubscribeReady();
|
|
41
|
+
unsubscribeError();
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
return {
|
|
45
|
+
isReady: status === 'ready',
|
|
46
|
+
isError: status === 'error',
|
|
47
|
+
isPending: status === 'pending',
|
|
48
|
+
store,
|
|
49
|
+
error
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Обертка, которая ждет готовности Synapse
|
|
54
|
+
*/ function withSynapseReady(Component) {
|
|
55
|
+
function WrappedComponent(props) {
|
|
56
|
+
const { isReady, isError, error } = useSynapseReady();
|
|
57
|
+
// Показываем ошибку
|
|
58
|
+
if (isError && error) return /*#__PURE__*/ React.createElement(React.Fragment, null, errorComponent(error));
|
|
59
|
+
// Показываем загрузку
|
|
60
|
+
if (!isReady) return /*#__PURE__*/ React.createElement(React.Fragment, null, loadingComponent);
|
|
61
|
+
// Рендерим компонент когда все готово
|
|
62
|
+
return /*#__PURE__*/ React.createElement(Component, props);
|
|
63
|
+
}
|
|
64
|
+
// Устанавливаем отображаемое имя для отладки
|
|
65
|
+
const componentName = Component.displayName || Component.name || 'Component';
|
|
66
|
+
WrappedComponent.displayName = `AwaitSynapse(${componentName})`;
|
|
67
|
+
return WrappedComponent;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
// React методы
|
|
71
|
+
withSynapseReady,
|
|
72
|
+
useSynapseReady,
|
|
73
|
+
// Проксируем все методы из awaiter (обёртки сохраняют контекст при деструктуризации)
|
|
74
|
+
waitForReady: ()=>awaiter.waitForReady(),
|
|
75
|
+
isReady: ()=>awaiter.isReady(),
|
|
76
|
+
getStoreIfReady: ()=>awaiter.getStoreIfReady(),
|
|
77
|
+
onReady: (cb)=>awaiter.onReady(cb),
|
|
78
|
+
onError: (cb)=>awaiter.onError(cb),
|
|
79
|
+
getStatus: ()=>awaiter.getStatus(),
|
|
80
|
+
getError: ()=>awaiter.getError(),
|
|
81
|
+
destroy: ()=>awaiter.destroy()
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { awaitSynapse };
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=awaitSynapse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react/utils/awaitSynapse.js","sources":["../../../src/react/utils/awaitSynapse.tsx"],"sourcesContent":["import { ComponentType, PropsWithChildren, ReactNode, useEffect, useState } from 'react'\n\nimport { IStorage } from '../../core'\nimport { AnySynapseStore, createSynapseAwaiter } from '../../utils'\n\ninterface ReactAwaitSynapseOptions {\n loadingComponent?: ReactNode\n errorComponent?: (error: Error) => ReactNode\n}\n\n/**\n * React-обертка для фреймворк-независимой утилиты ожидания Synapse\n * Добавляет React-специфичные методы поверх createSynapseAwaiter\n */\nexport function awaitSynapse<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors = any, TActions = any>(\n synapseStorePromise: Promise<AnySynapseStore<TStore, TStorage, TSelectors, TActions>> | AnySynapseStore<TStore, TStorage, TSelectors, TActions>,\n options?: ReactAwaitSynapseOptions,\n) {\n const { loadingComponent = <div>Инициализация...</div>, errorComponent = (error: Error) => <div>Ошибка инициализации: {error.message}</div> } = options || {}\n\n const awaiter = createSynapseAwaiter(synapseStorePromise)\n\n /**\n * Хук для получения текущего состояния готовности\n */\n function useSynapseReady() {\n const [status, setStatus] = useState<'pending' | 'ready' | 'error'>(() => awaiter.getStatus())\n const [store, setStore] = useState<AnySynapseStore<TStore, TStorage, TSelectors, TActions> | undefined>(() => awaiter.getStoreIfReady())\n const [error, setError] = useState<Error | null>(() => awaiter.getError())\n\n useEffect(() => {\n // Проверяем текущее состояние при монтировании\n const currentStatus = awaiter.getStatus()\n const currentStore = awaiter.getStoreIfReady()\n const currentError = awaiter.getError()\n\n setStatus(currentStatus)\n setStore(currentStore)\n setError(currentError)\n\n // Подписываемся на изменения\n const unsubscribeReady = awaiter.onReady((readyStore) => {\n setStatus('ready')\n setStore(readyStore)\n setError(null)\n })\n\n const unsubscribeError = awaiter.onError((err) => {\n setStatus('error')\n setStore(undefined)\n setError(err)\n })\n\n return () => {\n unsubscribeReady()\n unsubscribeError()\n }\n }, [])\n\n return {\n isReady: status === 'ready',\n isError: status === 'error',\n isPending: status === 'pending',\n store,\n error,\n }\n }\n\n /**\n * Обертка, которая ждет готовности Synapse\n */\n function withSynapseReady<ComponentProps>(Component: ComponentType<ComponentProps>) {\n function WrappedComponent(props: ComponentProps) {\n const { isReady, isError, error } = useSynapseReady()\n\n // Показываем ошибку\n if (isError && error) return <>{errorComponent(error)}</>\n\n // Показываем загрузку\n if (!isReady) return <>{loadingComponent}</>\n\n // Рендерим компонент когда все готово\n return <Component {...(props as PropsWithChildren<ComponentProps>)} />\n }\n\n // Устанавливаем отображаемое имя для отладки\n const componentName = Component.displayName || Component.name || 'Component'\n WrappedComponent.displayName = `AwaitSynapse(${componentName})`\n\n return WrappedComponent\n }\n\n return {\n // React методы\n withSynapseReady,\n useSynapseReady,\n\n // Проксируем все методы из awaiter (обёртки сохраняют контекст при деструктуризации)\n waitForReady: () => awaiter.waitForReady(),\n isReady: () => awaiter.isReady(),\n getStoreIfReady: () => awaiter.getStoreIfReady(),\n onReady: (cb: Parameters<typeof awaiter.onReady>[0]) => awaiter.onReady(cb),\n onError: (cb: Parameters<typeof awaiter.onError>[0]) => awaiter.onError(cb),\n getStatus: () => awaiter.getStatus(),\n getError: () => awaiter.getError(),\n destroy: () => awaiter.destroy(),\n }\n}\n"],"names":["useEffect","useState","createSynapseAwaiter","awaitSynapse","synapseStorePromise","options","loadingComponent","errorComponent","error","awaiter","useSynapseReady","status","setStatus","store","setStore","setError","currentStatus","currentStore","currentError","unsubscribeReady","readyStore","unsubscribeError","err","undefined","withSynapseReady","Component","WrappedComponent","props","isReady","isError","componentName","cb"],"mappings":";;;;;AAAwF;AAGrB;AAOnE;;;CAGC,GACM,SAASG,YAAYA,CAC1BC,mBAA+I,EAC/IC,OAAkC;IAElC,MAAM,EAAEC,iCAAmB,oBAAC,aAAI,mBAAsB,EAAEC,iBAAiB,CAACC,sBAAiB,oBAAC,aAAI,0BAAuBA,MAAM,OAAO,CAAO,EAAE,GAAGH,WAAW,CAAC;IAE5J,MAAMI,UAAUP,oBAAoBA,CAACE;IAErC;;GAEC,GACD,SAASM;QACP,MAAM,CAACC,QAAQC,UAAU,GAAGX,QAAQA,CAAgC,IAAMQ,QAAQ,SAAS;QAC3F,MAAM,CAACI,OAAOC,SAAS,GAAGb,QAAQA,CAAsE,IAAMQ,QAAQ,eAAe;QACrI,MAAM,CAACD,OAAOO,SAAS,GAAGd,QAAQA,CAAe,IAAMQ,QAAQ,QAAQ;QAEvET,SAASA,CAAC;YACR,+CAA+C;YAC/C,MAAMgB,gBAAgBP,QAAQ,SAAS;YACvC,MAAMQ,eAAeR,QAAQ,eAAe;YAC5C,MAAMS,eAAeT,QAAQ,QAAQ;YAErCG,UAAUI;YACVF,SAASG;YACTF,SAASG;YAET,6BAA6B;YAC7B,MAAMC,mBAAmBV,QAAQ,OAAO,CAAC,CAACW;gBACxCR,UAAU;gBACVE,SAASM;gBACTL,SAAS;YACX;YAEA,MAAMM,mBAAmBZ,QAAQ,OAAO,CAAC,CAACa;gBACxCV,UAAU;gBACVE,SAASS;gBACTR,SAASO;YACX;YAEA,OAAO;gBACLH;gBACAE;YACF;QACF,GAAG,EAAE;QAEL,OAAO;YACL,SAASV,WAAW;YACpB,SAASA,WAAW;YACpB,WAAWA,WAAW;YACtBE;YACAL;QACF;IACF;IAEA;;GAEC,GACD,SAASgB,iBAAiCC,SAAwC;QAChF,SAASC,iBAAiBC,KAAqB;YAC7C,MAAM,EAAEC,OAAO,EAAEC,OAAO,EAAErB,KAAK,EAAE,GAAGE;YAEpC,oBAAoB;YACpB,IAAImB,WAAWrB,OAAO,qBAAO,0CAAGD,eAAeC;YAE/C,sBAAsB;YACtB,IAAI,CAACoB,SAAS,qBAAO,0CAAGtB;YAExB,sCAAsC;YACtC,qBAAO,oBAACmB,WAAeE;QACzB;QAEA,6CAA6C;QAC7C,MAAMG,gBAAgBL,UAAU,WAAW,IAAIA,UAAU,IAAI,IAAI;QACjEC,iBAAiB,WAAW,GAAG,CAAC,aAAa,EAAEI,cAAc,CAAC,CAAC;QAE/D,OAAOJ;IACT;IAEA,OAAO;QACL,eAAe;QACfF;QACAd;QAEA,qFAAqF;QACrF,cAAc,IAAMD,QAAQ,YAAY;QACxC,SAAS,IAAMA,QAAQ,OAAO;QAC9B,iBAAiB,IAAMA,QAAQ,eAAe;QAC9C,SAAS,CAACsB,KAA8CtB,QAAQ,OAAO,CAACsB;QACxE,SAAS,CAACA,KAA8CtB,QAAQ,OAAO,CAACsB;QACxE,WAAW,IAAMtB,QAAQ,SAAS;QAClC,UAAU,IAAMA,QAAQ,QAAQ;QAChC,SAAS,IAAMA,QAAQ,OAAO;IAChC;AACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
import { IStorage } from '../../core';
|
|
4
|
+
import { SynapseStoreBasic, SynapseStoreWithDispatcher, SynapseStoreWithEffects } from '../../utils';
|
|
5
|
+
interface SimplifiedOptions {
|
|
6
|
+
loadingComponent?: React.ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Перегрузки для createSynapseCtx в зависимости от типа хранилища
|
|
10
|
+
*/
|
|
11
|
+
export declare function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions>(synapseStorePromise: Promise<SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>> | SynapseStoreWithEffects<TStore, TStorage, TSelectors, TActions>, options?: SimplifiedOptions): {
|
|
12
|
+
contextSynapse: <SelfComponentProps>(Component: ComponentType<SelfComponentProps>) => ComponentType<SelfComponentProps>;
|
|
13
|
+
useSynapseStorage: () => TStorage;
|
|
14
|
+
useSynapseSelectors: () => TSelectors;
|
|
15
|
+
useSynapseActions: () => TActions;
|
|
16
|
+
useSynapseState$: () => Observable<TStore>;
|
|
17
|
+
cleanupSynapse: () => Promise<void>;
|
|
18
|
+
};
|
|
19
|
+
export declare function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors, TActions>(synapseStorePromise: Promise<SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions>> | SynapseStoreWithDispatcher<TStore, TStorage, TSelectors, TActions>, options?: SimplifiedOptions): {
|
|
20
|
+
contextSynapse: <SelfComponentProps>(Component: ComponentType<SelfComponentProps>) => ComponentType<SelfComponentProps>;
|
|
21
|
+
useSynapseStorage: () => TStorage;
|
|
22
|
+
useSynapseSelectors: () => TSelectors;
|
|
23
|
+
useSynapseActions: () => TActions;
|
|
24
|
+
cleanupSynapse: () => Promise<void>;
|
|
25
|
+
};
|
|
26
|
+
export declare function createSynapseCtx<TStore extends Record<string, any>, TStorage extends IStorage<TStore>, TSelectors>(synapseStorePromise: Promise<SynapseStoreBasic<TStore, TStorage, TSelectors>> | SynapseStoreBasic<TStore, TStorage, TSelectors>, options?: SimplifiedOptions): {
|
|
27
|
+
contextSynapse: <SelfComponentProps>(Component: ComponentType<SelfComponentProps>) => ComponentType<SelfComponentProps>;
|
|
28
|
+
useSynapseStorage: () => TStorage;
|
|
29
|
+
useSynapseSelectors: () => TSelectors;
|
|
30
|
+
cleanupSynapse: () => Promise<void>;
|
|
31
|
+
};
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=createSynapseCtx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSynapseCtx.d.ts","sourceRoot":"","sources":["../../../src/react/utils/createSynapseCtx.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAiF,MAAM,OAAO,CAAA;AACpH,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAAO,EAAmB,iBAAiB,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAKrH,UAAU,iBAAiB;IACzB,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACnC;AAED;;GAEG;AAGH,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,QAAQ,EAC1H,mBAAmB,EAAE,OAAO,CAAC,uBAAuB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,EAC/J,OAAO,CAAC,EAAE,iBAAiB,GAC1B;IACD,cAAc,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,KAAK,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACvH,iBAAiB,EAAE,MAAM,QAAQ,CAAA;IACjC,mBAAmB,EAAE,MAAM,UAAU,CAAA;IACrC,iBAAiB,EAAE,MAAM,QAAQ,CAAA;IACjC,gBAAgB,EAAE,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;IAC1C,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC,CAAA;AAGD,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,QAAQ,EAC1H,mBAAmB,EAAE,OAAO,CAAC,0BAA0B,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,GAAG,0BAA0B,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC,EACrK,OAAO,CAAC,EAAE,iBAAiB,GAC1B;IACD,cAAc,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,KAAK,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACvH,iBAAiB,EAAE,MAAM,QAAQ,CAAA;IACjC,mBAAmB,EAAE,MAAM,UAAU,CAAA;IACrC,iBAAiB,EAAE,MAAM,QAAQ,CAAA;IACjC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC,CAAA;AAGD,wBAAgB,gBAAgB,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,QAAQ,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,EAChH,mBAAmB,EAAE,OAAO,CAAC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,GAAG,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,EAC/H,OAAO,CAAC,EAAE,iBAAiB,GAC1B;IACD,cAAc,EAAE,CAAC,kBAAkB,EAAE,SAAS,EAAE,aAAa,CAAC,kBAAkB,CAAC,KAAK,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACvH,iBAAiB,EAAE,MAAM,QAAQ,CAAA;IACjC,mBAAmB,EAAE,MAAM,UAAU,CAAA;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC,CAAA"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createContext, forwardRef, useContext, useEffect, useState } from "react";
|
|
2
|
+
import { handleCleanupError, handleOperationError } from "../../_utils/error-handling.util.js";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
const ERROR_HOOK_MESSAGE = 'Хук необходимо использовать внутри компонента contextSynapse';
|
|
9
|
+
const ERROR_CONTEXT_INIT = 'Ошибка при инициализации контекста:';
|
|
10
|
+
// Основная реализация
|
|
11
|
+
function createSynapseCtx(synapseStorePromise, options) {
|
|
12
|
+
const { loadingComponent = /*#__PURE__*/ React.createElement("div", null, "Инициализация контекста...") } = options || {};
|
|
13
|
+
// Lazy-инициализация: Promise создаётся при первом обращении и сбрасывается при cleanup
|
|
14
|
+
let storeInitPromise = null;
|
|
15
|
+
const getStoreInitPromise = ()=>{
|
|
16
|
+
if (!storeInitPromise) {
|
|
17
|
+
storeInitPromise = (async ()=>{
|
|
18
|
+
try {
|
|
19
|
+
const store = await (synapseStorePromise instanceof Promise ? synapseStorePromise : Promise.resolve(synapseStorePromise));
|
|
20
|
+
await store.storage.waitForReady();
|
|
21
|
+
return store;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
handleOperationError('createSynapseCtx: Synapse storage initialization error', error);
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
}
|
|
27
|
+
return storeInitPromise;
|
|
28
|
+
};
|
|
29
|
+
const SynapseContext = /*#__PURE__*/ createContext(null);
|
|
30
|
+
const useSynapseStorage = ()=>{
|
|
31
|
+
const context = useContext(SynapseContext);
|
|
32
|
+
if (!context) throw new Error(`useSynapseStorage: ${ERROR_HOOK_MESSAGE}`);
|
|
33
|
+
return context.storage;
|
|
34
|
+
};
|
|
35
|
+
const useSynapseSelectors = ()=>{
|
|
36
|
+
const context = useContext(SynapseContext);
|
|
37
|
+
if (!context) throw new Error(`useSynapseSelectors: ${ERROR_HOOK_MESSAGE}`);
|
|
38
|
+
return context.selectors;
|
|
39
|
+
};
|
|
40
|
+
// Условный хук для actions (только если есть dispatcher)
|
|
41
|
+
const useSynapseActions = ()=>{
|
|
42
|
+
const context = useContext(SynapseContext);
|
|
43
|
+
if (!context) throw new Error(`useSynapseActions: ${ERROR_HOOK_MESSAGE}`);
|
|
44
|
+
if ('actions' in context) {
|
|
45
|
+
return context.actions;
|
|
46
|
+
}
|
|
47
|
+
throw new Error('useSynapseActions: actions недоступны для этого типа хранилища. Убедитесь, что передана функция createDispatcherFn при создании хранилища.');
|
|
48
|
+
};
|
|
49
|
+
// Условный хук для state$ (только если есть effects)
|
|
50
|
+
const useSynapseState$ = ()=>{
|
|
51
|
+
const context = useContext(SynapseContext);
|
|
52
|
+
if (!context) throw new Error(`useSynapseState$: ${ERROR_HOOK_MESSAGE}`);
|
|
53
|
+
if ('state$' in context) {
|
|
54
|
+
return context.state$;
|
|
55
|
+
}
|
|
56
|
+
throw new Error('useSynapseState$: state$ недоступен для этого типа хранилища. Убедитесь, что переданы функции createDispatcherFn и createEffectConfig при создании хранилища.');
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Декоратор для обертывания компонентов в контекст Synapse
|
|
60
|
+
*/ function contextSynapse(Component) {
|
|
61
|
+
const WrappedComponent = /*#__PURE__*/ forwardRef(function WrappedComponent(props, ref) {
|
|
62
|
+
const [synapseStore, setSynapseStore] = useState(null);
|
|
63
|
+
const [isReady, setIsReady] = useState(false);
|
|
64
|
+
const [error, setError] = useState(null);
|
|
65
|
+
useEffect(()=>{
|
|
66
|
+
let mounted = true;
|
|
67
|
+
const initializeContext = async ()=>{
|
|
68
|
+
try {
|
|
69
|
+
const store = await getStoreInitPromise();
|
|
70
|
+
if (mounted) {
|
|
71
|
+
setSynapseStore(store);
|
|
72
|
+
setIsReady(true);
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
if (mounted) {
|
|
76
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
initializeContext();
|
|
81
|
+
return ()=>{
|
|
82
|
+
mounted = false;
|
|
83
|
+
};
|
|
84
|
+
}, []);
|
|
85
|
+
// Показываем ошибку если что-то пошло не так
|
|
86
|
+
if (error) return /*#__PURE__*/ React.createElement("div", null, `${ERROR_CONTEXT_INIT}: ${error.message}`);
|
|
87
|
+
// Показываем загрузку пока все не готово
|
|
88
|
+
if (!isReady || !synapseStore) return /*#__PURE__*/ React.createElement(React.Fragment, null, loadingComponent);
|
|
89
|
+
return /*#__PURE__*/ React.createElement(SynapseContext.Provider, {
|
|
90
|
+
value: synapseStore
|
|
91
|
+
}, /*#__PURE__*/ React.createElement(Component, {
|
|
92
|
+
...props,
|
|
93
|
+
ref: ref
|
|
94
|
+
}));
|
|
95
|
+
});
|
|
96
|
+
// Устанавливаем отображаемое имя для отладки
|
|
97
|
+
const componentName = Component.displayName || Component.name || 'Component';
|
|
98
|
+
WrappedComponent.displayName = `SynapseContext(${componentName})`;
|
|
99
|
+
// Копируем статические свойства оригинального компонента
|
|
100
|
+
const excludedKeys = new Set([
|
|
101
|
+
'$$typeof',
|
|
102
|
+
'render',
|
|
103
|
+
'defaultProps',
|
|
104
|
+
'displayName',
|
|
105
|
+
'propTypes'
|
|
106
|
+
]);
|
|
107
|
+
Object.keys(Component).forEach((key)=>{
|
|
108
|
+
if (!excludedKeys.has(key)) {
|
|
109
|
+
;
|
|
110
|
+
WrappedComponent[key] = Component[key];
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
return WrappedComponent;
|
|
114
|
+
}
|
|
115
|
+
const cleanupSynapse = async ()=>{
|
|
116
|
+
try {
|
|
117
|
+
if (storeInitPromise) {
|
|
118
|
+
const store = await storeInitPromise;
|
|
119
|
+
storeInitPromise = null;
|
|
120
|
+
return store?.destroy() || Promise.resolve();
|
|
121
|
+
}
|
|
122
|
+
} catch (error) {
|
|
123
|
+
storeInitPromise = null;
|
|
124
|
+
handleCleanupError('createSynapseCtx: error during Synapse cleanup', error);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
return {
|
|
128
|
+
contextSynapse,
|
|
129
|
+
useSynapseStorage,
|
|
130
|
+
useSynapseSelectors,
|
|
131
|
+
useSynapseActions,
|
|
132
|
+
useSynapseState$,
|
|
133
|
+
cleanupSynapse
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export { createSynapseCtx };
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=createSynapseCtx.js.map
|