@nmtjs/protocol 0.6.0 → 0.6.2

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.
@@ -1,19 +1,7 @@
1
- export function untilAborted(signal) {
2
- return new Promise((_, reject)=>{
3
- const handler = ()=>reject(new Error('aborted'));
4
- const options = {
5
- once: true
6
- };
7
- signal.addEventListener('abort', handler, options);
8
- });
9
- }
10
- export function onAbort(signal, listener) {
11
- signal.addEventListener('abort', listener, {
12
- once: true
13
- });
14
- return ()=>signal.removeEventListener('abort', listener);
15
- }
16
1
  export class EventEmitter {
2
+ static once(ee, event) {
3
+ return new Promise((resolve)=>ee.once(event, resolve));
4
+ }
17
5
  #target = new EventTarget();
18
6
  #listeners = new Map();
19
7
  on(event, listener, options) {
@@ -38,4 +26,3 @@ export class EventEmitter {
38
26
  }));
39
27
  }
40
28
  }
41
- export const once = (ee, event)=>new Promise((resolve)=>ee.once(event, resolve));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/client/events.ts"],"sourcesContent":["import type { Callback } from '@nmtjs/common'\n\nexport type EventMap = { [K: string]: any[] }\n\nexport function untilAborted(signal: AbortSignal) {\n return new Promise((_, reject) => {\n const handler = () => reject(new Error('aborted'))\n const options = { once: true }\n signal.addEventListener('abort', handler, options)\n })\n}\n\nexport function onAbort(signal: AbortSignal, listener: () => void) {\n signal.addEventListener('abort', listener, { once: true })\n return () => signal.removeEventListener('abort', listener)\n}\n\n/**\n * Very simple node-like event emitter wrapper around EventTarget\n *\n * @todo add errors and promise rejections handling\n */\nexport class EventEmitter<\n Events extends EventMap = EventMap,\n EventNames extends Extract<keyof Events, string> = Extract<\n keyof Events,\n string\n >,\n> {\n #target = new EventTarget()\n #listeners = new Map<Callback, Callback>()\n\n on<E extends EventNames>(\n event: E | (Object & string),\n listener: (...args: Events[E]) => void,\n options?: AddEventListenerOptions,\n ) {\n const wrapper = (event) => listener(...event.detail)\n this.#listeners.set(listener, wrapper)\n this.#target.addEventListener(event, wrapper, options)\n return () => this.#target.removeEventListener(event, wrapper)\n }\n\n once<E extends EventNames>(\n event: E | (Object & string),\n listener: (...args: Events[E]) => void,\n options?: AddEventListenerOptions,\n ) {\n return this.on(event, listener, { ...options, once: true })\n }\n\n off(event: EventNames | (Object & string), listener: Callback) {\n const wrapper = this.#listeners.get(listener)\n if (wrapper) this.#target.removeEventListener(event, wrapper)\n }\n\n emit<E extends EventNames | (Object & string)>(\n event: E,\n ...args: E extends EventEmitter ? Events[E] : any[]\n ) {\n return this.#target.dispatchEvent(new CustomEvent(event, { detail: args }))\n }\n}\n\nexport const once = (ee: EventEmitter, event: string) =>\n new Promise((resolve) => ee.once(event, resolve))\n"],"names":["untilAborted","signal","Promise","_","reject","handler","Error","options","once","addEventListener","onAbort","listener","removeEventListener","EventEmitter","EventTarget","Map","on","event","wrapper","detail","set","off","get","emit","args","dispatchEvent","CustomEvent","ee","resolve"],"mappings":"AAIA,OAAO,SAASA,aAAaC,MAAmB;IAC9C,OAAO,IAAIC,QAAQ,CAACC,GAAGC;QACrB,MAAMC,UAAU,IAAMD,OAAO,IAAIE,MAAM;QACvC,MAAMC,UAAU;YAAEC,MAAM;QAAK;QAC7BP,OAAOQ,gBAAgB,CAAC,SAASJ,SAASE;IAC5C;AACF;AAEA,OAAO,SAASG,QAAQT,MAAmB,EAAEU,QAAoB;IAC/DV,OAAOQ,gBAAgB,CAAC,SAASE,UAAU;QAAEH,MAAM;IAAK;IACxD,OAAO,IAAMP,OAAOW,mBAAmB,CAAC,SAASD;AACnD;AAOA,OAAO,MAAME;IAOX,CAAA,MAAO,GAAG,IAAIC,cAAa;IAC3B,CAAA,SAAU,GAAG,IAAIC,MAAyB;IAE1CC,GACEC,KAA4B,EAC5BN,QAAsC,EACtCJ,OAAiC,EACjC;QACA,MAAMW,UAAU,CAACD,QAAUN,YAAYM,MAAME,MAAM;QACnD,IAAI,CAAC,CAAA,SAAU,CAACC,GAAG,CAACT,UAAUO;QAC9B,IAAI,CAAC,CAAA,MAAO,CAACT,gBAAgB,CAACQ,OAAOC,SAASX;QAC9C,OAAO,IAAM,IAAI,CAAC,CAAA,MAAO,CAACK,mBAAmB,CAACK,OAAOC;IACvD;IAEAV,KACES,KAA4B,EAC5BN,QAAsC,EACtCJ,OAAiC,EACjC;QACA,OAAO,IAAI,CAACS,EAAE,CAACC,OAAON,UAAU;YAAE,GAAGJ,OAAO;YAAEC,MAAM;QAAK;IAC3D;IAEAa,IAAIJ,KAAqC,EAAEN,QAAkB,EAAE;QAC7D,MAAMO,UAAU,IAAI,CAAC,CAAA,SAAU,CAACI,GAAG,CAACX;QACpC,IAAIO,SAAS,IAAI,CAAC,CAAA,MAAO,CAACN,mBAAmB,CAACK,OAAOC;IACvD;IAEAK,KACEN,KAAQ,EACR,GAAGO,IAAgD,EACnD;QACA,OAAO,IAAI,CAAC,CAAA,MAAO,CAACC,aAAa,CAAC,IAAIC,YAAYT,OAAO;YAAEE,QAAQK;QAAK;IAC1E;AACF;AAEA,OAAO,MAAMhB,OAAO,CAACmB,IAAkBV,QACrC,IAAIf,QAAQ,CAAC0B,UAAYD,GAAGnB,IAAI,CAACS,OAAOW,UAAS"}
1
+ {"version":3,"sources":["../../../lib/client/events.ts"],"sourcesContent":["import type { Callback } from '@nmtjs/common'\n\nexport type EventMap = { [K: string]: any[] }\n\n/**\n * Very simple node-like event emitter wrapper around EventTarget\n *\n * @todo add errors and promise rejections handling\n */\nexport class EventEmitter<\n Events extends EventMap = EventMap,\n EventNames extends Extract<keyof Events, string> = Extract<\n keyof Events,\n string\n >,\n> {\n static once(ee: EventEmitter, event: string) {\n return new Promise((resolve) => ee.once(event, resolve))\n }\n\n #target = new EventTarget()\n #listeners = new Map<Callback, Callback>()\n\n on<E extends EventNames>(\n event: E | (Object & string),\n listener: (...args: Events[E]) => void,\n options?: AddEventListenerOptions,\n ) {\n const wrapper = (event) => listener(...event.detail)\n this.#listeners.set(listener, wrapper)\n this.#target.addEventListener(event, wrapper, options)\n return () => this.#target.removeEventListener(event, wrapper)\n }\n\n once<E extends EventNames>(\n event: E | (Object & string),\n listener: (...args: Events[E]) => void,\n options?: AddEventListenerOptions,\n ) {\n return this.on(event, listener, { ...options, once: true })\n }\n\n off(event: EventNames | (Object & string), listener: Callback) {\n const wrapper = this.#listeners.get(listener)\n if (wrapper) this.#target.removeEventListener(event, wrapper)\n }\n\n emit<E extends EventNames | (Object & string)>(\n event: E,\n ...args: E extends EventEmitter ? Events[E] : any[]\n ) {\n return this.#target.dispatchEvent(new CustomEvent(event, { detail: args }))\n }\n}\n"],"names":["EventEmitter","once","ee","event","Promise","resolve","EventTarget","Map","on","listener","options","wrapper","detail","set","addEventListener","removeEventListener","off","get","emit","args","dispatchEvent","CustomEvent"],"mappings":"AASA,OAAO,MAAMA;IAOX,OAAOC,KAAKC,EAAgB,EAAEC,KAAa,EAAE;QAC3C,OAAO,IAAIC,QAAQ,CAACC,UAAYH,GAAGD,IAAI,CAACE,OAAOE;IACjD;IAEA,CAAA,MAAO,GAAG,IAAIC,cAAa;IAC3B,CAAA,SAAU,GAAG,IAAIC,MAAyB;IAE1CC,GACEL,KAA4B,EAC5BM,QAAsC,EACtCC,OAAiC,EACjC;QACA,MAAMC,UAAU,CAACR,QAAUM,YAAYN,MAAMS,MAAM;QACnD,IAAI,CAAC,CAAA,SAAU,CAACC,GAAG,CAACJ,UAAUE;QAC9B,IAAI,CAAC,CAAA,MAAO,CAACG,gBAAgB,CAACX,OAAOQ,SAASD;QAC9C,OAAO,IAAM,IAAI,CAAC,CAAA,MAAO,CAACK,mBAAmB,CAACZ,OAAOQ;IACvD;IAEAV,KACEE,KAA4B,EAC5BM,QAAsC,EACtCC,OAAiC,EACjC;QACA,OAAO,IAAI,CAACF,EAAE,CAACL,OAAOM,UAAU;YAAE,GAAGC,OAAO;YAAET,MAAM;QAAK;IAC3D;IAEAe,IAAIb,KAAqC,EAAEM,QAAkB,EAAE;QAC7D,MAAME,UAAU,IAAI,CAAC,CAAA,SAAU,CAACM,GAAG,CAACR;QACpC,IAAIE,SAAS,IAAI,CAAC,CAAA,MAAO,CAACI,mBAAmB,CAACZ,OAAOQ;IACvD;IAEAO,KACEf,KAAQ,EACR,GAAGgB,IAAgD,EACnD;QACA,OAAO,IAAI,CAAC,CAAA,MAAO,CAACC,aAAa,CAAC,IAAIC,YAAYlB,OAAO;YAAES,QAAQO;QAAK;IAC1E;AACF"}
@@ -1,6 +1,6 @@
1
- import { createPromise } from '@nmtjs/common';
1
+ import { createPromise, onceAborted } from '@nmtjs/common';
2
2
  import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
3
- import { ClientMessageType, ServerMessageType } from "../common/enums.js";
3
+ import { ClientMessageType, ErrorCode, ServerMessageType } from "../common/enums.js";
4
4
  import { EventEmitter } from "./events.js";
5
5
  import { ProtocolClientBlobStream, ProtocolServerBlobStream, ProtocolServerStream } from "./stream.js";
6
6
  export class ProtocolError extends Error {
@@ -104,115 +104,112 @@ export class ProtocolBaseTransformer {
104
104
  }
105
105
  }
106
106
  export class ProtocolBaseClient extends EventEmitter {
107
- transport;
108
- format;
109
- transformer;
110
107
  #clientStreams;
111
108
  #serverStreams;
112
- #serverRPCStreams;
113
- #serverRPCStreamCalls;
114
- #calls;
115
- #callId;
116
- #streamId;
117
- constructor(transport, format, transformer = new ProtocolBaseTransformer()){
109
+ #rpcStreams;
110
+ #rpcStreamData = new Map();
111
+ #calls = new Map();
112
+ #transport;
113
+ #format;
114
+ transformer = new ProtocolBaseTransformer();
115
+ #timeout;
116
+ #callId = 0;
117
+ #streamId = 0;
118
+ constructor(options){
118
119
  super();
119
- this.transport = transport;
120
- this.format = format;
121
- this.transformer = transformer;
122
- this.#serverRPCStreamCalls = new Map();
123
- this.#calls = new Map();
124
- this.#callId = 0;
125
- this.#streamId = 0;
120
+ this.#transport = options.transport;
121
+ this.#format = options.format;
122
+ this.#timeout = options.timeout ?? 60000;
126
123
  this.#clientStreams = new ProtocolClientStreams();
127
124
  this.#serverStreams = new ProtocolServerStreams();
128
- this.#serverRPCStreams = new ProtocolServerStreams();
129
- this.transport.on(`${ServerMessageType.Event}`, (buffer)=>{
130
- const [namespace, event, payload] = this.format.decode(buffer);
125
+ this.#rpcStreams = new ProtocolServerStreams();
126
+ this.#transport.on(`${ServerMessageType.Event}`, (buffer)=>{
127
+ const [namespace, event, payload] = this.#format.decode(buffer);
131
128
  const name = `${namespace}/${event}`;
132
129
  const transformed = this.transformer.decodeEvent(namespace, event, payload);
133
130
  this.emit(name, transformed);
134
131
  });
135
- this.transport.on(`${ServerMessageType.RpcResponse}`, (buffer)=>{
132
+ this.#transport.on(`${ServerMessageType.RpcResponse}`, (buffer)=>{
136
133
  const { call, error, payload } = this.#handleResponse(buffer);
137
134
  if (error) call.reject(error);
138
135
  else call.resolve(payload);
139
136
  });
140
- this.transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer)=>{
137
+ this.#transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer)=>{
141
138
  const { call, response, payload, error } = this.#handleResponse(buffer);
142
139
  if (error) return call.reject(error);
143
140
  console.log('Creating RPC stream', response);
144
141
  const stream = new ProtocolServerStream();
145
- this.#serverRPCStreams.add(response.callId, stream);
146
- this.#serverRPCStreamCalls.set(response.callId, {
142
+ this.#rpcStreams.add(response.callId, stream);
143
+ this.#rpcStreamData.set(response.callId, {
147
144
  namespace: call.namespace,
148
145
  procedure: call.procedure
149
146
  });
150
- call.resolve([
147
+ call.resolve({
151
148
  payload,
152
149
  stream
153
- ]);
150
+ });
154
151
  });
155
- this.transport.on(`${ServerMessageType.RpcStreamChunk}`, async (buffer)=>{
152
+ this.#transport.on(`${ServerMessageType.RpcStreamChunk}`, async (buffer)=>{
156
153
  const callId = decodeNumber(buffer, 'Uint32');
157
154
  console.log('RPC stream chunk', callId);
158
155
  const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
159
156
  if (chunk.byteLength === 0) {
160
- this.#serverRPCStreams.end(callId);
161
- this.#serverRPCStreamCalls.delete(callId);
157
+ this.#rpcStreams.end(callId);
158
+ this.#rpcStreamData.delete(callId);
162
159
  } else {
163
- const call = this.#serverRPCStreamCalls.get(callId);
160
+ const call = this.#rpcStreamData.get(callId);
164
161
  console.log('RPC stream call', call);
165
162
  if (call) {
166
- const payload = this.format.decode(chunk);
163
+ const payload = this.#format.decode(chunk);
167
164
  console.log('RPC stream payload', payload);
168
165
  try {
169
166
  const transformed = this.transformer.decodeRPCChunk(call.namespace, call.procedure, payload);
170
- await this.#serverRPCStreams.push(callId, transformed);
167
+ await this.#rpcStreams.push(callId, transformed);
171
168
  } catch (error) {
172
- this._send(ClientMessageType.RpcStreamAbort, encodeNumber(callId, 'Uint32'));
173
- this.#serverRPCStreams.remove(callId);
174
- this.#serverRPCStreamCalls.delete(callId);
169
+ this.#send(ClientMessageType.RpcStreamAbort, encodeNumber(callId, 'Uint32'));
170
+ this.#rpcStreams.remove(callId);
171
+ this.#rpcStreamData.delete(callId);
175
172
  }
176
173
  }
177
174
  }
178
175
  });
179
- this.transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer)=>{
176
+ this.#transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer)=>{
180
177
  const callId = decodeNumber(buffer, 'Uint32');
181
178
  console.log('RPC stream abort', callId);
182
179
  const call = this.#calls.get(callId);
183
180
  if (call) {
184
181
  this.#serverStreams.end(callId);
185
- this.#serverRPCStreams.abort(callId);
182
+ this.#rpcStreams.abort(callId);
186
183
  }
187
184
  });
188
- this.transport.on(`${ServerMessageType.ServerStreamPush}`, async (buffer)=>{
185
+ this.#transport.on(`${ServerMessageType.ServerStreamPush}`, async (buffer)=>{
189
186
  const streamId = decodeNumber(buffer, 'Uint32');
190
187
  const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT);
191
188
  console.log('Server stream push', streamId, chunk.byteLength);
192
189
  try {
193
190
  await this.#serverStreams.push(streamId, chunk);
194
- this._send(ClientMessageType.ServerStreamPull, encodeNumber(streamId, 'Uint32'));
191
+ this.#send(ClientMessageType.ServerStreamPull, encodeNumber(streamId, 'Uint32'));
195
192
  } catch (error) {
196
- this._send(ClientMessageType.ServerStreamAbort, encodeNumber(streamId, 'Uint32'));
193
+ this.#send(ClientMessageType.ServerStreamAbort, encodeNumber(streamId, 'Uint32'));
197
194
  this.#serverStreams.remove(streamId);
198
195
  }
199
196
  });
200
- this.transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer)=>{
197
+ this.#transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer)=>{
201
198
  const streamId = decodeNumber(buffer, 'Uint32');
202
199
  console.log('Server stream end', streamId);
203
200
  this.#serverStreams.end(streamId);
204
201
  });
205
- this.transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer)=>{
202
+ this.#transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer)=>{
206
203
  const streamId = decodeNumber(buffer, 'Uint32');
207
204
  console.log('Server stream abort', streamId);
208
205
  this.#serverStreams.abort(streamId);
209
206
  });
210
- this.transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer)=>{
207
+ this.#transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer)=>{
211
208
  const streamId = decodeNumber(buffer, 'Uint32');
212
209
  console.log('Client stream abort', streamId);
213
210
  this.#clientStreams.abort(streamId);
214
211
  });
215
- this.transport.on(`${ServerMessageType.ClientStreamPull}`, async (buffer)=>{
212
+ this.#transport.on(`${ServerMessageType.ClientStreamPull}`, async (buffer)=>{
216
213
  const streamId = decodeNumber(buffer, 'Uint32');
217
214
  console.log('Client stream pull', streamId);
218
215
  const size = decodeNumber(buffer, 'Uint32', Uint32Array.BYTES_PER_ELEMENT);
@@ -220,34 +217,39 @@ export class ProtocolBaseClient extends EventEmitter {
220
217
  try {
221
218
  const chunk = await this.#clientStreams.pull(streamId, size);
222
219
  if (chunk) {
223
- this._send(ClientMessageType.ClientStreamPush, concat(streamIdEncoded, chunk));
220
+ this.#send(ClientMessageType.ClientStreamPush, concat(streamIdEncoded, chunk));
224
221
  } else {
225
- this._send(ClientMessageType.ClientStreamEnd, streamIdEncoded);
222
+ this.#send(ClientMessageType.ClientStreamEnd, streamIdEncoded);
226
223
  this.#clientStreams.end(streamId);
227
224
  }
228
225
  } catch (error) {
229
226
  console.error(error);
230
- this._send(ClientMessageType.ClientStreamAbort, streamIdEncoded);
227
+ this.#send(ClientMessageType.ClientStreamAbort, streamIdEncoded);
231
228
  }
232
229
  });
233
230
  }
234
231
  async connect(auth) {
235
- return await this.transport.connect(auth, this.format.contentType);
232
+ return await this.#transport.connect(auth, this.#format.contentType);
236
233
  }
237
234
  async disconnect() {
238
- return await this.transport.disconnect();
235
+ return await this.#transport.disconnect();
239
236
  }
240
- async _send(messageType, buffer) {
237
+ async #send(messageType, buffer) {
241
238
  console.log('Client transport send', ClientMessageType[messageType], buffer.byteLength);
242
- return await this.transport.send(messageType, buffer);
239
+ return await this.#transport.send(messageType, buffer);
243
240
  }
244
241
  async _call(namespace, procedure, payload, options = {}) {
242
+ const timeoutSignal = AbortSignal.timeout(options.timeout || this.#timeout);
243
+ const signal = options.signal ? AbortSignal.any([
244
+ options.signal,
245
+ timeoutSignal
246
+ ]) : timeoutSignal;
245
247
  const callId = ++this.#callId;
246
248
  const call = Object.assign(createPromise(), {
247
249
  namespace,
248
250
  procedure
249
251
  });
250
- const buffer = this.format.encodeRPC({
252
+ const buffer = this.#format.encodeRPC({
251
253
  callId,
252
254
  namespace,
253
255
  procedure,
@@ -263,17 +265,26 @@ export class ProtocolBaseClient extends EventEmitter {
263
265
  return stream;
264
266
  }
265
267
  });
266
- this.transport.send(ClientMessageType.Rpc, buffer).catch(console.error);
268
+ this.#transport.send(ClientMessageType.Rpc, buffer).catch(console.error);
267
269
  this.#calls.set(callId, call);
268
- return call.promise;
270
+ const onAborted = onceAborted(signal).then(()=>{
271
+ if (this.#calls.has(callId)) {
272
+ this.#send(ClientMessageType.RpcAbort, encodeNumber(callId, 'Uint32'));
273
+ }
274
+ throw new ProtocolError(ErrorCode.RequestTimeout, 'Request timeout');
275
+ });
276
+ return Promise.race([
277
+ call.promise,
278
+ onAborted
279
+ ]);
269
280
  }
270
281
  #handleResponse(buffer) {
271
282
  const callStreams = [];
272
- const response = this.format.decodeRPC(buffer, {
283
+ const response = this.#format.decodeRPC(buffer, {
273
284
  addStream: (id, metadata)=>{
274
285
  console.log('Client transport blob stream', id, metadata);
275
286
  const stream = new ProtocolServerBlobStream(id, metadata, ()=>{
276
- this._send(ClientMessageType.ServerStreamPull, encodeNumber(id, 'Uint32'));
287
+ this.#send(ClientMessageType.ServerStreamPull, encodeNumber(id, 'Uint32'));
277
288
  });
278
289
  callStreams.push(stream);
279
290
  this.#serverStreams.add(id, stream);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/client/protocol.ts"],"sourcesContent":["import { type InteractivePromise, createPromise } from '@nmtjs/common'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ClientMessageType, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport { EventEmitter } from './events.ts'\nimport type { BaseClientFormat } from './format.ts'\nimport {\n ProtocolClientBlobStream,\n ProtocolServerBlobStream,\n ProtocolServerStream,\n} from './stream.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 ProtocolClientStreams {\n readonly #collection = new Map<number, ProtocolClientBlobStream>()\n\n get(streamId: number) {\n const stream = this.#collection.get(streamId)\n if (!stream) throw new Error('Stream not found')\n return stream\n }\n\n add(\n source: ReadableStream,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n ) {\n const stream = new ProtocolClientBlobStream(source, streamId, metadata)\n this.#collection.set(streamId, stream)\n return stream\n }\n\n remove(streamId: number) {\n this.#collection.delete(streamId)\n }\n\n abort(streamId: number) {\n const stream = this.get(streamId)\n stream.abort()\n this.remove(streamId)\n }\n\n pull(streamId: number, size: number) {\n const stream = this.get(streamId)\n return stream.read(size)\n }\n\n end(streamId: number) {\n const stream = this.get(streamId)\n stream.end()\n this.remove(streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n readonly #collection = new Map<number, ProtocolServerStream>()\n\n has(streamId: number) {\n return this.#collection.has(streamId)\n }\n\n get(streamId: number) {\n const stream = this.#collection.get(streamId)\n if (!stream) throw new Error('Stream not found')\n return stream\n }\n\n add(streamId: number, stream: ProtocolServerStream) {\n this.#collection.set(streamId, stream)\n return stream\n }\n\n remove(streamId: number) {\n this.#collection.delete(streamId)\n }\n\n abort(streamId: number) {\n if (this.has(streamId)) {\n const stream = this.get(streamId)\n stream.abort()\n this.remove(streamId)\n }\n }\n\n async push(streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(streamId)\n return await stream.push(chunk)\n }\n\n end(streamId: number) {\n const stream = this.get(streamId)\n stream.end()\n this.remove(streamId)\n }\n}\n\nexport interface ProtocolTransport\n extends EventEmitter<{\n [K in `${ServerMessageType}`]: [ArrayBuffer]\n }> {\n connect(\n auth: any,\n contentType: BaseClientFormat['contentType'],\n ): Promise<void>\n disconnect(): Promise<void>\n send(messageType: ClientMessageType, buffer: ArrayBuffer): Promise<void>\n}\n\nexport class ProtocolBaseTransformer {\n encodeRPC(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeRPC(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeRPCChunk(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeEvent(namespace: string, event: string, payload: any) {\n return payload\n }\n}\n\nexport type ProtocolClientCall = InteractivePromise<any> &\n Pick<ProtocolRPC, 'namespace' | 'procedure'>\n\nexport abstract class ProtocolBaseClient<\n T extends Record<string, Record<string, any>>,\n> extends EventEmitter<\n {\n [N in keyof T]: {\n [E in keyof T[N] as `${Extract<N, string>}/${Extract<E, string>}`]: [\n payload: T[N][E],\n ]\n }\n }[keyof T]\n> {\n readonly #clientStreams: ProtocolClientStreams\n readonly #serverStreams: ProtocolServerStreams\n readonly #serverRPCStreams: ProtocolServerStreams\n readonly #serverRPCStreamCalls = new Map<\n number,\n Pick<ProtocolRPC, 'namespace' | 'procedure'>\n >()\n readonly #calls = new Map<number, ProtocolClientCall>()\n\n #callId = 0\n #streamId = 0\n\n constructor(\n protected readonly transport: ProtocolTransport,\n protected readonly format: BaseClientFormat,\n protected readonly transformer: ProtocolBaseTransformer = new ProtocolBaseTransformer(),\n ) {\n super()\n\n this.#clientStreams = new ProtocolClientStreams()\n this.#serverStreams = new ProtocolServerStreams()\n this.#serverRPCStreams = new ProtocolServerStreams()\n\n this.transport.on(`${ServerMessageType.Event}`, (buffer) => {\n const [namespace, event, payload] = this.format.decode(buffer)\n const name = `${namespace}/${event}`\n const transformed = this.transformer.decodeEvent(\n namespace,\n event,\n payload,\n )\n this.emit(name, transformed)\n })\n\n this.transport.on(`${ServerMessageType.RpcResponse}`, (buffer) => {\n const { call, error, payload } = this.#handleResponse(buffer)\n if (error) call.reject(error)\n else call.resolve(payload)\n })\n\n this.transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer) => {\n const { call, response, payload, error } = this.#handleResponse(buffer)\n if (error) return call.reject(error)\n console.log('Creating RPC stream', response)\n const stream = new ProtocolServerStream()\n this.#serverRPCStreams.add(response.callId, stream)\n this.#serverRPCStreamCalls.set(response.callId, {\n namespace: call.namespace,\n procedure: call.procedure,\n })\n call.resolve([payload, stream])\n })\n\n this.transport.on(`${ServerMessageType.RpcStreamChunk}`, async (buffer) => {\n const callId = decodeNumber(buffer, 'Uint32')\n console.log('RPC stream chunk', callId)\n\n const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT)\n if (chunk.byteLength === 0) {\n this.#serverRPCStreams.end(callId)\n this.#serverRPCStreamCalls.delete(callId)\n } else {\n const call = this.#serverRPCStreamCalls.get(callId)\n console.log('RPC stream call', call)\n if (call) {\n const payload = this.format.decode(chunk)\n console.log('RPC stream payload', payload)\n try {\n const transformed = this.transformer.decodeRPCChunk(\n call.namespace,\n call.procedure,\n payload,\n )\n await this.#serverRPCStreams.push(callId, transformed)\n } catch (error) {\n this._send(\n ClientMessageType.RpcStreamAbort,\n encodeNumber(callId, 'Uint32'),\n )\n this.#serverRPCStreams.remove(callId)\n this.#serverRPCStreamCalls.delete(callId)\n }\n }\n }\n })\n\n this.transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer) => {\n const callId = decodeNumber(buffer, 'Uint32')\n console.log('RPC stream abort', callId)\n const call = this.#calls.get(callId)\n if (call) {\n this.#serverStreams.end(callId)\n this.#serverRPCStreams.abort(callId)\n }\n })\n\n this.transport.on(\n `${ServerMessageType.ServerStreamPush}`,\n async (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT)\n console.log('Server stream push', streamId, chunk.byteLength)\n try {\n await this.#serverStreams.push(streamId, chunk)\n this._send(\n ClientMessageType.ServerStreamPull,\n encodeNumber(streamId, 'Uint32'),\n )\n } catch (error) {\n this._send(\n ClientMessageType.ServerStreamAbort,\n encodeNumber(streamId, 'Uint32'),\n )\n this.#serverStreams.remove(streamId)\n }\n },\n )\n\n this.transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Server stream end', streamId)\n this.#serverStreams.end(streamId)\n })\n\n this.transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Server stream abort', streamId)\n this.#serverStreams.abort(streamId)\n })\n\n this.transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Client stream abort', streamId)\n this.#clientStreams.abort(streamId)\n })\n\n this.transport.on(\n `${ServerMessageType.ClientStreamPull}`,\n async (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Client stream pull', streamId)\n const size = decodeNumber(\n buffer,\n 'Uint32',\n Uint32Array.BYTES_PER_ELEMENT,\n )\n const streamIdEncoded = encodeNumber(streamId, 'Uint32')\n try {\n const chunk = await this.#clientStreams.pull(streamId, size)\n if (chunk) {\n this._send(\n ClientMessageType.ClientStreamPush,\n concat(streamIdEncoded, chunk),\n )\n } else {\n this._send(ClientMessageType.ClientStreamEnd, streamIdEncoded)\n this.#clientStreams.end(streamId)\n }\n } catch (error) {\n console.error(error)\n this._send(ClientMessageType.ClientStreamAbort, streamIdEncoded)\n }\n },\n )\n }\n\n async connect(auth: any) {\n return await this.transport.connect(auth, this.format.contentType)\n }\n\n async disconnect() {\n return await this.transport.disconnect()\n }\n\n protected async _send(messageType: ClientMessageType, buffer: ArrayBuffer) {\n console.log(\n 'Client transport send',\n ClientMessageType[messageType],\n buffer.byteLength,\n )\n return await this.transport.send(messageType, buffer)\n }\n\n protected async _call(\n namespace: string,\n procedure: string,\n payload: any,\n options = {},\n ) {\n const callId = ++this.#callId\n const call = Object.assign(createPromise(), {\n namespace,\n procedure,\n })\n const buffer = this.format.encodeRPC(\n {\n callId,\n namespace,\n procedure,\n payload: this.transformer.encodeRPC(namespace, procedure, payload),\n },\n {\n addStream: (blob) => {\n const streamId = ++this.#streamId\n const stream = this.#clientStreams.add(\n blob.source,\n streamId,\n blob.metadata,\n )\n return stream\n },\n getStream: (id) => {\n const stream = this.#clientStreams.get(id)\n return stream\n },\n },\n )\n\n this.transport.send(ClientMessageType.Rpc, buffer).catch(console.error)\n\n this.#calls.set(callId, call)\n\n return call.promise\n }\n\n #handleResponse(buffer: ArrayBuffer) {\n const callStreams: ProtocolServerBlobStream[] = []\n const response = this.format.decodeRPC(buffer, {\n addStream: (id, metadata) => {\n console.log('Client transport blob stream', id, metadata)\n const stream = new ProtocolServerBlobStream(id, metadata, () => {\n this._send(\n ClientMessageType.ServerStreamPull,\n encodeNumber(id, 'Uint32'),\n )\n })\n callStreams.push(stream)\n this.#serverStreams.add(id, stream)\n return stream\n },\n getStream: (id) => {\n return this.#serverStreams.get(id)\n },\n })\n\n console.log('Client transport response', response)\n\n const call = this.#calls.get(response.callId)\n\n if (call) {\n this.#calls.delete(response.callId)\n\n if (response.error) {\n const error = new ProtocolError(\n response.error.code,\n response.error.message,\n response.error.data,\n )\n return { call, response, error }\n } else {\n const payload = this.transformer.decodeRPC(\n call.namespace,\n call.procedure,\n response.payload,\n )\n return { call, response, payload }\n }\n }\n\n for (const stream of callStreams) {\n this.#serverStreams.abort(stream.id)\n }\n\n throw new Error('Call not found')\n }\n}\n"],"names":["createPromise","concat","decodeNumber","encodeNumber","ClientMessageType","ServerMessageType","EventEmitter","ProtocolClientBlobStream","ProtocolServerBlobStream","ProtocolServerStream","ProtocolError","Error","code","data","constructor","message","toString","toJSON","ProtocolClientStreams","Map","get","streamId","stream","add","source","metadata","set","remove","delete","abort","pull","size","read","end","ProtocolServerStreams","has","push","chunk","ProtocolBaseTransformer","encodeRPC","namespace","procedure","payload","decodeRPC","decodeRPCChunk","decodeEvent","event","ProtocolBaseClient","transport","format","transformer","on","Event","buffer","decode","name","transformed","emit","RpcResponse","call","error","reject","resolve","RpcStreamResponse","response","console","log","callId","RpcStreamChunk","slice","Uint32Array","BYTES_PER_ELEMENT","byteLength","_send","RpcStreamAbort","ServerStreamPush","ServerStreamPull","ServerStreamAbort","ServerStreamEnd","ClientStreamAbort","ClientStreamPull","streamIdEncoded","ClientStreamPush","ClientStreamEnd","connect","auth","contentType","disconnect","messageType","send","_call","options","Object","assign","addStream","blob","getStream","id","Rpc","catch","promise","callStreams"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../lib/client/protocol.ts"],"sourcesContent":["import {\n type InteractivePromise,\n createPromise,\n onceAborted,\n} from '@nmtjs/common'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlobMetadata } from '../common/blob.ts'\nimport {\n ClientMessageType,\n ErrorCode,\n ServerMessageType,\n} from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport { EventEmitter } from './events.ts'\nimport type { BaseClientFormat } from './format.ts'\nimport {\n ProtocolClientBlobStream,\n ProtocolServerBlobStream,\n ProtocolServerStream,\n} from './stream.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 ProtocolClientStreams {\n readonly #collection = new Map<number, ProtocolClientBlobStream>()\n\n get(streamId: number) {\n const stream = this.#collection.get(streamId)\n if (!stream) throw new Error('Stream not found')\n return stream\n }\n\n add(\n source: ReadableStream,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n ) {\n const stream = new ProtocolClientBlobStream(source, streamId, metadata)\n this.#collection.set(streamId, stream)\n return stream\n }\n\n remove(streamId: number) {\n this.#collection.delete(streamId)\n }\n\n abort(streamId: number) {\n const stream = this.get(streamId)\n stream.abort()\n this.remove(streamId)\n }\n\n pull(streamId: number, size: number) {\n const stream = this.get(streamId)\n return stream.read(size)\n }\n\n end(streamId: number) {\n const stream = this.get(streamId)\n stream.end()\n this.remove(streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n readonly #collection = new Map<number, ProtocolServerStream>()\n\n has(streamId: number) {\n return this.#collection.has(streamId)\n }\n\n get(streamId: number) {\n const stream = this.#collection.get(streamId)\n if (!stream) throw new Error('Stream not found')\n return stream\n }\n\n add(streamId: number, stream: ProtocolServerStream) {\n this.#collection.set(streamId, stream)\n return stream\n }\n\n remove(streamId: number) {\n this.#collection.delete(streamId)\n }\n\n abort(streamId: number) {\n if (this.has(streamId)) {\n const stream = this.get(streamId)\n stream.abort()\n this.remove(streamId)\n }\n }\n\n async push(streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(streamId)\n return await stream.push(chunk)\n }\n\n end(streamId: number) {\n const stream = this.get(streamId)\n stream.end()\n this.remove(streamId)\n }\n}\n\nexport interface ProtocolTransport\n extends EventEmitter<{\n [K in `${ServerMessageType}`]: [ArrayBuffer]\n }> {\n connect(\n auth: any,\n contentType: BaseClientFormat['contentType'],\n ): Promise<void>\n disconnect(): Promise<void>\n send(messageType: ClientMessageType, buffer: ArrayBuffer): Promise<void>\n}\n\nexport class ProtocolBaseTransformer {\n encodeRPC(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeRPC(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeRPCChunk(namespace: string, procedure: string, payload: any) {\n return payload\n }\n decodeEvent(namespace: string, event: string, payload: any) {\n return payload\n }\n}\n\nexport type ProtocolClientCall = InteractivePromise<any> &\n Pick<ProtocolRPC, 'namespace' | 'procedure'>\n\nexport type ProtocolBaseClientOptions = {\n transport: ProtocolTransport\n format: BaseClientFormat\n transformer?: ProtocolBaseTransformer\n timeout?: number\n}\n\nexport type ProtocolBaseClientCallOptions = {\n signal?: AbortSignal\n timeout?: number\n}\n\nexport abstract class ProtocolBaseClient<\n T extends Record<string, Record<string, any>>,\n> extends EventEmitter<\n {\n [N in keyof T]: {\n [E in keyof T[N] as `${Extract<N, string>}/${Extract<E, string>}`]: [\n payload: T[N][E],\n ]\n }\n }[keyof T]\n> {\n readonly #clientStreams: ProtocolClientStreams\n readonly #serverStreams: ProtocolServerStreams\n readonly #rpcStreams: ProtocolServerStreams\n readonly #rpcStreamData = new Map<\n number,\n Pick<ProtocolRPC, 'namespace' | 'procedure'>\n >()\n readonly #calls = new Map<number, ProtocolClientCall>()\n\n readonly #transport: ProtocolTransport\n readonly #format: BaseClientFormat\n readonly transformer: ProtocolBaseTransformer = new ProtocolBaseTransformer()\n readonly #timeout: number\n\n #callId = 0\n #streamId = 0\n\n constructor(options: ProtocolBaseClientOptions) {\n super()\n\n this.#transport = options.transport\n this.#format = options.format\n this.#timeout = options.timeout ?? 60000\n\n this.#clientStreams = new ProtocolClientStreams()\n this.#serverStreams = new ProtocolServerStreams()\n this.#rpcStreams = new ProtocolServerStreams()\n\n this.#transport.on(`${ServerMessageType.Event}`, (buffer) => {\n const [namespace, event, payload] = this.#format.decode(buffer)\n const name = `${namespace}/${event}`\n const transformed = this.transformer.decodeEvent(\n namespace,\n event,\n payload,\n )\n this.emit(name, transformed)\n })\n\n this.#transport.on(`${ServerMessageType.RpcResponse}`, (buffer) => {\n const { call, error, payload } = this.#handleResponse(buffer)\n if (error) call.reject(error)\n else call.resolve(payload)\n })\n\n this.#transport.on(`${ServerMessageType.RpcStreamResponse}`, (buffer) => {\n const { call, response, payload, error } = this.#handleResponse(buffer)\n if (error) return call.reject(error)\n console.log('Creating RPC stream', response)\n const stream = new ProtocolServerStream()\n this.#rpcStreams.add(response.callId, stream)\n this.#rpcStreamData.set(response.callId, {\n namespace: call.namespace,\n procedure: call.procedure,\n })\n call.resolve({ payload, stream })\n })\n\n this.#transport.on(\n `${ServerMessageType.RpcStreamChunk}`,\n async (buffer) => {\n const callId = decodeNumber(buffer, 'Uint32')\n console.log('RPC stream chunk', callId)\n\n const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT)\n if (chunk.byteLength === 0) {\n this.#rpcStreams.end(callId)\n this.#rpcStreamData.delete(callId)\n } else {\n const call = this.#rpcStreamData.get(callId)\n console.log('RPC stream call', call)\n if (call) {\n const payload = this.#format.decode(chunk)\n console.log('RPC stream payload', payload)\n try {\n const transformed = this.transformer.decodeRPCChunk(\n call.namespace,\n call.procedure,\n payload,\n )\n await this.#rpcStreams.push(callId, transformed)\n } catch (error) {\n this.#send(\n ClientMessageType.RpcStreamAbort,\n encodeNumber(callId, 'Uint32'),\n )\n this.#rpcStreams.remove(callId)\n this.#rpcStreamData.delete(callId)\n }\n }\n }\n },\n )\n\n this.#transport.on(`${ServerMessageType.RpcStreamAbort}`, (buffer) => {\n const callId = decodeNumber(buffer, 'Uint32')\n console.log('RPC stream abort', callId)\n const call = this.#calls.get(callId)\n if (call) {\n this.#serverStreams.end(callId)\n this.#rpcStreams.abort(callId)\n }\n })\n\n this.#transport.on(\n `${ServerMessageType.ServerStreamPush}`,\n async (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n const chunk = buffer.slice(Uint32Array.BYTES_PER_ELEMENT)\n console.log('Server stream push', streamId, chunk.byteLength)\n try {\n await this.#serverStreams.push(streamId, chunk)\n this.#send(\n ClientMessageType.ServerStreamPull,\n encodeNumber(streamId, 'Uint32'),\n )\n } catch (error) {\n this.#send(\n ClientMessageType.ServerStreamAbort,\n encodeNumber(streamId, 'Uint32'),\n )\n this.#serverStreams.remove(streamId)\n }\n },\n )\n\n this.#transport.on(`${ServerMessageType.ServerStreamEnd}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Server stream end', streamId)\n this.#serverStreams.end(streamId)\n })\n\n this.#transport.on(`${ServerMessageType.ServerStreamAbort}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Server stream abort', streamId)\n this.#serverStreams.abort(streamId)\n })\n\n this.#transport.on(`${ServerMessageType.ClientStreamAbort}`, (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Client stream abort', streamId)\n this.#clientStreams.abort(streamId)\n })\n\n this.#transport.on(\n `${ServerMessageType.ClientStreamPull}`,\n async (buffer) => {\n const streamId = decodeNumber(buffer, 'Uint32')\n console.log('Client stream pull', streamId)\n const size = decodeNumber(\n buffer,\n 'Uint32',\n Uint32Array.BYTES_PER_ELEMENT,\n )\n const streamIdEncoded = encodeNumber(streamId, 'Uint32')\n try {\n const chunk = await this.#clientStreams.pull(streamId, size)\n if (chunk) {\n this.#send(\n ClientMessageType.ClientStreamPush,\n concat(streamIdEncoded, chunk),\n )\n } else {\n this.#send(ClientMessageType.ClientStreamEnd, streamIdEncoded)\n this.#clientStreams.end(streamId)\n }\n } catch (error) {\n console.error(error)\n this.#send(ClientMessageType.ClientStreamAbort, streamIdEncoded)\n }\n },\n )\n }\n\n async connect(auth: any) {\n return await this.#transport.connect(auth, this.#format.contentType)\n }\n\n async disconnect() {\n return await this.#transport.disconnect()\n }\n\n async #send(messageType: ClientMessageType, buffer: ArrayBuffer) {\n console.log(\n 'Client transport send',\n ClientMessageType[messageType],\n buffer.byteLength,\n )\n return await this.#transport.send(messageType, buffer)\n }\n\n protected async _call(\n namespace: string,\n procedure: string,\n payload: any,\n options: ProtocolBaseClientCallOptions = {},\n ) {\n const timeoutSignal = AbortSignal.timeout(options.timeout || this.#timeout)\n const signal = options.signal\n ? AbortSignal.any([options.signal, timeoutSignal])\n : timeoutSignal\n\n const callId = ++this.#callId\n const call = Object.assign(createPromise(), {\n namespace,\n procedure,\n })\n const buffer = this.#format.encodeRPC(\n {\n callId,\n namespace,\n procedure,\n payload: this.transformer.encodeRPC(namespace, procedure, payload),\n },\n {\n addStream: (blob) => {\n const streamId = ++this.#streamId\n const stream = this.#clientStreams.add(\n blob.source,\n streamId,\n blob.metadata,\n )\n return stream\n },\n getStream: (id) => {\n const stream = this.#clientStreams.get(id)\n return stream\n },\n },\n )\n\n this.#transport.send(ClientMessageType.Rpc, buffer).catch(console.error)\n\n this.#calls.set(callId, call)\n\n const onAborted = onceAborted(signal).then(() => {\n if (this.#calls.has(callId)) {\n this.#send(ClientMessageType.RpcAbort, encodeNumber(callId, 'Uint32'))\n }\n throw new ProtocolError(ErrorCode.RequestTimeout, 'Request timeout')\n })\n\n return Promise.race([call.promise, onAborted])\n }\n\n #handleResponse(buffer: ArrayBuffer) {\n const callStreams: ProtocolServerBlobStream[] = []\n const response = this.#format.decodeRPC(buffer, {\n addStream: (id, metadata) => {\n console.log('Client transport blob stream', id, metadata)\n const stream = new ProtocolServerBlobStream(id, metadata, () => {\n this.#send(\n ClientMessageType.ServerStreamPull,\n encodeNumber(id, 'Uint32'),\n )\n })\n callStreams.push(stream)\n this.#serverStreams.add(id, stream)\n return stream\n },\n getStream: (id) => {\n return this.#serverStreams.get(id)\n },\n })\n\n console.log('Client transport response', response)\n\n const call = this.#calls.get(response.callId)\n\n if (call) {\n this.#calls.delete(response.callId)\n\n if (response.error) {\n const error = new ProtocolError(\n response.error.code,\n response.error.message,\n response.error.data,\n )\n return { call, response, error }\n } else {\n const payload = this.transformer.decodeRPC(\n call.namespace,\n call.procedure,\n response.payload,\n )\n return { call, response, payload }\n }\n }\n\n for (const stream of callStreams) {\n this.#serverStreams.abort(stream.id)\n }\n\n throw new Error('Call not found')\n }\n}\n"],"names":["createPromise","onceAborted","concat","decodeNumber","encodeNumber","ClientMessageType","ErrorCode","ServerMessageType","EventEmitter","ProtocolClientBlobStream","ProtocolServerBlobStream","ProtocolServerStream","ProtocolError","Error","code","data","constructor","message","toString","toJSON","ProtocolClientStreams","Map","get","streamId","stream","add","source","metadata","set","remove","delete","abort","pull","size","read","end","ProtocolServerStreams","has","push","chunk","ProtocolBaseTransformer","encodeRPC","namespace","procedure","payload","decodeRPC","decodeRPCChunk","decodeEvent","event","ProtocolBaseClient","transformer","options","transport","format","timeout","on","Event","buffer","decode","name","transformed","emit","RpcResponse","call","error","reject","resolve","RpcStreamResponse","response","console","log","callId","RpcStreamChunk","slice","Uint32Array","BYTES_PER_ELEMENT","byteLength","RpcStreamAbort","ServerStreamPush","ServerStreamPull","ServerStreamAbort","ServerStreamEnd","ClientStreamAbort","ClientStreamPull","streamIdEncoded","ClientStreamPush","ClientStreamEnd","connect","auth","contentType","disconnect","messageType","send","_call","timeoutSignal","AbortSignal","signal","any","Object","assign","addStream","blob","getStream","id","Rpc","catch","onAborted","then","RpcAbort","RequestTimeout","Promise","race","promise","callStreams"],"mappings":"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"}
@@ -51,9 +51,8 @@ export class ProtocolClientBlobStream extends TransformStream {
51
51
  this.#reader.cancel(error);
52
52
  }
53
53
  async end() {
54
- if (!this.writable.locked && await this.writable.getWriter().closed) {
55
- await this.writable.close();
56
- }
54
+ if (!this.writable.locked) await this.writable.close();
55
+ else await this.writable.abort(new Error('Stream closed'));
57
56
  }
58
57
  }
59
58
  export class ProtocolServerStream extends TransformStream {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/client/stream.ts"],"sourcesContent":["import { type Callback, defer } from '@nmtjs/common'\nimport { encodeText } from '../common/binary.ts'\nimport type { ProtocolBlobMetadata } from '../common/blob.ts'\n\nexport class ProtocolClientBlobStream extends TransformStream<\n any,\n ArrayBuffer\n> {\n #queue: ArrayBuffer\n #reader: ReadableStreamDefaultReader\n\n constructor(\n readonly source: ReadableStream,\n readonly id: number,\n readonly metadata: ProtocolBlobMetadata,\n ) {\n super({\n start: () => {\n defer(() => source.pipeThrough(this))\n },\n transform: (chunk, controller) => {\n if (chunk instanceof ArrayBuffer) {\n controller.enqueue(chunk)\n } else if (chunk instanceof Uint8Array) {\n controller.enqueue(chunk.buffer)\n } else if (typeof chunk === 'string') {\n controller.enqueue(encodeText(chunk))\n } else {\n throw new Error(\n 'Invalid chunk data type. Expected ArrayBuffer, Uint8Array, or string.',\n )\n }\n },\n })\n\n this.#queue = new ArrayBuffer(0)\n this.#reader = this.readable.getReader()\n }\n\n async read(size: number) {\n if (this.#queue.byteLength >= size) {\n const chunk = this.#queue.slice(0, size)\n const remaining = this.#queue.slice(size)\n this.#queue = remaining\n return chunk\n } else {\n const { done, value } = await this.#reader.read()\n if (!done) {\n const buffer = value as ArrayBuffer\n const chunk = buffer.slice(0, size)\n const remaining = buffer.slice(size)\n this.#queue = remaining\n return chunk\n }\n return null\n }\n }\n\n abort(error = new Error('Stream aborted')) {\n this.#reader.cancel(error)\n }\n\n async end() {\n if (!this.writable.locked && (await this.writable.getWriter().closed)) {\n await this.writable.close()\n }\n }\n}\n\nexport class ProtocolServerStream<T = any> extends TransformStream<any, T> {\n #writer: WritableStreamDefaultWriter\n\n constructor(start?: Callback) {\n super({ start })\n this.#writer = this.writable.getWriter()\n }\n\n async *[Symbol.asyncIterator]() {\n const reader = this.readable.getReader()\n while (true) {\n const { done, value } = await reader.read()\n if (!done) yield value\n else return void 0\n }\n }\n\n async push(chunk: any) {\n await this.#writer.write(chunk)\n }\n\n async end() {\n await this.#writer.close()\n }\n\n abort(error = new Error('Stream aborted')) {\n this.#writer.abort(error)\n }\n}\n\nexport class ProtocolServerBlobStream extends ProtocolServerStream<ArrayBuffer> {\n constructor(\n readonly id: number,\n readonly metadata: ProtocolBlobMetadata,\n start: Callback,\n ) {\n super(start)\n }\n\n push(chunk: ArrayBuffer) {\n return super.push(chunk)\n }\n\n end() {\n return super.end()\n }\n}\n"],"names":["defer","encodeText","ProtocolClientBlobStream","TransformStream","constructor","source","id","metadata","start","pipeThrough","transform","chunk","controller","ArrayBuffer","enqueue","Uint8Array","buffer","Error","readable","getReader","read","size","byteLength","slice","remaining","done","value","abort","error","cancel","end","writable","locked","getWriter","closed","close","ProtocolServerStream","Symbol","asyncIterator","reader","push","write","ProtocolServerBlobStream"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../lib/client/stream.ts"],"sourcesContent":["import { type Callback, defer } from '@nmtjs/common'\nimport { encodeText } from '../common/binary.ts'\nimport type { ProtocolBlobMetadata } from '../common/blob.ts'\n\nexport class ProtocolClientBlobStream extends TransformStream<\n any,\n ArrayBuffer\n> {\n #queue: ArrayBuffer\n #reader: ReadableStreamDefaultReader\n\n constructor(\n readonly source: ReadableStream,\n readonly id: number,\n readonly metadata: ProtocolBlobMetadata,\n ) {\n super({\n start: () => {\n defer(() => source.pipeThrough(this))\n },\n transform: (chunk, controller) => {\n if (chunk instanceof ArrayBuffer) {\n controller.enqueue(chunk)\n } else if (chunk instanceof Uint8Array) {\n controller.enqueue(chunk.buffer as unknown as ArrayBuffer)\n } else if (typeof chunk === 'string') {\n controller.enqueue(encodeText(chunk))\n } else {\n throw new Error(\n 'Invalid chunk data type. Expected ArrayBuffer, Uint8Array, or string.',\n )\n }\n },\n })\n\n this.#queue = new ArrayBuffer(0)\n this.#reader = this.readable.getReader()\n }\n\n async read(size: number) {\n if (this.#queue.byteLength >= size) {\n const chunk = this.#queue.slice(0, size)\n const remaining = this.#queue.slice(size)\n this.#queue = remaining\n return chunk\n } else {\n const { done, value } = await this.#reader.read()\n if (!done) {\n const buffer = value as ArrayBuffer\n const chunk = buffer.slice(0, size)\n const remaining = buffer.slice(size)\n this.#queue = remaining\n return chunk\n }\n return null\n }\n }\n\n abort(error = new Error('Stream aborted')) {\n this.#reader.cancel(error)\n }\n\n async end() {\n if (!this.writable.locked) await this.writable.close()\n else await this.writable.abort(new Error('Stream closed'))\n }\n}\n\nexport interface ProtocolServerStreamInterface<T = any> {\n [Symbol.asyncIterator](): AsyncGenerator<T>\n abort(error?: Error): void\n}\n\nexport class ProtocolServerStream<T = any>\n extends TransformStream<any, T>\n implements ProtocolServerStreamInterface<T>\n{\n #writer: WritableStreamDefaultWriter\n\n constructor(start?: Callback) {\n super({ start })\n this.#writer = this.writable.getWriter()\n }\n\n async *[Symbol.asyncIterator]() {\n const reader = this.readable.getReader()\n while (true) {\n const { done, value } = await reader.read()\n if (!done) yield value\n else return void 0\n }\n }\n\n async push(chunk: any) {\n await this.#writer.write(chunk)\n }\n\n async end() {\n await this.#writer.close()\n }\n\n abort(error = new Error('Stream aborted')) {\n this.#writer.abort(error)\n }\n}\n\nexport class ProtocolServerBlobStream extends ProtocolServerStream<ArrayBuffer> {\n constructor(\n readonly id: number,\n readonly metadata: ProtocolBlobMetadata,\n start: Callback,\n ) {\n super(start)\n }\n\n push(chunk: ArrayBuffer) {\n return super.push(chunk)\n }\n\n end() {\n return super.end()\n }\n}\n"],"names":["defer","encodeText","ProtocolClientBlobStream","TransformStream","constructor","source","id","metadata","start","pipeThrough","transform","chunk","controller","ArrayBuffer","enqueue","Uint8Array","buffer","Error","readable","getReader","read","size","byteLength","slice","remaining","done","value","abort","error","cancel","end","writable","locked","close","ProtocolServerStream","getWriter","Symbol","asyncIterator","reader","push","write","ProtocolServerBlobStream"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/server/api.ts"],"sourcesContent":["import type { Container } from '@nmtjs/core'\nimport type { Hook } from '@nmtjs/core'\nimport type { Connection } from './connection.ts'\n\nexport type ProtocolApiCallOptions = {\n connection: Connection\n namespace: string\n procedure: string\n container: Container\n payload: any\n signal: AbortSignal\n}\n\nexport type ProtocolAnyIterable<T> =\n | (() => AsyncGenerator<T>)\n // | (() => Generator<T>)\n | AsyncIterable<T>\n// | Iterable<T>\n\nexport interface ProtocolApiCallBaseResult {\n output: unknown\n}\nexport interface ProtocolApiCallSubscriptionResult\n extends ProtocolApiCallBaseResult {\n subscription: never\n}\n\nexport interface ProtocolApiCallIterableResult\n extends ProtocolApiCallBaseResult {\n iterable: ProtocolAnyIterable<unknown>\n}\n\nexport type ProtocolApiCallResult =\n | ProtocolApiCallBaseResult\n | ProtocolApiCallSubscriptionResult\n | ProtocolApiCallIterableResult\n\nexport interface ProtocolApi {\n call(options: ProtocolApiCallOptions): Promise<ProtocolApiCallResult>\n}\n\ndeclare module '@nmtjs/core' {\n export interface HookType {\n [Hook.OnConnect]: (connection: Connection) => any\n [Hook.OnDisconnect]: (connection: Connection) => any\n }\n}\n"],"names":[],"mappings":"AAqCA,WAEC"}
1
+ {"version":3,"sources":["../../../lib/server/api.ts"],"sourcesContent":["import type { Container } from '@nmtjs/core'\nimport type { Hook } from '@nmtjs/core'\nimport type { Connection } from './connection.ts'\n\nexport type ProtocolApiCallOptions = {\n connection: Connection\n namespace: string\n procedure: string\n container: Container\n payload: any\n signal: AbortSignal\n}\n\nexport type ProtocolAnyIterable<T> =\n | (() => AsyncGenerator<T>)\n | AsyncIterable<T>\n\nexport interface ProtocolApiCallBaseResult {\n output: unknown\n}\nexport interface ProtocolApiCallSubscriptionResult\n extends ProtocolApiCallBaseResult {\n subscription: never\n}\n\nexport interface ProtocolApiCallIterableResult\n extends ProtocolApiCallBaseResult {\n iterable: ProtocolAnyIterable<unknown>\n onFinish?: () => void\n}\n\nexport type ProtocolApiCallResult =\n | ProtocolApiCallBaseResult\n | ProtocolApiCallSubscriptionResult\n | ProtocolApiCallIterableResult\n\nexport interface ProtocolApi {\n call(options: ProtocolApiCallOptions): Promise<ProtocolApiCallResult>\n}\n\ndeclare module '@nmtjs/core' {\n export interface HookType {\n [Hook.OnConnect]: (connection: Connection) => any\n [Hook.OnDisconnect]: (connection: Connection) => any\n }\n}\n"],"names":[],"mappings":"AAoCA,WAEC"}
@@ -12,6 +12,7 @@ export class ConnectionContext {
12
12
  calls = new Map();
13
13
  clientStreams = new Map();
14
14
  serverStreams = new Map();
15
+ rpcStreams = new Map();
15
16
  container;
16
17
  format;
17
18
  constructor(container, format){
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../lib/server/connection.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\n// import type { TAnyEventContract } from '@nmtjs/contract'\nimport type { InteractivePromise } from '@nmtjs/common'\nimport type { Container } from '@nmtjs/core'\nimport type { ProtocolApiCallResult } from './api.ts'\nimport type { BaseServerDecoder, BaseServerEncoder } from './format.ts'\nimport type { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\n\n// export type NotifyFn = <T extends TAnyEventContract>(\n// connection: Connection,\n// contract: T,\n// payload: t.infer.input.decoded<T['payload']>,\n// ) => Promise<boolean>\n\n// export type ConnectionNotifyFn = (\n// contract: TAnyEventContract,\n// payload: unknown,\n// ) => Promise<boolean>\n\nexport type ConnectionOptions<Data = unknown> = {\n id?: string\n data: Data\n}\n\nexport class Connection<Data = unknown> {\n readonly id: string\n readonly data: Data\n\n constructor(options: ConnectionOptions<Data>) {\n this.id = options.id ?? randomUUID()\n this.data = options.data\n }\n}\n\nexport type ConnectionCall<T = unknown> = InteractivePromise<T> & {\n abort: AbortController['abort']\n}\n\nexport class ConnectionContext {\n streamId = 1\n calls = new Map<number, ConnectionCall<ProtocolApiCallResult>>()\n clientStreams = new Map<number, ProtocolClientStream>()\n serverStreams = new Map<number, ProtocolServerStream>()\n container: Container\n format: {\n encoder: BaseServerEncoder\n decoder: BaseServerDecoder\n }\n\n constructor(\n container: ConnectionContext['container'],\n format: ConnectionContext['format'],\n ) {\n this.container = container\n this.format = format\n }\n}\n"],"names":["randomUUID","Connection","id","data","constructor","options","ConnectionContext","streamId","calls","Map","clientStreams","serverStreams","container","format"],"mappings":"AAAA,SAASA,UAAU,QAAQ,cAAa;AAwBxC,OAAO,MAAMC;IACFC,GAAU;IACVC,KAAU;IAEnBC,YAAYC,OAAgC,CAAE;QAC5C,IAAI,CAACH,EAAE,GAAGG,QAAQH,EAAE,IAAIF;QACxB,IAAI,CAACG,IAAI,GAAGE,QAAQF,IAAI;IAC1B;AACF;AAMA,OAAO,MAAMG;IACXC,WAAW,EAAC;IACZC,QAAQ,IAAIC,MAAoD;IAChEC,gBAAgB,IAAID,MAAmC;IACvDE,gBAAgB,IAAIF,MAAmC;IACvDG,UAAoB;IACpBC,OAGC;IAEDT,YACEQ,SAAyC,EACzCC,MAAmC,CACnC;QACA,IAAI,CAACD,SAAS,GAAGA;QACjB,IAAI,CAACC,MAAM,GAAGA;IAChB;AACF"}
1
+ {"version":3,"sources":["../../../lib/server/connection.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport type { InteractivePromise } from '@nmtjs/common'\nimport type { Container } from '@nmtjs/core'\nimport type { ProtocolApiCallResult } from './api.ts'\nimport type { BaseServerDecoder, BaseServerEncoder } from './format.ts'\nimport type { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\n\nexport type ConnectionOptions<Data = unknown> = {\n id?: string\n data: Data\n}\n\nexport class Connection<Data = unknown> {\n readonly id: string\n readonly data: Data\n\n constructor(options: ConnectionOptions<Data>) {\n this.id = options.id ?? randomUUID()\n this.data = options.data\n }\n}\n\nexport type ConnectionCall<T = unknown> = InteractivePromise<T> & {\n abort: AbortController['abort']\n}\n\nexport class ConnectionContext {\n streamId = 1\n calls = new Map<number, ConnectionCall<ProtocolApiCallResult>>()\n clientStreams = new Map<number, ProtocolClientStream>()\n serverStreams = new Map<number, ProtocolServerStream>()\n rpcStreams = new Map<number, AbortController>()\n container: Container\n format: {\n encoder: BaseServerEncoder\n decoder: BaseServerDecoder\n }\n\n constructor(\n container: ConnectionContext['container'],\n format: ConnectionContext['format'],\n ) {\n this.container = container\n this.format = format\n }\n}\n"],"names":["randomUUID","Connection","id","data","constructor","options","ConnectionContext","streamId","calls","Map","clientStreams","serverStreams","rpcStreams","container","format"],"mappings":"AAAA,SAASA,UAAU,QAAQ,cAAa;AAYxC,OAAO,MAAMC;IACFC,GAAU;IACVC,KAAU;IAEnBC,YAAYC,OAAgC,CAAE;QAC5C,IAAI,CAACH,EAAE,GAAGG,QAAQH,EAAE,IAAIF;QACxB,IAAI,CAACG,IAAI,GAAGE,QAAQF,IAAI;IAC1B;AACF;AAMA,OAAO,MAAMG;IACXC,WAAW,EAAC;IACZC,QAAQ,IAAIC,MAAoD;IAChEC,gBAAgB,IAAID,MAAmC;IACvDE,gBAAgB,IAAIF,MAAmC;IACvDG,aAAa,IAAIH,MAA8B;IAC/CI,UAAoB;IACpBC,OAGC;IAEDV,YACES,SAAyC,EACzCC,MAAmC,CACnC;QACA,IAAI,CAACD,SAAS,GAAGA;QACjB,IAAI,CAACC,MAAM,GAAGA;IAChB;AACF"}
@@ -1,4 +1,4 @@
1
- import { createPromise, throwError } from '@nmtjs/common';
1
+ import { createPromise, 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";
@@ -63,7 +63,7 @@ export class ProtocolConnections {
63
63
  concurrent: true
64
64
  }, connection);
65
65
  this.#collection.delete(connectionId);
66
- const { calls, serverStreams, clientStreams, container } = context;
66
+ const { calls, serverStreams, clientStreams, rpcStreams, container } = context;
67
67
  for (const call of calls.values()){
68
68
  call.reject(new Error('Connection closed'));
69
69
  }
@@ -73,6 +73,9 @@ export class ProtocolConnections {
73
73
  for (const stream of serverStreams.values()){
74
74
  stream.destroy(new Error('Connection closed'));
75
75
  }
76
+ for (const stream of rpcStreams.values()){
77
+ stream.abort(new Error('Connection closed'));
78
+ }
76
79
  try {
77
80
  await container.dispose();
78
81
  } catch (error) {
@@ -169,7 +172,7 @@ export class Protocol {
169
172
  this.clientStreams = new ProtocolClientStreams(this.connections);
170
173
  this.serverStreams = new ProtocolServerStreams(this.connections);
171
174
  }
172
- async call(connectionId, rpc, params = {}) {
175
+ async rpc(connectionId, rpc, params = {}) {
173
176
  const { connection, context, transport } = this.connections.get(connectionId);
174
177
  const { calls, format } = context;
175
178
  const { callId, namespace, procedure, payload } = rpc;
@@ -222,14 +225,20 @@ export class Protocol {
222
225
  } else if ('iterable' in response) {
223
226
  transport.send(connection, ServerMessageType.RpcStreamResponse, responseEncoded);
224
227
  try {
228
+ const ab = new AbortController();
229
+ context.rpcStreams.set(callId, ab);
225
230
  const iterable = typeof response.iterable === 'function' ? response.iterable() : response.iterable;
226
231
  for await (const chunk of iterable){
232
+ if (ab.signal.aborted) break;
227
233
  const chunkEncoded = format.encoder.encode(chunk);
228
234
  transport.send(connection, ServerMessageType.RpcStreamChunk, concat(callIdEncoded, chunkEncoded));
229
235
  }
230
236
  } catch (error) {
231
237
  this.application.logger.error(error);
232
238
  transport.send(connection, ServerMessageType.RpcStreamAbort, callIdEncoded);
239
+ } finally{
240
+ context.rpcStreams.delete(callId);
241
+ response.onFinish && defer(response.onFinish);
233
242
  }
234
243
  } else {
235
244
  transport.send(connection, ServerMessageType.RpcResponse, responseEncoded);
@@ -263,7 +272,7 @@ export class Protocol {
263
272
  });
264
273
  }
265
274
  }
266
- async callRaw(connectionId, buffer, params = {}) {
275
+ async rpcRaw(connectionId, buffer, params = {}) {
267
276
  const { connection, context, transport } = this.connections.get(connectionId);
268
277
  const { format } = context;
269
278
  const rpc = format.decoder.decodeRPC(buffer, {
@@ -276,16 +285,25 @@ export class Protocol {
276
285
  return this.serverStreams.get(connectionId, id);
277
286
  }
278
287
  });
279
- return await this.call(connectionId, rpc, params);
288
+ return await this.rpc(connectionId, rpc, params);
280
289
  }
281
- callAbort(connectionId, callId) {
290
+ rpcAbort(connectionId, callId) {
282
291
  const { context } = this.connections.get(connectionId);
283
292
  const call = context.calls.get(callId) ?? throwError('Call not found');
284
293
  call.abort();
285
294
  }
286
- callAbortRaw(connectionId, buffer) {
295
+ rpcAbortRaw(connectionId, buffer) {
296
+ const callId = decodeNumber(buffer, 'Uint32');
297
+ return this.rpcAbort(connectionId, callId);
298
+ }
299
+ rpcStreamAbort(connectionId, callId) {
300
+ const { context } = this.connections.get(connectionId);
301
+ const ab = context.rpcStreams.get(callId) ?? throwError('Call stream not found');
302
+ ab.abort();
303
+ }
304
+ rpcStreamAbortRaw(connectionId, buffer) {
287
305
  const callId = decodeNumber(buffer, 'Uint32');
288
- return this.callAbort(connectionId, callId);
306
+ return this.rpcStreamAbort(connectionId, callId);
289
307
  }
290
308
  notify(connectionId, event, payload) {
291
309
  throw Error('Unimplemented');