grpc-libp2p-client 0.0.25 → 0.0.27

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,2 +1,225 @@
1
+
1
2
  # grpc-libp2p-client
2
- grpc-libp2p-client
3
+
4
+ `grpc-libp2p-client` 是一个在浏览器环境中运行的 gRPC 客户端库,它构建于 [libp2p](https://libp2p.io/) 之上。它使得浏览器可以直接与基于 libp2p 的 gRPC 服务端进行安全、高效的点对点通信。
5
+
6
+ 本库完整支持四种 gRPC通信模式:
7
+ * **Unary (一元调用)**
8
+ * **Server Streaming (服务端流)**
9
+ * **Client Streaming (客户端流)**
10
+ * **Bidirectional Streaming (双向流)**
11
+
12
+ ---
13
+
14
+ ## 目录
15
+
16
+ - [安装](#安装)
17
+ - [快速上手](#快速上手)
18
+ - [用法示例](#用法示例)
19
+ - [1. Unary (请求-响应)](#1-unary-请求-响应)
20
+ - [2. Server Streaming (服务端流)](#2-server-streaming-服务端流)
21
+ - [3. Client Streaming (客户端流)](#3-client-streaming-客户端流)
22
+ - [4. Bidirectional (双向流)](#4-bidirectional-双向流)
23
+ - [API 参考](#api-参考)
24
+
25
+ ---
26
+
27
+ ## 安装
28
+
29
+ ```bash
30
+ npm install grpc-libp2p-client
31
+ # 或者
32
+ yarn add grpc-libp2p-client
33
+ ```
34
+
35
+ ## 快速上手
36
+
37
+ 下面是一个快速设置并初始化客户端的示例。
38
+
39
+ ```javascript
40
+ import { createLibp2p } from 'libp2p';
41
+ import { webRTC } from '@libp2p/webrtc';
42
+ import { noise } from '@chainsafe/libp2p-noise';
43
+ import { yamux } from '@chainsafe/libp2p-yamux';
44
+ import { Libp2pGrpcClient } from 'grpc-libp2p-client';
45
+
46
+ // 1. 创建并启动一个 libp2p 节点
47
+ // 这是客户端运行的基础,负责网络连接和数据传输
48
+ const node = await createLibp2p({
49
+ transports: [
50
+ webRTC()
51
+ ],
52
+ connectionEncryption: [
53
+ noise()
54
+ ],
55
+ streamMuxers: [
56
+ yamux()
57
+ ]
58
+ });
59
+ await node.start();
60
+ console.log('Libp2p node started with Peer ID:', node.peerId.toString());
61
+
62
+
63
+ // 2. 定义服务端信息
64
+ const serverPeerAddr = '/ip4/x.x.x.x/tcp/4006/p2p/12D3KooW...'; // 替换为你的 gRPC 服务端的 PeerAddr
65
+ const serverProtocol = '/my-grpc-service/1.0.0'; // 替换为服务端使用的协议ID
66
+
67
+ // 3. 实例化 gRPC 客户端
68
+ // 将 libp2p 节点实例和服务端信息传入
69
+ const grpcClient = new Libp2pGrpcClient(node, serverPeerAddr, "",serverProtocol);
70
+
71
+ console.log('gRPC client is ready to make calls.');
72
+ ```
73
+
74
+ ## 用法示例
75
+
76
+ 在初始化客户端后,你可以根据需要选择不同的模式与服务端通信。
77
+
78
+ **注意**: 所有模式中,请求体(`messageBytes`)都需要预先使用 `protobuf` 进行编码。
79
+
80
+ ### 1. Unary (请求-响应)
81
+
82
+ 这是最基础的模式,客户端发送一个请求,服务端返回一个响应。
83
+
84
+ ```javascript
85
+ // 假设 messageBytes 是已经编码好的请求数据
86
+ // const messageBytes = MyRequest.encode({ field: 'value' }).finish();
87
+
88
+ try {
89
+ const responseData = await grpcClient.unaryCall(
90
+ "/myservice.Service/MyMethod", // gRPC 方法路径
91
+ messageBytes, // Protobuf 编码后的请求字节流
92
+ 3000 // 调用超时时间 (ms)
93
+ );
94
+
95
+ // 解码响应数据
96
+ // const response = MyResponse.decode(responseData);
97
+ console.log('Unary call successful, response:', responseData);
98
+
99
+ } catch (error) {
100
+ console.error('Unary call failed:', error);
101
+ }
102
+ ```
103
+
104
+ ### 2. Server Streaming (服务端流)
105
+
106
+ 客户端发送一个请求,服务端以流的形式持续返回多个响应。
107
+
108
+ ```javascript
109
+ // 定义一个回调函数来处理服务端发来的每一条数据
110
+ const onDataCallback = (payload: Uint8Array) => {
111
+ // const message = MyStreamResponse.decode(payload);
112
+ console.log('Received stream data:', payload);
113
+ };
114
+
115
+ await grpcClient.Call(
116
+ "/myservice.Service/MyServerStreamMethod",
117
+ messageBytes,
118
+ 30000,
119
+ "server-streaming",
120
+ onDataCallback,
121
+ );
122
+ ```
123
+
124
+ ### 3. Client Streaming (客户端流)
125
+
126
+ 客户端以流的形式发送多个请求,服务端在接收完所有请求后返回一个响应。
127
+
128
+ ```javascript
129
+ // 创建一个异步迭代器,用于持续提供要发送的数据
130
+ const dataSourceCallback = async function* (): AsyncIterable<Uint8Array> {
131
+ for (let i = 0; i < 5; i++) {
132
+ // const requestPart = MyStreamRequest.encode({ part: i }).finish();
133
+ const requestPart = new Uint8Array([i]); // 示例数据
134
+ yield requestPart;
135
+ await new Promise(resolve => setTimeout(resolve, 500)); // 模拟异步发送
136
+ }
137
+ };
138
+
139
+ // 定义数据回调,只会在服务端最终响应时触发一次
140
+ const onDataCallback = (payload: Uint8Array) => {
141
+ // const finalResponse = MyFinalResponse.decode(payload);
142
+ console.log('Client stream finished, final response:', payload);
143
+ };
144
+
145
+ await grpcClient.Call(
146
+ "/myservice.Service/MyClientStreamMethod",
147
+ messageBytes, // 初始消息体
148
+ 30000,
149
+ "client-streaming",
150
+ onDataCallback,
151
+ dataSourceCallback,
152
+ );
153
+ ```
154
+
155
+ ### 4. Bidirectional (双向流)
156
+
157
+ 客户端和服务端可以同时向对方发送数据流,实现全双工通信。
158
+
159
+ ```javascript
160
+ // 定义数据回调,处理服务端发来的每一条数据
161
+ const onDataCallback = (payload: Uint8Array) => {
162
+ console.log('Bidi: Received data from server:', payload);
163
+ };
164
+
165
+ // 定义数据源,持续向服务端发送数据
166
+ const dataSourceCallback = async function* (): AsyncIterable<Uint8Array> {
167
+ for (let i = 0; i < 5; i++) {
168
+ const requestPart = new Uint8Array([i]);
169
+ console.log(`Bidi: Sending data to server: ${i}`);
170
+ yield requestPart;
171
+ await new Promise(resolve => setTimeout(resolve, 500));
172
+ }
173
+ };
174
+
175
+ // 定义结束和错误处理回调
176
+ const onEndCallback = () => console.log('Bidi stream ended.');
177
+ const onErrorCallback = (err: unknown) => console.error('Bidi stream error:', err);
178
+
179
+ await grpcClient.Call(
180
+ "/myservice.Service/MyBidiMethod",
181
+ messageBytes, // 可以发送一个初始消息
182
+ 30000,
183
+ "bidirectional",
184
+ onDataCallback,
185
+ dataSourceCallback,
186
+ onEndCallback,
187
+ onErrorCallback
188
+ );
189
+ ```
190
+
191
+ ---
192
+
193
+ ## API 参考
194
+
195
+ ### `new Libp2pGrpcClient(node, serverPeerAddr,token, protocol)`
196
+
197
+ - `node` (`Libp2p`): 一个已创建并启动的 libp2p 节点实例。
198
+ - `serverPeerAddr` (`string`): 目标 gRPC 服务端的p2p地址字符串。
199
+ - `token` (`string`): 目标 gRPC 服务端要求的认证信息,在http2头的authorization字段中提交,可以为空。
200
+ - `protocol` (`string`): 双方协定好的、用于 gRPC 通信的 libp2p 协议 ID。
201
+
202
+ ### `grpcClient.unaryCall(path, payload, timeout)`
203
+
204
+ 用于发起一次性的请求-响应调用。
205
+
206
+ - 返回: `Promise<Uint8Array>` - 服务端返回的 Protobuf 编码后的字节流。
207
+
208
+ ### `grpcClient.Call(path, payload, timeout, mode, onDataCallback,dataSourceCallback?,,onEndCallback?,onErrorCallback?,context?)`
209
+
210
+ 用于发起所有类型的流式调用。
211
+
212
+ - `path` (`string`): gRPC 方法的完整路径。
213
+ - `payload` (`Uint8Array` | `null`): 初始请求的字节流。
214
+ - `timeout` (`number`): 调用超时时间 (ms)。
215
+ - `mode` (`string`): 调用模式。
216
+ - `"server-streaming"`
217
+ - `"client-streaming"`
218
+ - `"bidirectional"`
219
+ - `onDataCallback` (`(data: Uint8Array) => void`): 接收数据的回调。
220
+ - `dataSourceCallback?` (`() => AsyncIterable<Uint8Array>`): 提供发送数据的异步迭代器 (用于客户端流和双向流)。
221
+ - `onEndCallback?` (`() => void`): 流正常结束时的回调。
222
+ - `onErrorCallback?` (`(err: unknown) => void`): 发生错误时的回调。
223
+ - `context?` (` { signal?: AbortSignal }`): 中间取消。
224
+
225
+
package/dist/grpc.js CHANGED
@@ -3761,7 +3761,6 @@
3761
3761
  });
3762
3762
  writer_1.addEventListener("drain", function (e) {
3763
3763
  var d = (e === null || e === void 0 ? void 0 : e.detail) || {};
3764
- console.debug("[unary stream ".concat(streamId_1, "] drain drained=").concat(d.drained, " queue=").concat(d.queueSize));
3765
3764
  });
3766
3765
  writer_1.addEventListener("stalled", function (e) {
3767
3766
  var _a;
@@ -3785,6 +3784,8 @@
3785
3784
  if (state) {
3786
3785
  _this.rejectStreamWaiters(state, new Error("Connection received GOAWAY"));
3787
3786
  }
3787
+ exitFlag = true;
3788
+ errMsg = "GOAWAY received: code=".concat(info.errorCode);
3788
3789
  try {
3789
3790
  (_a = connection === null || connection === void 0 ? void 0 : connection.close) === null || _a === void 0 ? void 0 : _a.call(connection);
3790
3791
  }
@@ -4121,7 +4122,7 @@
4121
4122
  _s.label = 7;
4122
4123
  case 7:
4123
4124
  _s.trys.push([7, 9, , 10]);
4124
- return [4 /*yield*/, this.waitForStreamSlot(state, internalController.signal, 10000)];
4125
+ return [4 /*yield*/, this.waitForStreamSlot(state, internalController.signal, timeout)];
4125
4126
  case 8:
4126
4127
  _s.sent();
4127
4128
  state.activeStreams += 1;
@@ -4179,6 +4180,10 @@
4179
4180
  if (state) {
4180
4181
  _this.rejectStreamWaiters(state, new Error("Connection received GOAWAY"));
4181
4182
  }
4183
+ if (onErrorCallback) {
4184
+ onErrorCallback(new Error("GOAWAY received: code=".concat(info.errorCode)));
4185
+ }
4186
+ internalController.abort();
4182
4187
  try {
4183
4188
  (_a = connection === null || connection === void 0 ? void 0 : connection.close) === null || _a === void 0 ? void 0 : _a.call(connection);
4184
4189
  }