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.
- package/LICENSE +21 -0
- package/README.md +302 -0
- package/README.zh-CN.md +308 -0
- package/dist/core/error/WindowError.d.ts +56 -0
- package/dist/core/error/WindowError.js +71 -0
- package/dist/core/error/WindowError.js.map +1 -0
- package/dist/core/error/WindowError.mjs +71 -0
- package/dist/core/error/WindowError.mjs.map +1 -0
- package/dist/core/ipc/IpcHandler.d.ts +48 -0
- package/dist/core/ipc/IpcHandler.js +59 -0
- package/dist/core/ipc/IpcHandler.js.map +1 -0
- package/dist/core/ipc/IpcHandler.mjs +59 -0
- package/dist/core/ipc/IpcHandler.mjs.map +1 -0
- package/dist/core/ipc/IpcRouter.d.ts +70 -0
- package/dist/core/ipc/IpcRouter.js +143 -0
- package/dist/core/ipc/IpcRouter.js.map +1 -0
- package/dist/core/ipc/IpcRouter.mjs +143 -0
- package/dist/core/ipc/IpcRouter.mjs.map +1 -0
- package/dist/core/ipc/index.d.ts +3 -0
- package/dist/core/ipc/index.js +1 -0
- package/dist/core/ipc/index.js.map +1 -0
- package/dist/core/ipc/index.mjs +1 -0
- package/dist/core/ipc/index.mjs.map +1 -0
- package/dist/core/ipc/ipc-router.type.d.ts +73 -0
- package/dist/core/ipc/transport/index.d.ts +65 -0
- package/dist/core/ipc/transport/index.js +229 -0
- package/dist/core/ipc/transport/index.js.map +1 -0
- package/dist/core/ipc/transport/index.mjs +229 -0
- package/dist/core/ipc/transport/index.mjs.map +1 -0
- package/dist/core/ipc/transport/ipc.type.d.ts +36 -0
- package/dist/core/lifecycle/LifecycleManager.d.ts +66 -0
- package/dist/core/lifecycle/LifecycleManager.js +140 -0
- package/dist/core/lifecycle/LifecycleManager.js.map +1 -0
- package/dist/core/lifecycle/LifecycleManager.mjs +140 -0
- package/dist/core/lifecycle/LifecycleManager.mjs.map +1 -0
- package/dist/core/message-bus/MessageBus.d.ts +282 -0
- package/dist/core/message-bus/MessageBus.js +677 -0
- package/dist/core/message-bus/MessageBus.js.map +1 -0
- package/dist/core/message-bus/MessageBus.mjs +677 -0
- package/dist/core/message-bus/MessageBus.mjs.map +1 -0
- package/dist/core/message-bus/MessageBusClient.d.ts +100 -0
- package/dist/core/message-bus/MessageBusClient.js +280 -0
- package/dist/core/message-bus/MessageBusClient.js.map +1 -0
- package/dist/core/message-bus/MessageBusClient.mjs +280 -0
- package/dist/core/message-bus/MessageBusClient.mjs.map +1 -0
- package/dist/core/message-bus/core/DataStoreManager.d.ts +51 -0
- package/dist/core/message-bus/core/DataStoreManager.js +94 -0
- package/dist/core/message-bus/core/DataStoreManager.js.map +1 -0
- package/dist/core/message-bus/core/DataStoreManager.mjs +94 -0
- package/dist/core/message-bus/core/DataStoreManager.mjs.map +1 -0
- package/dist/core/message-bus/core/ManagedPort.d.ts +26 -0
- package/dist/core/message-bus/core/ManagedPort.js +55 -0
- package/dist/core/message-bus/core/ManagedPort.js.map +1 -0
- package/dist/core/message-bus/core/ManagedPort.mjs +55 -0
- package/dist/core/message-bus/core/ManagedPort.mjs.map +1 -0
- package/dist/core/message-bus/core/PortManager.d.ts +47 -0
- package/dist/core/message-bus/core/PortManager.js +114 -0
- package/dist/core/message-bus/core/PortManager.js.map +1 -0
- package/dist/core/message-bus/core/PortManager.mjs +114 -0
- package/dist/core/message-bus/core/PortManager.mjs.map +1 -0
- package/dist/core/message-bus/core/SubscriptionManager.d.ts +36 -0
- package/dist/core/message-bus/core/SubscriptionManager.js +78 -0
- package/dist/core/message-bus/core/SubscriptionManager.js.map +1 -0
- package/dist/core/message-bus/core/SubscriptionManager.mjs +78 -0
- package/dist/core/message-bus/core/SubscriptionManager.mjs.map +1 -0
- package/dist/core/message-bus/core/TransactionManager.d.ts +54 -0
- package/dist/core/message-bus/core/TransactionManager.js +95 -0
- package/dist/core/message-bus/core/TransactionManager.js.map +1 -0
- package/dist/core/message-bus/core/TransactionManager.mjs +95 -0
- package/dist/core/message-bus/core/TransactionManager.mjs.map +1 -0
- package/dist/core/message-bus/core/index.d.ts +5 -0
- package/dist/core/message-bus/index.d.ts +4 -0
- package/dist/core/message-bus/index.js +1 -0
- package/dist/core/message-bus/index.js.map +1 -0
- package/dist/core/message-bus/index.mjs +1 -0
- package/dist/core/message-bus/index.mjs.map +1 -0
- package/dist/core/message-bus/message-bus.type.d.ts +143 -0
- package/dist/core/message-bus/message-bus.type.js +26 -0
- package/dist/core/message-bus/message-bus.type.js.map +1 -0
- package/dist/core/message-bus/message-bus.type.mjs +26 -0
- package/dist/core/message-bus/message-bus.type.mjs.map +1 -0
- package/dist/core/message-bus/preload.d.ts +16 -0
- package/dist/core/message-bus/preload.js +27 -0
- package/dist/core/message-bus/preload.js.map +1 -0
- package/dist/core/message-bus/preload.mjs +27 -0
- package/dist/core/message-bus/preload.mjs.map +1 -0
- package/dist/core/message-bus/transport/ITransport.d.ts +40 -0
- package/dist/core/message-bus/transport/IpcTransport.d.ts +18 -0
- package/dist/core/message-bus/transport/IpcTransport.js +60 -0
- package/dist/core/message-bus/transport/IpcTransport.js.map +1 -0
- package/dist/core/message-bus/transport/IpcTransport.mjs +60 -0
- package/dist/core/message-bus/transport/IpcTransport.mjs.map +1 -0
- package/dist/core/message-bus/transport/MessagePortTransport.d.ts +15 -0
- package/dist/core/message-bus/transport/MessagePortTransport.js +35 -0
- package/dist/core/message-bus/transport/MessagePortTransport.js.map +1 -0
- package/dist/core/message-bus/transport/MessagePortTransport.mjs +35 -0
- package/dist/core/message-bus/transport/MessagePortTransport.mjs.map +1 -0
- package/dist/core/message-bus/transport/index.d.ts +3 -0
- package/dist/core/window/IpcSetup.d.ts +50 -0
- package/dist/core/window/IpcSetup.js +96 -0
- package/dist/core/window/IpcSetup.js.map +1 -0
- package/dist/core/window/IpcSetup.mjs +96 -0
- package/dist/core/window/IpcSetup.mjs.map +1 -0
- package/dist/core/window/WindowCreator.d.ts +66 -0
- package/dist/core/window/WindowCreator.js +168 -0
- package/dist/core/window/WindowCreator.js.map +1 -0
- package/dist/core/window/WindowCreator.mjs +168 -0
- package/dist/core/window/WindowCreator.mjs.map +1 -0
- package/dist/core/window/WindowManager.d.ts +214 -0
- package/dist/core/window/WindowManager.js +583 -0
- package/dist/core/window/WindowManager.js.map +1 -0
- package/dist/core/window/WindowManager.mjs +583 -0
- package/dist/core/window/WindowManager.mjs.map +1 -0
- package/dist/core/window/WindowStore.d.ts +136 -0
- package/dist/core/window/WindowStore.js +436 -0
- package/dist/core/window/WindowStore.js.map +1 -0
- package/dist/core/window/WindowStore.mjs +436 -0
- package/dist/core/window/WindowStore.mjs.map +1 -0
- package/dist/core/window/constants.d.ts +17 -0
- package/dist/core/window/constants.js +15 -0
- package/dist/core/window/constants.js.map +1 -0
- package/dist/core/window/constants.mjs +15 -0
- package/dist/core/window/constants.mjs.map +1 -0
- package/dist/core/window/core/MetricsManager.d.ts +14 -0
- package/dist/core/window/core/MetricsManager.js +27 -0
- package/dist/core/window/core/MetricsManager.js.map +1 -0
- package/dist/core/window/core/MetricsManager.mjs +27 -0
- package/dist/core/window/core/MetricsManager.mjs.map +1 -0
- package/dist/core/window/core/PluginExecutor.d.ts +22 -0
- package/dist/core/window/core/PluginExecutor.js +110 -0
- package/dist/core/window/core/PluginExecutor.js.map +1 -0
- package/dist/core/window/core/PluginExecutor.mjs +110 -0
- package/dist/core/window/core/PluginExecutor.mjs.map +1 -0
- package/dist/core/window/core/WindowContextManager.d.ts +26 -0
- package/dist/core/window/core/WindowContextManager.js +59 -0
- package/dist/core/window/core/WindowContextManager.js.map +1 -0
- package/dist/core/window/core/WindowContextManager.mjs +59 -0
- package/dist/core/window/core/WindowContextManager.mjs.map +1 -0
- package/dist/core/window/core/WindowLifecycle.d.ts +15 -0
- package/dist/core/window/core/WindowLifecycle.js +150 -0
- package/dist/core/window/core/WindowLifecycle.js.map +1 -0
- package/dist/core/window/core/WindowLifecycle.mjs +150 -0
- package/dist/core/window/core/WindowLifecycle.mjs.map +1 -0
- package/dist/core/window/core/WindowOperator.d.ts +90 -0
- package/dist/core/window/core/WindowOperator.js +154 -0
- package/dist/core/window/core/WindowOperator.js.map +1 -0
- package/dist/core/window/core/WindowOperator.mjs +154 -0
- package/dist/core/window/core/WindowOperator.mjs.map +1 -0
- package/dist/core/window/core/WindowRegistry.d.ts +168 -0
- package/dist/core/window/core/WindowRegistry.js +331 -0
- package/dist/core/window/core/WindowRegistry.js.map +1 -0
- package/dist/core/window/core/WindowRegistry.mjs +331 -0
- package/dist/core/window/core/WindowRegistry.mjs.map +1 -0
- package/dist/core/window/core/WindowStateManager.d.ts +40 -0
- package/dist/core/window/core/WindowStateManager.js +110 -0
- package/dist/core/window/core/WindowStateManager.js.map +1 -0
- package/dist/core/window/core/WindowStateManager.mjs +110 -0
- package/dist/core/window/core/WindowStateManager.mjs.map +1 -0
- package/dist/core/window/index.d.ts +7 -0
- package/dist/core/window/index.js +1 -0
- package/dist/core/window/index.js.map +1 -0
- package/dist/core/window/index.mjs +1 -0
- package/dist/core/window/index.mjs.map +1 -0
- package/dist/core/window/window-manager.schema.d.ts +50 -0
- package/dist/core/window/window-manager.schema.js +87 -0
- package/dist/core/window/window-manager.schema.js.map +1 -0
- package/dist/core/window/window-manager.schema.mjs +87 -0
- package/dist/core/window/window-manager.schema.mjs.map +1 -0
- package/dist/core/window/window-manager.type.d.ts +365 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +33 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +1 -0
- package/dist/infrastructure/config/ConfigManager.d.ts +133 -0
- package/dist/infrastructure/config/ConfigManager.js +218 -0
- package/dist/infrastructure/config/ConfigManager.js.map +1 -0
- package/dist/infrastructure/config/ConfigManager.mjs +218 -0
- package/dist/infrastructure/config/ConfigManager.mjs.map +1 -0
- package/dist/infrastructure/config/index.d.ts +1 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.d.ts +106 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.js +218 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.js.map +1 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.mjs +218 -0
- package/dist/infrastructure/debug/EnhancedDebugHelper.mjs.map +1 -0
- package/dist/infrastructure/debug/PerformanceMonitor.d.ts +45 -0
- package/dist/infrastructure/debug/PerformanceMonitor.js +67 -0
- package/dist/infrastructure/debug/PerformanceMonitor.js.map +1 -0
- package/dist/infrastructure/debug/PerformanceMonitor.mjs +67 -0
- package/dist/infrastructure/debug/PerformanceMonitor.mjs.map +1 -0
- package/dist/infrastructure/debug/index.d.ts +22 -0
- package/dist/infrastructure/debug/index.js +47 -0
- package/dist/infrastructure/debug/index.js.map +1 -0
- package/dist/infrastructure/debug/index.mjs +47 -0
- package/dist/infrastructure/debug/index.mjs.map +1 -0
- package/dist/infrastructure/errors/ErrorCodes.d.ts +74 -0
- package/dist/infrastructure/errors/ErrorCodes.js +78 -0
- package/dist/infrastructure/errors/ErrorCodes.js.map +1 -0
- package/dist/infrastructure/errors/ErrorCodes.mjs +78 -0
- package/dist/infrastructure/errors/ErrorCodes.mjs.map +1 -0
- package/dist/infrastructure/errors/StandardError.d.ts +61 -0
- package/dist/infrastructure/errors/StandardError.js +84 -0
- package/dist/infrastructure/errors/StandardError.js.map +1 -0
- package/dist/infrastructure/errors/StandardError.mjs +84 -0
- package/dist/infrastructure/errors/StandardError.mjs.map +1 -0
- package/dist/infrastructure/errors/index.d.ts +13 -0
- package/dist/infrastructure/errors/index.js +24 -0
- package/dist/infrastructure/errors/index.js.map +1 -0
- package/dist/infrastructure/errors/index.mjs +24 -0
- package/dist/infrastructure/errors/index.mjs.map +1 -0
- package/dist/infrastructure/logger/ElectronLogger.d.ts +39 -0
- package/dist/infrastructure/logger/ElectronLogger.js +65 -0
- package/dist/infrastructure/logger/ElectronLogger.js.map +1 -0
- package/dist/infrastructure/logger/ElectronLogger.mjs +65 -0
- package/dist/infrastructure/logger/ElectronLogger.mjs.map +1 -0
- package/dist/infrastructure/logger/index.d.ts +2 -0
- package/dist/infrastructure/logger/logger.type.d.ts +8 -0
- package/dist/internal/types/BrandedTypes.d.ts +64 -0
- package/dist/internal/types/BrandedTypes.js +54 -0
- package/dist/internal/types/BrandedTypes.js.map +1 -0
- package/dist/internal/types/BrandedTypes.mjs +54 -0
- package/dist/internal/types/BrandedTypes.mjs.map +1 -0
- package/dist/internal/types/PerformanceOptions.d.ts +87 -0
- package/dist/internal/types/branded.d.ts +42 -0
- package/dist/internal/utils/MessageDispatcher.d.ts +67 -0
- package/dist/internal/utils/MessageDispatcher.js +96 -0
- package/dist/internal/utils/MessageDispatcher.js.map +1 -0
- package/dist/internal/utils/MessageDispatcher.mjs +96 -0
- package/dist/internal/utils/MessageDispatcher.mjs.map +1 -0
- package/dist/internal/utils/RateLimiter.d.ts +41 -0
- package/dist/internal/utils/RateLimiter.js +83 -0
- package/dist/internal/utils/RateLimiter.js.map +1 -0
- package/dist/internal/utils/RateLimiter.mjs +83 -0
- package/dist/internal/utils/RateLimiter.mjs.map +1 -0
- package/dist/internal/utils/StateKeeper.d.ts +125 -0
- package/dist/internal/utils/StateKeeper.js +334 -0
- package/dist/internal/utils/StateKeeper.js.map +1 -0
- package/dist/internal/utils/StateKeeper.mjs +334 -0
- package/dist/internal/utils/StateKeeper.mjs.map +1 -0
- package/dist/internal/utils/branded-helpers.d.ts +33 -0
- package/dist/internal/utils/index.d.ts +5 -0
- package/dist/preload/index.d.ts +45 -0
- package/dist/preload/index.js +91 -0
- package/dist/preload/index.js.map +1 -0
- package/dist/preload/index.mjs +91 -0
- package/dist/preload/index.mjs.map +1 -0
- package/dist/preload/preload.type.d.ts +15 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/types.mjs +1 -0
- package/dist/types.mjs.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {z}from'zod';import {MessageDispatcher}from'../../internal/utils/MessageDispatcher.mjs';import {IpcHandlerError}from'../../infrastructure/errors/index.mjs';import {RateLimiter}from'../../internal/utils/RateLimiter.mjs';import {PerformanceMonitor}from'../../infrastructure/debug/PerformanceMonitor.mjs';// Define the schema for IpcRequest
|
|
2
|
+
// 定义 IpcRequest 的 Schema
|
|
3
|
+
const IpcRequestSchema = z.object({
|
|
4
|
+
name: z.string({ message: 'Handler name is required' }),
|
|
5
|
+
payload: z.unknown().optional(),
|
|
6
|
+
});
|
|
7
|
+
class IpcRouter {
|
|
8
|
+
_api = {};
|
|
9
|
+
dispatcher;
|
|
10
|
+
rateLimiter;
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.dispatcher = new MessageDispatcher('IpcRouter', options.logger);
|
|
13
|
+
this.rateLimiter = new RateLimiter({
|
|
14
|
+
logger: options.logger,
|
|
15
|
+
defaultLimit: options.defaultRateLimit,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add a single IPC handler
|
|
20
|
+
* 添加单个IPC处理器
|
|
21
|
+
* @param handler - IPC handler instance (IPC处理器实例)
|
|
22
|
+
*/
|
|
23
|
+
addHandler(handler) {
|
|
24
|
+
this.dispatcher.register(handler.name, handler.callback, handler.schema);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Add multiple IPC handlers
|
|
28
|
+
* 添加多个IPC处理器
|
|
29
|
+
* @param handlers - Array of IPC handler instances (IPC处理器实例数组)
|
|
30
|
+
*/
|
|
31
|
+
addHandlers(handlers) {
|
|
32
|
+
handlers.forEach((handler) => this.addHandler(handler));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Set rate limit for a specific handler
|
|
36
|
+
* 为特定处理器设置限流
|
|
37
|
+
* @param handlerName - Handler name (处理器名称)
|
|
38
|
+
* @param config - Rate limit configuration (限流配置)
|
|
39
|
+
*/
|
|
40
|
+
setRateLimit(handlerName, config) {
|
|
41
|
+
this.rateLimiter.setLimit(handlerName, config);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Remove IPC handler by name
|
|
45
|
+
* 移除指定名称的IPC处理器
|
|
46
|
+
* @param name - Handler name (处理器名称)
|
|
47
|
+
*/
|
|
48
|
+
removeHandler(name) {
|
|
49
|
+
this.dispatcher.unregister(name);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Trigger callback of specified IPC handler
|
|
53
|
+
* 触发指定名称的IPC处理器回调
|
|
54
|
+
* @param data - Object containing handler name and data (包含处理器名称和数据的对象)
|
|
55
|
+
* @param senderId - Optional sender ID (e.g. window ID) for rate limiting (可选的发送者 ID,用于限流)
|
|
56
|
+
* @returns Return value of the callback function (回调函数的返回值)
|
|
57
|
+
*/
|
|
58
|
+
handle(data, senderId) {
|
|
59
|
+
const perf = PerformanceMonitor.getInstance();
|
|
60
|
+
const measureId = `ipc-${String(data.name)}-${Date.now()}`;
|
|
61
|
+
const handleAsync = async () => {
|
|
62
|
+
try {
|
|
63
|
+
perf.startMeasure(measureId, 'IPC Call', { handler: String(data.name), senderId });
|
|
64
|
+
// 0. Rate Limiting Check
|
|
65
|
+
// 0. 限流检查
|
|
66
|
+
if (senderId !== undefined) {
|
|
67
|
+
const rateLimitKey = `${senderId}:${String(data.name)}`;
|
|
68
|
+
const allowed = this.rateLimiter.check(rateLimitKey, String(data.name));
|
|
69
|
+
if (!allowed) {
|
|
70
|
+
throw new IpcHandlerError(String(data.name), new Error(`Rate limit exceeded for handler "${String(data.name)}"`));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Runtime validation using Zod (Envelope validation)
|
|
74
|
+
// 使用 Zod 进行运行时校验 (信封校验)
|
|
75
|
+
const validationResult = IpcRequestSchema.safeParse(data);
|
|
76
|
+
if (!validationResult.success) {
|
|
77
|
+
console.warn('[IpcRouter] Invalid IPC request data:', validationResult.error.format());
|
|
78
|
+
throw new IpcHandlerError('validation', new Error(`Invalid IPC request: ${validationResult.error.message}`));
|
|
79
|
+
}
|
|
80
|
+
// Payload validation if schema exists
|
|
81
|
+
// 如果存在 Schema,则进行 Payload 校验
|
|
82
|
+
const schema = this.dispatcher.getMetadata(data.name);
|
|
83
|
+
if (schema) {
|
|
84
|
+
const payloadResult = schema.safeParse(data.payload);
|
|
85
|
+
if (!payloadResult.success) {
|
|
86
|
+
console.warn(`[IpcRouter] Invalid payload for handler "${String(data.name)}":`, payloadResult.error.message);
|
|
87
|
+
throw new IpcHandlerError(String(data.name), new Error(`Invalid payload: ${payloadResult.error.message}`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// 1. Dependency Injection (inject this._api)
|
|
91
|
+
// 1. 依赖注入 (注入 this._api)
|
|
92
|
+
const context = { ...this._api };
|
|
93
|
+
// 2. Dispatch
|
|
94
|
+
// 2. 分发
|
|
95
|
+
const result = await Promise.resolve(this.dispatcher.dispatch(data.name, context, data.payload));
|
|
96
|
+
perf.endMeasure(measureId, { status: 'success' });
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
perf.endMeasure(measureId, {
|
|
101
|
+
status: 'error',
|
|
102
|
+
error: error instanceof Error ? error.message : String(error),
|
|
103
|
+
});
|
|
104
|
+
// Error handling
|
|
105
|
+
// 错误处理
|
|
106
|
+
if (error instanceof IpcHandlerError) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
throw new IpcHandlerError(String(data.name), error);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
return handleAsync();
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Inject API (Dependencies)
|
|
116
|
+
* 注入 API (依赖)
|
|
117
|
+
* @param name - API Name (API 名称)
|
|
118
|
+
* @param api - API Instance (API 实例)
|
|
119
|
+
*/
|
|
120
|
+
addApi(name, api) {
|
|
121
|
+
this._api[name] = api;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Inject multiple APIs (Batch)
|
|
125
|
+
* 批量注入 API
|
|
126
|
+
* @param apis - Object containing API instances (包含 API 实例的对象)
|
|
127
|
+
*/
|
|
128
|
+
addApis(apis) {
|
|
129
|
+
Object.entries(apis).forEach(([name, api]) => {
|
|
130
|
+
this.addApi(name, api);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Dispose IpcRouter
|
|
135
|
+
* 释放 IpcRouter
|
|
136
|
+
*/
|
|
137
|
+
dispose() {
|
|
138
|
+
this.rateLimiter.stopCleanup();
|
|
139
|
+
this.rateLimiter.clear();
|
|
140
|
+
this.dispatcher.clear();
|
|
141
|
+
this._api = {};
|
|
142
|
+
}
|
|
143
|
+
}export{IpcRouter as default};//# sourceMappingURL=IpcRouter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IpcRouter.mjs","sources":["../../../src/core/ipc/IpcRouter.ts"],"sourcesContent":["import IpcHandler from './IpcHandler';\nimport { IpcRequest, IpcSchema, IpcDefinition } from './ipc-router.type';\nimport { z } from 'zod';\nimport { MessageDispatcher } from '@/internal/utils/MessageDispatcher';\nimport { ILogger } from '@/infrastructure/logger';\nimport { IpcHandlerError } from '@/infrastructure/errors';\nimport { RateLimiter, RateLimitConfig } from '@/internal/utils/RateLimiter';\nimport { PerformanceMonitor } from '@/infrastructure/debug';\n\n// Define the schema for IpcRequest\n// 定义 IpcRequest 的 Schema\nconst IpcRequestSchema = z.object({\n name: z.string({ message: 'Handler name is required' }),\n payload: z.unknown().optional(),\n});\n\nexport default class IpcRouter<\n Api extends Record<string, any> = Record<string, any>,\n Schema extends IpcSchema = Record<string, IpcDefinition>,\n> {\n private _api: Api = {} as Api;\n private dispatcher: MessageDispatcher<Api>;\n private rateLimiter: RateLimiter;\n\n constructor(options: { logger?: ILogger; defaultRateLimit?: RateLimitConfig } = {}) {\n this.dispatcher = new MessageDispatcher('IpcRouter', options.logger);\n this.rateLimiter = new RateLimiter({\n logger: options.logger,\n defaultLimit: options.defaultRateLimit,\n });\n }\n\n /**\n * Add a single IPC handler\n * 添加单个IPC处理器\n * @param handler - IPC handler instance (IPC处理器实例)\n */\n addHandler<K extends keyof Schema>(\n handler: IpcHandler<Api, Schema[K]['payload'], Schema[K]['response']> & {\n name: K;\n }\n ): void {\n this.dispatcher.register(handler.name as string, handler.callback, handler.schema);\n }\n\n /**\n * Add multiple IPC handlers\n * 添加多个IPC处理器\n * @param handlers - Array of IPC handler instances (IPC处理器实例数组)\n */\n addHandlers(handlers: (IpcHandler<Api, any, any> & { name: keyof Schema })[]): void {\n handlers.forEach((handler) => this.addHandler(handler as any));\n }\n\n /**\n * Set rate limit for a specific handler\n * 为特定处理器设置限流\n * @param handlerName - Handler name (处理器名称)\n * @param config - Rate limit configuration (限流配置)\n */\n setRateLimit(handlerName: keyof Schema, config: RateLimitConfig): void {\n this.rateLimiter.setLimit(handlerName as string, config);\n }\n\n /**\n * Remove IPC handler by name\n * 移除指定名称的IPC处理器\n * @param name - Handler name (处理器名称)\n */\n removeHandler(name: string): void {\n this.dispatcher.unregister(name);\n }\n\n /**\n * Trigger callback of specified IPC handler\n * 触发指定名称的IPC处理器回调\n * @param data - Object containing handler name and data (包含处理器名称和数据的对象)\n * @param senderId - Optional sender ID (e.g. window ID) for rate limiting (可选的发送者 ID,用于限流)\n * @returns Return value of the callback function (回调函数的返回值)\n */\n handle<K extends keyof Schema>(\n data: IpcRequest<Schema[K]['payload']> & { name: K },\n senderId?: number | string\n ): Promise<Schema[K]['response']> {\n const perf = PerformanceMonitor.getInstance();\n const measureId = `ipc-${String(data.name)}-${Date.now()}`;\n\n const handleAsync = async (): Promise<Schema[K]['response']> => {\n try {\n perf.startMeasure(measureId, 'IPC Call', { handler: String(data.name), senderId });\n\n // 0. Rate Limiting Check\n // 0. 限流检查\n if (senderId !== undefined) {\n const rateLimitKey = `${senderId}:${String(data.name)}`;\n const allowed = this.rateLimiter.check(rateLimitKey, String(data.name));\n if (!allowed) {\n throw new IpcHandlerError(\n String(data.name),\n new Error(`Rate limit exceeded for handler \"${String(data.name)}\"`)\n );\n }\n }\n\n // Runtime validation using Zod (Envelope validation)\n // 使用 Zod 进行运行时校验 (信封校验)\n const validationResult = IpcRequestSchema.safeParse(data);\n\n if (!validationResult.success) {\n console.warn('[IpcRouter] Invalid IPC request data:', validationResult.error.format());\n throw new IpcHandlerError(\n 'validation',\n new Error(`Invalid IPC request: ${validationResult.error.message}`)\n );\n }\n\n // Payload validation if schema exists\n // 如果存在 Schema,则进行 Payload 校验\n const schema = this.dispatcher.getMetadata(data.name as string) as\n | z.ZodType<any>\n | undefined;\n if (schema) {\n const payloadResult = schema.safeParse(data.payload);\n if (!payloadResult.success) {\n console.warn(\n `[IpcRouter] Invalid payload for handler \"${String(data.name)}\":`,\n payloadResult.error.message\n );\n throw new IpcHandlerError(\n String(data.name),\n new Error(`Invalid payload: ${payloadResult.error.message}`)\n );\n }\n }\n\n // 1. Dependency Injection (inject this._api)\n // 1. 依赖注入 (注入 this._api)\n const context = { ...this._api };\n\n // 2. Dispatch\n // 2. 分发\n const result = await Promise.resolve(\n this.dispatcher.dispatch(data.name as string, context, data.payload)\n );\n\n perf.endMeasure(measureId, { status: 'success' });\n return result as Schema[K]['response'];\n } catch (error: any) {\n perf.endMeasure(measureId, {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n });\n\n // Error handling\n // 错误处理\n if (error instanceof IpcHandlerError) {\n throw error;\n }\n throw new IpcHandlerError(String(data.name), error);\n }\n };\n\n return handleAsync();\n }\n\n /**\n * Inject API (Dependencies)\n * 注入 API (依赖)\n * @param name - API Name (API 名称)\n * @param api - API Instance (API 实例)\n */\n addApi(name: keyof Api, api: any): void {\n this._api[name] = api;\n }\n\n /**\n * Inject multiple APIs (Batch)\n * 批量注入 API\n * @param apis - Object containing API instances (包含 API 实例的对象)\n */\n addApis(apis: Partial<Api>): void {\n Object.entries(apis).forEach(([name, api]) => {\n this.addApi(name as keyof Api, api);\n });\n }\n\n /**\n * Dispose IpcRouter\n * 释放 IpcRouter\n */\n dispose(): void {\n this.rateLimiter.stopCleanup();\n this.rateLimiter.clear();\n this.dispatcher.clear();\n this._api = {} as Api;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var IpcRouter=require('./IpcRouter.js'),IpcHandler=require('./IpcHandler.js');exports.IpcRouter=IpcRouter;exports.IpcHandler=IpcHandler;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{default as IpcRouter}from'./IpcRouter.mjs';export{default as IpcHandler}from'./IpcHandler.mjs';//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IPC Request Interface
|
|
3
|
+
* IPC 请求接口
|
|
4
|
+
*
|
|
5
|
+
* @template T - Payload type (载荷类型)
|
|
6
|
+
*/
|
|
7
|
+
export interface IpcRequest<T = any> {
|
|
8
|
+
/**
|
|
9
|
+
* Handler name
|
|
10
|
+
* 处理器名称
|
|
11
|
+
*/
|
|
12
|
+
name: string;
|
|
13
|
+
/**
|
|
14
|
+
* Request payload
|
|
15
|
+
* 请求载荷
|
|
16
|
+
*/
|
|
17
|
+
payload?: T;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* IPC Handler Callback Interface
|
|
21
|
+
* IPC 处理器回调接口
|
|
22
|
+
*
|
|
23
|
+
* @template Context - Context/API type (上下文/API 类型)
|
|
24
|
+
* @template T - Input data type (输入数据类型)
|
|
25
|
+
* @template R - Return value type (返回值类型)
|
|
26
|
+
*/
|
|
27
|
+
export interface IpcHandlerCallback<Context = Record<string, any>, T = any, R = any> {
|
|
28
|
+
/**
|
|
29
|
+
* Callback function
|
|
30
|
+
* 回调函数
|
|
31
|
+
* @param api - API object exposed to the handler (暴露给处理器的 API 对象)
|
|
32
|
+
* @param data - Input data (输入数据)
|
|
33
|
+
* @returns Result of the operation (操作结果)
|
|
34
|
+
*/
|
|
35
|
+
(api: Context, data: T): R;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* IPC Handler Data Interface
|
|
39
|
+
* IPC 处理器数据接口
|
|
40
|
+
*
|
|
41
|
+
* @template T - Data payload type (数据载荷类型)
|
|
42
|
+
*/
|
|
43
|
+
export interface IpcHandlerData<T = any> {
|
|
44
|
+
/**
|
|
45
|
+
* Handler name
|
|
46
|
+
* 处理器名称
|
|
47
|
+
*/
|
|
48
|
+
name: string;
|
|
49
|
+
/**
|
|
50
|
+
* Data payload
|
|
51
|
+
* 数据载荷
|
|
52
|
+
*/
|
|
53
|
+
data?: T;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* IPC Definition Interface
|
|
57
|
+
* IPC 定义接口
|
|
58
|
+
*
|
|
59
|
+
* @template Payload - Request payload type (请求载荷类型)
|
|
60
|
+
* @template Response - Response data type (响应数据类型)
|
|
61
|
+
*/
|
|
62
|
+
export interface IpcDefinition<Payload = any, Response = any> {
|
|
63
|
+
payload: Payload;
|
|
64
|
+
response: Response;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* IPC Schema Type
|
|
68
|
+
* IPC 架构类型
|
|
69
|
+
*
|
|
70
|
+
* Mapping of handler names to their definitions
|
|
71
|
+
* 处理器名称到定义的映射
|
|
72
|
+
*/
|
|
73
|
+
export type IpcSchema = Record<string, IpcDefinition>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ILogger } from '@/infrastructure/logger';
|
|
2
|
+
import type { IPCEventHandler, IPCHandleHandler, IIpcTransport } from './ipc.type';
|
|
3
|
+
/**
|
|
4
|
+
* @internal This class is an internal implementation detail.
|
|
5
|
+
* Please use `IpcRouter` for application-level IPC communication.
|
|
6
|
+
*/
|
|
7
|
+
export default class IpcTransport implements IIpcTransport {
|
|
8
|
+
private readonly channels;
|
|
9
|
+
private readonly handlers;
|
|
10
|
+
private logger;
|
|
11
|
+
constructor(logger?: ILogger);
|
|
12
|
+
/**
|
|
13
|
+
* Set custom logger
|
|
14
|
+
* 设置自定义日志实例
|
|
15
|
+
* @param logger - Logger instance
|
|
16
|
+
*/
|
|
17
|
+
setLogger(logger: ILogger): void;
|
|
18
|
+
/**
|
|
19
|
+
* 注册监听事件 (ipcMain.on)
|
|
20
|
+
* @param channel - 事件名称
|
|
21
|
+
* @param cb - 回调函数
|
|
22
|
+
*/
|
|
23
|
+
on(channel: string, cb?: IPCEventHandler): void;
|
|
24
|
+
/**
|
|
25
|
+
* 注册处理事件 (ipcMain.handle)
|
|
26
|
+
* 注意: 同一个 channel 只能注册一个 handler,重复注册会覆盖之前的 handler
|
|
27
|
+
* @param channel - 事件名称
|
|
28
|
+
* @param cb - 回调函数
|
|
29
|
+
*/
|
|
30
|
+
handle(channel: string, cb?: IPCHandleHandler): void;
|
|
31
|
+
/**
|
|
32
|
+
* 移除指定频道的监听器
|
|
33
|
+
* @param channel - 频道名称
|
|
34
|
+
* @param cb - 可选,指定要移除的回调函数。如果不传,则移除该频道下所有由 IpcTransport 管理的监听器
|
|
35
|
+
*/
|
|
36
|
+
removeListener(channel: string, cb?: IPCEventHandler): void;
|
|
37
|
+
/**
|
|
38
|
+
* 移除所有监听器
|
|
39
|
+
* @param channel - 可选,指定频道名称
|
|
40
|
+
*/
|
|
41
|
+
removeAllListeners(channel?: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* 移除处理器
|
|
44
|
+
* @param channel - 频道名称
|
|
45
|
+
*/
|
|
46
|
+
removeHandler(channel: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* 移除所有处理器
|
|
49
|
+
*/
|
|
50
|
+
removeAllHandlers(): void;
|
|
51
|
+
/**
|
|
52
|
+
* 记录错误信息
|
|
53
|
+
* @param err - 错误信息
|
|
54
|
+
*/
|
|
55
|
+
error(err: string): void;
|
|
56
|
+
/**
|
|
57
|
+
* 记录普通日志
|
|
58
|
+
* @param data - 日志信息
|
|
59
|
+
*/
|
|
60
|
+
log(data: string): void;
|
|
61
|
+
private logEvent;
|
|
62
|
+
private logError;
|
|
63
|
+
private serializeError;
|
|
64
|
+
private safeStringify;
|
|
65
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use strict';var electron=require('electron'),ElectronLogger=require('../../../infrastructure/logger/ElectronLogger.js');const emptyFunc = () => { };
|
|
2
|
+
/**
|
|
3
|
+
* @internal This class is an internal implementation detail.
|
|
4
|
+
* Please use `IpcRouter` for application-level IPC communication.
|
|
5
|
+
*/
|
|
6
|
+
class IpcTransport {
|
|
7
|
+
// 存储所有频道的回调函数 (用于清理)
|
|
8
|
+
// Map<channel, Map<originalCallback, wrappedCallback>>
|
|
9
|
+
channels = new Map();
|
|
10
|
+
handlers = new Set();
|
|
11
|
+
// 日志实例
|
|
12
|
+
logger;
|
|
13
|
+
constructor(logger) {
|
|
14
|
+
this.logger = logger || new ElectronLogger.ElectronLogger({ appName: 'IpcTransport' });
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Set custom logger
|
|
18
|
+
* 设置自定义日志实例
|
|
19
|
+
* @param logger - Logger instance
|
|
20
|
+
*/
|
|
21
|
+
setLogger(logger) {
|
|
22
|
+
this.logger = logger;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 注册监听事件 (ipcMain.on)
|
|
26
|
+
* @param channel - 事件名称
|
|
27
|
+
* @param cb - 回调函数
|
|
28
|
+
*/
|
|
29
|
+
on(channel, cb = emptyFunc) {
|
|
30
|
+
// 包装回调函数以添加日志和错误处理
|
|
31
|
+
const wrappedCb = async (event, ...args) => {
|
|
32
|
+
try {
|
|
33
|
+
this.logEvent(channel, 'on', args);
|
|
34
|
+
await cb(event, ...args);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.logError(channel, 'on', error);
|
|
38
|
+
// 尝试回传错误给发送者
|
|
39
|
+
if (!event.sender.isDestroyed()) {
|
|
40
|
+
event.sender.send(`${channel}:error`, this.serializeError(error));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
// 存储回调引用
|
|
45
|
+
if (!this.channels.has(channel)) {
|
|
46
|
+
this.channels.set(channel, new Map());
|
|
47
|
+
}
|
|
48
|
+
this.channels.get(channel).set(cb, wrappedCb);
|
|
49
|
+
electron.ipcMain.on(channel, wrappedCb);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* 注册处理事件 (ipcMain.handle)
|
|
53
|
+
* 注意: 同一个 channel 只能注册一个 handler,重复注册会覆盖之前的 handler
|
|
54
|
+
* @param channel - 事件名称
|
|
55
|
+
* @param cb - 回调函数
|
|
56
|
+
*/
|
|
57
|
+
handle(channel, cb = emptyFunc) {
|
|
58
|
+
// 确保先移除旧的 handler,防止 electron 抛出 "second handler" 错误
|
|
59
|
+
if (this.handlers.has(channel)) {
|
|
60
|
+
electron.ipcMain.removeHandler(channel);
|
|
61
|
+
}
|
|
62
|
+
this.handlers.add(channel);
|
|
63
|
+
// 包装回调函数以添加日志和错误处理
|
|
64
|
+
const wrappedCb = async (event, ...args) => {
|
|
65
|
+
try {
|
|
66
|
+
this.logEvent(channel, 'handle', args);
|
|
67
|
+
const result = await cb(event, ...args);
|
|
68
|
+
// Wrap result in standard response
|
|
69
|
+
// 将结果包装在标准响应中
|
|
70
|
+
return {
|
|
71
|
+
code: 0,
|
|
72
|
+
message: 'success',
|
|
73
|
+
data: result,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.logError(channel, 'handle', error);
|
|
78
|
+
// Enhanced error handling with StandardError support
|
|
79
|
+
// 增强的错误处理,支持 StandardError
|
|
80
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
81
|
+
// Check if it's a StandardError
|
|
82
|
+
if (error && typeof error === 'object' && 'code' in error && 'category' in error) {
|
|
83
|
+
return {
|
|
84
|
+
code: error.code,
|
|
85
|
+
message: error.message,
|
|
86
|
+
data: null,
|
|
87
|
+
category: error.category,
|
|
88
|
+
details: error.details,
|
|
89
|
+
stack: isDevelopment ? error.stack : undefined,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Return standard error response for regular errors
|
|
93
|
+
// 为常规错误返回标准错误响应
|
|
94
|
+
return {
|
|
95
|
+
code: error.code || 500,
|
|
96
|
+
message: error instanceof Error ? error.message : String(error),
|
|
97
|
+
data: null,
|
|
98
|
+
stack: isDevelopment && error instanceof Error ? error.stack : undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
electron.ipcMain.handle(channel, wrappedCb);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 移除指定频道的监听器
|
|
106
|
+
* @param channel - 频道名称
|
|
107
|
+
* @param cb - 可选,指定要移除的回调函数。如果不传,则移除该频道下所有由 IpcTransport 管理的监听器
|
|
108
|
+
*/
|
|
109
|
+
removeListener(channel, cb) {
|
|
110
|
+
const channelListeners = this.channels.get(channel);
|
|
111
|
+
if (!channelListeners)
|
|
112
|
+
return;
|
|
113
|
+
if (cb) {
|
|
114
|
+
// 移除特定回调
|
|
115
|
+
const wrappedCb = channelListeners.get(cb);
|
|
116
|
+
if (wrappedCb) {
|
|
117
|
+
electron.ipcMain.removeListener(channel, wrappedCb);
|
|
118
|
+
channelListeners.delete(cb);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// 移除该频道下所有由本实例管理的监听器
|
|
123
|
+
for (const wrappedCb of channelListeners.values()) {
|
|
124
|
+
electron.ipcMain.removeListener(channel, wrappedCb);
|
|
125
|
+
}
|
|
126
|
+
channelListeners.clear();
|
|
127
|
+
}
|
|
128
|
+
if (channelListeners.size === 0) {
|
|
129
|
+
this.channels.delete(channel);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* 移除所有监听器
|
|
134
|
+
* @param channel - 可选,指定频道名称
|
|
135
|
+
*/
|
|
136
|
+
removeAllListeners(channel) {
|
|
137
|
+
if (channel) {
|
|
138
|
+
this.removeListener(channel);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
for (const ch of this.channels.keys()) {
|
|
142
|
+
this.removeListener(ch);
|
|
143
|
+
}
|
|
144
|
+
this.channels.clear();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 移除处理器
|
|
149
|
+
* @param channel - 频道名称
|
|
150
|
+
*/
|
|
151
|
+
removeHandler(channel) {
|
|
152
|
+
if (this.handlers.has(channel)) {
|
|
153
|
+
electron.ipcMain.removeHandler(channel);
|
|
154
|
+
this.handlers.delete(channel);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* 移除所有处理器
|
|
159
|
+
*/
|
|
160
|
+
removeAllHandlers() {
|
|
161
|
+
for (const channel of this.handlers) {
|
|
162
|
+
electron.ipcMain.removeHandler(channel);
|
|
163
|
+
}
|
|
164
|
+
this.handlers.clear();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 记录错误信息
|
|
168
|
+
* @param err - 错误信息
|
|
169
|
+
*/
|
|
170
|
+
error(err) {
|
|
171
|
+
this.logger.error(`[IPC System Error]: ${err}`);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 记录普通日志
|
|
175
|
+
* @param data - 日志信息
|
|
176
|
+
*/
|
|
177
|
+
log(data) {
|
|
178
|
+
this.logger.info(`[IPC System Log]: ${data}`);
|
|
179
|
+
}
|
|
180
|
+
// 私有辅助方法:格式化日志
|
|
181
|
+
logEvent(channel, type, args) {
|
|
182
|
+
try {
|
|
183
|
+
// 尝试获取 data.name 作为操作名,这是我们约定的通信格式
|
|
184
|
+
const actionName = args[0]?.name;
|
|
185
|
+
const argStr = actionName ? `[Action: ${actionName}]` : `[Args: ${this.safeStringify(args)}]`;
|
|
186
|
+
this.logger.info(`[${type.toUpperCase()}] ${channel} ${argStr}`);
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
this.logger.info(`[${type.toUpperCase()}] ${channel} [Args parsing failed]`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
logError(channel, type, error) {
|
|
193
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
194
|
+
const errorStack = error instanceof Error ? error.stack : '';
|
|
195
|
+
this.logger.error(`[${type.toUpperCase()} ERROR] ${channel}: ${errorMsg}`, errorStack);
|
|
196
|
+
}
|
|
197
|
+
serializeError(error) {
|
|
198
|
+
if (error instanceof Error) {
|
|
199
|
+
// 获取所有属性,包括不可枚举的
|
|
200
|
+
const serialized = {
|
|
201
|
+
name: error.name,
|
|
202
|
+
message: error.message,
|
|
203
|
+
stack: error.stack,
|
|
204
|
+
};
|
|
205
|
+
// 复制其他自定义属性 (如 code, issues 等)
|
|
206
|
+
for (const key of Object.getOwnPropertyNames(error)) {
|
|
207
|
+
if (!['name', 'message', 'stack'].includes(key)) {
|
|
208
|
+
serialized[key] = error[key];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return serialized;
|
|
212
|
+
}
|
|
213
|
+
if (typeof error === 'object' && error !== null) {
|
|
214
|
+
return error;
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
message: String(error),
|
|
218
|
+
name: 'UnknownError',
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
safeStringify(obj) {
|
|
222
|
+
try {
|
|
223
|
+
return JSON.stringify(obj);
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return '[Circular or Non-serializable]';
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}module.exports=IpcTransport;//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/core/ipc/transport/index.ts"],"sourcesContent":["import { ipcMain, IpcMainEvent, IpcMainInvokeEvent } from 'electron';\nimport { Logger, ILogger } from '@/infrastructure/logger';\nimport type {\n EmptyFunc,\n IPCEventHandler,\n IPCHandleHandler,\n IpcResponse,\n IIpcTransport,\n} from './ipc.type';\n\nconst emptyFunc: EmptyFunc = () => {};\n\n/**\n * @internal This class is an internal implementation detail.\n * Please use `IpcRouter` for application-level IPC communication.\n */\nexport default class IpcTransport implements IIpcTransport {\n // 存储所有频道的回调函数 (用于清理)\n // Map<channel, Map<originalCallback, wrappedCallback>>\n private readonly channels: Map<\n string,\n Map<IPCEventHandler, (event: IpcMainEvent, ...args: unknown[]) => Promise<void>>\n > = new Map();\n private readonly handlers: Set<string> = new Set();\n\n // 日志实例\n private logger: ILogger;\n\n constructor(logger?: ILogger) {\n this.logger = logger || new Logger({ appName: 'IpcTransport' });\n }\n\n /**\n * Set custom logger\n * 设置自定义日志实例\n * @param logger - Logger instance\n */\n public setLogger(logger: ILogger): void {\n this.logger = logger;\n }\n\n /**\n * 注册监听事件 (ipcMain.on)\n * @param channel - 事件名称\n * @param cb - 回调函数\n */\n public on(channel: string, cb: IPCEventHandler = emptyFunc): void {\n // 包装回调函数以添加日志和错误处理\n const wrappedCb = async (event: IpcMainEvent, ...args: unknown[]) => {\n try {\n this.logEvent(channel, 'on', args);\n await cb(event, ...args);\n } catch (error) {\n this.logError(channel, 'on', error);\n // 尝试回传错误给发送者\n if (!event.sender.isDestroyed()) {\n event.sender.send(`${channel}:error`, this.serializeError(error));\n }\n }\n };\n\n // 存储回调引用\n if (!this.channels.has(channel)) {\n this.channels.set(channel, new Map());\n }\n this.channels.get(channel)!.set(cb, wrappedCb);\n\n ipcMain.on(channel, wrappedCb);\n }\n\n /**\n * 注册处理事件 (ipcMain.handle)\n * 注意: 同一个 channel 只能注册一个 handler,重复注册会覆盖之前的 handler\n * @param channel - 事件名称\n * @param cb - 回调函数\n */\n public handle(channel: string, cb: IPCHandleHandler = emptyFunc): void {\n // 确保先移除旧的 handler,防止 electron 抛出 \"second handler\" 错误\n if (this.handlers.has(channel)) {\n ipcMain.removeHandler(channel);\n }\n this.handlers.add(channel);\n\n // 包装回调函数以添加日志和错误处理\n const wrappedCb = async (\n event: IpcMainInvokeEvent,\n ...args: unknown[]\n ): Promise<IpcResponse> => {\n try {\n this.logEvent(channel, 'handle', args);\n const result = await cb(event, ...args);\n\n // Wrap result in standard response\n // 将结果包装在标准响应中\n return {\n code: 0,\n message: 'success',\n data: result,\n };\n } catch (error) {\n this.logError(channel, 'handle', error);\n\n // Enhanced error handling with StandardError support\n // 增强的错误处理,支持 StandardError\n const isDevelopment = process.env.NODE_ENV === 'development';\n\n // Check if it's a StandardError\n if (error && typeof error === 'object' && 'code' in error && 'category' in error) {\n return {\n code: (error as any).code,\n message: (error as any).message,\n data: null,\n category: (error as any).category,\n details: (error as any).details,\n stack: isDevelopment ? (error as any).stack : undefined,\n };\n }\n\n // Return standard error response for regular errors\n // 为常规错误返回标准错误响应\n return {\n code: (error as any).code || 500,\n message: error instanceof Error ? error.message : String(error),\n data: null,\n stack: isDevelopment && error instanceof Error ? error.stack : undefined,\n };\n }\n };\n\n ipcMain.handle(channel, wrappedCb);\n }\n\n /**\n * 移除指定频道的监听器\n * @param channel - 频道名称\n * @param cb - 可选,指定要移除的回调函数。如果不传,则移除该频道下所有由 IpcTransport 管理的监听器\n */\n public removeListener(channel: string, cb?: IPCEventHandler): void {\n const channelListeners = this.channels.get(channel);\n if (!channelListeners) return;\n\n if (cb) {\n // 移除特定回调\n const wrappedCb = channelListeners.get(cb);\n if (wrappedCb) {\n ipcMain.removeListener(channel, wrappedCb);\n channelListeners.delete(cb);\n }\n } else {\n // 移除该频道下所有由本实例管理的监听器\n for (const wrappedCb of channelListeners.values()) {\n ipcMain.removeListener(channel, wrappedCb);\n }\n channelListeners.clear();\n }\n\n if (channelListeners.size === 0) {\n this.channels.delete(channel);\n }\n }\n\n /**\n * 移除所有监听器\n * @param channel - 可选,指定频道名称\n */\n public removeAllListeners(channel?: string): void {\n if (channel) {\n this.removeListener(channel);\n } else {\n for (const ch of this.channels.keys()) {\n this.removeListener(ch);\n }\n this.channels.clear();\n }\n }\n\n /**\n * 移除处理器\n * @param channel - 频道名称\n */\n public removeHandler(channel: string): void {\n if (this.handlers.has(channel)) {\n ipcMain.removeHandler(channel);\n this.handlers.delete(channel);\n }\n }\n\n /**\n * 移除所有处理器\n */\n public removeAllHandlers(): void {\n for (const channel of this.handlers) {\n ipcMain.removeHandler(channel);\n }\n this.handlers.clear();\n }\n\n /**\n * 记录错误信息\n * @param err - 错误信息\n */\n public error(err: string): void {\n this.logger.error(`[IPC System Error]: ${err}`);\n }\n\n /**\n * 记录普通日志\n * @param data - 日志信息\n */\n public log(data: string): void {\n this.logger.info(`[IPC System Log]: ${data}`);\n }\n\n // 私有辅助方法:格式化日志\n private logEvent(channel: string, type: 'on' | 'handle', args: unknown[]): void {\n try {\n // 尝试获取 data.name 作为操作名,这是我们约定的通信格式\n const actionName = (args[0] as { name?: string })?.name;\n const argStr = actionName ? `[Action: ${actionName}]` : `[Args: ${this.safeStringify(args)}]`;\n this.logger.info(`[${type.toUpperCase()}] ${channel} ${argStr}`);\n } catch {\n this.logger.info(`[${type.toUpperCase()}] ${channel} [Args parsing failed]`);\n }\n }\n\n private logError(channel: string, type: 'on' | 'handle', error: unknown): void {\n const errorMsg = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : '';\n this.logger.error(`[${type.toUpperCase()} ERROR] ${channel}: ${errorMsg}`, errorStack);\n }\n\n private serializeError(error: unknown): Record<string, unknown> {\n if (error instanceof Error) {\n // 获取所有属性,包括不可枚举的\n const serialized: Record<string, unknown> = {\n name: error.name,\n message: error.message,\n stack: error.stack,\n };\n\n // 复制其他自定义属性 (如 code, issues 等)\n for (const key of Object.getOwnPropertyNames(error)) {\n if (!['name', 'message', 'stack'].includes(key)) {\n serialized[key] = (error as any)[key];\n }\n }\n return serialized;\n }\n\n if (typeof error === 'object' && error !== null) {\n return error as Record<string, unknown>;\n }\n\n return {\n message: String(error),\n name: 'UnknownError',\n };\n }\n\n private safeStringify(obj: unknown): string {\n try {\n return JSON.stringify(obj);\n } catch {\n return '[Circular or Non-serializable]';\n }\n }\n}\n"],"names":["Logger","ipcMain"],"mappings":"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"}
|