electron-infra-kit 0.0.2

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 (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +302 -0
  3. package/README.zh-CN.md +308 -0
  4. package/dist/core/error/WindowError.d.ts +56 -0
  5. package/dist/core/error/WindowError.js +71 -0
  6. package/dist/core/error/WindowError.js.map +1 -0
  7. package/dist/core/error/WindowError.mjs +71 -0
  8. package/dist/core/error/WindowError.mjs.map +1 -0
  9. package/dist/core/ipc/IpcHandler.d.ts +48 -0
  10. package/dist/core/ipc/IpcHandler.js +59 -0
  11. package/dist/core/ipc/IpcHandler.js.map +1 -0
  12. package/dist/core/ipc/IpcHandler.mjs +59 -0
  13. package/dist/core/ipc/IpcHandler.mjs.map +1 -0
  14. package/dist/core/ipc/IpcRouter.d.ts +70 -0
  15. package/dist/core/ipc/IpcRouter.js +143 -0
  16. package/dist/core/ipc/IpcRouter.js.map +1 -0
  17. package/dist/core/ipc/IpcRouter.mjs +143 -0
  18. package/dist/core/ipc/IpcRouter.mjs.map +1 -0
  19. package/dist/core/ipc/index.d.ts +3 -0
  20. package/dist/core/ipc/index.js +1 -0
  21. package/dist/core/ipc/index.js.map +1 -0
  22. package/dist/core/ipc/index.mjs +1 -0
  23. package/dist/core/ipc/index.mjs.map +1 -0
  24. package/dist/core/ipc/ipc-router.type.d.ts +73 -0
  25. package/dist/core/ipc/transport/index.d.ts +65 -0
  26. package/dist/core/ipc/transport/index.js +229 -0
  27. package/dist/core/ipc/transport/index.js.map +1 -0
  28. package/dist/core/ipc/transport/index.mjs +229 -0
  29. package/dist/core/ipc/transport/index.mjs.map +1 -0
  30. package/dist/core/ipc/transport/ipc.type.d.ts +36 -0
  31. package/dist/core/lifecycle/LifecycleManager.d.ts +66 -0
  32. package/dist/core/lifecycle/LifecycleManager.js +140 -0
  33. package/dist/core/lifecycle/LifecycleManager.js.map +1 -0
  34. package/dist/core/lifecycle/LifecycleManager.mjs +140 -0
  35. package/dist/core/lifecycle/LifecycleManager.mjs.map +1 -0
  36. package/dist/core/message-bus/MessageBus.d.ts +282 -0
  37. package/dist/core/message-bus/MessageBus.js +677 -0
  38. package/dist/core/message-bus/MessageBus.js.map +1 -0
  39. package/dist/core/message-bus/MessageBus.mjs +677 -0
  40. package/dist/core/message-bus/MessageBus.mjs.map +1 -0
  41. package/dist/core/message-bus/MessageBusClient.d.ts +100 -0
  42. package/dist/core/message-bus/MessageBusClient.js +280 -0
  43. package/dist/core/message-bus/MessageBusClient.js.map +1 -0
  44. package/dist/core/message-bus/MessageBusClient.mjs +280 -0
  45. package/dist/core/message-bus/MessageBusClient.mjs.map +1 -0
  46. package/dist/core/message-bus/core/DataStoreManager.d.ts +51 -0
  47. package/dist/core/message-bus/core/DataStoreManager.js +94 -0
  48. package/dist/core/message-bus/core/DataStoreManager.js.map +1 -0
  49. package/dist/core/message-bus/core/DataStoreManager.mjs +94 -0
  50. package/dist/core/message-bus/core/DataStoreManager.mjs.map +1 -0
  51. package/dist/core/message-bus/core/ManagedPort.d.ts +26 -0
  52. package/dist/core/message-bus/core/ManagedPort.js +55 -0
  53. package/dist/core/message-bus/core/ManagedPort.js.map +1 -0
  54. package/dist/core/message-bus/core/ManagedPort.mjs +55 -0
  55. package/dist/core/message-bus/core/ManagedPort.mjs.map +1 -0
  56. package/dist/core/message-bus/core/PortManager.d.ts +47 -0
  57. package/dist/core/message-bus/core/PortManager.js +114 -0
  58. package/dist/core/message-bus/core/PortManager.js.map +1 -0
  59. package/dist/core/message-bus/core/PortManager.mjs +114 -0
  60. package/dist/core/message-bus/core/PortManager.mjs.map +1 -0
  61. package/dist/core/message-bus/core/SubscriptionManager.d.ts +36 -0
  62. package/dist/core/message-bus/core/SubscriptionManager.js +78 -0
  63. package/dist/core/message-bus/core/SubscriptionManager.js.map +1 -0
  64. package/dist/core/message-bus/core/SubscriptionManager.mjs +78 -0
  65. package/dist/core/message-bus/core/SubscriptionManager.mjs.map +1 -0
  66. package/dist/core/message-bus/core/TransactionManager.d.ts +54 -0
  67. package/dist/core/message-bus/core/TransactionManager.js +95 -0
  68. package/dist/core/message-bus/core/TransactionManager.js.map +1 -0
  69. package/dist/core/message-bus/core/TransactionManager.mjs +95 -0
  70. package/dist/core/message-bus/core/TransactionManager.mjs.map +1 -0
  71. package/dist/core/message-bus/core/index.d.ts +5 -0
  72. package/dist/core/message-bus/index.d.ts +4 -0
  73. package/dist/core/message-bus/index.js +1 -0
  74. package/dist/core/message-bus/index.js.map +1 -0
  75. package/dist/core/message-bus/index.mjs +1 -0
  76. package/dist/core/message-bus/index.mjs.map +1 -0
  77. package/dist/core/message-bus/message-bus.type.d.ts +143 -0
  78. package/dist/core/message-bus/message-bus.type.js +26 -0
  79. package/dist/core/message-bus/message-bus.type.js.map +1 -0
  80. package/dist/core/message-bus/message-bus.type.mjs +26 -0
  81. package/dist/core/message-bus/message-bus.type.mjs.map +1 -0
  82. package/dist/core/message-bus/preload.d.ts +16 -0
  83. package/dist/core/message-bus/preload.js +27 -0
  84. package/dist/core/message-bus/preload.js.map +1 -0
  85. package/dist/core/message-bus/preload.mjs +27 -0
  86. package/dist/core/message-bus/preload.mjs.map +1 -0
  87. package/dist/core/message-bus/transport/ITransport.d.ts +40 -0
  88. package/dist/core/message-bus/transport/IpcTransport.d.ts +18 -0
  89. package/dist/core/message-bus/transport/IpcTransport.js +60 -0
  90. package/dist/core/message-bus/transport/IpcTransport.js.map +1 -0
  91. package/dist/core/message-bus/transport/IpcTransport.mjs +60 -0
  92. package/dist/core/message-bus/transport/IpcTransport.mjs.map +1 -0
  93. package/dist/core/message-bus/transport/MessagePortTransport.d.ts +15 -0
  94. package/dist/core/message-bus/transport/MessagePortTransport.js +35 -0
  95. package/dist/core/message-bus/transport/MessagePortTransport.js.map +1 -0
  96. package/dist/core/message-bus/transport/MessagePortTransport.mjs +35 -0
  97. package/dist/core/message-bus/transport/MessagePortTransport.mjs.map +1 -0
  98. package/dist/core/message-bus/transport/index.d.ts +3 -0
  99. package/dist/core/window/IpcSetup.d.ts +50 -0
  100. package/dist/core/window/IpcSetup.js +96 -0
  101. package/dist/core/window/IpcSetup.js.map +1 -0
  102. package/dist/core/window/IpcSetup.mjs +96 -0
  103. package/dist/core/window/IpcSetup.mjs.map +1 -0
  104. package/dist/core/window/WindowCreator.d.ts +66 -0
  105. package/dist/core/window/WindowCreator.js +168 -0
  106. package/dist/core/window/WindowCreator.js.map +1 -0
  107. package/dist/core/window/WindowCreator.mjs +168 -0
  108. package/dist/core/window/WindowCreator.mjs.map +1 -0
  109. package/dist/core/window/WindowManager.d.ts +214 -0
  110. package/dist/core/window/WindowManager.js +583 -0
  111. package/dist/core/window/WindowManager.js.map +1 -0
  112. package/dist/core/window/WindowManager.mjs +583 -0
  113. package/dist/core/window/WindowManager.mjs.map +1 -0
  114. package/dist/core/window/WindowStore.d.ts +136 -0
  115. package/dist/core/window/WindowStore.js +436 -0
  116. package/dist/core/window/WindowStore.js.map +1 -0
  117. package/dist/core/window/WindowStore.mjs +436 -0
  118. package/dist/core/window/WindowStore.mjs.map +1 -0
  119. package/dist/core/window/constants.d.ts +17 -0
  120. package/dist/core/window/constants.js +15 -0
  121. package/dist/core/window/constants.js.map +1 -0
  122. package/dist/core/window/constants.mjs +15 -0
  123. package/dist/core/window/constants.mjs.map +1 -0
  124. package/dist/core/window/core/MetricsManager.d.ts +14 -0
  125. package/dist/core/window/core/MetricsManager.js +27 -0
  126. package/dist/core/window/core/MetricsManager.js.map +1 -0
  127. package/dist/core/window/core/MetricsManager.mjs +27 -0
  128. package/dist/core/window/core/MetricsManager.mjs.map +1 -0
  129. package/dist/core/window/core/PluginExecutor.d.ts +22 -0
  130. package/dist/core/window/core/PluginExecutor.js +110 -0
  131. package/dist/core/window/core/PluginExecutor.js.map +1 -0
  132. package/dist/core/window/core/PluginExecutor.mjs +110 -0
  133. package/dist/core/window/core/PluginExecutor.mjs.map +1 -0
  134. package/dist/core/window/core/WindowContextManager.d.ts +26 -0
  135. package/dist/core/window/core/WindowContextManager.js +59 -0
  136. package/dist/core/window/core/WindowContextManager.js.map +1 -0
  137. package/dist/core/window/core/WindowContextManager.mjs +59 -0
  138. package/dist/core/window/core/WindowContextManager.mjs.map +1 -0
  139. package/dist/core/window/core/WindowLifecycle.d.ts +15 -0
  140. package/dist/core/window/core/WindowLifecycle.js +150 -0
  141. package/dist/core/window/core/WindowLifecycle.js.map +1 -0
  142. package/dist/core/window/core/WindowLifecycle.mjs +150 -0
  143. package/dist/core/window/core/WindowLifecycle.mjs.map +1 -0
  144. package/dist/core/window/core/WindowOperator.d.ts +90 -0
  145. package/dist/core/window/core/WindowOperator.js +154 -0
  146. package/dist/core/window/core/WindowOperator.js.map +1 -0
  147. package/dist/core/window/core/WindowOperator.mjs +154 -0
  148. package/dist/core/window/core/WindowOperator.mjs.map +1 -0
  149. package/dist/core/window/core/WindowRegistry.d.ts +168 -0
  150. package/dist/core/window/core/WindowRegistry.js +331 -0
  151. package/dist/core/window/core/WindowRegistry.js.map +1 -0
  152. package/dist/core/window/core/WindowRegistry.mjs +331 -0
  153. package/dist/core/window/core/WindowRegistry.mjs.map +1 -0
  154. package/dist/core/window/core/WindowStateManager.d.ts +40 -0
  155. package/dist/core/window/core/WindowStateManager.js +110 -0
  156. package/dist/core/window/core/WindowStateManager.js.map +1 -0
  157. package/dist/core/window/core/WindowStateManager.mjs +110 -0
  158. package/dist/core/window/core/WindowStateManager.mjs.map +1 -0
  159. package/dist/core/window/index.d.ts +7 -0
  160. package/dist/core/window/index.js +1 -0
  161. package/dist/core/window/index.js.map +1 -0
  162. package/dist/core/window/index.mjs +1 -0
  163. package/dist/core/window/index.mjs.map +1 -0
  164. package/dist/core/window/window-manager.schema.d.ts +50 -0
  165. package/dist/core/window/window-manager.schema.js +87 -0
  166. package/dist/core/window/window-manager.schema.js.map +1 -0
  167. package/dist/core/window/window-manager.schema.mjs +87 -0
  168. package/dist/core/window/window-manager.schema.mjs.map +1 -0
  169. package/dist/core/window/window-manager.type.d.ts +365 -0
  170. package/dist/index.d.ts +25 -0
  171. package/dist/index.js +33 -0
  172. package/dist/index.js.map +1 -0
  173. package/dist/index.mjs +33 -0
  174. package/dist/index.mjs.map +1 -0
  175. package/dist/index.umd.js +1 -0
  176. package/dist/infrastructure/config/ConfigManager.d.ts +133 -0
  177. package/dist/infrastructure/config/ConfigManager.js +218 -0
  178. package/dist/infrastructure/config/ConfigManager.js.map +1 -0
  179. package/dist/infrastructure/config/ConfigManager.mjs +218 -0
  180. package/dist/infrastructure/config/ConfigManager.mjs.map +1 -0
  181. package/dist/infrastructure/config/index.d.ts +1 -0
  182. package/dist/infrastructure/debug/EnhancedDebugHelper.d.ts +106 -0
  183. package/dist/infrastructure/debug/EnhancedDebugHelper.js +218 -0
  184. package/dist/infrastructure/debug/EnhancedDebugHelper.js.map +1 -0
  185. package/dist/infrastructure/debug/EnhancedDebugHelper.mjs +218 -0
  186. package/dist/infrastructure/debug/EnhancedDebugHelper.mjs.map +1 -0
  187. package/dist/infrastructure/debug/PerformanceMonitor.d.ts +45 -0
  188. package/dist/infrastructure/debug/PerformanceMonitor.js +67 -0
  189. package/dist/infrastructure/debug/PerformanceMonitor.js.map +1 -0
  190. package/dist/infrastructure/debug/PerformanceMonitor.mjs +67 -0
  191. package/dist/infrastructure/debug/PerformanceMonitor.mjs.map +1 -0
  192. package/dist/infrastructure/debug/index.d.ts +22 -0
  193. package/dist/infrastructure/debug/index.js +47 -0
  194. package/dist/infrastructure/debug/index.js.map +1 -0
  195. package/dist/infrastructure/debug/index.mjs +47 -0
  196. package/dist/infrastructure/debug/index.mjs.map +1 -0
  197. package/dist/infrastructure/errors/ErrorCodes.d.ts +74 -0
  198. package/dist/infrastructure/errors/ErrorCodes.js +78 -0
  199. package/dist/infrastructure/errors/ErrorCodes.js.map +1 -0
  200. package/dist/infrastructure/errors/ErrorCodes.mjs +78 -0
  201. package/dist/infrastructure/errors/ErrorCodes.mjs.map +1 -0
  202. package/dist/infrastructure/errors/StandardError.d.ts +61 -0
  203. package/dist/infrastructure/errors/StandardError.js +84 -0
  204. package/dist/infrastructure/errors/StandardError.js.map +1 -0
  205. package/dist/infrastructure/errors/StandardError.mjs +84 -0
  206. package/dist/infrastructure/errors/StandardError.mjs.map +1 -0
  207. package/dist/infrastructure/errors/index.d.ts +13 -0
  208. package/dist/infrastructure/errors/index.js +24 -0
  209. package/dist/infrastructure/errors/index.js.map +1 -0
  210. package/dist/infrastructure/errors/index.mjs +24 -0
  211. package/dist/infrastructure/errors/index.mjs.map +1 -0
  212. package/dist/infrastructure/logger/ElectronLogger.d.ts +39 -0
  213. package/dist/infrastructure/logger/ElectronLogger.js +65 -0
  214. package/dist/infrastructure/logger/ElectronLogger.js.map +1 -0
  215. package/dist/infrastructure/logger/ElectronLogger.mjs +65 -0
  216. package/dist/infrastructure/logger/ElectronLogger.mjs.map +1 -0
  217. package/dist/infrastructure/logger/index.d.ts +2 -0
  218. package/dist/infrastructure/logger/logger.type.d.ts +8 -0
  219. package/dist/internal/types/BrandedTypes.d.ts +64 -0
  220. package/dist/internal/types/BrandedTypes.js +54 -0
  221. package/dist/internal/types/BrandedTypes.js.map +1 -0
  222. package/dist/internal/types/BrandedTypes.mjs +54 -0
  223. package/dist/internal/types/BrandedTypes.mjs.map +1 -0
  224. package/dist/internal/types/PerformanceOptions.d.ts +87 -0
  225. package/dist/internal/types/branded.d.ts +42 -0
  226. package/dist/internal/utils/MessageDispatcher.d.ts +67 -0
  227. package/dist/internal/utils/MessageDispatcher.js +96 -0
  228. package/dist/internal/utils/MessageDispatcher.js.map +1 -0
  229. package/dist/internal/utils/MessageDispatcher.mjs +96 -0
  230. package/dist/internal/utils/MessageDispatcher.mjs.map +1 -0
  231. package/dist/internal/utils/RateLimiter.d.ts +41 -0
  232. package/dist/internal/utils/RateLimiter.js +83 -0
  233. package/dist/internal/utils/RateLimiter.js.map +1 -0
  234. package/dist/internal/utils/RateLimiter.mjs +83 -0
  235. package/dist/internal/utils/RateLimiter.mjs.map +1 -0
  236. package/dist/internal/utils/StateKeeper.d.ts +125 -0
  237. package/dist/internal/utils/StateKeeper.js +334 -0
  238. package/dist/internal/utils/StateKeeper.js.map +1 -0
  239. package/dist/internal/utils/StateKeeper.mjs +334 -0
  240. package/dist/internal/utils/StateKeeper.mjs.map +1 -0
  241. package/dist/internal/utils/branded-helpers.d.ts +33 -0
  242. package/dist/internal/utils/index.d.ts +5 -0
  243. package/dist/preload/index.d.ts +45 -0
  244. package/dist/preload/index.js +91 -0
  245. package/dist/preload/index.js.map +1 -0
  246. package/dist/preload/index.mjs +91 -0
  247. package/dist/preload/index.mjs.map +1 -0
  248. package/dist/preload/preload.type.d.ts +15 -0
  249. package/dist/types.d.ts +7 -0
  250. package/dist/types.js +1 -0
  251. package/dist/types.js.map +1 -0
  252. package/dist/types.mjs +1 -0
  253. package/dist/types.mjs.map +1 -0
  254. package/package.json +143 -0
@@ -0,0 +1,677 @@
1
+ import {MessageChannelMain,ipcMain}from'electron';import {EventEmitter}from'events';import {MessageDispatcher}from'../../internal/utils/MessageDispatcher.mjs';import {MessageProtocolType}from'./message-bus.type.mjs';import {EVENTS}from'../window/constants.mjs';import {TransactionManager}from'./core/TransactionManager.mjs';import {SubscriptionManager}from'./core/SubscriptionManager.mjs';import {DataStoreManager}from'./core/DataStoreManager.mjs';import {ElectronLogger}from'../../infrastructure/logger/ElectronLogger.mjs';import {IpcTransport}from'./transport/IpcTransport.mjs';import {MessagePortTransport}from'./transport/MessagePortTransport.mjs';import {PerformanceMonitor}from'../../infrastructure/debug/PerformanceMonitor.mjs';/**
2
+ * MessageBus - Multi-window state synchronization and communication bridge
3
+ * MessageBus - 多窗口状态同步与通信桥梁
4
+ *
5
+ * Design patterns / 设计模式:
6
+ * - Shared State (Instance-based): Singleton instance holds shared state (单例实例持有共享状态)
7
+ * - Transport Layer Abstraction: Decouples communication mechanism (传输层抽象:解耦通信机制)
8
+ * - Permission Control: Field-level + Window-level dual permission (权限控制:字段级 + 窗口级双重权限)
9
+ * - Message Proxy: Unified communication interface (消息代理:统一的通信接口)
10
+ * - Componentized: Delegates responsibilities to core managers (组件化:将职责委托给核心管理器)
11
+ */
12
+ class MessageBus extends EventEmitter {
13
+ eventName = EVENTS.WINDOW_STATE_CHANGED;
14
+ logger;
15
+ // Core Managers
16
+ // 核心管理器
17
+ subscriptionManager;
18
+ transactionManager;
19
+ dataStoreManager;
20
+ // Transport Layer
21
+ // 传输层
22
+ transport;
23
+ transportMode;
24
+ windows = new Map();
25
+ // Message dispatcher
26
+ // 消息分发器
27
+ dispatcher;
28
+ // Group resolver for P2P messaging
29
+ // P2P 消息的分组解析器
30
+ groupResolver;
31
+ // Track watch callbacks for cleanup
32
+ // 跟踪 watch 回调以便清理
33
+ watchCallbacks = new Set();
34
+ // Window subscriptions for auto cleanup (Task 1)
35
+ // 窗口订阅用于自动清理 (任务 1)
36
+ windowSubscriptions = new WeakMap();
37
+ /**
38
+ * Create a new MessageBus instance
39
+ * 创建一个新的 MessageBus 实例
40
+ *
41
+ * @param options - Configuration options
42
+ */
43
+ constructor(options = {}) {
44
+ super();
45
+ this.eventName = options.eventName || EVENTS.WINDOW_STATE_CHANGED;
46
+ this.logger = options.logger || new ElectronLogger({ appName: 'MessageBus' });
47
+ this.dispatcher = new MessageDispatcher('MessageBus', this.logger);
48
+ this.subscriptionManager = new SubscriptionManager(this.logger);
49
+ this.transactionManager = new TransactionManager(this.logger);
50
+ this.dataStoreManager = new DataStoreManager();
51
+ // Initialize Transport Strategy (Task 5)
52
+ // 初始化传输策略 (任务 5)
53
+ const mode = options.transportMode || 'auto';
54
+ this.transportMode = this.selectTransportMode(mode);
55
+ this.transport = this.createTransport(this.transportMode);
56
+ try {
57
+ this.transport.init((msg, windowId) => this.handleTransportMessage(msg, windowId));
58
+ this.logger.info(`MessageBus initialized with ${this.transportMode} transport`);
59
+ }
60
+ catch (error) {
61
+ // Fallback if initialization fails
62
+ this.logger.error(`Failed to initialize ${this.transportMode} transport: ${error}. Falling back to IPC.`);
63
+ this.transportMode = 'ipc';
64
+ this.transport = new IpcTransport(this.logger);
65
+ this.transport.init((msg, windowId) => this.handleTransportMessage(msg, windowId));
66
+ }
67
+ this.registerDefaultHandlers();
68
+ }
69
+ /**
70
+ * Select transport mode
71
+ * 选择传输模式
72
+ */
73
+ selectTransportMode(mode) {
74
+ if (mode === 'ipc')
75
+ return 'ipc';
76
+ if (mode === 'messageport')
77
+ return 'messageport';
78
+ // Auto: Check environment capabilities
79
+ // 自动:检查环境能力
80
+ if (typeof MessageChannelMain === 'undefined') {
81
+ this.logger.warn('MessageChannelMain not available, falling back to IPC transport');
82
+ return 'ipc';
83
+ }
84
+ return 'messageport';
85
+ }
86
+ /**
87
+ * Create transport instance
88
+ * 创建传输实例
89
+ */
90
+ createTransport(mode) {
91
+ if (mode === 'ipc')
92
+ return new IpcTransport(this.logger);
93
+ return new MessagePortTransport(this.logger);
94
+ }
95
+ /**
96
+ * Handle incoming message from transport
97
+ * 处理来自传输层的消息
98
+ */
99
+ handleTransportMessage(msg, windowId) {
100
+ try {
101
+ if (msg && msg.type) {
102
+ const result = this.dispatcher.dispatch(msg.type, this, { ...msg, windowId });
103
+ // Handle response if requestId exists (for 'get' requests)
104
+ if (msg.requestId) {
105
+ Promise.resolve(result)
106
+ .then((value) => {
107
+ this.transport.send(windowId, {
108
+ type: MessageProtocolType.GET_RESPONSE,
109
+ requestId: msg.requestId,
110
+ value,
111
+ });
112
+ })
113
+ .catch((err) => {
114
+ this.logger.error(`Error handling message ${msg.type}: ${err}`);
115
+ });
116
+ }
117
+ }
118
+ }
119
+ catch (error) {
120
+ this.logger.error(`Failed to handle message from window ${windowId}: ${error}`);
121
+ }
122
+ }
123
+ /**
124
+ * Register a window with MessageBus
125
+ * 注册窗口到 MessageBus
126
+ * @param windowId - Window ID (窗口 ID)
127
+ * @param window - BrowserWindow instance (BrowserWindow 实例)
128
+ */
129
+ registerWindow(windowId, window) {
130
+ // Clean up existing registration if any
131
+ // 清理现有的注册(如果有)
132
+ this.unregisterWindow(windowId);
133
+ this.windows.set(windowId, window);
134
+ this.transport.registerWindow(windowId, window);
135
+ }
136
+ /**
137
+ * Unregister a window from MessageBus
138
+ * 从 MessageBus 注销窗口
139
+ * @param windowId - Window ID (窗口 ID)
140
+ */
141
+ unregisterWindow(windowId) {
142
+ // 1. Clean up window-specific subscriptions (Task 1)
143
+ const window = this.windows.get(windowId);
144
+ if (window && this.windowSubscriptions.has(window)) {
145
+ const unsubs = this.windowSubscriptions.get(window);
146
+ if (unsubs) {
147
+ this.logger.info(`Cleaning up ${unsubs.size} subscriptions for window ${windowId}`);
148
+ unsubs.forEach((unsub) => {
149
+ try {
150
+ unsub();
151
+ }
152
+ catch (e) {
153
+ /* ignore */
154
+ }
155
+ });
156
+ this.windowSubscriptions.delete(window);
157
+ }
158
+ }
159
+ this.transport.unregisterWindow(windowId);
160
+ this.windows.delete(windowId);
161
+ // Remove subscriptions for this window
162
+ // 移除该窗口的订阅
163
+ this.subscriptionManager.removeWindow(windowId);
164
+ // Rollback any active transactions
165
+ // 回滚任何活跃事务
166
+ if (this.transactionManager.hasTransaction(windowId)) {
167
+ this.transactionManager.rollback(windowId);
168
+ }
169
+ }
170
+ /**
171
+ * Auto register/unregister windows with WindowManager
172
+ * 自动注册/注销窗口与 WindowManager
173
+ * @param windowManager - WindowManager instance (WindowManager 实例)
174
+ */
175
+ autoRegisterWindows(windowManager) {
176
+ // Register on window creation
177
+ // 在窗口创建时注册
178
+ windowManager.on('window-created', ({ window, id }) => {
179
+ this.registerWindow(id, window);
180
+ });
181
+ // Unregister on window destruction
182
+ // 在窗口销毁时注销
183
+ windowManager.on('window-will-be-destroyed', (id) => {
184
+ this.unregisterWindow(id);
185
+ });
186
+ }
187
+ /**
188
+ * Dispose all resources
189
+ * 释放所有资源
190
+ */
191
+ dispose() {
192
+ this.logger.info('Disposing MessageBus...');
193
+ // 1. Clean up all watch callbacks
194
+ // 清理所有 watch 回调
195
+ this.watchCallbacks.forEach((unsubscribe) => {
196
+ try {
197
+ unsubscribe();
198
+ }
199
+ catch (error) {
200
+ this.logger.warn(`Failed to unsubscribe watch callback: ${error}`);
201
+ }
202
+ });
203
+ this.watchCallbacks.clear();
204
+ // 2. Clean up MessageHandlers
205
+ this.dispatcher.clear();
206
+ // 3. Dispose transport
207
+ this.transport.dispose();
208
+ // 4. Clear data and subscriptions
209
+ this.dataStoreManager.clear();
210
+ this.subscriptionManager.clear();
211
+ this.transactionManager.clear();
212
+ this.windows.clear();
213
+ // 5. Remove all event listeners
214
+ this.removeAllListeners();
215
+ this.logger.info('MessageBus disposed');
216
+ }
217
+ /**
218
+ * Register a single event handler
219
+ * 注册单个事件处理器
220
+ * @param handler - Event handler (事件处理器)
221
+ */
222
+ registerHandler(handler) {
223
+ this.on(handler.eventName, handler.callback);
224
+ }
225
+ /**
226
+ * Batch register event handlers
227
+ * 批量注册事件处理器
228
+ * @param handlers - Array of event handlers (事件处理器数组)
229
+ */
230
+ registerHandlers(handlers) {
231
+ handlers.forEach((handler) => this.registerHandler(handler));
232
+ }
233
+ /**
234
+ * Unregister a single event handler
235
+ * 注销单个事件处理器
236
+ * @param handler - Event handler (事件处理器)
237
+ */
238
+ unregisterHandler(handler) {
239
+ this.removeListener(handler.eventName, handler.callback);
240
+ }
241
+ /**
242
+ * Batch unregister event handlers
243
+ * 批量注销事件处理器
244
+ * @param handlers - Array of event handlers (事件处理器数组)
245
+ */
246
+ unregisterHandlers(handlers) {
247
+ handlers.forEach((handler) => this.unregisterHandler(handler));
248
+ }
249
+ /**
250
+ * Get data
251
+ * 获取数据
252
+ * @param key - Data key, returns all data if not provided (数据键,不传则返回所有数据)
253
+ * @returns Data value or all data (数据值或所有数据)
254
+ */
255
+ getData(key) {
256
+ if (key) {
257
+ return this.dataStoreManager.get(key);
258
+ }
259
+ return this.dataStoreManager.getAll();
260
+ }
261
+ /**
262
+ * Check permission
263
+ * 检查权限
264
+ * @param key - Data key (数据键)
265
+ * @param windowId - Operation window ID (操作窗口 ID)
266
+ * @param operation - Operation type (操作类型)
267
+ * @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
268
+ */
269
+ checkPermission(key, windowId, operation) {
270
+ return this.dataStoreManager.checkPermission(key, windowId, operation);
271
+ }
272
+ /**
273
+ * Set data (with permission check and transaction support)
274
+ * 设置数据(带权限验证和事务支持)
275
+ * @param key - Data key (数据键)
276
+ * @param value - Data value (数据值)
277
+ * @param windowId - Operation window ID (操作窗口 ID)
278
+ * @param eventName - Optional event name (可选的事件名称)
279
+ * @param skipTransaction - Whether to skip transaction check (是否跳过事务检查)
280
+ * @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
281
+ */
282
+ setData(key, value, windowId, eventName, skipTransaction = false) {
283
+ const permissionCheck = this.checkPermission(key, windowId, 'modify');
284
+ if (!permissionCheck.success) {
285
+ return permissionCheck;
286
+ }
287
+ // Handle Transaction
288
+ if (!skipTransaction && windowId && this.transactionManager.hasTransaction(windowId)) {
289
+ this.transactionManager.add(windowId, key, { type: 'set', value });
290
+ return { success: true };
291
+ }
292
+ const item = this.dataStoreManager.getItem(key);
293
+ const oldValue = item?.value;
294
+ this.dataStoreManager.set(key, value);
295
+ // Broadcast change
296
+ // 广播变更
297
+ const event = {
298
+ type: MessageProtocolType.SET,
299
+ key,
300
+ value,
301
+ oldValue,
302
+ windowId,
303
+ timestamp: Date.now(),
304
+ };
305
+ this.broadcastChange(event);
306
+ this.emit(eventName || this.eventName, event);
307
+ return { success: true };
308
+ }
309
+ /**
310
+ * Delete data
311
+ * 删除数据
312
+ * @param key - Data key (数据键)
313
+ * @param windowId - Operation window ID (操作窗口 ID)
314
+ * @param eventName - Optional event name (可选的事件名称)
315
+ * @param skipTransaction - Whether to skip transaction check (是否跳过事务检查)
316
+ * @returns Result object with success flag and error message (包含成功标志和错误消息的结果对象)
317
+ */
318
+ deleteData(key, windowId, eventName, skipTransaction = false) {
319
+ const permissionCheck = this.checkPermission(key, windowId, 'delete');
320
+ if (!permissionCheck.success) {
321
+ return permissionCheck;
322
+ }
323
+ // Handle Transaction
324
+ if (!skipTransaction && windowId && this.transactionManager.hasTransaction(windowId)) {
325
+ this.transactionManager.add(windowId, key, { type: 'delete' });
326
+ return { success: true };
327
+ }
328
+ const item = this.dataStoreManager.getItem(key);
329
+ const oldValue = item?.value;
330
+ this.dataStoreManager.delete(key);
331
+ const event = {
332
+ type: MessageProtocolType.DELETE,
333
+ key,
334
+ oldValue,
335
+ windowId,
336
+ timestamp: Date.now(),
337
+ };
338
+ this.broadcastChange(event);
339
+ this.emit(eventName || this.eventName, event);
340
+ return { success: true };
341
+ }
342
+ /**
343
+ * Start a transaction
344
+ * 开启事务
345
+ * @param windowId - Window ID (窗口 ID)
346
+ */
347
+ startTransaction(windowId) {
348
+ this.transactionManager.start(windowId);
349
+ }
350
+ /**
351
+ * Commit a transaction
352
+ * 提交事务
353
+ * @param windowId - Window ID (窗口 ID)
354
+ */
355
+ commitTransaction(windowId) {
356
+ const buffer = this.transactionManager.commit(windowId);
357
+ if (!buffer)
358
+ return;
359
+ buffer.forEach((op, key) => {
360
+ if (op.type === 'set') {
361
+ this.setData(key, op.value, windowId, undefined, true);
362
+ }
363
+ else if (op.type === 'delete') {
364
+ this.deleteData(key, windowId, undefined, true);
365
+ }
366
+ });
367
+ }
368
+ /**
369
+ * Rollback a transaction
370
+ * 回滚事务
371
+ * @param windowId - Window ID (窗口 ID)
372
+ */
373
+ rollbackTransaction(windowId) {
374
+ this.transactionManager.rollback(windowId);
375
+ }
376
+ /**
377
+ * Watch for data changes (Main Process)
378
+ * 监听数据变化(主进程)
379
+ *
380
+ * ⚠️ IMPORTANT: You must call the returned unsubscribe function to prevent memory leaks
381
+ * ⚠️ 重要:必须调用返回的取消订阅函数以防止内存泄漏
382
+ *
383
+ * @param key - Data key to watch (监听的键)
384
+ * @param callback - Callback function (回调函数)
385
+ * @param windowId - Optional window ID to bind lifecycle (可选的窗口 ID,用于绑定生命周期)
386
+ * @returns Unsubscribe function (取消订阅函数)
387
+ */
388
+ watch(key, callback, windowId) {
389
+ const handler = (event) => {
390
+ if ('key' in event && event.key === key) {
391
+ if (event.type === MessageProtocolType.SET) {
392
+ callback(event.value, event.oldValue);
393
+ }
394
+ else if (event.type === MessageProtocolType.DELETE) {
395
+ callback(undefined, event.oldValue);
396
+ }
397
+ }
398
+ };
399
+ this.on(this.eventName, handler);
400
+ const unsubscribe = () => {
401
+ this.off(this.eventName, handler);
402
+ this.watchCallbacks.delete(unsubscribe);
403
+ // Cleanup from weak map if exists
404
+ if (windowId) {
405
+ const window = this.windows.get(windowId);
406
+ if (window && this.windowSubscriptions.has(window)) {
407
+ this.windowSubscriptions.get(window)?.delete(unsubscribe);
408
+ }
409
+ }
410
+ };
411
+ // Track for automatic cleanup on dispose
412
+ // 跟踪以便在 dispose 时自动清理
413
+ this.watchCallbacks.add(unsubscribe);
414
+ // Track for window lifecycle cleanup (Task 1)
415
+ if (windowId) {
416
+ const window = this.windows.get(windowId);
417
+ if (window) {
418
+ if (!this.windowSubscriptions.has(window)) {
419
+ this.windowSubscriptions.set(window, new Set());
420
+ }
421
+ this.windowSubscriptions.get(window).add(unsubscribe);
422
+ }
423
+ else {
424
+ this.logger.warn(`Window ${windowId} not found, watch subscription will not be auto-cleaned up on window destroy`);
425
+ }
426
+ }
427
+ return unsubscribe;
428
+ }
429
+ /**
430
+ * Atomic update
431
+ * 原子更新
432
+ * @param key - Data key (数据键)
433
+ * @param updater - Updater function or new value (更新函数或新值)
434
+ * @param windowId - Window ID (窗口 ID)
435
+ */
436
+ updateData(key, updater, windowId) {
437
+ let currentValue = this.dataStoreManager.get(key);
438
+ if (windowId) {
439
+ const buffered = this.transactionManager.getBufferedValue(windowId, key);
440
+ if (buffered.has) {
441
+ currentValue = buffered.value;
442
+ }
443
+ }
444
+ const newValue = typeof updater === 'function' ? updater(currentValue) : updater;
445
+ return this.setData(key, newValue, windowId);
446
+ }
447
+ /**
448
+ * Set field permission
449
+ * 设置字段权限
450
+ * @param key - Data key (数据键)
451
+ * @param permission - Permission object (权限对象)
452
+ */
453
+ setFieldPermission(key, permission) {
454
+ this.dataStoreManager.setPermission(key, permission);
455
+ }
456
+ /**
457
+ * Get registered windows list (for debugging)
458
+ * 获取已注册的窗口列表(调试用)
459
+ * @returns Array of registered window IDs (已注册的窗口 ID 数组)
460
+ */
461
+ getRegisteredWindows() {
462
+ return Array.from(this.windows.keys());
463
+ }
464
+ /**
465
+ * Register message handler
466
+ * 注册消息处理器
467
+ * @param handler - Bus message handler (总线消息处理器)
468
+ */
469
+ registerMessageHandler(handler) {
470
+ this.dispatcher.register(handler.name, handler.callback);
471
+ }
472
+ /**
473
+ * Register default handlers
474
+ * 注册默认处理器
475
+ */
476
+ registerDefaultHandlers() {
477
+ this.registerMessageHandler({
478
+ name: MessageProtocolType.GET,
479
+ callback: (bus, { key } = {}) => bus.getData(key),
480
+ });
481
+ this.registerMessageHandler({
482
+ name: MessageProtocolType.SET,
483
+ callback: (bus, { key, value, windowId, eventName }) => bus.setData(key, value, windowId, eventName),
484
+ });
485
+ this.registerMessageHandler({
486
+ name: MessageProtocolType.DELETE,
487
+ callback: (bus, { key, windowId, eventName }) => bus.deleteData(key, windowId, eventName),
488
+ });
489
+ this.registerMessageHandler({
490
+ name: MessageProtocolType.SET_PERMISSION,
491
+ callback: (bus, { key, permission }) => bus.setFieldPermission(key, permission),
492
+ });
493
+ this.registerMessageHandler({
494
+ name: MessageProtocolType.SUBSCRIBE,
495
+ callback: (bus, { windowId, keys }) => bus.subscribe(windowId, keys),
496
+ });
497
+ this.registerMessageHandler({
498
+ name: MessageProtocolType.UNSUBSCRIBE,
499
+ callback: (bus, { windowId, keys }) => bus.unsubscribe(windowId, keys),
500
+ });
501
+ this.registerMessageHandler({
502
+ name: MessageProtocolType.TRANSACTION_START,
503
+ callback: (bus, { windowId }) => bus.startTransaction(windowId),
504
+ });
505
+ this.registerMessageHandler({
506
+ name: MessageProtocolType.TRANSACTION_COMMIT,
507
+ callback: (bus, { windowId }) => bus.commitTransaction(windowId),
508
+ });
509
+ this.registerMessageHandler({
510
+ name: MessageProtocolType.TRANSACTION_ROLLBACK,
511
+ callback: (bus, { windowId }) => bus.rollbackTransaction(windowId),
512
+ });
513
+ this.registerMessageHandler({
514
+ name: MessageProtocolType.SEND_TO_WINDOW,
515
+ callback: (bus, { targetWindowId, channel, data }) => bus.sendToWindow(targetWindowId, channel, data),
516
+ });
517
+ this.registerMessageHandler({
518
+ name: MessageProtocolType.SEND_TO_GROUP,
519
+ callback: (bus, { group, channel, data }) => bus.sendToGroup(group, channel, data),
520
+ });
521
+ this.registerMessageHandler({
522
+ name: MessageProtocolType.UPDATE,
523
+ callback: (bus, { key, value, windowId }) => {
524
+ return bus.setData(key, value, windowId);
525
+ },
526
+ });
527
+ }
528
+ /**
529
+ * Handle message
530
+ * 处理消息
531
+ * @param name - Message name (消息名称)
532
+ * @param data - Message data (消息数据)
533
+ * @returns Result of handler (处理器结果)
534
+ */
535
+ handleMessage(name, data) {
536
+ return this.dispatcher.dispatch(name, this, data);
537
+ }
538
+ /**
539
+ * Initialize communication listener (optional)
540
+ * 初始化通信监听器(可选)
541
+ *
542
+ * Allows renderer process to read/write data directly via unified channel.
543
+ * 允许渲染进程通过统一通道直接读写数据。
544
+ */
545
+ initializeListener() {
546
+ // Unified channel, optimize communication
547
+ // 统一通道,优化通信方式
548
+ ipcMain.handle('message-bus-invoke', (_, { name, data }) => this.handleMessage(name, data));
549
+ }
550
+ /**
551
+ * Set group resolver
552
+ * 设置分组解析器
553
+ * @param resolver - Group resolver function (分组解析函数)
554
+ */
555
+ setGroupResolver(resolver) {
556
+ this.groupResolver = resolver;
557
+ }
558
+ /**
559
+ * Send message to specific window
560
+ * 发送消息到指定窗口
561
+ * @param windowId - Target window ID (目标窗口 ID)
562
+ * @param channel - Channel name (频道名称)
563
+ * @param data - Message data (消息数据)
564
+ * @returns Success or not (是否成功)
565
+ */
566
+ sendToWindow(windowId, channel, data) {
567
+ const perf = PerformanceMonitor.getInstance();
568
+ const measureId = `message-bus-send-${Date.now()}`;
569
+ perf.startMeasure(measureId, 'MessageBus Send', { windowId, channel });
570
+ if (!this.windows.has(windowId)) {
571
+ this.logger.warn(`Window ${windowId} not found or not registered`);
572
+ perf.endMeasure(measureId, { status: 'failed', reason: 'window_not_found' });
573
+ return false;
574
+ }
575
+ try {
576
+ const message = {
577
+ type: MessageProtocolType.MESSAGE,
578
+ channel,
579
+ value: data,
580
+ timestamp: Date.now(),
581
+ };
582
+ this.transport.send(windowId, JSON.stringify(message));
583
+ perf.endMeasure(measureId, { status: 'success' });
584
+ return true;
585
+ }
586
+ catch (error) {
587
+ this.logger.error(`Failed to send message to window ${windowId}: ${error}`);
588
+ this.emit('error', error);
589
+ perf.endMeasure(measureId, {
590
+ status: 'error',
591
+ error: error instanceof Error ? error.message : String(error),
592
+ });
593
+ return false;
594
+ }
595
+ }
596
+ /**
597
+ * Send message to a group of windows
598
+ * 发送消息到一组窗口
599
+ * @param group - Group name (组名)
600
+ * @param channel - Channel name (频道名称)
601
+ * @param data - Message data (消息数据)
602
+ * @returns Number of successful sends (成功发送的数量)
603
+ */
604
+ sendToGroup(group, channel, data) {
605
+ const perf = PerformanceMonitor.getInstance();
606
+ const measureId = `message-bus-broadcast-${Date.now()}`;
607
+ perf.startMeasure(measureId, 'MessageBus Broadcast', { group, channel });
608
+ if (!this.groupResolver) {
609
+ this.logger.warn('Group resolver not set, cannot send to group');
610
+ perf.endMeasure(measureId, { status: 'failed', reason: 'no_group_resolver' });
611
+ return 0;
612
+ }
613
+ const windowIds = this.groupResolver(group);
614
+ const count = this.broadcastToWindows(windowIds, channel, data);
615
+ perf.endMeasure(measureId, {
616
+ status: 'success',
617
+ windowCount: windowIds.length,
618
+ successCount: count,
619
+ });
620
+ return count;
621
+ }
622
+ /**
623
+ * Broadcast message to specific windows
624
+ * 广播消息到指定的一组窗口
625
+ * @param windowIds - Target window IDs (目标窗口 ID 列表)
626
+ * @param channel - Channel name (频道名称)
627
+ * @param data - Message data (消息数据)
628
+ * @returns Number of successful sends (成功发送的数量)
629
+ */
630
+ broadcastToWindows(windowIds, channel, data) {
631
+ const message = {
632
+ type: MessageProtocolType.MESSAGE,
633
+ channel,
634
+ value: data,
635
+ timestamp: Date.now(),
636
+ };
637
+ const serializedMessage = JSON.stringify(message);
638
+ return this.transport.broadcast(serializedMessage, windowIds);
639
+ }
640
+ /**
641
+ * Subscribe to specific keys
642
+ * 订阅特定的 key
643
+ * @param windowId - Window ID (窗口 ID)
644
+ * @param keys - Keys to subscribe (订阅的 key 列表)
645
+ */
646
+ subscribe(windowId, keys) {
647
+ this.subscriptionManager.subscribe(windowId, keys);
648
+ }
649
+ /**
650
+ * Unsubscribe from specific keys
651
+ * 取消订阅特定的 key
652
+ * @param windowId - Window ID (窗口 ID)
653
+ * @param keys - Keys to unsubscribe (取消订阅的 key 列表)
654
+ */
655
+ unsubscribe(windowId, keys) {
656
+ this.subscriptionManager.unsubscribe(windowId, keys);
657
+ }
658
+ /**
659
+ * Broadcast changes to all windows via Transport
660
+ * 通过传输层广播变更到所有窗口
661
+ * @param event - Data change event (数据变更事件)
662
+ */
663
+ broadcastChange(event) {
664
+ const message = JSON.stringify(event);
665
+ // If it's a key-based event and has subscribers, only broadcast to them
666
+ // 如果是基于 key 的事件且有订阅者,只广播给订阅者
667
+ if ('key' in event && event.key) {
668
+ const subscribers = this.subscriptionManager.getSubscribers(event.key);
669
+ if (subscribers) {
670
+ this.transport.broadcast(message, Array.from(subscribers));
671
+ return;
672
+ }
673
+ }
674
+ // Broadcast to all windows (fallback or non-keyed events)
675
+ this.transport.broadcast(message);
676
+ }
677
+ }export{MessageBus};//# sourceMappingURL=MessageBus.mjs.map