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 +224 -1
- package/dist/grpc.js +7 -2
- package/dist/grpc.js.map +1 -1
- package/dist/grpc.min.js +1 -1
- package/dist/grpc.min.js.map +1 -1
- package/dist/index.cjs.js +7 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +7 -2
- package/dist/index.esm.js.map +1 -1
- package/package.json +13 -6
- package/src/index.ts +7 -4
package/README.md
CHANGED
|
@@ -1,2 +1,225 @@
|
|
|
1
|
+
|
|
1
2
|
# grpc-libp2p-client
|
|
2
|
-
|
|
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,
|
|
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
|
}
|