@nmtjs/protocol 0.8.0 → 0.9.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.
- package/dist/client/events.js +2 -0
- package/dist/client/events.js.map +1 -1
- package/dist/client/format.js +2 -0
- package/dist/client/format.js.map +1 -1
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/protocol.js +205 -199
- package/dist/client/protocol.js.map +1 -1
- package/dist/client/stream.js +9 -12
- package/dist/client/stream.js.map +1 -1
- package/dist/client/types.js +3 -0
- package/dist/client/types.js.map +1 -0
- package/dist/common/binary.js +2 -0
- package/dist/common/binary.js.map +1 -1
- package/dist/common/blob.js +6 -2
- package/dist/common/blob.js.map +1 -1
- package/dist/common/enums.js +4 -1
- package/dist/common/enums.js.map +1 -1
- package/dist/common/index.js +2 -0
- package/dist/common/index.js.map +1 -1
- package/dist/common/types.js +2 -0
- package/dist/common/types.js.map +1 -1
- package/dist/server/api.js +4 -1
- package/dist/server/api.js.map +1 -1
- package/dist/server/connection.js +2 -0
- package/dist/server/connection.js.map +1 -1
- package/dist/server/constants.js +2 -0
- package/dist/server/constants.js.map +1 -1
- package/dist/server/format.js +2 -0
- package/dist/server/format.js.map +1 -1
- package/dist/server/index.js +3 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/injectables.js +2 -0
- package/dist/server/injectables.js.map +1 -1
- package/dist/server/protocol.js +154 -55
- package/dist/server/protocol.js.map +1 -1
- package/dist/server/registry.js +2 -0
- package/dist/server/registry.js.map +1 -1
- package/dist/server/stream.js +3 -1
- package/dist/server/stream.js.map +1 -1
- package/dist/server/transport.js +2 -0
- package/dist/server/transport.js.map +1 -1
- package/dist/server/types.js +3 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils.js +7 -2
- package/dist/server/utils.js.map +1 -1
- package/package.json +7 -7
- package/src/client/format.ts +34 -5
- package/src/client/index.ts +2 -0
- package/src/client/protocol.ts +381 -274
- package/src/client/stream.ts +7 -14
- package/src/client/types.ts +14 -0
- package/src/common/blob.ts +10 -3
- package/src/common/enums.ts +3 -1
- package/src/common/types.ts +28 -47
- package/src/server/api.ts +15 -1
- package/src/server/connection.ts +1 -5
- package/src/server/format.ts +14 -4
- package/src/server/index.ts +1 -0
- package/src/server/protocol.ts +208 -66
- package/src/server/stream.ts +2 -7
- package/src/server/transport.ts +5 -1
- package/src/server/types.ts +21 -0
- package/src/server/utils.ts +9 -2
package/dist/server/protocol.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defer, throwError } from "@nmtjs/common";
|
|
2
2
|
import { Hook, Scope } from "@nmtjs/core";
|
|
3
3
|
import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
|
|
4
4
|
import { ErrorCode, ServerMessageType } from "../common/enums.js";
|
|
5
|
+
import { isIterableResult } from "./api.js";
|
|
5
6
|
import { Connection, ConnectionContext } from "./connection.js";
|
|
7
|
+
import { ProtocolInjectables } from "./injectables.js";
|
|
6
8
|
import { ProtocolClientStream, ProtocolServerStream } from "./stream.js";
|
|
7
9
|
import { getFormat } from "./utils.js";
|
|
8
10
|
export class ProtocolError extends Error {
|
|
@@ -42,16 +44,26 @@ export class ProtocolConnections {
|
|
|
42
44
|
const format = getFormat(this.application.format, params);
|
|
43
45
|
const container = this.application.container.fork(Scope.Connection);
|
|
44
46
|
const context = new ConnectionContext(container, format);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
container.provide(ProtocolInjectables.connection, connection);
|
|
48
|
+
try {
|
|
49
|
+
await this.initialize(connection);
|
|
50
|
+
this.#collection.set(connection.id, {
|
|
51
|
+
connection,
|
|
52
|
+
context,
|
|
53
|
+
transport
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
connection,
|
|
57
|
+
context
|
|
58
|
+
};
|
|
59
|
+
} finally {
|
|
60
|
+
container.dispose().catch((error) => {
|
|
61
|
+
this.application.logger.error({
|
|
62
|
+
error,
|
|
63
|
+
connection
|
|
64
|
+
}, "Error during disposing connection");
|
|
65
|
+
});
|
|
66
|
+
}
|
|
55
67
|
}
|
|
56
68
|
async remove(connectionId) {
|
|
57
69
|
const { connection, context } = this.get(connectionId);
|
|
@@ -79,6 +91,9 @@ export class ProtocolConnections {
|
|
|
79
91
|
}, "Error during closing connection");
|
|
80
92
|
}
|
|
81
93
|
}
|
|
94
|
+
async initialize(connection) {
|
|
95
|
+
await this.application.registry.hooks.call(Hook.OnConnect, { concurrent: false }, connection);
|
|
96
|
+
}
|
|
82
97
|
}
|
|
83
98
|
export class ProtocolClientStreams {
|
|
84
99
|
constructor(connections) {
|
|
@@ -105,11 +120,11 @@ export class ProtocolClientStreams {
|
|
|
105
120
|
}
|
|
106
121
|
push(connectionId, streamId, chunk) {
|
|
107
122
|
const stream = this.get(connectionId, streamId);
|
|
108
|
-
stream.
|
|
123
|
+
stream.write(Buffer.from(chunk));
|
|
109
124
|
}
|
|
110
125
|
end(connectionId, streamId) {
|
|
111
126
|
const stream = this.get(connectionId, streamId);
|
|
112
|
-
stream.
|
|
127
|
+
stream.end(null);
|
|
113
128
|
this.remove(connectionId, streamId);
|
|
114
129
|
}
|
|
115
130
|
abort(connectionId, streamId, error = new Error("Aborted")) {
|
|
@@ -142,6 +157,7 @@ export class ProtocolServerStreams {
|
|
|
142
157
|
serverStreams.delete(streamId);
|
|
143
158
|
}
|
|
144
159
|
pull(connectionId, streamId) {
|
|
160
|
+
console.log("Pulling stream", streamId);
|
|
145
161
|
const stream = this.get(connectionId, streamId);
|
|
146
162
|
stream.resume();
|
|
147
163
|
}
|
|
@@ -152,90 +168,120 @@ export class ProtocolServerStreams {
|
|
|
152
168
|
}
|
|
153
169
|
}
|
|
154
170
|
export class Protocol {
|
|
155
|
-
connections;
|
|
156
|
-
clientStreams;
|
|
157
|
-
serverStreams;
|
|
171
|
+
#connections;
|
|
172
|
+
#clientStreams;
|
|
173
|
+
#serverStreams;
|
|
158
174
|
constructor(application) {
|
|
159
175
|
this.application = application;
|
|
160
|
-
this
|
|
161
|
-
this
|
|
162
|
-
this
|
|
176
|
+
this.#connections = new ProtocolConnections(this.application);
|
|
177
|
+
this.#clientStreams = new ProtocolClientStreams(this.#connections);
|
|
178
|
+
this.#serverStreams = new ProtocolServerStreams(this.#connections);
|
|
179
|
+
}
|
|
180
|
+
async call(options) {
|
|
181
|
+
const { container, connection } = options;
|
|
182
|
+
try {
|
|
183
|
+
return await this.application.api.call(options);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
if (error instanceof ProtocolError === false) {
|
|
186
|
+
this.application.logger.error({
|
|
187
|
+
error,
|
|
188
|
+
connection
|
|
189
|
+
}, "Error during RPC call");
|
|
190
|
+
throw new ProtocolError(ErrorCode.InternalServerError, "Internal server error");
|
|
191
|
+
}
|
|
192
|
+
throw error;
|
|
193
|
+
} finally {
|
|
194
|
+
container.dispose().catch((error) => {
|
|
195
|
+
this.application.logger.error({
|
|
196
|
+
error,
|
|
197
|
+
connection
|
|
198
|
+
}, "Error during disposing connection's container");
|
|
199
|
+
});
|
|
200
|
+
}
|
|
163
201
|
}
|
|
164
202
|
async rpc(connectionId, rpc, params = {}) {
|
|
165
|
-
const { connection, context, transport } = this
|
|
203
|
+
const { connection, context, transport } = this.#connections.get(connectionId);
|
|
166
204
|
const { calls, format } = context;
|
|
167
205
|
const { callId, namespace, procedure, payload } = rpc;
|
|
168
206
|
const abortController = new AbortController();
|
|
169
207
|
const signal = params.signal ? AbortSignal.any([params.signal, abortController.signal]) : abortController.signal;
|
|
170
|
-
|
|
171
|
-
calls.set(callId, call);
|
|
172
|
-
call.promise.finally(() => calls.delete(callId));
|
|
208
|
+
calls.set(callId, abortController);
|
|
173
209
|
const callIdEncoded = encodeNumber(callId, "Uint32");
|
|
174
210
|
const container = context.container.fork(Scope.Call);
|
|
211
|
+
if (params.provides) {
|
|
212
|
+
for (const [key, value] of params.provides) {
|
|
213
|
+
container.provide(key, value);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
175
216
|
try {
|
|
176
|
-
const response = await this.
|
|
217
|
+
const response = await this.call({
|
|
177
218
|
connection,
|
|
178
219
|
container,
|
|
179
220
|
namespace,
|
|
180
221
|
payload,
|
|
181
222
|
procedure,
|
|
182
|
-
signal
|
|
223
|
+
signal,
|
|
224
|
+
metadata: params.metadata
|
|
183
225
|
});
|
|
184
226
|
const responseEncoded = format.encoder.encodeRPC({
|
|
185
227
|
callId,
|
|
186
|
-
|
|
228
|
+
result: response.output
|
|
187
229
|
}, {
|
|
188
230
|
addStream: (blob) => {
|
|
189
|
-
const
|
|
190
|
-
const stream = this
|
|
231
|
+
const streamId = context.streamId++;
|
|
232
|
+
const stream = this.#serverStreams.add(connectionId, streamId, blob);
|
|
191
233
|
stream.on("data", (chunk) => {
|
|
192
234
|
stream.pause();
|
|
193
235
|
const buf = Buffer.from(chunk);
|
|
194
|
-
transport.send(connection, ServerMessageType.ServerStreamPush, concat(encodeNumber(
|
|
236
|
+
transport.send(connection, ServerMessageType.ServerStreamPush, concat(encodeNumber(streamId, "Uint32"), buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)), {
|
|
237
|
+
callId,
|
|
238
|
+
streamId
|
|
239
|
+
});
|
|
195
240
|
});
|
|
196
241
|
stream.on("error", (err) => {
|
|
197
|
-
transport.send(connection, ServerMessageType.ServerStreamAbort, encodeNumber(
|
|
242
|
+
transport.send(connection, ServerMessageType.ServerStreamAbort, encodeNumber(streamId, "Uint32"), {
|
|
243
|
+
callId,
|
|
244
|
+
streamId
|
|
245
|
+
});
|
|
198
246
|
});
|
|
199
247
|
stream.on("end", () => {
|
|
200
|
-
|
|
248
|
+
console.log("Stream ended");
|
|
249
|
+
transport.send(connection, ServerMessageType.ServerStreamEnd, encodeNumber(streamId, "Uint32"), {
|
|
250
|
+
callId,
|
|
251
|
+
streamId
|
|
252
|
+
});
|
|
201
253
|
});
|
|
202
254
|
return stream;
|
|
203
255
|
},
|
|
204
256
|
getStream: (id) => {
|
|
205
|
-
return this.
|
|
257
|
+
return this.#serverStreams.get(connectionId, id);
|
|
206
258
|
}
|
|
207
259
|
});
|
|
208
260
|
if ("subscription" in response) {
|
|
209
261
|
throwError("Unimplemented");
|
|
210
|
-
} else if (
|
|
211
|
-
transport.send(connection, ServerMessageType.RpcStreamResponse, responseEncoded);
|
|
262
|
+
} else if (isIterableResult(response)) {
|
|
263
|
+
transport.send(connection, ServerMessageType.RpcStreamResponse, responseEncoded, { callId });
|
|
212
264
|
try {
|
|
213
265
|
const ab = new AbortController();
|
|
214
266
|
context.rpcStreams.set(callId, ab);
|
|
215
267
|
const iterable = typeof response.iterable === "function" ? response.iterable() : response.iterable;
|
|
216
268
|
for await (const chunk of iterable) {
|
|
217
|
-
|
|
269
|
+
ab.signal.throwIfAborted();
|
|
218
270
|
const chunkEncoded = format.encoder.encode(chunk);
|
|
219
|
-
transport.send(connection, ServerMessageType.RpcStreamChunk, concat(callIdEncoded, chunkEncoded));
|
|
271
|
+
transport.send(connection, ServerMessageType.RpcStreamChunk, concat(callIdEncoded, chunkEncoded), { callId });
|
|
220
272
|
}
|
|
273
|
+
transport.send(connection, ServerMessageType.RpcStreamEnd, callIdEncoded, { callId });
|
|
221
274
|
} catch (error) {
|
|
222
275
|
this.application.logger.error(error);
|
|
223
|
-
transport.send(connection, ServerMessageType.RpcStreamAbort, callIdEncoded);
|
|
276
|
+
transport.send(connection, ServerMessageType.RpcStreamAbort, callIdEncoded, { callId });
|
|
224
277
|
} finally {
|
|
225
278
|
context.rpcStreams.delete(callId);
|
|
226
279
|
response.onFinish && defer(response.onFinish);
|
|
227
280
|
}
|
|
228
281
|
} else {
|
|
229
|
-
transport.send(connection, ServerMessageType.RpcResponse, responseEncoded);
|
|
282
|
+
transport.send(connection, ServerMessageType.RpcResponse, responseEncoded, { callId });
|
|
230
283
|
}
|
|
231
284
|
} catch (error) {
|
|
232
|
-
if (error instanceof ProtocolError === false) {
|
|
233
|
-
this.application.logger.error({
|
|
234
|
-
error,
|
|
235
|
-
connection
|
|
236
|
-
}, "Error during RPC call");
|
|
237
|
-
error = new ProtocolError(ErrorCode.InternalServerError, "Internal server error");
|
|
238
|
-
}
|
|
239
285
|
const payload = format.encoder.encodeRPC({
|
|
240
286
|
callId,
|
|
241
287
|
error
|
|
@@ -247,34 +293,40 @@ export class Protocol {
|
|
|
247
293
|
throwError("Cannot handle stream for error response");
|
|
248
294
|
}
|
|
249
295
|
});
|
|
250
|
-
transport.send(connection, ServerMessageType.RpcResponse, payload
|
|
296
|
+
transport.send(connection, ServerMessageType.RpcResponse, payload, {
|
|
297
|
+
error,
|
|
298
|
+
callId
|
|
299
|
+
});
|
|
251
300
|
} finally {
|
|
301
|
+
calls.delete(callId);
|
|
252
302
|
container.dispose().catch((error) => {
|
|
253
303
|
this.application.logger.error({
|
|
254
304
|
error,
|
|
255
305
|
connection
|
|
256
|
-
}, "Error during disposing connection
|
|
306
|
+
}, "Error during disposing connection");
|
|
257
307
|
});
|
|
258
308
|
}
|
|
259
309
|
}
|
|
260
310
|
async rpcRaw(connectionId, buffer, params = {}) {
|
|
261
|
-
const { connection, context, transport } = this
|
|
311
|
+
const { connection, context, transport } = this.#connections.get(connectionId);
|
|
262
312
|
const { format } = context;
|
|
263
313
|
const rpc = format.decoder.decodeRPC(buffer, {
|
|
264
|
-
addStream: (
|
|
265
|
-
|
|
266
|
-
transport.send(connection, ServerMessageType.ClientStreamPull, concat(encodeNumber(
|
|
314
|
+
addStream: (streamId, callId, metadata) => {
|
|
315
|
+
return this.#clientStreams.add(connectionId, streamId, metadata, (size) => {
|
|
316
|
+
transport.send(connection, ServerMessageType.ClientStreamPull, concat(encodeNumber(streamId, "Uint32"), encodeNumber(size, "Uint32")), {
|
|
317
|
+
callId,
|
|
318
|
+
streamId
|
|
319
|
+
});
|
|
267
320
|
});
|
|
268
|
-
return stream;
|
|
269
321
|
},
|
|
270
322
|
getStream: (id) => {
|
|
271
|
-
return this.
|
|
323
|
+
return this.#clientStreams.get(connectionId, id);
|
|
272
324
|
}
|
|
273
325
|
});
|
|
274
326
|
return await this.rpc(connectionId, rpc, params);
|
|
275
327
|
}
|
|
276
328
|
rpcAbort(connectionId, callId) {
|
|
277
|
-
const { context } = this
|
|
329
|
+
const { context } = this.#connections.get(connectionId);
|
|
278
330
|
const call = context.calls.get(callId) ?? throwError("Call not found");
|
|
279
331
|
call.abort();
|
|
280
332
|
}
|
|
@@ -283,7 +335,7 @@ export class Protocol {
|
|
|
283
335
|
return this.rpcAbort(connectionId, callId);
|
|
284
336
|
}
|
|
285
337
|
rpcStreamAbort(connectionId, callId) {
|
|
286
|
-
const { context } = this
|
|
338
|
+
const { context } = this.#connections.get(connectionId);
|
|
287
339
|
const ab = context.rpcStreams.get(callId) ?? throwError("Call stream not found");
|
|
288
340
|
ab.abort();
|
|
289
341
|
}
|
|
@@ -294,4 +346,51 @@ export class Protocol {
|
|
|
294
346
|
notify(connectionId, event, payload) {
|
|
295
347
|
throw Error("Unimplemented");
|
|
296
348
|
}
|
|
349
|
+
addConnection(transport, options, params) {
|
|
350
|
+
return this.#connections.add(transport, options, params);
|
|
351
|
+
}
|
|
352
|
+
removeConnection(connectionId) {
|
|
353
|
+
return this.#connections.remove(connectionId);
|
|
354
|
+
}
|
|
355
|
+
getConnection(connectionId) {
|
|
356
|
+
return this.#connections.get(connectionId);
|
|
357
|
+
}
|
|
358
|
+
initializeConnection(connection) {
|
|
359
|
+
return this.#connections.initialize(connection);
|
|
360
|
+
}
|
|
361
|
+
getClientStream(connectionId, streamId) {
|
|
362
|
+
return this.#clientStreams.get(connectionId, streamId);
|
|
363
|
+
}
|
|
364
|
+
addClientStream(connectionId, streamId, metadata, read) {
|
|
365
|
+
return this.#clientStreams.add(connectionId, streamId, metadata, read);
|
|
366
|
+
}
|
|
367
|
+
removeClientStream(connectionId, streamId) {
|
|
368
|
+
return this.#clientStreams.remove(connectionId, streamId);
|
|
369
|
+
}
|
|
370
|
+
pushClientStream(connectionId, streamId, chunk) {
|
|
371
|
+
return this.#clientStreams.push(connectionId, streamId, chunk);
|
|
372
|
+
}
|
|
373
|
+
endClientStream(connectionId, streamId) {
|
|
374
|
+
return this.#clientStreams.end(connectionId, streamId);
|
|
375
|
+
}
|
|
376
|
+
abortClientStream(connectionId, streamId, error) {
|
|
377
|
+
return this.#clientStreams.abort(connectionId, streamId, error);
|
|
378
|
+
}
|
|
379
|
+
getServerStream(connectionId, streamId) {
|
|
380
|
+
return this.#serverStreams.get(connectionId, streamId);
|
|
381
|
+
}
|
|
382
|
+
addServerStream(connectionId, streamId, blob) {
|
|
383
|
+
return this.#serverStreams.add(connectionId, streamId, blob);
|
|
384
|
+
}
|
|
385
|
+
removeServerStream(connectionId, streamId) {
|
|
386
|
+
return this.#serverStreams.remove(connectionId, streamId);
|
|
387
|
+
}
|
|
388
|
+
pullServerStream(connectionId, streamId) {
|
|
389
|
+
return this.#serverStreams.pull(connectionId, streamId);
|
|
390
|
+
}
|
|
391
|
+
abortServerStream(connectionId, streamId, error) {
|
|
392
|
+
return this.#serverStreams.abort(connectionId, streamId, error);
|
|
393
|
+
}
|
|
297
394
|
}
|
|
395
|
+
|
|
396
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","names":["code: string","message?: string","data?: any","#collection","application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n }","connectionId: string","transport: Transport<any>","options: ConnectionOptions<T>","params: ResolveFormatParams","connections: ProtocolConnections","streamId: number","metadata: ProtocolBlobMetadata","read: Callback","chunk: ArrayBuffer","blob: ProtocolBlob","application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n }","rpc: ProtocolRPC","params: { signal?: AbortSignal }","buffer: ArrayBuffer","callId: number"],"sources":["src/server/protocol.ts"],"sourcesContent":["import { type Callback, createPromise, defer, throwError } from '@nmtjs/common'\nimport { type Container, Hook, type Logger, Scope } from '@nmtjs/core'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ErrorCode, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport type { ProtocolApi, ProtocolApiCallResult } from './api.ts'\nimport {\n Connection,\n ConnectionContext,\n type ConnectionOptions,\n} from './connection.ts'\nimport type { Format } from './format.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\nimport type { Transport } from './transport.ts'\nimport { getFormat, type ResolveFormatParams } from './utils.ts'\n\nexport class ProtocolError extends Error {\n code: string\n data?: any\n\n constructor(code: string, message?: string, data?: any) {\n super(message)\n this.code = code\n this.data = data\n }\n\n get message() {\n return `${this.code} ${super.message}`\n }\n\n toString() {\n return `${this.code} ${this.message}`\n }\n\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n data: this.data,\n }\n }\n}\n\nexport class ProtocolConnections {\n readonly #collection = new Map<\n string,\n {\n connection: Connection\n context: ConnectionContext\n transport: Transport\n }\n >()\n\n constructor(\n private readonly application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n },\n ) {}\n\n get(connectionId: string) {\n const connection = this.#collection.get(connectionId)\n if (!connection) throwError('Connection not found')\n return connection\n }\n\n async add<T>(\n transport: Transport<any>,\n options: ConnectionOptions<T>,\n params: ResolveFormatParams,\n ) {\n const connection = new Connection(options)\n const format = getFormat(this.application.format, params)\n const container = this.application.container.fork(Scope.Connection)\n const context = new ConnectionContext(container, format)\n\n this.#collection.set(connection.id, { connection, context, transport })\n\n await this.application.registry.hooks.call(\n Hook.OnConnect,\n { concurrent: false },\n connection,\n )\n\n return { connection, context }\n }\n\n async remove(connectionId: string) {\n const { connection, context } = this.get(connectionId)\n\n this.application.registry.hooks.call(\n Hook.OnDisconnect,\n { concurrent: true },\n connection,\n )\n\n this.#collection.delete(connectionId)\n\n const { calls, serverStreams, clientStreams, rpcStreams, container } =\n context\n\n for (const call of calls.values()) {\n call.abort(new Error('Connection closed'))\n }\n\n for (const stream of clientStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of serverStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of rpcStreams.values()) {\n stream.abort(new Error('Connection closed'))\n }\n\n try {\n await container.dispose()\n } catch (error) {\n this.application.logger.error(\n { error, connection },\n 'Error during closing connection',\n )\n }\n }\n}\n\nexport class ProtocolClientStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = clientStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n clientStreams.get(streamId) || throwError('Stream not found')\n clientStreams.delete(streamId)\n }\n\n add(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = new ProtocolClientStream(streamId, metadata, { read })\n clientStreams.set(streamId, stream)\n return stream\n }\n\n push(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(connectionId, streamId)\n stream.push(Buffer.from(chunk))\n }\n\n end(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.push(null)\n this.remove(connectionId, streamId)\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = serverStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n add(connectionId: string, streamId: number, blob: ProtocolBlob) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = new ProtocolServerStream(streamId, blob)\n serverStreams.set(streamId, stream)\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n serverStreams.has(streamId) || throwError('Stream not found')\n serverStreams.delete(streamId)\n }\n\n pull(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.resume()\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class Protocol {\n readonly connections: ProtocolConnections\n readonly clientStreams: ProtocolClientStreams\n readonly serverStreams: ProtocolServerStreams\n\n constructor(\n protected readonly application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n },\n ) {\n this.connections = new ProtocolConnections(this.application)\n this.clientStreams = new ProtocolClientStreams(this.connections)\n this.serverStreams = new ProtocolServerStreams(this.connections)\n }\n\n async rpc(\n connectionId: string,\n rpc: ProtocolRPC,\n params: { signal?: AbortSignal } = {},\n ) {\n const { connection, context, transport } =\n this.connections.get(connectionId)\n const { calls, format } = context\n const { callId, namespace, procedure, payload } = rpc\n const abortController = new AbortController()\n const signal = params.signal\n ? AbortSignal.any([params.signal, abortController.signal])\n : abortController.signal\n\n const call = Object.assign(createPromise<ProtocolApiCallResult>(), {\n abort: () => abortController.abort(),\n })\n\n calls.set(callId, call)\n call.promise.finally(() => calls.delete(callId))\n\n const callIdEncoded = encodeNumber(callId, 'Uint32')\n const container = context.container.fork(Scope.Call)\n\n try {\n const response = await this.application.api.call({\n connection,\n container,\n namespace,\n payload,\n procedure,\n signal,\n })\n\n const responseEncoded = format.encoder.encodeRPC(\n {\n callId,\n payload: response.output,\n },\n {\n addStream: (blob) => {\n const id = context.streamId++\n const stream = this.serverStreams.add(connectionId, id, blob)\n stream.on('data', (chunk) => {\n stream.pause()\n const buf = Buffer.from(chunk)\n transport.send(\n connection,\n ServerMessageType.ServerStreamPush,\n concat(\n encodeNumber(id, 'Uint32'),\n (buf.buffer as ArrayBuffer).slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n ),\n ),\n )\n })\n stream.on('error', (err) => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamAbort,\n encodeNumber(id, 'Uint32'),\n )\n })\n stream.on('end', () => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamEnd,\n encodeNumber(id, 'Uint32'),\n )\n })\n return stream\n },\n getStream: (id) => {\n return this.clientStreams.get(connectionId, id)\n },\n },\n )\n\n if ('subscription' in response) {\n throwError('Unimplemented')\n } else if ('iterable' in response) {\n transport.send(\n connection,\n ServerMessageType.RpcStreamResponse,\n responseEncoded,\n )\n try {\n const ab = new AbortController()\n context.rpcStreams.set(callId, ab)\n const iterable =\n typeof response.iterable === 'function'\n ? response.iterable()\n : response.iterable\n for await (const chunk of iterable) {\n if (ab.signal.aborted) break\n const chunkEncoded = format.encoder.encode(chunk)\n transport.send(\n connection,\n ServerMessageType.RpcStreamChunk,\n concat(callIdEncoded, chunkEncoded),\n )\n }\n } catch (error) {\n this.application.logger.error(error)\n transport.send(\n connection,\n ServerMessageType.RpcStreamAbort,\n callIdEncoded,\n )\n } finally {\n context.rpcStreams.delete(callId)\n response.onFinish && defer(response.onFinish)\n }\n } else {\n transport.send(\n connection,\n ServerMessageType.RpcResponse,\n responseEncoded,\n )\n }\n } catch (error) {\n if (error instanceof ProtocolError === false) {\n this.application.logger.error(\n { error, connection },\n 'Error during RPC call',\n )\n\n // biome-ignore lint/suspicious/noCatchAssign:\n error = new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal server error',\n )\n }\n\n const payload = format.encoder.encodeRPC(\n { callId, error },\n {\n addStream(blob) {\n throwError('Cannot handle stream for error response')\n },\n getStream(id) {\n throwError('Cannot handle stream for error response')\n },\n },\n )\n transport.send(connection, ServerMessageType.RpcResponse, payload)\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n \"Error during disposing connection's container\",\n )\n })\n }\n }\n\n async rpcRaw(\n connectionId: string,\n buffer: ArrayBuffer,\n params: { signal?: AbortSignal } = {},\n ) {\n const { connection, context, transport } =\n this.connections.get(connectionId)\n\n const { format } = context\n\n const rpc = format.decoder.decodeRPC(buffer, {\n addStream: (id, metadata) => {\n const stream = this.clientStreams.add(\n connectionId,\n id,\n metadata,\n (size) => {\n transport.send(\n connection,\n ServerMessageType.ClientStreamPull,\n concat(encodeNumber(id, 'Uint32'), encodeNumber(size, 'Uint32')),\n )\n },\n )\n return stream\n },\n getStream: (id) => {\n return this.serverStreams.get(connectionId, id)\n },\n })\n\n return await this.rpc(connectionId, rpc, params)\n }\n\n rpcAbort(connectionId: string, callId: number) {\n const { context } = this.connections.get(connectionId)\n const call = context.calls.get(callId) ?? throwError('Call not found')\n call.abort()\n }\n\n rpcAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcAbort(connectionId, callId)\n }\n\n rpcStreamAbort(connectionId: string, callId: number) {\n const { context } = this.connections.get(connectionId)\n const ab =\n context.rpcStreams.get(callId) ?? throwError('Call stream not found')\n ab.abort()\n }\n\n rpcStreamAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcStreamAbort(connectionId, callId)\n }\n\n notify(connectionId: string, event, payload) {\n throw Error('Unimplemented')\n }\n}\n"],"version":3}
|
|
1
|
+
{"mappings":"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","names":["code: string","message?: string","data?: any","#collection","application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n }","connectionId: string","transport: ProtocolConnectionTransport","options: ConnectionOptions<T>","params: ResolveFormatParams","connection: Connection","connections: ProtocolConnections","streamId: number","metadata: ProtocolBlobMetadata","read: Callback","chunk: ArrayBuffer","blob: ProtocolBlob","application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n }","#connections","#clientStreams","#serverStreams","options: ProtocolApiCallOptions","rpc: ProtocolRPC","params: ProtocolRPCOptions","buffer: ArrayBuffer","callId: number","options: ConnectionOptions","error?: Error"],"sources":["../../src/server/protocol.ts"],"sourcesContent":["import { type Callback, defer, throwError } from '@nmtjs/common'\nimport {\n type AnyInjectable,\n type Container,\n Hook,\n type Logger,\n Scope,\n} from '@nmtjs/core'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ErrorCode, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport {\n isIterableResult,\n type ProtocolApi,\n type ProtocolApiCallOptions,\n} from './api.ts'\nimport {\n Connection,\n ConnectionContext,\n type ConnectionOptions,\n} from './connection.ts'\nimport type { Format } from './format.ts'\nimport { ProtocolInjectables } from './injectables.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\nimport type { Transport } from './transport.ts'\nimport { getFormat, type ResolveFormatParams } from './utils.ts'\n\nexport class ProtocolError extends Error {\n code: string\n data?: any\n\n constructor(code: string, message?: string, data?: any) {\n super(message)\n this.code = code\n this.data = data\n }\n\n get message() {\n return `${this.code} ${super.message}`\n }\n\n toString() {\n return `${this.code} ${this.message}`\n }\n\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n data: this.data,\n }\n }\n}\n\nexport type ProtocolConnectionTransport = {\n send: Transport<any>['send']\n}\n\nexport class ProtocolConnections {\n readonly #collection = new Map<\n string,\n {\n connection: Connection\n context: ConnectionContext\n transport: ProtocolConnectionTransport\n }\n >()\n\n constructor(\n private readonly application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n },\n ) {}\n\n get(connectionId: string) {\n const connection = this.#collection.get(connectionId)\n if (!connection) throwError('Connection not found')\n return connection\n }\n\n async add<T>(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions<T>,\n params: ResolveFormatParams,\n ) {\n const connection = new Connection(options)\n const format = getFormat(this.application.format, params)\n const container = this.application.container.fork(Scope.Connection)\n const context = new ConnectionContext(container, format)\n container.provide(ProtocolInjectables.connection, connection)\n try {\n await this.initialize(connection)\n this.#collection.set(connection.id, { connection, context, transport })\n return { connection, context }\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n }\n }\n\n async remove(connectionId: string) {\n const { connection, context } = this.get(connectionId)\n\n this.application.registry.hooks.call(\n Hook.OnDisconnect,\n { concurrent: true },\n connection,\n )\n\n this.#collection.delete(connectionId)\n\n const { calls, serverStreams, clientStreams, rpcStreams, container } =\n context\n\n for (const call of calls.values()) {\n call.abort(new Error('Connection closed'))\n }\n\n for (const stream of clientStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of serverStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of rpcStreams.values()) {\n stream.abort(new Error('Connection closed'))\n }\n\n try {\n await container.dispose()\n } catch (error) {\n this.application.logger.error(\n { error, connection },\n 'Error during closing connection',\n )\n }\n }\n\n async initialize(connection: Connection) {\n await this.application.registry.hooks.call(\n Hook.OnConnect,\n { concurrent: false },\n connection,\n )\n }\n}\n\nexport class ProtocolClientStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = clientStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n clientStreams.get(streamId) || throwError('Stream not found')\n clientStreams.delete(streamId)\n }\n\n add(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = new ProtocolClientStream(streamId, metadata, { read })\n clientStreams.set(streamId, stream)\n return stream\n }\n\n push(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(connectionId, streamId)\n stream.write(Buffer.from(chunk))\n }\n\n end(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.end(null)\n this.remove(connectionId, streamId)\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = serverStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n add(connectionId: string, streamId: number, blob: ProtocolBlob) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = new ProtocolServerStream(streamId, blob)\n serverStreams.set(streamId, stream)\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n serverStreams.has(streamId) || throwError('Stream not found')\n serverStreams.delete(streamId)\n }\n\n pull(connectionId: string, streamId: number) {\n console.log('Pulling stream', streamId)\n const stream = this.get(connectionId, streamId)\n stream.resume()\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport type ProtocolRPCOptions = {\n signal?: AbortSignal\n provides?: [AnyInjectable, any][]\n metadata?: ProtocolApiCallOptions['metadata']\n}\n\nexport class Protocol {\n #connections: ProtocolConnections\n #clientStreams: ProtocolClientStreams\n #serverStreams: ProtocolServerStreams\n\n constructor(\n protected readonly application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n },\n ) {\n this.#connections = new ProtocolConnections(this.application)\n this.#clientStreams = new ProtocolClientStreams(this.#connections)\n this.#serverStreams = new ProtocolServerStreams(this.#connections)\n }\n\n async call(options: ProtocolApiCallOptions) {\n const { container, connection } = options\n try {\n return await this.application.api.call(options)\n } catch (error) {\n if (error instanceof ProtocolError === false) {\n this.application.logger.error(\n { error, connection },\n 'Error during RPC call',\n )\n throw new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal server error',\n )\n }\n throw error\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n \"Error during disposing connection's container\",\n )\n })\n }\n }\n\n async rpc(\n connectionId: string,\n rpc: ProtocolRPC,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n const { calls, format } = context\n const { callId, namespace, procedure, payload } = rpc\n const abortController = new AbortController()\n const signal = params.signal\n ? AbortSignal.any([params.signal, abortController.signal])\n : abortController.signal\n\n calls.set(callId, abortController)\n\n const callIdEncoded = encodeNumber(callId, 'Uint32')\n const container = context.container.fork(Scope.Call)\n\n if (params.provides) {\n for (const [key, value] of params.provides) {\n container.provide(key, value)\n }\n }\n\n try {\n const response = await this.call({\n connection,\n container,\n namespace,\n payload,\n procedure,\n signal,\n metadata: params.metadata,\n })\n\n const responseEncoded = format.encoder.encodeRPC(\n {\n callId,\n result: response.output,\n },\n {\n addStream: (blob) => {\n const streamId = context.streamId++\n const stream = this.#serverStreams.add(connectionId, streamId, blob)\n stream.on('data', (chunk) => {\n stream.pause()\n const buf = Buffer.from(chunk)\n transport.send(\n connection,\n ServerMessageType.ServerStreamPush,\n concat(\n encodeNumber(streamId, 'Uint32'),\n (buf.buffer as ArrayBuffer).slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n ),\n ),\n { callId, streamId },\n )\n })\n stream.on('error', (err) => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamAbort,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n stream.on('end', () => {\n console.log('Stream ended')\n transport.send(\n connection,\n ServerMessageType.ServerStreamEnd,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n return stream\n },\n getStream: (id) => {\n return this.#serverStreams.get(connectionId, id)\n },\n },\n )\n\n if ('subscription' in response) {\n throwError('Unimplemented')\n } else if (isIterableResult(response)) {\n transport.send(\n connection,\n ServerMessageType.RpcStreamResponse,\n responseEncoded,\n { callId },\n )\n try {\n const ab = new AbortController()\n context.rpcStreams.set(callId, ab)\n const iterable =\n typeof response.iterable === 'function'\n ? response.iterable()\n : response.iterable\n for await (const chunk of iterable) {\n ab.signal.throwIfAborted()\n const chunkEncoded = format.encoder.encode(chunk)\n transport.send(\n connection,\n ServerMessageType.RpcStreamChunk,\n concat(callIdEncoded, chunkEncoded),\n { callId },\n )\n }\n transport.send(\n connection,\n ServerMessageType.RpcStreamEnd,\n callIdEncoded,\n { callId },\n )\n } catch (error) {\n this.application.logger.error(error)\n transport.send(\n connection,\n ServerMessageType.RpcStreamAbort,\n callIdEncoded,\n { callId },\n )\n } finally {\n context.rpcStreams.delete(callId)\n response.onFinish && defer(response.onFinish)\n }\n } else {\n transport.send(\n connection,\n ServerMessageType.RpcResponse,\n responseEncoded,\n { callId },\n )\n }\n } catch (error) {\n const payload = format.encoder.encodeRPC(\n { callId, error },\n {\n addStream(blob) {\n throwError('Cannot handle stream for error response')\n },\n getStream(id) {\n throwError('Cannot handle stream for error response')\n },\n },\n )\n\n transport.send(connection, ServerMessageType.RpcResponse, payload, {\n error,\n callId,\n })\n } finally {\n calls.delete(callId)\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n }\n }\n\n async rpcRaw(\n connectionId: string,\n buffer: ArrayBuffer,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n\n const { format } = context\n\n const rpc = format.decoder.decodeRPC(buffer, {\n addStream: (streamId, callId, metadata) => {\n return this.#clientStreams.add(\n connectionId,\n streamId,\n metadata,\n (size) => {\n transport.send(\n connection,\n ServerMessageType.ClientStreamPull,\n concat(\n encodeNumber(streamId, 'Uint32'),\n encodeNumber(size, 'Uint32'),\n ),\n { callId, streamId },\n )\n },\n )\n },\n getStream: (id) => {\n return this.#clientStreams.get(connectionId, id)\n },\n })\n\n return await this.rpc(connectionId, rpc, params)\n }\n\n rpcAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const call = context.calls.get(callId) ?? throwError('Call not found')\n call.abort()\n }\n\n rpcAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcAbort(connectionId, callId)\n }\n\n rpcStreamAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const ab =\n context.rpcStreams.get(callId) ?? throwError('Call stream not found')\n ab.abort()\n }\n\n rpcStreamAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcStreamAbort(connectionId, callId)\n }\n\n notify(connectionId: string, event, payload) {\n throw Error('Unimplemented')\n }\n\n addConnection(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions,\n params: ResolveFormatParams,\n ) {\n return this.#connections.add(transport, options, params)\n }\n\n removeConnection(connectionId: string) {\n return this.#connections.remove(connectionId)\n }\n\n getConnection(connectionId: string) {\n return this.#connections.get(connectionId)\n }\n\n initializeConnection(connection: Connection) {\n return this.#connections.initialize(connection)\n }\n\n getClientStream(\n connectionId: string,\n streamId: number,\n ): ProtocolClientStream {\n return this.#clientStreams.get(connectionId, streamId)\n }\n\n addClientStream(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n return this.#clientStreams.add(connectionId, streamId, metadata, read)\n }\n\n removeClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.remove(connectionId, streamId)\n }\n\n pushClientStream(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n return this.#clientStreams.push(connectionId, streamId, chunk)\n }\n\n endClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.end(connectionId, streamId)\n }\n\n abortClientStream(connectionId: string, streamId: number, error?: Error) {\n return this.#clientStreams.abort(connectionId, streamId, error)\n }\n\n getServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.get(connectionId, streamId)\n }\n\n addServerStream(connectionId: string, streamId: number, blob: ProtocolBlob) {\n return this.#serverStreams.add(connectionId, streamId, blob)\n }\n\n removeServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.remove(connectionId, streamId)\n }\n\n pullServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.pull(connectionId, streamId)\n }\n\n abortServerStream(connectionId: string, streamId: number, error?: Error) {\n return this.#serverStreams.abort(connectionId, streamId, error)\n }\n}\n"],"version":3,"file":"protocol.js"}
|
package/dist/server/registry.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,SAAS,gBAAgB,aAAa;AAEtC,OAAO,MAAM,yBAAyB,SAAS,CAAE","names":[],"sources":["src/server/registry.ts"],"sourcesContent":["import { Registry } from '@nmtjs/core'\n\nexport class ProtocolRegistry extends Registry {}\n"],"version":3}
|
|
1
|
+
{"mappings":"AAAA,SAAS,gBAAgB,aAAa;AAEtC,OAAO,MAAM,yBAAyB,SAAS,CAAE","names":[],"sources":["../../src/server/registry.ts"],"sourcesContent":["import { Registry } from '@nmtjs/core'\n\nexport class ProtocolRegistry extends Registry {}\n"],"version":3,"file":"registry.js"}
|
package/dist/server/stream.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PassThrough, Readable } from "node:stream";
|
|
2
2
|
import { ReadableStream } from "node:stream/web";
|
|
3
|
-
export class ProtocolClientStream extends
|
|
3
|
+
export class ProtocolClientStream extends PassThrough {
|
|
4
4
|
constructor(id, metadata, options) {
|
|
5
5
|
super(options);
|
|
6
6
|
this.id = id;
|
|
@@ -26,3 +26,5 @@ export class ProtocolServerStream extends PassThrough {
|
|
|
26
26
|
this.metadata = blob.metadata;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,
|
|
1
|
+
{"mappings":"AAAA,SAAS,aAAa,gBAAsC,aAAa;AACzE,SAAS,sBAAsB,iBAAiB;AAGhD,OAAO,MAAM,6BAA6B,YAAY;CACpD,YACkBA,IACAC,UAChBC,SACA;AACA,QAAM,QAAQ;OAJE;OACA;CAIjB;AACF;AAED,OAAO,MAAM,6BAA6B,YAAY;CACpD,AAAgB;CAChB,AAAgB;CAEhB,YAAYF,IAAYG,MAAoB;EAC1C,IAAIC;AAEJ,MAAI,KAAK,kBAAkB,UAAU;AACnC,cAAW,KAAK;EACjB,WAAU,KAAK,kBAAkB,gBAAgB;AAChD,cAAW,SAAS,QAAQ,KAAK,OAAyB;EAC3D,OAAM;AACL,SAAM,IAAI,MAAM;EACjB;AAED,SAAO;AAEP,OAAK,OAAO;AACZ,WAAS,KAAK,KAAK;AAEnB,OAAK,KAAK;AACV,OAAK,WAAW,KAAK;CACtB;AACF","names":["id: number","metadata: ProtocolBlobMetadata","options?: ReadableOptions","blob: ProtocolBlob","readable: Readable"],"sources":["../../src/server/stream.ts"],"sourcesContent":["import { PassThrough, Readable, type ReadableOptions } from 'node:stream'\nimport { ReadableStream } from 'node:stream/web'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\n\nexport class ProtocolClientStream extends PassThrough {\n constructor(\n public readonly id: number,\n public readonly metadata: ProtocolBlobMetadata,\n options?: ReadableOptions,\n ) {\n super(options)\n }\n}\n\nexport class ProtocolServerStream extends PassThrough {\n public readonly id: number\n public readonly metadata: ProtocolBlobMetadata\n\n constructor(id: number, blob: ProtocolBlob) {\n let readable: Readable\n\n if (blob.source instanceof Readable) {\n readable = blob.source\n } else if (blob.source instanceof ReadableStream) {\n readable = Readable.fromWeb(blob.source as ReadableStream)\n } else {\n throw new Error('Invalid source type')\n }\n\n super()\n\n this.pause()\n readable.pipe(this)\n\n this.id = id\n this.metadata = blob.metadata\n }\n}\n"],"version":3,"file":"stream.js"}
|
package/dist/server/transport.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAIA,SAAS,wBAAwB,gBAAgB;
|
|
1
|
+
{"mappings":"AAIA,SAAS,wBAAwB,gBAAgB;AA4BjD,OAAO,MAAM,kBAAkB,CAC7BA,MACAC,UACoC;CAAE;CAAM;EAAO,mBAAmB;AAAM;AAE9E,OAAO,MAAM,oBAAoB,CAC/BC,WAC8B,oBAAoB","names":["name: string","init: TransportPlugin<Type, Options>['init']","plugin: BasePlugin<any, any, any>"],"sources":["../../src/server/transport.ts"],"sourcesContent":["import type { Async } from '@nmtjs/common'\nimport type { BasePlugin, PluginContext } from '@nmtjs/core'\nimport type { ServerMessageType } from '../common/enums.ts'\nimport type { Connection } from './connection.ts'\nimport { kTransportPlugin } from './constants.ts'\nimport type { Format } from './format.ts'\nimport type { Protocol } from './protocol.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport type { ProtocolSendMetadata } from './types.ts'\n\nexport interface Transport<T = unknown> {\n start: () => Promise<void>\n stop: () => Promise<void>\n send: (\n connection: Connection<T>,\n messageType: ServerMessageType,\n buffer: ArrayBuffer,\n metadata: ProtocolSendMetadata,\n ) => any\n}\n\nexport interface TransportPluginContext extends PluginContext {\n protocol: Protocol\n registry: ProtocolRegistry\n format: Format\n}\n\nexport interface TransportPlugin<Type = unknown, Options = unknown>\n extends BasePlugin<Transport<Type>, Options, TransportPluginContext> {\n [kTransportPlugin]: any\n}\n\nexport const createTransport = <Type = unknown, Options = unknown>(\n name: string,\n init: TransportPlugin<Type, Options>['init'],\n): TransportPlugin<Type, Options> => ({ name, init, [kTransportPlugin]: true })\n\nexport const isTransportPlugin = (\n plugin: BasePlugin<any, any, any>,\n): plugin is TransportPlugin => kTransportPlugin in plugin\n"],"version":3,"file":"transport.js"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"mappings":"","names":[],"sources":["../../src/server/types.ts"],"sourcesContent":["import type { ProtocolServerBlobStream } from '../client/stream.ts'\nimport type { ProtocolBlob, ProtocolBlobInterface } from '../common/blob.ts'\nimport type { ProtocolClientStream } from './stream.ts'\n\nexport type InputType<T> = T extends ProtocolBlobInterface\n ? ProtocolClientStream\n : T extends object\n ? { [K in keyof T]: InputType<T[K]> }\n : T\n\nexport type OutputType<T> = T extends ProtocolBlobInterface\n ? ProtocolBlob\n : T extends object\n ? { [K in keyof T]: OutputType<T[K]> }\n : T\n\nexport type ProtocolSendMetadata = {\n streamId?: number\n callId?: number\n error?: any\n}\n"],"version":3,"file":"types.js"}
|
package/dist/server/utils.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
export class UnsupportedFormatError extends Error {}
|
|
2
|
+
export class UnsupportedContentTypeError extends UnsupportedFormatError {}
|
|
3
|
+
export class UnsupportedAcceptTypeError extends UnsupportedFormatError {}
|
|
1
4
|
export const getFormat = (format, { acceptType, contentType }) => {
|
|
2
5
|
const encoder = contentType ? format.supportsEncoder(contentType) : undefined;
|
|
3
|
-
if (!encoder) throw new
|
|
6
|
+
if (!encoder) throw new UnsupportedContentTypeError("Unsupported Content-Type");
|
|
4
7
|
const decoder = acceptType ? format.supportsDecoder(acceptType) : undefined;
|
|
5
|
-
if (!decoder) throw new
|
|
8
|
+
if (!decoder) throw new UnsupportedAcceptTypeError("Unsupported Accept-Type");
|
|
6
9
|
return {
|
|
7
10
|
encoder,
|
|
8
11
|
decoder
|
|
9
12
|
};
|
|
10
13
|
};
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=utils.js.map
|
package/dist/server/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAOA,OAAO,MAAM,YAAY,CACvBA,QACA,EAAE,YAAY,aAAkC,KAC7C;CACH,MAAM,UAAU,cAAc,OAAO,gBAAgB,YAAY,GAAG;AACpE,MAAK,
|
|
1
|
+
{"mappings":"AAOA,OAAO,MAAM,+BAA+B,MAAM,CAAE;AAEpD,OAAO,MAAM,oCAAoC,uBAAuB,CAAE;AAE1E,OAAO,MAAM,mCAAmC,uBAAuB,CAAE;AAEzE,OAAO,MAAM,YAAY,CACvBA,QACA,EAAE,YAAY,aAAkC,KAC7C;CACH,MAAM,UAAU,cAAc,OAAO,gBAAgB,YAAY,GAAG;AACpE,MAAK,QACH,OAAM,IAAI,4BAA4B;CAExC,MAAM,UAAU,aAAa,OAAO,gBAAgB,WAAW,GAAG;AAClE,MAAK,QAAS,OAAM,IAAI,2BAA2B;AAEnD,QAAO;EACL;EACA;CACD;AACF","names":["format: Format"],"sources":["../../src/server/utils.ts"],"sourcesContent":["import type { Format } from './format.ts'\n\nexport type ResolveFormatParams = {\n contentType?: string | null\n acceptType?: string | null\n}\n\nexport class UnsupportedFormatError extends Error {}\n\nexport class UnsupportedContentTypeError extends UnsupportedFormatError {}\n\nexport class UnsupportedAcceptTypeError extends UnsupportedFormatError {}\n\nexport const getFormat = (\n format: Format,\n { acceptType, contentType }: ResolveFormatParams,\n) => {\n const encoder = contentType ? format.supportsEncoder(contentType) : undefined\n if (!encoder)\n throw new UnsupportedContentTypeError('Unsupported Content-Type')\n\n const decoder = acceptType ? format.supportsDecoder(acceptType) : undefined\n if (!decoder) throw new UnsupportedAcceptTypeError('Unsupported Accept-Type')\n\n return {\n encoder,\n decoder,\n }\n}\n"],"version":3,"file":"utils.js"}
|
package/package.json
CHANGED
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@nmtjs/
|
|
20
|
-
"@nmtjs/
|
|
21
|
-
"@nmtjs/
|
|
19
|
+
"@nmtjs/core": "0.9.0",
|
|
20
|
+
"@nmtjs/common": "0.9.0",
|
|
21
|
+
"@nmtjs/type": "0.9.0"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@nmtjs/common": "0.
|
|
25
|
-
"@nmtjs/type": "0.
|
|
26
|
-
"@nmtjs/core": "0.
|
|
24
|
+
"@nmtjs/common": "0.9.0",
|
|
25
|
+
"@nmtjs/type": "0.9.0",
|
|
26
|
+
"@nmtjs/core": "0.9.0"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"src",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"LICENSE.md",
|
|
32
32
|
"README.md"
|
|
33
33
|
],
|
|
34
|
-
"version": "0.
|
|
34
|
+
"version": "0.9.0",
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "neemata-build --root=./src './**/*.ts'",
|
|
37
37
|
"type-check": "tsc --noEmit"
|
package/src/client/format.ts
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
BaseClientDecoder,
|
|
3
|
-
BaseClientEncoder,
|
|
2
|
+
// BaseClientDecoder,
|
|
3
|
+
// BaseClientEncoder,
|
|
4
4
|
DecodeRPCContext,
|
|
5
5
|
EncodeRPCContext,
|
|
6
6
|
ProtocolRPC,
|
|
7
|
+
// ProtocolRPCEncode,
|
|
7
8
|
ProtocolRPCResponse,
|
|
8
9
|
} from '../common/types.ts'
|
|
10
|
+
import type {
|
|
11
|
+
ProtocolClientBlobStream,
|
|
12
|
+
ProtocolServerBlobStream,
|
|
13
|
+
} from './stream.ts'
|
|
14
|
+
|
|
15
|
+
export type ProtocolRPCEncode = {
|
|
16
|
+
buffer: ArrayBuffer
|
|
17
|
+
streams: Record<number, ProtocolClientBlobStream>
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface BaseClientDecoder {
|
|
21
|
+
decode(buffer: ArrayBuffer): any
|
|
22
|
+
decodeRPC(
|
|
23
|
+
buffer: ArrayBuffer,
|
|
24
|
+
context: DecodeRPCContext<ProtocolServerBlobStream>,
|
|
25
|
+
): ProtocolRPCResponse<ProtocolServerBlobStream>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface BaseClientEncoder {
|
|
29
|
+
encode(data: any): ArrayBuffer
|
|
30
|
+
encodeRPC(
|
|
31
|
+
rpc: ProtocolRPC,
|
|
32
|
+
context: EncodeRPCContext<ProtocolClientBlobStream>,
|
|
33
|
+
): ProtocolRPCEncode
|
|
34
|
+
}
|
|
9
35
|
|
|
10
36
|
export abstract class BaseClientFormat
|
|
11
37
|
implements BaseClientDecoder, BaseClientEncoder
|
|
@@ -13,10 +39,13 @@ export abstract class BaseClientFormat
|
|
|
13
39
|
abstract contentType: string
|
|
14
40
|
|
|
15
41
|
abstract encode(data: any): ArrayBuffer
|
|
16
|
-
abstract encodeRPC(
|
|
42
|
+
abstract encodeRPC(
|
|
43
|
+
rpc: ProtocolRPC,
|
|
44
|
+
context: EncodeRPCContext<ProtocolClientBlobStream>,
|
|
45
|
+
): ProtocolRPCEncode
|
|
17
46
|
abstract decode(buffer: ArrayBuffer): any
|
|
18
47
|
abstract decodeRPC(
|
|
19
48
|
buffer: ArrayBuffer,
|
|
20
|
-
context: DecodeRPCContext
|
|
21
|
-
): ProtocolRPCResponse
|
|
49
|
+
context: DecodeRPCContext<ProtocolServerBlobStream>,
|
|
50
|
+
): ProtocolRPCResponse<ProtocolServerBlobStream>
|
|
22
51
|
}
|