synapse-storage 3.0.2 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.cjs +1 -0
- package/dist/api.d.cts +365 -0
- package/dist/api.d.ts +365 -0
- package/dist/api.js +1 -0
- package/dist/chunk-22J2S57D.cjs +1 -0
- package/dist/chunk-4USKKL5R.js +1 -0
- package/dist/chunk-5X65PSGD.js +1 -0
- package/dist/chunk-635Q6YJZ.cjs +1 -0
- package/dist/chunk-6RNZVHSR.js +1 -0
- package/dist/chunk-FW5NGLPP.cjs +1 -0
- package/dist/chunk-IPUPRMZK.js +1 -0
- package/dist/chunk-NMDHQXMS.cjs +1 -0
- package/dist/chunk-S7X7IDBT.js +1 -0
- package/dist/chunk-UFBCZ25Y.cjs +1 -0
- package/dist/chunk-VSIVOWZF.cjs +1 -0
- package/dist/chunk-WC5TDS6C.cjs +1 -0
- package/dist/chunk-WQNH3LVB.js +1 -0
- package/dist/chunk-ZE2EJX2Y.js +1 -0
- package/dist/core.cjs +1 -0
- package/dist/core.d.cts +397 -0
- package/dist/{core/storage/modules/plugin/plugin.interface.d.ts → core.d.ts} +203 -7
- package/dist/core.js +1 -0
- package/dist/dispatcher.module-CdpmkplA.d.cts +363 -0
- package/dist/dispatcher.module-jd8U_ZEs.d.ts +363 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +1 -14
- package/dist/react.cjs +1 -0
- package/dist/react.d.cts +74 -0
- package/dist/react.d.ts +74 -0
- package/dist/react.js +1 -0
- package/dist/reactive.cjs +1 -0
- package/dist/reactive.d.cts +35 -0
- package/dist/reactive.d.ts +35 -0
- package/dist/reactive.js +1 -0
- package/dist/{core/selector/selector.interface.d.ts → selector.interface-CA5y-kD_.d.cts} +7 -35
- package/dist/selector.interface-CA5y-kD_.d.ts +63 -0
- package/dist/storage.interface-Dl8SLUd1.d.cts +128 -0
- package/dist/storage.interface-Dl8SLUd1.d.ts +128 -0
- package/dist/utils.cjs +1 -0
- package/dist/utils.d.cts +92 -0
- package/dist/utils.d.ts +92 -0
- package/dist/utils.js +1 -0
- package/package.json +54 -17
- package/dist/_utils/chunk.util.d.ts +0 -8
- package/dist/_utils/chunk.util.d.ts.map +0 -1
- package/dist/_utils/chunk.util.js +0 -21
- package/dist/_utils/chunk.util.js.map +0 -1
- package/dist/_utils/deepMerge.util.d.ts +0 -2
- package/dist/_utils/deepMerge.util.d.ts.map +0 -1
- package/dist/_utils/deepMerge.util.js +0 -16
- package/dist/_utils/deepMerge.util.js.map +0 -1
- package/dist/_utils/flatMap.util.d.ts +0 -10
- package/dist/_utils/flatMap.util.d.ts.map +0 -1
- package/dist/_utils/flatMap.util.js +0 -23
- package/dist/_utils/flatMap.util.js.map +0 -1
- package/dist/_utils/index.d.ts +0 -4
- package/dist/_utils/index.d.ts.map +0 -1
- package/dist/_utils/index.js +0 -4
- package/dist/_utils/index.js.map +0 -1
- package/dist/api/api.module.d.ts +0 -38
- package/dist/api/api.module.d.ts.map +0 -1
- package/dist/api/api.module.js +0 -82
- package/dist/api/api.module.js.map +0 -1
- package/dist/api/components/endpoint.d.ts +0 -26
- package/dist/api/components/endpoint.d.ts.map +0 -1
- package/dist/api/components/endpoint.js +0 -253
- package/dist/api/components/endpoint.js.map +0 -1
- package/dist/api/components/query-storage.d.ts +0 -84
- package/dist/api/components/query-storage.d.ts.map +0 -1
- package/dist/api/components/query-storage.js +0 -221
- package/dist/api/components/query-storage.js.map +0 -1
- package/dist/api/example.d.ts +0 -83
- package/dist/api/example.d.ts.map +0 -1
- package/dist/api/example.js +0 -85
- package/dist/api/example.js.map +0 -1
- package/dist/api/index.d.ts +0 -4
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -6
- package/dist/api/index.js.map +0 -1
- package/dist/api/types/api.interface.d.ts +0 -108
- package/dist/api/types/api.interface.d.ts.map +0 -1
- package/dist/api/types/api.interface.js +0 -19
- package/dist/api/types/api.interface.js.map +0 -1
- package/dist/api/types/endpoint.interface.d.ts +0 -116
- package/dist/api/types/endpoint.interface.d.ts.map +0 -1
- package/dist/api/types/endpoint.interface.js +0 -2
- package/dist/api/types/endpoint.interface.js.map +0 -1
- package/dist/api/types/query.interface.d.ts +0 -87
- package/dist/api/types/query.interface.d.ts.map +0 -1
- package/dist/api/types/query.interface.js +0 -2
- package/dist/api/types/query.interface.js.map +0 -1
- package/dist/api/utils/api-helpers.d.ts +0 -22
- package/dist/api/utils/api-helpers.d.ts.map +0 -1
- package/dist/api/utils/api-helpers.js +0 -44
- package/dist/api/utils/api-helpers.js.map +0 -1
- package/dist/api/utils/create-header-context.d.ts +0 -10
- package/dist/api/utils/create-header-context.d.ts.map +0 -1
- package/dist/api/utils/create-header-context.js +0 -36
- package/dist/api/utils/create-header-context.js.map +0 -1
- package/dist/api/utils/endpoint-headers.d.ts +0 -23
- package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
- package/dist/api/utils/endpoint-headers.js +0 -57
- package/dist/api/utils/endpoint-headers.js.map +0 -1
- package/dist/api/utils/fetch-base-query.d.ts +0 -9
- package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
- package/dist/api/utils/fetch-base-query.js +0 -181
- package/dist/api/utils/fetch-base-query.js.map +0 -1
- package/dist/api/utils/file-utils.d.ts +0 -43
- package/dist/api/utils/file-utils.d.ts.map +0 -1
- package/dist/api/utils/file-utils.js +0 -108
- package/dist/api/utils/file-utils.js.map +0 -1
- package/dist/api/utils/get-cacheable-headers.d.ts +0 -8
- package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
- package/dist/api/utils/get-cacheable-headers.js +0 -21
- package/dist/api/utils/get-cacheable-headers.js.map +0 -1
- package/dist/core/index.d.ts +0 -3
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -3
- package/dist/core/index.js.map +0 -1
- package/dist/core/selector/index.d.ts +0 -3
- package/dist/core/selector/index.d.ts.map +0 -1
- package/dist/core/selector/index.js +0 -2
- package/dist/core/selector/index.js.map +0 -1
- package/dist/core/selector/selector.interface.d.ts.map +0 -1
- package/dist/core/selector/selector.interface.js +0 -2
- package/dist/core/selector/selector.interface.js.map +0 -1
- package/dist/core/selector/selector.module.d.ts +0 -29
- package/dist/core/selector/selector.module.d.ts.map +0 -1
- package/dist/core/selector/selector.module.js +0 -467
- package/dist/core/selector/selector.module.js.map +0 -1
- package/dist/core/storage/adapters/base-storage.service.d.ts +0 -65
- package/dist/core/storage/adapters/base-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/base-storage.service.js +0 -660
- package/dist/core/storage/adapters/base-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.d.ts +0 -63
- package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.js +0 -595
- package/dist/core/storage/adapters/indexed-DB.service.js.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.old.d.ts +0 -38
- package/dist/core/storage/adapters/indexed-DB.service.old.d.ts.map +0 -1
- package/dist/core/storage/adapters/indexed-DB.service.old.js +0 -318
- package/dist/core/storage/adapters/indexed-DB.service.old.js.map +0 -1
- package/dist/core/storage/adapters/local-storage.service.d.ts +0 -21
- package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/local-storage.service.js +0 -99
- package/dist/core/storage/adapters/local-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/memory-storage.service.d.ts +0 -22
- package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
- package/dist/core/storage/adapters/memory-storage.service.js +0 -99
- package/dist/core/storage/adapters/memory-storage.service.js.map +0 -1
- package/dist/core/storage/adapters/path.utils.d.ts +0 -5
- package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
- package/dist/core/storage/adapters/path.utils.js +0 -35
- package/dist/core/storage/adapters/path.utils.js.map +0 -1
- package/dist/core/storage/index.d.ts +0 -11
- package/dist/core/storage/index.d.ts.map +0 -1
- package/dist/core/storage/index.js +0 -12
- package/dist/core/storage/index.js.map +0 -1
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -9
- package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/broadcast.middleware.js +0 -115
- package/dist/core/storage/middlewares/broadcast.middleware.js.map +0 -1
- package/dist/core/storage/middlewares/index.d.ts +0 -4
- package/dist/core/storage/middlewares/index.d.ts.map +0 -1
- package/dist/core/storage/middlewares/index.js +0 -3
- package/dist/core/storage/middlewares/index.js.map +0 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -7
- package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-batching.middleware.js +0 -36
- package/dist/core/storage/middlewares/storage-batching.middleware.js.map +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -7
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +0 -46
- package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.interface.js +0 -2
- package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -25
- package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
- package/dist/core/storage/modules/plugin/plugin.service.js +0 -186
- package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
- package/dist/core/storage/storage.interface.d.ts +0 -70
- package/dist/core/storage/storage.interface.d.ts.map +0 -1
- package/dist/core/storage/storage.interface.js +0 -10
- package/dist/core/storage/storage.interface.js.map +0 -1
- package/dist/core/storage/utils/batch.utils.d.ts +0 -33
- package/dist/core/storage/utils/batch.utils.d.ts.map +0 -1
- package/dist/core/storage/utils/batch.utils.js +0 -88
- package/dist/core/storage/utils/batch.utils.js.map +0 -1
- package/dist/core/storage/utils/broadcast.util.d.ts +0 -48
- package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
- package/dist/core/storage/utils/broadcast.util.js +0 -162
- package/dist/core/storage/utils/broadcast.util.js.map +0 -1
- package/dist/core/storage/utils/cache.util.d.ts +0 -33
- package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
- package/dist/core/storage/utils/cache.util.js +0 -47
- package/dist/core/storage/utils/cache.util.js.map +0 -1
- package/dist/core/storage/utils/middleware-module.d.ts +0 -46
- package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
- package/dist/core/storage/utils/middleware-module.js +0 -109
- package/dist/core/storage/utils/middleware-module.js.map +0 -1
- package/dist/core/storage/utils/storage-key.d.ts +0 -11
- package/dist/core/storage/utils/storage-key.d.ts.map +0 -1
- package/dist/core/storage/utils/storage-key.js +0 -21
- package/dist/core/storage/utils/storage-key.js.map +0 -1
- package/dist/core/storage/utils/storage.utils.d.ts +0 -17
- package/dist/core/storage/utils/storage.utils.d.ts.map +0 -1
- package/dist/core/storage/utils/storage.utils.js +0 -57
- package/dist/core/storage/utils/storage.utils.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/react/hooks/index.d.ts +0 -3
- package/dist/react/hooks/index.d.ts.map +0 -1
- package/dist/react/hooks/index.js +0 -3
- package/dist/react/hooks/index.js.map +0 -1
- package/dist/react/hooks/useSelector.d.ts +0 -22
- package/dist/react/hooks/useSelector.d.ts.map +0 -1
- package/dist/react/hooks/useSelector.js +0 -104
- package/dist/react/hooks/useSelector.js.map +0 -1
- package/dist/react/hooks/useStorageSubscribe.d.ts +0 -12
- package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
- package/dist/react/hooks/useStorageSubscribe.js +0 -49
- package/dist/react/hooks/useStorageSubscribe.js.map +0 -1
- package/dist/react/index.d.ts +0 -3
- package/dist/react/index.d.ts.map +0 -1
- package/dist/react/index.js +0 -3
- package/dist/react/index.js.map +0 -1
- package/dist/react/utils/createSynapseCtx.d.ts +0 -40
- package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
- package/dist/react/utils/createSynapseCtx.js +0 -125
- package/dist/react/utils/createSynapseCtx.js.map +0 -1
- package/dist/react/utils/index.d.ts +0 -2
- package/dist/react/utils/index.d.ts.map +0 -1
- package/dist/react/utils/index.js +0 -2
- package/dist/react/utils/index.js.map +0 -1
- package/dist/reactive/dispatcher/dispatcher.module.d.ts +0 -195
- package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
- package/dist/reactive/dispatcher/dispatcher.module.js +0 -288
- package/dist/reactive/dispatcher/dispatcher.module.js.map +0 -1
- package/dist/reactive/dispatcher/index.d.ts +0 -3
- package/dist/reactive/dispatcher/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/index.js +0 -3
- package/dist/reactive/dispatcher/index.js.map +0 -1
- package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -2
- package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/index.js +0 -2
- package/dist/reactive/dispatcher/middlewares/index.js.map +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -31
- package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js +0 -126
- package/dist/reactive/dispatcher/middlewares/logger.middleware.js.map +0 -1
- package/dist/reactive/effects/effects.module.d.ts +0 -150
- package/dist/reactive/effects/effects.module.d.ts.map +0 -1
- package/dist/reactive/effects/effects.module.js +0 -277
- package/dist/reactive/effects/effects.module.js.map +0 -1
- package/dist/reactive/effects/index.d.ts +0 -2
- package/dist/reactive/effects/index.d.ts.map +0 -1
- package/dist/reactive/effects/index.js +0 -2
- package/dist/reactive/effects/index.js.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -12
- package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestConsistent.js +0 -16
- package/dist/reactive/effects/utils/chunkRequestConsistent.js.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -12
- package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
- package/dist/reactive/effects/utils/chunkRequestParallel.js +0 -13
- package/dist/reactive/effects/utils/chunkRequestParallel.js.map +0 -1
- package/dist/reactive/effects/utils/index.d.ts +0 -3
- package/dist/reactive/effects/utils/index.d.ts.map +0 -1
- package/dist/reactive/effects/utils/index.js +0 -3
- package/dist/reactive/effects/utils/index.js.map +0 -1
- package/dist/reactive/index.d.ts +0 -3
- package/dist/reactive/index.d.ts.map +0 -1
- package/dist/reactive/index.js +0 -3
- package/dist/reactive/index.js.map +0 -1
- package/dist/utils/createSynapse.d.ts +0 -92
- package/dist/utils/createSynapse.d.ts.map +0 -1
- package/dist/utils/createSynapse.js +0 -79
- package/dist/utils/createSynapse.js.map +0 -1
- package/dist/utils/index.d.ts +0 -2
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -2
- package/dist/utils/index.js.map +0 -1
|
@@ -1,660 +0,0 @@
|
|
|
1
|
-
import { batchingMiddleware } from '../middlewares/storage-batching.middleware';
|
|
2
|
-
import { shallowCompareMiddleware } from '../middlewares/storage-shallow-compare.middleware';
|
|
3
|
-
import { StorageEvents } from '../storage.interface';
|
|
4
|
-
import { MiddlewareModule } from '../utils/middleware-module';
|
|
5
|
-
import { getValueByPath } from './path.utils.js';
|
|
6
|
-
export class BaseStorage {
|
|
7
|
-
config;
|
|
8
|
-
pluginExecutor;
|
|
9
|
-
eventEmitter;
|
|
10
|
-
logger;
|
|
11
|
-
// Константа для глобальной подписки
|
|
12
|
-
static GLOBAL_SUBSCRIPTION_KEY = '*';
|
|
13
|
-
name;
|
|
14
|
-
selectorPathCache = new WeakMap();
|
|
15
|
-
middlewareModule;
|
|
16
|
-
initializedMiddlewares = null;
|
|
17
|
-
subscribers = new Map();
|
|
18
|
-
constructor(config, pluginExecutor, eventEmitter, logger) {
|
|
19
|
-
this.config = config;
|
|
20
|
-
this.pluginExecutor = pluginExecutor;
|
|
21
|
-
this.eventEmitter = eventEmitter;
|
|
22
|
-
this.logger = logger;
|
|
23
|
-
this.name = config.name;
|
|
24
|
-
this.middlewareModule = new MiddlewareModule({
|
|
25
|
-
getState: this.getState.bind(this),
|
|
26
|
-
// Предоставляем базовые операции хранилища
|
|
27
|
-
doGet: this.doGet.bind(this),
|
|
28
|
-
doSet: this.doSet.bind(this),
|
|
29
|
-
doUpdate: this.doUpdate.bind(this),
|
|
30
|
-
doDelete: this.doDelete.bind(this),
|
|
31
|
-
doClear: this.doClear.bind(this),
|
|
32
|
-
doKeys: this.doKeys.bind(this),
|
|
33
|
-
// Предоставляем методы для работы с подписчиками
|
|
34
|
-
notifySubscribers: this.notifySubscribers.bind(this),
|
|
35
|
-
// Предоставляем плагины и эмиттер
|
|
36
|
-
pluginExecutor: this.pluginExecutor,
|
|
37
|
-
eventEmitter: this.eventEmitter,
|
|
38
|
-
logger: this.logger,
|
|
39
|
-
});
|
|
40
|
-
this.initializeMiddlewares();
|
|
41
|
-
}
|
|
42
|
-
initializeMiddlewares() {
|
|
43
|
-
if (this.config.middlewares && !this.initializedMiddlewares) {
|
|
44
|
-
// Создаем middleware только один раз
|
|
45
|
-
this.initializedMiddlewares = this.config.middlewares(() => this.getDefaultMiddleware());
|
|
46
|
-
// Применяем их
|
|
47
|
-
this.initializedMiddlewares.forEach((middleware) => this.middlewareModule.use(middleware));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
getDefaultMiddleware() {
|
|
51
|
-
return {
|
|
52
|
-
batching: (options = {}) => batchingMiddleware(options),
|
|
53
|
-
shallowCompare: (options = {}) => shallowCompareMiddleware(options),
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
async initializeWithMiddlewares() {
|
|
57
|
-
try {
|
|
58
|
-
const state = await this.getState();
|
|
59
|
-
const hasExistingState = Object.keys(state).length > 0;
|
|
60
|
-
if (!hasExistingState && this.config.initialState) {
|
|
61
|
-
// Только если нет существующих данных и есть initialState,
|
|
62
|
-
// делаем dispatch для установки начального состояния
|
|
63
|
-
await this.middlewareModule.dispatch({
|
|
64
|
-
type: 'init',
|
|
65
|
-
value: this.config.initialState,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
this.logger?.error('Ошибка инициализации хранилища', { error });
|
|
71
|
-
throw error;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async get(key) {
|
|
75
|
-
try {
|
|
76
|
-
const metadata = { operation: 'get', timestamp: Date.now(), key };
|
|
77
|
-
// Передаем в middleware chain
|
|
78
|
-
const middlewareResult = await this.middlewareModule.dispatch({
|
|
79
|
-
type: 'get',
|
|
80
|
-
key,
|
|
81
|
-
metadata,
|
|
82
|
-
});
|
|
83
|
-
// Обрабатываем значение через плагины
|
|
84
|
-
const finalResult = (await this.pluginExecutor?.executeAfterGet(key, middlewareResult, metadata)) ?? middlewareResult;
|
|
85
|
-
await this.emitEvent({
|
|
86
|
-
type: StorageEvents.STORAGE_SELECT,
|
|
87
|
-
payload: { key, value: finalResult },
|
|
88
|
-
});
|
|
89
|
-
return finalResult;
|
|
90
|
-
}
|
|
91
|
-
catch (error) {
|
|
92
|
-
this.logger?.error('Error getting value', { key, error });
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
async set(key, value) {
|
|
97
|
-
try {
|
|
98
|
-
const metadata = { operation: 'set', timestamp: Date.now(), key };
|
|
99
|
-
// Обрабатываем значение через плагины
|
|
100
|
-
const processedValue = (await this.pluginExecutor?.executeBeforeSet(value, metadata)) ?? value;
|
|
101
|
-
// Передаем в middleware chain
|
|
102
|
-
const middlewareResult = await this.middlewareModule.dispatch({
|
|
103
|
-
type: 'set',
|
|
104
|
-
key,
|
|
105
|
-
value: processedValue,
|
|
106
|
-
metadata,
|
|
107
|
-
});
|
|
108
|
-
// Проверяем метаданные, добавленные shallowCompare middleware
|
|
109
|
-
const valueNotChanged = middlewareResult?.__metadata?.valueNotChanged === true;
|
|
110
|
-
// Финальная обработка значения, передаем оригинальный ключ
|
|
111
|
-
let finalResult;
|
|
112
|
-
if (valueNotChanged && middlewareResult?.__metadata?.originalValue !== undefined) {
|
|
113
|
-
// Если значение не изменилось, используем оригинальное значение без метаданных
|
|
114
|
-
finalResult = middlewareResult.__metadata.originalValue;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
finalResult = (await this.pluginExecutor?.executeAfterSet(key, middlewareResult, metadata)) ?? middlewareResult;
|
|
118
|
-
}
|
|
119
|
-
// Уведомляем подписчиков только если значение изменилось
|
|
120
|
-
if (!valueNotChanged) {
|
|
121
|
-
// Просто берем путь из первого параметра
|
|
122
|
-
const keyStr = key.toString();
|
|
123
|
-
const changedPaths = [keyStr];
|
|
124
|
-
// Уведомляем подписчиков конкретного ключа
|
|
125
|
-
this.notifySubscribers(key, finalResult);
|
|
126
|
-
// Уведомляем глобальных подписчиков с информацией о пути
|
|
127
|
-
this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {
|
|
128
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
129
|
-
key,
|
|
130
|
-
value: finalResult,
|
|
131
|
-
changedPaths,
|
|
132
|
-
});
|
|
133
|
-
await this.emitEvent({
|
|
134
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
135
|
-
payload: {
|
|
136
|
-
key,
|
|
137
|
-
value: finalResult,
|
|
138
|
-
changedPaths,
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
this.logger?.error('Error setting value', { key, error });
|
|
145
|
-
throw error;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
async update(updater) {
|
|
149
|
-
try {
|
|
150
|
-
const metadata = { operation: 'update', timestamp: Date.now() };
|
|
151
|
-
// Получаем текущее состояние
|
|
152
|
-
const currentState = (await this.getState());
|
|
153
|
-
// Используем structuredClone для создания глубокой копии
|
|
154
|
-
const newState = structuredClone(currentState);
|
|
155
|
-
// Применяем обновление
|
|
156
|
-
updater(newState);
|
|
157
|
-
// Находим все изменившиеся пути
|
|
158
|
-
const changedPaths = this.findChangedPaths(currentState, newState);
|
|
159
|
-
// Если нет изменений, завершаем метод
|
|
160
|
-
if (changedPaths.size === 0) {
|
|
161
|
-
if (this.logger?.debug) {
|
|
162
|
-
this.logger.debug('No changes detected in update');
|
|
163
|
-
}
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (this.logger?.debug) {
|
|
167
|
-
this.logger.debug('Changed paths:', { paths: Array.from(changedPaths) });
|
|
168
|
-
}
|
|
169
|
-
// Определяем изменившиеся верхнеуровневые ключи для middleware
|
|
170
|
-
const changedTopLevelKeys = new Set();
|
|
171
|
-
for (const path of changedPaths) {
|
|
172
|
-
const topLevelKey = path.split('.')[0];
|
|
173
|
-
changedTopLevelKeys.add(topLevelKey);
|
|
174
|
-
}
|
|
175
|
-
// Подготавливаем обновления для middleware (только верхнеуровневые ключи)
|
|
176
|
-
const updates = await Promise.all(Array.from(changedTopLevelKeys).map(async (key) => {
|
|
177
|
-
const keyMetadata = { ...metadata, key };
|
|
178
|
-
// Обрабатываем значение через плагины
|
|
179
|
-
const processedValue = (await this.pluginExecutor?.executeBeforeSet(newState[key], keyMetadata)) ?? newState[key];
|
|
180
|
-
return { key, value: processedValue };
|
|
181
|
-
}));
|
|
182
|
-
// Делаем dispatch для batch-обновления
|
|
183
|
-
const result = await this.middlewareModule.dispatch({
|
|
184
|
-
type: 'update',
|
|
185
|
-
value: updates,
|
|
186
|
-
metadata: {
|
|
187
|
-
...metadata,
|
|
188
|
-
batchUpdate: true,
|
|
189
|
-
changedPaths: Array.from(changedPaths),
|
|
190
|
-
},
|
|
191
|
-
});
|
|
192
|
-
// Преобразуем результат в объект
|
|
193
|
-
let updatedValues = {};
|
|
194
|
-
if (Array.isArray(result)) {
|
|
195
|
-
result.forEach((update) => {
|
|
196
|
-
if (update && typeof update === 'object' && 'key' in update && 'value' in update) {
|
|
197
|
-
updatedValues[update.key] = update.value;
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
else if (result && typeof result === 'object') {
|
|
202
|
-
updatedValues = { ...result };
|
|
203
|
-
}
|
|
204
|
-
// Определяем действительно измененные ключи после middleware
|
|
205
|
-
const actuallyChangedKeys = Object.keys(updatedValues).filter((key) => !this.isEqual(currentState[key], updatedValues[key]));
|
|
206
|
-
if (actuallyChangedKeys.length === 0) {
|
|
207
|
-
if (this.logger?.debug) {
|
|
208
|
-
this.logger.debug('No actual changes after middleware processing');
|
|
209
|
-
}
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// Создаем объект с измененными значениями
|
|
213
|
-
const finalUpdates = {};
|
|
214
|
-
actuallyChangedKeys.forEach((key) => {
|
|
215
|
-
finalUpdates[key] = updatedValues[key];
|
|
216
|
-
});
|
|
217
|
-
if (this.logger?.debug) {
|
|
218
|
-
this.logger.debug('Notifying subscribers about changes:', { keys: actuallyChangedKeys });
|
|
219
|
-
}
|
|
220
|
-
// Уведомляем о глобальном обновлении
|
|
221
|
-
this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {
|
|
222
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
223
|
-
key: actuallyChangedKeys,
|
|
224
|
-
value: finalUpdates,
|
|
225
|
-
changedPaths: Array.from(changedPaths), // Добавляем информацию о всех изменившихся путях
|
|
226
|
-
});
|
|
227
|
-
// Уведомляем подписчиков на ТОЧНЫЕ ИЗМЕНИВШИЕСЯ ПУТИ
|
|
228
|
-
// Важное отличие от предыдущей реализации - уведомляем только о тех путях, которые
|
|
229
|
-
// действительно изменились, а не обо всех вложенных объектах
|
|
230
|
-
for (const path of changedPaths) {
|
|
231
|
-
try {
|
|
232
|
-
// Находим верхнеуровневый ключ
|
|
233
|
-
const topLevelKey = path.split('.')[0];
|
|
234
|
-
// Если верхнеуровневый ключ был изменен, используем его обновленное значение
|
|
235
|
-
if (topLevelKey in finalUpdates) {
|
|
236
|
-
let value;
|
|
237
|
-
if (path === topLevelKey) {
|
|
238
|
-
// Если это верхнеуровневый ключ, используем его напрямую
|
|
239
|
-
value = finalUpdates[topLevelKey];
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
// Иначе получаем значение по вложенному пути
|
|
243
|
-
const restPath = path.substring(topLevelKey.length + 1);
|
|
244
|
-
value = getValueByPath(finalUpdates[topLevelKey], restPath);
|
|
245
|
-
}
|
|
246
|
-
// Уведомляем подписчиков для этого конкретного пути
|
|
247
|
-
if (value !== undefined) {
|
|
248
|
-
this.notifySubscribers(path, value);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
catch (error) {
|
|
253
|
-
this.logger?.error('Error notifying path subscribers', { path, error });
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
// Отправляем событие
|
|
257
|
-
await this.emitEvent({
|
|
258
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
259
|
-
payload: {
|
|
260
|
-
state: finalUpdates,
|
|
261
|
-
key: actuallyChangedKeys,
|
|
262
|
-
changedPaths: Array.from(changedPaths),
|
|
263
|
-
},
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
catch (error) {
|
|
267
|
-
this.logger?.error('Error updating state', { error });
|
|
268
|
-
throw error;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
async delete(key) {
|
|
272
|
-
try {
|
|
273
|
-
const metadata = { operation: 'delete', timestamp: Date.now(), key };
|
|
274
|
-
// Проверяем возможность удаления
|
|
275
|
-
if (await this.pluginExecutor?.executeBeforeDelete(key, metadata)) {
|
|
276
|
-
const middlewareResult = await this.middlewareModule.dispatch({
|
|
277
|
-
type: 'delete',
|
|
278
|
-
key,
|
|
279
|
-
metadata,
|
|
280
|
-
});
|
|
281
|
-
// Выполняем afterDelete с оригинальным ключом
|
|
282
|
-
await this.pluginExecutor?.executeAfterDelete(key, metadata);
|
|
283
|
-
// Определяем путь изменения (по аналогии с set)
|
|
284
|
-
const keyStr = key.toString();
|
|
285
|
-
const changedPaths = [keyStr];
|
|
286
|
-
// Уведомляем подписчиков используя оригинальный ключ
|
|
287
|
-
this.notifySubscribers(key, undefined);
|
|
288
|
-
this.notifySubscribers(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, {
|
|
289
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
290
|
-
key,
|
|
291
|
-
value: undefined,
|
|
292
|
-
result: middlewareResult,
|
|
293
|
-
changedPaths,
|
|
294
|
-
});
|
|
295
|
-
await this.emitEvent({
|
|
296
|
-
type: StorageEvents.STORAGE_UPDATE,
|
|
297
|
-
payload: {
|
|
298
|
-
key,
|
|
299
|
-
value: undefined,
|
|
300
|
-
result: middlewareResult,
|
|
301
|
-
changedPaths,
|
|
302
|
-
},
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
this.logger?.error('Error deleting value', { key, error });
|
|
308
|
-
throw error;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
async clear() {
|
|
312
|
-
try {
|
|
313
|
-
this.pluginExecutor?.executeOnClear();
|
|
314
|
-
await this.middlewareModule.dispatch({
|
|
315
|
-
type: 'clear',
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
catch (error) {
|
|
319
|
-
this.logger?.error('Error clearing storage', { error });
|
|
320
|
-
throw error;
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
async keys() {
|
|
324
|
-
try {
|
|
325
|
-
return await this.middlewareModule.dispatch({
|
|
326
|
-
type: 'keys',
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
catch (error) {
|
|
330
|
-
this.logger?.error('Error getting keys', { error });
|
|
331
|
-
throw error;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
async has(key) {
|
|
335
|
-
try {
|
|
336
|
-
return await this.doHas(key);
|
|
337
|
-
}
|
|
338
|
-
catch (error) {
|
|
339
|
-
this.logger?.error('Error checking value existence', { key, error });
|
|
340
|
-
throw error;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
async getState() {
|
|
344
|
-
try {
|
|
345
|
-
const value = await this.doGet('');
|
|
346
|
-
return value || {};
|
|
347
|
-
}
|
|
348
|
-
catch (error) {
|
|
349
|
-
this.logger?.error('Error getting state', { error });
|
|
350
|
-
throw error;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// Вспомогательный метод для подписки на все изменения
|
|
354
|
-
subscribeToAll(callback) {
|
|
355
|
-
// Подписываемся на глобальный ключ, который получает уведомления обо всех изменениях
|
|
356
|
-
if (!this.subscribers.has(BaseStorage.GLOBAL_SUBSCRIPTION_KEY)) {
|
|
357
|
-
this.subscribers.set(BaseStorage.GLOBAL_SUBSCRIPTION_KEY, new Set());
|
|
358
|
-
}
|
|
359
|
-
// Добавляем колбэк в набор подписчиков для глобального ключа
|
|
360
|
-
this.subscribers.get(BaseStorage.GLOBAL_SUBSCRIPTION_KEY).add(callback);
|
|
361
|
-
// Возвращаем функцию отписки
|
|
362
|
-
return () => {
|
|
363
|
-
const subscribers = this.subscribers.get(BaseStorage.GLOBAL_SUBSCRIPTION_KEY);
|
|
364
|
-
if (subscribers) {
|
|
365
|
-
subscribers.delete(callback);
|
|
366
|
-
if (subscribers.size === 0) {
|
|
367
|
-
this.subscribers.delete(BaseStorage.GLOBAL_SUBSCRIPTION_KEY);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
subscribe(keyOrSelector, callback) {
|
|
373
|
-
if (typeof keyOrSelector === 'string') {
|
|
374
|
-
// Существующая логика для строкового ключа
|
|
375
|
-
return this.subscribeByKey(keyOrSelector, callback);
|
|
376
|
-
}
|
|
377
|
-
// Новая логика для селектора пути
|
|
378
|
-
return this.subscribeBySelector(keyOrSelector, callback);
|
|
379
|
-
}
|
|
380
|
-
async destroy() {
|
|
381
|
-
try {
|
|
382
|
-
await this.clear();
|
|
383
|
-
await this.doDestroy();
|
|
384
|
-
// Очищаем middleware и соединения
|
|
385
|
-
if (this.initializedMiddlewares) {
|
|
386
|
-
// Если у middleware есть метод cleanup/destroy - вызываем его
|
|
387
|
-
await Promise.all(this.initializedMiddlewares.map(async (middleware) => {
|
|
388
|
-
if ('cleanup' in middleware) {
|
|
389
|
-
await middleware.cleanup?.();
|
|
390
|
-
}
|
|
391
|
-
}));
|
|
392
|
-
this.initializedMiddlewares = null;
|
|
393
|
-
}
|
|
394
|
-
await this.emitEvent({
|
|
395
|
-
type: StorageEvents.STORAGE_DESTROY,
|
|
396
|
-
});
|
|
397
|
-
}
|
|
398
|
-
catch (error) {
|
|
399
|
-
this.logger?.error('Error destroying storage', { error });
|
|
400
|
-
throw error;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
// Вспомогательные методы
|
|
404
|
-
subscribeByKey(key, callback) {
|
|
405
|
-
// Создаем коллекцию подписчиков, если ее еще нет
|
|
406
|
-
if (!this.subscribers.has(key)) {
|
|
407
|
-
this.subscribers.set(key, new Set());
|
|
408
|
-
}
|
|
409
|
-
// Флаг для отслеживания отправки начального значения
|
|
410
|
-
let initialValueSent = false;
|
|
411
|
-
// Добавляем колбэк в набор подписчиков
|
|
412
|
-
this.subscribers.get(key).add(callback);
|
|
413
|
-
// Получаем и отправляем начальное значение, но только один раз
|
|
414
|
-
this.get(key).then((value) => {
|
|
415
|
-
try {
|
|
416
|
-
if (!initialValueSent) {
|
|
417
|
-
initialValueSent = true;
|
|
418
|
-
callback(value);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
catch (error) {
|
|
422
|
-
this.logger?.error('Error in initial callback', { key, error });
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
// Возвращаем функцию отписки
|
|
426
|
-
return () => {
|
|
427
|
-
const subscribers = this.subscribers.get(key);
|
|
428
|
-
if (subscribers) {
|
|
429
|
-
subscribers.delete(callback);
|
|
430
|
-
if (subscribers.size === 0) {
|
|
431
|
-
this.subscribers.delete(key);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
createDummyState() {
|
|
437
|
-
const handler = {
|
|
438
|
-
get: (target, prop) => {
|
|
439
|
-
target[prop] = target[prop] || new Proxy({}, handler);
|
|
440
|
-
return target[prop];
|
|
441
|
-
},
|
|
442
|
-
};
|
|
443
|
-
return new Proxy({}, handler);
|
|
444
|
-
}
|
|
445
|
-
isEqual(a, b) {
|
|
446
|
-
// Если ссылки одинаковые, объекты равны
|
|
447
|
-
if (a === b)
|
|
448
|
-
return true;
|
|
449
|
-
// Если хотя бы один из объектов null/undefined, они равны только если оба null/undefined
|
|
450
|
-
if (a == null || b == null)
|
|
451
|
-
return a === b;
|
|
452
|
-
// Если типы различаются, объекты не равны
|
|
453
|
-
const typeA = typeof a;
|
|
454
|
-
const typeB = typeof b;
|
|
455
|
-
if (typeA !== typeB)
|
|
456
|
-
return false;
|
|
457
|
-
// Обработка примитивных типов
|
|
458
|
-
if (typeA !== 'object')
|
|
459
|
-
return a === b;
|
|
460
|
-
// Обработка различных типов объектов
|
|
461
|
-
// Обработка Date объектов
|
|
462
|
-
if (a instanceof Date && b instanceof Date) {
|
|
463
|
-
return a.getTime() === b.getTime();
|
|
464
|
-
}
|
|
465
|
-
// Обработка массивов
|
|
466
|
-
if (Array.isArray(a) && Array.isArray(b)) {
|
|
467
|
-
if (a.length !== b.length)
|
|
468
|
-
return false;
|
|
469
|
-
for (let i = 0; i < a.length; i++) {
|
|
470
|
-
if (!this.isEqual(a[i], b[i]))
|
|
471
|
-
return false;
|
|
472
|
-
}
|
|
473
|
-
return true;
|
|
474
|
-
}
|
|
475
|
-
// Обработка обычных объектов
|
|
476
|
-
const keysA = Object.keys(a);
|
|
477
|
-
const keysB = Object.keys(b);
|
|
478
|
-
if (keysA.length !== keysB.length)
|
|
479
|
-
return false;
|
|
480
|
-
return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && this.isEqual(a[key], b[key]));
|
|
481
|
-
}
|
|
482
|
-
/**
|
|
483
|
-
* Возвращает полный путь, а не только корневой ключ
|
|
484
|
-
*/
|
|
485
|
-
extractPath(selector, dummyState) {
|
|
486
|
-
// Проверяем кэш
|
|
487
|
-
if (this.selectorPathCache.has(selector)) {
|
|
488
|
-
return this.selectorPathCache.get(selector);
|
|
489
|
-
}
|
|
490
|
-
const accessedPaths = [];
|
|
491
|
-
// Создаем прокси с рекурсивным обработчиком для отслеживания доступа к свойствам
|
|
492
|
-
const createProxyHandler = (path = '') => ({
|
|
493
|
-
get: (target, prop) => {
|
|
494
|
-
// Игнорируем служебные свойства Symbol
|
|
495
|
-
if (typeof prop === 'symbol') {
|
|
496
|
-
return Reflect.get(target, prop);
|
|
497
|
-
}
|
|
498
|
-
// Формируем текущий путь
|
|
499
|
-
const currentPath = path ? `${path}.${prop}` : prop;
|
|
500
|
-
// Сохраняем путь в список
|
|
501
|
-
accessedPaths.push(currentPath);
|
|
502
|
-
// Возвращаем новый прокси для вложенного свойства
|
|
503
|
-
return new Proxy({}, createProxyHandler(currentPath));
|
|
504
|
-
},
|
|
505
|
-
// Обработка опциональной цепочки (?.)
|
|
506
|
-
has: (target, prop) => {
|
|
507
|
-
// Симулируем, что свойство существует для работы опциональной цепочки
|
|
508
|
-
return true;
|
|
509
|
-
},
|
|
510
|
-
// Поддержка для Array.prototype.map и других операций над массивами
|
|
511
|
-
ownKeys: () => [],
|
|
512
|
-
getOwnPropertyDescriptor: () => ({
|
|
513
|
-
configurable: true,
|
|
514
|
-
enumerable: true,
|
|
515
|
-
}),
|
|
516
|
-
apply: (target, thisArg, args) => {
|
|
517
|
-
// Обработка вызова функций (например, массивы могут иметь методы)
|
|
518
|
-
return new Proxy(() => { }, createProxyHandler(path));
|
|
519
|
-
},
|
|
520
|
-
});
|
|
521
|
-
try {
|
|
522
|
-
// Применяем селектор к прокси для отслеживания пути
|
|
523
|
-
selector(new Proxy(dummyState, createProxyHandler()));
|
|
524
|
-
}
|
|
525
|
-
catch (error) {
|
|
526
|
-
// Игнорируем ошибки - они могут возникать из-за доступа к несуществующим свойствам
|
|
527
|
-
}
|
|
528
|
-
// Если нет доступа к путям, возвращаем пустую строку
|
|
529
|
-
if (accessedPaths.length === 0)
|
|
530
|
-
return '';
|
|
531
|
-
// Сортируем пути по длине (самый длинный первым), так мы получим самый специфичный путь
|
|
532
|
-
accessedPaths.sort((a, b) => b.length - a.length);
|
|
533
|
-
// Возвращаем наиболее специфичный путь (самый длинный)
|
|
534
|
-
this.selectorPathCache.set(selector, accessedPaths[0]);
|
|
535
|
-
return accessedPaths[0];
|
|
536
|
-
}
|
|
537
|
-
notifySubscribers(key, value) {
|
|
538
|
-
const keyStr = key.toString();
|
|
539
|
-
// 1. Точное соответствие - уведомляем подписчиков для этого конкретного ключа
|
|
540
|
-
const exactSubscribers = this.subscribers.get(keyStr);
|
|
541
|
-
if (exactSubscribers?.size) {
|
|
542
|
-
// Создаем безопасную копию подписчиков для итерации
|
|
543
|
-
const subscribersCopy = new Set(exactSubscribers);
|
|
544
|
-
subscribersCopy.forEach((callback) => {
|
|
545
|
-
try {
|
|
546
|
-
callback(value);
|
|
547
|
-
}
|
|
548
|
-
catch (error) {
|
|
549
|
-
this.logger?.error('Ошибка в подписчике на колбэк', { key: keyStr, error });
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Метод для определения изменившихся путей между двумя объектами
|
|
556
|
-
*/
|
|
557
|
-
findChangedPaths(oldObj, newObj, prefix = '', changedPaths = new Set(), visited = new WeakMap()) {
|
|
558
|
-
// Если ссылки идентичны, нет изменений
|
|
559
|
-
if (oldObj === newObj)
|
|
560
|
-
return changedPaths;
|
|
561
|
-
// Если один из объектов не является объектом или null, проверяем на изменения
|
|
562
|
-
if (typeof oldObj !== 'object' || typeof newObj !== 'object' || oldObj === null || newObj === null) {
|
|
563
|
-
if (oldObj !== newObj) {
|
|
564
|
-
changedPaths.add(prefix || '');
|
|
565
|
-
}
|
|
566
|
-
return changedPaths;
|
|
567
|
-
}
|
|
568
|
-
// Проверка на циклические ссылки
|
|
569
|
-
if (visited.has(oldObj))
|
|
570
|
-
return changedPaths;
|
|
571
|
-
visited.set(oldObj, true);
|
|
572
|
-
// Собираем все ключи из обоих объектов
|
|
573
|
-
const allKeys = new Set([...Object.keys(oldObj || {}), ...Object.keys(newObj || {})]);
|
|
574
|
-
// Для каждого ключа проверяем изменения
|
|
575
|
-
for (const key of allKeys) {
|
|
576
|
-
const oldValue = oldObj[key];
|
|
577
|
-
const newValue = newObj[key];
|
|
578
|
-
// Если значения идентичны, пропускаем
|
|
579
|
-
if (oldValue === newValue)
|
|
580
|
-
continue;
|
|
581
|
-
const path = prefix ? `${prefix}.${key}` : key;
|
|
582
|
-
// Если оба значения - объекты (но не массивы), рекурсивно проверяем их
|
|
583
|
-
if (oldValue && newValue && typeof oldValue === 'object' && typeof newValue === 'object' && !Array.isArray(oldValue) && !Array.isArray(newValue)) {
|
|
584
|
-
this.findChangedPaths(oldValue, newValue, path, changedPaths, visited);
|
|
585
|
-
}
|
|
586
|
-
// Если оба значения - массивы, используем isEqual для сравнения
|
|
587
|
-
else if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
|
588
|
-
if (!this.isEqual(oldValue, newValue)) {
|
|
589
|
-
changedPaths.add(path);
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
// Для остальных типов данных - просто сравниваем
|
|
593
|
-
else if (!this.isEqual(oldValue, newValue)) {
|
|
594
|
-
changedPaths.add(path);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
return changedPaths;
|
|
598
|
-
}
|
|
599
|
-
subscribeBySelector(pathSelector, callback) {
|
|
600
|
-
// Получаем полный путь из селектора (не только корневой ключ)
|
|
601
|
-
const dummyState = this.createDummyState();
|
|
602
|
-
const fullPath = this.extractPath(pathSelector, dummyState);
|
|
603
|
-
if (this.logger?.debug) {
|
|
604
|
-
this.logger.debug('Subscribing to path:', { path: fullPath });
|
|
605
|
-
}
|
|
606
|
-
// Создаем обертку для колбэка, которая применяет оригинальный селектор к текущему состоянию
|
|
607
|
-
const wrappedCallback = async (value) => {
|
|
608
|
-
try {
|
|
609
|
-
// Для значений undefined или null, нам нужно получить текущее состояние
|
|
610
|
-
if (value === undefined || value === null) {
|
|
611
|
-
const currentState = (await this.getState());
|
|
612
|
-
const selectedValue = pathSelector(currentState);
|
|
613
|
-
callback(selectedValue);
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
// Если значение не объект или точно соответствует ожидаемому типу,
|
|
617
|
-
// передаем его напрямую
|
|
618
|
-
if (typeof value !== 'object' || value === null) {
|
|
619
|
-
callback(value);
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
// Для объектов запускаем селектор, чтобы получить точное значение
|
|
623
|
-
const currentState = (await this.getState());
|
|
624
|
-
const selectedValue = pathSelector(currentState);
|
|
625
|
-
callback(selectedValue);
|
|
626
|
-
}
|
|
627
|
-
catch (error) {
|
|
628
|
-
this.logger?.error('Error in selector callback', { path: fullPath, error });
|
|
629
|
-
// В случае ошибки передаем исходное значение
|
|
630
|
-
callback(value);
|
|
631
|
-
}
|
|
632
|
-
};
|
|
633
|
-
// Если путь не удалось извлечь, подписываемся на глобальные изменения
|
|
634
|
-
if (!fullPath) {
|
|
635
|
-
return this.subscribeToAll(() => {
|
|
636
|
-
this.getState().then((state) => {
|
|
637
|
-
callback(pathSelector(state));
|
|
638
|
-
});
|
|
639
|
-
});
|
|
640
|
-
}
|
|
641
|
-
// Подписываемся на полный путь, а не только на корневой ключ
|
|
642
|
-
return this.subscribeByKey(fullPath, wrappedCallback);
|
|
643
|
-
}
|
|
644
|
-
async emitEvent(event) {
|
|
645
|
-
try {
|
|
646
|
-
await this.eventEmitter?.emit({
|
|
647
|
-
...event,
|
|
648
|
-
metadata: {
|
|
649
|
-
...(event.metadata || {}),
|
|
650
|
-
timestamp: Date.now(),
|
|
651
|
-
storageName: this.name,
|
|
652
|
-
},
|
|
653
|
-
});
|
|
654
|
-
}
|
|
655
|
-
catch (error) {
|
|
656
|
-
this.logger?.error('Error emitting event', { event, error });
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
//# sourceMappingURL=base-storage.service.js.map
|