@nmtjs/protocol 0.6.5 → 0.7.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 (62) hide show
  1. package/dist/client/events.js +29 -26
  2. package/dist/client/events.js.map +1 -1
  3. package/dist/client/format.js +1 -2
  4. package/dist/client/format.js.map +1 -1
  5. package/dist/client/index.js.map +1 -1
  6. package/dist/client/protocol.js +331 -336
  7. package/dist/client/protocol.js.map +1 -1
  8. package/dist/client/stream.js +79 -92
  9. package/dist/client/stream.js.map +1 -1
  10. package/dist/common/binary.js +20 -20
  11. package/dist/common/binary.js.map +1 -1
  12. package/dist/common/blob.js +36 -40
  13. package/dist/common/blob.js.map +1 -1
  14. package/dist/common/enums.js +44 -44
  15. package/dist/common/enums.js.map +1 -1
  16. package/dist/common/index.js.map +1 -1
  17. package/dist/common/types.js +1 -1
  18. package/dist/common/types.js.map +1 -1
  19. package/dist/server/api.js +1 -1
  20. package/dist/server/api.js.map +1 -1
  21. package/dist/server/connection.js +18 -18
  22. package/dist/server/connection.js.map +1 -1
  23. package/dist/server/constants.js +1 -1
  24. package/dist/server/constants.js.map +1 -1
  25. package/dist/server/format.js +42 -45
  26. package/dist/server/format.js.map +1 -1
  27. package/dist/server/index.js.map +1 -1
  28. package/dist/server/injectables.js +18 -18
  29. package/dist/server/injectables.js.map +1 -1
  30. package/dist/server/protocol.js +282 -296
  31. package/dist/server/protocol.js.map +1 -1
  32. package/dist/server/registry.js +2 -19
  33. package/dist/server/registry.js.map +1 -1
  34. package/dist/server/stream.js +24 -26
  35. package/dist/server/stream.js.map +1 -1
  36. package/dist/server/transport.js +6 -6
  37. package/dist/server/transport.js.map +1 -1
  38. package/dist/server/utils.js +9 -9
  39. package/dist/server/utils.js.map +1 -1
  40. package/package.json +12 -16
  41. package/{lib → src}/client/protocol.ts +4 -3
  42. package/{lib → src}/client/stream.ts +18 -26
  43. package/{lib → src}/server/connection.ts +1 -1
  44. package/{lib → src}/server/protocol.ts +18 -8
  45. package/src/server/registry.ts +3 -0
  46. package/lib/server/registry.ts +0 -24
  47. /package/{lib → src}/client/events.ts +0 -0
  48. /package/{lib → src}/client/format.ts +0 -0
  49. /package/{lib → src}/client/index.ts +0 -0
  50. /package/{lib → src}/common/binary.ts +0 -0
  51. /package/{lib → src}/common/blob.ts +0 -0
  52. /package/{lib → src}/common/enums.ts +0 -0
  53. /package/{lib → src}/common/index.ts +0 -0
  54. /package/{lib → src}/common/types.ts +0 -0
  55. /package/{lib → src}/server/api.ts +0 -0
  56. /package/{lib → src}/server/constants.ts +0 -0
  57. /package/{lib → src}/server/format.ts +0 -0
  58. /package/{lib → src}/server/index.ts +0 -0
  59. /package/{lib → src}/server/injectables.ts +0 -0
  60. /package/{lib → src}/server/stream.ts +0 -0
  61. /package/{lib → src}/server/transport.ts +0 -0
  62. /package/{lib → src}/server/utils.ts +0 -0
@@ -1,350 +1,345 @@
1
- import { createPromise, onceAborted } from '@nmtjs/common';
1
+ import { createPromise, onceAborted } from "@nmtjs/common";
2
2
  import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
3
3
  import { ClientMessageType, ErrorCode, ServerMessageType } from "../common/enums.js";
4
4
  import { EventEmitter } from "./events.js";
5
5
  import { ProtocolClientBlobStream, ProtocolServerBlobStream, ProtocolServerStream } from "./stream.js";
6
6
  export class ProtocolError extends Error {
7
- code;
8
- data;
9
- constructor(code, message, data){
10
- super(message);
11
- this.code = code;
12
- this.data = data;
13
- }
14
- get message() {
15
- return `${this.code} ${super.message}`;
16
- }
17
- toString() {
18
- return `${this.code} ${this.message}`;
19
- }
20
- toJSON() {
21
- return {
22
- code: this.code,
23
- message: this.message,
24
- data: this.data
25
- };
26
- }
7
+ code;
8
+ data;
9
+ constructor(code, message, data) {
10
+ super(message);
11
+ this.code = code;
12
+ this.data = data;
13
+ }
14
+ get message() {
15
+ return `${this.code} ${super.message}`;
16
+ }
17
+ toString() {
18
+ return `${this.code} ${this.message}`;
19
+ }
20
+ toJSON() {
21
+ return {
22
+ code: this.code,
23
+ message: this.message,
24
+ data: this.data
25
+ };
26
+ }
27
27
  }
28
28
  export class ProtocolClientStreams {
29
- #collection = new Map();
30
- get(streamId) {
31
- const stream = this.#collection.get(streamId);
32
- if (!stream) throw new Error('Stream not found');
33
- return stream;
34
- }
35
- add(source, streamId, metadata) {
36
- const stream = new ProtocolClientBlobStream(source, streamId, metadata);
37
- this.#collection.set(streamId, stream);
38
- return stream;
39
- }
40
- remove(streamId) {
41
- this.#collection.delete(streamId);
42
- }
43
- abort(streamId) {
44
- const stream = this.get(streamId);
45
- stream.abort();
46
- this.remove(streamId);
47
- }
48
- pull(streamId, size) {
49
- const stream = this.get(streamId);
50
- return stream.read(size);
51
- }
52
- end(streamId) {
53
- const stream = this.get(streamId);
54
- stream.end();
55
- this.remove(streamId);
56
- }
57
- clear(error) {
58
- if (error) {
59
- for (const stream of this.#collection.values()){
60
- stream.abort(error);
61
- }
62
- }
63
- this.#collection.clear();
64
- }
29
+ #collection = new Map();
30
+ get(streamId) {
31
+ const stream = this.#collection.get(streamId);
32
+ if (!stream) throw new Error("Stream not found");
33
+ return stream;
34
+ }
35
+ add(source, streamId, metadata) {
36
+ const stream = new ProtocolClientBlobStream(source, streamId, metadata);
37
+ this.#collection.set(streamId, stream);
38
+ return stream;
39
+ }
40
+ remove(streamId) {
41
+ this.#collection.delete(streamId);
42
+ }
43
+ abort(streamId) {
44
+ const stream = this.get(streamId);
45
+ stream.abort();
46
+ this.remove(streamId);
47
+ }
48
+ pull(streamId, size) {
49
+ const stream = this.get(streamId);
50
+ return stream.read(size);
51
+ }
52
+ end(streamId) {
53
+ this.get(streamId).end();
54
+ this.remove(streamId);
55
+ }
56
+ clear(error) {
57
+ if (error) {
58
+ for (const stream of this.#collection.values()) {
59
+ stream.abort(error);
60
+ }
61
+ }
62
+ this.#collection.clear();
63
+ }
65
64
  }
66
65
  export class ProtocolServerStreams {
67
- #collection = new Map();
68
- has(streamId) {
69
- return this.#collection.has(streamId);
70
- }
71
- get(streamId) {
72
- const stream = this.#collection.get(streamId);
73
- if (!stream) throw new Error('Stream not found');
74
- return stream;
75
- }
76
- add(streamId, stream) {
77
- this.#collection.set(streamId, stream);
78
- return stream;
79
- }
80
- remove(streamId) {
81
- this.#collection.delete(streamId);
82
- }
83
- abort(streamId) {
84
- if (this.has(streamId)) {
85
- const stream = this.get(streamId);
86
- stream.abort();
87
- this.remove(streamId);
88
- }
89
- }
90
- async push(streamId, chunk) {
91
- const stream = this.get(streamId);
92
- return await stream.push(chunk);
93
- }
94
- end(streamId) {
95
- const stream = this.get(streamId);
96
- stream.end();
97
- this.remove(streamId);
98
- }
99
- clear(error) {
100
- if (error) {
101
- for (const stream of this.#collection.values()){
102
- stream.abort(error);
103
- }
104
- }
105
- this.#collection.clear();
106
- }
66
+ #collection = new Map();
67
+ has(streamId) {
68
+ return this.#collection.has(streamId);
69
+ }
70
+ get(streamId) {
71
+ const stream = this.#collection.get(streamId);
72
+ if (!stream) throw new Error("Stream not found");
73
+ return stream;
74
+ }
75
+ add(streamId, stream) {
76
+ this.#collection.set(streamId, stream);
77
+ return stream;
78
+ }
79
+ remove(streamId) {
80
+ this.#collection.delete(streamId);
81
+ }
82
+ abort(streamId) {
83
+ if (this.has(streamId)) {
84
+ const stream = this.get(streamId);
85
+ stream.abort();
86
+ this.remove(streamId);
87
+ }
88
+ }
89
+ async push(streamId, chunk) {
90
+ const stream = this.get(streamId);
91
+ return await stream.push(chunk);
92
+ }
93
+ end(streamId) {
94
+ const stream = this.get(streamId);
95
+ stream.end();
96
+ this.remove(streamId);
97
+ }
98
+ clear(error) {
99
+ if (error) {
100
+ for (const stream of this.#collection.values()) {
101
+ stream.abort(error);
102
+ }
103
+ }
104
+ this.#collection.clear();
105
+ }
107
106
  }
108
107
  export class ProtocolBaseTransformer {
109
- encodeRPC(namespace, procedure, payload) {
110
- return payload;
111
- }
112
- decodeRPC(namespace, procedure, payload) {
113
- return payload;
114
- }
115
- decodeRPCChunk(namespace, procedure, payload) {
116
- return payload;
117
- }
118
- decodeEvent(namespace, event, payload) {
119
- return payload;
120
- }
108
+ encodeRPC(namespace, procedure, payload) {
109
+ return payload;
110
+ }
111
+ decodeRPC(namespace, procedure, payload) {
112
+ return payload;
113
+ }
114
+ decodeRPCChunk(namespace, procedure, payload) {
115
+ return payload;
116
+ }
117
+ decodeEvent(namespace, event, payload) {
118
+ return payload;
119
+ }
121
120
  }
122
121
  export class ProtocolBaseClient extends EventEmitter {
123
- #clientStreams;
124
- #serverStreams;
125
- #rpcStreams;
126
- #rpcStreamData = new Map();
127
- #calls = new Map();
128
- #transport;
129
- #format;
130
- transformer = new ProtocolBaseTransformer();
131
- #timeout;
132
- #callId = 0;
133
- #streamId = 0;
134
- constructor(options){
135
- super();
136
- this.#transport = options.transport;
137
- this.#format = options.format;
138
- this.#timeout = options.timeout ?? 60000;
139
- this.#clientStreams = new ProtocolClientStreams();
140
- this.#serverStreams = new ProtocolServerStreams();
141
- this.#rpcStreams = new ProtocolServerStreams();
142
- this.#transport.on(`${ServerMessageType.Event}`, (buffer)=>{
143
- const [namespace, event, payload] = this.#format.decode(buffer);
144
- const name = `${namespace}/${event}`;
145
- const transformed = this.transformer.decodeEvent(namespace, event, payload);
146
- this.emit(name, transformed);
147
- });
148
- this.#transport.on(`${ServerMessageType.RpcResponse}`, (buffer)=>{
149
- const { call, error, payload } = this.#handleResponse(buffer);
150
- if (error) call.reject(error);
151
- else call.resolve(payload);
152
- });
153
- this.#transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer)=>{
154
- const { call, response, payload, error } = this.#handleResponse(buffer);
155
- if (error) return call.reject(error);
156
- console.log('Creating RPC stream', response);
157
- const stream = new ProtocolServerStream();
158
- this.#rpcStreams.add(response.callId, stream);
159
- this.#rpcStreamData.set(response.callId, {
160
- namespace: call.namespace,
161
- procedure: call.procedure
162
- });
163
- call.resolve({
164
- payload,
165
- stream
166
- });
167
- });
168
- this.#transport.on(`${ServerMessageType.RpcStreamChunk}`, async (buffer)=>{
169
- const callId = decodeNumber(buffer, 'Uint32');
170
- console.log('RPC stream chunk', callId);
171
- const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
172
- if (chunk.byteLength === 0) {
173
- this.#rpcStreams.end(callId);
174
- this.#rpcStreamData.delete(callId);
175
- } else {
176
- const call = this.#rpcStreamData.get(callId);
177
- console.log('RPC stream call', call);
178
- if (call) {
179
- const payload = this.#format.decode(chunk);
180
- console.log('RPC stream payload', payload);
181
- try {
182
- const transformed = this.transformer.decodeRPCChunk(call.namespace, call.procedure, payload);
183
- await this.#rpcStreams.push(callId, transformed);
184
- } catch (error) {
185
- this.#send(ClientMessageType.RpcStreamAbort, encodeNumber(callId, 'Uint32'));
186
- this.#rpcStreams.remove(callId);
187
- this.#rpcStreamData.delete(callId);
188
- }
189
- }
190
- }
191
- });
192
- this.#transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer)=>{
193
- const callId = decodeNumber(buffer, 'Uint32');
194
- console.log('RPC stream abort', callId);
195
- const call = this.#calls.get(callId);
196
- if (call) {
197
- this.#serverStreams.end(callId);
198
- this.#rpcStreams.abort(callId);
199
- }
200
- });
201
- this.#transport.on(`${ServerMessageType.ServerStreamPush}`, async (buffer)=>{
202
- const streamId = decodeNumber(buffer, 'Uint32');
203
- const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
204
- console.log('Server stream push', streamId, chunk.byteLength);
205
- try {
206
- await this.#serverStreams.push(streamId, chunk);
207
- this.#send(ClientMessageType.ServerStreamPull, encodeNumber(streamId, 'Uint32'));
208
- } catch (error) {
209
- this.#send(ClientMessageType.ServerStreamAbort, encodeNumber(streamId, 'Uint32'));
210
- this.#serverStreams.remove(streamId);
211
- }
212
- });
213
- this.#transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer)=>{
214
- const streamId = decodeNumber(buffer, 'Uint32');
215
- console.log('Server stream end', streamId);
216
- this.#serverStreams.end(streamId);
217
- });
218
- this.#transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer)=>{
219
- const streamId = decodeNumber(buffer, 'Uint32');
220
- console.log('Server stream abort', streamId);
221
- this.#serverStreams.abort(streamId);
222
- });
223
- this.#transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer)=>{
224
- const streamId = decodeNumber(buffer, 'Uint32');
225
- console.log('Client stream abort', streamId);
226
- this.#clientStreams.abort(streamId);
227
- });
228
- this.#transport.on(`${ServerMessageType.ClientStreamPull}`, async (buffer)=>{
229
- const streamId = decodeNumber(buffer, 'Uint32');
230
- console.log('Client stream pull', streamId);
231
- const size = decodeNumber(buffer, 'Uint32', Uint32Array.BYTES_PER_ELEMENT);
232
- const streamIdEncoded = encodeNumber(streamId, 'Uint32');
233
- try {
234
- const chunk = await this.#clientStreams.pull(streamId, size);
235
- if (chunk) {
236
- this.#send(ClientMessageType.ClientStreamPush, concat(streamIdEncoded, chunk));
237
- } else {
238
- this.#send(ClientMessageType.ClientStreamEnd, streamIdEncoded);
239
- this.#clientStreams.end(streamId);
240
- }
241
- } catch (error) {
242
- console.error(error);
243
- this.#send(ClientMessageType.ClientStreamAbort, streamIdEncoded);
244
- }
245
- });
246
- this.#transport.on('disconnected', ()=>{});
247
- }
248
- async connect(auth) {
249
- return await this.#transport.connect(auth, this.#format.contentType);
250
- }
251
- async disconnect() {
252
- this.#clear();
253
- return await this.#transport.disconnect();
254
- }
255
- async #send(messageType, buffer) {
256
- console.log('Client transport send', ClientMessageType[messageType], buffer.byteLength);
257
- return await this.#transport.send(messageType, buffer);
258
- }
259
- async #clear() {
260
- const error = new ProtocolError(ErrorCode.ConnectionError, 'Connection closed');
261
- for (const call of this.#calls.values())call.reject(error);
262
- this.#calls.clear();
263
- this.#serverStreams.clear(error);
264
- this.#clientStreams.clear(error);
265
- this.#rpcStreams.clear(error);
266
- this.#callId = 0;
267
- this.#streamId = 0;
268
- }
269
- async _call(namespace, procedure, payload, options = {}) {
270
- const timeoutSignal = AbortSignal.timeout(options.timeout || this.#timeout);
271
- const signal = options.signal ? AbortSignal.any([
272
- options.signal,
273
- timeoutSignal
274
- ]) : timeoutSignal;
275
- const callId = ++this.#callId;
276
- const call = Object.assign(createPromise(), {
277
- namespace,
278
- procedure
279
- });
280
- const buffer = this.#format.encodeRPC({
281
- callId,
282
- namespace,
283
- procedure,
284
- payload: this.transformer.encodeRPC(namespace, procedure, payload)
285
- }, {
286
- addStream: (blob)=>{
287
- const streamId = ++this.#streamId;
288
- const stream = this.#clientStreams.add(blob.source, streamId, blob.metadata);
289
- return stream;
290
- },
291
- getStream: (id)=>{
292
- const stream = this.#clientStreams.get(id);
293
- return stream;
294
- }
295
- });
296
- this.#transport.send(ClientMessageType.Rpc, buffer).catch(console.error);
297
- this.#calls.set(callId, call);
298
- const onAborted = onceAborted(signal).then(()=>{
299
- if (this.#calls.has(callId)) {
300
- this.#send(ClientMessageType.RpcAbort, encodeNumber(callId, 'Uint32'));
301
- }
302
- throw new ProtocolError(ErrorCode.RequestTimeout, 'Request timeout');
303
- });
304
- return Promise.race([
305
- call.promise,
306
- onAborted
307
- ]);
308
- }
309
- #handleResponse(buffer) {
310
- const callStreams = [];
311
- const response = this.#format.decodeRPC(buffer, {
312
- addStream: (id, metadata)=>{
313
- console.log('Client transport blob stream', id, metadata);
314
- const stream = new ProtocolServerBlobStream(id, metadata, ()=>{
315
- this.#send(ClientMessageType.ServerStreamPull, encodeNumber(id, 'Uint32'));
316
- });
317
- callStreams.push(stream);
318
- this.#serverStreams.add(id, stream);
319
- return stream;
320
- },
321
- getStream: (id)=>{
322
- return this.#serverStreams.get(id);
323
- }
324
- });
325
- console.log('Client transport response', response);
326
- const call = this.#calls.get(response.callId);
327
- if (call) {
328
- this.#calls.delete(response.callId);
329
- if (response.error) {
330
- const error = new ProtocolError(response.error.code, response.error.message, response.error.data);
331
- return {
332
- call,
333
- response,
334
- error
335
- };
336
- } else {
337
- const payload = this.transformer.decodeRPC(call.namespace, call.procedure, response.payload);
338
- return {
339
- call,
340
- response,
341
- payload
342
- };
343
- }
344
- }
345
- for (const stream of callStreams){
346
- this.#serverStreams.abort(stream.id);
347
- }
348
- throw new Error('Call not found');
349
- }
122
+ #clientStreams;
123
+ #serverStreams;
124
+ #rpcStreams;
125
+ #rpcStreamData = new Map();
126
+ #calls = new Map();
127
+ #transport;
128
+ #format;
129
+ transformer = new ProtocolBaseTransformer();
130
+ #timeout;
131
+ #callId = 0;
132
+ #streamId = 0;
133
+ constructor(options) {
134
+ super();
135
+ this.#transport = options.transport;
136
+ this.#format = options.format;
137
+ this.#timeout = options.timeout ?? 6e4;
138
+ this.#clientStreams = new ProtocolClientStreams();
139
+ this.#serverStreams = new ProtocolServerStreams();
140
+ this.#rpcStreams = new ProtocolServerStreams();
141
+ this.#transport.on(`${ServerMessageType.Event}`, (buffer) => {
142
+ const [namespace, event, payload] = this.#format.decode(buffer);
143
+ const name = `${namespace}/${event}`;
144
+ const transformed = this.transformer.decodeEvent(namespace, event, payload);
145
+ this.emit(name, transformed);
146
+ });
147
+ this.#transport.on(`${ServerMessageType.RpcResponse}`, (buffer) => {
148
+ const { call, error, payload } = this.#handleResponse(buffer);
149
+ if (error) call.reject(error);
150
+ else call.resolve(payload);
151
+ });
152
+ this.#transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer) => {
153
+ const { call, response, payload, error } = this.#handleResponse(buffer);
154
+ if (error) return call.reject(error);
155
+ console.log("Creating RPC stream", response);
156
+ const stream = new ProtocolServerStream();
157
+ this.#rpcStreams.add(response.callId, stream);
158
+ this.#rpcStreamData.set(response.callId, {
159
+ namespace: call.namespace,
160
+ procedure: call.procedure
161
+ });
162
+ call.resolve({
163
+ payload,
164
+ stream
165
+ });
166
+ });
167
+ this.#transport.on(`${ServerMessageType.RpcStreamChunk}`, async (buffer) => {
168
+ const callId = decodeNumber(buffer, "Uint32");
169
+ console.log("RPC stream chunk", callId);
170
+ const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
171
+ if (chunk.byteLength === 0) {
172
+ this.#rpcStreams.end(callId);
173
+ this.#rpcStreamData.delete(callId);
174
+ } else {
175
+ const call = this.#rpcStreamData.get(callId);
176
+ console.log("RPC stream call", call);
177
+ if (call) {
178
+ const payload = this.#format.decode(chunk);
179
+ console.log("RPC stream payload", payload);
180
+ try {
181
+ const transformed = this.transformer.decodeRPCChunk(call.namespace, call.procedure, payload);
182
+ await this.#rpcStreams.push(callId, transformed);
183
+ } catch (error) {
184
+ this.#send(ClientMessageType.RpcStreamAbort, encodeNumber(callId, "Uint32"));
185
+ this.#rpcStreams.remove(callId);
186
+ this.#rpcStreamData.delete(callId);
187
+ }
188
+ }
189
+ }
190
+ });
191
+ this.#transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer) => {
192
+ const callId = decodeNumber(buffer, "Uint32");
193
+ console.log("RPC stream abort", callId);
194
+ const call = this.#calls.get(callId);
195
+ if (call) {
196
+ this.#serverStreams.end(callId);
197
+ this.#rpcStreams.abort(callId);
198
+ }
199
+ });
200
+ this.#transport.on(`${ServerMessageType.ServerStreamPush}`, async (buffer) => {
201
+ const streamId = decodeNumber(buffer, "Uint32");
202
+ const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
203
+ console.log("Server stream push", streamId, chunk.byteLength);
204
+ try {
205
+ await this.#serverStreams.push(streamId, chunk);
206
+ this.#send(ClientMessageType.ServerStreamPull, encodeNumber(streamId, "Uint32"));
207
+ } catch (error) {
208
+ this.#send(ClientMessageType.ServerStreamAbort, encodeNumber(streamId, "Uint32"));
209
+ this.#serverStreams.remove(streamId);
210
+ }
211
+ });
212
+ this.#transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer) => {
213
+ const streamId = decodeNumber(buffer, "Uint32");
214
+ console.log("Server stream end", streamId);
215
+ this.#serverStreams.end(streamId);
216
+ });
217
+ this.#transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer) => {
218
+ const streamId = decodeNumber(buffer, "Uint32");
219
+ console.log("Server stream abort", streamId);
220
+ this.#serverStreams.abort(streamId);
221
+ });
222
+ this.#transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer) => {
223
+ const streamId = decodeNumber(buffer, "Uint32");
224
+ console.log("Client stream abort", streamId);
225
+ this.#clientStreams.abort(streamId);
226
+ });
227
+ this.#transport.on(`${ServerMessageType.ClientStreamPull}`, async (buffer) => {
228
+ const streamId = decodeNumber(buffer, "Uint32");
229
+ console.log("Client stream pull", streamId);
230
+ const size = decodeNumber(buffer, "Uint32", Uint32Array.BYTES_PER_ELEMENT);
231
+ const streamIdEncoded = encodeNumber(streamId, "Uint32");
232
+ try {
233
+ const chunk = await this.#clientStreams.pull(streamId, size);
234
+ if (chunk) {
235
+ this.#send(ClientMessageType.ClientStreamPush, concat(streamIdEncoded, chunk));
236
+ } else {
237
+ this.#send(ClientMessageType.ClientStreamEnd, streamIdEncoded);
238
+ this.#clientStreams.end(streamId);
239
+ }
240
+ } catch (error) {
241
+ console.error(error);
242
+ this.#send(ClientMessageType.ClientStreamAbort, streamIdEncoded);
243
+ }
244
+ });
245
+ this.#transport.on("disconnected", () => {
246
+ this.#clear();
247
+ });
248
+ }
249
+ async connect(auth) {
250
+ return await this.#transport.connect(auth, this.#format.contentType);
251
+ }
252
+ async disconnect() {
253
+ this.#clear();
254
+ return await this.#transport.disconnect();
255
+ }
256
+ async #send(messageType, buffer) {
257
+ console.log("Client transport send", ClientMessageType[messageType], buffer.byteLength);
258
+ return await this.#transport.send(messageType, buffer);
259
+ }
260
+ async #clear() {
261
+ const error = new ProtocolError(ErrorCode.ConnectionError, "Connection closed");
262
+ for (const call of this.#calls.values()) call.reject(error);
263
+ this.#calls.clear();
264
+ this.#serverStreams.clear(error);
265
+ this.#clientStreams.clear(error);
266
+ this.#rpcStreams.clear(error);
267
+ this.#callId = 0;
268
+ this.#streamId = 0;
269
+ }
270
+ async _call(namespace, procedure, payload, options = {}) {
271
+ const timeoutSignal = AbortSignal.timeout(options.timeout || this.#timeout);
272
+ const signal = options.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal;
273
+ const callId = ++this.#callId;
274
+ const call = Object.assign(createPromise(), {
275
+ namespace,
276
+ procedure
277
+ });
278
+ const buffer = this.#format.encodeRPC({
279
+ callId,
280
+ namespace,
281
+ procedure,
282
+ payload: this.transformer.encodeRPC(namespace, procedure, payload)
283
+ }, {
284
+ addStream: (blob) => {
285
+ const streamId = ++this.#streamId;
286
+ const stream = this.#clientStreams.add(blob.source, streamId, blob.metadata);
287
+ return stream;
288
+ },
289
+ getStream: (id) => {
290
+ const stream = this.#clientStreams.get(id);
291
+ return stream;
292
+ }
293
+ });
294
+ this.#transport.send(ClientMessageType.Rpc, buffer).catch(console.error);
295
+ this.#calls.set(callId, call);
296
+ const onAborted = onceAborted(signal).then(() => {
297
+ if (this.#calls.has(callId)) {
298
+ this.#send(ClientMessageType.RpcAbort, encodeNumber(callId, "Uint32"));
299
+ }
300
+ throw new ProtocolError(ErrorCode.RequestTimeout, "Request timeout");
301
+ });
302
+ return Promise.race([call.promise, onAborted]);
303
+ }
304
+ #handleResponse(buffer) {
305
+ const callStreams = [];
306
+ const response = this.#format.decodeRPC(buffer, {
307
+ addStream: (id, metadata) => {
308
+ console.log("Client transport blob stream", id, metadata);
309
+ const stream = new ProtocolServerBlobStream(id, metadata, () => {
310
+ this.#send(ClientMessageType.ServerStreamPull, encodeNumber(id, "Uint32"));
311
+ });
312
+ callStreams.push(stream);
313
+ this.#serverStreams.add(id, stream);
314
+ return stream;
315
+ },
316
+ getStream: (id) => {
317
+ return this.#serverStreams.get(id);
318
+ }
319
+ });
320
+ console.log("Client transport response", response);
321
+ const call = this.#calls.get(response.callId);
322
+ if (call) {
323
+ this.#calls.delete(response.callId);
324
+ if (response.error) {
325
+ const error = new ProtocolError(response.error.code, response.error.message, response.error.data);
326
+ return {
327
+ call,
328
+ response,
329
+ error
330
+ };
331
+ } else {
332
+ const payload = this.transformer.decodeRPC(call.namespace, call.procedure, response.payload);
333
+ return {
334
+ call,
335
+ response,
336
+ payload
337
+ };
338
+ }
339
+ }
340
+ for (const stream of callStreams) {
341
+ this.#serverStreams.abort(stream.id);
342
+ }
343
+ throw new Error("Call not found");
344
+ }
350
345
  }