synapse-storage 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/dist/api.cjs +891 -0
  2. package/dist/api.cjs.map +1 -0
  3. package/dist/api.d.cts +365 -0
  4. package/dist/api.d.ts +365 -0
  5. package/dist/api.js +860 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/core.cjs +2389 -0
  8. package/dist/core.cjs.map +1 -0
  9. package/dist/core.d.cts +397 -0
  10. package/dist/{core/storage/modules/plugin/plugin.interface.d.ts → core.d.ts} +203 -7
  11. package/dist/core.js +2356 -0
  12. package/dist/core.js.map +1 -0
  13. package/dist/dispatcher.module-CdpmkplA.d.cts +363 -0
  14. package/dist/dispatcher.module-jd8U_ZEs.d.ts +363 -0
  15. package/dist/index.cjs +4148 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +10 -0
  18. package/dist/index.d.ts +10 -10
  19. package/dist/index.js +4092 -13
  20. package/dist/index.js.map +1 -1
  21. package/dist/react.cjs +268 -0
  22. package/dist/react.cjs.map +1 -0
  23. package/dist/react.d.cts +74 -0
  24. package/dist/react.d.ts +74 -0
  25. package/dist/react.js +239 -0
  26. package/dist/react.js.map +1 -0
  27. package/dist/reactive.cjs +643 -0
  28. package/dist/reactive.cjs.map +1 -0
  29. package/dist/reactive.d.cts +35 -0
  30. package/dist/reactive.d.ts +35 -0
  31. package/dist/reactive.js +604 -0
  32. package/dist/reactive.js.map +1 -0
  33. package/dist/{core/selector/selector.interface.d.ts → selector.interface-CA5y-kD_.d.cts} +7 -35
  34. package/dist/selector.interface-CA5y-kD_.d.ts +63 -0
  35. package/dist/storage.interface-Dl8SLUd1.d.cts +128 -0
  36. package/dist/storage.interface-Dl8SLUd1.d.ts +128 -0
  37. package/dist/utils.cjs +601 -0
  38. package/dist/utils.cjs.map +1 -0
  39. package/dist/utils.d.cts +92 -0
  40. package/dist/utils.d.ts +92 -0
  41. package/dist/utils.js +574 -0
  42. package/dist/utils.js.map +1 -0
  43. package/package.json +54 -17
  44. package/dist/_utils/chunk.util.d.ts +0 -8
  45. package/dist/_utils/chunk.util.d.ts.map +0 -1
  46. package/dist/_utils/chunk.util.js +0 -21
  47. package/dist/_utils/chunk.util.js.map +0 -1
  48. package/dist/_utils/deepMerge.util.d.ts +0 -2
  49. package/dist/_utils/deepMerge.util.d.ts.map +0 -1
  50. package/dist/_utils/deepMerge.util.js +0 -16
  51. package/dist/_utils/deepMerge.util.js.map +0 -1
  52. package/dist/_utils/flatMap.util.d.ts +0 -10
  53. package/dist/_utils/flatMap.util.d.ts.map +0 -1
  54. package/dist/_utils/flatMap.util.js +0 -23
  55. package/dist/_utils/flatMap.util.js.map +0 -1
  56. package/dist/_utils/index.d.ts +0 -4
  57. package/dist/_utils/index.d.ts.map +0 -1
  58. package/dist/_utils/index.js +0 -4
  59. package/dist/_utils/index.js.map +0 -1
  60. package/dist/api/api.module.d.ts +0 -38
  61. package/dist/api/api.module.d.ts.map +0 -1
  62. package/dist/api/api.module.js +0 -82
  63. package/dist/api/api.module.js.map +0 -1
  64. package/dist/api/components/endpoint.d.ts +0 -26
  65. package/dist/api/components/endpoint.d.ts.map +0 -1
  66. package/dist/api/components/endpoint.js +0 -253
  67. package/dist/api/components/endpoint.js.map +0 -1
  68. package/dist/api/components/query-storage.d.ts +0 -84
  69. package/dist/api/components/query-storage.d.ts.map +0 -1
  70. package/dist/api/components/query-storage.js +0 -221
  71. package/dist/api/components/query-storage.js.map +0 -1
  72. package/dist/api/example.d.ts +0 -83
  73. package/dist/api/example.d.ts.map +0 -1
  74. package/dist/api/example.js +0 -85
  75. package/dist/api/example.js.map +0 -1
  76. package/dist/api/index.d.ts +0 -4
  77. package/dist/api/index.d.ts.map +0 -1
  78. package/dist/api/index.js +0 -6
  79. package/dist/api/index.js.map +0 -1
  80. package/dist/api/types/api.interface.d.ts +0 -108
  81. package/dist/api/types/api.interface.d.ts.map +0 -1
  82. package/dist/api/types/api.interface.js +0 -19
  83. package/dist/api/types/api.interface.js.map +0 -1
  84. package/dist/api/types/endpoint.interface.d.ts +0 -116
  85. package/dist/api/types/endpoint.interface.d.ts.map +0 -1
  86. package/dist/api/types/endpoint.interface.js +0 -2
  87. package/dist/api/types/endpoint.interface.js.map +0 -1
  88. package/dist/api/types/query.interface.d.ts +0 -87
  89. package/dist/api/types/query.interface.d.ts.map +0 -1
  90. package/dist/api/types/query.interface.js +0 -2
  91. package/dist/api/types/query.interface.js.map +0 -1
  92. package/dist/api/utils/api-helpers.d.ts +0 -22
  93. package/dist/api/utils/api-helpers.d.ts.map +0 -1
  94. package/dist/api/utils/api-helpers.js +0 -44
  95. package/dist/api/utils/api-helpers.js.map +0 -1
  96. package/dist/api/utils/create-header-context.d.ts +0 -10
  97. package/dist/api/utils/create-header-context.d.ts.map +0 -1
  98. package/dist/api/utils/create-header-context.js +0 -36
  99. package/dist/api/utils/create-header-context.js.map +0 -1
  100. package/dist/api/utils/endpoint-headers.d.ts +0 -23
  101. package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
  102. package/dist/api/utils/endpoint-headers.js +0 -57
  103. package/dist/api/utils/endpoint-headers.js.map +0 -1
  104. package/dist/api/utils/fetch-base-query.d.ts +0 -9
  105. package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
  106. package/dist/api/utils/fetch-base-query.js +0 -181
  107. package/dist/api/utils/fetch-base-query.js.map +0 -1
  108. package/dist/api/utils/file-utils.d.ts +0 -43
  109. package/dist/api/utils/file-utils.d.ts.map +0 -1
  110. package/dist/api/utils/file-utils.js +0 -108
  111. package/dist/api/utils/file-utils.js.map +0 -1
  112. package/dist/api/utils/get-cacheable-headers.d.ts +0 -8
  113. package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
  114. package/dist/api/utils/get-cacheable-headers.js +0 -21
  115. package/dist/api/utils/get-cacheable-headers.js.map +0 -1
  116. package/dist/core/index.d.ts +0 -3
  117. package/dist/core/index.d.ts.map +0 -1
  118. package/dist/core/index.js +0 -3
  119. package/dist/core/index.js.map +0 -1
  120. package/dist/core/selector/index.d.ts +0 -3
  121. package/dist/core/selector/index.d.ts.map +0 -1
  122. package/dist/core/selector/index.js +0 -2
  123. package/dist/core/selector/index.js.map +0 -1
  124. package/dist/core/selector/selector.interface.d.ts.map +0 -1
  125. package/dist/core/selector/selector.interface.js +0 -2
  126. package/dist/core/selector/selector.interface.js.map +0 -1
  127. package/dist/core/selector/selector.module.d.ts +0 -29
  128. package/dist/core/selector/selector.module.d.ts.map +0 -1
  129. package/dist/core/selector/selector.module.js +0 -467
  130. package/dist/core/selector/selector.module.js.map +0 -1
  131. package/dist/core/storage/adapters/base-storage.service.d.ts +0 -65
  132. package/dist/core/storage/adapters/base-storage.service.d.ts.map +0 -1
  133. package/dist/core/storage/adapters/base-storage.service.js +0 -660
  134. package/dist/core/storage/adapters/base-storage.service.js.map +0 -1
  135. package/dist/core/storage/adapters/indexed-DB.service.d.ts +0 -63
  136. package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
  137. package/dist/core/storage/adapters/indexed-DB.service.js +0 -595
  138. package/dist/core/storage/adapters/indexed-DB.service.js.map +0 -1
  139. package/dist/core/storage/adapters/indexed-DB.service.old.d.ts +0 -38
  140. package/dist/core/storage/adapters/indexed-DB.service.old.d.ts.map +0 -1
  141. package/dist/core/storage/adapters/indexed-DB.service.old.js +0 -318
  142. package/dist/core/storage/adapters/indexed-DB.service.old.js.map +0 -1
  143. package/dist/core/storage/adapters/local-storage.service.d.ts +0 -21
  144. package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
  145. package/dist/core/storage/adapters/local-storage.service.js +0 -99
  146. package/dist/core/storage/adapters/local-storage.service.js.map +0 -1
  147. package/dist/core/storage/adapters/memory-storage.service.d.ts +0 -22
  148. package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
  149. package/dist/core/storage/adapters/memory-storage.service.js +0 -99
  150. package/dist/core/storage/adapters/memory-storage.service.js.map +0 -1
  151. package/dist/core/storage/adapters/path.utils.d.ts +0 -5
  152. package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
  153. package/dist/core/storage/adapters/path.utils.js +0 -35
  154. package/dist/core/storage/adapters/path.utils.js.map +0 -1
  155. package/dist/core/storage/index.d.ts +0 -11
  156. package/dist/core/storage/index.d.ts.map +0 -1
  157. package/dist/core/storage/index.js +0 -12
  158. package/dist/core/storage/index.js.map +0 -1
  159. package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -9
  160. package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
  161. package/dist/core/storage/middlewares/broadcast.middleware.js +0 -115
  162. package/dist/core/storage/middlewares/broadcast.middleware.js.map +0 -1
  163. package/dist/core/storage/middlewares/index.d.ts +0 -4
  164. package/dist/core/storage/middlewares/index.d.ts.map +0 -1
  165. package/dist/core/storage/middlewares/index.js +0 -3
  166. package/dist/core/storage/middlewares/index.js.map +0 -1
  167. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -7
  168. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
  169. package/dist/core/storage/middlewares/storage-batching.middleware.js +0 -36
  170. package/dist/core/storage/middlewares/storage-batching.middleware.js.map +0 -1
  171. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -7
  172. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
  173. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +0 -46
  174. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +0 -1
  175. package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
  176. package/dist/core/storage/modules/plugin/plugin.interface.js +0 -2
  177. package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
  178. package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -25
  179. package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
  180. package/dist/core/storage/modules/plugin/plugin.service.js +0 -186
  181. package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
  182. package/dist/core/storage/storage.interface.d.ts +0 -70
  183. package/dist/core/storage/storage.interface.d.ts.map +0 -1
  184. package/dist/core/storage/storage.interface.js +0 -10
  185. package/dist/core/storage/storage.interface.js.map +0 -1
  186. package/dist/core/storage/utils/batch.utils.d.ts +0 -33
  187. package/dist/core/storage/utils/batch.utils.d.ts.map +0 -1
  188. package/dist/core/storage/utils/batch.utils.js +0 -88
  189. package/dist/core/storage/utils/batch.utils.js.map +0 -1
  190. package/dist/core/storage/utils/broadcast.util.d.ts +0 -48
  191. package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
  192. package/dist/core/storage/utils/broadcast.util.js +0 -162
  193. package/dist/core/storage/utils/broadcast.util.js.map +0 -1
  194. package/dist/core/storage/utils/cache.util.d.ts +0 -33
  195. package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
  196. package/dist/core/storage/utils/cache.util.js +0 -47
  197. package/dist/core/storage/utils/cache.util.js.map +0 -1
  198. package/dist/core/storage/utils/middleware-module.d.ts +0 -46
  199. package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
  200. package/dist/core/storage/utils/middleware-module.js +0 -109
  201. package/dist/core/storage/utils/middleware-module.js.map +0 -1
  202. package/dist/core/storage/utils/storage-key.d.ts +0 -11
  203. package/dist/core/storage/utils/storage-key.d.ts.map +0 -1
  204. package/dist/core/storage/utils/storage-key.js +0 -21
  205. package/dist/core/storage/utils/storage-key.js.map +0 -1
  206. package/dist/core/storage/utils/storage.utils.d.ts +0 -17
  207. package/dist/core/storage/utils/storage.utils.d.ts.map +0 -1
  208. package/dist/core/storage/utils/storage.utils.js +0 -57
  209. package/dist/core/storage/utils/storage.utils.js.map +0 -1
  210. package/dist/index.d.ts.map +0 -1
  211. package/dist/react/hooks/index.d.ts +0 -3
  212. package/dist/react/hooks/index.d.ts.map +0 -1
  213. package/dist/react/hooks/index.js +0 -3
  214. package/dist/react/hooks/index.js.map +0 -1
  215. package/dist/react/hooks/useSelector.d.ts +0 -22
  216. package/dist/react/hooks/useSelector.d.ts.map +0 -1
  217. package/dist/react/hooks/useSelector.js +0 -104
  218. package/dist/react/hooks/useSelector.js.map +0 -1
  219. package/dist/react/hooks/useStorageSubscribe.d.ts +0 -12
  220. package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
  221. package/dist/react/hooks/useStorageSubscribe.js +0 -49
  222. package/dist/react/hooks/useStorageSubscribe.js.map +0 -1
  223. package/dist/react/index.d.ts +0 -3
  224. package/dist/react/index.d.ts.map +0 -1
  225. package/dist/react/index.js +0 -3
  226. package/dist/react/index.js.map +0 -1
  227. package/dist/react/utils/createSynapseCtx.d.ts +0 -40
  228. package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
  229. package/dist/react/utils/createSynapseCtx.js +0 -125
  230. package/dist/react/utils/createSynapseCtx.js.map +0 -1
  231. package/dist/react/utils/index.d.ts +0 -2
  232. package/dist/react/utils/index.d.ts.map +0 -1
  233. package/dist/react/utils/index.js +0 -2
  234. package/dist/react/utils/index.js.map +0 -1
  235. package/dist/reactive/dispatcher/dispatcher.module.d.ts +0 -195
  236. package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
  237. package/dist/reactive/dispatcher/dispatcher.module.js +0 -288
  238. package/dist/reactive/dispatcher/dispatcher.module.js.map +0 -1
  239. package/dist/reactive/dispatcher/index.d.ts +0 -3
  240. package/dist/reactive/dispatcher/index.d.ts.map +0 -1
  241. package/dist/reactive/dispatcher/index.js +0 -3
  242. package/dist/reactive/dispatcher/index.js.map +0 -1
  243. package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -2
  244. package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
  245. package/dist/reactive/dispatcher/middlewares/index.js +0 -2
  246. package/dist/reactive/dispatcher/middlewares/index.js.map +0 -1
  247. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -31
  248. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
  249. package/dist/reactive/dispatcher/middlewares/logger.middleware.js +0 -126
  250. package/dist/reactive/dispatcher/middlewares/logger.middleware.js.map +0 -1
  251. package/dist/reactive/effects/effects.module.d.ts +0 -150
  252. package/dist/reactive/effects/effects.module.d.ts.map +0 -1
  253. package/dist/reactive/effects/effects.module.js +0 -277
  254. package/dist/reactive/effects/effects.module.js.map +0 -1
  255. package/dist/reactive/effects/index.d.ts +0 -2
  256. package/dist/reactive/effects/index.d.ts.map +0 -1
  257. package/dist/reactive/effects/index.js +0 -2
  258. package/dist/reactive/effects/index.js.map +0 -1
  259. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -12
  260. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
  261. package/dist/reactive/effects/utils/chunkRequestConsistent.js +0 -16
  262. package/dist/reactive/effects/utils/chunkRequestConsistent.js.map +0 -1
  263. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -12
  264. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
  265. package/dist/reactive/effects/utils/chunkRequestParallel.js +0 -13
  266. package/dist/reactive/effects/utils/chunkRequestParallel.js.map +0 -1
  267. package/dist/reactive/effects/utils/index.d.ts +0 -3
  268. package/dist/reactive/effects/utils/index.d.ts.map +0 -1
  269. package/dist/reactive/effects/utils/index.js +0 -3
  270. package/dist/reactive/effects/utils/index.js.map +0 -1
  271. package/dist/reactive/index.d.ts +0 -3
  272. package/dist/reactive/index.d.ts.map +0 -1
  273. package/dist/reactive/index.js +0 -3
  274. package/dist/reactive/index.js.map +0 -1
  275. package/dist/utils/createSynapse.d.ts +0 -92
  276. package/dist/utils/createSynapse.d.ts.map +0 -1
  277. package/dist/utils/createSynapse.js +0 -79
  278. package/dist/utils/createSynapse.js.map +0 -1
  279. package/dist/utils/index.d.ts +0 -2
  280. package/dist/utils/index.d.ts.map +0 -1
  281. package/dist/utils/index.js +0 -2
  282. 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