moonbridge-ts 0.5.0 → 0.6.0

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 (53) hide show
  1. package/README.md +237 -229
  2. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.d.ts +5 -4
  3. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.d.ts.map +1 -1
  4. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.js +44 -9
  5. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.js.map +1 -1
  6. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.mjs +44 -9
  7. package/dist/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.mjs.map +1 -1
  8. package/dist/moonbridge-ipc/client/moonbridge_ipc_client.d.ts +7 -2
  9. package/dist/moonbridge-ipc/client/moonbridge_ipc_client.d.ts.map +1 -1
  10. package/dist/moonbridge-ipc/client/moonbridge_ipc_client.js.map +1 -1
  11. package/dist/moonbridge-ipc/client/moonbridge_ipc_client.mjs.map +1 -1
  12. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.d.ts +7 -0
  13. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.d.ts.map +1 -0
  14. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.js +78 -0
  15. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.js.map +1 -0
  16. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.mjs +76 -0
  17. package/dist/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.mjs.map +1 -0
  18. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.d.ts +55 -0
  19. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.d.ts.map +1 -0
  20. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.js +71 -0
  21. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.js.map +1 -0
  22. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.mjs +65 -0
  23. package/dist/moonbridge-ipc/client/rpc/rpc_annotation.mjs.map +1 -0
  24. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.d.ts +57 -0
  25. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.d.ts.map +1 -0
  26. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.js +16 -0
  27. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.js.map +1 -0
  28. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.mjs +14 -0
  29. package/dist/moonbridge-ipc/client/rpc/rpc_service_factory.mjs.map +1 -0
  30. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.d.ts +14 -0
  31. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.d.ts.map +1 -0
  32. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.js +27 -0
  33. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.js.map +1 -0
  34. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.mjs +25 -0
  35. package/dist/moonbridge-ipc/client/rpc/service/job/ipc_request_job.mjs.map +1 -0
  36. package/dist/moonbridge-ipc/client/types/ipc_messenger.d.ts +30 -14
  37. package/dist/moonbridge-ipc/client/types/ipc_messenger.d.ts.map +1 -1
  38. package/dist/moonbridge-ipc/index.d.ts +3 -0
  39. package/dist/moonbridge-ipc/index.d.ts.map +1 -1
  40. package/dist/moonbridge-ipc/index.js +21 -0
  41. package/dist/moonbridge-ipc/index.mjs +3 -0
  42. package/package.json +2 -2
  43. package/src/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.ts +66 -21
  44. package/src/moonbridge-ipc/client/moonbridge_ipc_client.ts +7 -2
  45. package/src/moonbridge-ipc/client/rpc/internal/rpc_service_proxy.ts +103 -0
  46. package/src/moonbridge-ipc/client/rpc/rpc_annotation.ts +125 -0
  47. package/src/moonbridge-ipc/client/rpc/rpc_service_factory.ts +61 -0
  48. package/src/moonbridge-ipc/client/rpc/service/job/ipc_request_job.ts +33 -0
  49. package/src/moonbridge-ipc/client/types/ipc_messenger.ts +33 -15
  50. package/src/moonbridge-ipc/index.ts +3 -0
  51. package/tests/unit/ipc_messenger.route.test.ts +71 -0
  52. package/tests/unit/rpc_service_factory.test.ts +94 -0
  53. package/tests/unit/rpc_service_proxy.test.ts +145 -0
package/README.md CHANGED
@@ -1,303 +1,311 @@
1
1
  # moonbridge-ts
2
2
 
3
- 基于 MoonBridge 通信协议的 TypeScript IPC 库,面向**仅支持 WebSocket 的环境**(如 WPS 加载项任务窗格、浏览器页面),与 moonbridge-ipc 服务端互通(不限制技术栈),实现稳定、统一 IPC 通信。
3
+ 基于 MoonBridge 通信协议的 TypeScript IPC 库,面向 WebSocket 场景(浏览器、WPS 加载项、Node)。
4
4
 
5
- ---
5
+ ## 1. moonbridge-ts 是什么?
6
6
 
7
- ## 完全一致原则(与 Flutter 端对齐)
7
+ `moonbridge-ts` moonbridge IPC 的 TypeScript 实现,用于在不同进程/应用之间进行消息通信。
8
8
 
9
- 本库以 **moonbridge-ipc-flutter** 的 `lib/` 为**唯一参考**,在以下维度与 Flutter 端保持**完全一致**,便于跨端维护与同一套心智模型:
9
+ 角色模型与 Flutter 版本一致:
10
10
 
11
- - **命名**:类名、方法名、枚举名、文件名、目录名与 Flutter 端一致(仅因语言规范导致的拼写风格可微调)。
12
- - **设计模式**:Flutter 使用的设计模式在 TS 端以相同方式体现;Flutter 用 class 则 TS 用 class,Flutter 用 enum 则 TS 用 enum。
13
- - **公开 API**:对外方法签名、参数语义、返回值约定与 Flutter 端对应抽象一致,使两端调用方式可互换理解。
14
- - **目录与层级**:目录结构、模块划分与 Flutter `lib/` 一致(如 `client/`、`general/encode`、`general/message`、`general/transport`),便于按相同路径在两端定位。
15
- - **平台封装例外**:仅在**平台能力差异**(如 WebSocket 的运行时 API 不同)时,底层实现可不同,但**对外暴露的 API(方法名、参数与语义)须与 Flutter 端抽象完全一致**(如 `TransportClient.connectWithServer()`、`sendData()`、`isClientConnected`、`onErrorAndClose()`)。
16
- - **实施顺序**:先**第一步**完全还原 `lib/general/`(encode、message、transport、config、error、lock、statistics、utils、app_launch),再**第二步**对齐 client/、extension/ 及根入口 index.ts。
11
+ 1. 客户端:发送请求、接收请求、处理回调、发布/订阅事件。
12
+ 2. 服务端:负责客户端注册、消息转发、会话建立、唤醒目标客户端。
17
13
 
18
- 详见仓库内 `specs/001-moonbridge-js-full-1to1/` 下的规格与契约。
14
+ 当前 TS 版本传输层仅提供 WebSocket 通道(`ws://`)。
19
15
 
20
- ---
16
+ 角色环境限制:
21
17
 
22
- ## 1. 是什么?
18
+ 1. `server` 角色需要监听端口,浏览器环境受限,`MoonBridgeIpcServer` 只能在 Node.js 环境使用。
19
+ 2. `client` 角色不需要监听端口,`MoonBridgeIpcClient` 可在 Node.js 和浏览器环境使用。
23
20
 
24
- **适用场景**:moonbridge-ts 面向**仅支持 WebSocket 的环境**(WPS 加载项任务窗格、浏览器页面),无法使用 Node Socket。与 Flutter 端差异:JS 无 Dart 反射、无 build_runner,模块通过 `@MoonBridgeModule` / `@MoonBridgeMethod` 装饰器在**运行时**注册到 MoonBridgeRegistry。
25
-
26
- moonbridge-ts 是 **MoonBridge IPC 在 TypeScript 侧的客户端与服务端实现**,与 Flutter 端「客户端 / 服务端」角色模型一致:
27
-
28
- - **客户端**:负责消息的发送与接收(本库实现**客户端**角色)。
29
- - **服务端**:由 NPC 侧 moonbridge-ipc-flutter 承担,负责消息的中转与分发(本库同时提供 **MoonBridgeIpcServer** 用于服务端场景)。
21
+ ## 2. 当前提供的能力
30
22
 
31
- 可以类比为:每个"微信用户"是客户端,既能发消息也能收消息;微信服务器负责中转。本库相当于在 WPS 或浏览器里运行的"微信客户端",通过 WebSocket 连接 NPC 的 MoonBridge IPC 服务端;同时也提供"微信服务器"能力供 NPC 端使用。
23
+ 1. 支持单应用/多应用跨进程通信(经 IPC 服务端转发)。
24
+ 2. 支持 Request/Response/Error 三类消息与回调链路。
25
+ 3. 支持消息拦截(`MessageInterceptor`)。
26
+ 4. 支持连接状态监听(`ConnectionObserver`)。
27
+ 5. 支持心跳保活(默认开启,默认 3000ms)。
28
+ 6. 支持客户端身份认证(服务端白名单 `ClientIdentityProvider`)。
29
+ 7. 支持自动唤醒目标应用(`autoLaunch` + `AppLauncher`)。
30
+ 8. 支持 1 对 1 指定客户端通信。
31
+ 9. 支持 EventBus 广播通信。
32
+ 10. 支持端口候选策略(`PortCandidateRule`,服务端按规则尝试绑定端口,客户端按规则尝试连接端口)。
33
+ 11. 支持 WPS 场景 deeplink 唤醒(`WpsAppLauncher`)。
32
34
 
33
- ---
35
+ ### 2.1 `PortCandidateRule` 作用说明
34
36
 
35
- ## 2. 当前提供的能力
37
+ `PortCandidateRule` 用于在端口不确定或端口可能被占用时,给 server/client 提供一致的端口尝试规则:
36
38
 
37
- ### 2.1 客户端能力(MoonBridgeIpcClient)
39
+ 1. 服务端启动时,如果初始端口被占用,会按 `PortCandidateRule` 生成的有序端口列表继续尝试绑定,直到某个端口启动成功,或所有候选端口尝试完毕后启动失败。
40
+ 2. 客户端连接时,会按同一规则生成的有序端口列表依次尝试连接;每个端口都会执行连接和握手校验,直到连接并握手成功,或所有候选端口尝试完毕后连接失败。
41
+ 3. 该机制可避免“固定端口冲突导致整体不可用”,并确保 server 与 client 共享相同的端口探索顺序。
38
42
 
39
- - 基于 **WebSocket(ws)** 的传输层,与 Flutter 端 WebSocket 接入语义一致;wss 预留。
40
- - **握手与协议**:连接建立后发送 Handshake,校验对端为 MoonBridge IPC 服务后再进入会话。
41
- - **连接管理**:连接状态机(disconnected / connecting / connected / disconnecting)、有限次数重试与固定间隔(与 Flutter IpcConnectionManager 对齐)。
42
- - **发送请求并接收响应**:`messenger.postMessage(target, { args: [..., callback] })`,将回调作为 args 末位传入,服务端响应时调用 callback。
43
- - **接收对端请求**:`registerHandler(moduleName, methodName, handler)` 注册本地方法;对端发送 TYPE_NAME_REQUEST 时派发到 handler,参数中 callbackId 替换为 ResultCallback,业务调用 `callback.invoke(result)` 回写 TYPE_NAME_RESPONSE;未注册则回写 TYPE_NAME_ERROR。协议与 [contracts](../specs/001-moonbridge-js-receive-extensions/contracts/message-formats.md) 一致(仓库内路径)。
44
- - **心跳保活**:连接建立后按 `heartbeatIntervalMs`(默认 30s)发送 TYPE_NAME_PING;可配置 `heartbeatEnabled`、`heartbeatIntervalMs`。
45
- - **EventBus**:`client.getEventBus().register(eventName, callback)` 订阅,`client.postEvent(type, source?, data?)` 发布;收到 TYPE_NAME_EVENT 时按事件名派发。
46
- - **可配置**:serverAddress、serverPort、path、clientName、heartbeatIntervalMs、heartbeatEnabled 等,与 Flutter 端配置概念一致。
43
+ ## 3. API 设计概览
47
44
 
48
- ### 2.2 服务端能力(MoonBridgeIpcServer)
45
+ ### 客户端(`MoonBridgeIpcClient`)
49
46
 
50
- - 基于 **WebSocket(ws)** 的服务端接收与分发。
51
- - **客户端身份管理**:支持客户端身份认证(ClientIdentity),记录连接客户端信息。
52
- - **消息派发**:根据 clientName、moduleName、methodName 派发到注册的 handler。
53
- - **响应回写**:支持同步响应和异步响应(通过 ResultCallback)。
54
- - **EventBus 事件分发**:收到 TYPE_NAME_EVENT 时向订阅者广播。
47
+ - `MoonBridgeIpcClient.builder()`
48
+ - `connect(onResult?)`
49
+ - `disconnect()`
50
+ - `isConnected()`
51
+ - `messenger.call(target).args(...).onError(...).strategy(...).send()`
52
+ - `rpcServiceFactory.createService(ServiceType, clientName?)`
53
+ - `eventBus.register(subscriber)`
54
+ - `eventBus.unregister(subscriber)`
55
+ - `eventBus.post(event)`
55
56
 
56
- ### 2.3 模块化能力(@MoonBridgeModule / @MoonBridgeMethod)
57
+ ### 服务端(`MoonBridgeIpcServer`)
57
58
 
58
- - 通过装饰器注册模块和方法,运行时自动注册到 MoonBridgeRegistry。
59
- - 支持 `BridgeModule` 基类,提供与 Flutter 端一致的模块抽象。
60
- - 支持方法拦截、日志等横切关注点。
59
+ - `MoonBridgeIpcServer.builder()`
60
+ - `start(): Promise<boolean>`
61
+ - `stop(): Promise<void>`
62
+ - `clientIdentityProviders([...])`
63
+ - `messagePreprocessor(...)`
64
+ - `onMessageReceived(...)`
65
+ - `wakeAppInterceptor(...)`
61
66
 
62
- ### 2.4 WPS 应用启动能力(WpsAppLauncher)
67
+ ### 传输层(与 Flutter 抽象保持一致)
63
68
 
64
- - 支持通过 AppLaunchIdentifier 启动 WPS 应用。
65
- - 支持应用安装路径查询和类型转换。
69
+ `TransportClient` 统一接口:
66
70
 
67
- ---
71
+ - `connectWithServer()`
72
+ - `sendData(data)`
73
+ - `onMessage(cb)`
74
+ - `onErrorAndClose({ onError, onServerClose })`
75
+ - `close()`
76
+ - `isClientConnected`
68
77
 
69
- ## 3. 架构与分层(与 Flutter lib/ 一一对应)
78
+ ## 4. 接入流程与示例
70
79
 
71
- moonbridge-ipc-flutter 保持**一致的分层与目录**,便于按相同路径在两端定位:
80
+ ### 4.1 安装
72
81
 
73
- ```
74
- ┌──────────────────────────────────────────────────────────────────────────┐
75
- │ moonbridge/ 核心模块层 │
76
- │ ├── kernel/ Bridge、BridgeModule 核心抽象 │
77
- │ ├── annotation/ @MoonBridgeModule、@MoonBridgeMethod 装饰器 │
78
- │ └── logger/ 日志抽象 │
79
- ├──────────────────────────────────────────────────────────────────────────┤
80
- │ moonbridge-ipc/ IPC 通信层 │
81
- │ ├── client/ IPC 客户端(MoonBridgeIpcClient) │
82
- │ │ ├── internal/ 内部实现(连接管理、桥接、执行器等) │
83
- │ │ └── types/ 客户端类型定义 │
84
- │ ├── server/ IPC 服务端(MoonBridgeIpcServer) │
85
- │ │ └── credential/ 客户端身份认证 │
86
- │ ├── general/ 通用层(与 Flutter lib/general 对应) │
87
- │ │ ├── encode/ IpcMessageEncoder 消息编码 │
88
- │ │ ├── message/ 消息类型常量、负载类型 │
89
- │ │ └── error/ IpcError 与错误码 │
90
- │ └── extension/ 扩展能力 │
91
- ├──────────────────────────────────────────────────────────────────────────┤
92
- │ wps-launcher/ WPS 应用启动层 │
93
- │ └── launcher/ WpsAppLauncher 实现 │
94
- └──────────────────────────────────────────────────────────────────────────┘
82
+ ```bash
83
+ npm install moonbridge-ts
95
84
  ```
96
85
 
97
- - **moonbridge/**:对应 Flutter 端核心抽象,提供 Bridge、BridgeModule、装饰器等。
98
- - **moonbridge-ipc/client**:对应 Flutter `lib/client/`,对外暴露 `MoonBridgeIpcClient`。
99
- - **moonbridge-ipc/server**:对应 Flutter 服务端实现,对外暴露 `MoonBridgeIpcServer`。
100
- - **moonbridge-ipc/general**:对应 Flutter `lib/general/`,协议常量与编解码。
101
- - **wps-launcher/**:对应 Flutter `lib/app_launch/`,WPS 应用启动能力。
102
-
103
- ---
104
-
105
- ## 4. 目录结构
106
-
107
- ```text
108
- moonbridge-ts/
109
- ├── src/
110
- │ ├── moonbridge/ # 核心模块层
111
- │ │ ├── kernel/
112
- │ │ │ ├── bridge.ts # Bridge 抽象
113
- │ │ │ ├── bridge_module.ts # BridgeModule 基类
114
- │ │ │ ├── result_callback.ts # 结果回调
115
- │ │ │ └── executor.ts # 执行器
116
- │ │ ├── annotation/
117
- │ │ │ ├── decorators.ts # @MoonBridgeModule、@MoonBridgeMethod
118
- │ │ │ └── registry.ts # MoonBridgeRegistry
119
- │ │ ├── message/ # 消息解析
120
- │ │ ├── module/ # 模块创建与方法调用
121
- │ │ ├── logger/
122
- │ │ │ └── logger.ts # 日志抽象
123
- │ │ └── index.ts # 对外导出
124
- │ ├── moonbridge-ipc/ # IPC 通信层
125
- │ │ ├── client/
126
- │ │ │ ├── moonbridge_ipc_client.ts # 客户端入口
127
- │ │ │ ├── internal/ # 内部实现
128
- │ │ │ │ ├── bridge/ # 桥接与执行
129
- │ │ │ │ ├── ipc/ # IPC 核心
130
- │ │ │ │ └── settings/ # 配置
131
- │ │ │ └── types/ # 类型定义
132
- │ │ ├── server/
133
- │ │ │ ├── moonbridge_ipc_server.ts # 服务端入口
134
- │ │ │ ├── credential/ # 客户端身份
135
- │ │ │ └── internal/ # 内部实现
136
- │ │ ├── general/
137
- │ │ │ ├── encode/ # 消息编码
138
- │ │ │ ├── message/ # 消息类型
139
- │ │ │ └── error/ # 错误定义
140
- │ │ ├── extension/ # 扩展
141
- │ │ └── index.ts # 对外导出
142
- │ ├── wps-launcher/ # WPS 应用启动
143
- │ │ ├── launcher/
144
- │ │ │ └── wps_app_launcher.ts
145
- │ │ └── index.ts # 对外导出
146
- │ └── index.ts # 根入口
147
- ├── tests/
148
- │ ├── unit/
149
- │ └── integration/
150
- ├── docs/
151
- │ ├── ROADMAP.md
152
- │ ├── REFACTOR_SCOPE.md
153
- │ └── STRUCTURE.md
154
- ├── DEPENDENCIES.md
155
- ├── package.json
156
- └── README.md
157
- ```
86
+ ### 4.2 初始化服务端(Node)
87
+
88
+ ```ts
89
+ import {
90
+ MoonBridgeIpcServer,
91
+ WebSocketServerEndpoint,
92
+ ClientIdentity,
93
+ } from 'moonbridge-ts';
158
94
 
159
- ---
95
+ const endpoint = new WebSocketServerEndpoint({
96
+ address: '0.0.0.0',
97
+ port: 9091,
98
+ path: '/ws',
99
+ useTls: false,
100
+ });
160
101
 
161
- ## 5. 使用示例
102
+ const getClientIdentity = (clientName: string) => {
103
+ switch (clientName) {
104
+ case 'client_a':
105
+ return new ClientIdentity('client_a');
106
+ case 'client_b':
107
+ return new ClientIdentity('client_b');
108
+ default:
109
+ return undefined;
110
+ }
111
+ };
162
112
 
163
- ### 5.1 安装
113
+ const server = MoonBridgeIpcServer.builder()
114
+ .serverName('moonbridge_server')
115
+ .useWebSocketChannel(endpoint)
116
+ .clientIdentityProviders([getClientIdentity])
117
+ .build(true);
164
118
 
165
- ```bash
166
- npm install moonbridge-ts
167
- # 或本地引用
168
- # "moonbridge-ts": "path:../moonbridge-ts"
119
+ const started = await server.start();
120
+ if (!started) {
121
+ throw new Error('IPC server start failed');
122
+ }
169
123
  ```
170
124
 
171
- ### 5.2 客户端初始化与连接
125
+ ### 4.3 初始化客户端
172
126
 
173
- ```typescript
127
+ ```ts
174
128
  import {
175
- MoonBridgeIpcClientBuilder,
129
+ MoonBridgeIpcClient,
176
130
  WebSocketServerEndpoint,
131
+ IpcMessageStrategy,
177
132
  } from 'moonbridge-ts';
178
133
 
179
- const client = MoonBridgeIpcClientBuilder.builder()
134
+ const client = MoonBridgeIpcClient.builder()
180
135
  .clientName('client_a')
181
- .useWebSocketChannel(new WebSocketServerEndpoint('127.0.0.1', 9100, '/ws'))
136
+ .useWebSocketChannel(
137
+ new WebSocketServerEndpoint({
138
+ address: '127.0.0.1',
139
+ port: 9091,
140
+ path: '/ws',
141
+ useTls: false,
142
+ }),
143
+ )
144
+ .messageStrategy(new IpcMessageStrategy(1, true))
182
145
  .build(true);
183
146
 
184
- client.connect((success, error) => {
185
- if (success) console.log('连接成功');
186
- else console.error('连接失败', error);
147
+ client.connect((isConnected, error) => {
148
+ if (isConnected) {
149
+ console.log('connect success');
150
+ return;
151
+ }
152
+ console.error('connect failed', error);
187
153
  });
188
154
  ```
189
155
 
190
- ### 5.3 发送消息
191
-
192
- ```typescript
193
- // 极简调用:仅传核心定位 + 参数
194
- client.messenger.postMessage(
195
- { clientName: 'client_b', moduleName: 'Printer', methodName: 'print' },
196
- ['hello']
197
- );
198
-
199
- // 完整调用:传定位 + 全量配置(含 args、strategy、onError)
200
- client.messenger.postMessage(
201
- { clientName: 'npc', moduleName: 'explainPage', methodName: 'call' },
202
- {
203
- args: [{ slide: 1, docPath: '/path/to.pptx' }, (res) => console.log(res)],
204
- onError: (err) => console.error(err),
156
+ ### 4.4 客户端接收消息(模块方式)
157
+
158
+ ```ts
159
+ import {
160
+ Bridge,
161
+ BridgeModule,
162
+ MoonBridgeMethod,
163
+ MoonBridgeModule,
164
+ ResultCallback,
165
+ } from 'moonbridge-ts';
166
+
167
+ @MoonBridgeModule('CallPhone')
168
+ export class CallModule extends BridgeModule {
169
+ constructor(bridge: Bridge) {
170
+ super(bridge);
205
171
  }
206
- );
207
- ```
208
172
 
209
- ### 5.4 模块实现(宿主侧)
173
+ @MoonBridgeMethod('callWithCallback')
174
+ callWithCallback(phoneNumber: string, callback: ResultCallback): void {
175
+ console.log(`[MoonBridge] call: ${phoneNumber}`);
176
+ callback.invoke(['callback - Success']);
177
+ }
178
+ }
179
+ ```
210
180
 
211
- ```typescript
212
- import { BridgeModule } from 'moonbridge-ts';
213
- import { Bridge } from 'moonbridge-ts';
214
- import { MoonBridgeModule, MoonBridgeMethod } from 'moonbridge-ts';
181
+ `tsconfig.json` 需开启:
215
182
 
216
- @MoonBridgeModule('Printer')
217
- class PrintModule extends BridgeModule {
218
- constructor(bridge: Bridge) { super(bridge); }
219
- @MoonBridgeMethod('print')
220
- printMessage(msg: string) { console.log('[MoonBridge] print', msg); }
183
+ ```json
184
+ {
185
+ "experimentalDecorators": true,
186
+ "emitDecoratorMetadata": true,
187
+ "useDefineForClassFields": false
221
188
  }
222
189
  ```
223
190
 
224
- **装饰器配置**(tsconfig.json):`"experimentalDecorators": true`,必要时 `"useDefineForClassFields": false`。
191
+ ### 4.5 客户端发送消息
225
192
 
226
- ### 5.5 服务端示例
193
+ ```ts
194
+ // 方式:call(推荐)
195
+ client.messenger
196
+ .call({ clientName: 'client_b', moduleName: 'CallPhone', methodName: 'callWithCallback' })
197
+ .args('0431-4610123', (response) => console.log('response:', response))
198
+ .onError((error) => console.error('ipc error:', error))
199
+ .send();
200
+ ```
227
201
 
228
- ```typescript
229
- import { MoonBridgeIpcServerBuilder, WebSocketServerEndpoint } from 'moonbridge-ts';
202
+ ### 4.6 EventBus(订阅与发布)
230
203
 
231
- const server = MoonBridgeIpcServerBuilder.builder()
232
- .serverName('moonbridge_server')
233
- .useWebSocketChannel(new WebSocketServerEndpoint('0.0.0.0', 9100, '/ws'))
234
- .build();
204
+ ```ts
205
+ import { Subscriber } from 'moonbridge-ts';
206
+ import { Event } from 'moonbridge-ts/moonbridge-ipc/general/message/event';
235
207
 
236
- server.start((success, error) => {
237
- if (success) console.log('服务端启动成功');
238
- else console.error('服务端启动失败', error);
208
+ const subscriber = new Subscriber('TestEvent', (event) => {
209
+ console.log('event:', event.type, event.data);
239
210
  });
240
- ```
241
211
 
242
- ### 5.6 在 WPS 加载项中集成
212
+ client.eventBus.register(subscriber);
213
+ await client.eventBus.post(new Event('TestEvent', 'client_a', { key: 'hello' }));
214
+ ```
243
215
 
244
- 1. 构建本库:`npm install && npm run build`,得到 `dist/`(含 CJS、ESM、IIFE)。
245
- 2. 在任务窗格页面中引入 IIFE:`<script src="path/to/index.global.js"></script>`,会暴露 `window.MoonbridgeJS`(含 `MoonBridgeIpcClientBuilder`、`WebSocketServerEndpoint` 等)。
246
- 3. 使用仓库内 `wps-addin/src/ipc/moonbridge/client.js` 提供的 `createNpcClient()`,内部会读取 `getConfig()` 的 npcWsUrl/npcWsPort 并组装 WebSocket 通道。
247
- 4. 端口与地址需按环境配置(见 `window.getConfig()` 或 `__NPC_LINK_CONFIG__`),避免误用固定配置。
248
- 5. 为「连接」「讲解当前页」「发送消息」等按钮绑定 `createNpcClient().connect()`、`client.messenger.postMessage(...)` 即可。
216
+ ### 4.7 WPS 场景唤醒(可选)
249
217
 
250
- 详见仓库根目录下 `specs/005-moonbridge-js-ipc/quickstart.md`。
218
+ ```ts
219
+ import {
220
+ MoonBridgeIpcClient,
221
+ WebSocketServerEndpoint,
222
+ WpsAppLauncher,
223
+ } from 'moonbridge-ts';
251
224
 
252
- ---
225
+ const client = MoonBridgeIpcClient.builder()
226
+ .clientName('client_a')
227
+ .useWebSocketChannel(
228
+ new WebSocketServerEndpoint({
229
+ address: '127.0.0.1',
230
+ port: 9091,
231
+ path: '/ws',
232
+ useTls: false,
233
+ }),
234
+ )
235
+ .appLauncher(
236
+ new WpsAppLauncher({
237
+ appUrl: 'server://',
238
+ fallbackMethod: 'linkClick',
239
+ }),
240
+ )
241
+ .build();
242
+ ```
253
243
 
254
- ## 6. moonbridge-ipc-flutter 的对应关系
244
+ ### 4.8 RPC 风格调用(装饰器 + rpcServiceFactory)
255
245
 
256
- | Flutter 端 | moonbridge-ts |
257
- | --------------------------------- | ---------------------------------- |
258
- | MoonBridgeIpcClient | MoonBridgeIpcClient |
259
- | MoonBridgeIpcServer | MoonBridgeIpcServer |
260
- | IpcConnectionManager | IpcConnectionManager |
261
- | TransportClient / WebSocketClient | ITransportClient / WebSocketClient |
262
- | Handshake、Request/Response 协议 | general/encode、general/message |
263
- | 连接重试、握手超时 | connection_manager + retry_policy |
264
- | ClientIdentity | ClientIdentity |
265
- | ResultCallback | ResultCallback |
246
+ ```ts
247
+ import {
248
+ IpcCallRetry,
249
+ IpcRemoteCall,
250
+ IpcRemoteClient,
251
+ IpcRequestJob,
252
+ MoonBridgeIpcClient,
253
+ } from 'moonbridge-ts';
266
254
 
267
- 报文格式与 Flutter 端对齐,详见 **docs/ROADMAP.md** 与特性契约 `specs/001-moonbridge-js-receive-extensions/contracts/message-formats.md`。客户端身份与动态端口为可选扩展,见 ROADMAP。
255
+ @IpcRemoteClient({ name: 'client_b' })
256
+ abstract class CallPhoneService {
257
+ @IpcCallRetry({ retries: 3 })
258
+ @IpcRemoteCall({ module: 'CallPhone', method: 'callPhone' })
259
+ callPhone(_number: string): IpcRequestJob {
260
+ return IpcRequestJob.stub();
261
+ }
268
262
 
269
- ---
263
+ @IpcRemoteCall({ module: 'CallPhone', method: 'callWithCallback' })
264
+ callPhoneWithCallback(_number: string, _onResponse: (response: unknown[]) => void): IpcRequestJob {
265
+ return IpcRequestJob.stub();
266
+ }
267
+ }
270
268
 
271
- ## 7. 开发与测试
269
+ const client = MoonBridgeIpcClient.builder()
270
+ .clientName('client_a')
271
+ // ...省略 useWebSocketChannel(...)
272
+ .build(true);
272
273
 
273
- ```bash
274
- npm install
275
- npm run build # 产出 dist/
276
- npm run test # 单元测试(Vitest)
277
- npm run lint # ESLint
278
- npm run format # Prettier
279
- ```
274
+ const service = client.rpcServiceFactory.createService(CallPhoneService);
280
275
 
281
- ---
276
+ service?.callPhone('11111').onIpcError((error) => {
277
+ console.error('IPC error:', error);
278
+ }).send();
282
279
 
283
- ## 8. 注意事项
280
+ service?.callPhoneWithCallback('176****0000', (response) => {
281
+ console.log('response:', response);
282
+ }).onIpcError((error) => {
283
+ console.error('IPC error:', error);
284
+ }).send();
285
+ ```
284
286
 
285
- - 仅使用 **ws**,未实现 wss;与当前 Flutter 端保持一致。
286
- - 客户端身份与鉴权与 Flutter 端一致:基于 clientName 及可选的 ClientIdentity,无 Token/Cookie。
287
- - 本库**实现客户端和服务端**,客户端连接 NPC(moonbridge-ipc-flutter),服务端可供 NPC 或其他客户端连接。
287
+ ## 5. Flutter README 的对齐点
288
288
 
289
- ---
289
+ 1. 角色模型一致:客户端负责收发,服务端负责转发与会话构建。
290
+ 2. Builder 使用方式一致:链式配置后 `build(...)`。
291
+ 3. 协议语义一致:握手、注册、请求、响应、错误、心跳、事件。
292
+ 4. 模块能力一致:`@MoonBridgeModule` + `@MoonBridgeMethod`。
293
+ 5. 客户端身份机制一致:服务端白名单控制可接入客户端。
290
294
 
291
- ## 9. 规范与约定(贡献与维护)
295
+ ## 6. 重要差异与注意事项
292
296
 
293
- **本项目不做向后兼容,只保留最新方案。** 方案升级或更新时,不保留废弃实现、无需考虑向后兼容,仅保留最新实现,以避免历史兼容逻辑堆积、降低维护成本。
297
+ 1. `MoonBridgeIpcServer` 只能在 Node.js 环境使用(浏览器无法监听端口)。
298
+ 2. `MoonBridgeIpcClient` 可在 Node.js 和浏览器环境使用(仅需主动连接,不需监听端口)。
299
+ 3. TS 端当前只支持 WebSocket,不支持 TCP Socket 客户端。
300
+ 4. `useTls: true`(`wss`)当前未实现,需使用 `ws`。
301
+ 5. 服务端如果不配置 `clientIdentityProviders`,客户端会因白名单校验失败而无法完成注册。
302
+ 6. 模块通过装饰器运行时注册,模块文件必须被加载(import)后才能生效。
303
+ 7. RPC 服务代理依赖装饰器元数据:服务类型需使用 `@IpcRemoteClient` 和 `@IpcRemoteCall` 标注后再通过 `client.rpcServiceFactory.createService(...)` 创建。
294
304
 
295
- moonbridge-ts moonbridge-ipc-flutter 采用**一比一翻译**原则:命名、目录层级、对外 API 语义尽量一致;仅在平台能力差异(如 WebSocket 底层 API)时内部实现可不同,**对外暴露的 API 须与 Flutter 端抽象一致**。
305
+ ## 7. 开发命令
296
306
 
297
- - **与 Flutter 的详细对应**:见 [docs/STRUCTURE.md](docs/STRUCTURE.md)。
298
- - **单文件结构约定**(分区、`// IMPORTS`、`// CLASS: Xxx` 等):见 [specs/001-moonbridge-js-refactor/contracts/file-structure.md](../specs/001-moonbridge-js-refactor/contracts/file-structure.md)。
299
- - **注释约定**(文件头、JSDoc、与 Flutter 对应注明):见 [specs/001-moonbridge-js-refactor/contracts/comment-convention.md](../specs/001-moonbridge-js-refactor/contracts/comment-convention.md)。
300
- - **Flutter–JS 一比一对应约定**:见 [specs/001-moonbridge-js-refactor/contracts/flutter-js-1-to-1.md](../specs/001-moonbridge-js-refactor/contracts/flutter-js-1-to-1.md)。
301
- - **禁止顶层业务函数**:业务逻辑应封装在 class/interface 中;client/ 与 transport/ 不新增无归属的顶层函数(工厂等使用类静态方法,如 `ClientConfig.create`、`ResultCallback.create`、`RpcProxy.createService`)。协议层编解码过渡期可保留顶层函数,须在注释中标明与 Flutter 对应。
302
- - **查阅 specs 与 contracts**:仓库内 `specs/001-moonbridge-js-refactor/` 含本改造的 spec、plan、tasks、contracts;`contracts/` 下为单文件结构、注释、Flutter–JS 一比一约定。
303
- - **规范豁免**:自动生成代码(如未来 RPC 生成器产物)、对第三方 API 的极薄 wrapper 可豁免完整注释与分区规范,仅需文件头与对外入口简短说明;见 research.md 与 spec Edge Cases。
307
+ ```bash
308
+ npm run build
309
+ npm run test
310
+ npm run lint
311
+ ```
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * MoonBridge IPC 客户端实际实现与注册表,对应 Flutter lib/client/internal/moonbridge_ipc_client.internal.dart。
3
- * JS 端不实现 RPC(getService 恒返回 undefined)。
4
3
  */
5
4
  import { IpcClientSettings } from './settings/ipc_client_settings';
6
5
  import { IpcConnectionCompletionHandler } from '../types/ipc_types';
7
6
  import { MoonBridgeIpcClient } from '../moonbridge_ipc_client';
8
- import { Messenger, MessageEndpoint, MessageCallOptions } from '../types/ipc_messenger';
7
+ import { Messenger, MessageEndpoint, RoutedMessage } from '../types/ipc_messenger';
9
8
  import { EventBus } from '../types/ipc_event_bus';
10
9
  import { IpcClientComponentProvider } from './ipc/ipc_client_component_provider';
11
10
  import { IpcConnectionManager } from './ipc/connect/ipc_connection_manager';
@@ -14,6 +13,7 @@ import { IpcCommunicationAgent } from './ipc/communication/ipc_communication_age
14
13
  import { IpcEventBus } from './ipc/eventbus/ipc_event_bus';
15
14
  import { IpcConnectionKeeper } from './ipc/keep/ipc_connection_keeper';
16
15
  import { IpcClientBridge } from './bridge/ipc_client_bridge';
16
+ import { RpcServiceFactory } from '../rpc/rpc_service_factory';
17
17
  /**
18
18
  * 实际 IPC 客户端实现:继承组件装配,并实现 MoonBridgeIpcClient、Messenger。
19
19
  * 装配顺序与 Flutter RealMoonBridgeIpcClient 一致;JS 不传入 moduleFactories(见 spec 012)。
@@ -26,6 +26,7 @@ export declare class RealMoonBridgeIpcClient implements IpcClientComponentProvid
26
26
  readonly ipcEventBus: IpcEventBus;
27
27
  readonly connectionKeeper: IpcConnectionKeeper;
28
28
  readonly bridge: IpcClientBridge;
29
+ readonly rpcServiceFactory: RpcServiceFactory;
29
30
  constructor(settings: IpcClientSettings);
30
31
  get clientName(): string;
31
32
  connect(onResult?: IpcConnectionCompletionHandler): void;
@@ -33,8 +34,8 @@ export declare class RealMoonBridgeIpcClient implements IpcClientComponentProvid
33
34
  isConnected(): boolean;
34
35
  get messenger(): Messenger;
35
36
  get eventBus(): EventBus;
36
- postMessage(target: MessageEndpoint, argsOrOptions?: unknown[] | MessageCallOptions): void;
37
- getService<T = unknown>(_clientName?: string): T | undefined;
37
+ call(target: MessageEndpoint): RoutedMessage;
38
+ private sendMessage;
38
39
  private realPostMessage;
39
40
  }
40
41
  //# sourceMappingURL=moonbridge_ipc_client.internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"moonbridge_ipc_client.internal.d.ts","sourceRoot":"","sources":["../../../../src/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAE,8BAA8B,EAAoB,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,0BAA0B,EAAE,mBAAmB,EAAE,SAAS;IACxG,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACnD,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACnD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;IAC/C,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;gBAIrB,QAAQ,EAAE,iBAAiB;IAsBvC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,QAAQ,CAAC,EAAE,8BAA8B,GAAG,IAAI;IAKlD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,WAAW,IAAI,OAAO;IAItB,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,WAAW,CACT,MAAM,EAAE,eAAe,EACvB,aAAa,CAAC,EAAE,OAAO,EAAE,GAAG,kBAAkB,GAC7C,IAAI;IAwBP,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAM5D,OAAO,CAAC,eAAe;CAqCxB"}
1
+ {"version":3,"file":"moonbridge_ipc_client.internal.d.ts","sourceRoot":"","sources":["../../../../src/moonbridge-ipc/client/internal/moonbridge_ipc_client.internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAE,8BAA8B,EAAoB,MAAM,oBAAoB,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAA4B,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAEzF;;;GAGG;AACH,qBAAa,uBAAwB,YAAW,0BAA0B,EAAE,mBAAmB,EAAE,SAAS;IACxG,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACjD,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACnD,QAAQ,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;IACnD,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;IAC/C,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;gBAIlC,QAAQ,EAAE,iBAAiB;IAuBvC,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,OAAO,CAAC,QAAQ,CAAC,EAAE,8BAA8B,GAAG,IAAI;IAKlD,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC,WAAW,IAAI,OAAO;IAItB,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED,IAAI,QAAQ,IAAI,QAAQ,CAEvB;IAED,IAAI,CAAC,MAAM,EAAE,eAAe,GAAG,aAAa;IAgB5C,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,eAAe;CAqCxB"}