@nmtjs/ws-transport 0.10.2 → 0.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -169,7 +169,7 @@ export class WsTransportServer {
169
169
  acceptType,
170
170
  contentType: isBlob ? "*/*" : contentType
171
171
  });
172
- let payload = undefined;
172
+ let payload;
173
173
  if (body) {
174
174
  if (isBlob) {
175
175
  const type = contentType || "application/octet-stream";
@@ -227,7 +227,6 @@ export class WsTransportServer {
227
227
  });
228
228
  ac.signal.addEventListener("abort", () => stream.destroy(), { once: true });
229
229
  stream.on("data", (chunk) => {
230
- console.log({ chunk });
231
230
  if (ac.signal.aborted) return;
232
231
  const buf = Buffer.from(chunk);
233
232
  const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
@@ -1 +1 @@
1
- {"mappings":"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","names":["context: TransportPluginContext","options: WsTransportOptions","ws: WsTransportSocket","error: any","connection: Connection<WsConnectionData>","messageType: ServerMessageType","buffer: ArrayBuffer","res: HttpResponse","req: HttpRequest","metadata: ProtocolApiCallOptions['metadata']","format: ReturnType<typeof getFormat>","payload: any","stream: Readable","cause: any"],"sources":["../src/server.ts"],"sourcesContent":["import {\n App,\n type HttpRequest,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n us_socket_local_port,\n} from 'uWebSockets.js'\nimport { randomUUID } from 'node:crypto'\nimport { once } from 'node:events'\nimport { Duplex, Readable } from 'node:stream'\nimport { Scope } from '@nmtjs/core'\nimport {\n ClientMessageType,\n decodeNumber,\n ErrorCode,\n ProtocolBlob,\n type ServerMessageType,\n} from '@nmtjs/protocol'\nimport {\n Connection,\n getFormat,\n isIterableResult,\n isSubscriptionResult,\n type ProtocolApiCallOptions,\n ProtocolClientStream,\n ProtocolError,\n ProtocolInjectables,\n type Transport,\n type TransportPluginContext,\n UnsupportedContentTypeError,\n UnsupportedFormatError,\n} from '@nmtjs/protocol/server'\nimport {\n AllowedHttpMethod,\n HttpCode,\n HttpCodeMap,\n HttpStatusText,\n} from './http.ts'\nimport { WsTransportInjectables } from './injectables.ts'\nimport type {\n WsConnectionData,\n WsTransportOptions,\n WsTransportSocket,\n WsUserData,\n} from './types.ts'\nimport {\n getRequestBody,\n getRequestData,\n readableToArrayBuffer,\n send,\n setHeaders,\n} from './utils.ts'\n\nconst DEFAULT_ALLOWED_METHODS = ['post'] as ('get' | 'post')[]\n\nexport class WsTransportServer implements Transport<WsConnectionData> {\n protected server!: TemplatedApp\n protected clients: Map<string, WsTransportSocket> = new Map()\n\n constructor(\n protected readonly context: TransportPluginContext,\n protected readonly options: WsTransportOptions,\n ) {\n this.server = this.options.tls ? SSLApp(options.tls!) : App()\n this.server\n .options('/*', (res, req) => {\n this.applyCors(res, req)\n res.writeStatus('200 OK')\n res.endWithoutBody()\n })\n .get('/healthy', (res, req) => {\n this.applyCors(res, req)\n res.writeHeader('Content-Type', 'text/plain')\n res.end('OK')\n })\n .ws<WsUserData>('/api', {\n sendPingsAutomatically: true,\n maxPayloadLength: this.options.maxPayloadLength,\n upgrade: async (res, req, socketContext) => {\n const ac = new AbortController()\n\n res.onAborted(ac.abort.bind(ac))\n\n const requestData = getRequestData(req, res)\n const contentType =\n requestData.query.get('content-type') ||\n requestData.headers.get('content-type')\n const acceptType =\n requestData.query.get('accept') || requestData.headers.get('accept')\n\n const connectionId = randomUUID()\n\n try {\n const { context } = await this.protocol.addConnection(\n this,\n { id: connectionId, data: { type: 'ws' } },\n { acceptType, contentType },\n )\n context.container.provide(\n WsTransportInjectables.connectionData,\n requestData,\n )\n if (!ac.signal.aborted) {\n res.cork(() => {\n res.upgrade(\n {\n id: connectionId,\n request: requestData,\n contentType,\n acceptType,\n backpressure: null,\n context,\n } as WsUserData,\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n socketContext,\n )\n })\n }\n } catch (error) {\n this.logger.debug(\n new Error('Failed to upgrade connection', { cause: error }),\n )\n if (!ac.signal.aborted) {\n res.cork(() => {\n res.writeStatus('500 Internal Server Error')\n res.endWithoutBody()\n })\n }\n }\n },\n open: (ws: WsTransportSocket) => {\n const { id } = ws.getUserData()\n this.logger.debug('Connection %s opened', id)\n this.clients.set(id, ws)\n },\n message: async (ws: WsTransportSocket, buffer) => {\n const messageType = decodeNumber(buffer, 'Uint8')\n if (messageType in this === false) {\n ws.end(1011, 'Unknown message type')\n } else {\n try {\n await this[messageType](\n ws,\n buffer.slice(Uint8Array.BYTES_PER_ELEMENT),\n )\n } catch (error: any) {\n this.logError(error, 'Error while processing message')\n }\n }\n },\n drain: (ws: WsTransportSocket) => {\n const data = ws.getUserData()\n data.backpressure?.resolve()\n data.backpressure = null\n },\n close: async (ws: WsTransportSocket, code, message) => {\n const { id } = ws.getUserData()\n\n this.logger.debug(\n 'Connection %s closed with code %s: %s',\n id,\n code,\n Buffer.from(message).toString(),\n )\n this.clients.delete(id)\n await this.protocol.removeConnection(id)\n },\n })\n .get('/api/:namespace/:procedure', this.httpHandler.bind(this))\n .post('/api/:namespace/:procedure', this.httpHandler.bind(this))\n }\n\n send(\n connection: Connection<WsConnectionData>,\n messageType: ServerMessageType,\n buffer: ArrayBuffer,\n ) {\n const ws = this.clients.get(connection.id)\n if (ws) send(ws, messageType, buffer)\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const { hostname = '127.0.0.1', port = 0, unix } = this.options\n if (unix) {\n this.server.listen_unix((socket) => {\n if (socket) {\n this.logger.info('Server started on unix://%s', unix)\n resolve()\n } else {\n reject(new Error('Failed to start WebSockets server'))\n }\n }, unix)\n } else {\n this.server.listen(hostname, port, (socket) => {\n if (socket) {\n this.logger.info(\n 'WebSocket Server started on %s:%s',\n hostname,\n us_socket_local_port(socket),\n )\n resolve()\n } else {\n reject(new Error('Failed to start WebSockets server'))\n }\n })\n }\n })\n }\n\n async stop() {\n this.server.close()\n }\n\n // TODO: decompose this mess\n protected async httpHandler(res: HttpResponse, req: HttpRequest) {\n this.applyCors(res, req)\n\n const ac = new AbortController()\n\n res.onAborted(ac.abort.bind(ac))\n\n const method = req.getMethod() as 'get' | 'post'\n const namespace = req.getParameter('namespace')\n const procedure = req.getParameter('procedure')\n const requestData = getRequestData(req, res)\n\n if (!namespace || !procedure) {\n const status = HttpCode.NotFound\n const text = HttpStatusText[status]\n return void res.cork(() => {\n if (ac.signal.aborted) return\n res.writeStatus(`${status} ${text}`)\n res.endWithoutBody()\n })\n }\n\n const isBlob = requestData.headers.get('x-neemata-blob') === 'true'\n\n const contentType = requestData.headers.get('content-type')\n const acceptType = requestData.headers.get('accept')\n const connectionId = randomUUID()\n const connection = new Connection<WsConnectionData>({\n id: connectionId,\n data: { type: 'http' },\n })\n const responseHeaders = new Headers()\n const container = this.context.container.fork(Scope.Call)\n container.provide(ProtocolInjectables.connection, connection)\n container.provide(WsTransportInjectables.connectionData, requestData)\n container.provide(\n WsTransportInjectables.httpResponseHeaders,\n responseHeaders,\n )\n\n const body = method === 'post' ? getRequestBody(res) : undefined\n\n const metadata: ProtocolApiCallOptions['metadata'] = (metadata) => {\n const allowHttpMethod =\n metadata.get(AllowedHttpMethod) ?? DEFAULT_ALLOWED_METHODS\n if (!allowHttpMethod.includes(method)) {\n throw new ProtocolError(ErrorCode.NotFound)\n }\n }\n let format: ReturnType<typeof getFormat>\n try {\n format = getFormat(this.context.format, {\n acceptType,\n contentType: isBlob ? '*/*' : contentType,\n })\n\n let payload: any = undefined\n\n if (body) {\n if (isBlob) {\n const type = contentType || 'application/octet-stream'\n const contentLength = requestData.headers.get('content-length')\n const size = contentLength\n ? Number.parseInt(contentLength)\n : undefined\n const stream = new ProtocolClientStream(-1, { size, type })\n body.pipe(stream)\n payload = stream\n } else {\n const buffer = await readableToArrayBuffer(body)\n if (buffer.byteLength > 0) {\n payload = format.decoder.decode(buffer)\n }\n }\n }\n\n const result = await this.protocol.call({\n connection,\n namespace,\n procedure,\n payload,\n metadata,\n container,\n signal: ac.signal,\n })\n\n if (isIterableResult(result) || isSubscriptionResult(result)) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.NotImplemented\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end()\n })\n } else {\n const { output } = result\n\n if (output instanceof ProtocolBlob) {\n const { source, metadata } = output\n const { type } = metadata\n\n let stream: Readable\n\n if (source instanceof ReadableStream) {\n stream = Readable.fromWeb(source as any)\n } else if (source instanceof Readable || source instanceof Duplex) {\n stream = Readable.from(source)\n } else {\n throw new Error('Invalid stream source')\n }\n\n res.cork(() => {\n if (ac.signal.aborted) return\n responseHeaders.set('X-Neemata-Blob', 'true')\n responseHeaders.set('Content-Type', type)\n if (metadata.size)\n res.writeHeader('Content-Length', metadata.size.toString())\n setHeaders(res, responseHeaders)\n })\n\n ac.signal.addEventListener('abort', () => stream.destroy(), {\n once: true,\n })\n\n stream.on('data', (chunk) => {\n console.log({ chunk })\n if (ac.signal.aborted) return\n const buf = Buffer.from(chunk)\n const ab = buf.buffer.slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n )\n const ok = res.write(ab)\n if (!ok) {\n stream.pause()\n res.onWritable(() => {\n stream.resume()\n return true\n })\n }\n })\n await once(stream, 'end')\n if (stream.readableAborted) {\n res.end(undefined, true)\n } else {\n res.end()\n }\n } else {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.OK\n const text = HttpStatusText[status]\n const buffer = format.encoder.encode(output)\n res.writeStatus(`${status} ${text}`)\n responseHeaders.set('Content-Type', format.encoder.contentType)\n setHeaders(res, responseHeaders)\n res.end(buffer)\n })\n }\n }\n } catch (error) {\n if (ac.signal.aborted) return\n if (error instanceof UnsupportedFormatError) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status =\n error instanceof UnsupportedContentTypeError\n ? HttpCode.UnsupportedMediaType\n : HttpCode.NotAcceptable\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end()\n })\n } else if (error instanceof ProtocolError) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status =\n error.code in HttpCodeMap\n ? HttpCodeMap[error.code]\n : HttpCode.InternalServerError\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end(format!.encoder.encode(error))\n })\n } else {\n this.logError(error, 'Unknown error while processing request')\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.InternalServerError\n const text = HttpStatusText[status]\n const payload = format!.encoder.encode(\n new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal Server Error',\n ),\n )\n res.writeStatus(`${status} ${text}`)\n res.end(payload)\n })\n }\n } finally {\n container.dispose().catch((error) => {\n this.logError(error, 'Error while disposing call container')\n })\n }\n }\n\n protected get protocol() {\n return this.context.protocol\n }\n\n protected get logger() {\n return this.context.logger\n }\n\n protected async logError(\n cause: any,\n message = 'Unknown error while processing request',\n ) {\n this.logger.error(new Error(message, { cause }))\n }\n\n protected applyCors(res: HttpResponse, req: HttpRequest) {\n if (this.options.cors === false) return\n\n const origin = req.getHeader('origin')\n if (!origin) return\n\n let allowed = false\n\n if (this.options.cors === undefined || this.options.cors === true) {\n allowed = true\n } else if (Array.isArray(this.options.cors)) {\n allowed = this.options.cors.includes(origin)\n } else {\n allowed = this.options.cors(origin)\n }\n\n if (!allowed) return\n\n res.writeHeader('Access-Control-Allow-Origin', origin)\n res.writeHeader('Access-Control-Allow-Headers', 'Content-Type')\n res.writeHeader('Access-Control-Allow-Methods', 'GET, POST')\n res.writeHeader('Access-Control-Allow-Credentials', 'true')\n }\n\n protected [ClientMessageType.Rpc](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcRaw(id, buffer)\n }\n\n protected [ClientMessageType.RpcAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcAbortRaw(id, buffer)\n }\n\n protected [ClientMessageType.RpcStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcStreamAbortRaw(id, buffer)\n }\n\n protected [ClientMessageType.ClientStreamPush](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.pushClientStream(\n id,\n streamId,\n buffer.slice(Uint32Array.BYTES_PER_ELEMENT),\n )\n }\n\n protected [ClientMessageType.ClientStreamEnd](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.endClientStream(id, streamId)\n }\n\n protected [ClientMessageType.ClientStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.abortClientStream(id, streamId)\n }\n\n protected [ClientMessageType.ServerStreamPull](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.pullServerStream(id, streamId)\n }\n\n protected [ClientMessageType.ServerStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.abortServerStream(id, streamId)\n }\n}\n"],"version":3,"file":"server.js"}
1
+ {"mappings":"AAAA,SACE,KAGA,QAEA,4BACK,gBAAgB;AACvB,SAAS,kBAAkB,aAAa;AACxC,SAAS,YAAY,aAAa;AAClC,SAAS,QAAQ,gBAAgB,aAAa;AAC9C,SAAS,aAAa,aAAa;AACnC,SACE,mBACA,cACA,WACA,oBAEK,iBAAiB;AACxB,SACE,YACA,WACA,kBACA,sBAEA,sBACA,eACA,qBAGA,6BACA,8BACK,wBAAwB;AAC/B,SACE,mBACA,UACA,aACA,sBACK,WAAW;AAClB,SAAS,8BAA8B,kBAAkB;AAOzD,SACE,gBACA,gBACA,uBACA,MACA,kBACK,YAAY;AAEnB,MAAM,0BAA0B,CAAC,MAAO;AAExC,OAAO,MAAM,kBAAyD;CACpE,AAAU;CACV,AAAU,UAA0C,IAAI;CAExD,YACqBA,SACAC,SACnB;OAFmB;OACA;AAEnB,OAAK,SAAS,KAAK,QAAQ,MAAM,OAAO,QAAQ,IAAK,GAAG,KAAK;AAC7D,OAAK,OACF,QAAQ,MAAM,CAAC,KAAK,QAAQ;AAC3B,QAAK,UAAU,KAAK,IAAI;AACxB,OAAI,YAAY,SAAS;AACzB,OAAI,gBAAgB;EACrB,EAAC,CACD,IAAI,YAAY,CAAC,KAAK,QAAQ;AAC7B,QAAK,UAAU,KAAK,IAAI;AACxB,OAAI,YAAY,gBAAgB,aAAa;AAC7C,OAAI,IAAI,KAAK;EACd,EAAC,CACD,GAAe,QAAQ;GACtB,wBAAwB;GACxB,kBAAkB,KAAK,QAAQ;GAC/B,SAAS,OAAO,KAAK,KAAK,kBAAkB;IAC1C,MAAM,KAAK,IAAI;AAEf,QAAI,UAAU,GAAG,MAAM,KAAK,GAAG,CAAC;IAEhC,MAAM,cAAc,eAAe,KAAK,IAAI;IAC5C,MAAM,cACJ,YAAY,MAAM,IAAI,eAAe,IACrC,YAAY,QAAQ,IAAI,eAAe;IACzC,MAAM,aACJ,YAAY,MAAM,IAAI,SAAS,IAAI,YAAY,QAAQ,IAAI,SAAS;IAEtE,MAAM,eAAe,YAAY;AAEjC,QAAI;KACF,MAAM,EAAE,SAAS,GAAG,MAAM,KAAK,SAAS,cACtC,MACA;MAAE,IAAI;MAAc,MAAM,EAAE,MAAM,KAAM;KAAE,GAC1C;MAAE;MAAY;KAAa,EAC5B;AACD,aAAQ,UAAU,QAChB,uBAAuB,gBACvB,YACD;AACD,UAAK,GAAG,OAAO,SAAS;AACtB,UAAI,KAAK,MAAM;AACb,WAAI,QACF;QACE,IAAI;QACJ,SAAS;QACT;QACA;QACA,cAAc;QACd;OACD,GACD,IAAI,UAAU,oBAAoB,EAClC,IAAI,UAAU,yBAAyB,EACvC,IAAI,UAAU,2BAA2B,EACzC,cACD;MACF,EAAC;KACH;IACF,SAAQ,OAAO;AACd,UAAK,OAAO,MACV,IAAI,MAAM,gCAAgC,EAAE,OAAO,MAAO,GAC3D;AACD,UAAK,GAAG,OAAO,SAAS;AACtB,UAAI,KAAK,MAAM;AACb,WAAI,YAAY,4BAA4B;AAC5C,WAAI,gBAAgB;MACrB,EAAC;KACH;IACF;GACF;GACD,MAAM,CAACC,OAA0B;IAC/B,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;AAC/B,SAAK,OAAO,MAAM,wBAAwB,GAAG;AAC7C,SAAK,QAAQ,IAAI,IAAI,GAAG;GACzB;GACD,SAAS,OAAOA,IAAuB,WAAW;IAChD,MAAM,cAAc,aAAa,QAAQ,QAAQ;AACjD,QAAI,eAAe,SAAS,OAAO;AACjC,QAAG,IAAI,MAAM,uBAAuB;IACrC,OAAM;AACL,SAAI;AACF,YAAM,KAAK,aACT,IACA,OAAO,MAAM,WAAW,kBAAkB,CAC3C;KACF,SAAQC,OAAY;AACnB,WAAK,SAAS,OAAO,iCAAiC;KACvD;IACF;GACF;GACD,OAAO,CAACD,OAA0B;IAChC,MAAM,OAAO,GAAG,aAAa;AAC7B,SAAK,cAAc,SAAS;AAC5B,SAAK,eAAe;GACrB;GACD,OAAO,OAAOA,IAAuB,MAAM,YAAY;IACrD,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;AAE/B,SAAK,OAAO,MACV,yCACA,IACA,MACA,OAAO,KAAK,QAAQ,CAAC,UAAU,CAChC;AACD,SAAK,QAAQ,OAAO,GAAG;AACvB,UAAM,KAAK,SAAS,iBAAiB,GAAG;GACzC;EACF,EAAC,CACD,IAAI,8BAA8B,KAAK,YAAY,KAAK,KAAK,CAAC,CAC9D,KAAK,8BAA8B,KAAK,YAAY,KAAK,KAAK,CAAC;CACnE;CAED,KACEE,YACAC,aACAC,QACA;EACA,MAAM,KAAK,KAAK,QAAQ,IAAI,WAAW,GAAG;AAC1C,MAAI,GAAI,MAAK,IAAI,aAAa,OAAO;CACtC;CAED,MAAM,QAAQ;AACZ,SAAO,IAAI,QAAc,CAAC,SAAS,WAAW;GAC5C,MAAM,EAAE,WAAW,aAAa,OAAO,GAAG,MAAM,GAAG,KAAK;AACxD,OAAI,MAAM;AACR,SAAK,OAAO,YAAY,CAAC,WAAW;AAClC,SAAI,QAAQ;AACV,WAAK,OAAO,KAAK,+BAA+B,KAAK;AACrD,eAAS;KACV,OAAM;AACL,aAAO,IAAI,MAAM,qCAAqC;KACvD;IACF,GAAE,KAAK;GACT,OAAM;AACL,SAAK,OAAO,OAAO,UAAU,MAAM,CAAC,WAAW;AAC7C,SAAI,QAAQ;AACV,WAAK,OAAO,KACV,qCACA,UACA,qBAAqB,OAAO,CAC7B;AACD,eAAS;KACV,OAAM;AACL,aAAO,IAAI,MAAM,qCAAqC;KACvD;IACF,EAAC;GACH;EACF;CACF;CAED,MAAM,OAAO;AACX,OAAK,OAAO,OAAO;CACpB;CAGD,MAAgB,YAAYC,KAAmBC,KAAkB;AAC/D,OAAK,UAAU,KAAK,IAAI;EAExB,MAAM,KAAK,IAAI;AAEf,MAAI,UAAU,GAAG,MAAM,KAAK,GAAG,CAAC;EAEhC,MAAM,SAAS,IAAI,WAAW;EAC9B,MAAM,YAAY,IAAI,aAAa,YAAY;EAC/C,MAAM,YAAY,IAAI,aAAa,YAAY;EAC/C,MAAM,cAAc,eAAe,KAAK,IAAI;AAE5C,OAAK,cAAc,WAAW;GAC5B,MAAM,SAAS,SAAS;GACxB,MAAM,OAAO,eAAe;AAC5B,eAAY,IAAI,KAAK,MAAM;AACzB,QAAI,GAAG,OAAO,QAAS;AACvB,QAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,QAAI,gBAAgB;GACrB,EAAC;EACH;EAED,MAAM,SAAS,YAAY,QAAQ,IAAI,iBAAiB,KAAK;EAE7D,MAAM,cAAc,YAAY,QAAQ,IAAI,eAAe;EAC3D,MAAM,aAAa,YAAY,QAAQ,IAAI,SAAS;EACpD,MAAM,eAAe,YAAY;EACjC,MAAM,aAAa,IAAI,WAA6B;GAClD,IAAI;GACJ,MAAM,EAAE,MAAM,OAAQ;EACvB;EACD,MAAM,kBAAkB,IAAI;EAC5B,MAAM,YAAY,KAAK,QAAQ,UAAU,KAAK,MAAM,KAAK;AACzD,YAAU,QAAQ,oBAAoB,YAAY,WAAW;AAC7D,YAAU,QAAQ,uBAAuB,gBAAgB,YAAY;AACrE,YAAU,QACR,uBAAuB,qBACvB,gBACD;EAED,MAAM,OAAO,WAAW,SAAS,eAAe,IAAI,GAAG;EAEvD,MAAMC,WAA+C,CAAC,aAAa;GACjE,MAAM,kBACJ,SAAS,IAAI,kBAAkB,IAAI;AACrC,QAAK,gBAAgB,SAAS,OAAO,EAAE;AACrC,UAAM,IAAI,cAAc,UAAU;GACnC;EACF;EACD,IAAIC;AACJ,MAAI;AACF,YAAS,UAAU,KAAK,QAAQ,QAAQ;IACtC;IACA,aAAa,SAAS,QAAQ;GAC/B,EAAC;GAEF,IAAIC;AAEJ,OAAI,MAAM;AACR,QAAI,QAAQ;KACV,MAAM,OAAO,eAAe;KAC5B,MAAM,gBAAgB,YAAY,QAAQ,IAAI,iBAAiB;KAC/D,MAAM,OAAO,gBACT,OAAO,SAAS,cAAc,GAC9B;KACJ,MAAM,SAAS,IAAI,sBAAsB,GAAG;MAAE;MAAM;KAAM;AAC1D,UAAK,KAAK,OAAO;AACjB,eAAU;IACX,OAAM;KACL,MAAM,SAAS,MAAM,sBAAsB,KAAK;AAChD,SAAI,OAAO,aAAa,GAAG;AACzB,gBAAU,OAAO,QAAQ,OAAO,OAAO;KACxC;IACF;GACF;GAED,MAAM,SAAS,MAAM,KAAK,SAAS,KAAK;IACtC;IACA;IACA;IACA;IACA;IACA;IACA,QAAQ,GAAG;GACZ,EAAC;AAEF,OAAI,iBAAiB,OAAO,IAAI,qBAAqB,OAAO,EAAE;AAC5D,QAAI,KAAK,MAAM;AACb,SAAI,GAAG,OAAO,QAAS;KACvB,MAAM,SAAS,SAAS;KACxB,MAAM,OAAO,eAAe;AAC5B,SAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,SAAI,KAAK;IACV,EAAC;GACH,OAAM;IACL,MAAM,EAAE,QAAQ,GAAG;AAEnB,QAAI,kBAAkB,cAAc;KAClC,MAAM,EAAE,QAAQ,UAAU,GAAG;KAC7B,MAAM,EAAE,MAAM,GAAG;KAEjB,IAAIC;AAEJ,SAAI,kBAAkB,gBAAgB;AACpC,eAAS,SAAS,QAAQ,OAAc;KACzC,WAAU,kBAAkB,YAAY,kBAAkB,QAAQ;AACjE,eAAS,SAAS,KAAK,OAAO;KAC/B,OAAM;AACL,YAAM,IAAI,MAAM;KACjB;AAED,SAAI,KAAK,MAAM;AACb,UAAI,GAAG,OAAO,QAAS;AACvB,sBAAgB,IAAI,kBAAkB,OAAO;AAC7C,sBAAgB,IAAI,gBAAgB,KAAK;AACzC,UAAI,SAAS,KACX,KAAI,YAAY,kBAAkB,SAAS,KAAK,UAAU,CAAC;AAC7D,iBAAW,KAAK,gBAAgB;KACjC,EAAC;AAEF,QAAG,OAAO,iBAAiB,SAAS,MAAM,OAAO,SAAS,EAAE,EAC1D,MAAM,KACP,EAAC;AAEF,YAAO,GAAG,QAAQ,CAAC,UAAU;AAC3B,UAAI,GAAG,OAAO,QAAS;MACvB,MAAM,MAAM,OAAO,KAAK,MAAM;MAC9B,MAAM,KAAK,IAAI,OAAO,MACpB,IAAI,YACJ,IAAI,aAAa,IAAI,WACtB;MACD,MAAM,KAAK,IAAI,MAAM,GAAG;AACxB,WAAK,IAAI;AACP,cAAO,OAAO;AACd,WAAI,WAAW,MAAM;AACnB,eAAO,QAAQ;AACf,eAAO;OACR,EAAC;MACH;KACF,EAAC;AACF,WAAM,KAAK,QAAQ,MAAM;AACzB,SAAI,OAAO,iBAAiB;AAC1B,UAAI,IAAI,WAAW,KAAK;KACzB,OAAM;AACL,UAAI,KAAK;KACV;IACF,OAAM;AACL,SAAI,KAAK,MAAM;AACb,UAAI,GAAG,OAAO,QAAS;MACvB,MAAM,SAAS,SAAS;MACxB,MAAM,OAAO,eAAe;MAC5B,MAAM,SAAS,OAAO,QAAQ,OAAO,OAAO;AAC5C,UAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,sBAAgB,IAAI,gBAAgB,OAAO,QAAQ,YAAY;AAC/D,iBAAW,KAAK,gBAAgB;AAChC,UAAI,IAAI,OAAO;KAChB,EAAC;IACH;GACF;EACF,SAAQ,OAAO;AACd,OAAI,GAAG,OAAO,QAAS;AACvB,OAAI,iBAAiB,wBAAwB;AAC3C,QAAI,KAAK,MAAM;AACb,SAAI,GAAG,OAAO,QAAS;KACvB,MAAM,SACJ,iBAAiB,8BACb,SAAS,uBACT,SAAS;KACf,MAAM,OAAO,eAAe;AAC5B,SAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,SAAI,KAAK;IACV,EAAC;GACH,WAAU,iBAAiB,eAAe;AACzC,QAAI,KAAK,MAAM;AACb,SAAI,GAAG,OAAO,QAAS;KACvB,MAAM,SACJ,MAAM,QAAQ,cACV,YAAY,MAAM,QAClB,SAAS;KACf,MAAM,OAAO,eAAe;AAC5B,SAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,SAAI,IAAI,OAAQ,QAAQ,OAAO,MAAM,CAAC;IACvC,EAAC;GACH,OAAM;AACL,SAAK,SAAS,OAAO,yCAAyC;AAC9D,QAAI,KAAK,MAAM;AACb,SAAI,GAAG,OAAO,QAAS;KACvB,MAAM,SAAS,SAAS;KACxB,MAAM,OAAO,eAAe;KAC5B,MAAM,UAAU,OAAQ,QAAQ,OAC9B,IAAI,cACF,UAAU,qBACV,yBAEH;AACD,SAAI,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE;AACpC,SAAI,IAAI,QAAQ;IACjB,EAAC;GACH;EACF,UAAS;AACR,aAAU,SAAS,CAAC,MAAM,CAAC,UAAU;AACnC,SAAK,SAAS,OAAO,uCAAuC;GAC7D,EAAC;EACH;CACF;CAED,IAAc,WAAW;AACvB,SAAO,KAAK,QAAQ;CACrB;CAED,IAAc,SAAS;AACrB,SAAO,KAAK,QAAQ;CACrB;CAED,MAAgB,SACdC,OACA,UAAU,0CACV;AACA,OAAK,OAAO,MAAM,IAAI,MAAM,SAAS,EAAE,MAAO,GAAE;CACjD;CAED,AAAU,UAAUN,KAAmBC,KAAkB;AACvD,MAAI,KAAK,QAAQ,SAAS,MAAO;EAEjC,MAAM,SAAS,IAAI,UAAU,SAAS;AACtC,OAAK,OAAQ;EAEb,IAAI,UAAU;AAEd,MAAI,KAAK,QAAQ,SAAS,aAAa,KAAK,QAAQ,SAAS,MAAM;AACjE,aAAU;EACX,WAAU,MAAM,QAAQ,KAAK,QAAQ,KAAK,EAAE;AAC3C,aAAU,KAAK,QAAQ,KAAK,SAAS,OAAO;EAC7C,OAAM;AACL,aAAU,KAAK,QAAQ,KAAK,OAAO;EACpC;AAED,OAAK,QAAS;AAEd,MAAI,YAAY,+BAA+B,OAAO;AACtD,MAAI,YAAY,gCAAgC,eAAe;AAC/D,MAAI,YAAY,gCAAgC,YAAY;AAC5D,MAAI,YAAY,oCAAoC,OAAO;CAC5D;CAED,CAAW,kBAAkB,KAC3BN,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;AAC/B,OAAK,SAAS,OAAO,IAAI,OAAO;CACjC;CAED,CAAW,kBAAkB,UAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;AAC/B,OAAK,SAAS,YAAY,IAAI,OAAO;CACtC;CAED,CAAW,kBAAkB,gBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;AAC/B,OAAK,SAAS,kBAAkB,IAAI,OAAO;CAC5C;CAED,CAAW,kBAAkB,kBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;EAC/B,MAAM,WAAW,aAAa,QAAQ,SAAS;AAC/C,OAAK,SAAS,iBACZ,IACA,UACA,OAAO,MAAM,YAAY,kBAAkB,CAC5C;CACF;CAED,CAAW,kBAAkB,iBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;EAC/B,MAAM,WAAW,aAAa,QAAQ,SAAS;AAC/C,OAAK,SAAS,gBAAgB,IAAI,SAAS;CAC5C;CAED,CAAW,kBAAkB,mBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;EAC/B,MAAM,WAAW,aAAa,QAAQ,SAAS;AAC/C,OAAK,SAAS,kBAAkB,IAAI,SAAS;CAC9C;CAED,CAAW,kBAAkB,kBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;EAC/B,MAAM,WAAW,aAAa,QAAQ,SAAS;AAC/C,OAAK,SAAS,iBAAiB,IAAI,SAAS;CAC7C;CAED,CAAW,kBAAkB,mBAC3BJ,IACAI,QACA;EACA,MAAM,EAAE,IAAI,GAAG,GAAG,aAAa;EAC/B,MAAM,WAAW,aAAa,QAAQ,SAAS;AAC/C,OAAK,SAAS,kBAAkB,IAAI,SAAS;CAC9C;AACF","names":["context: TransportPluginContext","options: WsTransportOptions","ws: WsTransportSocket","error: any","connection: Connection<WsConnectionData>","messageType: ServerMessageType","buffer: ArrayBuffer","res: HttpResponse","req: HttpRequest","metadata: ProtocolApiCallOptions['metadata']","format: ReturnType<typeof getFormat>","payload: any","stream: Readable","cause: any"],"sources":["../src/server.ts"],"sourcesContent":["import {\n App,\n type HttpRequest,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n us_socket_local_port,\n} from 'uWebSockets.js'\nimport { randomUUID } from 'node:crypto'\nimport { once } from 'node:events'\nimport { Duplex, Readable } from 'node:stream'\nimport { Scope } from '@nmtjs/core'\nimport {\n ClientMessageType,\n decodeNumber,\n ErrorCode,\n ProtocolBlob,\n type ServerMessageType,\n} from '@nmtjs/protocol'\nimport {\n Connection,\n getFormat,\n isIterableResult,\n isSubscriptionResult,\n type ProtocolApiCallOptions,\n ProtocolClientStream,\n ProtocolError,\n ProtocolInjectables,\n type Transport,\n type TransportPluginContext,\n UnsupportedContentTypeError,\n UnsupportedFormatError,\n} from '@nmtjs/protocol/server'\nimport {\n AllowedHttpMethod,\n HttpCode,\n HttpCodeMap,\n HttpStatusText,\n} from './http.ts'\nimport { WsTransportInjectables } from './injectables.ts'\nimport type {\n WsConnectionData,\n WsTransportOptions,\n WsTransportSocket,\n WsUserData,\n} from './types.ts'\nimport {\n getRequestBody,\n getRequestData,\n readableToArrayBuffer,\n send,\n setHeaders,\n} from './utils.ts'\n\nconst DEFAULT_ALLOWED_METHODS = ['post'] as ('get' | 'post')[]\n\nexport class WsTransportServer implements Transport<WsConnectionData> {\n protected server!: TemplatedApp\n protected clients: Map<string, WsTransportSocket> = new Map()\n\n constructor(\n protected readonly context: TransportPluginContext,\n protected readonly options: WsTransportOptions,\n ) {\n this.server = this.options.tls ? SSLApp(options.tls!) : App()\n this.server\n .options('/*', (res, req) => {\n this.applyCors(res, req)\n res.writeStatus('200 OK')\n res.endWithoutBody()\n })\n .get('/healthy', (res, req) => {\n this.applyCors(res, req)\n res.writeHeader('Content-Type', 'text/plain')\n res.end('OK')\n })\n .ws<WsUserData>('/api', {\n sendPingsAutomatically: true,\n maxPayloadLength: this.options.maxPayloadLength,\n upgrade: async (res, req, socketContext) => {\n const ac = new AbortController()\n\n res.onAborted(ac.abort.bind(ac))\n\n const requestData = getRequestData(req, res)\n const contentType =\n requestData.query.get('content-type') ||\n requestData.headers.get('content-type')\n const acceptType =\n requestData.query.get('accept') || requestData.headers.get('accept')\n\n const connectionId = randomUUID()\n\n try {\n const { context } = await this.protocol.addConnection(\n this,\n { id: connectionId, data: { type: 'ws' } },\n { acceptType, contentType },\n )\n context.container.provide(\n WsTransportInjectables.connectionData,\n requestData,\n )\n if (!ac.signal.aborted) {\n res.cork(() => {\n res.upgrade(\n {\n id: connectionId,\n request: requestData,\n contentType,\n acceptType,\n backpressure: null,\n context,\n } as WsUserData,\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n socketContext,\n )\n })\n }\n } catch (error) {\n this.logger.debug(\n new Error('Failed to upgrade connection', { cause: error }),\n )\n if (!ac.signal.aborted) {\n res.cork(() => {\n res.writeStatus('500 Internal Server Error')\n res.endWithoutBody()\n })\n }\n }\n },\n open: (ws: WsTransportSocket) => {\n const { id } = ws.getUserData()\n this.logger.debug('Connection %s opened', id)\n this.clients.set(id, ws)\n },\n message: async (ws: WsTransportSocket, buffer) => {\n const messageType = decodeNumber(buffer, 'Uint8')\n if (messageType in this === false) {\n ws.end(1011, 'Unknown message type')\n } else {\n try {\n await this[messageType](\n ws,\n buffer.slice(Uint8Array.BYTES_PER_ELEMENT),\n )\n } catch (error: any) {\n this.logError(error, 'Error while processing message')\n }\n }\n },\n drain: (ws: WsTransportSocket) => {\n const data = ws.getUserData()\n data.backpressure?.resolve()\n data.backpressure = null\n },\n close: async (ws: WsTransportSocket, code, message) => {\n const { id } = ws.getUserData()\n\n this.logger.debug(\n 'Connection %s closed with code %s: %s',\n id,\n code,\n Buffer.from(message).toString(),\n )\n this.clients.delete(id)\n await this.protocol.removeConnection(id)\n },\n })\n .get('/api/:namespace/:procedure', this.httpHandler.bind(this))\n .post('/api/:namespace/:procedure', this.httpHandler.bind(this))\n }\n\n send(\n connection: Connection<WsConnectionData>,\n messageType: ServerMessageType,\n buffer: ArrayBuffer,\n ) {\n const ws = this.clients.get(connection.id)\n if (ws) send(ws, messageType, buffer)\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const { hostname = '127.0.0.1', port = 0, unix } = this.options\n if (unix) {\n this.server.listen_unix((socket) => {\n if (socket) {\n this.logger.info('Server started on unix://%s', unix)\n resolve()\n } else {\n reject(new Error('Failed to start WebSockets server'))\n }\n }, unix)\n } else {\n this.server.listen(hostname, port, (socket) => {\n if (socket) {\n this.logger.info(\n 'WebSocket Server started on %s:%s',\n hostname,\n us_socket_local_port(socket),\n )\n resolve()\n } else {\n reject(new Error('Failed to start WebSockets server'))\n }\n })\n }\n })\n }\n\n async stop() {\n this.server.close()\n }\n\n // TODO: decompose this mess\n protected async httpHandler(res: HttpResponse, req: HttpRequest) {\n this.applyCors(res, req)\n\n const ac = new AbortController()\n\n res.onAborted(ac.abort.bind(ac))\n\n const method = req.getMethod() as 'get' | 'post'\n const namespace = req.getParameter('namespace')\n const procedure = req.getParameter('procedure')\n const requestData = getRequestData(req, res)\n\n if (!namespace || !procedure) {\n const status = HttpCode.NotFound\n const text = HttpStatusText[status]\n return void res.cork(() => {\n if (ac.signal.aborted) return\n res.writeStatus(`${status} ${text}`)\n res.endWithoutBody()\n })\n }\n\n const isBlob = requestData.headers.get('x-neemata-blob') === 'true'\n\n const contentType = requestData.headers.get('content-type')\n const acceptType = requestData.headers.get('accept')\n const connectionId = randomUUID()\n const connection = new Connection<WsConnectionData>({\n id: connectionId,\n data: { type: 'http' },\n })\n const responseHeaders = new Headers()\n const container = this.context.container.fork(Scope.Call)\n container.provide(ProtocolInjectables.connection, connection)\n container.provide(WsTransportInjectables.connectionData, requestData)\n container.provide(\n WsTransportInjectables.httpResponseHeaders,\n responseHeaders,\n )\n\n const body = method === 'post' ? getRequestBody(res) : undefined\n\n const metadata: ProtocolApiCallOptions['metadata'] = (metadata) => {\n const allowHttpMethod =\n metadata.get(AllowedHttpMethod) ?? DEFAULT_ALLOWED_METHODS\n if (!allowHttpMethod.includes(method)) {\n throw new ProtocolError(ErrorCode.NotFound)\n }\n }\n let format: ReturnType<typeof getFormat>\n try {\n format = getFormat(this.context.format, {\n acceptType,\n contentType: isBlob ? '*/*' : contentType,\n })\n\n let payload: any\n\n if (body) {\n if (isBlob) {\n const type = contentType || 'application/octet-stream'\n const contentLength = requestData.headers.get('content-length')\n const size = contentLength\n ? Number.parseInt(contentLength)\n : undefined\n const stream = new ProtocolClientStream(-1, { size, type })\n body.pipe(stream)\n payload = stream\n } else {\n const buffer = await readableToArrayBuffer(body)\n if (buffer.byteLength > 0) {\n payload = format.decoder.decode(buffer)\n }\n }\n }\n\n const result = await this.protocol.call({\n connection,\n namespace,\n procedure,\n payload,\n metadata,\n container,\n signal: ac.signal,\n })\n\n if (isIterableResult(result) || isSubscriptionResult(result)) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.NotImplemented\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end()\n })\n } else {\n const { output } = result\n\n if (output instanceof ProtocolBlob) {\n const { source, metadata } = output\n const { type } = metadata\n\n let stream: Readable\n\n if (source instanceof ReadableStream) {\n stream = Readable.fromWeb(source as any)\n } else if (source instanceof Readable || source instanceof Duplex) {\n stream = Readable.from(source)\n } else {\n throw new Error('Invalid stream source')\n }\n\n res.cork(() => {\n if (ac.signal.aborted) return\n responseHeaders.set('X-Neemata-Blob', 'true')\n responseHeaders.set('Content-Type', type)\n if (metadata.size)\n res.writeHeader('Content-Length', metadata.size.toString())\n setHeaders(res, responseHeaders)\n })\n\n ac.signal.addEventListener('abort', () => stream.destroy(), {\n once: true,\n })\n\n stream.on('data', (chunk) => {\n if (ac.signal.aborted) return\n const buf = Buffer.from(chunk)\n const ab = buf.buffer.slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n )\n const ok = res.write(ab)\n if (!ok) {\n stream.pause()\n res.onWritable(() => {\n stream.resume()\n return true\n })\n }\n })\n await once(stream, 'end')\n if (stream.readableAborted) {\n res.end(undefined, true)\n } else {\n res.end()\n }\n } else {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.OK\n const text = HttpStatusText[status]\n const buffer = format.encoder.encode(output)\n res.writeStatus(`${status} ${text}`)\n responseHeaders.set('Content-Type', format.encoder.contentType)\n setHeaders(res, responseHeaders)\n res.end(buffer)\n })\n }\n }\n } catch (error) {\n if (ac.signal.aborted) return\n if (error instanceof UnsupportedFormatError) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status =\n error instanceof UnsupportedContentTypeError\n ? HttpCode.UnsupportedMediaType\n : HttpCode.NotAcceptable\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end()\n })\n } else if (error instanceof ProtocolError) {\n res.cork(() => {\n if (ac.signal.aborted) return\n const status =\n error.code in HttpCodeMap\n ? HttpCodeMap[error.code]\n : HttpCode.InternalServerError\n const text = HttpStatusText[status]\n res.writeStatus(`${status} ${text}`)\n res.end(format!.encoder.encode(error))\n })\n } else {\n this.logError(error, 'Unknown error while processing request')\n res.cork(() => {\n if (ac.signal.aborted) return\n const status = HttpCode.InternalServerError\n const text = HttpStatusText[status]\n const payload = format!.encoder.encode(\n new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal Server Error',\n ),\n )\n res.writeStatus(`${status} ${text}`)\n res.end(payload)\n })\n }\n } finally {\n container.dispose().catch((error) => {\n this.logError(error, 'Error while disposing call container')\n })\n }\n }\n\n protected get protocol() {\n return this.context.protocol\n }\n\n protected get logger() {\n return this.context.logger\n }\n\n protected async logError(\n cause: any,\n message = 'Unknown error while processing request',\n ) {\n this.logger.error(new Error(message, { cause }))\n }\n\n protected applyCors(res: HttpResponse, req: HttpRequest) {\n if (this.options.cors === false) return\n\n const origin = req.getHeader('origin')\n if (!origin) return\n\n let allowed = false\n\n if (this.options.cors === undefined || this.options.cors === true) {\n allowed = true\n } else if (Array.isArray(this.options.cors)) {\n allowed = this.options.cors.includes(origin)\n } else {\n allowed = this.options.cors(origin)\n }\n\n if (!allowed) return\n\n res.writeHeader('Access-Control-Allow-Origin', origin)\n res.writeHeader('Access-Control-Allow-Headers', 'Content-Type')\n res.writeHeader('Access-Control-Allow-Methods', 'GET, POST')\n res.writeHeader('Access-Control-Allow-Credentials', 'true')\n }\n\n protected [ClientMessageType.Rpc](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcRaw(id, buffer)\n }\n\n protected [ClientMessageType.RpcAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcAbortRaw(id, buffer)\n }\n\n protected [ClientMessageType.RpcStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n this.protocol.rpcStreamAbortRaw(id, buffer)\n }\n\n protected [ClientMessageType.ClientStreamPush](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.pushClientStream(\n id,\n streamId,\n buffer.slice(Uint32Array.BYTES_PER_ELEMENT),\n )\n }\n\n protected [ClientMessageType.ClientStreamEnd](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.endClientStream(id, streamId)\n }\n\n protected [ClientMessageType.ClientStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.abortClientStream(id, streamId)\n }\n\n protected [ClientMessageType.ServerStreamPull](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.pullServerStream(id, streamId)\n }\n\n protected [ClientMessageType.ServerStreamAbort](\n ws: WsTransportSocket,\n buffer: ArrayBuffer,\n ) {\n const { id } = ws.getUserData()\n const streamId = decodeNumber(buffer, 'Uint32')\n this.protocol.abortServerStream(id, streamId)\n }\n}\n"],"version":3,"file":"server.js"}
package/dist/utils.js CHANGED
@@ -15,7 +15,7 @@ export const send = (ws, type, ...buffers) => {
15
15
  return null;
16
16
  }
17
17
  return true;
18
- } catch (error) {
18
+ } catch {
19
19
  return null;
20
20
  }
21
21
  };
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"AACA,SAAS,mBAAkC,aAAa;AACxD,SAAS,qBAAqB,eAAe;AAC7C,SAAS,QAAQ,WAAW,oBAAoB,iBAAiB;AACjE,SAAS,qBAAqB,wBAAwB;AAGtD,OAAO,MAAM,OAAO,CAClBA,IACAC,MACA,GAAG,YACgB;CACnB,MAAM,OAAO,GAAG,aAAa;AAC7B,KAAI;EACF,MAAM,SAAS,OAAO,aAAa,MAAM,QAAQ,EAAE,GAAG,QAAQ;EAC9D,MAAM,SAAS,GAAG,KAAK,QAAQ,KAAK;AACpC,MAAI,WAAW,GAAG;AAChB,QAAK,eAAe,eAAe;AACnC,UAAO;EACR;AACD,MAAI,WAAW,GAAG;AAChB,UAAO;EACR;AACD,SAAO;CACR,SAAQ,OAAO;AACd,SAAO;CACR;AACF;AAED,OAAO,MAAM,WAAW,CAACC,UAEnB;CACJ,MAAMC,MAA8B,CAAE;AACtC,OAAM,QAAQ,CAAC,OAAO,QAAQ;AAC5B,MAAI,OAAO;CACZ,EAAC;AACF,QAAO;AACR;AAaD,OAAO,MAAM,iBAAiB,CAC5BC,KACAC,QACgB;CAChB,MAAM,MAAM,IAAI,QAAQ;CACxB,MAAM,SAAS,IAAI,WAAW;CAC9B,MAAM,UAAU,IAAI;CACpB,MAAM,cAAc,IAAI,UAAU;CAClC,MAAM,QAAQ,IAAI,gBAAgB;CAClC,MAAM,SAAS,QAAQ,IAAI,SAAS;CACpC,MAAM,uBAAuB,IAAI,+BAA+B;CAChE,MAAM,gBAAgB,IAAI,wBAAwB;AAElD,KAAI,QAAQ,CAAC,KAAK,UAAU,QAAQ,OAAO,KAAK,MAAM,CAAC;AAEvD,QAAO,OAAO,OAAO;EACnB;EACA,QAAQ,SAAS,IAAI,IAAI,KAAK,UAAU;EACxC;EACA;EACA;EACA;EACA,eAAe,OAAO,KAAK,cAAc,CAAC,UAAU;EACpD,sBAAsB,OAAO,KAAK,qBAAqB,CAAC,UAAU;CACnE,EAAC;AACH;AAED,OAAO,SAAS,eAAeA,KAAmB;CAChD,MAAM,SAAS,IAAI;AACnB,KAAI,OAAO,CAAC,OAAO,WAAW;AAC5B,SAAO,MAAM,OAAO,KAAK,MAAM,CAAC;AAChC,MAAI,OAAQ,QAAO,KAAK;CACzB,EAAC;AACF,KAAI,UAAU,MAAM,OAAO,SAAS,CAAC;AACrC,QAAO;AACR;AAED,OAAO,SAAS,WAAWA,KAAmBC,SAAkB;AAC9D,SAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,MAAI,QAAQ,aAAc;AAC1B,MAAI,YAAY,KAAK,MAAM;CAC5B,EAAC;CACF,MAAM,UAAU,QAAQ,cAAc;AACtC,KAAI,SAAS;AACX,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,YAAY,cAAc,OAAO;EACtC;CACF;AACF;AAED,OAAO,SAAS,sBAAsBC,QAAwC;AAC5E,QAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;EACtC,MAAMC,SAAmB,CAAE;AAC3B,SAAO,GAAG,QAAQ,CAAC,UAAU;AAC3B,UAAO,KAAK,MAAM;EACnB,EAAC;AACF,SAAO,GAAG,OAAO,MAAM;AACrB,WAAQ,OAAO,OAAO,OAAO,CAAC,OAAO;EACtC,EAAC;AACF,SAAO,GAAG,SAAS,CAAC,UAAU;AAC5B,UAAO,MAAM;EACd,EAAC;CACH;AACF;AAED,OAAO,MAAM,gBAAgB,CAAC,UAAU,4BACtC,IAAI,cAAc,UAAU,qBAAqB;AAEnD,OAAO,MAAM,gBAAgB,CAAC,UAAU,gBACtC,IAAI,cAAc,UAAU,UAAU;AAExC,OAAO,MAAM,iBAAiB,CAAC,UAAU,gBACvC,IAAI,cAAc,UAAU,WAAW;AAEzC,OAAO,MAAM,sBAAsB,CAAC,UAAU,sBAC5C,IAAI,cAAc,UAAU,gBAAgB","names":["ws: WsTransportSocket","type: number","input: {\n forEach: (cb: (value, key) => void) => void\n}","obj: Record<string, string>","req: HttpRequest","res: HttpResponse","headers: Headers","stream: Readable","chunks: Buffer[]"],"sources":["../src/utils.ts"],"sourcesContent":["import type { HttpRequest, HttpResponse } from 'uWebSockets.js'\nimport { PassThrough, type Readable } from 'node:stream'\nimport { createPromise } from '@nmtjs/common'\nimport { concat, ErrorCode, encodeNumber } from '@nmtjs/protocol'\nimport { ProtocolError } from '@nmtjs/protocol/server'\nimport type { WsTransportSocket } from './types.ts'\n\nexport const send = (\n ws: WsTransportSocket,\n type: number,\n ...buffers: ArrayBuffer[]\n): boolean | null => {\n const data = ws.getUserData()\n try {\n const buffer = concat(encodeNumber(type, 'Uint8'), ...buffers)\n const result = ws.send(buffer, true)\n if (result === 0) {\n data.backpressure = createPromise()\n return false\n }\n if (result === 2) {\n return null\n }\n return true\n } catch (error) {\n return null\n }\n}\n\nexport const toRecord = (input: {\n forEach: (cb: (value, key) => void) => void\n}) => {\n const obj: Record<string, string> = {}\n input.forEach((value, key) => {\n obj[key] = value\n })\n return obj\n}\n\nexport type RequestData = Readonly<{\n url: string\n origin: URL | null\n method: string\n headers: Headers\n querystring: string\n query: URLSearchParams\n remoteAddress: string\n proxiedRemoteAddress: string\n}>\n\nexport const getRequestData = (\n req: HttpRequest,\n res: HttpResponse,\n): RequestData => {\n const url = req.getUrl()\n const method = req.getMethod()\n const headers = new Headers()\n const querystring = req.getQuery()\n const query = new URLSearchParams(querystring)\n const origin = headers.get('origin')\n const proxiedRemoteAddress = res.getProxiedRemoteAddressAsText()\n const remoteAddress = res.getRemoteAddressAsText()\n\n req.forEach((key, value) => headers.append(key, value))\n\n return Object.freeze({\n url,\n origin: origin ? new URL(url, origin) : null,\n method,\n headers,\n querystring,\n query,\n remoteAddress: Buffer.from(remoteAddress).toString(),\n proxiedRemoteAddress: Buffer.from(proxiedRemoteAddress).toString(),\n })\n}\n\nexport function getRequestBody(res: HttpResponse) {\n const stream = new PassThrough()\n res.onData((chunk, isLast) => {\n stream.write(Buffer.from(chunk))\n if (isLast) stream.end()\n })\n res.onAborted(() => stream.destroy())\n return stream\n}\n\nexport function setHeaders(res: HttpResponse, headers: Headers) {\n headers.forEach((value, key) => {\n if (key === 'set-cookie') return\n res.writeHeader(key, value)\n })\n const cookies = headers.getSetCookie()\n if (cookies) {\n for (const cookie of cookies) {\n res.writeHeader('set-cookie', cookie)\n }\n }\n}\n\nexport function readableToArrayBuffer(stream: Readable): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n stream.on('data', (chunk) => {\n chunks.push(chunk)\n })\n stream.on('end', () => {\n resolve(Buffer.concat(chunks).buffer)\n })\n stream.on('error', (error) => {\n reject(error)\n })\n })\n}\n\nexport const InternalError = (message = 'Internal Server Error') =>\n new ProtocolError(ErrorCode.InternalServerError, message)\n\nexport const NotFoundError = (message = 'Not Found') =>\n new ProtocolError(ErrorCode.NotFound, message)\n\nexport const ForbiddenError = (message = 'Forbidden') =>\n new ProtocolError(ErrorCode.Forbidden, message)\n\nexport const RequestTimeoutError = (message = 'Request Timeout') =>\n new ProtocolError(ErrorCode.RequestTimeout, message)\n"],"version":3,"file":"utils.js"}
1
+ {"mappings":"AACA,SAAS,mBAAkC,aAAa;AACxD,SAAS,qBAAqB,eAAe;AAC7C,SAAS,QAAQ,WAAW,oBAAoB,iBAAiB;AACjE,SAAS,qBAAqB,wBAAwB;AAGtD,OAAO,MAAM,OAAO,CAClBA,IACAC,MACA,GAAG,YACgB;CACnB,MAAM,OAAO,GAAG,aAAa;AAC7B,KAAI;EACF,MAAM,SAAS,OAAO,aAAa,MAAM,QAAQ,EAAE,GAAG,QAAQ;EAC9D,MAAM,SAAS,GAAG,KAAK,QAAQ,KAAK;AACpC,MAAI,WAAW,GAAG;AAChB,QAAK,eAAe,eAAe;AACnC,UAAO;EACR;AACD,MAAI,WAAW,GAAG;AAChB,UAAO;EACR;AACD,SAAO;CACR,QAAO;AACN,SAAO;CACR;AACF;AAED,OAAO,MAAM,WAAW,CAACC,UAEnB;CACJ,MAAMC,MAA8B,CAAE;AACtC,OAAM,QAAQ,CAAC,OAAO,QAAQ;AAC5B,MAAI,OAAO;CACZ,EAAC;AACF,QAAO;AACR;AAaD,OAAO,MAAM,iBAAiB,CAC5BC,KACAC,QACgB;CAChB,MAAM,MAAM,IAAI,QAAQ;CACxB,MAAM,SAAS,IAAI,WAAW;CAC9B,MAAM,UAAU,IAAI;CACpB,MAAM,cAAc,IAAI,UAAU;CAClC,MAAM,QAAQ,IAAI,gBAAgB;CAClC,MAAM,SAAS,QAAQ,IAAI,SAAS;CACpC,MAAM,uBAAuB,IAAI,+BAA+B;CAChE,MAAM,gBAAgB,IAAI,wBAAwB;AAElD,KAAI,QAAQ,CAAC,KAAK,UAAU,QAAQ,OAAO,KAAK,MAAM,CAAC;AAEvD,QAAO,OAAO,OAAO;EACnB;EACA,QAAQ,SAAS,IAAI,IAAI,KAAK,UAAU;EACxC;EACA;EACA;EACA;EACA,eAAe,OAAO,KAAK,cAAc,CAAC,UAAU;EACpD,sBAAsB,OAAO,KAAK,qBAAqB,CAAC,UAAU;CACnE,EAAC;AACH;AAED,OAAO,SAAS,eAAeA,KAAmB;CAChD,MAAM,SAAS,IAAI;AACnB,KAAI,OAAO,CAAC,OAAO,WAAW;AAC5B,SAAO,MAAM,OAAO,KAAK,MAAM,CAAC;AAChC,MAAI,OAAQ,QAAO,KAAK;CACzB,EAAC;AACF,KAAI,UAAU,MAAM,OAAO,SAAS,CAAC;AACrC,QAAO;AACR;AAED,OAAO,SAAS,WAAWA,KAAmBC,SAAkB;AAC9D,SAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC9B,MAAI,QAAQ,aAAc;AAC1B,MAAI,YAAY,KAAK,MAAM;CAC5B,EAAC;CACF,MAAM,UAAU,QAAQ,cAAc;AACtC,KAAI,SAAS;AACX,OAAK,MAAM,UAAU,SAAS;AAC5B,OAAI,YAAY,cAAc,OAAO;EACtC;CACF;AACF;AAED,OAAO,SAAS,sBAAsBC,QAAwC;AAC5E,QAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;EACtC,MAAMC,SAAmB,CAAE;AAC3B,SAAO,GAAG,QAAQ,CAAC,UAAU;AAC3B,UAAO,KAAK,MAAM;EACnB,EAAC;AACF,SAAO,GAAG,OAAO,MAAM;AACrB,WAAQ,OAAO,OAAO,OAAO,CAAC,OAAO;EACtC,EAAC;AACF,SAAO,GAAG,SAAS,CAAC,UAAU;AAC5B,UAAO,MAAM;EACd,EAAC;CACH;AACF;AAED,OAAO,MAAM,gBAAgB,CAAC,UAAU,4BACtC,IAAI,cAAc,UAAU,qBAAqB;AAEnD,OAAO,MAAM,gBAAgB,CAAC,UAAU,gBACtC,IAAI,cAAc,UAAU,UAAU;AAExC,OAAO,MAAM,iBAAiB,CAAC,UAAU,gBACvC,IAAI,cAAc,UAAU,WAAW;AAEzC,OAAO,MAAM,sBAAsB,CAAC,UAAU,sBAC5C,IAAI,cAAc,UAAU,gBAAgB","names":["ws: WsTransportSocket","type: number","input: {\n forEach: (cb: (value, key) => void) => void\n}","obj: Record<string, string>","req: HttpRequest","res: HttpResponse","headers: Headers","stream: Readable","chunks: Buffer[]"],"sources":["../src/utils.ts"],"sourcesContent":["import type { HttpRequest, HttpResponse } from 'uWebSockets.js'\nimport { PassThrough, type Readable } from 'node:stream'\nimport { createPromise } from '@nmtjs/common'\nimport { concat, ErrorCode, encodeNumber } from '@nmtjs/protocol'\nimport { ProtocolError } from '@nmtjs/protocol/server'\nimport type { WsTransportSocket } from './types.ts'\n\nexport const send = (\n ws: WsTransportSocket,\n type: number,\n ...buffers: ArrayBuffer[]\n): boolean | null => {\n const data = ws.getUserData()\n try {\n const buffer = concat(encodeNumber(type, 'Uint8'), ...buffers)\n const result = ws.send(buffer, true)\n if (result === 0) {\n data.backpressure = createPromise()\n return false\n }\n if (result === 2) {\n return null\n }\n return true\n } catch {\n return null\n }\n}\n\nexport const toRecord = (input: {\n forEach: (cb: (value, key) => void) => void\n}) => {\n const obj: Record<string, string> = {}\n input.forEach((value, key) => {\n obj[key] = value\n })\n return obj\n}\n\nexport type RequestData = Readonly<{\n url: string\n origin: URL | null\n method: string\n headers: Headers\n querystring: string\n query: URLSearchParams\n remoteAddress: string\n proxiedRemoteAddress: string\n}>\n\nexport const getRequestData = (\n req: HttpRequest,\n res: HttpResponse,\n): RequestData => {\n const url = req.getUrl()\n const method = req.getMethod()\n const headers = new Headers()\n const querystring = req.getQuery()\n const query = new URLSearchParams(querystring)\n const origin = headers.get('origin')\n const proxiedRemoteAddress = res.getProxiedRemoteAddressAsText()\n const remoteAddress = res.getRemoteAddressAsText()\n\n req.forEach((key, value) => headers.append(key, value))\n\n return Object.freeze({\n url,\n origin: origin ? new URL(url, origin) : null,\n method,\n headers,\n querystring,\n query,\n remoteAddress: Buffer.from(remoteAddress).toString(),\n proxiedRemoteAddress: Buffer.from(proxiedRemoteAddress).toString(),\n })\n}\n\nexport function getRequestBody(res: HttpResponse) {\n const stream = new PassThrough()\n res.onData((chunk, isLast) => {\n stream.write(Buffer.from(chunk))\n if (isLast) stream.end()\n })\n res.onAborted(() => stream.destroy())\n return stream\n}\n\nexport function setHeaders(res: HttpResponse, headers: Headers) {\n headers.forEach((value, key) => {\n if (key === 'set-cookie') return\n res.writeHeader(key, value)\n })\n const cookies = headers.getSetCookie()\n if (cookies) {\n for (const cookie of cookies) {\n res.writeHeader('set-cookie', cookie)\n }\n }\n}\n\nexport function readableToArrayBuffer(stream: Readable): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = []\n stream.on('data', (chunk) => {\n chunks.push(chunk)\n })\n stream.on('end', () => {\n resolve(Buffer.concat(chunks).buffer)\n })\n stream.on('error', (error) => {\n reject(error)\n })\n })\n}\n\nexport const InternalError = (message = 'Internal Server Error') =>\n new ProtocolError(ErrorCode.InternalServerError, message)\n\nexport const NotFoundError = (message = 'Not Found') =>\n new ProtocolError(ErrorCode.NotFound, message)\n\nexport const ForbiddenError = (message = 'Forbidden') =>\n new ProtocolError(ErrorCode.Forbidden, message)\n\nexport const RequestTimeoutError = (message = 'Request Timeout') =>\n new ProtocolError(ErrorCode.RequestTimeout, message)\n"],"version":3,"file":"utils.js"}
package/package.json CHANGED
@@ -11,15 +11,15 @@
11
11
  "uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.51.0"
12
12
  },
13
13
  "peerDependencies": {
14
- "@nmtjs/core": "0.10.2",
15
- "@nmtjs/common": "0.10.2",
16
- "@nmtjs/protocol": "0.10.2"
14
+ "@nmtjs/common": "0.10.3",
15
+ "@nmtjs/protocol": "0.10.3",
16
+ "@nmtjs/core": "0.10.3"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "^18",
20
- "@nmtjs/client": "0.10.2",
21
- "@nmtjs/common": "0.10.2",
22
- "@nmtjs/protocol": "0.10.2"
20
+ "@nmtjs/common": "0.10.3",
21
+ "@nmtjs/protocol": "0.10.3",
22
+ "@nmtjs/client": "0.10.3"
23
23
  },
24
24
  "engines": {
25
25
  "node": ">=18"
@@ -30,7 +30,7 @@
30
30
  "LICENSE.md",
31
31
  "README.md"
32
32
  ],
33
- "version": "0.10.2",
33
+ "version": "0.10.3",
34
34
  "scripts": {
35
35
  "build": "neemata-build --root ./src './**/*.ts'",
36
36
  "type-check": "tsc --noEmit"
package/src/server.ts CHANGED
@@ -272,7 +272,7 @@ export class WsTransportServer implements Transport<WsConnectionData> {
272
272
  contentType: isBlob ? '*/*' : contentType,
273
273
  })
274
274
 
275
- let payload: any = undefined
275
+ let payload: any
276
276
 
277
277
  if (body) {
278
278
  if (isBlob) {
@@ -341,7 +341,6 @@ export class WsTransportServer implements Transport<WsConnectionData> {
341
341
  })
342
342
 
343
343
  stream.on('data', (chunk) => {
344
- console.log({ chunk })
345
344
  if (ac.signal.aborted) return
346
345
  const buf = Buffer.from(chunk)
347
346
  const ab = buf.buffer.slice(
package/src/utils.ts CHANGED
@@ -22,7 +22,7 @@ export const send = (
22
22
  return null
23
23
  }
24
24
  return true
25
- } catch (error) {
25
+ } catch {
26
26
  return null
27
27
  }
28
28
  }