@cg-devcenter/rtc-fpnn-webjs-sdk 1.0.0-cg.2 → 1.0.0-cg.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,61 +1,82 @@
1
1
  # @cg-devcenter/rtc-fpnn-webjs-sdk
2
2
 
3
- RTC WebSocket Client SDK。新接入使用 `tlv-v1`;`fpnn` 仅保留浏览器兼容能力。
3
+ RTC WebSocket Client SDK。新接入建议使用 `protocol: 'tlv-v1'`;`fpnn` 用于兼容已有浏览器接入。完整接入说明和 API 参数见 [USAGE.md](docs/USAGE.md)。
4
4
 
5
- ## 模块导出
5
+ ## 安装
6
6
 
7
- - `RTMClient`
8
- - `RTMConfig`
9
- - `RTMProcessor`
10
- - `TLVCodec`
11
- - `TLVWebSocketClient`
7
+ ```bash
8
+ npm install @cg-devcenter/rtc-fpnn-webjs-sdk@1.0.0-cg.3
9
+ ```
12
10
 
13
- ## 客户端构造
11
+ 本文档中的 Promise API、`RTMSharedWorkerClient` 和 Vite 入口从 `1.0.0-cg.3` 起提供;此前发布的 `1.0.0-cg.2` 不包含这些能力。若 `.3` 尚未发布到 npm,可让测试项目安装本地 tarball:`npm install ./cg-devcenter-rtc-fpnn-webjs-sdk-1.0.0-cg.3.tgz`。
14
12
 
15
- `new rtm.RTMClient(options)`
13
+ 浏览器可加载 `dist/rtm.min.js` 并从 `window.rtm` 使用;CommonJS:
16
14
 
17
- | 参数 | 类型 | TLV v1 规则 |
18
- | --- | --- | --- |
19
- | `pid` | `number` | 必填。 |
20
- | `protocol` | `'tlv-v1' \| 'fpnn'` | 新接入为 `'tlv-v1'`。 |
21
- | `tlvEndpoint` | `string` | 必填完整 WebSocket URL。 |
22
- | `autoReconnect` | `boolean` | 缺省为 `true`。 |
23
- | `connectionTimeout` | `number` | 毫秒。 |
24
- | `requestMetadata` | `() => Record<string, unknown>` | 可返回 `trace`、`sent_ms`。 |
25
- | `webSocketFactory` | `(url) => RTMWebSocket` | 无全局 `WebSocket` 时必填。 |
26
- | `locale` | `string` | 映射为 `auth.login.locale`。 |
27
- | `clientVersion` | `string` | 映射为 `auth.login.client_ver`。 |
15
+ ```js
16
+ const rtm = require('@cg-devcenter/rtc-fpnn-webjs-sdk');
17
+ ```
28
18
 
29
- `fpnn` 仅支持浏览器。TLV credential 由业务服务端签发,项目密钥不属于客户端参数。
19
+ Node.js 使用 TLV v1 时,需自行提供 `webSocketFactory(url)`。SDK 不携带 Node WebSocket 实现。`fpnn` 和 `RTMSharedWorkerClient` 仅适用于浏览器。
30
20
 
31
- ## 生命周期 API
21
+ ## Quick Start
32
22
 
33
- | API | 回调/结果 |
34
- | --- | --- |
35
- | `login(uid, credential, callback, timeout)` | `callback(accepted, errorCode)` |
36
- | `bye()` | 发送 `connection.close`。 |
37
- | `close()` | 主动关闭。 |
38
- | `startAutoReconnect()` | 关闭当前连接后重新登录。 |
39
- | `destroy()` | 释放客户端资源。 |
40
- | `getServerTime(timeout, callback)` | `callback(err, data)` |
23
+ 从业务服务端取得当前 UID 的 credential,然后连接 Gate。credential 必须由服务端签发;项目 SecretKey 不要放进浏览器。
41
24
 
42
- `uid`、消息 ID、群 ID、房间 ID 和时间游标超出安全整数范围时使用 `RTMConfig.Int64`。
25
+ ```js
26
+ async function startChat(rtm, { pid, endpoint, uid, peerUid, credential }) {
27
+ const client = new rtm.RTMClient({
28
+ protocol: 'tlv-v1',
29
+ pid,
30
+ tlvEndpoint: endpoint,
31
+ });
32
+ let loggedIn = false;
43
33
 
44
- ## Push API
34
+ client.processor.on(rtm.RTMConfig.TLV_SERVER_PUSH.recvMessage, (event) => {
35
+ console.log('Direct message', event);
36
+ });
45
37
 
46
- 通过 `client.processor.on(name, callback)` 注册:
38
+ try {
39
+ await client.promises.login(uid, credential);
40
+ loggedIn = true;
41
+ return await client.promises.sendChat(peerUid, 'hello', '{}');
42
+ } finally {
43
+ try {
44
+ if (loggedIn) await client.promises.bye(5000);
45
+ } finally {
46
+ client.destroy();
47
+ }
48
+ }
49
+ }
50
+ ```
47
51
 
48
- - `RTMConfig.TLV_SERVER_PUSH.recvMessage`:`event.direct`
49
- - `RTMConfig.TLV_SERVER_PUSH.recvGroupMessage`:`event.group`
50
- - `RTMConfig.TLV_SERVER_PUSH.recvRoomMessage`:`event.room`
51
- - `RTMConfig.TLV_SERVER_PUSH.recvBroadcastMessage`:`event.broadcast`
52
- - `RTMConfig.TLV_SERVER_PUSH.kickOut`:`event.kicked`
53
- - `RTMConfig.TLV_SERVER_PUSH.kickOutRoom`:`event.room_removed`
52
+ 此片段假定调用方已加载 SDK,并取得 `pid`、完整 WebSocket endpoint、`uid`、`peerUid` 和服务端签发的 `credential`。带 credential 获取方式、错误处理、关闭流程、参数和返回值的完整示例见 [SDK 接入指南](docs/USAGE.md#2-快速开始登录收-push发消息关闭)。
54
53
 
55
- 可靠消息 Push 由 SDK 自动 ACK 并按 `message_ref` 去重。
54
+ ## 同 UID 多窗口
56
55
 
57
- ## API 文档
56
+ 需要同一浏览器内多个同源页面共用一个 UID 的 RTC 登录和 WebSocket 时,使用 SDK 的 `RTMSharedWorkerClient`。SDK 默认从主 SDK 脚本旁自动定位 `rtm.shared-worker.js`,业务代码无需维护 `workerUrl`;部署时将两个文件放在同一同源目录即可。首次登录需要 credential;同 UID 后续页面复用共享会话。部署和 Push 路由示例见 [SharedWorker 接入说明](docs/USAGE.md#4-同-uid-多窗口sharedworker)。
58
57
 
59
- - [公开方法与参数](docs/USAGE.md)
60
- - [TLV v1 wire 契约](docs/TLV_CONTRACT.md)
58
+ Vite 项目应从 `@cg-devcenter/rtc-fpnn-webjs-sdk/vite` 导入 ESM 入口,由 SDK 自动打包和配置 Worker 文件;传入 `uid` 可自动生成稳定的 Worker 名称。多账号应用应传 `uid` 或显式 `workerName`,避免多个账号共用默认名称。最后一个页面 detach 后默认 5 秒关闭共享连接。
59
+
60
+ 仓库的演示页面可用以下命令启动:
61
+
62
+ ```bash
63
+ npm run build
64
+ npm run demo:shared-worker
65
+ ```
66
+
67
+ 发送台和收件箱 demo 地址、真实 Gate 配置方式见 [Demo 使用说明](examples/shared-worker-demo/README.md)。
68
+
69
+ 另有使用 Vue 3、Vite 和 npm 包导入方式的同功能示例,SDK 尚未发布时通过 yalc 本地安装和验证:[Vue 3 SharedWorker Demo](examples/vue3-shared-worker-demo/README.md)。
70
+
71
+ ## TLV v1 最小接入 Demo
72
+
73
+ 需要在浏览器里手动验证普通 `RTMClient` 接入时,在仓库根目录运行 `npm run build` 后执行 `npm run demo:tlv-basic`,再打开 `http://127.0.0.1:4174`。Demo 使用本机静态服务器;PID、WebSocket endpoint、UID 和服务端签发的 credential 由接入者填写,不会保存到浏览器存储。详见 [Demo 使用说明](examples/tlv-basic-demo/README.md)。
74
+
75
+ ## 文档
76
+
77
+ - [接入指南与 API 参数](docs/USAGE.md)
78
+ - [能力总览与典型业务流程](docs/CAPABILITIES.md)
79
+ - [TLV v1 URI、请求字段与返回值](docs/TLV_CONTRACT.md)
61
80
  - [TLV v1 传输规则](docs/TLV.md)
81
+ - [在线 Gate 验证](docs/TLV_LIVE_E2E_TEST.md)
82
+ - [TypeScript 声明](dist/rtm.d.ts)
package/dist/rtm.d.ts CHANGED
@@ -2,6 +2,34 @@ export as namespace rtm;
2
2
 
3
3
  declare namespace rtm {
4
4
  type RTMProtocol = 'fpnn' | 'tlv-v1';
5
+ export type RTMId = string | number | { toString(): string };
6
+
7
+ export interface RTMLoginPromiseResult {
8
+ accepted: true;
9
+ errorCode: number;
10
+ }
11
+
12
+ type RTMPromiseExcludedMethod = 'close' | 'destroy' | 'emit' | 'off' | 'on'
13
+ | 'removeEvent' | 'startAutoReconnect' | 'promises' | 'processor';
14
+
15
+ /** Promise versions of callback-based RTM requests. Parameters keep the original order, without callback. */
16
+ export type RTMPromiseApi = {
17
+ [Method in Exclude<keyof RTMClient, RTMPromiseExcludedMethod>]:
18
+ RTMClient[Method] extends (...args: any[]) => any ? (...args: any[]) => Promise<any> : never;
19
+ } & {
20
+ login(uid: RTMId, credential: string, timeout?: number): Promise<RTMLoginPromiseResult>;
21
+ bye(timeout?: number): Promise<any>;
22
+ sendChat(to: RTMId, msg: string | ArrayBuffer | Uint8Array, attrs?: string, mid?: RTMId, timeout?: number): Promise<any>;
23
+ sendGroupChat(gid: RTMId, msg: string | ArrayBuffer | Uint8Array, attrs?: string, mid?: RTMId, timeout?: number): Promise<any>;
24
+ sendRoomChat(rid: RTMId, msg: string | ArrayBuffer | Uint8Array, attrs?: string, mid?: RTMId, timeout?: number): Promise<any>;
25
+ getP2PMessage(ouid: RTMId, desc?: boolean, num?: number, begin?: RTMId, end?: RTMId, lastid?: RTMId, mtypes?: number[], timeout?: number): Promise<any>;
26
+ getGroupMessage(gid: RTMId, desc?: boolean, num?: number, begin?: RTMId, end?: RTMId, lastid?: RTMId, mtypes?: number[], timeout?: number): Promise<any>;
27
+ getRoomMessage(rid: RTMId, desc?: boolean, num?: number, begin?: RTMId, end?: RTMId, lastid?: RTMId, mtypes?: number[], timeout?: number): Promise<any>;
28
+ getSession(timeout?: number): Promise<any>;
29
+ getUnreadMessage(clear?: boolean, withLogout?: boolean, timeout?: number): Promise<any>;
30
+ };
31
+
32
+ export type RTMSharedWorkerPromiseApi = RTMPromiseApi;
5
33
 
6
34
  interface RTMRegressiveStrategy {
7
35
  startConnectFailedCount: number;
@@ -33,7 +61,7 @@ declare namespace rtm {
33
61
  clientVersion?: string;
34
62
  authSec?: number;
35
63
  authVer?: 2;
36
- requestMetadata?: () => Record<string, unknown>;
64
+ requestMetadata?: Record<string, unknown> | (() => Record<string, unknown>);
37
65
  requestMetadataProvider?: () => Record<string, unknown>;
38
66
  webSocketFactory?: (url: string) => RTMWebSocket;
39
67
  attrs?: Record<string, string>;
@@ -46,6 +74,8 @@ declare namespace rtm {
46
74
 
47
75
  export class RTMClient {
48
76
  constructor(options: RTMClientOptions);
77
+ /** Promise facade for callback-based business request methods. */
78
+ readonly promises: RTMPromiseApi;
49
79
  processor;
50
80
  login(uid, token, callback, timeout);
51
81
  destroy();
@@ -75,7 +105,8 @@ declare namespace rtm {
75
105
  fileToken(cmd, tos, to, rid, gid, timeout, callback);
76
106
  close();
77
107
  startAutoReconnect();
78
- bye();
108
+ bye(callback?: (err?: Error | null, data?: any) => void): void;
109
+ bye(timeout?: number, callback?: (err?: Error | null, data?: any) => void): void;
79
110
  addAttrs(attrs, timeout, callback);
80
111
  getAttrs(timeout, callback);
81
112
  addDebugLog(msg, attrs, timeout, callback);
@@ -157,6 +188,114 @@ declare namespace rtm {
157
188
  removeEvent();
158
189
  }
159
190
 
191
+ export interface RTMSharedWorkerClientOptions {
192
+ pid: number;
193
+ /** SharedWorker supports the TLV transport only. */
194
+ protocol?: 'tlv-v1';
195
+ /** Required full ws:// or wss:// WebSocket URL. */
196
+ tlvEndpoint: string;
197
+ autoReconnect?: boolean;
198
+ connectionTimeout?: number;
199
+ requestTimeout?: number;
200
+ /** Static TLV metadata; only trace and sent_ms are sent on the wire. */
201
+ requestMetadata?: Record<string, unknown>;
202
+ locale?: string;
203
+ clientVersion?: string;
204
+ authSec?: number;
205
+ authVer?: 2;
206
+ attrs?: Record<string, string>;
207
+ tlvHeartbeatIdleMs?: number;
208
+ tlvHeartbeatTimeoutMs?: number;
209
+ pushDedupTtlMs?: number;
210
+ regressiveStrategy?: RTMRegressiveStrategy;
211
+ }
212
+
213
+ export type RTMConversationType = 'direct' | 'group' | 'room';
214
+
215
+ export interface RTMConversation {
216
+ type: RTMConversationType;
217
+ /** Use a decimal string for IDs larger than Number.MAX_SAFE_INTEGER. */
218
+ id: string | number | { toString(): string };
219
+ }
220
+
221
+ export interface RTMSharedWorkerOptions {
222
+ /** Optional same-origin Worker URL. The classic entry defaults beside its script; the Vite entry bundles this resource automatically. */
223
+ workerUrl?: string;
224
+ /** Explicit stable name. When omitted and uid is provided, the SDK derives one from pid, uid, endpoint, and workerNamespace. */
225
+ workerName?: string;
226
+ /** UID used only to derive workerName when workerName is omitted; it does not log in automatically. */
227
+ uid?: RTMId;
228
+ /** Optional application/environment scope included in the derived workerName. */
229
+ workerNamespace?: string;
230
+ /** Maximum time to wait for the SharedWorker init response; defaults to 10000 ms. */
231
+ readyTimeout?: number;
232
+ /** Close and release the RTC session after the last page detaches; defaults to 5000 ms. Use 0 to close immediately. All tabs sharing a Worker must use the same value. */
233
+ idleShutdownTimeout?: number;
234
+ /** Structured-cloneable options supported by the SharedWorker TLV transport. */
235
+ clientOptions: RTMSharedWorkerClientOptions;
236
+ /** Optional route for this page. When omitted, this page receives all conversation Push events. */
237
+ conversation?: RTMConversation | null;
238
+ }
239
+
240
+ export interface RTMSharedSessionSnapshot {
241
+ status: 'idle' | 'connecting' | 'authenticated';
242
+ /** Decimal UID string for the shared session; null while idle. */
243
+ uid: string | null;
244
+ }
245
+
246
+ export interface RTMSharedLoginResult {
247
+ accepted: boolean;
248
+ errorCode: number;
249
+ /** True when this call reused an authenticated session or joined its login attempt. */
250
+ reused: boolean;
251
+ /** Decimal UID of the resulting or conflicting shared session. */
252
+ uid: string | null;
253
+ }
254
+
255
+ interface RTMSharedProcessor {
256
+ on(type: string, callback: (...args: any[]) => void): this;
257
+ off(type: string, callback?: (...args: any[]) => void): this;
258
+ removeEvent(type?: string, callback?: (...args: any[]) => void): this;
259
+ }
260
+
261
+ export class RTMSharedWorkerClient {
262
+ constructor(options: RTMSharedWorkerOptions);
263
+ /** Creates a stable name for the same project, UID, endpoint, and optional application/environment namespace. */
264
+ static createWorkerName(identity: RTMSharedWorkerIdentity): string;
265
+ /** Promise facade for callback-based business request methods. */
266
+ readonly promises: RTMSharedWorkerPromiseApi;
267
+ processor: RTMSharedProcessor;
268
+ /** Resolves with the session snapshot after this page attaches to the Worker. */
269
+ whenReady(): Promise<RTMSharedSessionSnapshot>;
270
+ /** Returns the latest session snapshot observed by this page. */
271
+ getSharedSession(): RTMSharedSessionSnapshot;
272
+ /** Reuses/joins a same-UID login; credential is required only when the shared session is idle. */
273
+ loginIfNeeded(uid: string | number | { toString(): string }, credential?: string, timeout?: number): Promise<RTMSharedLoginResult>;
274
+ /** Receives the current snapshot on ready and whenever a shared tab's login state changes. */
275
+ on(type: 'SharedWorkerReady' | 'SharedSessionState', callback: (session: RTMSharedSessionSnapshot) => void): this;
276
+ on(type: string, callback: (...args: any[]) => void): this;
277
+ off(type: string, callback?: (...args: any[]) => void): this;
278
+ removeEvent(type?: string, callback?: (...args: any[]) => void): this;
279
+ /** Route matching conversation Push events to this page; pass null to receive all conversations. */
280
+ setConversation(conversation: RTMConversation | null, callback?: (error?: Error | null) => void): this;
281
+ /** Detaches this page; also called automatically on pagehide (except BFCache). It does not close the shared connection. */
282
+ destroy(): void;
283
+ }
284
+
285
+ export interface RTMSharedWorkerIdentity {
286
+ pid: string | number;
287
+ uid: RTMId;
288
+ endpoint?: string;
289
+ namespace?: string;
290
+ }
291
+
292
+ export function createSharedWorkerName(identity: RTMSharedWorkerIdentity): string;
293
+
294
+ type RTMSharedWorkerClientMethods = Pick<RTMClient, Exclude<keyof RTMClient,
295
+ 'emit' | 'promises'>>;
296
+
297
+ export interface RTMSharedWorkerClient extends RTMSharedWorkerClientMethods {}
298
+
160
299
  export class RTMConfig {
161
300
  static ERROR_CODE;
162
301
  static Int64;