synapse-storage 4.1.2 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +142 -12
  2. package/dist/_utils/chunk.util.d.ts +0 -1
  3. package/dist/_utils/deepMerge.util.d.ts +0 -1
  4. package/dist/_utils/error-handling.util.d.ts +0 -1
  5. package/dist/_utils/flatMap.util.d.ts +0 -1
  6. package/dist/_utils/index.d.ts +0 -1
  7. package/dist/_utils/logger-console.util.d.ts +0 -1
  8. package/dist/api/api.module.d.ts +0 -1
  9. package/dist/api/components/endpoint.d.ts +11 -12
  10. package/dist/api/components/endpoint.js.map +1 -1
  11. package/dist/api/components/query-storage.d.ts +0 -1
  12. package/dist/api/components/query-storage.js +1 -1
  13. package/dist/api/components/query-storage.js.map +1 -1
  14. package/dist/api/index.d.ts +0 -1
  15. package/dist/api/types/api.interface.d.ts +0 -1
  16. package/dist/api/types/endpoint.interface.d.ts +0 -1
  17. package/dist/api/types/query.interface.d.ts +0 -1
  18. package/dist/api/utils/api-helpers.d.ts +0 -1
  19. package/dist/{core/storage → api}/utils/cache.util.d.ts +3 -6
  20. package/dist/{core/storage → api}/utils/cache.util.js +4 -7
  21. package/dist/api/utils/cache.util.js.map +1 -0
  22. package/dist/api/utils/create-header-context.d.ts +0 -1
  23. package/dist/api/utils/endpoint-headers.d.ts +0 -1
  24. package/dist/api/utils/fetch-base-query.d.ts +0 -1
  25. package/dist/api/utils/file-utils.d.ts +0 -1
  26. package/dist/api/utils/get-cacheable-headers.d.ts +0 -1
  27. package/dist/core/index.d.ts +0 -1
  28. package/dist/core/selector/index.d.ts +1 -1
  29. package/dist/core/selector/index.js +2 -0
  30. package/dist/core/selector/index.js.map +1 -1
  31. package/dist/core/selector/selector.interface.d.ts +15 -30
  32. package/dist/core/selector/selector.interface.js +2 -2
  33. package/dist/core/selector/selector.interface.js.map +1 -1
  34. package/dist/core/selector/selector.module.d.ts +16 -1
  35. package/dist/core/selector/selector.module.js +82 -20
  36. package/dist/core/selector/selector.module.js.map +1 -1
  37. package/dist/core/selector/selectors.base.d.ts +56 -0
  38. package/dist/core/selector/selectors.base.js +118 -0
  39. package/dist/core/selector/selectors.base.js.map +1 -0
  40. package/dist/core/storage/adapters/async-base-storage.service.d.ts +15 -4
  41. package/dist/core/storage/adapters/async-base-storage.service.js +106 -36
  42. package/dist/core/storage/adapters/async-base-storage.service.js.map +1 -1
  43. package/dist/core/storage/adapters/indexed-DB.service.d.ts +4 -5
  44. package/dist/core/storage/adapters/indexed-DB.service.js +66 -14
  45. package/dist/core/storage/adapters/indexed-DB.service.js.map +1 -1
  46. package/dist/core/storage/adapters/local-storage.service.d.ts +9 -4
  47. package/dist/core/storage/adapters/local-storage.service.js +25 -5
  48. package/dist/core/storage/adapters/local-storage.service.js.map +1 -1
  49. package/dist/core/storage/adapters/memory-storage.service.d.ts +2 -4
  50. package/dist/core/storage/adapters/memory-storage.service.js +5 -5
  51. package/dist/core/storage/adapters/memory-storage.service.js.map +1 -1
  52. package/dist/core/storage/adapters/path.utils.d.ts +0 -1
  53. package/dist/core/storage/adapters/storage-core.d.ts +6 -2
  54. package/dist/core/storage/adapters/storage-core.js +6 -3
  55. package/dist/core/storage/adapters/storage-core.js.map +1 -1
  56. package/dist/core/storage/adapters/sync-base-storage.service.d.ts +20 -4
  57. package/dist/core/storage/adapters/sync-base-storage.service.js +110 -35
  58. package/dist/core/storage/adapters/sync-base-storage.service.js.map +1 -1
  59. package/dist/core/storage/index.d.ts +2 -5
  60. package/dist/core/storage/index.js +1 -5
  61. package/dist/core/storage/index.js.map +1 -1
  62. package/dist/core/storage/middlewares/broadcast.middleware.d.ts +0 -1
  63. package/dist/core/storage/middlewares/index.d.ts +3 -1
  64. package/dist/core/storage/middlewares/index.js +6 -0
  65. package/dist/core/storage/middlewares/index.js.map +1 -1
  66. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts +0 -1
  67. package/dist/core/storage/middlewares/storage-logger.middleware.d.ts +20 -0
  68. package/dist/core/storage/middlewares/storage-logger.middleware.js +53 -0
  69. package/dist/core/storage/middlewares/storage-logger.middleware.js.map +1 -0
  70. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts +0 -1
  71. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js +4 -10
  72. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.js.map +1 -1
  73. package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts +0 -1
  74. package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts +0 -1
  75. package/dist/core/storage/middlewares/sync-storage-logger.middleware.d.ts +7 -0
  76. package/dist/core/storage/middlewares/sync-storage-logger.middleware.js +48 -0
  77. package/dist/core/storage/middlewares/sync-storage-logger.middleware.js.map +1 -0
  78. package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts +0 -1
  79. package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js +4 -10
  80. package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.js.map +1 -1
  81. package/dist/core/storage/modules/singleton/mixin.util.d.ts +0 -1
  82. package/dist/core/storage/modules/singleton/models.d.ts +0 -1
  83. package/dist/core/storage/modules/singleton/singleton.util.d.ts +0 -1
  84. package/dist/core/storage/storage.interface.d.ts +59 -4
  85. package/dist/core/storage/storage.interface.js +0 -2
  86. package/dist/core/storage/storage.interface.js.map +1 -1
  87. package/dist/core/storage/utils/broadcast.util.d.ts +0 -1
  88. package/dist/core/storage/utils/middleware-module.d.ts +0 -3
  89. package/dist/core/storage/utils/middleware-module.js +0 -8
  90. package/dist/core/storage/utils/middleware-module.js.map +1 -1
  91. package/dist/core/storage/utils/migration.util.d.ts +38 -0
  92. package/dist/core/storage/utils/migration.util.js +48 -0
  93. package/dist/core/storage/utils/migration.util.js.map +1 -0
  94. package/dist/core/storage/utils/path-selector.util.d.ts +0 -1
  95. package/dist/core/storage/utils/state-diff.util.d.ts +8 -1
  96. package/dist/core/storage/utils/state-diff.util.js +17 -1
  97. package/dist/core/storage/utils/state-diff.util.js.map +1 -1
  98. package/dist/core/storage/utils/storage-factory.util.d.ts +7 -9
  99. package/dist/core/storage/utils/storage-factory.util.js +10 -10
  100. package/dist/core/storage/utils/storage-factory.util.js.map +1 -1
  101. package/dist/core/storage/utils/storage-key.d.ts +0 -1
  102. package/dist/index.d.ts +0 -1
  103. package/dist/react/hooks/index.d.ts +2 -1
  104. package/dist/react/hooks/index.js +4 -0
  105. package/dist/react/hooks/index.js.map +1 -1
  106. package/dist/react/hooks/useCreateStorage.d.ts +5 -6
  107. package/dist/react/hooks/useCreateStorage.js +2 -2
  108. package/dist/react/hooks/useCreateStorage.js.map +1 -1
  109. package/dist/react/hooks/useObservable.d.ts +17 -0
  110. package/dist/react/hooks/useObservable.js +38 -0
  111. package/dist/react/hooks/useObservable.js.map +1 -0
  112. package/dist/react/hooks/useSelector.d.ts +0 -1
  113. package/dist/react/hooks/useSelector.js +5 -2
  114. package/dist/react/hooks/useSelector.js.map +1 -1
  115. package/dist/react/hooks/useStorage.d.ts +0 -1
  116. package/dist/react/hooks/useStorageSubscribe.d.ts +0 -1
  117. package/dist/react/hooks/useSubscription.d.ts +13 -0
  118. package/dist/react/hooks/useSubscription.js +23 -0
  119. package/dist/react/hooks/useSubscription.js.map +1 -0
  120. package/dist/react/index.d.ts +0 -1
  121. package/dist/react/utils/awaitSynapse.d.ts +9 -10
  122. package/dist/react/utils/awaitSynapse.js +3 -2
  123. package/dist/react/utils/awaitSynapse.js.map +1 -1
  124. package/dist/react/utils/createSynapseCtx.d.ts +18 -23
  125. package/dist/react/utils/createSynapseCtx.js +64 -39
  126. package/dist/react/utils/createSynapseCtx.js.map +1 -1
  127. package/dist/react/utils/index.d.ts +0 -1
  128. package/dist/reactive/dispatcher/dispatcher.base.d.ts +122 -0
  129. package/dist/reactive/dispatcher/dispatcher.base.js +294 -0
  130. package/dist/reactive/dispatcher/dispatcher.base.js.map +1 -0
  131. package/dist/reactive/dispatcher/dispatcher.module.d.ts +12 -67
  132. package/dist/reactive/dispatcher/dispatcher.module.js +13 -72
  133. package/dist/reactive/dispatcher/dispatcher.module.js.map +1 -1
  134. package/dist/reactive/dispatcher/index.d.ts +1 -1
  135. package/dist/reactive/dispatcher/index.js +2 -0
  136. package/dist/reactive/dispatcher/index.js.map +1 -1
  137. package/dist/reactive/dispatcher/middlewares/index.d.ts +0 -1
  138. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts +0 -1
  139. package/dist/reactive/dispatcher/path.util.d.ts +15 -0
  140. package/dist/reactive/dispatcher/path.util.js +34 -0
  141. package/dist/reactive/dispatcher/path.util.js.map +1 -0
  142. package/dist/reactive/dispatcher/standalone.d.ts +1 -150
  143. package/dist/reactive/dispatcher/standalone.js +6 -217
  144. package/dist/reactive/dispatcher/standalone.js.map +1 -1
  145. package/dist/reactive/effects/effects.base.d.ts +62 -0
  146. package/dist/reactive/effects/effects.base.js +90 -0
  147. package/dist/reactive/effects/effects.base.js.map +1 -0
  148. package/dist/reactive/effects/effects.module.d.ts +122 -11
  149. package/dist/reactive/effects/effects.module.js +129 -17
  150. package/dist/reactive/effects/effects.module.js.map +1 -1
  151. package/dist/reactive/effects/index.d.ts +1 -1
  152. package/dist/reactive/effects/index.js +2 -0
  153. package/dist/reactive/effects/index.js.map +1 -1
  154. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts +0 -1
  155. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts +0 -1
  156. package/dist/reactive/effects/utils/fromRequest.d.ts +0 -1
  157. package/dist/reactive/effects/utils/index.d.ts +0 -1
  158. package/dist/reactive/effects/utils/toObservable.d.ts +0 -1
  159. package/dist/reactive/index.d.ts +0 -1
  160. package/dist/utils/createEventBus.d.ts +47 -46
  161. package/dist/utils/createEventBus.js +152 -174
  162. package/dist/utils/createEventBus.js.map +1 -1
  163. package/dist/utils/createSynapse/createSynapse.d.ts +25 -7
  164. package/dist/utils/createSynapse/createSynapse.js +28 -98
  165. package/dist/utils/createSynapse/createSynapse.js.map +1 -1
  166. package/dist/utils/createSynapse/factory.d.ts +6 -0
  167. package/dist/utils/createSynapse/factory.js +256 -0
  168. package/dist/utils/createSynapse/factory.js.map +1 -0
  169. package/dist/utils/createSynapse/index.d.ts +2 -2
  170. package/dist/utils/createSynapse/index.js.map +1 -1
  171. package/dist/utils/createSynapse/synapse.types.d.ts +87 -0
  172. package/dist/utils/createSynapse/synapse.types.js +11 -0
  173. package/dist/utils/createSynapse/synapse.types.js.map +1 -0
  174. package/dist/utils/createSynapse/types.d.ts +6 -85
  175. package/dist/utils/createSynapse/types.js +2 -1
  176. package/dist/utils/createSynapse/types.js.map +1 -1
  177. package/dist/utils/createSynapse/waitForDependencies.d.ts +0 -1
  178. package/dist/utils/createSynapse/waitForDependencies.js +1 -1
  179. package/dist/utils/createSynapse/waitForDependencies.js.map +1 -1
  180. package/dist/utils/createSynapseAwaiter.d.ts +13 -10
  181. package/dist/utils/createSynapseAwaiter.js +30 -3
  182. package/dist/utils/createSynapseAwaiter.js.map +1 -1
  183. package/dist/utils/dehydrateModule.d.ts +6 -0
  184. package/dist/utils/dehydrateModule.js +43 -0
  185. package/dist/utils/dehydrateModule.js.map +1 -0
  186. package/dist/utils/index.d.ts +3 -3
  187. package/dist/utils/index.js +3 -0
  188. package/dist/utils/index.js.map +1 -1
  189. package/package.json +12 -2
  190. package/dist/_utils/chunk.util.d.ts.map +0 -1
  191. package/dist/_utils/deepMerge.util.d.ts.map +0 -1
  192. package/dist/_utils/error-handling.util.d.ts.map +0 -1
  193. package/dist/_utils/flatMap.util.d.ts.map +0 -1
  194. package/dist/_utils/index.d.ts.map +0 -1
  195. package/dist/_utils/logger-console.util.d.ts.map +0 -1
  196. package/dist/api/api.module.d.ts.map +0 -1
  197. package/dist/api/components/endpoint.d.ts.map +0 -1
  198. package/dist/api/components/query-storage.d.ts.map +0 -1
  199. package/dist/api/example.d.ts +0 -83
  200. package/dist/api/example.d.ts.map +0 -1
  201. package/dist/api/example.js +0 -90
  202. package/dist/api/example.js.map +0 -1
  203. package/dist/api/index.d.ts.map +0 -1
  204. package/dist/api/types/api.interface.d.ts.map +0 -1
  205. package/dist/api/types/endpoint.interface.d.ts.map +0 -1
  206. package/dist/api/types/query.interface.d.ts.map +0 -1
  207. package/dist/api/utils/api-helpers.d.ts.map +0 -1
  208. package/dist/api/utils/create-header-context.d.ts.map +0 -1
  209. package/dist/api/utils/endpoint-headers.d.ts.map +0 -1
  210. package/dist/api/utils/fetch-base-query.d.ts.map +0 -1
  211. package/dist/api/utils/file-utils.d.ts.map +0 -1
  212. package/dist/api/utils/get-cacheable-headers.d.ts.map +0 -1
  213. package/dist/core/index.d.ts.map +0 -1
  214. package/dist/core/selector/index.d.ts.map +0 -1
  215. package/dist/core/selector/selector.interface.d.ts.map +0 -1
  216. package/dist/core/selector/selector.module.d.ts.map +0 -1
  217. package/dist/core/storage/adapters/async-base-storage.service.d.ts.map +0 -1
  218. package/dist/core/storage/adapters/indexed-DB.service.d.ts.map +0 -1
  219. package/dist/core/storage/adapters/local-storage.service.d.ts.map +0 -1
  220. package/dist/core/storage/adapters/memory-storage.service.d.ts.map +0 -1
  221. package/dist/core/storage/adapters/path.utils.d.ts.map +0 -1
  222. package/dist/core/storage/adapters/storage-core.d.ts.map +0 -1
  223. package/dist/core/storage/adapters/sync-base-storage.service.d.ts.map +0 -1
  224. package/dist/core/storage/index.d.ts.map +0 -1
  225. package/dist/core/storage/middlewares/broadcast.middleware.d.ts.map +0 -1
  226. package/dist/core/storage/middlewares/index.d.ts.map +0 -1
  227. package/dist/core/storage/middlewares/storage-batching.middleware.d.ts.map +0 -1
  228. package/dist/core/storage/middlewares/storage-shallow-compare.middleware.d.ts.map +0 -1
  229. package/dist/core/storage/middlewares/sync-broadcast.middleware.d.ts.map +0 -1
  230. package/dist/core/storage/middlewares/sync-storage-batching.middleware.d.ts.map +0 -1
  231. package/dist/core/storage/middlewares/sync-storage-shallow-compare.middleware.d.ts.map +0 -1
  232. package/dist/core/storage/modules/plugin/plugin.interface.d.ts +0 -101
  233. package/dist/core/storage/modules/plugin/plugin.interface.d.ts.map +0 -1
  234. package/dist/core/storage/modules/plugin/plugin.interface.js +0 -8
  235. package/dist/core/storage/modules/plugin/plugin.interface.js.map +0 -1
  236. package/dist/core/storage/modules/plugin/plugin.service.d.ts +0 -49
  237. package/dist/core/storage/modules/plugin/plugin.service.d.ts.map +0 -1
  238. package/dist/core/storage/modules/plugin/plugin.service.js +0 -406
  239. package/dist/core/storage/modules/plugin/plugin.service.js.map +0 -1
  240. package/dist/core/storage/modules/singleton/mixin.util.d.ts.map +0 -1
  241. package/dist/core/storage/modules/singleton/models.d.ts.map +0 -1
  242. package/dist/core/storage/modules/singleton/singleton.util.d.ts.map +0 -1
  243. package/dist/core/storage/storage.interface.d.ts.map +0 -1
  244. package/dist/core/storage/utils/broadcast.util.d.ts.map +0 -1
  245. package/dist/core/storage/utils/cache.util.d.ts.map +0 -1
  246. package/dist/core/storage/utils/cache.util.js.map +0 -1
  247. package/dist/core/storage/utils/middleware-module.d.ts.map +0 -1
  248. package/dist/core/storage/utils/path-selector.util.d.ts.map +0 -1
  249. package/dist/core/storage/utils/state-diff.util.d.ts.map +0 -1
  250. package/dist/core/storage/utils/storage-factory.util.d.ts.map +0 -1
  251. package/dist/core/storage/utils/storage-key.d.ts.map +0 -1
  252. package/dist/core/storage/utils/storage.utils.d.ts +0 -17
  253. package/dist/core/storage/utils/storage.utils.d.ts.map +0 -1
  254. package/dist/core/storage/utils/storage.utils.js +0 -57
  255. package/dist/core/storage/utils/storage.utils.js.map +0 -1
  256. package/dist/index.d.ts.map +0 -1
  257. package/dist/react/hooks/index.d.ts.map +0 -1
  258. package/dist/react/hooks/useCreateStorage.d.ts.map +0 -1
  259. package/dist/react/hooks/useSelector.d.ts.map +0 -1
  260. package/dist/react/hooks/useStorage.d.ts.map +0 -1
  261. package/dist/react/hooks/useStorageSubscribe.d.ts.map +0 -1
  262. package/dist/react/index.d.ts.map +0 -1
  263. package/dist/react/utils/awaitSynapse.d.ts.map +0 -1
  264. package/dist/react/utils/createSynapseCtx.d.ts.map +0 -1
  265. package/dist/react/utils/index.d.ts.map +0 -1
  266. package/dist/reactive/dispatcher/dispatcher.module.d.ts.map +0 -1
  267. package/dist/reactive/dispatcher/index.d.ts.map +0 -1
  268. package/dist/reactive/dispatcher/middlewares/index.d.ts.map +0 -1
  269. package/dist/reactive/dispatcher/middlewares/logger.middleware.d.ts.map +0 -1
  270. package/dist/reactive/dispatcher/standalone.d.ts.map +0 -1
  271. package/dist/reactive/effects/effects.module.d.ts.map +0 -1
  272. package/dist/reactive/effects/index.d.ts.map +0 -1
  273. package/dist/reactive/effects/utils/chunkRequestConsistent.d.ts.map +0 -1
  274. package/dist/reactive/effects/utils/chunkRequestParallel.d.ts.map +0 -1
  275. package/dist/reactive/effects/utils/fromRequest.d.ts.map +0 -1
  276. package/dist/reactive/effects/utils/index.d.ts.map +0 -1
  277. package/dist/reactive/effects/utils/toObservable.d.ts.map +0 -1
  278. package/dist/reactive/index.d.ts.map +0 -1
  279. package/dist/utils/createEventBus.d.ts.map +0 -1
  280. package/dist/utils/createSynapse/createSynapse.d.ts.map +0 -1
  281. package/dist/utils/createSynapse/index.d.ts.map +0 -1
  282. package/dist/utils/createSynapse/types.d.ts.map +0 -1
  283. package/dist/utils/createSynapse/validate.d.ts +0 -2
  284. package/dist/utils/createSynapse/validate.d.ts.map +0 -1
  285. package/dist/utils/createSynapse/validate.js +0 -76
  286. package/dist/utils/createSynapse/validate.js.map +0 -1
  287. package/dist/utils/createSynapse/waitForDependencies.d.ts.map +0 -1
  288. package/dist/utils/createSynapseAwaiter.d.ts.map +0 -1
  289. package/dist/utils/index.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"core/storage/adapters/memory-storage.service.js","sources":["../../../../src/core/storage/adapters/memory-storage.service.ts"],"sourcesContent":["import { ISyncPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { SingletonMixin } from '../modules/singleton/mixin.util'\nimport { IEventEmitter, ILogger, MemoryStorageConfig, StorageType } from '../storage.interface'\nimport { StorageKey, StorageKeyType } from '../utils/storage-key'\nimport { getValueByPath, parsePath, setValueByPath } from './path.utils'\nimport { SyncBaseStorage } from './sync-base-storage.service'\n\nexport class MemoryStorage<T extends Record<string, any>> extends SyncBaseStorage<T> {\n protected static readonly STORAGE_TYPE: StorageType = 'memory'\n readonly type: StorageType = 'memory'\n\n private storage = new Map<string, any>()\n\n constructor(config: MemoryStorageConfig<T>, pluginExecutor?: ISyncPluginExecutor, eventEmitter?: IEventEmitter, logger?: ILogger) {\n super(config, pluginExecutor, eventEmitter, logger)\n }\n\n static create<T extends Record<string, any>>(\n config: MemoryStorageConfig<T>,\n pluginExecutor?: ISyncPluginExecutor,\n eventEmitter?: IEventEmitter,\n logger?: ILogger,\n ): MemoryStorage<T> {\n return SingletonMixin.handleSingletonCreation(\n config,\n this.STORAGE_TYPE,\n (finalConfig) => new MemoryStorage<T>(finalConfig as MemoryStorageConfig<T>, pluginExecutor, eventEmitter, logger),\n logger,\n )\n }\n\n protected async doInitialize(): Promise<this> {\n try {\n this.logger?.debug(`Initializing MemoryStorage \"${this.name}\"`)\n\n this.initializeMiddlewares()\n this.initializeWithMiddlewares()\n\n this.logger?.debug(`MemoryStorage \"${this.name}\" initialized successfully`)\n return this\n } catch (error) {\n this.logger?.error('Error initializing MemoryStorage', { error })\n throw error\n }\n }\n\n protected doGet(key: StorageKeyType): any {\n const state = this.storage.get(this.name)\n if (!state) return undefined\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n return state[key.valueOf()]\n }\n\n return getValueByPath(state, key)\n }\n\n protected doSet(key: StorageKeyType, value: any): void {\n const state = this.storage.get(this.name) || {}\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n state[key.valueOf()] = value\n this.storage.set(this.name, state)\n return\n }\n\n const newState = setValueByPath({ ...state }, key, value)\n this.storage.set(this.name, newState)\n }\n\n protected doRemove(key: StorageKeyType): boolean {\n const state = this.storage.get(this.name)\n if (!state) return false\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n const rawKey = key.valueOf()\n if (!(rawKey in state)) return false\n delete state[rawKey]\n this.storage.set(this.name, state)\n return true\n }\n\n const pathParts = parsePath(key)\n const parentPath = pathParts.slice(0, -1).join('.')\n const lastKey = pathParts[pathParts.length - 1]\n const parent = parentPath ? getValueByPath(state, parentPath) : state\n\n if (!parent || !(lastKey in parent)) return false\n\n delete parent[lastKey]\n this.storage.set(this.name, state)\n return true\n }\n\n protected doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): void {\n const currentState = this.storage.get(this.name) || {}\n const newState = { ...currentState }\n\n for (const { key, value } of updates) {\n if (key instanceof StorageKey && key.isUnparseable()) {\n newState[key.valueOf()] = value\n } else {\n setValueByPath(newState, key, value)\n }\n }\n\n this.storage.set(this.name, newState)\n }\n\n protected doClear(): void {\n this.storage.delete(this.name)\n }\n\n protected doKeys(): string[] {\n const state = this.storage.get(this.name)\n if (!state) return []\n return Object.keys(state)\n }\n\n protected doHas(key: StorageKeyType): boolean {\n const value = this.doGet(key)\n return value !== undefined\n }\n\n protected async doDestroy(): Promise<void> {\n this.storage.delete(this.name)\n }\n}\n"],"names":["SingletonMixin","StorageKey","getValueByPath","parsePath","setValueByPath","SyncBaseStorage","MemoryStorage","Map","config","pluginExecutor","eventEmitter","logger","finalConfig","error","key","state","undefined","value","newState","rawKey","pathParts","parentPath","lastKey","parent","updates","currentState","Object"],"mappings":";;;;;;;;;AACgE;AAEC;AACO;AACX;AAEtD,MAAMM,aAAaA,SAAwCD,eAAeA;IAC/E,OAA0B,eAA4B,SAAQ;IACrD,OAAoB,SAAQ;IAE7B,UAAU,IAAIE,MAAkB;IAExC,YAAYC,MAA8B,EAAEC,cAAoC,EAAEC,YAA4B,EAAEC,MAAgB,CAAE;QAChI,KAAK,CAACH,QAAQC,gBAAgBC,cAAcC;IAC9C;IAEA,OAAO,OACLH,MAA8B,EAC9BC,cAAoC,EACpCC,YAA4B,EAC5BC,MAAgB,EACE;QAClB,OAAOX,sCAAsC,CAC3CQ,QACA,IAAI,CAAC,YAAY,EACjB,CAACI,cAAgB,IAAIN,aAAaA,CAAIM,aAAuCH,gBAAgBC,cAAcC,SAC3GA;IAEJ;IAEA,MAAgB,eAA8B;QAC5C,IAAI;YACF,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,4BAA4B,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAE9D,IAAI,CAAC,qBAAqB;YAC1B,IAAI,CAAC,yBAAyB;YAE9B,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC;YAC1E,OAAO,IAAI;QACb,EAAE,OAAOE,OAAO;YACd,IAAI,CAAC,MAAM,EAAE,MAAM,oCAAoC;gBAAEA;YAAM;YAC/D,MAAMA;QACR;IACF;IAEU,MAAMC,GAAmB,EAAO;QACxC,MAAMC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;QACxC,IAAI,CAACA,OAAO,OAAOC;QAEnB,IAAIF,eAAeb,UAAUA,IAAIa,IAAI,aAAa,IAAI;YACpD,OAAOC,KAAK,CAACD,IAAI,OAAO,GAAG;QAC7B;QAEA,OAAOZ,cAAcA,CAACa,OAAOD;IAC/B;IAEU,MAAMA,GAAmB,EAAEG,KAAU,EAAQ;QACrD,MAAMF,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;QAE9C,IAAID,eAAeb,UAAUA,IAAIa,IAAI,aAAa,IAAI;YACpDC,KAAK,CAACD,IAAI,OAAO,GAAG,GAAGG;YACvB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAEF;YAC5B;QACF;QAEA,MAAMG,WAAWd,cAAcA,CAAC;YAAE,GAAGW,KAAK;QAAC,GAAGD,KAAKG;QACnD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAEC;IAC9B;IAEU,SAASJ,GAAmB,EAAW;QAC/C,MAAMC,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;QACxC,IAAI,CAACA,OAAO,OAAO;QAEnB,IAAID,eAAeb,UAAUA,IAAIa,IAAI,aAAa,IAAI;YACpD,MAAMK,SAASL,IAAI,OAAO;YAC1B,IAAI,CAAEK,CAAAA,UAAUJ,KAAI,GAAI,OAAO;YAC/B,OAAOA,KAAK,CAACI,OAAO;YACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAEJ;YAC5B,OAAO;QACT;QAEA,MAAMK,YAAYjB,SAASA,CAACW;QAC5B,MAAMO,aAAaD,UAAU,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;QAC/C,MAAME,UAAUF,SAAS,CAACA,UAAU,MAAM,GAAG,EAAE;QAC/C,MAAMG,SAASF,aAAanB,cAAcA,CAACa,OAAOM,cAAcN;QAEhE,IAAI,CAACQ,UAAU,CAAED,CAAAA,WAAWC,MAAK,GAAI,OAAO;QAE5C,OAAOA,MAAM,CAACD,QAAQ;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAEP;QAC5B,OAAO;IACT;IAEU,SAASS,OAAmD,EAAQ;QAC5E,MAAMC,eAAe,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC;QACrD,MAAMP,WAAW;YAAE,GAAGO,YAAY;QAAC;QAEnC,KAAK,MAAM,EAAEX,GAAG,EAAEG,KAAK,EAAE,IAAIO,QAAS;YACpC,IAAIV,eAAeb,UAAUA,IAAIa,IAAI,aAAa,IAAI;gBACpDI,QAAQ,CAACJ,IAAI,OAAO,GAAG,GAAGG;YAC5B,OAAO;gBACLb,cAAcA,CAACc,UAAUJ,KAAKG;YAChC;QACF;QAEA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAEC;IAC9B;IAEU,UAAgB;QACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;IAC/B;IAEU,SAAmB;QAC3B,MAAMH,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;QACxC,IAAI,CAACA,OAAO,OAAO,EAAE;QACrB,OAAOW,OAAO,IAAI,CAACX;IACrB;IAEU,MAAMD,GAAmB,EAAW;QAC5C,MAAMG,QAAQ,IAAI,CAAC,KAAK,CAACH;QACzB,OAAOG,UAAUD;IACnB;IAEA,MAAgB,YAA2B;QACzC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;IAC/B;AACF"}
1
+ {"version":3,"file":"core/storage/adapters/memory-storage.service.js","sources":["../../../../src/core/storage/adapters/memory-storage.service.ts"],"sourcesContent":["import { SingletonMixin } from '../modules/singleton/mixin.util'\nimport { IEventEmitter, ILogger, MemoryStorageConfig, StorageType } from '../storage.interface'\nimport { StorageKey, StorageKeyType } from '../utils/storage-key'\nimport { getValueByPath, parsePath, setValueByPath } from './path.utils'\nimport { SyncBaseStorage } from './sync-base-storage.service'\n\nexport class MemoryStorage<T extends Record<string, any>> extends SyncBaseStorage<T> {\n protected static readonly STORAGE_TYPE: StorageType = 'memory'\n readonly type: StorageType = 'memory'\n\n private storage = new Map<string, any>()\n\n constructor(config: MemoryStorageConfig<T>, eventEmitter?: IEventEmitter, logger?: ILogger) {\n super(config, eventEmitter, logger)\n }\n\n static create<T extends Record<string, any>>(config: MemoryStorageConfig<T>, eventEmitter?: IEventEmitter, logger?: ILogger): MemoryStorage<T> {\n return SingletonMixin.handleSingletonCreation(\n config,\n this.STORAGE_TYPE,\n (finalConfig) => new MemoryStorage<T>(finalConfig as MemoryStorageConfig<T>, eventEmitter, logger),\n logger,\n )\n }\n\n protected async doInitialize(): Promise<this> {\n try {\n this.logger?.debug(`Initializing MemoryStorage \"${this.name}\"`)\n\n this.initializeMiddlewares()\n this.initializeWithMiddlewares()\n\n this.logger?.debug(`MemoryStorage \"${this.name}\" initialized successfully`)\n return this\n } catch (error) {\n this.logger?.error('Error initializing MemoryStorage', { error })\n throw error\n }\n }\n\n protected doGet(key: StorageKeyType): any {\n const state = this.storage.get(this.name)\n if (!state) return undefined\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n return state[key.valueOf()]\n }\n\n return getValueByPath(state, key)\n }\n\n protected doSet(key: StorageKeyType, value: any): void {\n const state = this.storage.get(this.name) || {}\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n state[key.valueOf()] = value\n this.storage.set(this.name, state)\n return\n }\n\n const newState = setValueByPath({ ...state }, key, value)\n this.storage.set(this.name, newState)\n }\n\n protected doRemove(key: StorageKeyType): boolean {\n const state = this.storage.get(this.name)\n if (!state) return false\n\n if (key instanceof StorageKey && key.isUnparseable()) {\n const rawKey = key.valueOf()\n if (!(rawKey in state)) return false\n delete state[rawKey]\n this.storage.set(this.name, state)\n return true\n }\n\n const pathParts = parsePath(key)\n const parentPath = pathParts.slice(0, -1).join('.')\n const lastKey = pathParts[pathParts.length - 1]\n const parent = parentPath ? getValueByPath(state, parentPath) : state\n\n if (!parent || !(lastKey in parent)) return false\n\n delete parent[lastKey]\n this.storage.set(this.name, state)\n return true\n }\n\n protected doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): void {\n const currentState = this.storage.get(this.name) || {}\n const newState = { ...currentState }\n\n for (const { key, value } of updates) {\n if (key instanceof StorageKey && key.isUnparseable()) {\n newState[key.valueOf()] = value\n } else {\n setValueByPath(newState, key, value)\n }\n }\n\n this.storage.set(this.name, newState)\n }\n\n protected doClear(): void {\n this.storage.delete(this.name)\n }\n\n protected doKeys(): string[] {\n const state = this.storage.get(this.name)\n if (!state) return []\n return Object.keys(state)\n }\n\n protected doHas(key: StorageKeyType): boolean {\n const value = this.doGet(key)\n return value !== undefined\n }\n\n protected async doDestroy(): Promise<void> {\n // Очистка управляется флагом config.clearOnDestroy в performCleanup (memory → по умолчанию true).\n }\n}\n"],"names":["SingletonMixin","StorageKey","getValueByPath","parsePath","setValueByPath","SyncBaseStorage","MemoryStorage","Map","config","eventEmitter","logger","finalConfig","error","key","state","undefined","value","newState","rawKey","pathParts","parentPath","lastKey","parent","updates","currentState","Object"],"mappings":"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"}
@@ -2,4 +2,3 @@ import { StorageKey } from '../utils/storage-key';
2
2
  export declare function parsePath(path: string | StorageKey): string[];
3
3
  export declare function getValueByPath(obj: any, path: string | StorageKey): any;
4
4
  export declare function setValueByPath(obj: any, path: string | StorageKey, value: any): any;
5
- //# sourceMappingURL=path.utils.d.ts.map
@@ -25,7 +25,6 @@ export declare abstract class StorageCore<T extends Record<string, any>> impleme
25
25
  private statusSubscribers;
26
26
  protected subscribers: Map<StorageKeyType, Set<(value: any) => void>>;
27
27
  protected _stateCache: T;
28
- protected keyVersions: Map<string, number>;
29
28
  constructor(coreConfig: BaseStorageConfig<T>, eventEmitter?: IEventEmitter | undefined, logger?: ILogger | undefined);
30
29
  get initStatus(): StorageInitStatus;
31
30
  waitForReady(): Promise<this>;
@@ -43,6 +42,12 @@ export declare abstract class StorageCore<T extends Record<string, any>> impleme
43
42
  subscribe<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction;
44
43
  protected abstract subscribeByKey(key: string, callback: (value: any) => void): VoidFunction;
45
44
  protected abstract subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction;
45
+ /**
46
+ * Хук изменения ключа. По умолчанию no-op.
47
+ * Async-хранилища переопределяют для защиты от race condition в subscribeByKey
48
+ * (см. AsyncBaseStorage). Sync версии не нужен — get() синхронный.
49
+ */
50
+ protected trackKeyVersion(_keyStr: string): void;
46
51
  protected notifySubscribers(key: StorageKeyType, value: any): void;
47
52
  initialize(): Promise<this>;
48
53
  /**
@@ -58,4 +63,3 @@ export declare abstract class StorageCore<T extends Record<string, any>> impleme
58
63
  protected abstract performCleanup(): Promise<void>;
59
64
  protected emitEvent(event: StorageEvent): Promise<void>;
60
65
  }
61
- //# sourceMappingURL=storage-core.d.ts.map
@@ -28,7 +28,6 @@ import { StorageEvents, StorageStatus } from "../storage.interface.js";
28
28
  statusSubscribers = new Set();
29
29
  subscribers = new Map();
30
30
  _stateCache = {};
31
- keyVersions = new Map();
32
31
  constructor(coreConfig, eventEmitter, logger){
33
32
  this.coreConfig = coreConfig;
34
33
  this.eventEmitter = eventEmitter;
@@ -119,10 +118,14 @@ import { StorageEvents, StorageStatus } from "../storage.interface.js";
119
118
  }
120
119
  return this.subscribeBySelector(keyOrSelector, callback);
121
120
  }
121
+ /**
122
+ * Хук изменения ключа. По умолчанию no-op.
123
+ * Async-хранилища переопределяют для защиты от race condition в subscribeByKey
124
+ * (см. AsyncBaseStorage). Sync версии не нужен — get() синхронный.
125
+ */ trackKeyVersion(_keyStr) {}
122
126
  notifySubscribers(key, value) {
123
127
  const keyStr = key.toString();
124
- // Инкрементируем версию ключа — используется для защиты от race condition в subscribeByKey (async)
125
- this.keyVersions.set(keyStr, (this.keyVersions.get(keyStr) ?? 0) + 1);
128
+ this.trackKeyVersion(keyStr);
126
129
  const exactSubscribers = this.subscribers.get(keyStr);
127
130
  if (exactSubscribers?.size) {
128
131
  const subscribersCopy = new Set(exactSubscribers);
@@ -1 +1 @@
1
- {"version":3,"file":"core/storage/adapters/storage-core.js","sources":["../../../../src/core/storage/adapters/storage-core.ts"],"sourcesContent":["import { SingletonKeyGenerator, SingletonManager } from '../modules/singleton/singleton.util'\nimport { BaseStorageConfig, IEventEmitter, ILogger, IStorageBase, StorageEvent, StorageEvents, StorageInitStatus, StorageStatus, StorageType } from '../storage.interface'\nimport { StorageKeyType } from '../utils/storage-key'\n\nexport type PathSelector<T, R> = (state: T) => R\n\n/**\n * Общая константа для глобальной подписки.\n * Используется в StorageCore и наследниках.\n */\nexport const GLOBAL_SUBSCRIPTION_KEY = '*'\n\n/**\n * Абстрактный базовый класс с общей инфраструктурой хранилища.\n *\n * Содержит: status management, subscriptions, lifecycle wrappers,\n * state cache, event emission, singleton cleanup.\n *\n * Не содержит: middleware, plugin executor, do* методы, публичные CRUD-операции.\n */\nexport abstract class StorageCore<T extends Record<string, any>> implements IStorageBase<T> {\n name: string\n abstract readonly type: StorageType\n\n private _initStatus: StorageInitStatus = { status: StorageStatus.IDLE }\n private _isDestroyed = false\n private statusSubscribers = new Set<(status: StorageInitStatus) => void>()\n\n protected subscribers = new Map<StorageKeyType, Set<(value: any) => void>>()\n protected _stateCache: T = {} as T\n protected keyVersions = new Map<string, number>()\n\n constructor(\n protected readonly coreConfig: BaseStorageConfig<T>,\n protected readonly eventEmitter?: IEventEmitter,\n protected readonly logger?: ILogger,\n ) {\n this.name = coreConfig.name\n }\n\n // ─── Status Management ──────────────────────────────────────────────────────\n\n get initStatus(): StorageInitStatus {\n return { ...this._initStatus }\n }\n\n async waitForReady(): Promise<this> {\n if (this._initStatus.status === StorageStatus.READY) return this\n if (this._initStatus.status === StorageStatus.ERROR) {\n throw this._initStatus.error || new Error('Storage initialization failed')\n }\n\n return new Promise((resolve, reject) => {\n const unsubscribe = this.onStatusChange((status) => {\n if (status.status === StorageStatus.READY) {\n unsubscribe()\n resolve(this)\n } else if (status.status === StorageStatus.ERROR) {\n unsubscribe()\n reject(status.error || new Error('Storage initialization failed'))\n }\n })\n })\n }\n\n onStatusChange(callback: (status: StorageInitStatus) => void): VoidFunction {\n this.statusSubscribers.add(callback)\n callback(this.initStatus)\n\n return () => {\n this.statusSubscribers.delete(callback)\n }\n }\n\n protected updateInitStatus(update: Partial<StorageInitStatus>): void {\n const previousStatus = this._initStatus.status\n\n this._initStatus = { ...this._initStatus, ...update }\n\n if (previousStatus !== this._initStatus.status) {\n this.logger?.debug(`Storage \"${this.name}\" status changed: ${previousStatus} -> ${this._initStatus.status}`)\n }\n\n const statusCopy = this.initStatus\n this.statusSubscribers.forEach((callback) => {\n try {\n callback(statusCopy)\n } catch (error) {\n this.logger?.error('Error in status change callback', { error })\n }\n })\n }\n\n protected ensureReady(): void {\n if (this._isDestroyed) {\n throw new Error(`Storage \"${this.name}\" has been destroyed`)\n }\n if (this._initStatus.status !== StorageStatus.READY) {\n throw new Error(`Storage \"${this.name}\" is not ready. Current status: ${this._initStatus.status}`)\n }\n }\n\n // ─── State Cache ────────────────────────────────────────────────────────────\n\n public getStateSync(): T {\n return this._stateCache\n }\n\n // ─── Subscriptions ──────────────────────────────────────────────────────────\n\n public subscribeToAll(callback: (event: { type: string; key?: StorageKeyType[] | StorageKeyType; value?: any; changedPaths?: string[] }) => void): VoidFunction {\n if (!this.subscribers.has(GLOBAL_SUBSCRIPTION_KEY)) {\n this.subscribers.set(GLOBAL_SUBSCRIPTION_KEY, new Set())\n }\n\n this.subscribers.get(GLOBAL_SUBSCRIPTION_KEY)!.add(callback)\n\n return () => {\n const subscribers = this.subscribers.get(GLOBAL_SUBSCRIPTION_KEY)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(GLOBAL_SUBSCRIPTION_KEY)\n }\n }\n }\n }\n\n public subscribe(key: string, callback: (value: any) => void): VoidFunction\n public subscribe<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction\n public subscribe<R>(keyOrSelector: string | PathSelector<T, R>, callback: (value: any) => void): VoidFunction {\n if (typeof keyOrSelector === 'string') {\n return this.subscribeByKey(keyOrSelector, callback)\n }\n return this.subscribeBySelector(keyOrSelector, callback)\n }\n\n protected abstract subscribeByKey(key: string, callback: (value: any) => void): VoidFunction\n protected abstract subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction\n\n protected notifySubscribers(key: StorageKeyType, value: any): void {\n const keyStr = key.toString()\n\n // Инкрементируем версию ключа — используется для защиты от race condition в subscribeByKey (async)\n this.keyVersions.set(keyStr, (this.keyVersions.get(keyStr) ?? 0) + 1)\n\n const exactSubscribers = this.subscribers.get(keyStr)\n if (exactSubscribers?.size) {\n const subscribersCopy = new Set(exactSubscribers)\n subscribersCopy.forEach((callback) => {\n try {\n callback(value)\n } catch (error) {\n this.logger?.error('Ошибка в подписчике на колбэк', { key: keyStr, error })\n }\n })\n }\n }\n\n // ─── Lifecycle ──────────────────────────────────────────────────────────────\n\n public async initialize(): Promise<this> {\n if (this._initStatus.status === StorageStatus.READY) return this\n if (this._initStatus.status === StorageStatus.LOADING) return this.waitForReady()\n\n // Allow re-initialization after destroy\n this._isDestroyed = false\n\n this.updateInitStatus({ status: StorageStatus.LOADING, error: undefined })\n\n try {\n await this.performInitialize()\n this.updateInitStatus({ status: StorageStatus.READY, error: undefined })\n return this\n } catch (error) {\n this.updateInitStatus({\n status: StorageStatus.ERROR,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n throw error\n }\n }\n\n /**\n * Subclass-specific initialization.\n * Called inside initialize() wrapper after status is set to LOADING.\n */\n protected abstract performInitialize(): Promise<void>\n\n public async destroy(): Promise<void> {\n if (this._isDestroyed) return\n this._isDestroyed = true\n\n try {\n if (this._initStatus.status === StorageStatus.LOADING) {\n try {\n await this.waitForReady()\n } catch {\n // Инициализация упала — продолжаем destroy\n }\n }\n\n if (this._initStatus.status === StorageStatus.READY) {\n await this.performCleanup()\n }\n\n this.statusSubscribers.clear()\n\n if (this.coreConfig.singleton?.enabled) {\n const key = SingletonKeyGenerator.generate(this.coreConfig as any, this.type)\n SingletonManager.remove(key)\n }\n\n this._stateCache = {} as T\n this.updateInitStatus({ status: StorageStatus.IDLE })\n\n await this.emitEvent({ type: StorageEvents.STORAGE_DESTROY })\n } catch (error) {\n this.logger?.error('Error destroying storage', { error })\n throw error\n }\n }\n\n /**\n * Subclass-specific cleanup during destroy.\n * Should clear storage data, call doDestroy, cleanup middlewares.\n */\n protected abstract performCleanup(): Promise<void>\n\n // ─── Events ─────────────────────────────────────────────────────────────────\n\n protected async emitEvent(event: StorageEvent): Promise<void> {\n try {\n await this.eventEmitter?.emit({\n ...event,\n metadata: {\n ...(event.metadata || {}),\n timestamp: Date.now(),\n storageName: this.name,\n },\n })\n } catch (error) {\n this.logger?.error('Error emitting event', { event, error })\n }\n }\n}\n"],"names":["SingletonKeyGenerator","SingletonManager","StorageEvents","StorageStatus","GLOBAL_SUBSCRIPTION_KEY","StorageCore","Set","Map","coreConfig","eventEmitter","logger","Error","Promise","resolve","reject","unsubscribe","status","callback","update","previousStatus","statusCopy","error","subscribers","keyOrSelector","key","value","keyStr","exactSubscribers","subscribersCopy","undefined","String","event","Date"],"mappings":"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"}
1
+ {"version":3,"file":"core/storage/adapters/storage-core.js","sources":["../../../../src/core/storage/adapters/storage-core.ts"],"sourcesContent":["import { SingletonKeyGenerator, SingletonManager } from '../modules/singleton/singleton.util'\nimport { BaseStorageConfig, IEventEmitter, ILogger, IStorageBase, StorageEvent, StorageEvents, StorageInitStatus, StorageStatus, StorageType } from '../storage.interface'\nimport { StorageKeyType } from '../utils/storage-key'\n\nexport type PathSelector<T, R> = (state: T) => R\n\n/**\n * Общая константа для глобальной подписки.\n * Используется в StorageCore и наследниках.\n */\nexport const GLOBAL_SUBSCRIPTION_KEY = '*'\n\n/**\n * Абстрактный базовый класс с общей инфраструктурой хранилища.\n *\n * Содержит: status management, subscriptions, lifecycle wrappers,\n * state cache, event emission, singleton cleanup.\n *\n * Не содержит: middleware, plugin executor, do* методы, публичные CRUD-операции.\n */\nexport abstract class StorageCore<T extends Record<string, any>> implements IStorageBase<T> {\n name: string\n abstract readonly type: StorageType\n\n private _initStatus: StorageInitStatus = { status: StorageStatus.IDLE }\n private _isDestroyed = false\n private statusSubscribers = new Set<(status: StorageInitStatus) => void>()\n\n protected subscribers = new Map<StorageKeyType, Set<(value: any) => void>>()\n protected _stateCache: T = {} as T\n\n constructor(\n protected readonly coreConfig: BaseStorageConfig<T>,\n protected readonly eventEmitter?: IEventEmitter,\n protected readonly logger?: ILogger,\n ) {\n this.name = coreConfig.name\n }\n\n // ─── Status Management ──────────────────────────────────────────────────────\n\n get initStatus(): StorageInitStatus {\n return { ...this._initStatus }\n }\n\n async waitForReady(): Promise<this> {\n if (this._initStatus.status === StorageStatus.READY) return this\n if (this._initStatus.status === StorageStatus.ERROR) {\n throw this._initStatus.error || new Error('Storage initialization failed')\n }\n\n return new Promise((resolve, reject) => {\n const unsubscribe = this.onStatusChange((status) => {\n if (status.status === StorageStatus.READY) {\n unsubscribe()\n resolve(this)\n } else if (status.status === StorageStatus.ERROR) {\n unsubscribe()\n reject(status.error || new Error('Storage initialization failed'))\n }\n })\n })\n }\n\n onStatusChange(callback: (status: StorageInitStatus) => void): VoidFunction {\n this.statusSubscribers.add(callback)\n callback(this.initStatus)\n\n return () => {\n this.statusSubscribers.delete(callback)\n }\n }\n\n protected updateInitStatus(update: Partial<StorageInitStatus>): void {\n const previousStatus = this._initStatus.status\n\n this._initStatus = { ...this._initStatus, ...update }\n\n if (previousStatus !== this._initStatus.status) {\n this.logger?.debug(`Storage \"${this.name}\" status changed: ${previousStatus} -> ${this._initStatus.status}`)\n }\n\n const statusCopy = this.initStatus\n this.statusSubscribers.forEach((callback) => {\n try {\n callback(statusCopy)\n } catch (error) {\n this.logger?.error('Error in status change callback', { error })\n }\n })\n }\n\n protected ensureReady(): void {\n if (this._isDestroyed) {\n throw new Error(`Storage \"${this.name}\" has been destroyed`)\n }\n if (this._initStatus.status !== StorageStatus.READY) {\n throw new Error(`Storage \"${this.name}\" is not ready. Current status: ${this._initStatus.status}`)\n }\n }\n\n // ─── State Cache ────────────────────────────────────────────────────────────\n\n public getStateSync(): T {\n return this._stateCache\n }\n\n // ─── Subscriptions ──────────────────────────────────────────────────────────\n\n public subscribeToAll(callback: (event: { type: string; key?: StorageKeyType[] | StorageKeyType; value?: any; changedPaths?: string[] }) => void): VoidFunction {\n if (!this.subscribers.has(GLOBAL_SUBSCRIPTION_KEY)) {\n this.subscribers.set(GLOBAL_SUBSCRIPTION_KEY, new Set())\n }\n\n this.subscribers.get(GLOBAL_SUBSCRIPTION_KEY)!.add(callback)\n\n return () => {\n const subscribers = this.subscribers.get(GLOBAL_SUBSCRIPTION_KEY)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(GLOBAL_SUBSCRIPTION_KEY)\n }\n }\n }\n }\n\n public subscribe(key: string, callback: (value: any) => void): VoidFunction\n public subscribe<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction\n public subscribe<R>(keyOrSelector: string | PathSelector<T, R>, callback: (value: any) => void): VoidFunction {\n if (typeof keyOrSelector === 'string') {\n return this.subscribeByKey(keyOrSelector, callback)\n }\n return this.subscribeBySelector(keyOrSelector, callback)\n }\n\n protected abstract subscribeByKey(key: string, callback: (value: any) => void): VoidFunction\n protected abstract subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction\n\n /**\n * Хук изменения ключа. По умолчанию no-op.\n * Async-хранилища переопределяют для защиты от race condition в subscribeByKey\n * (см. AsyncBaseStorage). Sync версии не нужен — get() синхронный.\n */\n protected trackKeyVersion(_keyStr: string): void {}\n\n protected notifySubscribers(key: StorageKeyType, value: any): void {\n const keyStr = key.toString()\n\n this.trackKeyVersion(keyStr)\n\n const exactSubscribers = this.subscribers.get(keyStr)\n if (exactSubscribers?.size) {\n const subscribersCopy = new Set(exactSubscribers)\n subscribersCopy.forEach((callback) => {\n try {\n callback(value)\n } catch (error) {\n this.logger?.error('Ошибка в подписчике на колбэк', { key: keyStr, error })\n }\n })\n }\n }\n\n // ─── Lifecycle ──────────────────────────────────────────────────────────────\n\n public async initialize(): Promise<this> {\n if (this._initStatus.status === StorageStatus.READY) return this\n if (this._initStatus.status === StorageStatus.LOADING) return this.waitForReady()\n\n // Allow re-initialization after destroy\n this._isDestroyed = false\n\n this.updateInitStatus({ status: StorageStatus.LOADING, error: undefined })\n\n try {\n await this.performInitialize()\n this.updateInitStatus({ status: StorageStatus.READY, error: undefined })\n return this\n } catch (error) {\n this.updateInitStatus({\n status: StorageStatus.ERROR,\n error: error instanceof Error ? error : new Error(String(error)),\n })\n throw error\n }\n }\n\n /**\n * Subclass-specific initialization.\n * Called inside initialize() wrapper after status is set to LOADING.\n */\n protected abstract performInitialize(): Promise<void>\n\n public async destroy(): Promise<void> {\n if (this._isDestroyed) return\n this._isDestroyed = true\n\n try {\n if (this._initStatus.status === StorageStatus.LOADING) {\n try {\n await this.waitForReady()\n } catch {\n // Инициализация упала — продолжаем destroy\n }\n }\n\n if (this._initStatus.status === StorageStatus.READY) {\n await this.performCleanup()\n }\n\n this.statusSubscribers.clear()\n\n if (this.coreConfig.singleton?.enabled) {\n const key = SingletonKeyGenerator.generate(this.coreConfig as any, this.type)\n SingletonManager.remove(key)\n }\n\n this._stateCache = {} as T\n this.updateInitStatus({ status: StorageStatus.IDLE })\n\n await this.emitEvent({ type: StorageEvents.STORAGE_DESTROY })\n } catch (error) {\n this.logger?.error('Error destroying storage', { error })\n throw error\n }\n }\n\n /**\n * Subclass-specific cleanup during destroy.\n * Should clear storage data, call doDestroy, cleanup middlewares.\n */\n protected abstract performCleanup(): Promise<void>\n\n // ─── Events ─────────────────────────────────────────────────────────────────\n\n protected async emitEvent(event: StorageEvent): Promise<void> {\n try {\n await this.eventEmitter?.emit({\n ...event,\n metadata: {\n ...(event.metadata || {}),\n timestamp: Date.now(),\n storageName: this.name,\n },\n })\n } catch (error) {\n this.logger?.error('Error emitting event', { event, error })\n }\n }\n}\n"],"names":["SingletonKeyGenerator","SingletonManager","StorageEvents","StorageStatus","GLOBAL_SUBSCRIPTION_KEY","StorageCore","Set","Map","coreConfig","eventEmitter","logger","Error","Promise","resolve","reject","unsubscribe","status","callback","update","previousStatus","statusCopy","error","subscribers","keyOrSelector","_keyStr","key","value","keyStr","exactSubscribers","subscribersCopy","undefined","String","event","Date"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- import { ISyncPluginExecutor } from '../modules/plugin/plugin.interface';
2
1
  import { IEventEmitter, ILogger, ISyncStorage, StorageType, SyncDefaultMiddlewares, SyncStorageConfig } from '../storage.interface';
3
2
  import { StorageKeyType } from '../utils/storage-key';
4
3
  import { PathSelector, StorageCore } from './storage-core';
@@ -11,12 +10,11 @@ import { PathSelector, StorageCore } from './storage-core';
11
10
  */
12
11
  export declare abstract class SyncBaseStorage<T extends Record<string, any>> extends StorageCore<T> implements ISyncStorage<T> {
13
12
  protected readonly config: SyncStorageConfig<T>;
14
- protected readonly pluginExecutor?: ISyncPluginExecutor | undefined;
15
13
  abstract readonly type: StorageType;
16
14
  private middlewareModule;
17
15
  private initializedMiddlewares;
18
16
  private selectorPathCache;
19
- constructor(config: SyncStorageConfig<T>, pluginExecutor?: ISyncPluginExecutor | undefined, eventEmitter?: IEventEmitter, logger?: ILogger);
17
+ constructor(config: SyncStorageConfig<T>, eventEmitter?: IEventEmitter, logger?: ILogger);
20
18
  protected abstract doGet(key: StorageKeyType): any;
21
19
  protected abstract doSet(key: StorageKeyType, value: any): void;
22
20
  protected abstract doUpdate(updates: Array<{
@@ -32,10 +30,21 @@ export declare abstract class SyncBaseStorage<T extends Record<string, any>> ext
32
30
  /** Lifecycle — всегда async */
33
31
  protected abstract doDestroy(): Promise<void>;
34
32
  protected performInitialize(): Promise<void>;
33
+ /**
34
+ * Дефолт для `config.clearOnDestroy`, если он не задан.
35
+ * Memory: `true` (эфемерное). LocalStorage переопределяет на `false` (персистентное).
36
+ */
37
+ protected get clearOnDestroyDefault(): boolean;
35
38
  protected performCleanup(): Promise<void>;
36
39
  protected initializeMiddlewares(): void;
37
40
  protected getDefaultMiddleware(): SyncDefaultMiddlewares;
38
41
  protected initializeWithMiddlewares(): void;
42
+ /** Читает сохранённую версию схемы. По умолчанию `undefined` (эфемерные хранилища). */
43
+ protected readPersistedVersion(): number | undefined;
44
+ /** Сохраняет версию схемы рядом с данными. По умолчанию no-op (эфемерные хранилища). */
45
+ protected writePersistedVersion(_version: number): void;
46
+ /** Удаляет сохранённую версию схемы (вызывается при destroy с `clearOnDestroy`). */
47
+ protected clearPersistedVersion(): void;
39
48
  private getRawState;
40
49
  get<R>(key: StorageKeyType): R | undefined;
41
50
  set<R>(key: StorageKeyType, value: R): void;
@@ -43,6 +52,14 @@ export declare abstract class SyncBaseStorage<T extends Record<string, any>> ext
43
52
  remove(key: StorageKeyType): void;
44
53
  clear(): void;
45
54
  reset(): void;
55
+ /**
56
+ * SSR-гидрация: заменяет всё состояние переданным снапшотом. Намеренно НЕ требует
57
+ * `ready()` — типичный сценарий вызвать её до `initialize()`, чтобы инициализация
58
+ * не перезатёрла серверное состояние `initialState`-ом (см. `initializeWithMiddlewares`).
59
+ */
60
+ hydrate(state: T): void;
61
+ /** Уведомляет подписчиков о замене состояния гидрацией (no-op до initialize/без подписок). */
62
+ private notifyHydration;
46
63
  keys(): string[];
47
64
  has(key: StorageKeyType): boolean;
48
65
  getState(): T;
@@ -53,4 +70,3 @@ export declare abstract class SyncBaseStorage<T extends Record<string, any>> ext
53
70
  protected subscribeByKey(key: string, callback: (value: any) => void): VoidFunction;
54
71
  protected subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction;
55
72
  }
56
- //# sourceMappingURL=sync-base-storage.service.d.ts.map
@@ -1,7 +1,9 @@
1
1
  import { syncBatchingMiddleware } from "../middlewares/sync-storage-batching.middleware.js";
2
+ import { syncLoggerMiddleware } from "../middlewares/sync-storage-logger.middleware.js";
2
3
  import { syncShallowCompareMiddleware } from "../middlewares/sync-storage-shallow-compare.middleware.js";
3
4
  import { StorageEvents } from "../storage.interface.js";
4
5
  import { SyncMiddlewareModule, VALUE_NOT_CHANGED } from "../utils/middleware-module.js";
6
+ import { decideMigration } from "../utils/migration.util.js";
5
7
  import { createDummyState, extractPath } from "../utils/path-selector.util.js";
6
8
  import { createLazyClone, findChangedPaths, isEqual } from "../utils/state-diff.util.js";
7
9
  import { getValueByPath } from "./path.utils.js";
@@ -22,6 +24,10 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
22
24
 
23
25
 
24
26
 
27
+
28
+
29
+
30
+
25
31
 
26
32
  /**
27
33
  * Базовый класс для синхронных хранилищ (Memory, LocalStorage).
@@ -31,12 +37,11 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
31
37
  * subscribeByKey упрощён — нет race condition без async get.
32
38
  */ class SyncBaseStorage extends StorageCore {
33
39
  config;
34
- pluginExecutor;
35
40
  middlewareModule;
36
41
  initializedMiddlewares = null;
37
42
  selectorPathCache = new WeakMap();
38
- constructor(config, pluginExecutor, eventEmitter, logger){
39
- super(config, eventEmitter, logger), this.config = config, this.pluginExecutor = pluginExecutor;
43
+ constructor(config, eventEmitter, logger){
44
+ super(config, eventEmitter, logger), this.config = config;
40
45
  this.middlewareModule = new SyncMiddlewareModule({
41
46
  getState: ()=>this.getRawState(),
42
47
  doGet: this.doGet.bind(this),
@@ -53,10 +58,18 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
53
58
  await this.doInitialize();
54
59
  this._stateCache = this.getRawState();
55
60
  }
61
+ /**
62
+ * Дефолт для `config.clearOnDestroy`, если он не задан.
63
+ * Memory: `true` (эфемерное). LocalStorage переопределяет на `false` (персистентное).
64
+ */ get clearOnDestroyDefault() {
65
+ return true;
66
+ }
56
67
  async performCleanup() {
57
68
  // Обходим публичный clear() (избегая ensureReady после _isDestroyed = true)
58
- this.pluginExecutor?.executeOnClear();
59
- this.doClear();
69
+ if (this.config.clearOnDestroy ?? this.clearOnDestroyDefault) {
70
+ this.doClear();
71
+ this.clearPersistedVersion();
72
+ }
60
73
  await this.doDestroy();
61
74
  if (this.initializedMiddlewares) {
62
75
  this.initializedMiddlewares.forEach((m)=>m.cleanup?.());
@@ -73,18 +86,59 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
73
86
  getDefaultMiddleware() {
74
87
  return {
75
88
  batching: (options = {})=>syncBatchingMiddleware(options),
76
- shallowCompare: (options = {})=>syncShallowCompareMiddleware(options)
89
+ shallowCompare: (options = {})=>syncShallowCompareMiddleware(options),
90
+ logger: (options = {})=>syncLoggerMiddleware(options)
77
91
  };
78
92
  }
79
93
  initializeWithMiddlewares() {
80
94
  try {
81
95
  const state = this.getRawState();
82
96
  const hasExistingState = Object.keys(state).length > 0;
83
- if (!hasExistingState && this.config.initialState) {
84
- this.middlewareModule.dispatch({
85
- type: 'init',
86
- value: this.config.initialState
87
- });
97
+ // Миграция выключена (version не задан) — прежнее поведение: засеять initialState на пустом.
98
+ if (this.config.version === undefined) {
99
+ if (!hasExistingState && this.config.initialState) {
100
+ this.middlewareModule.dispatch({
101
+ type: 'init',
102
+ value: this.config.initialState
103
+ });
104
+ }
105
+ return;
106
+ }
107
+ const decision = decideMigration({
108
+ hasExisting: hasExistingState,
109
+ existingState: state,
110
+ persistedVersion: this.readPersistedVersion(),
111
+ targetVersion: this.config.version,
112
+ migrate: this.config.migrate
113
+ });
114
+ switch(decision.kind){
115
+ case 'seed':
116
+ {
117
+ if (this.config.initialState) {
118
+ this.middlewareModule.dispatch({
119
+ type: 'init',
120
+ value: this.config.initialState
121
+ });
122
+ }
123
+ this.writePersistedVersion(this.config.version);
124
+ break;
125
+ }
126
+ case 'migrate':
127
+ {
128
+ this.middlewareModule.dispatch({
129
+ type: 'reset',
130
+ value: decision.state
131
+ });
132
+ this.writePersistedVersion(this.config.version);
133
+ break;
134
+ }
135
+ case 'bump':
136
+ {
137
+ this.writePersistedVersion(this.config.version);
138
+ break;
139
+ }
140
+ case 'none':
141
+ break;
88
142
  }
89
143
  } catch (error) {
90
144
  this.logger?.error('Ошибка инициализации хранилища', {
@@ -93,6 +147,12 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
93
147
  throw error;
94
148
  }
95
149
  }
150
+ // ─── Persisted schema version (persist-migration) ───────────────────────────
151
+ /** Читает сохранённую версию схемы. По умолчанию `undefined` (эфемерные хранилища). */ readPersistedVersion() {
152
+ return undefined;
153
+ }
154
+ /** Сохраняет версию схемы рядом с данными. По умолчанию no-op (эфемерные хранилища). */ writePersistedVersion(_version) {}
155
+ /** Удаляет сохранённую версию схемы (вызывается при destroy с `clearOnDestroy`). */ clearPersistedVersion() {}
96
156
  // ─── Internal state access ──────────────────────────────────────────────────
97
157
  getRawState() {
98
158
  try {
@@ -114,19 +174,12 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
114
174
  timestamp: Date.now(),
115
175
  key
116
176
  };
117
- const middlewareResult = this.middlewareModule.dispatch({
177
+ const finalResult = this.middlewareModule.dispatch({
118
178
  type: 'get',
119
179
  key,
120
180
  metadata
121
181
  });
122
- const finalResult = this.pluginExecutor?.executeAfterGet(key, middlewareResult, metadata) ?? middlewareResult;
123
- this.emitEvent({
124
- type: StorageEvents.STORAGE_SELECT,
125
- payload: {
126
- key,
127
- value: finalResult
128
- }
129
- });
182
+ // Чтения не эмитят событий это горячий путь, а STORAGE_SELECT нигде не потребляется.
130
183
  return finalResult;
131
184
  } catch (error) {
132
185
  this.logger?.error('Error getting value', {
@@ -144,15 +197,13 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
144
197
  timestamp: Date.now(),
145
198
  key
146
199
  };
147
- const processedValue = this.pluginExecutor?.executeBeforeSet(value, metadata) ?? value;
148
- const middlewareResult = this.middlewareModule.dispatch({
200
+ const finalResult = this.middlewareModule.dispatch({
149
201
  type: 'set',
150
202
  key,
151
- value: processedValue,
203
+ value,
152
204
  metadata
153
205
  });
154
- if (middlewareResult === VALUE_NOT_CHANGED) return;
155
- const finalResult = this.pluginExecutor?.executeAfterSet(key, middlewareResult, metadata) ?? middlewareResult;
206
+ if (finalResult === VALUE_NOT_CHANGED) return;
156
207
  this._stateCache = this.getRawState();
157
208
  const keyStr = key.toString();
158
209
  const changedPaths = [
@@ -204,14 +255,9 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
204
255
  changedTopLevelKeys.add(path.split('.')[0]);
205
256
  }
206
257
  const updates = Array.from(changedTopLevelKeys).map((key)=>{
207
- const keyMetadata = {
208
- ...metadata,
209
- key
210
- };
211
- const processedValue = this.pluginExecutor?.executeBeforeSet(newState[key], keyMetadata) ?? newState[key];
212
258
  return {
213
259
  key,
214
- value: processedValue
260
+ value: newState[key]
215
261
  };
216
262
  });
217
263
  const result = this.middlewareModule.dispatch({
@@ -302,15 +348,12 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
302
348
  timestamp: Date.now(),
303
349
  key
304
350
  };
305
- const preventDeletion = this.pluginExecutor?.executeBeforeDelete(key, metadata);
306
- if (preventDeletion === false) return;
307
351
  const middlewareResult = this.middlewareModule.dispatch({
308
352
  type: 'delete',
309
353
  key,
310
354
  metadata
311
355
  });
312
356
  if (middlewareResult === false) return;
313
- this.pluginExecutor?.executeAfterDelete(key, metadata);
314
357
  this._stateCache = this.getRawState();
315
358
  const keyStr = key.toString();
316
359
  const changedPaths = [
@@ -344,7 +387,6 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
344
387
  clear() {
345
388
  this.ensureReady();
346
389
  try {
347
- this.pluginExecutor?.executeOnClear();
348
390
  this.middlewareModule.dispatch({
349
391
  type: 'clear'
350
392
  });
@@ -385,6 +427,39 @@ import { GLOBAL_SUBSCRIPTION_KEY, StorageCore } from "./storage-core.js";
385
427
  throw error;
386
428
  }
387
429
  }
430
+ /**
431
+ * SSR-гидрация: заменяет всё состояние переданным снапшотом. Намеренно НЕ требует
432
+ * `ready()` — типичный сценарий вызвать её до `initialize()`, чтобы инициализация
433
+ * не перезатёрла серверное состояние `initialState`-ом (см. `initializeWithMiddlewares`).
434
+ */ hydrate(state) {
435
+ try {
436
+ this.doSet('', state);
437
+ this._stateCache = this.getRawState();
438
+ // Если включён persist-migration — фиксируем текущую версию: серверный снапшот
439
+ // уже в актуальной схеме, миграцию на нём запускать не нужно.
440
+ if (this.config.version !== undefined) {
441
+ this.writePersistedVersion(this.config.version);
442
+ }
443
+ this.notifyHydration(this._stateCache);
444
+ } catch (error) {
445
+ this.logger?.error('Error hydrating storage', {
446
+ error
447
+ });
448
+ throw error;
449
+ }
450
+ }
451
+ /** Уведомляет подписчиков о замене состояния гидрацией (no-op до initialize/без подписок). */ notifyHydration(state) {
452
+ const changedPaths = Object.keys(state);
453
+ for (const key of changedPaths){
454
+ this.notifySubscribers(key, state[key]);
455
+ }
456
+ this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {
457
+ type: StorageEvents.STORAGE_UPDATE,
458
+ key: changedPaths,
459
+ value: state,
460
+ changedPaths
461
+ });
462
+ }
388
463
  keys() {
389
464
  this.ensureReady();
390
465
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"core/storage/adapters/sync-base-storage.service.js","sources":["../../../../src/core/storage/adapters/sync-base-storage.service.ts"],"sourcesContent":["import { syncBatchingMiddleware } from '../middlewares/sync-storage-batching.middleware'\nimport { syncShallowCompareMiddleware } from '../middlewares/sync-storage-shallow-compare.middleware'\nimport { ISyncPluginExecutor } from '../modules/plugin/plugin.interface'\nimport { IEventEmitter, ILogger, ISyncStorage, StorageEvents, StorageType, SyncDefaultMiddlewares, SyncStorageConfig } from '../storage.interface'\nimport { SyncMiddleware, SyncMiddlewareModule, VALUE_NOT_CHANGED } from '../utils/middleware-module'\nimport { createDummyState, extractPath } from '../utils/path-selector.util'\nimport { createLazyClone, findChangedPaths, isEqual } from '../utils/state-diff.util'\nimport { StorageKeyType } from '../utils/storage-key'\nimport { getValueByPath } from './path.utils'\nimport { GLOBAL_SUBSCRIPTION_KEY, PathSelector, StorageCore } from './storage-core'\n\n/**\n * Базовый класс для синхронных хранилищ (Memory, LocalStorage).\n *\n * Все CRUD-операции выполняются синхронно.\n * Lifecycle (initialize, destroy) остаётся async.\n * subscribeByKey упрощён — нет race condition без async get.\n */\nexport abstract class SyncBaseStorage<T extends Record<string, any>> extends StorageCore<T> implements ISyncStorage<T> {\n abstract readonly type: StorageType\n\n private middlewareModule: SyncMiddlewareModule\n private initializedMiddlewares: SyncMiddleware[] | null = null\n private selectorPathCache = new WeakMap<PathSelector<any, any>, string>()\n\n constructor(\n protected readonly config: SyncStorageConfig<T>,\n protected readonly pluginExecutor?: ISyncPluginExecutor,\n eventEmitter?: IEventEmitter,\n logger?: ILogger,\n ) {\n super(config, eventEmitter, logger)\n this.middlewareModule = new SyncMiddlewareModule({\n getState: () => this.getRawState(),\n doGet: this.doGet.bind(this),\n doSet: this.doSet.bind(this),\n doUpdate: this.doUpdate.bind(this),\n doRemove: this.doRemove.bind(this),\n doClear: this.doClear.bind(this),\n doKeys: this.doKeys.bind(this),\n notifySubscribers: this.notifySubscribers.bind(this),\n })\n }\n\n // ─── Abstract sync do* methods ──────────────────────────────────────────────\n\n protected abstract doGet(key: StorageKeyType): any\n protected abstract doSet(key: StorageKeyType, value: any): void\n protected abstract doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): void\n protected abstract doRemove(key: StorageKeyType): boolean\n protected abstract doClear(): void\n protected abstract doKeys(): string[]\n protected abstract doHas(key: StorageKeyType): boolean\n\n /** Lifecycle — всегда async */\n protected abstract doInitialize(): Promise<this>\n /** Lifecycle — всегда async */\n protected abstract doDestroy(): Promise<void>\n\n // ─── Lifecycle hooks ────────────────────────────────────────────────────────\n\n protected async performInitialize(): Promise<void> {\n await this.doInitialize()\n this._stateCache = this.getRawState()\n }\n\n protected async performCleanup(): Promise<void> {\n // Обходим публичный clear() (избегая ensureReady после _isDestroyed = true)\n this.pluginExecutor?.executeOnClear()\n this.doClear()\n\n await this.doDestroy()\n\n if (this.initializedMiddlewares) {\n this.initializedMiddlewares.forEach((m) => m.cleanup?.())\n this.initializedMiddlewares = null\n }\n }\n\n // ─── Middleware initialization ──────────────────────────────────────────────\n\n protected initializeMiddlewares(): void {\n if (this.config.middlewares && !this.initializedMiddlewares) {\n this.initializedMiddlewares = this.config.middlewares(() => this.getDefaultMiddleware())\n this.initializedMiddlewares.forEach((middleware) => this.middlewareModule.use(middleware))\n }\n }\n\n protected getDefaultMiddleware(): SyncDefaultMiddlewares {\n return {\n batching: (options = {}) => syncBatchingMiddleware(options),\n shallowCompare: (options = {}) => syncShallowCompareMiddleware(options),\n }\n }\n\n protected initializeWithMiddlewares(): void {\n try {\n const state = this.getRawState()\n const hasExistingState = Object.keys(state).length > 0\n\n if (!hasExistingState && this.config.initialState) {\n this.middlewareModule.dispatch({\n type: 'init',\n value: this.config.initialState,\n })\n }\n } catch (error) {\n this.logger?.error('Ошибка инициализации хранилища', { error })\n throw error\n }\n }\n\n // ─── Internal state access ──────────────────────────────────────────────────\n\n private getRawState(): T {\n try {\n const value = this.doGet('')\n return value || {}\n } catch (error) {\n this.logger?.error('Error getting state', { error })\n throw error\n }\n }\n\n // ─── Public sync API ────────────────────────────────────────────────────────\n\n public get<R>(key: StorageKeyType): R | undefined {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'get', timestamp: Date.now(), key }\n\n const middlewareResult = this.middlewareModule.dispatch({\n type: 'get',\n key,\n metadata,\n })\n\n const finalResult = this.pluginExecutor?.executeAfterGet(key, middlewareResult, metadata) ?? middlewareResult\n\n this.emitEvent({\n type: StorageEvents.STORAGE_SELECT,\n payload: { key, value: finalResult },\n })\n\n return finalResult\n } catch (error) {\n this.logger?.error('Error getting value', { key, error })\n throw error\n }\n }\n\n public set<R>(key: StorageKeyType, value: R): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'set', timestamp: Date.now(), key }\n\n const processedValue = this.pluginExecutor?.executeBeforeSet(value, metadata) ?? value\n\n const middlewareResult = this.middlewareModule.dispatch({\n type: 'set',\n key,\n value: processedValue,\n metadata,\n })\n\n if (middlewareResult === VALUE_NOT_CHANGED) return\n\n const finalResult = this.pluginExecutor?.executeAfterSet(key, middlewareResult, metadata) ?? middlewareResult\n\n this._stateCache = this.getRawState()\n\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n this.notifySubscribers(key, finalResult)\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: finalResult,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: { key, value: finalResult, changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error setting value', { key, error })\n throw error\n }\n }\n\n public update(updater: (state: T) => void): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'update', timestamp: Date.now() }\n\n const currentState = this.getState()\n const newState = createLazyClone(currentState)\n updater(newState)\n\n const changedPaths = findChangedPaths(currentState, newState)\n\n if (changedPaths.size === 0) {\n this.logger?.debug?.('No changes detected in update')\n return\n }\n\n this.logger?.debug?.('Changed paths:', { paths: Array.from(changedPaths) })\n\n const changedTopLevelKeys = new Set<string>()\n for (const path of changedPaths) {\n changedTopLevelKeys.add(path.split('.')[0])\n }\n\n const updates = Array.from(changedTopLevelKeys).map((key) => {\n const keyMetadata = { ...metadata, key }\n const processedValue = this.pluginExecutor?.executeBeforeSet(newState[key], keyMetadata) ?? newState[key]\n return { key, value: processedValue }\n })\n\n const result = this.middlewareModule.dispatch({\n type: 'update',\n value: updates,\n metadata: {\n ...metadata,\n batchUpdate: true,\n changedPaths: Array.from(changedPaths),\n },\n })\n\n let updatedValues: Record<string, any> = {}\n if (Array.isArray(result)) {\n result.forEach((update: any) => {\n if (update && typeof update === 'object' && 'key' in update && 'value' in update) {\n updatedValues[update.key as string] = update.value\n }\n })\n } else if (result && typeof result === 'object') {\n updatedValues = { ...result }\n }\n\n const actuallyChangedKeys = Object.keys(updatedValues).filter((key) => !isEqual(currentState[key], updatedValues[key]))\n\n if (actuallyChangedKeys.length === 0) {\n this.logger?.debug?.('No actual changes after middleware processing')\n return\n }\n\n const finalUpdates: Record<string, any> = {}\n actuallyChangedKeys.forEach((key) => {\n finalUpdates[key] = updatedValues[key]\n })\n\n this.logger?.debug?.('Notifying subscribers about changes:', { keys: actuallyChangedKeys })\n\n this._stateCache = { ...currentState, ...finalUpdates } as T\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key: actuallyChangedKeys,\n value: finalUpdates,\n changedPaths: Array.from(changedPaths),\n })\n\n for (const path of changedPaths) {\n try {\n const topLevelKey = path.split('.')[0]\n if (topLevelKey in finalUpdates) {\n let value\n if (path === topLevelKey) {\n value = finalUpdates[topLevelKey]\n } else {\n const restPath = path.substring(topLevelKey.length + 1)\n value = getValueByPath(finalUpdates[topLevelKey], restPath)\n }\n if (value !== undefined) {\n this.notifySubscribers(path, value)\n }\n }\n } catch (error) {\n this.logger?.error('Error notifying path subscribers', { path, error })\n }\n }\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: {\n state: finalUpdates,\n key: actuallyChangedKeys,\n changedPaths: Array.from(changedPaths),\n },\n })\n } catch (error) {\n this.logger?.error('Error updating state', { error })\n throw error\n }\n }\n\n public remove(key: StorageKeyType): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'delete', timestamp: Date.now(), key }\n\n const preventDeletion = this.pluginExecutor?.executeBeforeDelete(key, metadata)\n if (preventDeletion === false) return\n\n const middlewareResult = this.middlewareModule.dispatch({\n type: 'delete',\n key,\n metadata,\n })\n\n if (middlewareResult === false) return\n\n this.pluginExecutor?.executeAfterDelete(key, metadata)\n\n this._stateCache = this.getRawState()\n\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n this.notifySubscribers(key, undefined)\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: undefined,\n result: middlewareResult,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: { key, value: undefined, result: middlewareResult, changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error deleting value', { key, error })\n throw error\n }\n }\n\n public clear(): void {\n this.ensureReady()\n\n try {\n this.pluginExecutor?.executeOnClear()\n\n this.middlewareModule.dispatch({ type: 'clear' })\n\n this._stateCache = {} as T\n } catch (error) {\n this.logger?.error('Error clearing storage', { error })\n throw error\n }\n }\n\n public reset(): void {\n this.ensureReady()\n\n try {\n const initialState = this.config.initialState\n\n this.middlewareModule.dispatch({\n type: 'reset',\n value: initialState,\n })\n\n this._stateCache = initialState ? ({ ...initialState } as T) : ({} as T)\n\n const changedPaths = Object.keys(this._stateCache)\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_CLEAR,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_CLEAR,\n payload: { changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error resetting storage', { error })\n throw error\n }\n }\n\n public keys(): string[] {\n this.ensureReady()\n\n try {\n return this.middlewareModule.dispatch({ type: 'keys' })\n } catch (error) {\n this.logger?.error('Error getting keys', { error })\n throw error\n }\n }\n\n public has(key: StorageKeyType): boolean {\n this.ensureReady()\n try {\n return this.doHas(key)\n } catch (error) {\n this.logger?.error('Error checking value existence', { key, error })\n throw error\n }\n }\n\n public getState(): T {\n this.ensureReady()\n return this.getRawState()\n }\n\n // ─── Subscriptions (4.4 — simplified for sync) ─────────────────────────────\n\n /**\n * Sync-версия subscribeByKey.\n * Нет race condition (get() синхронный) → не нужен keyVersions tracking.\n */\n protected subscribeByKey(key: string, callback: (value: any) => void): VoidFunction {\n if (!this.subscribers.has(key)) {\n this.subscribers.set(key, new Set())\n }\n this.subscribers.get(key)!.add(callback)\n\n // Синхронно получаем начальное значение и сразу вызываем callback\n try {\n const value = this.get(key)\n callback(value)\n } catch (error) {\n this.logger?.error('Error in initial callback', { key, error })\n }\n\n return () => {\n const subscribers = this.subscribers.get(key)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(key)\n }\n }\n }\n }\n\n protected subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction {\n const dummyState = createDummyState<T>()\n const fullPath = extractPath(pathSelector, dummyState, this.selectorPathCache)\n\n this.logger?.debug?.('Subscribing to path:', { path: fullPath })\n\n // Sync-обёртка: получаем текущее состояние синхронно и применяем селектор\n const wrappedCallback = (value: any) => {\n try {\n if (value === undefined || value === null || typeof value === 'object') {\n const currentState = this.getState()\n const selectedValue = pathSelector(currentState)\n callback(selectedValue as R)\n return\n }\n callback(value as R)\n } catch (error) {\n this.logger?.error('Error in selector callback', { path: fullPath, error })\n callback(value as R)\n }\n }\n\n if (!fullPath) {\n return this.subscribeToAll(() => {\n callback(pathSelector(this.getState()))\n })\n }\n\n return this.subscribeByKey(fullPath, wrappedCallback)\n }\n}\n"],"names":["syncBatchingMiddleware","syncShallowCompareMiddleware","StorageEvents","SyncMiddlewareModule","VALUE_NOT_CHANGED","createDummyState","extractPath","createLazyClone","findChangedPaths","isEqual","getValueByPath","GLOBAL_SUBSCRIPTION_KEY","StorageCore","SyncBaseStorage","WeakMap","config","pluginExecutor","eventEmitter","logger","m","middleware","options","state","hasExistingState","Object","error","value","key","metadata","Date","middlewareResult","finalResult","processedValue","keyStr","changedPaths","updater","currentState","newState","Array","changedTopLevelKeys","Set","path","updates","keyMetadata","result","updatedValues","update","actuallyChangedKeys","finalUpdates","topLevelKey","restPath","undefined","preventDeletion","initialState","callback","subscribers","pathSelector","dummyState","fullPath","wrappedCallback","selectedValue"],"mappings":"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"}
1
+ {"version":3,"file":"core/storage/adapters/sync-base-storage.service.js","sources":["../../../../src/core/storage/adapters/sync-base-storage.service.ts"],"sourcesContent":["import { syncBatchingMiddleware } from '../middlewares/sync-storage-batching.middleware'\nimport { syncLoggerMiddleware } from '../middlewares/sync-storage-logger.middleware'\nimport { syncShallowCompareMiddleware } from '../middlewares/sync-storage-shallow-compare.middleware'\nimport { IEventEmitter, ILogger, ISyncStorage, StorageEvents, StorageType, SyncDefaultMiddlewares, SyncStorageConfig } from '../storage.interface'\nimport { SyncMiddleware, SyncMiddlewareModule, VALUE_NOT_CHANGED } from '../utils/middleware-module'\nimport { decideMigration } from '../utils/migration.util'\nimport { createDummyState, extractPath } from '../utils/path-selector.util'\nimport { createLazyClone, findChangedPaths, isEqual } from '../utils/state-diff.util'\nimport { StorageKeyType } from '../utils/storage-key'\nimport { getValueByPath } from './path.utils'\nimport { GLOBAL_SUBSCRIPTION_KEY, PathSelector, StorageCore } from './storage-core'\n\n/**\n * Базовый класс для синхронных хранилищ (Memory, LocalStorage).\n *\n * Все CRUD-операции выполняются синхронно.\n * Lifecycle (initialize, destroy) остаётся async.\n * subscribeByKey упрощён — нет race condition без async get.\n */\nexport abstract class SyncBaseStorage<T extends Record<string, any>> extends StorageCore<T> implements ISyncStorage<T> {\n abstract readonly type: StorageType\n\n private middlewareModule: SyncMiddlewareModule\n private initializedMiddlewares: SyncMiddleware[] | null = null\n private selectorPathCache = new WeakMap<PathSelector<any, any>, string>()\n\n constructor(\n protected readonly config: SyncStorageConfig<T>,\n eventEmitter?: IEventEmitter,\n logger?: ILogger,\n ) {\n super(config, eventEmitter, logger)\n this.middlewareModule = new SyncMiddlewareModule({\n getState: () => this.getRawState(),\n doGet: this.doGet.bind(this),\n doSet: this.doSet.bind(this),\n doUpdate: this.doUpdate.bind(this),\n doRemove: this.doRemove.bind(this),\n doClear: this.doClear.bind(this),\n doKeys: this.doKeys.bind(this),\n notifySubscribers: this.notifySubscribers.bind(this),\n })\n }\n\n // ─── Abstract sync do* methods ──────────────────────────────────────────────\n\n protected abstract doGet(key: StorageKeyType): any\n protected abstract doSet(key: StorageKeyType, value: any): void\n protected abstract doUpdate(updates: Array<{ key: StorageKeyType; value: any }>): void\n protected abstract doRemove(key: StorageKeyType): boolean\n protected abstract doClear(): void\n protected abstract doKeys(): string[]\n protected abstract doHas(key: StorageKeyType): boolean\n\n /** Lifecycle — всегда async */\n protected abstract doInitialize(): Promise<this>\n /** Lifecycle — всегда async */\n protected abstract doDestroy(): Promise<void>\n\n // ─── Lifecycle hooks ────────────────────────────────────────────────────────\n\n protected async performInitialize(): Promise<void> {\n await this.doInitialize()\n this._stateCache = this.getRawState()\n }\n\n /**\n * Дефолт для `config.clearOnDestroy`, если он не задан.\n * Memory: `true` (эфемерное). LocalStorage переопределяет на `false` (персистентное).\n */\n protected get clearOnDestroyDefault(): boolean {\n return true\n }\n\n protected async performCleanup(): Promise<void> {\n // Обходим публичный clear() (избегая ensureReady после _isDestroyed = true)\n if (this.config.clearOnDestroy ?? this.clearOnDestroyDefault) {\n this.doClear()\n this.clearPersistedVersion()\n }\n\n await this.doDestroy()\n\n if (this.initializedMiddlewares) {\n this.initializedMiddlewares.forEach((m) => m.cleanup?.())\n this.initializedMiddlewares = null\n }\n }\n\n // ─── Middleware initialization ──────────────────────────────────────────────\n\n protected initializeMiddlewares(): void {\n if (this.config.middlewares && !this.initializedMiddlewares) {\n this.initializedMiddlewares = this.config.middlewares(() => this.getDefaultMiddleware())\n this.initializedMiddlewares.forEach((middleware) => this.middlewareModule.use(middleware))\n }\n }\n\n protected getDefaultMiddleware(): SyncDefaultMiddlewares {\n return {\n batching: (options = {}) => syncBatchingMiddleware(options),\n shallowCompare: (options = {}) => syncShallowCompareMiddleware(options),\n logger: (options = {}) => syncLoggerMiddleware(options),\n }\n }\n\n protected initializeWithMiddlewares(): void {\n try {\n const state = this.getRawState()\n const hasExistingState = Object.keys(state).length > 0\n\n // Миграция выключена (version не задан) — прежнее поведение: засеять initialState на пустом.\n if (this.config.version === undefined) {\n if (!hasExistingState && this.config.initialState) {\n this.middlewareModule.dispatch({ type: 'init', value: this.config.initialState })\n }\n return\n }\n\n const decision = decideMigration({\n hasExisting: hasExistingState,\n existingState: state,\n persistedVersion: this.readPersistedVersion(),\n targetVersion: this.config.version,\n migrate: this.config.migrate,\n })\n\n switch (decision.kind) {\n case 'seed': {\n if (this.config.initialState) {\n this.middlewareModule.dispatch({ type: 'init', value: this.config.initialState })\n }\n this.writePersistedVersion(this.config.version)\n break\n }\n case 'migrate': {\n this.middlewareModule.dispatch({ type: 'reset', value: decision.state })\n this.writePersistedVersion(this.config.version)\n break\n }\n case 'bump': {\n this.writePersistedVersion(this.config.version)\n break\n }\n case 'none':\n break\n }\n } catch (error) {\n this.logger?.error('Ошибка инициализации хранилища', { error })\n throw error\n }\n }\n\n // ─── Persisted schema version (persist-migration) ───────────────────────────\n\n /** Читает сохранённую версию схемы. По умолчанию `undefined` (эфемерные хранилища). */\n protected readPersistedVersion(): number | undefined {\n return undefined\n }\n\n /** Сохраняет версию схемы рядом с данными. По умолчанию no-op (эфемерные хранилища). */\n protected writePersistedVersion(_version: number): void {}\n\n /** Удаляет сохранённую версию схемы (вызывается при destroy с `clearOnDestroy`). */\n protected clearPersistedVersion(): void {}\n\n // ─── Internal state access ──────────────────────────────────────────────────\n\n private getRawState(): T {\n try {\n const value = this.doGet('')\n return value || {}\n } catch (error) {\n this.logger?.error('Error getting state', { error })\n throw error\n }\n }\n\n // ─── Public sync API ────────────────────────────────────────────────────────\n\n public get<R>(key: StorageKeyType): R | undefined {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'get', timestamp: Date.now(), key }\n\n const finalResult = this.middlewareModule.dispatch({\n type: 'get',\n key,\n metadata,\n })\n\n // Чтения не эмитят событий — это горячий путь, а STORAGE_SELECT нигде не потребляется.\n return finalResult\n } catch (error) {\n this.logger?.error('Error getting value', { key, error })\n throw error\n }\n }\n\n public set<R>(key: StorageKeyType, value: R): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'set', timestamp: Date.now(), key }\n\n const finalResult = this.middlewareModule.dispatch({\n type: 'set',\n key,\n value,\n metadata,\n })\n\n if (finalResult === VALUE_NOT_CHANGED) return\n\n this._stateCache = this.getRawState()\n\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n this.notifySubscribers(key, finalResult)\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: finalResult,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: { key, value: finalResult, changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error setting value', { key, error })\n throw error\n }\n }\n\n public update(updater: (state: T) => void): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'update', timestamp: Date.now() }\n\n const currentState = this.getState()\n const newState = createLazyClone(currentState)\n updater(newState)\n\n const changedPaths = findChangedPaths(currentState, newState)\n\n if (changedPaths.size === 0) {\n this.logger?.debug?.('No changes detected in update')\n return\n }\n\n this.logger?.debug?.('Changed paths:', { paths: Array.from(changedPaths) })\n\n const changedTopLevelKeys = new Set<string>()\n for (const path of changedPaths) {\n changedTopLevelKeys.add(path.split('.')[0])\n }\n\n const updates = Array.from(changedTopLevelKeys).map((key) => {\n return { key, value: newState[key] }\n })\n\n const result = this.middlewareModule.dispatch({\n type: 'update',\n value: updates,\n metadata: {\n ...metadata,\n batchUpdate: true,\n changedPaths: Array.from(changedPaths),\n },\n })\n\n let updatedValues: Record<string, any> = {}\n if (Array.isArray(result)) {\n result.forEach((update: any) => {\n if (update && typeof update === 'object' && 'key' in update && 'value' in update) {\n updatedValues[update.key as string] = update.value\n }\n })\n } else if (result && typeof result === 'object') {\n updatedValues = { ...result }\n }\n\n const actuallyChangedKeys = Object.keys(updatedValues).filter((key) => !isEqual(currentState[key], updatedValues[key]))\n\n if (actuallyChangedKeys.length === 0) {\n this.logger?.debug?.('No actual changes after middleware processing')\n return\n }\n\n const finalUpdates: Record<string, any> = {}\n actuallyChangedKeys.forEach((key) => {\n finalUpdates[key] = updatedValues[key]\n })\n\n this.logger?.debug?.('Notifying subscribers about changes:', { keys: actuallyChangedKeys })\n\n this._stateCache = { ...currentState, ...finalUpdates } as T\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key: actuallyChangedKeys,\n value: finalUpdates,\n changedPaths: Array.from(changedPaths),\n })\n\n for (const path of changedPaths) {\n try {\n const topLevelKey = path.split('.')[0]\n if (topLevelKey in finalUpdates) {\n let value\n if (path === topLevelKey) {\n value = finalUpdates[topLevelKey]\n } else {\n const restPath = path.substring(topLevelKey.length + 1)\n value = getValueByPath(finalUpdates[topLevelKey], restPath)\n }\n if (value !== undefined) {\n this.notifySubscribers(path, value)\n }\n }\n } catch (error) {\n this.logger?.error('Error notifying path subscribers', { path, error })\n }\n }\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: {\n state: finalUpdates,\n key: actuallyChangedKeys,\n changedPaths: Array.from(changedPaths),\n },\n })\n } catch (error) {\n this.logger?.error('Error updating state', { error })\n throw error\n }\n }\n\n public remove(key: StorageKeyType): void {\n this.ensureReady()\n\n try {\n const metadata = { operation: 'delete', timestamp: Date.now(), key }\n\n const middlewareResult = this.middlewareModule.dispatch({\n type: 'delete',\n key,\n metadata,\n })\n\n if (middlewareResult === false) return\n\n this._stateCache = this.getRawState()\n\n const keyStr = key.toString()\n const changedPaths = [keyStr]\n\n this.notifySubscribers(key, undefined)\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key,\n value: undefined,\n result: middlewareResult,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_UPDATE,\n payload: { key, value: undefined, result: middlewareResult, changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error deleting value', { key, error })\n throw error\n }\n }\n\n public clear(): void {\n this.ensureReady()\n\n try {\n this.middlewareModule.dispatch({ type: 'clear' })\n\n this._stateCache = {} as T\n } catch (error) {\n this.logger?.error('Error clearing storage', { error })\n throw error\n }\n }\n\n public reset(): void {\n this.ensureReady()\n\n try {\n const initialState = this.config.initialState\n\n this.middlewareModule.dispatch({\n type: 'reset',\n value: initialState,\n })\n\n this._stateCache = initialState ? ({ ...initialState } as T) : ({} as T)\n\n const changedPaths = Object.keys(this._stateCache)\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_CLEAR,\n changedPaths,\n })\n\n this.emitEvent({\n type: StorageEvents.STORAGE_CLEAR,\n payload: { changedPaths },\n })\n } catch (error) {\n this.logger?.error('Error resetting storage', { error })\n throw error\n }\n }\n\n /**\n * SSR-гидрация: заменяет всё состояние переданным снапшотом. Намеренно НЕ требует\n * `ready()` — типичный сценарий вызвать её до `initialize()`, чтобы инициализация\n * не перезатёрла серверное состояние `initialState`-ом (см. `initializeWithMiddlewares`).\n */\n public hydrate(state: T): void {\n try {\n this.doSet('', state)\n this._stateCache = this.getRawState()\n\n // Если включён persist-migration — фиксируем текущую версию: серверный снапшот\n // уже в актуальной схеме, миграцию на нём запускать не нужно.\n if (this.config.version !== undefined) {\n this.writePersistedVersion(this.config.version)\n }\n\n this.notifyHydration(this._stateCache)\n } catch (error) {\n this.logger?.error('Error hydrating storage', { error })\n throw error\n }\n }\n\n /** Уведомляет подписчиков о замене состояния гидрацией (no-op до initialize/без подписок). */\n private notifyHydration(state: T): void {\n const changedPaths = Object.keys(state)\n\n for (const key of changedPaths) {\n this.notifySubscribers(key, (state as Record<string, any>)[key])\n }\n\n this.notifySubscribers(GLOBAL_SUBSCRIPTION_KEY, {\n type: StorageEvents.STORAGE_UPDATE,\n key: changedPaths,\n value: state,\n changedPaths,\n })\n }\n\n public keys(): string[] {\n this.ensureReady()\n\n try {\n return this.middlewareModule.dispatch({ type: 'keys' })\n } catch (error) {\n this.logger?.error('Error getting keys', { error })\n throw error\n }\n }\n\n public has(key: StorageKeyType): boolean {\n this.ensureReady()\n try {\n return this.doHas(key)\n } catch (error) {\n this.logger?.error('Error checking value existence', { key, error })\n throw error\n }\n }\n\n public getState(): T {\n this.ensureReady()\n return this.getRawState()\n }\n\n // ─── Subscriptions (4.4 — simplified for sync) ─────────────────────────────\n\n /**\n * Sync-версия subscribeByKey.\n * Нет race condition (get() синхронный) → не нужен keyVersions tracking.\n */\n protected subscribeByKey(key: string, callback: (value: any) => void): VoidFunction {\n if (!this.subscribers.has(key)) {\n this.subscribers.set(key, new Set())\n }\n this.subscribers.get(key)!.add(callback)\n\n // Синхронно получаем начальное значение и сразу вызываем callback\n try {\n const value = this.get(key)\n callback(value)\n } catch (error) {\n this.logger?.error('Error in initial callback', { key, error })\n }\n\n return () => {\n const subscribers = this.subscribers.get(key)\n if (subscribers) {\n subscribers.delete(callback)\n if (subscribers.size === 0) {\n this.subscribers.delete(key)\n }\n }\n }\n }\n\n protected subscribeBySelector<R>(pathSelector: PathSelector<T, R>, callback: (value: R) => void): VoidFunction {\n const dummyState = createDummyState<T>()\n const fullPath = extractPath(pathSelector, dummyState, this.selectorPathCache)\n\n this.logger?.debug?.('Subscribing to path:', { path: fullPath })\n\n // Sync-обёртка: получаем текущее состояние синхронно и применяем селектор\n const wrappedCallback = (value: any) => {\n try {\n if (value === undefined || value === null || typeof value === 'object') {\n const currentState = this.getState()\n const selectedValue = pathSelector(currentState)\n callback(selectedValue as R)\n return\n }\n callback(value as R)\n } catch (error) {\n this.logger?.error('Error in selector callback', { path: fullPath, error })\n callback(value as R)\n }\n }\n\n if (!fullPath) {\n return this.subscribeToAll(() => {\n callback(pathSelector(this.getState()))\n })\n }\n\n return this.subscribeByKey(fullPath, wrappedCallback)\n }\n}\n"],"names":["syncBatchingMiddleware","syncLoggerMiddleware","syncShallowCompareMiddleware","StorageEvents","SyncMiddlewareModule","VALUE_NOT_CHANGED","decideMigration","createDummyState","extractPath","createLazyClone","findChangedPaths","isEqual","getValueByPath","GLOBAL_SUBSCRIPTION_KEY","StorageCore","SyncBaseStorage","WeakMap","config","eventEmitter","logger","m","middleware","options","state","hasExistingState","Object","undefined","decision","error","_version","value","key","metadata","Date","finalResult","keyStr","changedPaths","updater","currentState","newState","Array","changedTopLevelKeys","Set","path","updates","result","updatedValues","update","actuallyChangedKeys","finalUpdates","topLevelKey","restPath","middlewareResult","initialState","callback","subscribers","pathSelector","dummyState","fullPath","wrappedCallback","selectedValue"],"mappings":"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"}