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
package/dist/index.js ADDED
@@ -0,0 +1,33 @@
1
+ 'use strict';var WindowManager=require('./core/window/WindowManager.js'),IpcRouter=require('./core/ipc/IpcRouter.js'),MessageBus=require('./core/message-bus/MessageBus.js'),index=require('./infrastructure/debug/index.js'),LifecycleManager=require('./core/lifecycle/LifecycleManager.js'),index$1=require('./preload/index.js'),types=require('./types.js'),index$2=require('./infrastructure/errors/index.js'),WindowStore=require('./core/window/WindowStore.js'),WindowCreator=require('./core/window/WindowCreator.js'),IpcHandler=require('./core/ipc/IpcHandler.js'),ElectronLogger=require('./infrastructure/logger/ElectronLogger.js'),EnhancedDebugHelper=require('./infrastructure/debug/EnhancedDebugHelper.js'),windowManager_schema=require('./core/window/window-manager.schema.js'),IpcSetup=require('./core/window/IpcSetup.js'),WindowError=require('./core/error/WindowError.js'),MessageBusClient=require('./core/message-bus/MessageBusClient.js'),preload=require('./core/message-bus/preload.js'),messageBus_type=require('./core/message-bus/message-bus.type.js'),ConfigManager=require('./infrastructure/config/ConfigManager.js'),ErrorCodes=require('./infrastructure/errors/ErrorCodes.js'),StandardError=require('./infrastructure/errors/StandardError.js');/**
2
+ * Quick Start Helper
3
+ * 快速开始助手
4
+ * @param config - WindowManager configuration
5
+ * @returns Object containing initialized instances
6
+ */
7
+ function createElectronToolkit(config = {}) {
8
+ // Create IpcRouter
9
+ const ipcRouter = new IpcRouter({ logger: config.logger });
10
+ // Create WindowManager with ipcRouter integrated
11
+ const windowManager = new WindowManager({
12
+ ...config,
13
+ ipcRouter,
14
+ });
15
+ // Create MessageBus
16
+ const messageBus = new MessageBus.MessageBus({ logger: config.logger });
17
+ // Automatically integrate MessageBus with WindowManager
18
+ // 自动集成 MessageBus 和 WindowManager
19
+ messageBus.autoRegisterWindows(windowManager);
20
+ // Setup Debug Mode
21
+ // 设置调试模式
22
+ if (config.isDevelopment || process.env.NODE_ENV === 'development') {
23
+ index.DebugHelper.enableDebugMode();
24
+ index.DebugHelper.register('windowManager', windowManager);
25
+ index.DebugHelper.register('ipcRouter', ipcRouter);
26
+ index.DebugHelper.register('messageBus', messageBus);
27
+ }
28
+ return {
29
+ windowManager,
30
+ ipcRouter,
31
+ messageBus,
32
+ };
33
+ }exports.WindowManager=WindowManager;exports.IpcRouter=IpcRouter;exports.MessageBus=MessageBus.MessageBus;exports.DebugHelper=index.DebugHelper;exports.LifecycleManager=LifecycleManager.LifecycleManager;exports.IpcRendererBridge=index$1.IpcRendererBridge;exports.ipcRendererBridge=index$1.ipcRendererBridge;exports.Types=types;exports.ElectronToolkitError=index$2.ElectronToolkitError;exports.IpcHandlerError=index$2.IpcHandlerError;exports.WindowNotFoundError=index$2.WindowNotFoundError;exports.WindowStore=WindowStore;exports.WindowCreator=WindowCreator;exports.IpcHandler=IpcHandler;exports.Logger=ElectronLogger.ElectronLogger;exports.EnhancedDebugHelper=EnhancedDebugHelper.EnhancedDebugHelper;exports.debugHelper=EnhancedDebugHelper.debugHelper;exports.validateWindowManagerConfig=windowManager_schema.validateWindowManagerConfig;exports.IpcSetup=IpcSetup.IpcSetup;exports.WindowError=WindowError.WindowError;Object.defineProperty(exports,"WindowErrorCode",{enumerable:true,get:function(){return WindowError.WindowErrorCode}});exports.MessageBusClient=MessageBusClient.MessageBusClient;exports.setupMessageBus=preload.setupMessageBus;Object.defineProperty(exports,"MessageProtocolType",{enumerable:true,get:function(){return messageBus_type.MessageProtocolType}});exports.ConfigManager=ConfigManager.ConfigManager;Object.defineProperty(exports,"ErrorCategory",{enumerable:true,get:function(){return ErrorCodes.ErrorCategory}});Object.defineProperty(exports,"IpcErrorCode",{enumerable:true,get:function(){return ErrorCodes.IpcErrorCode}});Object.defineProperty(exports,"MessageBusErrorCode",{enumerable:true,get:function(){return ErrorCodes.MessageBusErrorCode}});Object.defineProperty(exports,"WindowManagerErrorCode",{enumerable:true,get:function(){return ErrorCodes.WindowManagerErrorCode}});exports.NotFoundError=StandardError.NotFoundError;exports.PermissionError=StandardError.PermissionError;exports.StandardError=StandardError.StandardError;exports.ValidationError=StandardError.ValidationError;exports.createElectronToolkit=createElectronToolkit;//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import WindowManager from './core/window/WindowManager';\nimport IpcRouter from './core/ipc/IpcRouter';\nimport { MessageBus } from './core/message-bus/MessageBus';\nimport { WindowManagerConfig } from './core/window/window-manager.type';\nimport { DebugHelper } from './infrastructure/debug';\n\n/**\n * Quick Start Helper\n * 快速开始助手\n * @param config - WindowManager configuration\n * @returns Object containing initialized instances\n */\nexport function createElectronToolkit(config: WindowManagerConfig = {}) {\n // Create IpcRouter\n const ipcRouter = new IpcRouter({ logger: config.logger });\n\n // Create WindowManager with ipcRouter integrated\n const windowManager = new WindowManager({\n ...config,\n ipcRouter,\n });\n\n // Create MessageBus\n const messageBus = new MessageBus({ logger: config.logger });\n\n // Automatically integrate MessageBus with WindowManager\n // 自动集成 MessageBus 和 WindowManager\n messageBus.autoRegisterWindows(windowManager);\n\n // Setup Debug Mode\n // 设置调试模式\n if (config.isDevelopment || process.env.NODE_ENV === 'development') {\n DebugHelper.enableDebugMode();\n DebugHelper.register('windowManager', windowManager);\n DebugHelper.register('ipcRouter', ipcRouter);\n DebugHelper.register('messageBus', messageBus);\n }\n\n return {\n windowManager,\n ipcRouter,\n messageBus,\n };\n}\n\nexport * from './core/window';\nexport * from './core/ipc';\nexport * from './core/message-bus';\nexport * from './core/lifecycle/LifecycleManager';\n// IpcTransport is internal, do not export\n// export { default as IpcTransport } from './ipc-transport'\nexport { Logger, type LoggerOptions } from './infrastructure/logger';\nexport * from './preload';\n// Internal utils should not be exported\n// export * from './internal/utils';\nexport * from './infrastructure/config';\nexport * as Types from './types';\nexport { DebugHelper, debugHelper, EnhancedDebugHelper } from './infrastructure/debug';\nexport * from './infrastructure/errors';\n"],"names":["MessageBus","DebugHelper"],"mappings":"+tCAMA;;;;;AAKG;AACG,SAAU,qBAAqB,CAAC,MAAA,GAA8B,EAAE,EAAA;;AAEpE,IAAA,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;;AAG1D,IAAA,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;AACtC,QAAA,GAAG,MAAM;QACT,SAAS;AACV,KAAA,CAAC;;AAGF,IAAA,MAAM,UAAU,GAAG,IAAIA,qBAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;;;AAI5D,IAAA,UAAU,CAAC,mBAAmB,CAAC,aAAa,CAAC;;;AAI7C,IAAA,IAAI,MAAM,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;QAClEC,iBAAW,CAAC,eAAe,EAAE;AAC7B,QAAAA,iBAAW,CAAC,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC;AACpD,QAAAA,iBAAW,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;AAC5C,QAAAA,iBAAW,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAChD;IAEA,OAAO;QACL,aAAa;QACb,SAAS;QACT,UAAU;KACX;AACH"}
package/dist/index.mjs ADDED
@@ -0,0 +1,33 @@
1
+ import WindowManager from'./core/window/WindowManager.mjs';import IpcRouter from'./core/ipc/IpcRouter.mjs';import {MessageBus}from'./core/message-bus/MessageBus.mjs';import {DebugHelper}from'./infrastructure/debug/index.mjs';export{LifecycleManager}from'./core/lifecycle/LifecycleManager.mjs';export{IpcRendererBridge,ipcRendererBridge}from'./preload/index.mjs';import*as types from'./types.mjs';export{types as Types };export{ElectronToolkitError,IpcHandlerError,WindowNotFoundError}from'./infrastructure/errors/index.mjs';export{default as WindowStore}from'./core/window/WindowStore.mjs';export{default as WindowCreator}from'./core/window/WindowCreator.mjs';export{default as IpcHandler}from'./core/ipc/IpcHandler.mjs';export{ElectronLogger as Logger}from'./infrastructure/logger/ElectronLogger.mjs';export{EnhancedDebugHelper,debugHelper}from'./infrastructure/debug/EnhancedDebugHelper.mjs';export{validateWindowManagerConfig}from'./core/window/window-manager.schema.mjs';export{IpcSetup}from'./core/window/IpcSetup.mjs';export{WindowError,WindowErrorCode}from'./core/error/WindowError.mjs';export{MessageBusClient}from'./core/message-bus/MessageBusClient.mjs';export{setupMessageBus}from'./core/message-bus/preload.mjs';export{MessageProtocolType}from'./core/message-bus/message-bus.type.mjs';export{ConfigManager}from'./infrastructure/config/ConfigManager.mjs';export{ErrorCategory,IpcErrorCode,MessageBusErrorCode,WindowManagerErrorCode}from'./infrastructure/errors/ErrorCodes.mjs';export{NotFoundError,PermissionError,StandardError,ValidationError}from'./infrastructure/errors/StandardError.mjs';/**
2
+ * Quick Start Helper
3
+ * 快速开始助手
4
+ * @param config - WindowManager configuration
5
+ * @returns Object containing initialized instances
6
+ */
7
+ function createElectronToolkit(config = {}) {
8
+ // Create IpcRouter
9
+ const ipcRouter = new IpcRouter({ logger: config.logger });
10
+ // Create WindowManager with ipcRouter integrated
11
+ const windowManager = new WindowManager({
12
+ ...config,
13
+ ipcRouter,
14
+ });
15
+ // Create MessageBus
16
+ const messageBus = new MessageBus({ logger: config.logger });
17
+ // Automatically integrate MessageBus with WindowManager
18
+ // 自动集成 MessageBus 和 WindowManager
19
+ messageBus.autoRegisterWindows(windowManager);
20
+ // Setup Debug Mode
21
+ // 设置调试模式
22
+ if (config.isDevelopment || process.env.NODE_ENV === 'development') {
23
+ DebugHelper.enableDebugMode();
24
+ DebugHelper.register('windowManager', windowManager);
25
+ DebugHelper.register('ipcRouter', ipcRouter);
26
+ DebugHelper.register('messageBus', messageBus);
27
+ }
28
+ return {
29
+ windowManager,
30
+ ipcRouter,
31
+ messageBus,
32
+ };
33
+ }export{DebugHelper,IpcRouter,MessageBus,WindowManager,createElectronToolkit};//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.ts"],"sourcesContent":["import WindowManager from './core/window/WindowManager';\nimport IpcRouter from './core/ipc/IpcRouter';\nimport { MessageBus } from './core/message-bus/MessageBus';\nimport { WindowManagerConfig } from './core/window/window-manager.type';\nimport { DebugHelper } from './infrastructure/debug';\n\n/**\n * Quick Start Helper\n * 快速开始助手\n * @param config - WindowManager configuration\n * @returns Object containing initialized instances\n */\nexport function createElectronToolkit(config: WindowManagerConfig = {}) {\n // Create IpcRouter\n const ipcRouter = new IpcRouter({ logger: config.logger });\n\n // Create WindowManager with ipcRouter integrated\n const windowManager = new WindowManager({\n ...config,\n ipcRouter,\n });\n\n // Create MessageBus\n const messageBus = new MessageBus({ logger: config.logger });\n\n // Automatically integrate MessageBus with WindowManager\n // 自动集成 MessageBus 和 WindowManager\n messageBus.autoRegisterWindows(windowManager);\n\n // Setup Debug Mode\n // 设置调试模式\n if (config.isDevelopment || process.env.NODE_ENV === 'development') {\n DebugHelper.enableDebugMode();\n DebugHelper.register('windowManager', windowManager);\n DebugHelper.register('ipcRouter', ipcRouter);\n DebugHelper.register('messageBus', messageBus);\n }\n\n return {\n windowManager,\n ipcRouter,\n messageBus,\n };\n}\n\nexport * from './core/window';\nexport * from './core/ipc';\nexport * from './core/message-bus';\nexport * from './core/lifecycle/LifecycleManager';\n// IpcTransport is internal, do not export\n// export { default as IpcTransport } from './ipc-transport'\nexport { Logger, type LoggerOptions } from './infrastructure/logger';\nexport * from './preload';\n// Internal utils should not be exported\n// export * from './internal/utils';\nexport * from './infrastructure/config';\nexport * as Types from './types';\nexport { DebugHelper, debugHelper, EnhancedDebugHelper } from './infrastructure/debug';\nexport * from './infrastructure/errors';\n"],"names":[],"mappings":"mkDAMA;;;;;AAKG;AACG,SAAU,qBAAqB,CAAC,MAAA,GAA8B,EAAE,EAAA;;AAEpE,IAAA,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;;AAG1D,IAAA,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;AACtC,QAAA,GAAG,MAAM;QACT,SAAS;AACV,KAAA,CAAC;;AAGF,IAAA,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;;;AAI5D,IAAA,UAAU,CAAC,mBAAmB,CAAC,aAAa,CAAC;;;AAI7C,IAAA,IAAI,MAAM,CAAC,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;QAClE,WAAW,CAAC,eAAe,EAAE;AAC7B,QAAA,WAAW,CAAC,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC;AACpD,QAAA,WAAW,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;AAC5C,QAAA,WAAW,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAChD;IAEA,OAAO;QACL,aAAa;QACb,SAAS;QACT,UAAU;KACX;AACH"}
@@ -0,0 +1 @@
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("electron"),require("tiny-typed-emitter"),require("zod"),require("uuid"),require("events"),require("fs"),require("path"),require("crypto"),require("electron-log")):"function"==typeof define&&define.amd?define(["exports","electron","tiny-typed-emitter","zod","uuid","events","fs","path","crypto","electron-log"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ElectronInfraKit={},e.Electron,e.tinyTypedEmitter,e.zod,e.uuid,e.events,e.fs,e.path,e.crypto,e.electronLog)}(this,function(e,t,s,i,r,o,n,a,d,h){"use strict";function c(e){var t=Object.create(null);return e&&Object.keys(e).forEach(function(s){if("default"!==s){var i=Object.getOwnPropertyDescriptor(e,s);Object.defineProperty(t,s,i.get?i:{enumerable:!0,get:function(){return e[s]}})}}),t.default=e,Object.freeze(t)}var l=c(n),g=c(a),u=c(d);class w{logger;isDev;constructor(e={}){this.isDev="production"!==process.env.NODE_ENV;const{appName:t="main",maxSize:s=10485760,fileName:i,fileLevel:r,consoleLevel:o}=e;this.logger=h.create({logId:t}),this.logger.scope(t);const n=this.isDev?"debug":"info",a=!!this.isDev&&"debug";this.logger.transports.file.level=r??n,this.logger.transports.console.level=o??a,this.logger.transports.file.format="[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] {text}",this.logger.transports.file.maxSize=s,this.logger.transports.file.fileName=i??(this.isDev?`${t}_dev.log`:`${t}.log`)}info(e,...t){this.logger.info(e,...t)}debug(e,...t){this.logger.debug(e,...t)}error(e,...t){this.logger.error(e,...t)}warn(e,...t){this.logger.warn(e,...t)}verbose(e,...t){this.logger.verbose(e,...t)}silly(e,...t){this.logger.silly(e,...t)}getLogger(){return this.logger}}const p=i.z.custom(e=>"object"==typeof e&&null!==e&&"info"in e&&"warn"in e&&"error"in e&&"debug"in e&&"function"==typeof e.info&&"function"==typeof e.warn&&"function"==typeof e.error&&"function"==typeof e.debug,"Logger must implement ILogger interface with info/warn/error/debug methods"),m=i.z.custom(e=>"object"==typeof e&&null!==e&&"handle"in e&&"addHandler"in e&&"function"==typeof e.handle&&"function"==typeof e.addHandler,"IpcRouter must implement handle/addHandler methods"),f=i.z.custom(e=>"object"==typeof e&&null!==e&&"registerWindow"in e&&"unregisterWindow"in e&&"function"==typeof e.registerWindow&&"function"==typeof e.unregisterWindow,"MessageBus must implement registerWindow/unregisterWindow methods"),y=i.z.object({logger:p.optional(),ipcRouter:m.optional(),messageBus:f.optional(),isDevelopment:i.z.boolean().default(!1),preventExternalLinks:i.z.boolean().default(!0),defaultConfig:i.z.record(i.z.string(),i.z.any()).default({}),plugins:i.z.array(i.z.any()).default([]),hooks:i.z.record(i.z.string(),i.z.any()).default({}),ipc:i.z.object({autoInit:i.z.boolean().default(!0)}).default({autoInit:!0}),store:i.z.record(i.z.string(),i.z.any()).default({}),ipcSetup:i.z.function().optional(),ipcTransport:i.z.any().optional()}).strict();function S(e){const t=y.safeParse(e);return t.success?{success:!0,data:t.data}:{success:!1,error:t.error.issues.map(e=>`${e.path.join(".")}: ${e.message}`).join("; ")}}class I{logger;windows=new Map;windowNames=new Map;windowIds=new Map;windowInstanceIds=new Map;_mainWindow=null;groups=new Map;windowGroups=new Map;cleanupTimer=null;constructor(e){this.logger=e}register(e,t,s){this.windows.set(e,s),this.windowNames.set(t,e),this.windowIds.set(e,t),this.windowInstanceIds.set(s,e),this._mainWindow||(this._mainWindow=s)}unregister(e){const t=this.windowGroups.get(e);t&&(t.forEach(t=>{const s=this.groups.get(t);s&&(s.delete(e),0===s.size&&this.groups.delete(t))}),this.windowGroups.delete(e));const s=this.windowIds.get(e);s&&this.windowNames.delete(s);const i=this.windows.get(e);i&&(this.windowInstanceIds.delete(i),this._mainWindow===i&&(this._mainWindow=null)),this.windows.delete(e),this.windowIds.delete(e)}addToGroup(e,t){this.windows.has(e)?(this.groups.has(t)||this.groups.set(t,new Set),this.groups.get(t).add(e),this.windowGroups.has(e)||this.windowGroups.set(e,new Set),this.windowGroups.get(e).add(t)):this.logger.warn(`Cannot add non-existent window ${e} to group ${t}`)}removeFromGroup(e,t){const s=this.groups.get(t);s&&(s.delete(e),0===s.size&&this.groups.delete(t));const i=this.windowGroups.get(e);i&&(i.delete(t),0===i.size&&this.windowGroups.delete(e))}getGroupIds(e){const t=this.groups.get(e);return t?Array.from(t):[]}getWindowGroups(e){const t=this.windowGroups.get(e);return t?Array.from(t):[]}clear(){this.windows.clear(),this.windowNames.clear(),this.windowIds.clear(),this.windowInstanceIds.clear(),this.groups.clear(),this.windowGroups.clear(),this._mainWindow=null,this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null)}getById(e){return this.windows.get(e)}getIdByName(e){return this.windowNames.get(e)}getByName(e){const t=this.windowNames.get(e);return t?this.windows.get(t):void 0}getNameById(e){return this.windowIds.get(e)}getIdByWindow(e){return this.windowInstanceIds.get(e)}hasId(e){return this.windows.has(e)}hasName(e){return this.windowNames.has(e)}getAllIds(){return Array.from(this.windows.keys())}getAllWindows(){return Array.from(this.windows.values())}getNameMap(){return this.windowNames}getCount(){return this.windows.size}setMainWindow(e){this._mainWindow=e}getMainWindow(){return this._mainWindow}updateWindowName(e,t){const s=this.windowIds.get(e);s&&this.windowNames.delete(s),this.windowNames.set(t,e),this.windowIds.set(e,t)}startCleanupProtection(e=3e4){this.cleanupTimer&&clearInterval(this.cleanupTimer),this.cleanupTimer=setInterval(()=>{this.cleanupDestroyedWindows()},e),this.cleanupTimer.unref()}stopCleanupProtection(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null)}cleanupDestroyedWindows(){if(this.windows.size<=50)return void this.performCleanup(Array.from(this.windows.entries()));const e=Array.from(this.windows.entries());this.processCleanupChunk(e,0,50)}processCleanupChunk(e,t,s){if(t>=e.length)return;const i=Math.min(t+s,e.length),r=e.slice(t,i);this.performCleanup(r),i<e.length&&setImmediate(()=>{this.processCleanupChunk(e,i,s)})}performCleanup(e){const t=[];e.forEach(([e,s])=>{s.isDestroyed()&&t.push(e)}),t.length>0&&(this.logger.warn(`Found ${t.length} destroyed windows in registry. Cleaning up...`),t.forEach(e=>this.unregister(e)))}}class v{logger;constructor(e){this.logger=e}isSafe(e){return!!e&&!e.isDestroyed()}show(e){this.isSafe(e)&&(e.show(),e.setSkipTaskbar(!1))}hide(e){this.isSafe(e)&&(e.hide(),e.setSkipTaskbar(!0))}minimize(e){this.isSafe(e)&&e.minimize()}restore(e){this.isSafe(e)&&e.restore()}maximize(e){this.isSafe(e)&&e.maximize()}unmaximize(e){this.isSafe(e)&&e.unmaximize()}toggleFullScreen(e){this.isSafe(e)&&e.setFullScreen(!e.isFullScreen())}focus(e){this.isSafe(e)&&e.focus()}close(e){this.isSafe(e)&&e.close()}destroy(e){this.isSafe(e)&&e.destroy()}openDevTools(e){this.isSafe(e)&&e.webContents.openDevTools()}closeDevTools(e){this.isSafe(e)&&e.webContents.closeDevTools()}isDevToolsOpened(e){return!!this.isSafe(e)&&e.webContents.isDevToolsOpened()}send(e,t,s){this.isSafe(e)&&e.webContents.send(t,s)}setSkipTaskbar(e,t){this.isSafe(e)&&e.setSkipTaskbar(t)}}class E{persistence;logger;constructor(e,t){this.persistence=e,this.logger=t}async save(e,t){if(this.persistence)try{await this.persistence.save(e,t)}catch(t){this.logger.error(`Failed to save context for window ${e}: ${t}`)}else this.logger.warn("Context persistence is not enabled")}async load(e){if(!this.persistence)return null;try{return await this.persistence.load(e)}catch(t){return this.logger.error(`Failed to load context for window ${e}: ${t}`),null}}async clear(e){if(this.persistence)try{await this.persistence.clear(e)}catch(t){this.logger.error(`Failed to clear context for window ${e}: ${t}`)}}}class M{stateFile;state={};logger;saveTimer=null;throttleLastSave=0;saveDelay;saveStrategy;static activeFiles=new Set;hasLock=!1;isWriting=!1;pendingWrite=!1;lastSavedHash="";constructor(e={}){this.logger=e.logger||new w({appName:"StateKeeper"}),this.saveDelay=e.saveDelay??500,this.saveStrategy=e.saveStrategy??"debounce";const s=t.app.getPath("userData");this.stateFile=e.stateFilePath||g.join(s,"window-state.json"),M.activeFiles.has(this.stateFile)?(this.logger.warn(`State file "${this.stateFile}" is already in use by another StateKeeper instance. This may lead to data conflicts.`),this.hasLock=!1):(M.activeFiles.add(this.stateFile),this.hasLock=!0),this.loadState(),t.app.on("before-quit",()=>{this.flushSync()})}loadState(){try{if(l.existsSync(this.stateFile)){const e=l.readFileSync(this.stateFile,"utf-8");this.state=JSON.parse(e),this.lastSavedHash=u.createHash("md5").update(e).digest("hex")}}catch(e){this.logger.error(`Failed to load window state: ${e}`),this.state={}}}saveState(e,t){(function(e,t){if(e===t)return!0;if(!e||!t)return!1;const s=e.groups||[],i=t.groups||[],r=s.length===i.length&&[...s].sort().every((e,t)=>e===[...i].sort()[t]);return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height&&e.isMaximized===t.isMaximized&&e.isFullScreen===t.isFullScreen&&r&&(!e.displayBounds&&!t.displayBounds||!!e.displayBounds&&!!t.displayBounds&&e.displayBounds.x===t.displayBounds.x&&e.displayBounds.y===t.displayBounds.y&&e.displayBounds.width===t.displayBounds.width&&e.displayBounds.height===t.displayBounds.height)})(this.state[e],t)||(this.state[e]=t,this.persist())}flushSync(){this.saveTimer&&(clearTimeout(this.saveTimer),this.saveTimer=null);try{l.writeFileSync(this.stateFile,JSON.stringify(this.state,null,2))}catch(e){this.logger.error(`Failed to flush window state: ${e}`)}}persist(){if("throttle"===this.saveStrategy){const e=Date.now(),t=e-this.throttleLastSave;t>=this.saveDelay?(this.performSave(),this.throttleLastSave=e):(this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.performSave(),this.throttleLastSave=Date.now()},this.saveDelay-t))}else this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.performSave()},this.saveDelay)}async performSave(){if(this.isWriting)return void(this.pendingWrite=!0);this.isWriting=!0;const e=`${this.stateFile}.tmp`;try{const t=JSON.stringify(this.state,null,2),s=u.createHash("md5").update(t).digest("hex");if(s===this.lastSavedHash)return void(this.isWriting=!1);await l.promises.writeFile(e,t),await l.promises.rename(e,this.stateFile),this.lastSavedHash=s}catch(t){this.logger.error(`Failed to save window state: ${t}`);try{await l.promises.unlink(e)}catch(e){}}finally{this.saveTimer=null,this.isWriting=!1,this.pendingWrite&&(this.pendingWrite=!1,setImmediate(()=>this.performSave()))}}getWindowState(e,t=800,s=600){const i=this.state[e];return i&&this.isValidState(i)?i:{width:t,height:s,isMaximized:!1,isFullScreen:!1}}isValidState(e){const s=t.screen.getAllDisplays();return!(!e.displayBounds||!s.find(t=>t.bounds.x===e.displayBounds?.x&&t.bounds.y===e.displayBounds?.y&&t.bounds.width===e.displayBounds?.width&&t.bounds.height===e.displayBounds?.height)||void 0===e.x||void 0===e.y)||s.some(t=>{const{x:s,y:i,width:r,height:o}=t.bounds,n=e.x||0,a=e.y||0,d=e.width,h=e.height;return n<s+r&&n+d>s&&a<i+o&&a+h>i})}removeState(e){this.state[e]&&(delete this.state[e],this.persist())}dispose(){this.saveTimer&&(clearTimeout(this.saveTimer),this.saveTimer=null),this.hasLock&&M.activeFiles.delete(this.stateFile)}}class T{logger;stateKeeper;handlers=new Map;constructor(e,t){this.logger=e,this.stateKeeper=t||new M({logger:this.logger})}manage(e,s,i){this.unmanage(s.id);const r=()=>{if(!s.isDestroyed())try{const r=s.getBounds(),o=s.isMaximized(),n=s.isFullScreen(),a=t.screen.getDisplayMatching(r),d=i?i():void 0;this.stateKeeper.saveState(e,{x:r.x,y:r.y,width:r.width,height:r.height,isMaximized:o,isFullScreen:n,displayBounds:a.bounds,groups:d})}catch(t){this.logger.warn(`Failed to save state for window ${e}: ${t}`)}};s.on("resize",r),s.on("move",r),s.on("close",r),s.on("maximize",r),s.on("unmaximize",r),s.on("enter-full-screen",r),s.on("leave-full-screen",r),this.handlers.set(s.id,()=>{s.isDestroyed()||(s.removeListener("resize",r),s.removeListener("move",r),s.removeListener("close",r),s.removeListener("maximize",r),s.removeListener("unmaximize",r),s.removeListener("enter-full-screen",r),s.removeListener("leave-full-screen",r))}),s.once("closed",()=>{this.handlers.delete(s.id)})}unmanage(e){const t=this.handlers.get(e);t&&(t(),this.handlers.delete(e))}dispose(){this.handlers.forEach(e=>e()),this.handlers.clear(),this.stateKeeper&&"function"==typeof this.stateKeeper.dispose&&this.stateKeeper.dispose()}getState(e,t,s){return this.stateKeeper.getWindowState(e,t,s)}}const W="renderer-to-main",b="renderer-to-main-sync",N="message-bus-port",D="window-state-changed";class C extends o.EventEmitter{MAX_WINDOWS;enablePersistence=!1;logger;get persistenceEnabled(){return this.enablePersistence}registry;operator;contextManager;stateManager;focusHistory=[];constructor(e){super(),this.logger=e?.logger||new w({appName:"WindowStore"}),this.MAX_WINDOWS=e?.maxWindows||50,this.enablePersistence=e?.enablePersistence??!1,this.registry=new I(this.logger),this.operator=new v(this.logger),this.contextManager=new E(e?.contextPersistence,this.logger),this.stateManager=new T(this.logger,e?.stateKeeper),!1!==e?.autoStartCleanup&&this.startCleanupProtection(e?.cleanupInterval)}pushFocus(e){this.focusHistory=this.focusHistory.filter(t=>t!==e),this.focusHistory.push(e)}removeFocus(e){this.focusHistory=this.focusHistory.filter(t=>t!==e)}getPreviousFocusedWindow(){if(!(this.focusHistory.length<2))return this.focusHistory[this.focusHistory.length-2]}popFocus(){return this.focusHistory.pop()}joinGroup(e,t){this.registry.addToGroup(e,t)}leaveGroup(e,t){this.registry.removeFromGroup(e,t)}getGroup(e){return this.registry.getGroupIds(e)}async closeGroup(e){const t=this.registry.getGroupIds(e);if(!t||0===t.length)return;const s=t.map(t=>new Promise(s=>{try{setImmediate(()=>{this.operator.destroy(this.getTargetWindow(t)),s()})}catch(i){this.logger.error(`Failed to close window ${t} in group ${e}: ${i}`),s()}}));await Promise.all(s)}hideGroup(e){this.registry.getGroupIds(e).forEach(e=>this.hide(e))}showGroup(e){this.registry.getGroupIds(e).forEach(e=>{const t=this.getTargetWindow(e);t&&this.show(t)})}focusGroup(e){this.registry.getGroupIds(e).forEach(e=>this.focus(e))}show(e,t){this.operator.show(e)}hide(e){const t=this.getTargetWindow(e);t&&this.operator.hide(t)}isDestroyed(e){const t=this.getTargetWindow(e);return!t||t.isDestroyed()}isVisible(e){const t=this.getValidWindow(e);return t?.isVisible()||!1}isMinimized(e){return this.getTargetWindow(e)?.isMinimized()||!1}isMaximized(e){return this.getTargetWindow(e)?.isMaximized()||!1}fullScreenState(e){return this.getTargetWindow(e)?.isFullScreen()||!1}minimize(e){const t=this.getTargetWindow(e);t&&this.operator.minimize(t)}restore(e){const t=this.getValidWindow(e);t&&this.operator.restore(t)}maximize(e){const t=this.getValidWindow(e);t&&this.operator.maximize(t)}unmaximize(e){const t=this.getValidWindow(e);t&&this.operator.unmaximize(t)}fullScreen(e){const t=this.getValidWindow(e);t&&this.operator.toggleFullScreen(t)}focus(e){const t=this.getValidWindow(e);t&&this.operator.focus(t)}setMovable(e){e.setMovable(!0)}winClose(e){this.removeWindow(e)}openDevTools(e){const t=this.getTargetWindow(e);t&&this.operator.openDevTools(t)}isDevToolsOpened(e){const t=this.getTargetWindow(e);return!!t&&this.operator.isDevToolsOpened(t)}closeDevTools(e){const t=this.getTargetWindow(e);t&&this.operator.closeDevTools(t)}quit(){t.app.quit()}getWindowSize(){const{width:e,height:s}=t.screen.getPrimaryDisplay().workAreaSize;return{width:e,height:s}}send(e,t,s=""){const i=this.getTargetWindow(e);i&&this.operator.send(i,t,s)}setSkipTaskbar(e,t){const s=this.getTargetWindow(e);s&&this.operator.setSkipTaskbar(s,t)}get mainWindow(){return this.registry.getMainWindow()}set mainWindow(e){this.registry.setMainWindow(e)}getWindowCount(){return this.registry.getCount()}getAllWindowKeys(){return this.registry.getAllIds()}getAllWindows(){return this.registry.getAllWindows()}getWindowNames(){return this.registry.getNameMap()}getNameByWindowId(e){return this.registry.getNameById(e)}getWindowByNameId(e){return this.registry.getIdByName(e)}getWindowByName(e){return this.registry.getByName(e)}hasByName(e){return this.registry.hasName(e)}deleteByName(e){const t=this.registry.getIdByName(e);return!!t&&(this.registry.unregister(t),!0)}getWindowById(e){return this.registry.getById(e)}hasById(e){return this.registry.hasId(e)}deleteById(e){return!!this.registry.hasId(e)&&(this.registry.unregister(e),!0)}getWindowId(e){return this.registry.getIdByWindow(e)}updateWindowName(e,t){this.registry.updateWindowName(e,t)}getTargetWindow(e){return e?this.registry.getById(e)||this.registry.getByName(e):this.getCurrentWindow()}getValidWindow(e){const t=this.getTargetWindow(e);if(t&&!t.isDestroyed())return t;this.logger.warn(`Window ${e||"current"} not found or destroyed`)}getCurrentWindow(){const e=t.BrowserWindow.getFocusedWindow();return e&&!e.isDestroyed()?e:this.mainWindow??void 0}createWindow(e,t){if(this.registry.getCount()>=this.MAX_WINDOWS){const e=new Error(`Maximum window limit (${this.MAX_WINDOWS}) reached`);throw this.logger.error(e.message),e}const s=t?.windowId||r.v4();let i=t?.name||`window-${s}`;try{i=this.validateWindowName(i)}catch{this.logger.warn(`Window name "${i}" already exists, generating unique name`),i=`${i}-${Date.now()}`}return this.registerWindow(s,i,e,{enablePersistence:t?.enablePersistence}),s}removeWindow(e){const t=this.registry.getById(e);if(t&&!t.isDestroyed())try{this.operator.close(t),t.isDestroyed()||this.operator.destroy(t)}catch(t){this.logger.error(`Failed to remove window ${e}: ${t}`),this.emit("error",t)}this.registry.unregister(e)}validateWindowName(e){if(this.registry.hasName(e))throw new Error(`Window name "${e}" already exists`);return e}registerWindow(e,t,s,i){this.registry.register(e,t,s),(i?.enablePersistence??this.enablePersistence)&&this.stateManager.manage(t,s)}manageState(e,t,s){this.stateManager.manage(e,t,s)}getWindowGroups(e){return this.registry.getWindowGroups(e)}getWindowState(e,t,s){return this.stateManager.getState(e,t,s)}async saveWindowContext(e,t){await this.contextManager.save(e,t)}async loadWindowContext(e){return await this.contextManager.load(e)}async clearWindowContext(e){await this.contextManager.clear(e)}startCleanupProtection(e=3e4){this.registry.startCleanupProtection(e)}stopCleanupProtection(){this.registry.stopCleanupProtection()}async dispose(){this.logger.info("Disposing WindowStore..."),this.stopCleanupProtection();const e=this.getAllWindows();for(const t of e)t.isDestroyed()||t.close();this.registry.clear(),this.logger.info("WindowStore disposed")}}const O=()=>{};let R=class{channels=new Map;handlers=new Set;logger;constructor(e){this.logger=e||new w({appName:"IpcTransport"})}setLogger(e){this.logger=e}on(e,s=O){const i=async(t,...i)=>{try{this.logEvent(e,"on",i),await s(t,...i)}catch(s){this.logError(e,"on",s),t.sender.isDestroyed()||t.sender.send(`${e}:error`,this.serializeError(s))}};this.channels.has(e)||this.channels.set(e,new Map),this.channels.get(e).set(s,i),t.ipcMain.on(e,i)}handle(e,s=O){this.handlers.has(e)&&t.ipcMain.removeHandler(e),this.handlers.add(e),t.ipcMain.handle(e,async(t,...i)=>{try{return this.logEvent(e,"handle",i),{code:0,message:"success",data:await s(t,...i)}}catch(t){this.logError(e,"handle",t);const s="development"===process.env.NODE_ENV;return t&&"object"==typeof t&&"code"in t&&"category"in t?{code:t.code,message:t.message,data:null,category:t.category,details:t.details,stack:s?t.stack:void 0}:{code:t.code||500,message:t instanceof Error?t.message:String(t),data:null,stack:s&&t instanceof Error?t.stack:void 0}}})}removeListener(e,s){const i=this.channels.get(e);if(i){if(s){const r=i.get(s);r&&(t.ipcMain.removeListener(e,r),i.delete(s))}else{for(const s of i.values())t.ipcMain.removeListener(e,s);i.clear()}0===i.size&&this.channels.delete(e)}}removeAllListeners(e){if(e)this.removeListener(e);else{for(const e of this.channels.keys())this.removeListener(e);this.channels.clear()}}removeHandler(e){this.handlers.has(e)&&(t.ipcMain.removeHandler(e),this.handlers.delete(e))}removeAllHandlers(){for(const e of this.handlers)t.ipcMain.removeHandler(e);this.handlers.clear()}error(e){this.logger.error(`[IPC System Error]: ${e}`)}log(e){this.logger.info(`[IPC System Log]: ${e}`)}logEvent(e,t,s){try{const i=s[0]?.name,r=i?`[Action: ${i}]`:`[Args: ${this.safeStringify(s)}]`;this.logger.info(`[${t.toUpperCase()}] ${e} ${r}`)}catch{this.logger.info(`[${t.toUpperCase()}] ${e} [Args parsing failed]`)}}logError(e,t,s){const i=s instanceof Error?s.message:String(s),r=s instanceof Error?s.stack:"";this.logger.error(`[${t.toUpperCase()} ERROR] ${e}: ${i}`,r)}serializeError(e){if(e instanceof Error){const t={name:e.name,message:e.message,stack:e.stack};for(const s of Object.getOwnPropertyNames(e))["name","message","stack"].includes(s)||(t[s]=e[s]);return t}return"object"==typeof e&&null!==e?e:{message:String(e),name:"UnknownError"}}safeStringify(e){try{return JSON.stringify(e)}catch{return"[Circular or Non-serializable]"}}};class _{static defaultSetup(e,t){return _.setup({config:e.config,ipcRouter:e.ipcRouter,currentIpcChannel:e.currentIpcChannel,currentIpcSyncChannel:e.currentIpcSyncChannel,options:t})}static setup(e){const{config:t,ipcRouter:s,currentIpcChannel:i,currentIpcSyncChannel:r,options:o}=e,n=e.ipcTransport||new R,a=o?.channel||t.ipc?.channel||W,d=o?.syncChannel||t.ipc?.syncChannel||b;return i&&n.removeHandler(i),r&&n.removeListener(r),n.handle(a,async(e,t)=>{try{const i=e.sender?.id;return{code:0,message:"success",data:await s.handle(t,i)}}catch(e){return{code:e.code||500,message:e instanceof Error?e.message:String(e),data:null}}}),d&&n.on(d,(e,t)=>{try{const i=s.handle(t);e.returnValue={code:0,message:"success",data:i}}catch(t){e.returnValue={code:t.code||500,message:t instanceof Error?t.message:String(t),data:null}}}),{channel:a,syncChannel:d,ipcTransport:n}}}class P{metrics={creationTimes:[],totalCreated:0,totalDestroyed:0};recordCreation(e){this.metrics.creationTimes.push(e),this.metrics.totalCreated++}recordDestruction(){this.metrics.totalDestroyed++}getMetrics(e){const t=this.metrics.creationTimes.length>0?this.metrics.creationTimes.reduce((e,t)=>e+t,0)/this.metrics.creationTimes.length:0;return{windowCount:e,totalCreated:this.metrics.totalCreated,totalDestroyed:this.metrics.totalDestroyed,averageCreationTime:Math.round(t),memoryUsage:process.memoryUsage(),uptime:process.uptime()}}}class ${plugins=[];hooks={};logger;constructor(e,t=[],s={}){this.logger=e,this.plugins=t,this.hooks=s}addPlugin(e){this.plugins.push(e)}getPlugins(){return this.plugins}async initPlugins(e){for(const t of this.plugins)try{await(t.onInit?.(e))}catch(e){this.logger.error(`Plugin "${t.name}" initialization failed: ${e}`)}}async initPlugin(e,t){try{await(e.onInit?.(t))}catch(t){this.logger.error(`Plugin "${e.name}" initialization failed: ${t}`)}}onWillCreate(e){let t={...e};for(const e of this.plugins)if(e.onWillCreate){const s=e.onWillCreate(t);if(!1===s)return!1;s&&"object"==typeof s&&(t=s)}if(this.hooks.onWillCreate){const e=this.hooks.onWillCreate(t);if(!1===e)return!1;e&&"object"==typeof e&&(t=e)}return t}async onDidCreate(e){for(const t of this.plugins)try{await(t.onDidCreate?.(e))}catch(e){this.logger.error(`Plugin ${t.name} onDidCreate failed: ${e}`)}if(this.hooks.onDidCreate)try{await this.hooks.onDidCreate(e)}catch(e){this.logger.error(`Hook onDidCreate failed: ${e}`)}}async onWillDestroy(e){for(const t of this.plugins)try{await(t.onWillDestroy?.(e))}catch(e){this.logger.error(`Plugin ${t.name} onWillDestroy failed: ${e}`)}if(this.hooks.onWillDestroy)try{await this.hooks.onWillDestroy(e)}catch(e){this.logger.error(`Hook onWillDestroy failed: ${e}`)}}async onDidDestroy(e){for(const t of this.plugins)try{await(t.onDidDestroy?.(e))}catch(e){this.logger.error(`Plugin ${t.name} onDidDestroy failed: ${e}`)}if(this.hooks.onDidDestroy)try{await this.hooks.onDidDestroy(e)}catch(e){this.logger.error(`Hook onDidDestroy failed: ${e}`)}}}class k{static instance;logger;registry=new Map;performanceMetrics=[];metricsEnabled=!1;constructor(){this.logger=new w({appName:"DebugHelper"})}static getInstance(){return k.instance||(k.instance=new k),k.instance}register(e,t){this.registry.set(e,t),this.logger.info(`Registered component: ${e}`)}get(e){return this.registry.get(e)}getAll(){const e={};return this.registry.forEach((t,s)=>{e[s]=t}),e}enablePerformanceMonitoring(){this.metricsEnabled=!0,this.logger.info("Performance monitoring enabled")}disablePerformanceMonitoring(){this.metricsEnabled=!1,this.logger.info("Performance monitoring disabled")}recordMetric(e){this.metricsEnabled&&(this.performanceMetrics.push(e),this.performanceMetrics.length>1e3&&this.performanceMetrics.shift(),this.logger.info(`Performance: ${e.name} took ${e.duration.toFixed(2)}ms`,e.metadata))}getMetrics(){return[...this.performanceMetrics]}clearMetrics(){this.performanceMetrics=[],this.logger.info("Performance metrics cleared")}getStatistics(){const e={};return this.performanceMetrics.forEach(t=>{e[t.name]||(e[t.name]={count:0,total:0,min:1/0,max:-1/0,avg:0});const s=e[t.name];s.count++,s.total+=t.duration,s.min=Math.min(s.min,t.duration),s.max=Math.max(s.max,t.duration),s.avg=s.total/s.count}),e}createTimer(e,t){const s=performance.now();return()=>{const i=performance.now()-s;this.recordMetric({name:e,duration:i,timestamp:Date.now(),metadata:t})}}getWindowManagerInfo(){const e=this.registry.get("windowManager");if(!e)return null;try{const t=e.getAllWindows();return{windowCount:t.length,windows:t.map(e=>({isDestroyed:e.isDestroyed(),isVisible:e.isVisible(),isMinimized:e.isMinimized(),isMaximized:e.isMaximized(),title:e.getTitle()}))}}catch(e){return this.logger.error("Failed to get WindowManager info:",e),{error:"Failed to retrieve info"}}}getIpcRouterInfo(){return this.registry.get("ipcRouter")?{registered:!0,type:"IpcRouter"}:null}getMessageBusInfo(){const e=this.registry.get("messageBus");return e?{registeredWindows:e.getRegisteredWindows(),data:e.getData()}:null}getDebugSnapshot(){return{timestamp:Date.now(),components:{windowManager:this.getWindowManagerInfo(),ipcRouter:this.getIpcRouterInfo(),messageBus:this.getMessageBusInfo()},performance:{metrics:this.getMetrics(),statistics:this.getStatistics()}}}logSnapshot(){const e=this.getDebugSnapshot();console.log("=== Debug Snapshot ==="),console.log(JSON.stringify(e,null,2))}}const B=k.getInstance();class A{static instance;metrics=new Map;logger;constructor(e){this.logger=e||new w({appName:"PerformanceMonitor"})}static getInstance(e){return A.instance||(A.instance=new A(e)),A.instance}startMeasure(e,t,s){this.metrics.set(e,{name:t,startTime:performance.now(),metadata:s})}endMeasure(e,t){const s=this.metrics.get(e);if(!s)return;const i=performance.now()-s.startTime;return this.logger.info(`[Performance] ${s.name}: ${i.toFixed(2)}ms`,{...s.metadata,...t,duration:i}),this.metrics.delete(e),i}recordMetric(e,t,s){this.logger.info(`[Metric] ${e}: ${t}`,s)}}class L{static isDebugEnabled=!1;static enableDebugMode(){this.isDebugEnabled||(process.env.ELECTRON_TOOLKIT_DEBUG="true",this.isDebugEnabled=!0,"browser"===process.type&&(global.__ELECTRON_TOOLKIT_DEBUG__={instances:{},listInstances:()=>Object.keys(global.__ELECTRON_TOOLKIT_DEBUG__.instances),getInstance:e=>global.__ELECTRON_TOOLKIT_DEBUG__.instances[e]},console.log("[ElectronToolkit] Debug mode enabled. Access global.__ELECTRON_TOOLKIT_DEBUG__ for details.")))}static register(e,t){"browser"===process.type&&global.__ELECTRON_TOOLKIT_DEBUG__&&(global.__ELECTRON_TOOLKIT_DEBUG__.instances[e]=t)}}class x{api;data;winId;creator;extraOptions;logger;constructor(e,t,s,i,r){this.api=e,this.data=t,this.winId=t?.data?.winId||"",this.creator=s,this.extraOptions=i,this.logger=r||new w({appName:"WindowCreator"})}async createWindow(){let e=!1;if(this.winId&&this.api.window.hasById(this.winId)){if(!this.api.window.isDestroyed(this.winId))return{winId:this.winId,isNew:!1};this.logger.warn(`Window ${this.winId} is found in store but destroyed. Cleaning up and recreating.`),await this.api.window.removeWindow(this.winId)}const t=this.winId?{windowId:this.winId,...this.extraOptions?.(this.data.data)||{}}:this.data.data;return this.winId=await this.creator(t),e=!0,{winId:this.winId,isNew:!0}}showWindow(e,t){const s=this.api.window.getTargetWindow(e);s&&!s.isDestroyed()?t?s.once("ready-to-show",()=>{this.api.window.show(s,e)}):this.api.window.show(s,e):this.logger.error(`Failed to show window ${e}: Window not found or destroyed`)}async loadContent(e,t){const s=this.api.window.getTargetWindow(e);if(s&&!s.isDestroyed())if(t.loadWindowContent)try{await t.loadWindowContent(s)}catch(t){this.logger.error(`Custom loadWindowContent failed for window ${e}: ${t}`)}else if(this.data.contentLoader)try{await this.data.contentLoader(s,t)}catch(t){this.logger.error(`Global contentLoader failed for window ${e}: ${t}`)}else t.loadUrl?s.loadURL(t.loadUrl).catch(s=>{this.logger.error(`Failed to load URL "${t.loadUrl}" for window ${e}: ${s}`)}):t.loadFile&&s.loadFile(t.loadFile).catch(s=>{this.logger.error(`Failed to load file "${t.loadFile}" for window ${e}: ${s}`)})}async createAndShow(){try{const{isNew:e}=await this.createWindow();if(e){const e=this.winId?{windowId:this.winId,...this.extraOptions?.(this.data.data)||{}}:this.data.data;await this.loadContent(this.winId,e)}return this.showWindow(this.winId,e),this.winId}catch(e){throw this.logger.error(`Failed to create and show window: ${e}`),e}}}const z=!t.app.isPackaged;class F{wm;pluginExecutor;metrics;logger;constructor(e,t,s,i){this.wm=e,this.pluginExecutor=t,this.metrics=s,this.logger=i}async create(e={}){const s=Date.now(),i=A.getInstance(),r=`create-window-${Date.now()}`;i.startMeasure(r,"Window Creation",{name:e.name});const o=this.pluginExecutor.onWillCreate(e);if(!1===o)return"";(e=o).defaultConfig&&(this.wm.config.defaultConfig=e.defaultConfig),this.wm.config.isDevelopment=e.isDevelopment??z,this.logger.info(`Current Environment / 当前环境: ${JSON.stringify({appIsPackaged:t.app.isPackaged,cachedIsDev:z,finalConfigIsDev:this.wm.config.isDevelopment},null,2)}`);const n={window:{hasById:e=>this.wm.windowStore.hasById(e),isDestroyed:e=>this.wm.windowStore.isDestroyed(e),deleteByName:e=>{const t=this.wm.windowStore.getWindowByNameId(e);return!!t&&(this.removeWindow(t),!0)},deleteById:e=>!!this.wm.windowStore.hasById(e)&&(this.removeWindow(e),!0),getTargetWindow:e=>this.wm.windowStore.getTargetWindow(e),removeWindow:e=>this.removeWindow(e),show:(e,t)=>this.wm.windowStore.show(e,t)}},a=e.windowId||(e.name?this.wm.windowStore.getWindowByNameId(e.name):void 0);e.windowId&&this.wm.validateWindowId(e.windowId,"create");let d={...e};const h=e.enablePersistence??this.wm.windowStore.persistenceEnabled;if(h&&e.name){const t=this.wm.windowStore.getWindowState(e.name,e.width,e.height);t&&(d={...d,x:t.x,y:t.y,width:t.width,height:t.height,fullscreen:t.isFullScreen||e.fullscreen})}const c=new x(n,{data:{...d,winId:a},contentLoader:this.wm.config.contentLoader},async t=>{const s=this.wm.createBrowserWindow(t);if(h&&e.name){const t=this.wm.windowStore.getWindowState(e.name);t?.isMaximized&&!s.isFullScreen()&&s.maximize()}const i=this.wm.windowStore.createWindow(s,t);if(this.wm.configureWindowBehavior(s,i),t.name){const e=this.wm.windowStore.getWindowState(t.name);e&&e.groups&&Array.isArray(e.groups)&&e.groups.forEach(e=>{this.wm.windowStore.joinGroup(i,e)}),this.registerStateManagement(t.name,s)}const r={window:s,id:i,name:t.data.name||""};return await this.pluginExecutor.onDidCreate(r),this.wm.emit("window-created",r),i},void 0,this.logger),l=await c.createAndShow(),g=Date.now()-s;return this.metrics.recordCreation(g),g>2e3&&this.logger.warn(`Slow window creation detected: ${l} took ${g}ms`),i.endMeasure(r,{windowId:l}),l}async removeWindow(e){const t=A.getInstance(),s=`destroy-window-${e}`;t.startMeasure(s,"Window Destruction",{windowId:e}),this.wm.validateWindowId(e,"removeWindow"),await this.pluginExecutor.onWillDestroy(e),this.wm.emit("window-will-be-destroyed",e),this.wm.windowStore.removeWindow(e),this.metrics.recordDestruction(),await this.pluginExecutor.onDidDestroy(e),this.wm.emit("window-destroyed",e),t.endMeasure(s,{windowId:e})}registerStateManagement(e,t){this.wm.windowStore.persistenceEnabled&&this.wm.windowStore.manageState(e,t,()=>this.wm.windowStore.getWindowGroups(t.id.toString()))}}class G extends s.TypedEmitter{config={};ipcRouter;ipcTransport;messageBus;currentIpcChannel=null;currentIpcSyncChannel=null;logger;windowStore;metricsManager;pluginExecutor;lifecycle;isInitialized=!1;initPromise;initError=null;constructor(e={}){super();const t=S(e);if(!t.success)throw new Error(`Invalid WindowManager configuration: ${t.error}`);if(this.config=t.data,this.ipcRouter=this.config.ipcRouter,this.ipcTransport=this.config.ipcTransport,this.messageBus=this.config.messageBus,this.logger=this.config.logger||new w({appName:"WindowManager"}),e.logger){const t=["info","warn","error","debug"];for(const s of t)if("function"!=typeof e.logger[s])throw new Error(`config.logger must have ${t.join("/")} methods`)}if(e.ipcRouter&&"function"!=typeof e.ipcRouter.handle)throw new Error("config.ipcRouter must have handle/addHandler methods");this.windowStore=new C({logger:this.logger,...e.store||{}}),this.windowStore.on("error",e=>this.emit("error",e)),this.metricsManager=new P,this.pluginExecutor=new $(this.logger,e.plugins,e.hooks),this.lifecycle=new F(this,this.pluginExecutor,this.metricsManager,this.logger),this.messageBus&&this.messageBus.setGroupResolver(e=>this.windowStore.getGroup(e)),this.initPromise=this.init().then(async()=>{if(this.ipcRouter&&!1!==this.config.ipc?.autoInit)try{this.setupIPC()}catch(e){throw this.logger.warn(`Auto IPC setup failed: ${e}`),e}}).catch(e=>{throw this.initError=e instanceof Error?e:new Error(String(e)),this.logger.error(`WindowManager initialization failed: ${this.initError.message}`),this.emit("error",this.initError),this.initError})}async ready(){if(this.initError)throw this.initError;return this.initPromise}get initialized(){return this.isInitialized&&!this.initError}get initializationError(){return this.initError}async init(){this.isInitialized||(this.isInitialized=!0,await this.pluginExecutor.initPlugins(this))}use(e){return this.pluginExecutor.addPlugin(e),this.isInitialized&&this.pluginExecutor.initPlugin(e,this),this}setupIPC(e){let t;if(t=e?.setupImpl?e.setupImpl({config:this.config,ipcRouter:this.ipcRouter,currentIpcChannel:this.currentIpcChannel,currentIpcSyncChannel:this.currentIpcSyncChannel,options:e}):this.config.ipcSetup?this.config.ipcSetup(this,e):_.setup({config:this.config,ipcRouter:this.ipcRouter,currentIpcChannel:this.currentIpcChannel,currentIpcSyncChannel:this.currentIpcSyncChannel,options:e}),t)return this.currentIpcChannel=t.channel,this.currentIpcSyncChannel=t.syncChannel,void(t.ipcTransport&&(this.ipcTransport=t.ipcTransport));if(!this.ipcRouter)throw new Error("IpcRouter instance is required for IPC setup. Please pass it to the WindowManager constructor.")}async create(e={}){const t=A.getInstance(),s=`window-create-${Date.now()}`;t.startMeasure(s,"Window Creation",{name:e.name,width:e.width,height:e.height});try{const i=await this.lifecycle.create(e);return t.endMeasure(s,{status:"success",windowId:i}),i}catch(e){throw t.endMeasure(s,{status:"error",error:e instanceof Error?e.message:String(e)}),e}}async removeWindow(e){return this.lifecycle.removeWindow(e)}getMetrics(){return this.metricsManager.getMetrics(this.getWindowCount())}dispose(){this.logger.info("Disposing WindowManager..."),this.getAllWindowKeys().forEach(e=>{try{this.removeWindow(e)}catch(t){this.logger.error(`Failed to remove window ${e}: ${t}`)}}),this.windowStore.dispose(),this.ipcTransport&&(this.ipcTransport.removeAllHandlers(),this.ipcTransport.removeAllListeners()),this.ipcRouter&&"function"==typeof this.ipcRouter.dispose&&this.ipcRouter.dispose(),this.removeAllListeners(),this.logger.info("WindowManager disposed")}getMainWindowId(){return this.windowStore.mainWindow?this.windowStore.getWindowId(this.windowStore.mainWindow):void 0}createBrowserWindow(e){const s=this.getDefaultWindowConfig();return new t.BrowserWindow({...s,...e})}getDefaultWindowConfig(){return this.config.defaultConfig||{width:800,height:600,show:!1,webPreferences:{nodeIntegration:!1,contextIsolation:!0}}}configureWindowBehavior(e,s){this.config.isDevelopment&&this.windowStore.openDevTools(s),!1!==this.config.preventExternalLinks&&e.webContents.setWindowOpenHandler(e=>(t.shell.openExternal(e.url),{action:"deny"})),e.once("ready-to-show",()=>this.windowStore.show(e,s)),e.on("closed",()=>{this.windowStore.removeFocus(s),this.removeWindow(s)}),e.webContents.on("render-process-gone",(t,i)=>{this.logger.error(`Window ${s} crashed: ${i.reason} (Exit Code: ${i.exitCode})`);const{reason:r}=i;"crashed"!==r&&"oom"!==r||(this.logger.info(`Attempting to reload window ${s}...`),setTimeout(()=>{e.isDestroyed()||e.reload()},1e3))}),e.on("unresponsive",()=>{this.logger.warn(`Window ${s} is unresponsive`)}),e.on("focus",()=>{this.windowStore.pushFocus(s)}),e.isVisible()&&e.isFocused()&&this.windowStore.pushFocus(s)}joinGroup(e,t){this.windowStore.joinGroup(e,t)}leaveGroup(e,t){this.windowStore.leaveGroup(e,t)}getGroup(e){return this.windowStore.getGroup(e)}async closeGroup(e){await this.windowStore.closeGroup(e)}hideGroup(e){this.windowStore.hideGroup(e)}showGroup(e){this.windowStore.showGroup(e)}focusGroup(e){this.windowStore.focusGroup(e)}sendToGroup(e,t,s){if(!this.messageBus)return this.logger.warn("[WindowManager.sendToGroup] MessageBus not configured"),0;const i=this.windowStore.getGroup(e);return this.messageBus.broadcastToWindows(i,t,s)}focusPrevious(){const e=this.windowStore.getPreviousFocusedWindow();e&&this.windowStore.focus(e)}validateWindowId(e,t){if(!e||"string"!=typeof e||""===e.trim())throw new Error(`[WindowManager.${t}] Invalid windowId: must be a non-empty string`);return e}show(e,t){e&&!e.isDestroyed()?(void 0!==t&&this.validateWindowId(t,"show"),this.windowStore.show(e,t)):this.logger.warn("[WindowManager.show] Window is null or destroyed")}hide(e){this.windowStore.hide(this.validateWindowId(e,"hide"))}isDestroyed(e){return this.windowStore.isDestroyed(this.validateWindowId(e,"isDestroyed"))}isVisible(e){return this.windowStore.isVisible(this.validateWindowId(e,"isVisible"))}isMinimized(e){return this.windowStore.isMinimized(this.validateWindowId(e,"isMinimized"))}isMaximized(e){return this.windowStore.isMaximized(this.validateWindowId(e,"isMaximized"))}fullScreenState(e){return this.windowStore.fullScreenState(this.validateWindowId(e,"fullScreenState"))}minimize(e){e&&this.validateWindowId(e,"minimize"),this.windowStore.minimize(e)}restore(e){this.windowStore.restore(this.validateWindowId(e,"restore"))}maximize(e){this.windowStore.maximize(this.validateWindowId(e,"maximize"))}unmaximize(e){this.windowStore.unmaximize(this.validateWindowId(e,"unmaximize"))}fullScreen(e){this.windowStore.fullScreen(this.validateWindowId(e,"fullScreen"))}focus(e){this.windowStore.focus(this.validateWindowId(e,"focus"))}setMovable(e){e&&!e.isDestroyed()&&this.windowStore.setMovable(e)}close(e){this.windowStore.winClose(this.validateWindowId(e,"close"))}winClose(e){this.close(e)}openDevTools(e){this.windowStore.openDevTools(this.validateWindowId(e,"openDevTools"))}isDevToolsOpened(e){return this.windowStore.isDevToolsOpened(this.validateWindowId(e,"isDevToolsOpened"))}closeDevTools(e){this.windowStore.closeDevTools(this.validateWindowId(e,"closeDevTools"))}quit(){this.windowStore.quit()}getWindowSize(){return this.windowStore.getWindowSize()}send(e,t,s=""){this.windowStore.send(e,t,s)}setSkipTaskbar(e,t){this.windowStore.setSkipTaskbar(e,t)}get mainWindow(){return this.windowStore.mainWindow}getWindowCount(){return this.windowStore.getWindowCount()}getAllWindowKeys(){return this.windowStore.getAllWindowKeys()}getAllWindows(){return this.windowStore.getAllWindows()}getWindowNames(){return this.windowStore.getWindowNames()}getNameByWindowId(e){return this.windowStore.getNameByWindowId(e)}getWindowByNameId(e){return this.windowStore.getWindowByNameId(e)}getWindowByName(e){return this.windowStore.getWindowByName(e)}hasByName(e){return this.windowStore.hasByName(e)}deleteByName(e){return this.windowStore.deleteByName(e)}getWindowById(e){return this.windowStore.getWindowById(e)}hasById(e){return this.windowStore.hasById(e)}deleteById(e){return this.windowStore.deleteById(e)}getWindowId(e){return this.windowStore.getWindowId(e)}updateWindowName(e,t){this.windowStore.updateWindowName(e,t)}getTargetWindow(e){return this.windowStore.getTargetWindow(e)}getValidWindow(e){return this.windowStore.getValidWindow(e)}getCurrentWindow(){return this.windowStore.getCurrentWindow()}async saveWindowContext(e,t){await this.windowStore.saveWindowContext(e,t)}async loadWindowContext(e){return await this.windowStore.loadWindowContext(e)}async clearWindowContext(e){await this.windowStore.clearWindowContext(e)}startCleanupProtection(e=3e4){this.windowStore.startCleanupProtection(e)}stopCleanupProtection(){this.windowStore.stopCleanupProtection()}}class H{handlers=new Map;logger;errorHandler;constructor(e,t,s){this.logger=t||new w({appName:e}),this.errorHandler=s}register(e,t,s){this.handlers.has(e)&&this.logger.warn(`Handler "${e}" is being overwritten / 处理器 "${e}" 被覆盖`),this.handlers.set(e,{callback:t,metadata:s})}unregister(e){return this.handlers.delete(e)}getMetadata(e){return this.handlers.get(e)?.metadata}dispatch(e,t,s){const i=this.handlers.get(e);if(i)try{return i.callback(t,s)}catch(t){if(this.logger.error(`Error in handler "${e}": ${t} / 处理器 "${e}" 执行错误: ${t}`),this.errorHandler)return this.errorHandler(t,e);throw t}else this.logger.warn(`No handler found for "${e}" / 未找到处理器 "${e}"`)}has(e){return this.handlers.has(e)}getHandlerNames(){return Array.from(this.handlers.keys())}clear(){this.handlers.clear()}}var U,V,j,q;e.IpcErrorCode=void 0,(U=e.IpcErrorCode||(e.IpcErrorCode={}))[U.SUCCESS=0]="SUCCESS",U[U.BAD_REQUEST=400]="BAD_REQUEST",U[U.FORBIDDEN=403]="FORBIDDEN",U[U.NOT_FOUND=404]="NOT_FOUND",U[U.VALIDATION_ERROR=422]="VALIDATION_ERROR",U[U.INTERNAL_ERROR=500]="INTERNAL_ERROR",U[U.HANDLER_ERROR=501]="HANDLER_ERROR",e.MessageBusErrorCode=void 0,(V=e.MessageBusErrorCode||(e.MessageBusErrorCode={}))[V.SUCCESS=0]="SUCCESS",V[V.PERMISSION_DENIED=403]="PERMISSION_DENIED",V[V.NOT_FOUND=404]="NOT_FOUND",V[V.INVALID_OPERATION=400]="INVALID_OPERATION",V[V.INTERNAL_ERROR=500]="INTERNAL_ERROR",e.WindowManagerErrorCode=void 0,(j=e.WindowManagerErrorCode||(e.WindowManagerErrorCode={}))[j.SUCCESS=0]="SUCCESS",j[j.WINDOW_NOT_FOUND=404]="WINDOW_NOT_FOUND",j[j.WINDOW_ALREADY_EXISTS=409]="WINDOW_ALREADY_EXISTS",j[j.INVALID_CONFIG=400]="INVALID_CONFIG",j[j.CREATION_FAILED=500]="CREATION_FAILED",j[j.OPERATION_FAILED=500]="OPERATION_FAILED",e.ErrorCategory=void 0,(q=e.ErrorCategory||(e.ErrorCategory={})).VALIDATION="VALIDATION",q.PERMISSION="PERMISSION",q.NOT_FOUND="NOT_FOUND",q.INTERNAL="INTERNAL",q.BUSINESS="BUSINESS";class J extends Error{code;category;details;timestamp;constructor(t,s,i=e.ErrorCategory.INTERNAL,r){super(s),this.name="StandardError",this.code=t,this.category=i,this.details=r,this.timestamp=Date.now(),Error.captureStackTrace&&Error.captureStackTrace(this,J)}toResponse(e=!1){return{code:this.code,message:this.message,category:this.category,details:this.details,stack:e?this.stack:void 0,timestamp:this.timestamp}}static from(t,s=500){return t instanceof J?t:t instanceof Error?new J(s,t.message,e.ErrorCategory.INTERNAL,{originalError:t.name,stack:t.stack}):new J(s,String(t),e.ErrorCategory.INTERNAL,{originalError:t})}}class K extends Error{code;details;constructor(e,t,s){super(e),this.code=t,this.details=s,this.name="ElectronToolkitError"}}class X extends K{constructor(e,t){super(`IPC handler "${e}" failed: ${t.message}`,"IPC_HANDLER_ERROR",{handlerName:e,originalError:t})}}class Y{limits=new Map;state=new Map;defaultLimit=null;logger;cleanupTimer=null;cleanupInterval;constructor(e={}){this.logger=e.logger,this.defaultLimit=e.defaultLimit||null,this.cleanupInterval=e.cleanupInterval||6e4,this.startCleanup()}startCleanup(){this.cleanupTimer||(this.cleanupTimer=setInterval(()=>{this.cleanup()},this.cleanupInterval),this.cleanupTimer.unref())}stopCleanup(){this.cleanupTimer&&(clearInterval(this.cleanupTimer),this.cleanupTimer=null)}setLimit(e,t){this.limits.set(e,t)}check(e,t){const s=this.limits.get(t)||this.defaultLimit;if(!s)return!0;const i=Date.now();let r=this.state.get(e);return(!r||i>r.resetTime)&&(r={count:0,resetTime:i+s.interval},this.state.set(e,r)),r.count>=s.limit?(this.logger&&this.logger.warn(`Rate limit exceeded for ${e} (Rule: ${t}, Limit: ${s.limit}/${s.interval}ms)`),!1):(r.count++,!0)}clear(){this.state.clear()}cleanup(){const e=Date.now();for(const[t,s]of this.state.entries())e>s.resetTime&&this.state.delete(t)}}const Q=i.z.object({name:i.z.string({message:"Handler name is required"}),payload:i.z.unknown().optional()});class Z{_api={};dispatcher;rateLimiter;constructor(e={}){this.dispatcher=new H("IpcRouter",e.logger),this.rateLimiter=new Y({logger:e.logger,defaultLimit:e.defaultRateLimit})}addHandler(e){this.dispatcher.register(e.name,e.callback,e.schema)}addHandlers(e){e.forEach(e=>this.addHandler(e))}setRateLimit(e,t){this.rateLimiter.setLimit(e,t)}removeHandler(e){this.dispatcher.unregister(e)}handle(e,t){const s=A.getInstance(),i=`ipc-${String(e.name)}-${Date.now()}`;return(async()=>{try{if(s.startMeasure(i,"IPC Call",{handler:String(e.name),senderId:t}),void 0!==t){const s=`${t}:${String(e.name)}`;if(!this.rateLimiter.check(s,String(e.name)))throw new X(String(e.name),new Error(`Rate limit exceeded for handler "${String(e.name)}"`))}const r=Q.safeParse(e);if(!r.success)throw console.warn("[IpcRouter] Invalid IPC request data:",r.error.format()),new X("validation",new Error(`Invalid IPC request: ${r.error.message}`));const o=this.dispatcher.getMetadata(e.name);if(o){const t=o.safeParse(e.payload);if(!t.success)throw console.warn(`[IpcRouter] Invalid payload for handler "${String(e.name)}":`,t.error.message),new X(String(e.name),new Error(`Invalid payload: ${t.error.message}`))}const n={...this._api},a=await Promise.resolve(this.dispatcher.dispatch(e.name,n,e.payload));return s.endMeasure(i,{status:"success"}),a}catch(t){if(s.endMeasure(i,{status:"error",error:t instanceof Error?t.message:String(t)}),t instanceof X)throw t;throw new X(String(e.name),t)}})()}addApi(e,t){this._api[e]=t}addApis(e){Object.entries(e).forEach(([e,t])=>{this.addApi(e,t)})}dispose(){this.rateLimiter.stopCleanup(),this.rateLimiter.clear(),this.dispatcher.clear(),this._api={}}}var ee;e.MessageProtocolType=void 0,(ee=e.MessageProtocolType||(e.MessageProtocolType={})).GET="get",ee.GET_RESPONSE="get-response",ee.SET="set",ee.DELETE="delete",ee.CLEAR="clear",ee.MESSAGE="message",ee.SUBSCRIBE="subscribe",ee.UNSUBSCRIBE="unsubscribe",ee.SET_PERMISSION="set-permission",ee.CONNECT="__message_bus_ready__",ee.TRANSACTION_START="transaction-start",ee.TRANSACTION_COMMIT="transaction-commit",ee.TRANSACTION_ROLLBACK="transaction-rollback",ee.UPDATE="update",ee.SEND_TO_WINDOW="send-to-window",ee.SEND_TO_GROUP="send-to-group";class te{buffers=new Map;logger;constructor(e){this.logger=e}start(e){this.buffers.has(e)?this.logger.warn(`Transaction already started for window ${e}`):this.buffers.set(e,new Map)}commit(e){const t=this.buffers.get(e);if(t)return this.buffers.delete(e),t;this.logger.warn(`No transaction to commit for window ${e}`)}rollback(e){this.buffers.has(e)?this.buffers.delete(e):this.logger.warn(`No transaction to rollback for window ${e}`)}add(e,t,s){return!!this.buffers.has(e)&&(this.buffers.get(e).set(t,s),!0)}hasTransaction(e){return this.buffers.has(e)}getBufferedValue(e,t){if(this.buffers.has(e)){const s=this.buffers.get(e);if(s.has(t)){const e=s.get(t);return"set"===e.type?{has:!0,value:e.value}:{has:!0,value:void 0}}}return{has:!1}}clear(){this.buffers.clear()}}class se{subscriptions=new Map;logger;MAX_SUBSCRIPTIONS_PER_KEY=100;constructor(e){this.logger=e}subscribe(e,t){t.forEach(t=>{this.subscriptions.has(t)||this.subscriptions.set(t,new Set);const s=this.subscriptions.get(t);s.add(e),this.logger&&s.size>this.MAX_SUBSCRIPTIONS_PER_KEY&&s.size===this.MAX_SUBSCRIPTIONS_PER_KEY+1&&this.logger.warn(`High number of subscriptions (${s.size}) for key: "${t}". Potential memory leak or design issue.`)})}unsubscribe(e,t){t.forEach(t=>{const s=this.subscriptions.get(t);s&&(s.delete(e),0===s.size&&this.subscriptions.delete(t))})}removeWindow(e){this.subscriptions.forEach((t,s)=>{t.has(e)&&(t.delete(e),0===t.size&&this.subscriptions.delete(s))})}getSubscribers(e){return this.subscriptions.get(e)}clear(){this.subscriptions.clear()}}class ie{dataStore=new Map;get(e){return this.dataStore.get(e)?.value}getItem(e){return this.dataStore.get(e)}getAll(){const e={};return this.dataStore.forEach((t,s)=>{e[s]=t.value}),e}set(e,t){const s=this.dataStore.get(e);this.dataStore.set(e,{value:t,permission:s?.permission})}delete(e){this.dataStore.delete(e)}checkPermission(e,t,s){const i=this.dataStore.get(e);if(i?.permission){const r="string"==typeof i.permission?{mode:i.permission}:i.permission;if(r.readonly)return{success:!1,error:`Field "${e}" is readonly`};if(r.allowedWindows&&t&&!r.allowedWindows.includes(t))return{success:!1,error:`Window "${t}" is not allowed to ${s} "${e}"`}}return{success:!0}}setPermission(e,t){const s=this.dataStore.get(e);s?s.permission=t:this.dataStore.set(e,{value:void 0,permission:t})}clear(){this.dataStore.clear()}}class re{port;_isClosed=!1;constructor(e){this.port=e}get isClosed(){return this._isClosed}postMessage(e){if(this._isClosed)return!1;try{return this.port.postMessage(e),!0}catch(e){throw this._isClosed=!0,e}}close(){if(!this._isClosed){this._isClosed=!0;try{this.port.close()}catch(e){}}}get rawPort(){return this.port}}class oe{ports=new Map;logger;constructor(e){this.logger=e}register(e,s,i){this.unregister(e);const{port1:r,port2:o}=new t.MessageChannelMain,n=new re(r);this.ports.set(e,n),r.on("message",t=>{let s;try{s="string"==typeof t.data?JSON.parse(t.data):t.data}catch(t){return void this.logger.error(`Failed to parse message from window ${e}: ${t}`)}i(s,n)}),r.start();const a=()=>{try{s.webContents.postMessage(N,null,[o])}catch(t){this.logger.error(`Failed to post message to window ${e}: ${t}`),n.close(),this.ports.delete(e)}};s.webContents.isLoading()?s.webContents.once("did-finish-load",a):a()}unregister(e){const t=this.ports.get(e);return!!t&&(t.close(),this.ports.delete(e),!0)}get(e){return this.ports.get(e)}broadcast(e,t){let s=0;return(t||Array.from(this.ports.keys())).forEach(t=>{const i=this.ports.get(t);if(i)try{i.postMessage(e)&&s++}catch(e){this.logger.error(`Failed to broadcast to window ${t}: ${e}`)}}),s}dispose(){this.ports.forEach(e=>e.close()),this.ports.clear()}getAllWindowIds(){return Array.from(this.ports.keys())}}class ne{name="messageport";portManager;onMessage;constructor(e){this.portManager=new oe(e)}init(e){this.onMessage=e}registerWindow(e,t){this.portManager.register(e,t,(t,s)=>{this.onMessage&&this.onMessage(t,e)})}unregisterWindow(e){this.portManager.unregister(e)}send(e,t){const s=this.portManager.get(e);if(s){const e="string"==typeof t?t:JSON.stringify(t);s.postMessage(e)}}broadcast(e,t){const s="string"==typeof e?e:JSON.stringify(e);return this.portManager.broadcast(s,t)}dispose(){}}const ae="message-bus-ipc";class de{name="ipc";logger;windows=new Map;onMessage;constructor(e){this.logger=e,this.setupIpcListener()}setupIpcListener(){t.ipcMain.on(ae,(e,t)=>{const s=this.findWindowId(e.sender.id);s&&this.onMessage&&this.onMessage(t,s)})}findWindowId(e){for(const[t,s]of this.windows.entries())if(s.webContents.id===e)return t}init(e){this.onMessage=e}registerWindow(e,t){this.windows.set(e,t)}unregisterWindow(e){this.windows.delete(e)}send(e,t){const s=this.windows.get(e);s&&!s.isDestroyed()&&s.webContents.send(ae,t)}broadcast(e,t){let s=0;const i=t||Array.from(this.windows.keys());for(const t of i)try{this.send(t,e),s++}catch(e){this.logger.error(`Failed to send IPC message to ${t}`,e)}return s}dispose(){this.windows.clear(),t.ipcMain.removeAllListeners(ae)}}class he extends o.EventEmitter{eventName=D;logger;subscriptionManager;transactionManager;dataStoreManager;transport;transportMode;windows=new Map;dispatcher;groupResolver;watchCallbacks=new Set;windowSubscriptions=new WeakMap;constructor(e={}){super(),this.eventName=e.eventName||D,this.logger=e.logger||new w({appName:"MessageBus"}),this.dispatcher=new H("MessageBus",this.logger),this.subscriptionManager=new se(this.logger),this.transactionManager=new te(this.logger),this.dataStoreManager=new ie;const t=e.transportMode||"auto";this.transportMode=this.selectTransportMode(t),this.transport=this.createTransport(this.transportMode);try{this.transport.init((e,t)=>this.handleTransportMessage(e,t)),this.logger.info(`MessageBus initialized with ${this.transportMode} transport`)}catch(e){this.logger.error(`Failed to initialize ${this.transportMode} transport: ${e}. Falling back to IPC.`),this.transportMode="ipc",this.transport=new de(this.logger),this.transport.init((e,t)=>this.handleTransportMessage(e,t))}this.registerDefaultHandlers()}selectTransportMode(e){return"ipc"===e?"ipc":"messageport"===e?"messageport":void 0===t.MessageChannelMain?(this.logger.warn("MessageChannelMain not available, falling back to IPC transport"),"ipc"):"messageport"}createTransport(e){return"ipc"===e?new de(this.logger):new ne(this.logger)}handleTransportMessage(t,s){try{if(t&&t.type){const i=this.dispatcher.dispatch(t.type,this,{...t,windowId:s});t.requestId&&Promise.resolve(i).then(i=>{this.transport.send(s,{type:e.MessageProtocolType.GET_RESPONSE,requestId:t.requestId,value:i})}).catch(e=>{this.logger.error(`Error handling message ${t.type}: ${e}`)})}}catch(e){this.logger.error(`Failed to handle message from window ${s}: ${e}`)}}registerWindow(e,t){this.unregisterWindow(e),this.windows.set(e,t),this.transport.registerWindow(e,t)}unregisterWindow(e){const t=this.windows.get(e);if(t&&this.windowSubscriptions.has(t)){const s=this.windowSubscriptions.get(t);s&&(this.logger.info(`Cleaning up ${s.size} subscriptions for window ${e}`),s.forEach(e=>{try{e()}catch(e){}}),this.windowSubscriptions.delete(t))}this.transport.unregisterWindow(e),this.windows.delete(e),this.subscriptionManager.removeWindow(e),this.transactionManager.hasTransaction(e)&&this.transactionManager.rollback(e)}autoRegisterWindows(e){e.on("window-created",({window:e,id:t})=>{this.registerWindow(t,e)}),e.on("window-will-be-destroyed",e=>{this.unregisterWindow(e)})}dispose(){this.logger.info("Disposing MessageBus..."),this.watchCallbacks.forEach(e=>{try{e()}catch(e){this.logger.warn(`Failed to unsubscribe watch callback: ${e}`)}}),this.watchCallbacks.clear(),this.dispatcher.clear(),this.transport.dispose(),this.dataStoreManager.clear(),this.subscriptionManager.clear(),this.transactionManager.clear(),this.windows.clear(),this.removeAllListeners(),this.logger.info("MessageBus disposed")}registerHandler(e){this.on(e.eventName,e.callback)}registerHandlers(e){e.forEach(e=>this.registerHandler(e))}unregisterHandler(e){this.removeListener(e.eventName,e.callback)}unregisterHandlers(e){e.forEach(e=>this.unregisterHandler(e))}getData(e){return e?this.dataStoreManager.get(e):this.dataStoreManager.getAll()}checkPermission(e,t,s){return this.dataStoreManager.checkPermission(e,t,s)}setData(t,s,i,r,o=!1){const n=this.checkPermission(t,i,"modify");if(!n.success)return n;if(!o&&i&&this.transactionManager.hasTransaction(i))return this.transactionManager.add(i,t,{type:"set",value:s}),{success:!0};const a=this.dataStoreManager.getItem(t),d=a?.value;this.dataStoreManager.set(t,s);const h={type:e.MessageProtocolType.SET,key:t,value:s,oldValue:d,windowId:i,timestamp:Date.now()};return this.broadcastChange(h),this.emit(r||this.eventName,h),{success:!0}}deleteData(t,s,i,r=!1){const o=this.checkPermission(t,s,"delete");if(!o.success)return o;if(!r&&s&&this.transactionManager.hasTransaction(s))return this.transactionManager.add(s,t,{type:"delete"}),{success:!0};const n=this.dataStoreManager.getItem(t),a=n?.value;this.dataStoreManager.delete(t);const d={type:e.MessageProtocolType.DELETE,key:t,oldValue:a,windowId:s,timestamp:Date.now()};return this.broadcastChange(d),this.emit(i||this.eventName,d),{success:!0}}startTransaction(e){this.transactionManager.start(e)}commitTransaction(e){const t=this.transactionManager.commit(e);t&&t.forEach((t,s)=>{"set"===t.type?this.setData(s,t.value,e,void 0,!0):"delete"===t.type&&this.deleteData(s,e,void 0,!0)})}rollbackTransaction(e){this.transactionManager.rollback(e)}watch(t,s,i){const r=i=>{"key"in i&&i.key===t&&(i.type===e.MessageProtocolType.SET?s(i.value,i.oldValue):i.type===e.MessageProtocolType.DELETE&&s(void 0,i.oldValue))};this.on(this.eventName,r);const o=()=>{if(this.off(this.eventName,r),this.watchCallbacks.delete(o),i){const e=this.windows.get(i);e&&this.windowSubscriptions.has(e)&&this.windowSubscriptions.get(e)?.delete(o)}};if(this.watchCallbacks.add(o),i){const e=this.windows.get(i);e?(this.windowSubscriptions.has(e)||this.windowSubscriptions.set(e,new Set),this.windowSubscriptions.get(e).add(o)):this.logger.warn(`Window ${i} not found, watch subscription will not be auto-cleaned up on window destroy`)}return o}updateData(e,t,s){let i=this.dataStoreManager.get(e);if(s){const t=this.transactionManager.getBufferedValue(s,e);t.has&&(i=t.value)}const r="function"==typeof t?t(i):t;return this.setData(e,r,s)}setFieldPermission(e,t){this.dataStoreManager.setPermission(e,t)}getRegisteredWindows(){return Array.from(this.windows.keys())}registerMessageHandler(e){this.dispatcher.register(e.name,e.callback)}registerDefaultHandlers(){this.registerMessageHandler({name:e.MessageProtocolType.GET,callback:(e,{key:t}={})=>e.getData(t)}),this.registerMessageHandler({name:e.MessageProtocolType.SET,callback:(e,{key:t,value:s,windowId:i,eventName:r})=>e.setData(t,s,i,r)}),this.registerMessageHandler({name:e.MessageProtocolType.DELETE,callback:(e,{key:t,windowId:s,eventName:i})=>e.deleteData(t,s,i)}),this.registerMessageHandler({name:e.MessageProtocolType.SET_PERMISSION,callback:(e,{key:t,permission:s})=>e.setFieldPermission(t,s)}),this.registerMessageHandler({name:e.MessageProtocolType.SUBSCRIBE,callback:(e,{windowId:t,keys:s})=>e.subscribe(t,s)}),this.registerMessageHandler({name:e.MessageProtocolType.UNSUBSCRIBE,callback:(e,{windowId:t,keys:s})=>e.unsubscribe(t,s)}),this.registerMessageHandler({name:e.MessageProtocolType.TRANSACTION_START,callback:(e,{windowId:t})=>e.startTransaction(t)}),this.registerMessageHandler({name:e.MessageProtocolType.TRANSACTION_COMMIT,callback:(e,{windowId:t})=>e.commitTransaction(t)}),this.registerMessageHandler({name:e.MessageProtocolType.TRANSACTION_ROLLBACK,callback:(e,{windowId:t})=>e.rollbackTransaction(t)}),this.registerMessageHandler({name:e.MessageProtocolType.SEND_TO_WINDOW,callback:(e,{targetWindowId:t,channel:s,data:i})=>e.sendToWindow(t,s,i)}),this.registerMessageHandler({name:e.MessageProtocolType.SEND_TO_GROUP,callback:(e,{group:t,channel:s,data:i})=>e.sendToGroup(t,s,i)}),this.registerMessageHandler({name:e.MessageProtocolType.UPDATE,callback:(e,{key:t,value:s,windowId:i})=>e.setData(t,s,i)})}handleMessage(e,t){return this.dispatcher.dispatch(e,this,t)}initializeListener(){t.ipcMain.handle("message-bus-invoke",(e,{name:t,data:s})=>this.handleMessage(t,s))}setGroupResolver(e){this.groupResolver=e}sendToWindow(t,s,i){const r=A.getInstance(),o=`message-bus-send-${Date.now()}`;if(r.startMeasure(o,"MessageBus Send",{windowId:t,channel:s}),!this.windows.has(t))return this.logger.warn(`Window ${t} not found or not registered`),r.endMeasure(o,{status:"failed",reason:"window_not_found"}),!1;try{const n={type:e.MessageProtocolType.MESSAGE,channel:s,value:i,timestamp:Date.now()};return this.transport.send(t,JSON.stringify(n)),r.endMeasure(o,{status:"success"}),!0}catch(e){return this.logger.error(`Failed to send message to window ${t}: ${e}`),this.emit("error",e),r.endMeasure(o,{status:"error",error:e instanceof Error?e.message:String(e)}),!1}}sendToGroup(e,t,s){const i=A.getInstance(),r=`message-bus-broadcast-${Date.now()}`;if(i.startMeasure(r,"MessageBus Broadcast",{group:e,channel:t}),!this.groupResolver)return this.logger.warn("Group resolver not set, cannot send to group"),i.endMeasure(r,{status:"failed",reason:"no_group_resolver"}),0;const o=this.groupResolver(e),n=this.broadcastToWindows(o,t,s);return i.endMeasure(r,{status:"success",windowCount:o.length,successCount:n}),n}broadcastToWindows(t,s,i){const r={type:e.MessageProtocolType.MESSAGE,channel:s,value:i,timestamp:Date.now()},o=JSON.stringify(r);return this.transport.broadcast(o,t)}subscribe(e,t){this.subscriptionManager.subscribe(e,t)}unsubscribe(e,t){this.subscriptionManager.unsubscribe(e,t)}broadcastChange(e){const t=JSON.stringify(e);if("key"in e&&e.key){const s=this.subscriptionManager.getSubscribers(e.key);if(s)return void this.transport.broadcast(t,Array.from(s))}this.transport.broadcast(t)}}var ce;e.WindowErrorCode=void 0,(ce=e.WindowErrorCode||(e.WindowErrorCode={}))[ce.CONFIG_INVALID=1001]="CONFIG_INVALID",ce[ce.CONFIG_MISSING=1002]="CONFIG_MISSING",ce[ce.WINDOW_NOT_FOUND=2001]="WINDOW_NOT_FOUND",ce[ce.WINDOW_CREATION_FAILED=2002]="WINDOW_CREATION_FAILED",ce[ce.WINDOW_ALREADY_EXISTS=2003]="WINDOW_ALREADY_EXISTS",ce[ce.WINDOW_LIMIT_REACHED=2004]="WINDOW_LIMIT_REACHED",ce[ce.WINDOW_DESTROYED=2005]="WINDOW_DESTROYED",ce[ce.IPC_CONNECTION_FAILED=3001]="IPC_CONNECTION_FAILED",ce[ce.IPC_TIMEOUT=3002]="IPC_TIMEOUT",ce[ce.IPC_HANDLER_ERROR=3003]="IPC_HANDLER_ERROR",ce[ce.INTERNAL_ERROR=5001]="INTERNAL_ERROR",ce[ce.DEPENDENCY_MISSING=5002]="DEPENDENCY_MISSING";class le extends Error{code;originalError;details;suggestion;constructor(e){super(e.message),this.name="WindowError",this.code=e.code,this.originalError=e.originalError,this.details=e.details,this.suggestion=e.suggestion,Object.setPrototypeOf(this,le.prototype)}getErrorCategory(){return this.code>=1e3&&this.code<2e3?"configuration":this.code>=2e3&&this.code<3e3?"window":this.code>=3e3&&this.code<4e3?"ipc":this.code>=5e3&&this.code<6e3?"system":"unknown"}toJSON(){return{name:this.name,message:this.message,code:this.code,category:this.getErrorCategory(),details:this.details,suggestion:this.suggestion}}}class ge{bindings;channel=W;syncChannel=b;constructor(){this.bindings={invoke:this.invoke.bind(this),sendSync:this.sendSync.bind(this)}}configure(e){e.channel&&(this.channel=e.channel),e.syncChannel&&(this.syncChannel=e.syncChannel)}invoke=async(e,s)=>{const i=await t.ipcRenderer.invoke(this.channel,{name:e,payload:s});if(i&&"object"==typeof i&&"code"in i){if(0===i.code)return i.data;throw new Error(i.message||`IPC Error: ${i.code}`)}return i};sendSync=(e,s)=>{const i=t.ipcRenderer.sendSync(this.syncChannel,{name:e,payload:s});if(i&&"object"==typeof i&&"code"in i){if(0===i.code)return i.data;throw new Error(i.message||`IPC Error: ${i.code}`)}return i};getBindings(){return this.bindings}exposeApi(e="ipcApi"){try{t.contextBridge.exposeInMainWorld(e,this.bindings)}catch(e){console.error("[IpcRendererBridge] Failed to expose API:",e)}}}const ue=new ge;class we extends s.TypedEmitter{config={};filePath;logger;autoSave;saveTimer=null;saveDelay;schema;constructor(e={}){super(),this.logger=e.logger||new w({appName:"ConfigManager"}),this.autoSave=e.autoSave??!0,this.saveDelay=e.saveDelay||100,this.schema=e.schema;const s=t.app.getPath("userData");this.filePath=g.join(s,e.filename||"config.json"),this.load()}get(e,t){const s=this.getDeep(this.config,e);return void 0===s?t:s}set(e,t){const s=this.get(e);if(JSON.stringify(s)!==JSON.stringify(t)){if(this.schema){const s=JSON.parse(JSON.stringify(this.config));this.setDeep(s,e,t);const i=this.schema.safeParse(s);if(!i.success)throw new Error(`Configuration validation failed: ${i.error.message}`)}this.setDeep(this.config,e,t),this.emit("change",e,t,s),this.autoSave&&this.triggerSave()}}delete(e){if(!this.has(e))return;const t=this.get(e);this.deleteDeep(this.config,e),this.emit("change",e,void 0,t),this.autoSave&&this.triggerSave()}has(e){return void 0!==this.getDeep(this.config,e)}clear(){this.config={},this.emit("change","",{},{}),this.autoSave&&this.triggerSave()}async save(){this.saveTimer&&(clearTimeout(this.saveTimer),this.saveTimer=null);try{const e=JSON.stringify(this.config,null,2);await l.promises.writeFile(this.filePath,e,"utf-8"),this.emit("saved")}catch(e){const t=e instanceof Error?e:new Error(String(e));this.logger.error(`Failed to save configuration: ${t.message}`),this.emit("error",t)}}load(){try{if(l.existsSync(this.filePath)){const e=l.readFileSync(this.filePath,"utf-8");let t=JSON.parse(e);if(this.schema){const e=this.schema.safeParse(t);e.success?t=e.data:(this.logger.error(`Configuration validation failed: ${e.error.message}`),this.emit("error",new Error(`Configuration validation failed: ${e.error.message}`)))}this.config=t,this.emit("loaded",this.config),this.logger.info(`Configuration loaded from ${this.filePath}`)}else this.logger.info("No configuration file found, starting with empty config")}catch(e){const t=e instanceof Error?e:new Error(String(e));this.logger.error(`Failed to load configuration: ${t.message}`),this.emit("error",t)}}getAll(){return JSON.parse(JSON.stringify(this.config))}triggerSave(){this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.save()},this.saveDelay)}getDeep(e,t){if(!t)return;const s=t.split(".");let i=e;for(const e of s){if(null==i)return;i=i[e]}return i}setDeep(e,t,s){if(!t)return;const i=t.split("."),r=i.pop();let o=e;for(const e of i)void 0!==o[e]&&null!==o[e]&&"object"==typeof o[e]||(o[e]={}),o=o[e];o[r]=s}deleteDeep(e,t){if(!t)return;const s=t.split("."),i=s.pop();let r=e;for(const e of s){if(void 0===r[e]||null===r[e])return;r=r[e]}delete r[i]}}var pe=Object.freeze({__proto__:null,get MessageProtocolType(){return e.MessageProtocolType},createChannelName:function(e){if(!e||"string"!=typeof e)throw new Error("Invalid channel name: must be a non-empty string");return e},createEventName:function(e){if(!e||"string"!=typeof e)throw new Error("Invalid event name: must be a non-empty string");return e},createFieldKey:function(e){if(!e||"string"!=typeof e)throw new Error("Invalid field key: must be a non-empty string");return e},createHandlerName:function(e){if(!e||"string"!=typeof e)throw new Error("Invalid handler name: must be a non-empty string");return e},createWindowId:function(e){if(!e||"string"!=typeof e)throw new Error("Invalid window ID: must be a non-empty string");return e}});e.ConfigManager=we,e.DebugHelper=L,e.ElectronToolkitError=K,e.EnhancedDebugHelper=k,e.IpcHandler=class{_name;_event;_callback;_schema;constructor(e,t,s,i){this._name=e,this._event=t,this._callback=s,this._schema=i}get name(){return this._name}get event(){return this._event}get callback(){return this._callback}get schema(){return this._schema}},e.IpcHandlerError=X,e.IpcRendererBridge=ge,e.IpcRouter=Z,e.IpcSetup=_,e.LifecycleManager=class{windowManager;ipcRouter;messageBus;logger;isStarted=!1;config;constructor(e={}){this.config=e,this.logger=e.logger||new w({appName:"LifecycleManager"}),e.autoStart&&this.startup().catch(e=>{this.logger.error(`Auto-startup failed: ${e}`)})}async startup(){if(this.isStarted)this.logger.warn("LifecycleManager already started");else try{this.logger.info("Starting up Electron Toolkit services..."),this.ipcRouter=this.config.ipcRouter||new Z({logger:this.config.logger}),this.logger.info("IpcRouter initialized"),this.messageBus=this.config.messageBus||new he({logger:this.config.logger}),this.windowManager=this.config.windowManager||new G({...this.config,ipcRouter:this.ipcRouter,messageBus:this.messageBus}),await this.windowManager.ready(),this.logger.info("WindowManager initialized"),this.messageBus.autoRegisterWindows(this.windowManager),this.logger.info("MessageBus initialized"),(this.config.isDevelopment||"development"===process.env.NODE_ENV)&&(L.enableDebugMode(),L.register("windowManager",this.windowManager),L.register("ipcRouter",this.ipcRouter),L.register("messageBus",this.messageBus),L.register("lifecycleManager",this),this.logger.info("Debug mode enabled")),this.isStarted=!0,this.logger.info("Startup completed successfully")}catch(e){throw this.logger.error(`Startup failed: ${e}`),await this.shutdown(),e}}async shutdown(){if(this.logger.info("Shutting down Electron Toolkit services..."),this.messageBus){try{this.messageBus.dispose(),this.logger.info("MessageBus disposed")}catch(e){this.logger.warn(`MessageBus dispose error: ${e}`)}this.messageBus=void 0}if(this.windowManager){try{"function"==typeof this.windowManager.dispose?(await this.windowManager.dispose(),this.logger.info("WindowManager disposed")):this.windowManager.stopCleanupProtection()}catch(e){this.logger.warn(`WindowManager dispose error: ${e}`)}this.windowManager=void 0}if(this.ipcRouter){try{this.ipcRouter.dispose(),this.logger.info("IpcRouter disposed")}catch(e){this.logger.warn(`IpcRouter dispose error: ${e}`)}this.ipcRouter=void 0}this.isStarted=!1,this.logger.info("Shutdown completed")}get started(){return this.isStarted}},e.Logger=w,e.MessageBus=he,e.MessageBusClient=class{port=null;ready=!1;pendingOperations=[];subscriptions=new Map;messageListeners=new Map;pendingRequests=new Map;logger;constructor(e={}){this.logger=e.logger||new w({appName:"MessageBusClient"}),this.initialize()}subscribe(t,s){return this.subscriptions.has(t)||(this.subscriptions.set(t,new Set),this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.SUBSCRIBE,keys:[t]}))})),this.subscriptions.get(t).add(s),()=>{this.subscriptions.get(t)?.delete(s),0===this.subscriptions.get(t)?.size&&(this.subscriptions.delete(t),this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.UNSUBSCRIBE,keys:[t]}))}))}}watch(e,t){return this.subscribe(e,t)}onMessage(e,t){return this.messageListeners.has(e)||this.messageListeners.set(e,new Set),this.messageListeners.get(e).add(t),()=>{this.messageListeners.get(e)?.delete(t),0===this.messageListeners.get(e)?.size&&this.messageListeners.delete(e)}}sendToWindow(t,s,i){this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.SEND_TO_WINDOW,targetWindowId:t,channel:s,data:i}))})}sendToGroup(t,s,i){this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.SEND_TO_GROUP,group:t,channel:s,data:i}))})}set(t,s){this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.SET,key:t,value:s}))})}async get(t){return new Promise(s=>{this.ensureReady(()=>{const i=r.v4(),o=setTimeout(()=>{this.pendingRequests.has(i)&&(this.pendingRequests.delete(i),this.logger.warn(`Get request for key "${t}" timed out`),s(void 0))},5e3);this.pendingRequests.set(i,{resolve:s,timeout:o}),this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.GET,key:t,requestId:i}))})})}delete(t){this.ensureReady(()=>{this.port.postMessage(JSON.stringify({type:e.MessageProtocolType.DELETE,key:t}))})}initialize(){window.addEventListener("message",t=>{t.data?.type===e.MessageProtocolType.CONNECT&&(this.port=t.ports[0],this.port.onmessage=this.handleMessage.bind(this),this.port.start(),this.ready=!0,this.logger.debug("MessageBusClient connected"),this.pendingOperations.forEach(e=>e()),this.pendingOperations=[])})}handleMessage(t){try{const s=JSON.parse(t.data);if(s.type===e.MessageProtocolType.GET_RESPONSE&&s.requestId){const e=this.pendingRequests.get(s.requestId);return void(e&&(clearTimeout(e.timeout),this.pendingRequests.delete(s.requestId),e.resolve(s.value)))}if("message"===s.type&&s.channel){const e=this.messageListeners.get(s.channel);return void(e&&e.forEach(e=>{try{e(s.value)}catch(e){this.logger.error(`Error in message listener for channel "${s.channel}": ${e}`)}}))}if(s.key&&(s.type===e.MessageProtocolType.SET||s.type===e.MessageProtocolType.DELETE)){const e=this.subscriptions.get(s.key);e&&e.forEach(e=>{try{e(s.value)}catch(e){this.logger.error(`Error in subscription callback for key "${s.key}": ${e}`)}})}}catch(e){this.logger.error(`Failed to handle message: ${e}`)}}ensureReady(e){this.ready?e():this.pendingOperations.push(e)}dispose(){this.port&&(this.port.close(),this.port=null),this.subscriptions.clear(),this.pendingOperations=[],this.pendingRequests.forEach(e=>{clearTimeout(e.timeout),e.resolve(void 0)}),this.pendingRequests.clear(),this.ready=!1}},e.NotFoundError=class extends J{constructor(t,s){super(404,t,e.ErrorCategory.NOT_FOUND,s),this.name="NotFoundError"}},e.PermissionError=class extends J{constructor(t,s){super(403,t,e.ErrorCategory.PERMISSION,s),this.name="PermissionError"}},e.StandardError=J,e.Types=pe,e.ValidationError=class extends J{constructor(t,s){super(422,t,e.ErrorCategory.VALIDATION,s),this.name="ValidationError"}},e.WindowCreator=x,e.WindowError=le,e.WindowManager=G,e.WindowNotFoundError=class extends K{constructor(e){super(`Window "${e}" not found or destroyed`,"WINDOW_NOT_FOUND",{windowId:e})}},e.WindowStore=C,e.createElectronToolkit=function(e={}){const t=new Z({logger:e.logger}),s=new G({...e,ipcRouter:t}),i=new he({logger:e.logger});return i.autoRegisterWindows(s),(e.isDevelopment||"development"===process.env.NODE_ENV)&&(L.enableDebugMode(),L.register("windowManager",s),L.register("ipcRouter",t),L.register("messageBus",i)),{windowManager:s,ipcRouter:t,messageBus:i}},e.debugHelper=B,e.ipcRendererBridge=ue,e.setupMessageBus=function(){t.ipcRenderer.on(N,t=>{const[s]=t.ports;s?window.postMessage({type:e.MessageProtocolType.CONNECT,port:s},"*",[s]):console.error("[MessageBus] No port received in message-bus-port event")})},e.validateWindowManagerConfig=S});
@@ -0,0 +1,133 @@
1
+ import { TypedEmitter } from 'tiny-typed-emitter';
2
+ import { ILogger } from '@/infrastructure/logger';
3
+ import { z } from 'zod';
4
+ /**
5
+ * Config Manager Events
6
+ * 配置管理器事件
7
+ */
8
+ export interface ConfigManagerEvents {
9
+ /**
10
+ * Emitted when a configuration value changes
11
+ * 当配置值发生变化时触发
12
+ */
13
+ change: (key: string, newValue: any, oldValue: any) => void;
14
+ /**
15
+ * Emitted when configuration is loaded from disk
16
+ * 当配置从磁盘加载时触发
17
+ */
18
+ loaded: (config: Record<string, any>) => void;
19
+ /**
20
+ * Emitted when configuration is saved to disk
21
+ * 当配置保存到磁盘时触发
22
+ */
23
+ saved: () => void;
24
+ /**
25
+ * Emitted when an error occurs
26
+ * 当发生错误时触发
27
+ */
28
+ error: (error: Error) => void;
29
+ }
30
+ /**
31
+ * Config Manager Options
32
+ * 配置管理器选项
33
+ */
34
+ export interface ConfigManagerOptions {
35
+ /**
36
+ * Configuration filename (default: 'config.json')
37
+ * 配置文件名 (默认: 'config.json')
38
+ */
39
+ filename?: string;
40
+ /**
41
+ * Logger instance
42
+ * 日志实例
43
+ */
44
+ logger?: ILogger;
45
+ /**
46
+ * Whether to automatically save on changes (default: true)
47
+ * 是否在更改时自动保存 (默认: true)
48
+ */
49
+ autoSave?: boolean;
50
+ /**
51
+ * Save delay in milliseconds (debounce) (default: 100)
52
+ * 保存延迟(毫秒,防抖) (默认: 100)
53
+ */
54
+ saveDelay?: number;
55
+ /**
56
+ * Zod schema for validation
57
+ * 用于校验的 Zod schema
58
+ */
59
+ schema?: z.ZodType<any>;
60
+ }
61
+ /**
62
+ * Config Manager
63
+ * 配置管理器
64
+ *
65
+ * Manages application configuration with persistence and type safety support.
66
+ * 管理具有持久化和类型安全支持的应用程序配置。
67
+ */
68
+ export declare class ConfigManager extends TypedEmitter<ConfigManagerEvents> {
69
+ private config;
70
+ private filePath;
71
+ private logger;
72
+ private autoSave;
73
+ private saveTimer;
74
+ private saveDelay;
75
+ private schema?;
76
+ /**
77
+ * Create ConfigManager instance
78
+ * 创建 ConfigManager 实例
79
+ */
80
+ constructor(options?: ConfigManagerOptions);
81
+ /**
82
+ * Get configuration value
83
+ * 获取配置值
84
+ *
85
+ * @param key Dot-notation key (e.g., 'ui.theme') / 点符号键 (如 'ui.theme')
86
+ * @param defaultValue Default value if key not found / 如果键未找到的默认值
87
+ */
88
+ get<T>(key: string, defaultValue?: T): T;
89
+ /**
90
+ * Set configuration value
91
+ * 设置配置值
92
+ *
93
+ * @param key Dot-notation key (e.g., 'ui.theme') / 点符号键 (如 'ui.theme')
94
+ * @param value Value to set / 要设置的值
95
+ */
96
+ set(key: string, value: any): void;
97
+ /**
98
+ * Delete configuration value
99
+ * 删除配置值
100
+ *
101
+ * @param key Dot-notation key / 点符号键
102
+ */
103
+ delete(key: string): void;
104
+ /**
105
+ * Check if key exists
106
+ * 检查键是否存在
107
+ */
108
+ has(key: string): boolean;
109
+ /**
110
+ * Clear all configuration
111
+ * 清除所有配置
112
+ */
113
+ clear(): void;
114
+ /**
115
+ * Force save configuration to disk
116
+ * 强制保存配置到磁盘
117
+ */
118
+ save(): Promise<void>;
119
+ /**
120
+ * Load configuration from disk
121
+ * 从磁盘加载配置
122
+ */
123
+ load(): void;
124
+ /**
125
+ * Get the full configuration object
126
+ * 获取完整的配置对象
127
+ */
128
+ getAll(): Record<string, any>;
129
+ private triggerSave;
130
+ private getDeep;
131
+ private setDeep;
132
+ private deleteDeep;
133
+ }
@@ -0,0 +1,218 @@
1
+ 'use strict';var electron=require('electron'),fs=require('fs'),path=require('path'),tinyTypedEmitter=require('tiny-typed-emitter'),ElectronLogger=require('../logger/ElectronLogger.js');function _interopNamespaceDefault(e){var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var fs__namespace=/*#__PURE__*/_interopNamespaceDefault(fs);var path__namespace=/*#__PURE__*/_interopNamespaceDefault(path);/**
2
+ * Config Manager
3
+ * 配置管理器
4
+ *
5
+ * Manages application configuration with persistence and type safety support.
6
+ * 管理具有持久化和类型安全支持的应用程序配置。
7
+ */
8
+ class ConfigManager extends tinyTypedEmitter.TypedEmitter {
9
+ config = {};
10
+ filePath;
11
+ logger;
12
+ autoSave;
13
+ saveTimer = null;
14
+ saveDelay;
15
+ schema;
16
+ /**
17
+ * Create ConfigManager instance
18
+ * 创建 ConfigManager 实例
19
+ */
20
+ constructor(options = {}) {
21
+ super();
22
+ this.logger = options.logger || new ElectronLogger.ElectronLogger({ appName: 'ConfigManager' });
23
+ this.autoSave = options.autoSave ?? true;
24
+ this.saveDelay = options.saveDelay || 100;
25
+ this.schema = options.schema;
26
+ const userDataPath = electron.app.getPath('userData');
27
+ this.filePath = path__namespace.join(userDataPath, options.filename || 'config.json');
28
+ this.load();
29
+ }
30
+ /**
31
+ * Get configuration value
32
+ * 获取配置值
33
+ *
34
+ * @param key Dot-notation key (e.g., 'ui.theme') / 点符号键 (如 'ui.theme')
35
+ * @param defaultValue Default value if key not found / 如果键未找到的默认值
36
+ */
37
+ get(key, defaultValue) {
38
+ const value = this.getDeep(this.config, key);
39
+ return value === undefined ? defaultValue : value;
40
+ }
41
+ /**
42
+ * Set configuration value
43
+ * 设置配置值
44
+ *
45
+ * @param key Dot-notation key (e.g., 'ui.theme') / 点符号键 (如 'ui.theme')
46
+ * @param value Value to set / 要设置的值
47
+ */
48
+ set(key, value) {
49
+ const oldValue = this.get(key);
50
+ // Simple equality check to avoid unnecessary writes/events
51
+ // 简单的相等性检查以避免不必要的写入/事件
52
+ if (JSON.stringify(oldValue) === JSON.stringify(value)) {
53
+ return;
54
+ }
55
+ // Validation
56
+ if (this.schema) {
57
+ const tempConfig = JSON.parse(JSON.stringify(this.config));
58
+ this.setDeep(tempConfig, key, value);
59
+ const result = this.schema.safeParse(tempConfig);
60
+ if (!result.success) {
61
+ throw new Error(`Configuration validation failed: ${result.error.message}`);
62
+ }
63
+ }
64
+ this.setDeep(this.config, key, value);
65
+ this.emit('change', key, value, oldValue);
66
+ if (this.autoSave) {
67
+ this.triggerSave();
68
+ }
69
+ }
70
+ /**
71
+ * Delete configuration value
72
+ * 删除配置值
73
+ *
74
+ * @param key Dot-notation key / 点符号键
75
+ */
76
+ delete(key) {
77
+ if (!this.has(key))
78
+ return;
79
+ const oldValue = this.get(key);
80
+ this.deleteDeep(this.config, key);
81
+ this.emit('change', key, undefined, oldValue);
82
+ if (this.autoSave) {
83
+ this.triggerSave();
84
+ }
85
+ }
86
+ /**
87
+ * Check if key exists
88
+ * 检查键是否存在
89
+ */
90
+ has(key) {
91
+ return this.getDeep(this.config, key) !== undefined;
92
+ }
93
+ /**
94
+ * Clear all configuration
95
+ * 清除所有配置
96
+ */
97
+ clear() {
98
+ this.config = {};
99
+ this.emit('change', '', {}, {}); // Root change
100
+ if (this.autoSave) {
101
+ this.triggerSave();
102
+ }
103
+ }
104
+ /**
105
+ * Force save configuration to disk
106
+ * 强制保存配置到磁盘
107
+ */
108
+ async save() {
109
+ if (this.saveTimer) {
110
+ clearTimeout(this.saveTimer);
111
+ this.saveTimer = null;
112
+ }
113
+ try {
114
+ const data = JSON.stringify(this.config, null, 2);
115
+ await fs__namespace.promises.writeFile(this.filePath, data, 'utf-8');
116
+ this.emit('saved');
117
+ // this.logger.debug('Configuration saved');
118
+ }
119
+ catch (error) {
120
+ const err = error instanceof Error ? error : new Error(String(error));
121
+ this.logger.error(`Failed to save configuration: ${err.message}`);
122
+ this.emit('error', err);
123
+ }
124
+ }
125
+ /**
126
+ * Load configuration from disk
127
+ * 从磁盘加载配置
128
+ */
129
+ load() {
130
+ try {
131
+ if (fs__namespace.existsSync(this.filePath)) {
132
+ const data = fs__namespace.readFileSync(this.filePath, 'utf-8');
133
+ let parsedConfig = JSON.parse(data);
134
+ // Validation
135
+ if (this.schema) {
136
+ const result = this.schema.safeParse(parsedConfig);
137
+ if (!result.success) {
138
+ this.logger.error(`Configuration validation failed: ${result.error.message}`);
139
+ this.emit('error', new Error(`Configuration validation failed: ${result.error.message}`));
140
+ // We still load it, but maybe we should rely on the user to handle the error
141
+ // Or maybe we should use the partial valid data?
142
+ // For now, let's proceed with what we have, but logging the error is crucial.
143
+ }
144
+ else {
145
+ parsedConfig = result.data;
146
+ }
147
+ }
148
+ this.config = parsedConfig;
149
+ this.emit('loaded', this.config);
150
+ this.logger.info(`Configuration loaded from ${this.filePath}`);
151
+ }
152
+ else {
153
+ this.logger.info('No configuration file found, starting with empty config');
154
+ }
155
+ }
156
+ catch (error) {
157
+ const err = error instanceof Error ? error : new Error(String(error));
158
+ this.logger.error(`Failed to load configuration: ${err.message}`);
159
+ // Don't throw, just start with empty or partial config
160
+ this.emit('error', err);
161
+ }
162
+ }
163
+ /**
164
+ * Get the full configuration object
165
+ * 获取完整的配置对象
166
+ */
167
+ getAll() {
168
+ return JSON.parse(JSON.stringify(this.config));
169
+ }
170
+ // --- Private Helpers ---
171
+ triggerSave() {
172
+ if (this.saveTimer) {
173
+ clearTimeout(this.saveTimer);
174
+ }
175
+ this.saveTimer = setTimeout(() => {
176
+ this.save();
177
+ }, this.saveDelay);
178
+ }
179
+ getDeep(obj, path) {
180
+ if (!path)
181
+ return undefined;
182
+ const keys = path.split('.');
183
+ let current = obj;
184
+ for (const key of keys) {
185
+ if (current === undefined || current === null)
186
+ return undefined;
187
+ current = current[key];
188
+ }
189
+ return current;
190
+ }
191
+ setDeep(obj, path, value) {
192
+ if (!path)
193
+ return;
194
+ const keys = path.split('.');
195
+ const lastKey = keys.pop();
196
+ let current = obj;
197
+ for (const key of keys) {
198
+ if (current[key] === undefined || current[key] === null || typeof current[key] !== 'object') {
199
+ current[key] = {};
200
+ }
201
+ current = current[key];
202
+ }
203
+ current[lastKey] = value;
204
+ }
205
+ deleteDeep(obj, path) {
206
+ if (!path)
207
+ return;
208
+ const keys = path.split('.');
209
+ const lastKey = keys.pop();
210
+ let current = obj;
211
+ for (const key of keys) {
212
+ if (current[key] === undefined || current[key] === null)
213
+ return;
214
+ current = current[key];
215
+ }
216
+ delete current[lastKey];
217
+ }
218
+ }exports.ConfigManager=ConfigManager;//# sourceMappingURL=ConfigManager.js.map