@nmtjs/protocol 0.15.0-beta.35 → 0.15.0-beta.37
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/LICENSE.md +1 -1
- package/README.md +1 -1
- package/dist/client/events.d.ts +15 -0
- package/dist/client/events.js +28 -0
- package/dist/client/format.d.ts +13 -18
- package/dist/client/format.js +0 -1
- package/dist/client/index.d.ts +1 -4
- package/dist/client/index.js +4 -7
- package/dist/client/protocol.d.ts +138 -102
- package/dist/client/protocol.js +336 -7
- package/dist/client/stream.d.ts +19 -37
- package/dist/client/stream.js +46 -138
- package/dist/common/binary.d.ts +6 -5
- package/dist/common/binary.js +9 -22
- package/dist/common/blob.d.ts +8 -15
- package/dist/common/blob.js +30 -55
- package/dist/common/enums.d.ts +7 -17
- package/dist/common/enums.js +14 -34
- package/dist/common/index.d.ts +0 -2
- package/dist/common/index.js +4 -7
- package/dist/common/types.d.ts +24 -5
- package/dist/common/types.js +0 -1
- package/dist/server/api.d.ts +33 -0
- package/dist/server/api.js +7 -0
- package/dist/server/connection.d.ts +25 -0
- package/dist/server/connection.js +22 -0
- package/dist/server/constants.d.ts +4 -0
- package/dist/server/constants.js +2 -0
- package/dist/server/format.d.ts +23 -17
- package/dist/server/format.js +8 -13
- package/dist/server/index.d.ts +6 -4
- package/dist/server/index.js +11 -9
- package/dist/server/injectables.d.ts +14 -0
- package/dist/server/injectables.js +22 -0
- package/dist/server/protocol.d.ts +114 -88
- package/dist/server/protocol.js +354 -5
- package/dist/server/registry.d.ts +3 -0
- package/dist/server/registry.js +3 -0
- package/dist/server/stream.d.ts +0 -5
- package/dist/server/stream.js +2 -31
- package/dist/server/transport.d.ts +23 -0
- package/dist/server/transport.js +3 -0
- package/dist/server/types.d.ts +8 -29
- package/dist/server/types.js +0 -1
- package/dist/server/utils.d.ts +6 -3
- package/dist/server/utils.js +4 -5
- package/package.json +24 -17
- package/dist/client/format.js.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/client/protocol.js.map +0 -1
- package/dist/client/stream.js.map +0 -1
- package/dist/client/versions/v1.d.ts +0 -108
- package/dist/client/versions/v1.js +0 -128
- package/dist/client/versions/v1.js.map +0 -1
- package/dist/common/binary.js.map +0 -1
- package/dist/common/blob.js.map +0 -1
- package/dist/common/constants.d.ts +0 -2
- package/dist/common/constants.js +0 -2
- package/dist/common/constants.js.map +0 -1
- package/dist/common/enums.js.map +0 -1
- package/dist/common/index.js.map +0 -1
- package/dist/common/types.js.map +0 -1
- package/dist/common/utils.d.ts +0 -2
- package/dist/common/utils.js +0 -7
- package/dist/common/utils.js.map +0 -1
- package/dist/server/format.js.map +0 -1
- package/dist/server/index.js.map +0 -1
- package/dist/server/protocol.js.map +0 -1
- package/dist/server/stream.js.map +0 -1
- package/dist/server/types.js.map +0 -1
- package/dist/server/utils.js.map +0 -1
- package/dist/server/versions/v1.d.ts +0 -77
- package/dist/server/versions/v1.js +0 -119
- package/dist/server/versions/v1.js.map +0 -1
- package/src/client/format.ts +0 -49
- package/src/client/index.ts +0 -8
- package/src/client/protocol.ts +0 -107
- package/src/client/stream.ts +0 -222
- package/src/client/versions/v1.ts +0 -205
- package/src/common/binary.ts +0 -70
- package/src/common/blob.ts +0 -94
- package/src/common/constants.ts +0 -2
- package/src/common/enums.ts +0 -62
- package/src/common/index.ts +0 -6
- package/src/common/types.ts +0 -18
- package/src/common/utils.ts +0 -12
- package/src/server/format.ts +0 -117
- package/src/server/index.ts +0 -10
- package/src/server/protocol.ts +0 -97
- package/src/server/stream.ts +0 -72
- package/src/server/types.ts +0 -42
- package/src/server/utils.ts +0 -22
- package/src/server/versions/v1.ts +0 -198
package/dist/client/protocol.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
1
|
+
import { createPromise } from '@nmtjs/common';
|
|
2
|
+
import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
|
|
3
|
+
import { ClientMessageType, ErrorCode, ServerMessageType, } from "../common/enums.js";
|
|
4
|
+
import { EventEmitter } from "./events.js";
|
|
5
|
+
import { ProtocolClientBlobStream, ProtocolServerBlobStream, ProtocolServerStream, } from "./stream.js";
|
|
7
6
|
export class ProtocolError extends Error {
|
|
8
7
|
code;
|
|
9
8
|
data;
|
|
@@ -22,4 +21,334 @@ export class ProtocolError extends Error {
|
|
|
22
21
|
return { code: this.code, message: this.message, data: this.data };
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
|
-
|
|
24
|
+
export class ProtocolClientStreams {
|
|
25
|
+
#collection = new Map();
|
|
26
|
+
get(streamId) {
|
|
27
|
+
const stream = this.#collection.get(streamId);
|
|
28
|
+
if (!stream)
|
|
29
|
+
throw new Error('Stream not found');
|
|
30
|
+
return stream;
|
|
31
|
+
}
|
|
32
|
+
add(source, streamId, metadata) {
|
|
33
|
+
const stream = new ProtocolClientBlobStream(source, streamId, metadata);
|
|
34
|
+
this.#collection.set(streamId, stream);
|
|
35
|
+
return stream;
|
|
36
|
+
}
|
|
37
|
+
remove(streamId) {
|
|
38
|
+
this.#collection.delete(streamId);
|
|
39
|
+
}
|
|
40
|
+
abort(streamId, error) {
|
|
41
|
+
const stream = this.get(streamId);
|
|
42
|
+
stream.abort(error);
|
|
43
|
+
this.remove(streamId);
|
|
44
|
+
}
|
|
45
|
+
pull(streamId, size) {
|
|
46
|
+
const stream = this.get(streamId);
|
|
47
|
+
return stream.read(size);
|
|
48
|
+
}
|
|
49
|
+
end(streamId) {
|
|
50
|
+
this.get(streamId).end();
|
|
51
|
+
this.remove(streamId);
|
|
52
|
+
}
|
|
53
|
+
clear(error) {
|
|
54
|
+
if (error) {
|
|
55
|
+
for (const stream of this.#collection.values()) {
|
|
56
|
+
stream.abort(error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
this.#collection.clear();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export class ProtocolServerStreams {
|
|
63
|
+
#collection = new Map();
|
|
64
|
+
has(streamId) {
|
|
65
|
+
return this.#collection.has(streamId);
|
|
66
|
+
}
|
|
67
|
+
get(streamId) {
|
|
68
|
+
const stream = this.#collection.get(streamId);
|
|
69
|
+
if (!stream)
|
|
70
|
+
throw new Error('Stream not found');
|
|
71
|
+
return stream;
|
|
72
|
+
}
|
|
73
|
+
add(streamId, stream) {
|
|
74
|
+
this.#collection.set(streamId, stream);
|
|
75
|
+
return stream;
|
|
76
|
+
}
|
|
77
|
+
remove(streamId) {
|
|
78
|
+
this.#collection.delete(streamId);
|
|
79
|
+
}
|
|
80
|
+
abort(streamId) {
|
|
81
|
+
if (this.has(streamId)) {
|
|
82
|
+
const stream = this.get(streamId);
|
|
83
|
+
stream.abort();
|
|
84
|
+
this.remove(streamId);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async push(streamId, chunk) {
|
|
88
|
+
const stream = this.get(streamId);
|
|
89
|
+
return await stream.push(chunk);
|
|
90
|
+
}
|
|
91
|
+
end(streamId) {
|
|
92
|
+
const stream = this.get(streamId);
|
|
93
|
+
stream.end();
|
|
94
|
+
this.remove(streamId);
|
|
95
|
+
}
|
|
96
|
+
clear(error) {
|
|
97
|
+
if (error) {
|
|
98
|
+
for (const stream of this.#collection.values()) {
|
|
99
|
+
stream.abort(error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.#collection.clear();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export var ProtocolTransportStatus;
|
|
106
|
+
(function (ProtocolTransportStatus) {
|
|
107
|
+
ProtocolTransportStatus["CONNECTED"] = "CONNECTED";
|
|
108
|
+
ProtocolTransportStatus["DISCONNECTED"] = "DISCONNECTED";
|
|
109
|
+
ProtocolTransportStatus["CONNECTING"] = "CONNECTING";
|
|
110
|
+
})(ProtocolTransportStatus || (ProtocolTransportStatus = {}));
|
|
111
|
+
export class ProtocolTransport extends EventEmitter {
|
|
112
|
+
options;
|
|
113
|
+
status = ProtocolTransportStatus.DISCONNECTED;
|
|
114
|
+
constructor(options) {
|
|
115
|
+
super();
|
|
116
|
+
this.options = options;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export class ProtocolBaseTransformer {
|
|
120
|
+
encodeRPC(_procedure, payload) {
|
|
121
|
+
return payload;
|
|
122
|
+
}
|
|
123
|
+
decodeRPC(_procedure, payload) {
|
|
124
|
+
return payload;
|
|
125
|
+
}
|
|
126
|
+
decodeRPCChunk(_procedure, payload) {
|
|
127
|
+
return payload;
|
|
128
|
+
}
|
|
129
|
+
decodeEvent(_event, payload) {
|
|
130
|
+
return payload;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export class BaseProtocol extends EventEmitter {
|
|
134
|
+
format;
|
|
135
|
+
clientStreams = new ProtocolClientStreams();
|
|
136
|
+
serverStreams = new ProtocolServerStreams();
|
|
137
|
+
rpcStreams = new ProtocolServerStreams();
|
|
138
|
+
calls = new Map();
|
|
139
|
+
callId = 0;
|
|
140
|
+
streamId = 0;
|
|
141
|
+
constructor(format) {
|
|
142
|
+
super();
|
|
143
|
+
this.format = format;
|
|
144
|
+
}
|
|
145
|
+
get contentType() {
|
|
146
|
+
return this.format.contentType;
|
|
147
|
+
}
|
|
148
|
+
handleCallResponse(callId, call, response, transformer) {
|
|
149
|
+
if (response.error) {
|
|
150
|
+
call.reject(new ProtocolError(response.error.code, response.error.message, response.error.data));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
try {
|
|
154
|
+
const transformed = transformer.decodeRPC(call.procedure, response.result);
|
|
155
|
+
if (response.stream)
|
|
156
|
+
call.resolve({ result: transformed, stream: response.stream });
|
|
157
|
+
else
|
|
158
|
+
call.resolve(transformed);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
call.reject(new ProtocolError(ErrorCode.ClientRequestError, 'Unable to decode response', error));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
this.calls.delete(callId);
|
|
165
|
+
}
|
|
166
|
+
handleRpcResponse({ callId, error, result, streams }, transformer, stream) {
|
|
167
|
+
const call = this.calls.get(callId);
|
|
168
|
+
if (!call)
|
|
169
|
+
throw new Error('Call not found');
|
|
170
|
+
for (const key in streams) {
|
|
171
|
+
const stream = streams[key];
|
|
172
|
+
this.serverStreams.add(stream.id, stream);
|
|
173
|
+
}
|
|
174
|
+
this.handleCallResponse(callId, call, error ? { error } : { result, stream }, transformer);
|
|
175
|
+
return call;
|
|
176
|
+
}
|
|
177
|
+
handleRpcStreamResponse(response, stream, transformer) {
|
|
178
|
+
const call = this.handleRpcResponse(response, transformer, stream);
|
|
179
|
+
this.rpcStreams.add(response.callId, stream);
|
|
180
|
+
return call;
|
|
181
|
+
}
|
|
182
|
+
createCall(procedure, options) {
|
|
183
|
+
const timeoutSignal = AbortSignal.timeout(options.timeout);
|
|
184
|
+
const signal = options.signal
|
|
185
|
+
? AbortSignal.any([options.signal, timeoutSignal])
|
|
186
|
+
: timeoutSignal;
|
|
187
|
+
const call = Object.assign(createPromise(), { procedure, signal });
|
|
188
|
+
timeoutSignal.addEventListener('abort', () => {
|
|
189
|
+
const error = new ProtocolError(ErrorCode.RequestTimeout, 'Request timeout');
|
|
190
|
+
call.reject(error);
|
|
191
|
+
}, { once: true });
|
|
192
|
+
return call;
|
|
193
|
+
}
|
|
194
|
+
createRpc(procedure, payload, options, transformer) {
|
|
195
|
+
const callId = ++this.callId;
|
|
196
|
+
const call = this.createCall(procedure, options);
|
|
197
|
+
const { buffer, streams } = this.format.encodeRPC({ callId, procedure, payload: transformer.encodeRPC(procedure, payload) }, {
|
|
198
|
+
addStream: (blob) => {
|
|
199
|
+
const streamId = ++this.streamId;
|
|
200
|
+
return this.clientStreams.add(blob.source, streamId, blob.metadata);
|
|
201
|
+
},
|
|
202
|
+
getStream: (id) => {
|
|
203
|
+
const stream = this.clientStreams.get(id);
|
|
204
|
+
return stream;
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
this.calls.set(callId, call);
|
|
208
|
+
return { callId, call, streams, buffer };
|
|
209
|
+
}
|
|
210
|
+
pushRpcStream(callId, chunk) {
|
|
211
|
+
this.rpcStreams.push(callId, chunk);
|
|
212
|
+
}
|
|
213
|
+
endRpcStream(callId) {
|
|
214
|
+
this.rpcStreams.end(callId);
|
|
215
|
+
}
|
|
216
|
+
abortRpcStream(callId) {
|
|
217
|
+
this.rpcStreams.abort(callId);
|
|
218
|
+
}
|
|
219
|
+
removeClientStream(streamId) {
|
|
220
|
+
this.clientStreams.remove(streamId);
|
|
221
|
+
}
|
|
222
|
+
pullClientStream(streamId, size) {
|
|
223
|
+
return this.clientStreams.pull(streamId, size);
|
|
224
|
+
}
|
|
225
|
+
endClientStream(streamId) {
|
|
226
|
+
this.clientStreams.end(streamId);
|
|
227
|
+
}
|
|
228
|
+
abortClientStream(streamId, error) {
|
|
229
|
+
this.clientStreams.abort(streamId, error);
|
|
230
|
+
}
|
|
231
|
+
addServerStream(stream) {
|
|
232
|
+
this.serverStreams.add(stream.id, stream);
|
|
233
|
+
}
|
|
234
|
+
removeServerStream(streamId) {
|
|
235
|
+
this.serverStreams.remove(streamId);
|
|
236
|
+
}
|
|
237
|
+
pushServerStream(streamId, chunk) {
|
|
238
|
+
return this.serverStreams.push(streamId, chunk);
|
|
239
|
+
}
|
|
240
|
+
endServerStream(streamId) {
|
|
241
|
+
this.serverStreams.end(streamId);
|
|
242
|
+
}
|
|
243
|
+
abortServerStream(streamId, _error) {
|
|
244
|
+
this.serverStreams.abort(streamId);
|
|
245
|
+
}
|
|
246
|
+
emitEvent(event, payload, transformer) {
|
|
247
|
+
const transformed = transformer.decodeEvent(event, payload);
|
|
248
|
+
this.emit(event,
|
|
249
|
+
//@ts-expect-error
|
|
250
|
+
transformed);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
export class Protocol extends BaseProtocol {
|
|
254
|
+
handleServerMessage(buffer, transport, transformer) {
|
|
255
|
+
const type = decodeNumber(buffer, 'Uint8');
|
|
256
|
+
const messageBuffer = buffer.slice(Uint8Array.BYTES_PER_ELEMENT);
|
|
257
|
+
if (type in ServerMessageType) {
|
|
258
|
+
const messageType = type;
|
|
259
|
+
if (typeof ServerMessageType[messageType] !== 'undefined') {
|
|
260
|
+
this[messageType](messageBuffer, transport, transformer);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
throw new Error(`Unknown message type: ${messageType}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
[ServerMessageType.Event](buffer, _transport, transformer) {
|
|
268
|
+
const [event, payload] = this.format.decode(buffer);
|
|
269
|
+
this.emitEvent(event, payload, transformer);
|
|
270
|
+
}
|
|
271
|
+
[ServerMessageType.RpcResponse](buffer, transport, transformer) {
|
|
272
|
+
const response = this.format.decodeRPC(buffer, {
|
|
273
|
+
addStream: (id, callId, metadata) => {
|
|
274
|
+
return new ProtocolServerBlobStream(id, metadata, {
|
|
275
|
+
start: () => {
|
|
276
|
+
transport.send(ClientMessageType.ServerStreamPull, encodeNumber(id, 'Uint32'), { callId, streamId: id });
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
},
|
|
280
|
+
getStream: (id) => {
|
|
281
|
+
return this.serverStreams.get(id);
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
this.handleRpcResponse(response, transformer);
|
|
285
|
+
}
|
|
286
|
+
[ServerMessageType.RpcStreamResponse](buffer, transport, transformer) {
|
|
287
|
+
const response = this.format.decodeRPC(buffer, {
|
|
288
|
+
addStream: (id, callId, metadata) => {
|
|
289
|
+
return new ProtocolServerBlobStream(id, metadata, {
|
|
290
|
+
start: () => {
|
|
291
|
+
transport.send(ClientMessageType.ServerStreamPull, encodeNumber(id, 'Uint32'), { callId, streamId: id });
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
},
|
|
295
|
+
getStream: (id) => {
|
|
296
|
+
return this.serverStreams.get(id);
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
const stream = new ProtocolServerStream({
|
|
300
|
+
transform: (chunk, controller) => {
|
|
301
|
+
const transformed = transformer.decodeRPCChunk(call.procedure, chunk);
|
|
302
|
+
controller.enqueue(transformed);
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
const call = this.handleRpcStreamResponse(response, stream, transformer);
|
|
306
|
+
}
|
|
307
|
+
[ServerMessageType.RpcStreamChunk](buffer, _transport, _transformer) {
|
|
308
|
+
const callId = decodeNumber(buffer, 'Uint32');
|
|
309
|
+
const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
|
|
310
|
+
const payload = this.format.decode(chunk);
|
|
311
|
+
this.pushRpcStream(callId, payload);
|
|
312
|
+
}
|
|
313
|
+
[ServerMessageType.RpcStreamEnd](buffer, _transport, _transformer) {
|
|
314
|
+
const callId = decodeNumber(buffer, 'Uint32');
|
|
315
|
+
this.endRpcStream(callId);
|
|
316
|
+
}
|
|
317
|
+
[ServerMessageType.RpcStreamAbort](buffer, _transport, _transformer) {
|
|
318
|
+
const callId = decodeNumber(buffer, 'Uint32');
|
|
319
|
+
this.abortRpcStream(callId);
|
|
320
|
+
}
|
|
321
|
+
[ServerMessageType.ServerStreamPush](buffer, transport, _transformer) {
|
|
322
|
+
const streamId = decodeNumber(buffer, 'Uint32');
|
|
323
|
+
const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
|
|
324
|
+
this.pushServerStream(streamId, chunk);
|
|
325
|
+
transport.send(ClientMessageType.ServerStreamPull, encodeNumber(streamId, 'Uint32'), { streamId });
|
|
326
|
+
}
|
|
327
|
+
[ServerMessageType.ServerStreamEnd](buffer, _transport, _transformer) {
|
|
328
|
+
const streamId = decodeNumber(buffer, 'Uint32');
|
|
329
|
+
this.endServerStream(streamId);
|
|
330
|
+
}
|
|
331
|
+
[ServerMessageType.ServerStreamAbort](buffer, _transport, _transformer) {
|
|
332
|
+
const streamId = decodeNumber(buffer, 'Uint32');
|
|
333
|
+
this.abortServerStream(streamId);
|
|
334
|
+
}
|
|
335
|
+
[ServerMessageType.ClientStreamPull](buffer, transport, _transformer) {
|
|
336
|
+
const streamId = decodeNumber(buffer, 'Uint32');
|
|
337
|
+
const size = decodeNumber(buffer, 'Uint32', Uint32Array.BYTES_PER_ELEMENT);
|
|
338
|
+
this.pullClientStream(streamId, size).then((chunk) => {
|
|
339
|
+
if (chunk) {
|
|
340
|
+
transport.send(ClientMessageType.ClientStreamPush, concat(encodeNumber(streamId, 'Uint32'), chunk), { streamId });
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
transport.send(ClientMessageType.ClientStreamEnd, encodeNumber(streamId, 'Uint32'), { streamId });
|
|
344
|
+
this.endClientStream(streamId);
|
|
345
|
+
}
|
|
346
|
+
}, () => {
|
|
347
|
+
transport.send(ClientMessageType.ClientStreamAbort, encodeNumber(streamId, 'Uint32'), { streamId });
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
[ServerMessageType.ClientStreamAbort](buffer, _transport, _transformer) {
|
|
351
|
+
const streamId = decodeNumber(buffer, 'Uint32');
|
|
352
|
+
this.abortClientStream(streamId);
|
|
353
|
+
}
|
|
354
|
+
}
|
package/dist/client/stream.d.ts
CHANGED
|
@@ -1,49 +1,31 @@
|
|
|
1
|
-
import type { Callback, DuplexStreamOptions } from '@nmtjs/common';
|
|
2
|
-
import { DuplexStream } from '@nmtjs/common';
|
|
3
1
|
import type { ProtocolBlobInterface, ProtocolBlobMetadata } from '../common/blob.ts';
|
|
4
|
-
import {
|
|
5
|
-
export declare class ProtocolClientBlobStream extends
|
|
2
|
+
import { BlobKey } from '../common/blob.ts';
|
|
3
|
+
export declare class ProtocolClientBlobStream extends TransformStream<any, ArrayBuffer> implements ProtocolBlobInterface {
|
|
6
4
|
#private;
|
|
7
5
|
readonly source: ReadableStream;
|
|
8
6
|
readonly id: number;
|
|
9
7
|
readonly metadata: ProtocolBlobMetadata;
|
|
10
|
-
readonly [
|
|
8
|
+
readonly [BlobKey] = true;
|
|
11
9
|
constructor(source: ReadableStream, id: number, metadata: ProtocolBlobMetadata);
|
|
12
|
-
|
|
10
|
+
read(size: number): Promise<ArrayBuffer | null>;
|
|
11
|
+
abort(error?: Error): void;
|
|
13
12
|
end(): Promise<void>;
|
|
14
|
-
read(size: number): Promise<Uint8Array<ArrayBufferLike> | null>;
|
|
15
13
|
}
|
|
16
|
-
export
|
|
17
|
-
[Symbol.asyncIterator](): AsyncGenerator<
|
|
14
|
+
export interface ProtocolServerStreamInterface<T = any> {
|
|
15
|
+
[Symbol.asyncIterator](): AsyncGenerator<T>;
|
|
16
|
+
abort(error?: Error): void;
|
|
18
17
|
}
|
|
19
|
-
export declare class ProtocolServerStream<T =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
throw(error: any): Promise<IteratorResult<Awaited<T>, void>>;
|
|
27
|
-
};
|
|
28
|
-
};
|
|
18
|
+
export declare class ProtocolServerStream<T = any> extends TransformStream<any, T> implements ProtocolServerStreamInterface<T> {
|
|
19
|
+
#private;
|
|
20
|
+
constructor(options?: Transformer<any, T>);
|
|
21
|
+
[Symbol.asyncIterator](): AsyncGenerator<Awaited<T>, void, unknown>;
|
|
22
|
+
push(chunk: T): Promise<void>;
|
|
23
|
+
end(): Promise<void>;
|
|
24
|
+
abort(error?: Error): Promise<void>;
|
|
29
25
|
}
|
|
30
|
-
export declare class ProtocolServerBlobStream extends
|
|
26
|
+
export declare class ProtocolServerBlobStream extends ProtocolServerStream<ArrayBuffer> implements ProtocolBlobInterface {
|
|
27
|
+
readonly id: number;
|
|
31
28
|
readonly metadata: ProtocolBlobMetadata;
|
|
32
|
-
readonly [
|
|
33
|
-
constructor(metadata: ProtocolBlobMetadata, options?:
|
|
34
|
-
get size(): number;
|
|
35
|
-
get type(): string;
|
|
36
|
-
text(): Promise<string>;
|
|
37
|
-
bytes(): Promise<Uint8Array<ArrayBuffer>>;
|
|
38
|
-
arrayBuffer(): Promise<ArrayBuffer>;
|
|
39
|
-
json<T = unknown>(): Promise<T>;
|
|
40
|
-
stream(): ReadableStream<Uint8Array<ArrayBuffer>>;
|
|
41
|
-
/**
|
|
42
|
-
* Throws an error
|
|
43
|
-
*/
|
|
44
|
-
formData(): Promise<FormData>;
|
|
45
|
-
/**
|
|
46
|
-
* Throws an error
|
|
47
|
-
*/
|
|
48
|
-
slice(): Blob;
|
|
29
|
+
readonly [BlobKey] = true;
|
|
30
|
+
constructor(id: number, metadata: ProtocolBlobMetadata, options?: Transformer<any, ArrayBuffer>);
|
|
49
31
|
}
|
package/dist/client/stream.js
CHANGED
|
@@ -1,71 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { concat,
|
|
3
|
-
import {
|
|
4
|
-
export class ProtocolClientBlobStream extends
|
|
1
|
+
import { defer } from '@nmtjs/common';
|
|
2
|
+
import { concat, encodeText } from "../common/binary.js";
|
|
3
|
+
import { BlobKey } from "../common/blob.js";
|
|
4
|
+
export class ProtocolClientBlobStream extends TransformStream {
|
|
5
5
|
source;
|
|
6
6
|
id;
|
|
7
7
|
metadata;
|
|
8
|
-
[
|
|
8
|
+
[BlobKey] = true;
|
|
9
9
|
#queue;
|
|
10
10
|
#reader;
|
|
11
|
-
#sourceReader = null;
|
|
12
11
|
constructor(source, id, metadata) {
|
|
13
|
-
let sourceReader = null;
|
|
14
12
|
super({
|
|
15
13
|
start: () => {
|
|
16
|
-
|
|
14
|
+
defer(() => source.pipeThrough(this));
|
|
17
15
|
},
|
|
18
|
-
|
|
19
|
-
const { done, value } = await sourceReader.read();
|
|
20
|
-
if (done) {
|
|
21
|
-
controller.close();
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const chunk = value;
|
|
25
|
-
controller.enqueue(chunk instanceof Uint8Array
|
|
26
|
-
? chunk
|
|
27
|
-
: new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
28
|
-
},
|
|
29
|
-
transform: (chunk) => {
|
|
16
|
+
transform: (chunk, controller) => {
|
|
30
17
|
if (chunk instanceof ArrayBuffer) {
|
|
31
|
-
|
|
18
|
+
controller.enqueue(chunk);
|
|
32
19
|
}
|
|
33
20
|
else if (chunk instanceof Uint8Array) {
|
|
34
|
-
|
|
21
|
+
controller.enqueue(chunk.buffer);
|
|
35
22
|
}
|
|
36
23
|
else if (typeof chunk === 'string') {
|
|
37
|
-
|
|
24
|
+
controller.enqueue(encodeText(chunk));
|
|
38
25
|
}
|
|
39
26
|
else {
|
|
40
27
|
throw new Error('Invalid chunk data type. Expected ArrayBuffer, Uint8Array, or string.');
|
|
41
28
|
}
|
|
42
29
|
},
|
|
43
|
-
cancel: (reason) => {
|
|
44
|
-
// Use reader.cancel() if reader exists (stream is locked), otherwise source.cancel()
|
|
45
|
-
if (sourceReader) {
|
|
46
|
-
sourceReader.cancel(reason);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
source.cancel(reason);
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
30
|
});
|
|
53
31
|
this.source = source;
|
|
54
32
|
this.id = id;
|
|
55
33
|
this.metadata = metadata;
|
|
56
|
-
this.#queue = new
|
|
34
|
+
this.#queue = new ArrayBuffer(0);
|
|
57
35
|
this.#reader = this.readable.getReader();
|
|
58
|
-
this.#sourceReader = sourceReader;
|
|
59
|
-
}
|
|
60
|
-
async abort(reason = 'Stream aborted') {
|
|
61
|
-
await this.#reader.cancel(reason);
|
|
62
|
-
this.#reader.releaseLock();
|
|
63
|
-
this.#sourceReader?.releaseLock();
|
|
64
|
-
}
|
|
65
|
-
async end() {
|
|
66
|
-
// Release the reader lock when the stream is finished
|
|
67
|
-
this.#reader.releaseLock();
|
|
68
|
-
this.#sourceReader?.releaseLock();
|
|
69
36
|
}
|
|
70
37
|
async read(size) {
|
|
71
38
|
while (this.#queue.byteLength < size) {
|
|
@@ -73,7 +40,7 @@ export class ProtocolClientBlobStream extends DuplexStream {
|
|
|
73
40
|
if (done) {
|
|
74
41
|
if (this.#queue.byteLength > 0) {
|
|
75
42
|
const chunk = this.#queue;
|
|
76
|
-
this.#queue = new
|
|
43
|
+
this.#queue = new ArrayBuffer(0);
|
|
77
44
|
return chunk;
|
|
78
45
|
}
|
|
79
46
|
return null;
|
|
@@ -81,110 +48,51 @@ export class ProtocolClientBlobStream extends DuplexStream {
|
|
|
81
48
|
const buffer = value;
|
|
82
49
|
this.#queue = concat(this.#queue, buffer);
|
|
83
50
|
}
|
|
84
|
-
const chunk = this.#queue.
|
|
85
|
-
this.#queue = this.#queue.
|
|
51
|
+
const chunk = this.#queue.slice(0, size);
|
|
52
|
+
this.#queue = this.#queue.slice(size);
|
|
86
53
|
return chunk;
|
|
87
54
|
}
|
|
55
|
+
abort(error = new Error('Stream aborted')) {
|
|
56
|
+
this.#reader.cancel(error);
|
|
57
|
+
this.source.cancel(error);
|
|
58
|
+
}
|
|
59
|
+
end() {
|
|
60
|
+
return this.source.cancel('Stream ended');
|
|
61
|
+
}
|
|
88
62
|
}
|
|
89
|
-
export class
|
|
63
|
+
export class ProtocolServerStream extends TransformStream {
|
|
64
|
+
#writer;
|
|
65
|
+
constructor(options) {
|
|
66
|
+
super(options);
|
|
67
|
+
this.#writer = this.writable.getWriter();
|
|
68
|
+
}
|
|
90
69
|
async *[Symbol.asyncIterator]() {
|
|
91
70
|
const reader = this.readable.getReader();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
finally {
|
|
102
|
-
reader.releaseLock();
|
|
71
|
+
while (true) {
|
|
72
|
+
const { done, value } = await reader.read();
|
|
73
|
+
if (!done)
|
|
74
|
+
yield value;
|
|
75
|
+
else
|
|
76
|
+
break;
|
|
103
77
|
}
|
|
104
78
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
async next() {
|
|
115
|
-
const result = await iterator.next();
|
|
116
|
-
if (result.done)
|
|
117
|
-
onDone();
|
|
118
|
-
return result;
|
|
119
|
-
},
|
|
120
|
-
async return(value) {
|
|
121
|
-
onDone();
|
|
122
|
-
return iterator.return?.(value) ?? { done: true, value };
|
|
123
|
-
},
|
|
124
|
-
async throw(error) {
|
|
125
|
-
onDone();
|
|
126
|
-
return iterator.throw?.(error) ?? Promise.reject(error);
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
};
|
|
79
|
+
async push(chunk) {
|
|
80
|
+
await this.#writer.write(chunk);
|
|
81
|
+
}
|
|
82
|
+
async end() {
|
|
83
|
+
await this.#writer.close();
|
|
84
|
+
}
|
|
85
|
+
async abort(error = new Error('Stream aborted')) {
|
|
86
|
+
await this.#writer.abort(error);
|
|
131
87
|
}
|
|
132
88
|
}
|
|
133
|
-
export class ProtocolServerBlobStream extends
|
|
89
|
+
export class ProtocolServerBlobStream extends ProtocolServerStream {
|
|
90
|
+
id;
|
|
134
91
|
metadata;
|
|
135
|
-
[
|
|
136
|
-
constructor(metadata, options) {
|
|
92
|
+
[BlobKey] = true;
|
|
93
|
+
constructor(id, metadata, options) {
|
|
137
94
|
super(options);
|
|
95
|
+
this.id = id;
|
|
138
96
|
this.metadata = metadata;
|
|
139
97
|
}
|
|
140
|
-
get size() {
|
|
141
|
-
return this.metadata.size || Number.NaN;
|
|
142
|
-
}
|
|
143
|
-
get type() {
|
|
144
|
-
return this.metadata.type || 'application/octet-stream';
|
|
145
|
-
}
|
|
146
|
-
async text() {
|
|
147
|
-
const chunks = [];
|
|
148
|
-
for await (const chunk of this)
|
|
149
|
-
chunks.push(chunk);
|
|
150
|
-
return decodeText(concat(...chunks));
|
|
151
|
-
}
|
|
152
|
-
async bytes() {
|
|
153
|
-
const chunks = [];
|
|
154
|
-
for await (const chunk of this)
|
|
155
|
-
chunks.push(chunk);
|
|
156
|
-
return concat(...chunks);
|
|
157
|
-
}
|
|
158
|
-
async arrayBuffer() {
|
|
159
|
-
const bytes = await this.bytes();
|
|
160
|
-
return bytes.buffer;
|
|
161
|
-
}
|
|
162
|
-
async json() {
|
|
163
|
-
const text = await this.text();
|
|
164
|
-
return JSON.parse(text);
|
|
165
|
-
}
|
|
166
|
-
stream() {
|
|
167
|
-
const transform = new TransformStream({
|
|
168
|
-
transform: (chunk, controller) => {
|
|
169
|
-
controller.enqueue(chunk instanceof Uint8Array
|
|
170
|
-
? chunk
|
|
171
|
-
: new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
172
|
-
},
|
|
173
|
-
});
|
|
174
|
-
this.readable.pipeThrough(transform);
|
|
175
|
-
return transform.readable;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Throws an error
|
|
179
|
-
*/
|
|
180
|
-
async formData() {
|
|
181
|
-
throw new Error('Method not implemented.');
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Throws an error
|
|
185
|
-
*/
|
|
186
|
-
slice() {
|
|
187
|
-
throw new Error('Unable to slice');
|
|
188
|
-
}
|
|
189
98
|
}
|
|
190
|
-
//# sourceMappingURL=stream.js.map
|
package/dist/common/binary.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
declare const utf8decoder: TextDecoder;
|
|
1
2
|
export type BinaryTypes = {
|
|
2
3
|
Int8: number;
|
|
3
4
|
Int16: number;
|
|
@@ -11,8 +12,8 @@ export type BinaryTypes = {
|
|
|
11
12
|
BigUint64: bigint;
|
|
12
13
|
};
|
|
13
14
|
export declare const encodeNumber: <T extends keyof BinaryTypes>(value: BinaryTypes[T], type: T, littleEndian?: boolean) => ArrayBuffer;
|
|
14
|
-
export declare const decodeNumber: <T extends keyof BinaryTypes>(buffer: ArrayBuffer
|
|
15
|
-
export declare const encodeText: (text: string) =>
|
|
16
|
-
export declare const decodeText: (buffer:
|
|
17
|
-
export declare const concat: (...buffers:
|
|
18
|
-
export
|
|
15
|
+
export declare const decodeNumber: <T extends keyof BinaryTypes>(buffer: ArrayBuffer, type: T, offset?: number, littleEndian?: boolean) => BinaryTypes[T];
|
|
16
|
+
export declare const encodeText: (text: string) => ArrayBuffer;
|
|
17
|
+
export declare const decodeText: (buffer: Parameters<typeof utf8decoder.decode>[0]) => string;
|
|
18
|
+
export declare const concat: (...buffers: ArrayBuffer[]) => ArrayBuffer;
|
|
19
|
+
export {};
|