@nmtjs/ws-transport 0.2.0 → 0.2.1
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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/injectables.js.map +1 -1
- package/dist/lib/server.js +8 -3
- package/dist/lib/server.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/utils.js +1 -1
- package/dist/lib/utils.js.map +1 -1
- package/index.ts +1 -1
- package/lib/injectables.ts +4 -5
- package/lib/server.ts +13 -9
- package/lib/types.ts +1 -1
- package/lib/utils.ts +2 -2
- package/package.json +4 -5
- package/tsconfig.json +0 -3
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../index.ts"],"sourcesContent":["export * from './lib/
|
|
1
|
+
{"version":3,"sources":["../../index.ts"],"sourcesContent":["export * from './lib/injectables.ts'\nexport * from './lib/server.ts'\nexport * from './lib/transport.ts'\nexport * from './lib/types.ts'\nexport * from './lib/utils.ts'\n"],"names":[],"mappings":"AAAA,cAAc,uBAAsB;AACpC,cAAc,kBAAiB;AAC/B,cAAc,qBAAoB;AAClC,cAAc,iBAAgB;AAC9B,cAAc,iBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/injectables.ts"],"sourcesContent":["import type { LazyInjectable, Scope } from '@nmtjs/core'\nimport { ProtocolInjectables } from '@nmtjs/protocol/server'\nimport type { WsUserData } from './types.ts'\n\nconst connectionData
|
|
1
|
+
{"version":3,"sources":["../../../lib/injectables.ts"],"sourcesContent":["import type { LazyInjectable, Scope } from '@nmtjs/core'\nimport { ProtocolInjectables } from '@nmtjs/protocol/server'\nimport type { WsUserData } from './types.ts'\n\nconst connectionData = ProtocolInjectables.connectionData as LazyInjectable<\n WsUserData['request'],\n Scope.Connection\n>\n\nexport const WsTransportInjectables = {\n connectionData,\n} as const\n"],"names":["ProtocolInjectables","connectionData","WsTransportInjectables"],"mappings":"AACA,SAASA,mBAAmB,QAAQ,yBAAwB;AAG5D,MAAMC,iBAAiBD,oBAAoBC,cAAc;AAKzD,OAAO,MAAMC,yBAAyB;IACpCD;AACF,EAAU"}
|
package/dist/lib/server.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
1
|
import { App, SSLApp } from 'uWebSockets.js';
|
|
2
|
+
import assert from 'node:assert';
|
|
3
|
+
import { randomUUID } from 'node:crypto';
|
|
3
4
|
import { createPromise } from '@nmtjs/common';
|
|
4
5
|
import { ClientMessageType, decodeNumber } from '@nmtjs/protocol/common';
|
|
5
6
|
import { ProtocolInjectables } from '@nmtjs/protocol/server';
|
|
7
|
+
import { WsTransportInjectables } from "./injectables.js";
|
|
6
8
|
import { getRequestData, send } from "./utils.js";
|
|
7
9
|
export class WsTransportServer {
|
|
8
10
|
context;
|
|
@@ -52,13 +54,14 @@ export class WsTransportServer {
|
|
|
52
54
|
try {
|
|
53
55
|
const { context: _context, connection } = await this.context.protocol.connections.add(this, {
|
|
54
56
|
id,
|
|
55
|
-
data:
|
|
57
|
+
data: {}
|
|
56
58
|
}, {
|
|
57
59
|
acceptType: request.acceptType,
|
|
58
60
|
contentType: request.contentType
|
|
59
61
|
});
|
|
60
62
|
Object.assign(context, _context);
|
|
61
63
|
context.container.provide(ProtocolInjectables.connection, connection);
|
|
64
|
+
context.container.provide(WsTransportInjectables.connectionData, request);
|
|
62
65
|
opening.resolve();
|
|
63
66
|
} catch (error) {
|
|
64
67
|
opening.reject(error);
|
|
@@ -92,7 +95,9 @@ export class WsTransportServer {
|
|
|
92
95
|
});
|
|
93
96
|
}
|
|
94
97
|
send(connection, messageType, buffer) {
|
|
95
|
-
|
|
98
|
+
const ws = this.clients.get(connection.id);
|
|
99
|
+
assert(ws, 'Websocket not found');
|
|
100
|
+
send(ws, messageType, buffer);
|
|
96
101
|
}
|
|
97
102
|
async start() {
|
|
98
103
|
return new Promise((resolve, reject)=>{
|
package/dist/lib/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/server.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport {\n App,\n type HttpRequest,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n} from 'uWebSockets.js'\n\nimport { createPromise } from '@nmtjs/common'\nimport {\n ClientMessageType,\n type ServerMessageType,\n decodeNumber,\n decodeText,\n} from '@nmtjs/protocol/common'\nimport {\n type Connection,\n ProtocolInjectables,\n type Transport,\n type TransportPluginContext,\n} from '@nmtjs/protocol/server'\nimport type {\n WsTransportOptions,\n WsTransportSocket,\n WsUserData,\n} from './types.ts'\nimport { getRequestData, send } from './utils.ts'\n\nexport type WsConnectionData = {\n ws: WsTransportSocket\n}\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\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: (res, req, context) => {\n const requestData = getRequestData(req)\n\n const contentType =\n requestData.headers.get('content-type') ||\n requestData.query.get('content-type')\n\n const acceptType =\n requestData.headers.get('accept') || requestData.query.get('accept')\n\n const data: WsUserData = {\n id: randomUUID(),\n request: {\n query: requestData.query,\n headers: requestData.headers,\n proxiedRemoteAddress: Buffer.from(\n res.getProxiedRemoteAddressAsText(),\n ).toString(),\n remoteAddress: Buffer.from(\n res.getRemoteAddressAsText(),\n ).toString(),\n contentType,\n acceptType,\n },\n opening: createPromise(),\n backpressure: null,\n context: {} as any,\n }\n\n res.upgrade(\n data,\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context,\n )\n },\n open: async (ws: WsTransportSocket) => {\n const { id, context, request, opening } = ws.getUserData()\n this.clients.set(id, ws)\n this.logger.debug('Connection %s opened', id)\n try {\n const { context: _context, connection } =\n await this.context.protocol.connections.add(\n this,\n { id, data: request },\n {\n acceptType: request.acceptType,\n contentType: request.contentType,\n },\n )\n Object.assign(context, _context)\n context.container.provide(\n ProtocolInjectables.connection,\n connection,\n )\n opening.resolve()\n } catch (error) {\n opening.reject(error)\n }\n },\n message: async (ws: WsTransportSocket, buffer) => {\n const { opening } = ws.getUserData()\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 opening.promise\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.connections.remove(id)\n },\n })\n }\n\n send(\n connection: Connection<WsConnectionData>,\n messageType: ServerMessageType,\n buffer: ArrayBuffer,\n ) {\n send(connection.data.ws, messageType, buffer)\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const hostname = this.options.hostname ?? '127.0.0.1'\n this.server.listen(hostname, this.options.port!, (socket) => {\n if (socket) {\n this.logger.info(\n 'Server started on %s:%s',\n hostname,\n this.options.port!,\n )\n resolve()\n } else {\n reject(new Error('Failed to start server'))\n }\n })\n })\n }\n\n async stop() {\n this.server.close()\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: Error,\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 // TODO: this should be configurable\n const origin = req.getHeader('origin')\n if (!origin) return\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.clientStreams.push(\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.clientStreams.end(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.clientStreams.abort(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.serverStreams.pull(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.serverStreams.abort(id, streamId)\n }\n}\n"],"names":["randomUUID","App","SSLApp","createPromise","ClientMessageType","decodeNumber","ProtocolInjectables","getRequestData","send","WsTransportServer","server","clients","constructor","context","options","Map","tls","res","req","applyCors","writeStatus","endWithoutBody","get","writeHeader","end","ws","sendPingsAutomatically","maxPayloadLength","upgrade","requestData","contentType","headers","query","acceptType","data","id","request","proxiedRemoteAddress","Buffer","from","getProxiedRemoteAddressAsText","toString","remoteAddress","getRemoteAddressAsText","opening","backpressure","getHeader","open","getUserData","set","logger","debug","_context","connection","protocol","connections","add","Object","assign","container","provide","resolve","error","reject","message","buffer","messageType","promise","slice","Uint8Array","BYTES_PER_ELEMENT","logError","drain","close","code","delete","remove","start","Promise","hostname","listen","port","socket","info","Error","stop","cause","origin","Rpc","rpcRaw","RpcAbort","rpcAbortRaw","RpcStreamAbort","rpcStreamAbortRaw","ClientStreamPush","streamId","clientStreams","push","Uint32Array","ClientStreamEnd","ClientStreamAbort","abort","ServerStreamPull","serverStreams","pull","ServerStreamAbort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../lib/server.ts"],"sourcesContent":["import {\n App,\n type HttpRequest,\n type HttpResponse,\n SSLApp,\n type TemplatedApp,\n} from 'uWebSockets.js'\nimport assert from 'node:assert'\nimport { randomUUID } from 'node:crypto'\nimport { createPromise } from '@nmtjs/common'\nimport {\n ClientMessageType,\n decodeNumber,\n type ServerMessageType,\n} from '@nmtjs/protocol/common'\nimport {\n type Connection,\n ProtocolInjectables,\n type Transport,\n type TransportPluginContext,\n} from '@nmtjs/protocol/server'\nimport { WsTransportInjectables } from './injectables.ts'\nimport type {\n WsTransportOptions,\n WsTransportSocket,\n WsUserData,\n} from './types.ts'\nimport { getRequestData, send } from './utils.ts'\n\nexport type WsConnectionData = {}\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\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: (res, req, context) => {\n const requestData = getRequestData(req)\n\n const contentType =\n requestData.headers.get('content-type') ||\n requestData.query.get('content-type')\n\n const acceptType =\n requestData.headers.get('accept') || requestData.query.get('accept')\n\n const data: WsUserData = {\n id: randomUUID(),\n request: {\n query: requestData.query,\n headers: requestData.headers,\n proxiedRemoteAddress: Buffer.from(\n res.getProxiedRemoteAddressAsText(),\n ).toString(),\n remoteAddress: Buffer.from(\n res.getRemoteAddressAsText(),\n ).toString(),\n contentType,\n acceptType,\n },\n opening: createPromise(),\n backpressure: null,\n context: {} as any,\n }\n\n res.upgrade(\n data,\n req.getHeader('sec-websocket-key'),\n req.getHeader('sec-websocket-protocol'),\n req.getHeader('sec-websocket-extensions'),\n context,\n )\n },\n open: async (ws: WsTransportSocket) => {\n const { id, context, request, opening } = ws.getUserData()\n this.clients.set(id, ws)\n this.logger.debug('Connection %s opened', id)\n try {\n const { context: _context, connection } =\n await this.context.protocol.connections.add(\n this,\n { id, data: {} },\n {\n acceptType: request.acceptType,\n contentType: request.contentType,\n },\n )\n Object.assign(context, _context)\n context.container.provide(\n ProtocolInjectables.connection,\n connection,\n )\n context.container.provide(\n WsTransportInjectables.connectionData,\n request,\n )\n opening.resolve()\n } catch (error) {\n opening.reject(error)\n }\n },\n message: async (ws: WsTransportSocket, buffer) => {\n const { opening } = ws.getUserData()\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 opening.promise\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.connections.remove(id)\n },\n })\n }\n\n send(\n connection: Connection<WsConnectionData>,\n messageType: ServerMessageType,\n buffer: ArrayBuffer,\n ) {\n const ws = this.clients.get(connection.id)\n assert(ws, 'Websocket not found')\n send(ws, messageType, buffer)\n }\n\n async start() {\n return new Promise<void>((resolve, reject) => {\n const hostname = this.options.hostname ?? '127.0.0.1'\n this.server.listen(hostname, this.options.port!, (socket) => {\n if (socket) {\n this.logger.info(\n 'Server started on %s:%s',\n hostname,\n this.options.port!,\n )\n resolve()\n } else {\n reject(new Error('Failed to start server'))\n }\n })\n })\n }\n\n async stop() {\n this.server.close()\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: Error,\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 // TODO: this should be configurable\n const origin = req.getHeader('origin')\n if (!origin) return\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.clientStreams.push(\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.clientStreams.end(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.clientStreams.abort(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.serverStreams.pull(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.serverStreams.abort(id, streamId)\n }\n}\n"],"names":["App","SSLApp","assert","randomUUID","createPromise","ClientMessageType","decodeNumber","ProtocolInjectables","WsTransportInjectables","getRequestData","send","WsTransportServer","server","clients","constructor","context","options","Map","tls","res","req","applyCors","writeStatus","endWithoutBody","get","writeHeader","end","ws","sendPingsAutomatically","maxPayloadLength","upgrade","requestData","contentType","headers","query","acceptType","data","id","request","proxiedRemoteAddress","Buffer","from","getProxiedRemoteAddressAsText","toString","remoteAddress","getRemoteAddressAsText","opening","backpressure","getHeader","open","getUserData","set","logger","debug","_context","connection","protocol","connections","add","Object","assign","container","provide","connectionData","resolve","error","reject","message","buffer","messageType","promise","slice","Uint8Array","BYTES_PER_ELEMENT","logError","drain","close","code","delete","remove","start","Promise","hostname","listen","port","socket","info","Error","stop","cause","origin","Rpc","rpcRaw","RpcAbort","rpcAbortRaw","RpcStreamAbort","rpcStreamAbortRaw","ClientStreamPush","streamId","clientStreams","push","Uint32Array","ClientStreamEnd","ClientStreamAbort","abort","ServerStreamPull","serverStreams","pull","ServerStreamAbort"],"mappings":"AAAA,SACEA,GAAG,EAGHC,MAAM,QAED,iBAAgB;AACvB,OAAOC,YAAY,cAAa;AAChC,SAASC,UAAU,QAAQ,cAAa;AACxC,SAASC,aAAa,QAAQ,gBAAe;AAC7C,SACEC,iBAAiB,EACjBC,YAAY,QAEP,yBAAwB;AAC/B,SAEEC,mBAAmB,QAGd,yBAAwB;AAC/B,SAASC,sBAAsB,QAAQ,mBAAkB;AAMzD,SAASC,cAAc,EAAEC,IAAI,QAAQ,aAAY;AAIjD,OAAO,MAAMC;;;IACDC,OAAqB;IACrBC,QAAmD;IAE7DC,YACE,AAAmBC,OAA+B,EAClD,AAAmBC,OAA2B,CAC9C;aAFmBD,UAAAA;aACAC,UAAAA;aAJXH,UAA0C,IAAII;QAMtD,IAAI,CAACL,MAAM,GAAG,IAAI,CAACI,OAAO,CAACE,GAAG,GAAGjB,OAAOe,QAAQE,GAAG,IAAKlB;QAExD,IAAI,CAACY,MAAM,CACRI,OAAO,CAAC,MAAM,CAACG,KAAKC;YACnB,IAAI,CAACC,SAAS,CAACF,KAAKC;YACpBD,IAAIG,WAAW,CAAC;YAChBH,IAAII,cAAc;QACpB,GACCC,GAAG,CAAC,YAAY,CAACL,KAAKC;YACrB,IAAI,CAACC,SAAS,CAACF,KAAKC;YACpBD,IAAIM,WAAW,CAAC,gBAAgB;YAChCN,IAAIO,GAAG,CAAC;QACV,GACCC,EAAE,CAAa,QAAQ;YACtBC,wBAAwB;YACxBC,kBAAkB,IAAI,CAACb,OAAO,CAACa,gBAAgB;YAC/CC,SAAS,CAACX,KAAKC,KAAKL;gBAClB,MAAMgB,cAActB,eAAeW;gBAEnC,MAAMY,cACJD,YAAYE,OAAO,CAACT,GAAG,CAAC,mBACxBO,YAAYG,KAAK,CAACV,GAAG,CAAC;gBAExB,MAAMW,aACJJ,YAAYE,OAAO,CAACT,GAAG,CAAC,aAAaO,YAAYG,KAAK,CAACV,GAAG,CAAC;gBAE7D,MAAMY,OAAmB;oBACvBC,IAAIlC;oBACJmC,SAAS;wBACPJ,OAAOH,YAAYG,KAAK;wBACxBD,SAASF,YAAYE,OAAO;wBAC5BM,sBAAsBC,OAAOC,IAAI,CAC/BtB,IAAIuB,6BAA6B,IACjCC,QAAQ;wBACVC,eAAeJ,OAAOC,IAAI,CACxBtB,IAAI0B,sBAAsB,IAC1BF,QAAQ;wBACVX;wBACAG;oBACF;oBACAW,SAAS1C;oBACT2C,cAAc;oBACdhC,SAAS,CAAC;gBACZ;gBAEAI,IAAIW,OAAO,CACTM,MACAhB,IAAI4B,SAAS,CAAC,sBACd5B,IAAI4B,SAAS,CAAC,2BACd5B,IAAI4B,SAAS,CAAC,6BACdjC;YAEJ;YACAkC,MAAM,OAAOtB;gBACX,MAAM,EAAEU,EAAE,EAAEtB,OAAO,EAAEuB,OAAO,EAAEQ,OAAO,EAAE,GAAGnB,GAAGuB,WAAW;gBACxD,IAAI,CAACrC,OAAO,CAACsC,GAAG,CAACd,IAAIV;gBACrB,IAAI,CAACyB,MAAM,CAACC,KAAK,CAAC,wBAAwBhB;gBAC1C,IAAI;oBACF,MAAM,EAAEtB,SAASuC,QAAQ,EAAEC,UAAU,EAAE,GACrC,MAAM,IAAI,CAACxC,OAAO,CAACyC,QAAQ,CAACC,WAAW,CAACC,GAAG,CACzC,IAAI,EACJ;wBAAErB;wBAAID,MAAM,CAAC;oBAAE,GACf;wBACED,YAAYG,QAAQH,UAAU;wBAC9BH,aAAaM,QAAQN,WAAW;oBAClC;oBAEJ2B,OAAOC,MAAM,CAAC7C,SAASuC;oBACvBvC,QAAQ8C,SAAS,CAACC,OAAO,CACvBvD,oBAAoBgD,UAAU,EAC9BA;oBAEFxC,QAAQ8C,SAAS,CAACC,OAAO,CACvBtD,uBAAuBuD,cAAc,EACrCzB;oBAEFQ,QAAQkB,OAAO;gBACjB,EAAE,OAAOC,OAAO;oBACdnB,QAAQoB,MAAM,CAACD;gBACjB;YACF;YACAE,SAAS,OAAOxC,IAAuByC;gBACrC,MAAM,EAAEtB,OAAO,EAAE,GAAGnB,GAAGuB,WAAW;gBAClC,MAAMmB,cAAc/D,aAAa8D,QAAQ;gBACzC,IAAIC,eAAe,IAAI,KAAK,OAAO;oBACjC1C,GAAGD,GAAG,CAAC,MAAM;gBACf,OAAO;oBACL,IAAI;wBACF,MAAMoB,QAAQwB,OAAO;wBACrB,MAAM,IAAI,CAACD,YAAY,CACrB1C,IACAyC,OAAOG,KAAK,CAACC,WAAWC,iBAAiB;oBAE7C,EAAE,OAAOR,OAAY;wBACnB,IAAI,CAACS,QAAQ,CAACT,OAAO;oBACvB;gBACF;YACF;YACAU,OAAO,CAAChD;gBACN,MAAMS,OAAOT,GAAGuB,WAAW;gBAC3Bd,KAAKW,YAAY,EAAEiB;gBACnB5B,KAAKW,YAAY,GAAG;YACtB;YACA6B,OAAO,OAAOjD,IAAuBkD,MAAMV;gBACzC,MAAM,EAAE9B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;gBAE7B,IAAI,CAACE,MAAM,CAACC,KAAK,CACf,yCACAhB,IACAwC,MACArC,OAAOC,IAAI,CAAC0B,SAASxB,QAAQ;gBAE/B,IAAI,CAAC9B,OAAO,CAACiE,MAAM,CAACzC;gBACpB,MAAM,IAAI,CAACmB,QAAQ,CAACC,WAAW,CAACsB,MAAM,CAAC1C;YACzC;QACF;IACJ;IAEA3B,KACE6C,UAAwC,EACxCc,WAA8B,EAC9BD,MAAmB,EACnB;QACA,MAAMzC,KAAK,IAAI,CAACd,OAAO,CAACW,GAAG,CAAC+B,WAAWlB,EAAE;QACzCnC,OAAOyB,IAAI;QACXjB,KAAKiB,IAAI0C,aAAaD;IACxB;IAEA,MAAMY,QAAQ;QACZ,OAAO,IAAIC,QAAc,CAACjB,SAASE;YACjC,MAAMgB,WAAW,IAAI,CAAClE,OAAO,CAACkE,QAAQ,IAAI;YAC1C,IAAI,CAACtE,MAAM,CAACuE,MAAM,CAACD,UAAU,IAAI,CAAClE,OAAO,CAACoE,IAAI,EAAG,CAACC;gBAChD,IAAIA,QAAQ;oBACV,IAAI,CAACjC,MAAM,CAACkC,IAAI,CACd,2BACAJ,UACA,IAAI,CAAClE,OAAO,CAACoE,IAAI;oBAEnBpB;gBACF,OAAO;oBACLE,OAAO,IAAIqB,MAAM;gBACnB;YACF;QACF;IACF;IAEA,MAAMC,OAAO;QACX,IAAI,CAAC5E,MAAM,CAACgE,KAAK;IACnB;IAEA,IAAcpB,WAAW;QACvB,OAAO,IAAI,CAACzC,OAAO,CAACyC,QAAQ;IAC9B;IAEA,IAAcJ,SAAS;QACrB,OAAO,IAAI,CAACrC,OAAO,CAACqC,MAAM;IAC5B;IAEA,MAAgBsB,SACde,KAAY,EACZtB,UAAU,wCAAwC,EAClD;QACA,IAAI,CAACf,MAAM,CAACa,KAAK,CAAC,IAAIsB,MAAMpB,SAAS;YAAEsB;QAAM;IAC/C;IAEUpE,UAAUF,GAAiB,EAAEC,GAAgB,EAAE;QAEvD,MAAMsE,SAAStE,IAAI4B,SAAS,CAAC;QAC7B,IAAI,CAAC0C,QAAQ;QACbvE,IAAIM,WAAW,CAAC,+BAA+BiE;QAC/CvE,IAAIM,WAAW,CAAC,gCAAgC;QAChDN,IAAIM,WAAW,CAAC,gCAAgC;QAChDN,IAAIM,WAAW,CAAC,oCAAoC;IACtD;IAEU,CAACpB,kBAAkBsF,GAAG,CAAC,CAC/BhE,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,IAAI,CAACM,QAAQ,CAACoC,MAAM,CAACvD,IAAI+B;IAC3B;IAEU,CAAC/D,kBAAkBwF,QAAQ,CAAC,CACpClE,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,IAAI,CAACM,QAAQ,CAACsC,WAAW,CAACzD,IAAI+B;IAChC;IAEU,CAAC/D,kBAAkB0F,cAAc,CAAC,CAC1CpE,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,IAAI,CAACM,QAAQ,CAACwC,iBAAiB,CAAC3D,IAAI+B;IACtC;IAEU,CAAC/D,kBAAkB4F,gBAAgB,CAAC,CAC5CtE,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,MAAMgD,WAAW5F,aAAa8D,QAAQ;QACtC,IAAI,CAACZ,QAAQ,CAAC2C,aAAa,CAACC,IAAI,CAC9B/D,IACA6D,UACA9B,OAAOG,KAAK,CAAC8B,YAAY5B,iBAAiB;IAE9C;IAEU,CAACpE,kBAAkBiG,eAAe,CAAC,CAC3C3E,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,MAAMgD,WAAW5F,aAAa8D,QAAQ;QACtC,IAAI,CAACZ,QAAQ,CAAC2C,aAAa,CAACzE,GAAG,CAACW,IAAI6D;IACtC;IAEU,CAAC7F,kBAAkBkG,iBAAiB,CAAC,CAC7C5E,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,MAAMgD,WAAW5F,aAAa8D,QAAQ;QACtC,IAAI,CAACZ,QAAQ,CAAC2C,aAAa,CAACK,KAAK,CAACnE,IAAI6D;IACxC;IAEU,CAAC7F,kBAAkBoG,gBAAgB,CAAC,CAC5C9E,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,MAAMgD,WAAW5F,aAAa8D,QAAQ;QACtC,IAAI,CAACZ,QAAQ,CAACkD,aAAa,CAACC,IAAI,CAACtE,IAAI6D;IACvC;IAEU,CAAC7F,kBAAkBuG,iBAAiB,CAAC,CAC7CjF,EAAqB,EACrByC,MAAmB,EACnB;QACA,MAAM,EAAE/B,EAAE,EAAE,GAAGV,GAAGuB,WAAW;QAC7B,MAAMgD,WAAW5F,aAAa8D,QAAQ;QACtC,IAAI,CAACZ,QAAQ,CAACkD,aAAa,CAACF,KAAK,CAACnE,IAAI6D;IACxC;AACF"}
|
package/dist/lib/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/types.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"sources":["../../../lib/types.ts"],"sourcesContent":["import type { AppOptions, WebSocket } from 'uWebSockets.js'\nimport type { InteractivePromise } from '@nmtjs/common'\nimport type { Connection, ConnectionContext } from '@nmtjs/protocol/server'\n\nexport type WsUserData = {\n id: Connection['id']\n opening: InteractivePromise<void>\n backpressure: InteractivePromise<void> | null\n request: {\n headers: Map<string, string>\n query: URLSearchParams\n remoteAddress: string\n proxiedRemoteAddress: string\n acceptType: string | null\n contentType: string | null\n }\n context: ConnectionContext\n}\n\nexport type WsTransportSocket = WebSocket<WsUserData>\n\nexport type WsTransportOptions = {\n port?: number\n hostname?: string\n unix?: string\n tls?: AppOptions\n maxPayloadLength?: number\n maxStreamChunkLength?: number\n}\n"],"names":[],"mappings":"AAqBA,WAOC"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createPromise } from '@nmtjs/common';
|
|
2
|
-
import {
|
|
2
|
+
import { concat, ErrorCode, encodeNumber } from '@nmtjs/protocol/common';
|
|
3
3
|
import { ProtocolError } from '@nmtjs/protocol/server';
|
|
4
4
|
export const send = (ws, type, ...buffers)=>{
|
|
5
5
|
const data = ws.getUserData();
|
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../lib/utils.ts"],"sourcesContent":["import { createPromise } from '@nmtjs/common'\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../lib/utils.ts"],"sourcesContent":["import type { HttpRequest } from 'uWebSockets.js'\nimport { createPromise } from '@nmtjs/common'\nimport { concat, ErrorCode, encodeNumber } from '@nmtjs/protocol/common'\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\ntype RequestData = {\n url: string\n origin: URL | null\n method: string\n headers: Map<string, string>\n query: URLSearchParams\n}\n\nexport const getRequestData = (req: HttpRequest): RequestData => {\n const url = req.getUrl()\n const method = req.getMethod()\n const headers = new Map()\n req.forEach((key, value) => headers.set(key, value))\n const query = new URLSearchParams(req.getQuery())\n const origin = headers.has('origin')\n ? new URL(url, headers.get('origin'))\n : null\n\n return {\n url,\n origin,\n method,\n headers,\n query,\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"],"names":["createPromise","concat","ErrorCode","encodeNumber","ProtocolError","send","ws","type","buffers","data","getUserData","buffer","result","backpressure","error","toRecord","input","obj","forEach","value","key","getRequestData","req","url","getUrl","method","getMethod","headers","Map","set","query","URLSearchParams","getQuery","origin","has","URL","get","InternalError","message","InternalServerError","NotFoundError","NotFound","ForbiddenError","Forbidden","RequestTimeoutError","RequestTimeout"],"mappings":"AACA,SAASA,aAAa,QAAQ,gBAAe;AAC7C,SAASC,MAAM,EAAEC,SAAS,EAAEC,YAAY,QAAQ,yBAAwB;AACxE,SAASC,aAAa,QAAQ,yBAAwB;AAGtD,OAAO,MAAMC,OAAO,CAClBC,IACAC,MACA,GAAGC;IAEH,MAAMC,OAAOH,GAAGI,WAAW;IAC3B,IAAI;QACF,MAAMC,SAASV,OAAOE,aAAaI,MAAM,aAAaC;QACtD,MAAMI,SAASN,GAAGD,IAAI,CAACM,QAAQ;QAC/B,IAAIC,WAAW,GAAG;YAChBH,KAAKI,YAAY,GAAGb;YACpB,OAAO;QACT;QACA,IAAIY,WAAW,GAAG;YAChB,OAAO;QACT;QACA,OAAO;IACT,EAAE,OAAOE,OAAO;QACd,OAAO;IACT;AACF,EAAC;AAED,OAAO,MAAMC,WAAW,CAACC;IAGvB,MAAMC,MAA8B,CAAC;IACrCD,MAAME,OAAO,CAAC,CAACC,OAAOC;QACpBH,GAAG,CAACG,IAAI,GAAGD;IACb;IACA,OAAOF;AACT,EAAC;AAUD,OAAO,MAAMI,iBAAiB,CAACC;IAC7B,MAAMC,MAAMD,IAAIE,MAAM;IACtB,MAAMC,SAASH,IAAII,SAAS;IAC5B,MAAMC,UAAU,IAAIC;IACpBN,IAAIJ,OAAO,CAAC,CAACE,KAAKD,QAAUQ,QAAQE,GAAG,CAACT,KAAKD;IAC7C,MAAMW,QAAQ,IAAIC,gBAAgBT,IAAIU,QAAQ;IAC9C,MAAMC,SAASN,QAAQO,GAAG,CAAC,YACvB,IAAIC,IAAIZ,KAAKI,QAAQS,GAAG,CAAC,aACzB;IAEJ,OAAO;QACLb;QACAU;QACAR;QACAE;QACAG;IACF;AACF,EAAC;AAED,OAAO,MAAMO,gBAAgB,CAACC,UAAU,uBAAuB,GAC7D,IAAIlC,cAAcF,UAAUqC,mBAAmB,EAAED,SAAQ;AAE3D,OAAO,MAAME,gBAAgB,CAACF,UAAU,WAAW,GACjD,IAAIlC,cAAcF,UAAUuC,QAAQ,EAAEH,SAAQ;AAEhD,OAAO,MAAMI,iBAAiB,CAACJ,UAAU,WAAW,GAClD,IAAIlC,cAAcF,UAAUyC,SAAS,EAAEL,SAAQ;AAEjD,OAAO,MAAMM,sBAAsB,CAACN,UAAU,iBAAiB,GAC7D,IAAIlC,cAAcF,UAAU2C,cAAc,EAAEP,SAAQ"}
|
package/index.ts
CHANGED
package/lib/injectables.ts
CHANGED
|
@@ -2,11 +2,10 @@ import type { LazyInjectable, Scope } from '@nmtjs/core'
|
|
|
2
2
|
import { ProtocolInjectables } from '@nmtjs/protocol/server'
|
|
3
3
|
import type { WsUserData } from './types.ts'
|
|
4
4
|
|
|
5
|
-
const connectionData =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
>
|
|
5
|
+
const connectionData = ProtocolInjectables.connectionData as LazyInjectable<
|
|
6
|
+
WsUserData['request'],
|
|
7
|
+
Scope.Connection
|
|
8
|
+
>
|
|
10
9
|
|
|
11
10
|
export const WsTransportInjectables = {
|
|
12
11
|
connectionData,
|
package/lib/server.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto'
|
|
2
1
|
import {
|
|
3
2
|
App,
|
|
4
3
|
type HttpRequest,
|
|
@@ -6,13 +5,13 @@ import {
|
|
|
6
5
|
SSLApp,
|
|
7
6
|
type TemplatedApp,
|
|
8
7
|
} from 'uWebSockets.js'
|
|
9
|
-
|
|
8
|
+
import assert from 'node:assert'
|
|
9
|
+
import { randomUUID } from 'node:crypto'
|
|
10
10
|
import { createPromise } from '@nmtjs/common'
|
|
11
11
|
import {
|
|
12
12
|
ClientMessageType,
|
|
13
|
-
type ServerMessageType,
|
|
14
13
|
decodeNumber,
|
|
15
|
-
|
|
14
|
+
type ServerMessageType,
|
|
16
15
|
} from '@nmtjs/protocol/common'
|
|
17
16
|
import {
|
|
18
17
|
type Connection,
|
|
@@ -20,6 +19,7 @@ import {
|
|
|
20
19
|
type Transport,
|
|
21
20
|
type TransportPluginContext,
|
|
22
21
|
} from '@nmtjs/protocol/server'
|
|
22
|
+
import { WsTransportInjectables } from './injectables.ts'
|
|
23
23
|
import type {
|
|
24
24
|
WsTransportOptions,
|
|
25
25
|
WsTransportSocket,
|
|
@@ -27,9 +27,7 @@ import type {
|
|
|
27
27
|
} from './types.ts'
|
|
28
28
|
import { getRequestData, send } from './utils.ts'
|
|
29
29
|
|
|
30
|
-
export type WsConnectionData = {
|
|
31
|
-
ws: WsTransportSocket
|
|
32
|
-
}
|
|
30
|
+
export type WsConnectionData = {}
|
|
33
31
|
|
|
34
32
|
export class WsTransportServer implements Transport<WsConnectionData> {
|
|
35
33
|
protected server!: TemplatedApp
|
|
@@ -100,7 +98,7 @@ export class WsTransportServer implements Transport<WsConnectionData> {
|
|
|
100
98
|
const { context: _context, connection } =
|
|
101
99
|
await this.context.protocol.connections.add(
|
|
102
100
|
this,
|
|
103
|
-
{ id, data:
|
|
101
|
+
{ id, data: {} },
|
|
104
102
|
{
|
|
105
103
|
acceptType: request.acceptType,
|
|
106
104
|
contentType: request.contentType,
|
|
@@ -111,6 +109,10 @@ export class WsTransportServer implements Transport<WsConnectionData> {
|
|
|
111
109
|
ProtocolInjectables.connection,
|
|
112
110
|
connection,
|
|
113
111
|
)
|
|
112
|
+
context.container.provide(
|
|
113
|
+
WsTransportInjectables.connectionData,
|
|
114
|
+
request,
|
|
115
|
+
)
|
|
114
116
|
opening.resolve()
|
|
115
117
|
} catch (error) {
|
|
116
118
|
opening.reject(error)
|
|
@@ -158,7 +160,9 @@ export class WsTransportServer implements Transport<WsConnectionData> {
|
|
|
158
160
|
messageType: ServerMessageType,
|
|
159
161
|
buffer: ArrayBuffer,
|
|
160
162
|
) {
|
|
161
|
-
|
|
163
|
+
const ws = this.clients.get(connection.id)
|
|
164
|
+
assert(ws, 'Websocket not found')
|
|
165
|
+
send(ws, messageType, buffer)
|
|
162
166
|
}
|
|
163
167
|
|
|
164
168
|
async start() {
|
package/lib/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import type { AppOptions, WebSocket } from 'uWebSockets.js'
|
|
1
2
|
import type { InteractivePromise } from '@nmtjs/common'
|
|
2
3
|
import type { Connection, ConnectionContext } from '@nmtjs/protocol/server'
|
|
3
|
-
import type { AppOptions, WebSocket } from 'uWebSockets.js'
|
|
4
4
|
|
|
5
5
|
export type WsUserData = {
|
|
6
6
|
id: Connection['id']
|
package/lib/utils.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import type { HttpRequest } from 'uWebSockets.js'
|
|
1
2
|
import { createPromise } from '@nmtjs/common'
|
|
2
|
-
import {
|
|
3
|
+
import { concat, ErrorCode, encodeNumber } from '@nmtjs/protocol/common'
|
|
3
4
|
import { ProtocolError } from '@nmtjs/protocol/server'
|
|
4
|
-
import type { HttpRequest } from 'uWebSockets.js'
|
|
5
5
|
import type { WsTransportSocket } from './types.ts'
|
|
6
6
|
|
|
7
7
|
export const send = (
|
package/package.json
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.51.0",
|
|
12
|
-
"@nmtjs/core": "^0.6.
|
|
13
|
-
"@nmtjs/protocol": "^0.6.
|
|
14
|
-
"@nmtjs/common": "^0.6.
|
|
12
|
+
"@nmtjs/core": "^0.6.3",
|
|
13
|
+
"@nmtjs/protocol": "^0.6.3",
|
|
14
|
+
"@nmtjs/common": "^0.6.3"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@types/node": "^18.0.0"
|
|
@@ -23,11 +23,10 @@
|
|
|
23
23
|
"index.ts",
|
|
24
24
|
"lib",
|
|
25
25
|
"dist",
|
|
26
|
-
"tsconfig.json",
|
|
27
26
|
"LICENSE.md",
|
|
28
27
|
"README.md"
|
|
29
28
|
],
|
|
30
|
-
"version": "0.2.
|
|
29
|
+
"version": "0.2.1",
|
|
31
30
|
"scripts": {
|
|
32
31
|
"build": "neemata-build ./index.ts './lib/**/*.ts'",
|
|
33
32
|
"type-check": "tsc --noEmit"
|
package/tsconfig.json
DELETED