@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.
Files changed (64) hide show
  1. package/dist/client/events.js +2 -0
  2. package/dist/client/events.js.map +1 -1
  3. package/dist/client/format.js +2 -0
  4. package/dist/client/format.js.map +1 -1
  5. package/dist/client/index.js +3 -0
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/client/protocol.js +205 -199
  8. package/dist/client/protocol.js.map +1 -1
  9. package/dist/client/stream.js +9 -12
  10. package/dist/client/stream.js.map +1 -1
  11. package/dist/client/types.js +3 -0
  12. package/dist/client/types.js.map +1 -0
  13. package/dist/common/binary.js +2 -0
  14. package/dist/common/binary.js.map +1 -1
  15. package/dist/common/blob.js +6 -2
  16. package/dist/common/blob.js.map +1 -1
  17. package/dist/common/enums.js +4 -1
  18. package/dist/common/enums.js.map +1 -1
  19. package/dist/common/index.js +2 -0
  20. package/dist/common/index.js.map +1 -1
  21. package/dist/common/types.js +2 -0
  22. package/dist/common/types.js.map +1 -1
  23. package/dist/server/api.js +4 -1
  24. package/dist/server/api.js.map +1 -1
  25. package/dist/server/connection.js +2 -0
  26. package/dist/server/connection.js.map +1 -1
  27. package/dist/server/constants.js +2 -0
  28. package/dist/server/constants.js.map +1 -1
  29. package/dist/server/format.js +2 -0
  30. package/dist/server/format.js.map +1 -1
  31. package/dist/server/index.js +3 -0
  32. package/dist/server/index.js.map +1 -1
  33. package/dist/server/injectables.js +2 -0
  34. package/dist/server/injectables.js.map +1 -1
  35. package/dist/server/protocol.js +154 -55
  36. package/dist/server/protocol.js.map +1 -1
  37. package/dist/server/registry.js +2 -0
  38. package/dist/server/registry.js.map +1 -1
  39. package/dist/server/stream.js +3 -1
  40. package/dist/server/stream.js.map +1 -1
  41. package/dist/server/transport.js +2 -0
  42. package/dist/server/transport.js.map +1 -1
  43. package/dist/server/types.js +3 -0
  44. package/dist/server/types.js.map +1 -0
  45. package/dist/server/utils.js +7 -2
  46. package/dist/server/utils.js.map +1 -1
  47. package/package.json +7 -7
  48. package/src/client/format.ts +34 -5
  49. package/src/client/index.ts +2 -0
  50. package/src/client/protocol.ts +381 -274
  51. package/src/client/stream.ts +7 -14
  52. package/src/client/types.ts +14 -0
  53. package/src/common/blob.ts +10 -3
  54. package/src/common/enums.ts +3 -1
  55. package/src/common/types.ts +28 -47
  56. package/src/server/api.ts +15 -1
  57. package/src/server/connection.ts +1 -5
  58. package/src/server/format.ts +14 -4
  59. package/src/server/index.ts +1 -0
  60. package/src/server/protocol.ts +208 -66
  61. package/src/server/stream.ts +2 -7
  62. package/src/server/transport.ts +5 -1
  63. package/src/server/types.ts +21 -0
  64. package/src/server/utils.ts +9 -2
@@ -1,8 +1,10 @@
1
- import { createPromise, defer, throwError } from "@nmtjs/common";
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
- this.#collection.set(connection.id, {
46
- connection,
47
- context,
48
- transport
49
- });
50
- await this.application.registry.hooks.call(Hook.OnConnect, { concurrent: false }, connection);
51
- return {
52
- connection,
53
- context
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.push(Buffer.from(chunk));
123
+ stream.write(Buffer.from(chunk));
109
124
  }
110
125
  end(connectionId, streamId) {
111
126
  const stream = this.get(connectionId, streamId);
112
- stream.push(null);
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.connections = new ProtocolConnections(this.application);
161
- this.clientStreams = new ProtocolClientStreams(this.connections);
162
- this.serverStreams = new ProtocolServerStreams(this.connections);
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.connections.get(connectionId);
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
- const call = Object.assign(createPromise(), { abort: () => abortController.abort() });
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.application.api.call({
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
- payload: response.output
228
+ result: response.output
187
229
  }, {
188
230
  addStream: (blob) => {
189
- const id = context.streamId++;
190
- const stream = this.serverStreams.add(connectionId, id, blob);
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(id, "Uint32"), buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength)));
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(id, "Uint32"));
242
+ transport.send(connection, ServerMessageType.ServerStreamAbort, encodeNumber(streamId, "Uint32"), {
243
+ callId,
244
+ streamId
245
+ });
198
246
  });
199
247
  stream.on("end", () => {
200
- transport.send(connection, ServerMessageType.ServerStreamEnd, encodeNumber(id, "Uint32"));
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.clientStreams.get(connectionId, id);
257
+ return this.#serverStreams.get(connectionId, id);
206
258
  }
207
259
  });
208
260
  if ("subscription" in response) {
209
261
  throwError("Unimplemented");
210
- } else if ("iterable" in response) {
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
- if (ab.signal.aborted) break;
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's container");
306
+ }, "Error during disposing connection");
257
307
  });
258
308
  }
259
309
  }
260
310
  async rpcRaw(connectionId, buffer, params = {}) {
261
- const { connection, context, transport } = this.connections.get(connectionId);
311
+ const { connection, context, transport } = this.#connections.get(connectionId);
262
312
  const { format } = context;
263
313
  const rpc = format.decoder.decodeRPC(buffer, {
264
- addStream: (id, metadata) => {
265
- const stream = this.clientStreams.add(connectionId, id, metadata, (size) => {
266
- transport.send(connection, ServerMessageType.ClientStreamPull, concat(encodeNumber(id, "Uint32"), encodeNumber(size, "Uint32")));
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.serverStreams.get(connectionId, id);
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.connections.get(connectionId);
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.connections.get(connectionId);
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"}
@@ -1,2 +1,4 @@
1
1
  import { Registry } from "@nmtjs/core";
2
2
  export class ProtocolRegistry extends Registry {}
3
+
4
+ //# sourceMappingURL=registry.js.map
@@ -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"}
@@ -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 Readable {
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,SACE,aACA,gBAGK,aAAa;AACpB,SAAS,sBAAsB,iBAAiB;AAGhD,OAAO,MAAM,6BAA6B,SAAS;CACjD,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 {\n PassThrough,\n Readable,\n type ReadableOptions,\n type TransformOptions,\n} from 'node:stream'\nimport { ReadableStream } from 'node:stream/web'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\n\nexport class ProtocolClientStream extends Readable {\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}
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"}
@@ -5,3 +5,5 @@ export const createTransport = (name, init) => ({
5
5
  [kTransportPlugin]: true
6
6
  });
7
7
  export const isTransportPlugin = (plugin) => kTransportPlugin in plugin;
8
+
9
+ //# sourceMappingURL=transport.js.map
@@ -1 +1 @@
1
- {"mappings":"AAIA,SAAS,wBAAwB,gBAAgB;AAwBjD,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 { Protocol } from './protocol.ts'\nimport type { ProtocolRegistry } from './registry.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 ) => Async<void>\n}\n\nexport interface TransportPluginContext extends PluginContext {\n protocol: Protocol\n registry: ProtocolRegistry\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}
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,3 @@
1
+ export {};
2
+
3
+ //# sourceMappingURL=types.js.map
@@ -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"}
@@ -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 Error("Unsupported content-type");
6
+ if (!encoder) throw new UnsupportedContentTypeError("Unsupported Content-Type");
4
7
  const decoder = acceptType ? format.supportsDecoder(acceptType) : undefined;
5
- if (!decoder) throw new Error("Unsupported accept");
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
@@ -1 +1 @@
1
- {"mappings":"AAOA,OAAO,MAAM,YAAY,CACvBA,QACA,EAAE,YAAY,aAAkC,KAC7C;CACH,MAAM,UAAU,cAAc,OAAO,gBAAgB,YAAY,GAAG;AACpE,MAAK,QAAS,OAAM,IAAI,MAAM;CAE9B,MAAM,UAAU,aAAa,OAAO,gBAAgB,WAAW,GAAG;AAClE,MAAK,QAAS,OAAM,IAAI,MAAM;AAE9B,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 const getFormat = (\n format: Format,\n { acceptType, contentType }: ResolveFormatParams,\n) => {\n const encoder = contentType ? format.supportsEncoder(contentType) : undefined\n if (!encoder) throw new Error('Unsupported content-type')\n\n const decoder = acceptType ? format.supportsDecoder(acceptType) : undefined\n if (!decoder) throw new Error('Unsupported accept')\n\n return {\n encoder,\n decoder,\n }\n}\n"],"version":3}
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/type": "0.8.0",
20
- "@nmtjs/core": "0.8.0",
21
- "@nmtjs/common": "0.8.0"
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.8.0",
25
- "@nmtjs/type": "0.8.0",
26
- "@nmtjs/core": "0.8.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.8.0",
34
+ "version": "0.9.0",
35
35
  "scripts": {
36
36
  "build": "neemata-build --root=./src './**/*.ts'",
37
37
  "type-check": "tsc --noEmit"
@@ -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(rpc: ProtocolRPC, context: EncodeRPCContext): ArrayBuffer
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
  }