@nmtjs/protocol 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +9 -0
- package/dist/client/events.js +41 -0
- package/dist/client/events.js.map +1 -0
- package/dist/client/format.js +2 -0
- package/dist/client/format.js.map +1 -0
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/protocol.js +311 -0
- package/dist/client/protocol.js.map +1 -0
- package/dist/client/stream.js +99 -0
- package/dist/client/stream.js.map +1 -0
- package/dist/common/binary.js +25 -0
- package/dist/common/binary.js.map +1 -0
- package/dist/common/blob.js +42 -0
- package/dist/common/blob.js.map +1 -0
- package/dist/common/enums.js +44 -0
- package/dist/common/enums.js.map +1 -0
- package/dist/common/index.js +4 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/types.js +1 -0
- package/dist/common/types.js.map +1 -0
- package/dist/server/api.js +1 -0
- package/dist/server/api.js.map +1 -0
- package/dist/server/connection.js +21 -0
- package/dist/server/connection.js.map +1 -0
- package/dist/server/constants.js +1 -0
- package/dist/server/constants.js.map +1 -0
- package/dist/server/format.js +48 -0
- package/dist/server/format.js.map +1 -0
- package/dist/server/index.js +10 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/injectables.js +22 -0
- package/dist/server/injectables.js.map +1 -0
- package/dist/server/protocol.js +293 -0
- package/dist/server/protocol.js.map +1 -0
- package/dist/server/registry.js +19 -0
- package/dist/server/registry.js.map +1 -0
- package/dist/server/stream.js +30 -0
- package/dist/server/stream.js.map +1 -0
- package/dist/server/transport.js +7 -0
- package/dist/server/transport.js.map +1 -0
- package/dist/server/utils.js +10 -0
- package/dist/server/utils.js.map +1 -0
- package/lib/client/events.ts +66 -0
- package/lib/client/format.ts +22 -0
- package/lib/client/index.ts +4 -0
- package/lib/client/protocol.ts +440 -0
- package/lib/client/stream.ts +116 -0
- package/lib/common/binary.ts +60 -0
- package/lib/common/blob.ts +70 -0
- package/lib/common/enums.ts +46 -0
- package/lib/common/index.ts +4 -0
- package/lib/common/types.ts +64 -0
- package/lib/server/api.ts +47 -0
- package/lib/server/connection.ts +57 -0
- package/lib/server/constants.ts +4 -0
- package/lib/server/format.ts +107 -0
- package/lib/server/index.ts +10 -0
- package/lib/server/injectables.ts +51 -0
- package/lib/server/protocol.ts +422 -0
- package/lib/server/registry.ts +24 -0
- package/lib/server/stream.ts +43 -0
- package/lib/server/transport.ts +36 -0
- package/lib/server/utils.ts +22 -0
- package/package.json +39 -0
- package/tsconfig.json +3 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export var ClientMessageType;
|
|
2
|
+
(function(ClientMessageType) {
|
|
3
|
+
ClientMessageType[ClientMessageType["Rpc"] = 10] = "Rpc";
|
|
4
|
+
ClientMessageType[ClientMessageType["RpcAbort"] = 11] = "RpcAbort";
|
|
5
|
+
ClientMessageType[ClientMessageType["RpcStreamAbort"] = 12] = "RpcStreamAbort";
|
|
6
|
+
ClientMessageType[ClientMessageType["ClientStreamPush"] = 20] = "ClientStreamPush";
|
|
7
|
+
ClientMessageType[ClientMessageType["ClientStreamEnd"] = 21] = "ClientStreamEnd";
|
|
8
|
+
ClientMessageType[ClientMessageType["ClientStreamAbort"] = 22] = "ClientStreamAbort";
|
|
9
|
+
ClientMessageType[ClientMessageType["ServerStreamAbort"] = 23] = "ServerStreamAbort";
|
|
10
|
+
ClientMessageType[ClientMessageType["ServerStreamPull"] = 24] = "ServerStreamPull";
|
|
11
|
+
})(ClientMessageType || (ClientMessageType = {}));
|
|
12
|
+
export var ServerMessageType;
|
|
13
|
+
(function(ServerMessageType) {
|
|
14
|
+
ServerMessageType[ServerMessageType["Event"] = 1] = "Event";
|
|
15
|
+
ServerMessageType[ServerMessageType["RpcResponse"] = 10] = "RpcResponse";
|
|
16
|
+
ServerMessageType[ServerMessageType["RpcStreamResponse"] = 11] = "RpcStreamResponse";
|
|
17
|
+
ServerMessageType[ServerMessageType["RpcStreamChunk"] = 12] = "RpcStreamChunk";
|
|
18
|
+
ServerMessageType[ServerMessageType["RpcStreamAbort"] = 13] = "RpcStreamAbort";
|
|
19
|
+
ServerMessageType[ServerMessageType["ServerStreamPush"] = 20] = "ServerStreamPush";
|
|
20
|
+
ServerMessageType[ServerMessageType["ServerStreamEnd"] = 21] = "ServerStreamEnd";
|
|
21
|
+
ServerMessageType[ServerMessageType["ServerStreamAbort"] = 22] = "ServerStreamAbort";
|
|
22
|
+
ServerMessageType[ServerMessageType["ClientStreamAbort"] = 23] = "ClientStreamAbort";
|
|
23
|
+
ServerMessageType[ServerMessageType["ClientStreamPull"] = 24] = "ClientStreamPull";
|
|
24
|
+
})(ServerMessageType || (ServerMessageType = {}));
|
|
25
|
+
export var TransportType;
|
|
26
|
+
(function(TransportType) {
|
|
27
|
+
TransportType["Bidirectional"] = "Bidirectional";
|
|
28
|
+
TransportType["Unidirectional"] = "Unidirectional";
|
|
29
|
+
})(TransportType || (TransportType = {}));
|
|
30
|
+
export var ErrorCode;
|
|
31
|
+
(function(ErrorCode) {
|
|
32
|
+
ErrorCode["ValidationError"] = "ValidationError";
|
|
33
|
+
ErrorCode["BadRequest"] = "BadRequest";
|
|
34
|
+
ErrorCode["NotFound"] = "NotFound";
|
|
35
|
+
ErrorCode["Forbidden"] = "Forbidden";
|
|
36
|
+
ErrorCode["Unauthorized"] = "Unauthorized";
|
|
37
|
+
ErrorCode["InternalServerError"] = "InternalServerError";
|
|
38
|
+
ErrorCode["NotAcceptable"] = "NotAcceptable";
|
|
39
|
+
ErrorCode["RequestTimeout"] = "RequestTimeout";
|
|
40
|
+
ErrorCode["GatewayTimeout"] = "GatewayTimeout";
|
|
41
|
+
ErrorCode["ServiceUnavailable"] = "ServiceUnavailable";
|
|
42
|
+
ErrorCode["ClientRequestError"] = "ClientRequestError";
|
|
43
|
+
ErrorCode["ConnectionError"] = "ConnectionError";
|
|
44
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/common/enums.ts"],"sourcesContent":["export enum ClientMessageType {\n Rpc = 10,\n RpcAbort = 11,\n RpcStreamAbort = 12,\n\n ClientStreamPush = 20,\n ClientStreamEnd = 21,\n ClientStreamAbort = 22,\n ServerStreamAbort = 23,\n ServerStreamPull = 24,\n}\n\nexport enum ServerMessageType {\n Event = 1,\n\n RpcResponse = 10,\n RpcStreamResponse = 11,\n RpcStreamChunk = 12,\n RpcStreamAbort = 13,\n\n ServerStreamPush = 20,\n ServerStreamEnd = 21,\n ServerStreamAbort = 22,\n ClientStreamAbort = 23,\n ClientStreamPull = 24,\n}\n\nexport enum TransportType {\n Bidirectional = 'Bidirectional',\n Unidirectional = 'Unidirectional',\n}\n\nexport enum ErrorCode {\n ValidationError = 'ValidationError',\n BadRequest = 'BadRequest',\n NotFound = 'NotFound',\n Forbidden = 'Forbidden',\n Unauthorized = 'Unauthorized',\n InternalServerError = 'InternalServerError',\n NotAcceptable = 'NotAcceptable',\n RequestTimeout = 'RequestTimeout',\n GatewayTimeout = 'GatewayTimeout',\n ServiceUnavailable = 'ServiceUnavailable',\n ClientRequestError = 'ClientRequestError',\n ConnectionError = 'ConnectionError',\n}\n"],"names":["ClientMessageType","ServerMessageType","TransportType","ErrorCode"],"mappings":";UAAYA;;;;;;;;;GAAAA,sBAAAA;;UAYAC;;;;;;;;;;;GAAAA,sBAAAA;;UAeAC;;;GAAAA,kBAAAA;;UAKAC;;;;;;;;;;;;;GAAAA,cAAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/common/index.ts"],"sourcesContent":["export * from './types.ts'\nexport * from './enums.ts'\nexport * from './binary.ts'\nexport * from './blob.ts'\n"],"names":[],"mappings":"AAAA,cAAc,aAAY;AAC1B,cAAc,aAAY;AAC1B,cAAc,cAAa;AAC3B,cAAc,YAAW"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/common/types.ts"],"sourcesContent":["import type { ProtocolServerBlobStream } from '../client/stream.ts'\nimport type {\n ProtocolBlob,\n ProtocolBlobInterface,\n ProtocolBlobMetadata,\n} from './blob.ts'\n\nexport type ProtocolRPC = {\n callId: number\n namespace: string\n procedure: string\n payload: any\n}\n\nexport type ProtocolRPCResponse =\n | {\n callId: number\n error: any\n payload?: never\n }\n | {\n callId: number\n payload: any\n error?: never\n }\n\nexport interface EncodeRPCContext {\n getStream: (id: number) => any\n addStream: (blob: ProtocolBlob) => {\n id: number\n metadata: ProtocolBlobMetadata\n }\n}\n\nexport interface DecodeRPCContext {\n getStream: (id: number) => any\n addStream: (id: number, metadata: ProtocolBlobMetadata) => any\n}\n\nexport interface BaseClientDecoder {\n decode(buffer: ArrayBuffer): any\n decodeRPC(buffer: ArrayBuffer, context: DecodeRPCContext): ProtocolRPCResponse\n}\n\nexport interface BaseClientEncoder {\n encode(data: any): ArrayBuffer\n encodeRPC(rpc: ProtocolRPC, context: EncodeRPCContext): ArrayBuffer\n}\n\nexport type InputType<T> = T extends any[]\n ? InputType<T[number]>[]\n : T extends ProtocolBlobInterface\n ? ProtocolBlob\n : T extends object\n ? { [K in keyof T]: InputType<T[K]> }\n : T\n\nexport type OutputType<T> = T extends any[]\n ? OutputType<T[number]>[]\n : T extends ProtocolBlobInterface\n ? ProtocolServerBlobStream\n : T extends object\n ? { [K in keyof T]: OutputType<T[K]> }\n : T\n"],"names":[],"mappings":"AAyDA,WAMS"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
export class Connection {
|
|
3
|
+
id;
|
|
4
|
+
data;
|
|
5
|
+
constructor(options){
|
|
6
|
+
this.id = options.id ?? randomUUID();
|
|
7
|
+
this.data = options.data;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class ConnectionContext {
|
|
11
|
+
streamId = 1;
|
|
12
|
+
calls = new Map();
|
|
13
|
+
clientStreams = new Map();
|
|
14
|
+
serverStreams = new Map();
|
|
15
|
+
container;
|
|
16
|
+
format;
|
|
17
|
+
constructor(container, format){
|
|
18
|
+
this.container = container;
|
|
19
|
+
this.format = format;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const kTransportPlugin = Symbol.for('neemata:TransportPluginKey');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/constants.ts"],"sourcesContent":["export const kTransportPlugin: unique symbol = Symbol.for(\n 'neemata:TransportPluginKey',\n)\nexport type kTransportPlugin = typeof kTransportPlugin\n"],"names":["kTransportPlugin","Symbol","for"],"mappings":"AAAA,OAAO,MAAMA,mBAAkCC,OAAOC,GAAG,CACvD,8BACD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { match } from '@nmtjs/core';
|
|
2
|
+
export class BaseServerFormat {
|
|
3
|
+
}
|
|
4
|
+
export const parseContentTypes = (types)=>{
|
|
5
|
+
if (types === '*/*') return [
|
|
6
|
+
'*/*'
|
|
7
|
+
];
|
|
8
|
+
return types.split(',').map((t)=>{
|
|
9
|
+
const [type, ...rest] = t.split(';');
|
|
10
|
+
const params = new Map(rest.map((p)=>p.trim().split('=').slice(0, 2).map((p)=>p.trim())));
|
|
11
|
+
return {
|
|
12
|
+
type,
|
|
13
|
+
q: params.has('q') ? Number.parseFloat(params.get('q')) : 1
|
|
14
|
+
};
|
|
15
|
+
}).sort((a, b)=>{
|
|
16
|
+
if (a.type === '*/*') return 1;
|
|
17
|
+
if (b.type === '*/*') return -1;
|
|
18
|
+
return b.q - a.q ? -1 : 1;
|
|
19
|
+
}).map((t)=>t.type);
|
|
20
|
+
};
|
|
21
|
+
export class Format {
|
|
22
|
+
decoders = new Map();
|
|
23
|
+
encoders = new Map();
|
|
24
|
+
constructor(formats){
|
|
25
|
+
for (const format of formats){
|
|
26
|
+
this.encoders.set(format.contentType, format);
|
|
27
|
+
for (const acceptType of format.accept){
|
|
28
|
+
this.decoders.set(acceptType, format);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
supportsDecoder(contentType, throwIfUnsupported = false) {
|
|
33
|
+
return this.supports(this.decoders, contentType, throwIfUnsupported);
|
|
34
|
+
}
|
|
35
|
+
supportsEncoder(contentType, throwIfUnsupported = false) {
|
|
36
|
+
return this.supports(this.encoders, contentType, throwIfUnsupported);
|
|
37
|
+
}
|
|
38
|
+
supports(formats, contentType, throwIfUnsupported = false) {
|
|
39
|
+
const types = parseContentTypes(contentType);
|
|
40
|
+
for (const type of types){
|
|
41
|
+
for (const [pattern, format] of formats){
|
|
42
|
+
if (type === '*/*' || match(type, pattern)) return format;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (throwIfUnsupported) throw new Error(`No supported format found: ${contentType}`);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/format.ts"],"sourcesContent":["import { type Pattern, match } from '@nmtjs/core'\nimport type {\n DecodeRPCContext,\n EncodeRPCContext,\n ProtocolRPC,\n ProtocolRPCResponse,\n} from '../common/types.ts'\n\nexport interface BaseServerDecoder {\n accept: Pattern[]\n decode(buffer: ArrayBuffer): any\n decodeRPC(buffer: ArrayBuffer, context: DecodeRPCContext): ProtocolRPC\n}\n\nexport interface BaseServerEncoder {\n contentType: string\n encode(data: any): ArrayBuffer\n encodeRPC(rpc: ProtocolRPCResponse, context: EncodeRPCContext): ArrayBuffer\n}\n\nexport abstract class BaseServerFormat\n implements BaseServerDecoder, BaseServerEncoder\n{\n abstract accept: Pattern[]\n abstract contentType: string\n\n abstract encode(data: any): ArrayBuffer\n abstract encodeRPC(\n rpc: ProtocolRPCResponse,\n context: EncodeRPCContext,\n ): ArrayBuffer\n abstract decode(buffer: ArrayBuffer): any\n abstract decodeRPC(\n buffer: ArrayBuffer,\n context: DecodeRPCContext,\n ): ProtocolRPC\n}\n\nexport const parseContentTypes = (types: string) => {\n if (types === '*/*') return ['*/*']\n return types\n .split(',')\n .map((t) => {\n const [type, ...rest] = t.split(';')\n const params = new Map(\n rest.map((p) =>\n p\n .trim()\n .split('=')\n .slice(0, 2)\n .map((p) => p.trim()),\n ) as [string, string][],\n )\n return {\n type,\n q: params.has('q') ? Number.parseFloat(params.get('q')!) : 1,\n }\n })\n .sort((a, b) => {\n if (a.type === '*/*') return 1\n if (b.type === '*/*') return -1\n return b.q - a.q ? -1 : 1\n })\n .map((t) => t.type)\n}\n\nexport class Format {\n decoders = new Map<Pattern, BaseServerDecoder>()\n encoders = new Map<Pattern, BaseServerEncoder>()\n\n constructor(formats: BaseServerFormat[]) {\n for (const format of formats) {\n this.encoders.set(format.contentType, format)\n for (const acceptType of format.accept) {\n this.decoders.set(acceptType, format)\n }\n }\n }\n\n supportsDecoder(contentType: string, throwIfUnsupported = false) {\n return this.supports(this.decoders, contentType, throwIfUnsupported)\n }\n\n supportsEncoder(contentType: string, throwIfUnsupported = false) {\n return this.supports(this.encoders, contentType, throwIfUnsupported)\n }\n\n private supports<T extends BaseServerEncoder | BaseServerDecoder>(\n formats: Map<Pattern, T>,\n contentType: string,\n throwIfUnsupported = false,\n ): T | null {\n // TODO: Use node:utils.MIMEType (not implemented yet in Deno and Bun yet)\n const types = parseContentTypes(contentType)\n\n for (const type of types) {\n for (const [pattern, format] of formats) {\n if (type === '*/*' || match(type, pattern)) return format\n }\n }\n\n if (throwIfUnsupported)\n throw new Error(`No supported format found: ${contentType}`)\n\n return null\n }\n}\n"],"names":["match","BaseServerFormat","parseContentTypes","types","split","map","t","type","rest","params","Map","p","trim","slice","q","has","Number","parseFloat","get","sort","a","b","Format","decoders","encoders","constructor","formats","format","set","contentType","acceptType","accept","supportsDecoder","throwIfUnsupported","supports","supportsEncoder","pattern","Error"],"mappings":"AAAA,SAAuBA,KAAK,QAAQ,cAAa;AAoBjD,OAAO,MAAeC;AAgBtB;AAEA,OAAO,MAAMC,oBAAoB,CAACC;IAChC,IAAIA,UAAU,OAAO,OAAO;QAAC;KAAM;IACnC,OAAOA,MACJC,KAAK,CAAC,KACNC,GAAG,CAAC,CAACC;QACJ,MAAM,CAACC,MAAM,GAAGC,KAAK,GAAGF,EAAEF,KAAK,CAAC;QAChC,MAAMK,SAAS,IAAIC,IACjBF,KAAKH,GAAG,CAAC,CAACM,IACRA,EACGC,IAAI,GACJR,KAAK,CAAC,KACNS,KAAK,CAAC,GAAG,GACTR,GAAG,CAAC,CAACM,IAAMA,EAAEC,IAAI;QAGxB,OAAO;YACLL;YACAO,GAAGL,OAAOM,GAAG,CAAC,OAAOC,OAAOC,UAAU,CAACR,OAAOS,GAAG,CAAC,QAAS;QAC7D;IACF,GACCC,IAAI,CAAC,CAACC,GAAGC;QACR,IAAID,EAAEb,IAAI,KAAK,OAAO,OAAO;QAC7B,IAAIc,EAAEd,IAAI,KAAK,OAAO,OAAO,CAAC;QAC9B,OAAOc,EAAEP,CAAC,GAAGM,EAAEN,CAAC,GAAG,CAAC,IAAI;IAC1B,GACCT,GAAG,CAAC,CAACC,IAAMA,EAAEC,IAAI;AACtB,EAAC;AAED,OAAO,MAAMe;IACXC,WAAW,IAAIb,MAAiC;IAChDc,WAAW,IAAId,MAAiC;IAEhDe,YAAYC,OAA2B,CAAE;QACvC,KAAK,MAAMC,UAAUD,QAAS;YAC5B,IAAI,CAACF,QAAQ,CAACI,GAAG,CAACD,OAAOE,WAAW,EAAEF;YACtC,KAAK,MAAMG,cAAcH,OAAOI,MAAM,CAAE;gBACtC,IAAI,CAACR,QAAQ,CAACK,GAAG,CAACE,YAAYH;YAChC;QACF;IACF;IAEAK,gBAAgBH,WAAmB,EAAEI,qBAAqB,KAAK,EAAE;QAC/D,OAAO,IAAI,CAACC,QAAQ,CAAC,IAAI,CAACX,QAAQ,EAAEM,aAAaI;IACnD;IAEAE,gBAAgBN,WAAmB,EAAEI,qBAAqB,KAAK,EAAE;QAC/D,OAAO,IAAI,CAACC,QAAQ,CAAC,IAAI,CAACV,QAAQ,EAAEK,aAAaI;IACnD;IAEQC,SACNR,OAAwB,EACxBG,WAAmB,EACnBI,qBAAqB,KAAK,EAChB;QAEV,MAAM9B,QAAQD,kBAAkB2B;QAEhC,KAAK,MAAMtB,QAAQJ,MAAO;YACxB,KAAK,MAAM,CAACiC,SAAST,OAAO,IAAID,QAAS;gBACvC,IAAInB,SAAS,SAASP,MAAMO,MAAM6B,UAAU,OAAOT;YACrD;QACF;QAEA,IAAIM,oBACF,MAAM,IAAII,MAAM,CAAC,2BAA2B,EAAER,YAAY,CAAC;QAE7D,OAAO;IACT;AACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./api.js";
|
|
2
|
+
export * from "./connection.js";
|
|
3
|
+
export * from "./constants.js";
|
|
4
|
+
export * from "./injectables.js";
|
|
5
|
+
export * from "./format.js";
|
|
6
|
+
export * from "./protocol.js";
|
|
7
|
+
export * from "./registry.js";
|
|
8
|
+
export * from "./stream.js";
|
|
9
|
+
export * from "./transport.js";
|
|
10
|
+
export * from "./utils.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/index.ts"],"sourcesContent":["export * from './api.ts'\nexport * from './connection.ts'\nexport * from './constants.ts'\nexport * from './injectables.ts'\nexport * from './format.ts'\nexport * from './protocol.ts'\nexport * from './registry.ts'\nexport * from './stream.ts'\nexport * from './transport.ts'\nexport * from './utils.ts'\n"],"names":[],"mappings":"AAAA,cAAc,WAAU;AACxB,cAAc,kBAAiB;AAC/B,cAAc,iBAAgB;AAC9B,cAAc,mBAAkB;AAChC,cAAc,cAAa;AAC3B,cAAc,gBAAe;AAC7B,cAAc,gBAAe;AAC7B,cAAc,cAAa;AAC3B,cAAc,iBAAgB;AAC9B,cAAc,aAAY"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Scope, createFactoryInjectable, createLazyInjectable } from '@nmtjs/core';
|
|
2
|
+
const connection = createLazyInjectable(Scope.Connection, 'RPC connection');
|
|
3
|
+
const connectionData = createLazyInjectable(Scope.Connection, "RPC connection's data");
|
|
4
|
+
const transportStopSignal = createLazyInjectable(Scope.Global, 'Transport stop signal');
|
|
5
|
+
const rpcClientAbortSignal = createLazyInjectable(Scope.Call, 'RPC client abort signal');
|
|
6
|
+
const rpcTimeoutSignal = createLazyInjectable(Scope.Call, 'RPC timeout signal');
|
|
7
|
+
const rpcAbortSignal = createFactoryInjectable({
|
|
8
|
+
dependencies: {
|
|
9
|
+
rpcTimeoutSignal,
|
|
10
|
+
rpcClientAbortSignal,
|
|
11
|
+
transportStopSignal
|
|
12
|
+
},
|
|
13
|
+
factory: (ctx)=>AbortSignal.any(Object.values(ctx))
|
|
14
|
+
}, 'Any RPC abort signal');
|
|
15
|
+
export const ProtocolInjectables = {
|
|
16
|
+
connection,
|
|
17
|
+
connectionData,
|
|
18
|
+
transportStopSignal,
|
|
19
|
+
rpcClientAbortSignal,
|
|
20
|
+
rpcTimeoutSignal,
|
|
21
|
+
rpcAbortSignal
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/injectables.ts"],"sourcesContent":["import {\n Scope,\n createFactoryInjectable,\n createLazyInjectable,\n} from '@nmtjs/core'\n\nconst connection = createLazyInjectable<unknown, Scope.Connection>(\n Scope.Connection,\n 'RPC connection',\n)\n\nconst connectionData = createLazyInjectable<unknown, Scope.Connection>(\n Scope.Connection,\n \"RPC connection's data\",\n)\n\nconst transportStopSignal = createLazyInjectable<AbortSignal>(\n Scope.Global,\n 'Transport stop signal',\n)\n\nconst rpcClientAbortSignal = createLazyInjectable<AbortSignal, Scope.Call>(\n Scope.Call,\n 'RPC client abort signal',\n)\n\nconst rpcTimeoutSignal = createLazyInjectable<AbortSignal, Scope.Call>(\n Scope.Call,\n 'RPC timeout signal',\n)\n\nconst rpcAbortSignal = createFactoryInjectable(\n {\n dependencies: {\n rpcTimeoutSignal,\n rpcClientAbortSignal,\n transportStopSignal,\n },\n factory: (ctx) => AbortSignal.any(Object.values(ctx)),\n },\n 'Any RPC abort signal',\n)\n\nexport const ProtocolInjectables = {\n connection,\n connectionData,\n transportStopSignal,\n rpcClientAbortSignal,\n rpcTimeoutSignal,\n rpcAbortSignal,\n} as const\n"],"names":["Scope","createFactoryInjectable","createLazyInjectable","connection","Connection","connectionData","transportStopSignal","Global","rpcClientAbortSignal","Call","rpcTimeoutSignal","rpcAbortSignal","dependencies","factory","ctx","AbortSignal","any","Object","values","ProtocolInjectables"],"mappings":"AAAA,SACEA,KAAK,EACLC,uBAAuB,EACvBC,oBAAoB,QACf,cAAa;AAEpB,MAAMC,aAAaD,qBACjBF,MAAMI,UAAU,EAChB;AAGF,MAAMC,iBAAiBH,qBACrBF,MAAMI,UAAU,EAChB;AAGF,MAAME,sBAAsBJ,qBAC1BF,MAAMO,MAAM,EACZ;AAGF,MAAMC,uBAAuBN,qBAC3BF,MAAMS,IAAI,EACV;AAGF,MAAMC,mBAAmBR,qBACvBF,MAAMS,IAAI,EACV;AAGF,MAAME,iBAAiBV,wBACrB;IACEW,cAAc;QACZF;QACAF;QACAF;IACF;IACAO,SAAS,CAACC,MAAQC,YAAYC,GAAG,CAACC,OAAOC,MAAM,CAACJ;AAClD,GACA;AAGF,OAAO,MAAMK,sBAAsB;IACjChB;IACAE;IACAC;IACAE;IACAE;IACAC;AACF,EAAU"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { createPromise, throwError } from '@nmtjs/common';
|
|
2
|
+
import { Hook, Scope } from '@nmtjs/core';
|
|
3
|
+
import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
|
|
4
|
+
import { ErrorCode, ServerMessageType } from "../common/enums.js";
|
|
5
|
+
import { Connection, ConnectionContext } from "./connection.js";
|
|
6
|
+
import { ProtocolClientStream, ProtocolServerStream } from "./stream.js";
|
|
7
|
+
import { getFormat } from "./utils.js";
|
|
8
|
+
export class ProtocolError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
data;
|
|
11
|
+
constructor(code, message, data){
|
|
12
|
+
super(message);
|
|
13
|
+
this.code = code;
|
|
14
|
+
this.data = data;
|
|
15
|
+
}
|
|
16
|
+
get message() {
|
|
17
|
+
return `${this.code} ${super.message}`;
|
|
18
|
+
}
|
|
19
|
+
toString() {
|
|
20
|
+
return `${this.code} ${this.message}`;
|
|
21
|
+
}
|
|
22
|
+
toJSON() {
|
|
23
|
+
return {
|
|
24
|
+
code: this.code,
|
|
25
|
+
message: this.message,
|
|
26
|
+
data: this.data
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export class ProtocolConnections {
|
|
31
|
+
application;
|
|
32
|
+
#collection;
|
|
33
|
+
constructor(application){
|
|
34
|
+
this.application = application;
|
|
35
|
+
this.#collection = new Map();
|
|
36
|
+
}
|
|
37
|
+
get(connectionId) {
|
|
38
|
+
const connection = this.#collection.get(connectionId);
|
|
39
|
+
if (!connection) throwError('Connection not found');
|
|
40
|
+
return connection;
|
|
41
|
+
}
|
|
42
|
+
async add(transport, options, params) {
|
|
43
|
+
const connection = new Connection(options);
|
|
44
|
+
const format = getFormat(this.application.format, params);
|
|
45
|
+
const container = this.application.container.fork(Scope.Connection);
|
|
46
|
+
const context = new ConnectionContext(container, format);
|
|
47
|
+
this.#collection.set(connection.id, {
|
|
48
|
+
connection,
|
|
49
|
+
context,
|
|
50
|
+
transport
|
|
51
|
+
});
|
|
52
|
+
await this.application.registry.hooks.call(Hook.OnConnect, {
|
|
53
|
+
concurrent: false
|
|
54
|
+
}, connection);
|
|
55
|
+
return {
|
|
56
|
+
connection,
|
|
57
|
+
context
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
async remove(connectionId) {
|
|
61
|
+
const { connection, context } = this.get(connectionId);
|
|
62
|
+
this.application.registry.hooks.call(Hook.OnDisconnect, {
|
|
63
|
+
concurrent: true
|
|
64
|
+
}, connection);
|
|
65
|
+
this.#collection.delete(connectionId);
|
|
66
|
+
const { calls, serverStreams, clientStreams, container } = context;
|
|
67
|
+
for (const call of calls.values()){
|
|
68
|
+
call.reject(new Error('Connection closed'));
|
|
69
|
+
}
|
|
70
|
+
for (const stream of clientStreams.values()){
|
|
71
|
+
stream.destroy(new Error('Connection closed'));
|
|
72
|
+
}
|
|
73
|
+
for (const stream of serverStreams.values()){
|
|
74
|
+
stream.destroy(new Error('Connection closed'));
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await container.dispose();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
this.application.logger.error({
|
|
80
|
+
error,
|
|
81
|
+
connection
|
|
82
|
+
}, 'Error during closing connection');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export class ProtocolClientStreams {
|
|
87
|
+
connections;
|
|
88
|
+
constructor(connections){
|
|
89
|
+
this.connections = connections;
|
|
90
|
+
}
|
|
91
|
+
get(connectionId, streamId) {
|
|
92
|
+
const { context } = this.connections.get(connectionId);
|
|
93
|
+
const { clientStreams } = context;
|
|
94
|
+
const stream = clientStreams.get(streamId) ?? throwError('Stream not found');
|
|
95
|
+
return stream;
|
|
96
|
+
}
|
|
97
|
+
remove(connectionId, streamId) {
|
|
98
|
+
const { context } = this.connections.get(connectionId);
|
|
99
|
+
const { clientStreams } = context;
|
|
100
|
+
clientStreams.get(streamId) || throwError('Stream not found');
|
|
101
|
+
clientStreams.delete(streamId);
|
|
102
|
+
}
|
|
103
|
+
add(connectionId, streamId, metadata, read) {
|
|
104
|
+
const { context } = this.connections.get(connectionId);
|
|
105
|
+
const { clientStreams } = context;
|
|
106
|
+
const stream = new ProtocolClientStream(streamId, metadata, {
|
|
107
|
+
read
|
|
108
|
+
});
|
|
109
|
+
clientStreams.set(streamId, stream);
|
|
110
|
+
return stream;
|
|
111
|
+
}
|
|
112
|
+
push(connectionId, streamId, chunk) {
|
|
113
|
+
const stream = this.get(connectionId, streamId);
|
|
114
|
+
stream.push(Buffer.from(chunk));
|
|
115
|
+
}
|
|
116
|
+
end(connectionId, streamId) {
|
|
117
|
+
const stream = this.get(connectionId, streamId);
|
|
118
|
+
stream.push(null);
|
|
119
|
+
this.remove(connectionId, streamId);
|
|
120
|
+
}
|
|
121
|
+
abort(connectionId, streamId, error = new Error('Aborted')) {
|
|
122
|
+
const stream = this.get(connectionId, streamId);
|
|
123
|
+
stream.destroy(error);
|
|
124
|
+
this.remove(connectionId, streamId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
export class ProtocolServerStreams {
|
|
128
|
+
connections;
|
|
129
|
+
constructor(connections){
|
|
130
|
+
this.connections = connections;
|
|
131
|
+
}
|
|
132
|
+
get(connectionId, streamId) {
|
|
133
|
+
const { context } = this.connections.get(connectionId);
|
|
134
|
+
const { serverStreams } = context;
|
|
135
|
+
const stream = serverStreams.get(streamId) ?? throwError('Stream not found');
|
|
136
|
+
return stream;
|
|
137
|
+
}
|
|
138
|
+
add(connectionId, streamId, blob) {
|
|
139
|
+
const { context } = this.connections.get(connectionId);
|
|
140
|
+
const { serverStreams } = context;
|
|
141
|
+
const stream = new ProtocolServerStream(streamId, blob);
|
|
142
|
+
serverStreams.set(streamId, stream);
|
|
143
|
+
return stream;
|
|
144
|
+
}
|
|
145
|
+
remove(connectionId, streamId) {
|
|
146
|
+
const { context } = this.connections.get(connectionId);
|
|
147
|
+
const { serverStreams } = context;
|
|
148
|
+
serverStreams.has(streamId) || throwError('Stream not found');
|
|
149
|
+
serverStreams.delete(streamId);
|
|
150
|
+
}
|
|
151
|
+
pull(connectionId, streamId) {
|
|
152
|
+
const stream = this.get(connectionId, streamId);
|
|
153
|
+
stream.resume();
|
|
154
|
+
}
|
|
155
|
+
abort(connectionId, streamId, error = new Error('Aborted')) {
|
|
156
|
+
const stream = this.get(connectionId, streamId);
|
|
157
|
+
stream.destroy(error);
|
|
158
|
+
this.remove(connectionId, streamId);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export class Protocol {
|
|
162
|
+
application;
|
|
163
|
+
connections;
|
|
164
|
+
clientStreams;
|
|
165
|
+
serverStreams;
|
|
166
|
+
constructor(application){
|
|
167
|
+
this.application = application;
|
|
168
|
+
this.connections = new ProtocolConnections(this.application);
|
|
169
|
+
this.clientStreams = new ProtocolClientStreams(this.connections);
|
|
170
|
+
this.serverStreams = new ProtocolServerStreams(this.connections);
|
|
171
|
+
}
|
|
172
|
+
async call(connectionId, rpc, params = {}) {
|
|
173
|
+
const { connection, context, transport } = this.connections.get(connectionId);
|
|
174
|
+
const { calls, format } = context;
|
|
175
|
+
const { callId, namespace, procedure, payload } = rpc;
|
|
176
|
+
const abortController = new AbortController();
|
|
177
|
+
const signal = params.signal ? AbortSignal.any([
|
|
178
|
+
params.signal,
|
|
179
|
+
abortController.signal
|
|
180
|
+
]) : abortController.signal;
|
|
181
|
+
const call = Object.assign(createPromise(), {
|
|
182
|
+
abort: ()=>abortController.abort()
|
|
183
|
+
});
|
|
184
|
+
calls.set(callId, call);
|
|
185
|
+
call.promise.finally(()=>calls.delete(callId));
|
|
186
|
+
const callIdEncoded = encodeNumber(callId, 'Uint32');
|
|
187
|
+
const container = context.container.fork(Scope.Call);
|
|
188
|
+
try {
|
|
189
|
+
const response = await this.application.api.call({
|
|
190
|
+
connection,
|
|
191
|
+
container,
|
|
192
|
+
namespace,
|
|
193
|
+
payload,
|
|
194
|
+
procedure,
|
|
195
|
+
signal
|
|
196
|
+
});
|
|
197
|
+
const responseEncoded = format.encoder.encodeRPC({
|
|
198
|
+
callId,
|
|
199
|
+
payload: response.output
|
|
200
|
+
}, {
|
|
201
|
+
addStream: (blob)=>{
|
|
202
|
+
const id = context.streamId++;
|
|
203
|
+
const stream = this.serverStreams.add(connectionId, id, blob);
|
|
204
|
+
stream.on('data', (chunk)=>{
|
|
205
|
+
stream.pause();
|
|
206
|
+
transport.send(connection, ServerMessageType.ServerStreamPush, concat(encodeNumber(id, 'Uint32'), Buffer.from(chunk).buffer));
|
|
207
|
+
});
|
|
208
|
+
stream.on('error', (err)=>{
|
|
209
|
+
transport.send(connection, ServerMessageType.ServerStreamAbort, encodeNumber(id, 'Uint32'));
|
|
210
|
+
});
|
|
211
|
+
stream.on('end', ()=>{
|
|
212
|
+
transport.send(connection, ServerMessageType.ServerStreamEnd, encodeNumber(id, 'Uint32'));
|
|
213
|
+
});
|
|
214
|
+
return stream;
|
|
215
|
+
},
|
|
216
|
+
getStream: (id)=>{
|
|
217
|
+
return this.clientStreams.get(connectionId, id);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
if ('subscription' in response) {
|
|
221
|
+
throwError('Unimplemented');
|
|
222
|
+
} else if ('iterable' in response) {
|
|
223
|
+
transport.send(connection, ServerMessageType.RpcStreamResponse, responseEncoded);
|
|
224
|
+
try {
|
|
225
|
+
const iterable = typeof response.iterable === 'function' ? response.iterable() : response.iterable;
|
|
226
|
+
for await (const chunk of iterable){
|
|
227
|
+
const chunkEncoded = format.encoder.encode(chunk);
|
|
228
|
+
transport.send(connection, ServerMessageType.RpcStreamChunk, concat(callIdEncoded, chunkEncoded));
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
this.application.logger.error(error);
|
|
232
|
+
transport.send(connection, ServerMessageType.RpcStreamAbort, callIdEncoded);
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
transport.send(connection, ServerMessageType.RpcResponse, responseEncoded);
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof ProtocolError === false) {
|
|
239
|
+
this.application.logger.error({
|
|
240
|
+
error,
|
|
241
|
+
connection
|
|
242
|
+
}, 'Error during RPC call');
|
|
243
|
+
error = new ProtocolError(ErrorCode.InternalServerError, 'Internal server error');
|
|
244
|
+
}
|
|
245
|
+
const payload = format.encoder.encodeRPC({
|
|
246
|
+
callId,
|
|
247
|
+
error
|
|
248
|
+
}, {
|
|
249
|
+
addStream (blob) {
|
|
250
|
+
throwError('Cannot handle stream for error response');
|
|
251
|
+
},
|
|
252
|
+
getStream (id) {
|
|
253
|
+
throwError('Cannot handle stream for error response');
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
transport.send(connection, ServerMessageType.RpcResponse, payload);
|
|
257
|
+
} finally{
|
|
258
|
+
container.dispose().catch((error)=>{
|
|
259
|
+
this.application.logger.error({
|
|
260
|
+
error,
|
|
261
|
+
connection
|
|
262
|
+
}, "Error during disposing connection's container");
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async callRaw(connectionId, buffer, params = {}) {
|
|
267
|
+
const { connection, context, transport } = this.connections.get(connectionId);
|
|
268
|
+
const { format } = context;
|
|
269
|
+
const rpc = format.decoder.decodeRPC(buffer, {
|
|
270
|
+
addStream: (id, metadata)=>{
|
|
271
|
+
return this.clientStreams.add(connectionId, id, metadata, (size)=>{
|
|
272
|
+
transport.send(connection, ServerMessageType.ClientStreamPull, concat(encodeNumber(id, 'Uint32'), encodeNumber(size, 'Uint32')));
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
getStream: (id)=>{
|
|
276
|
+
return this.serverStreams.get(connectionId, id);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return await this.call(connectionId, rpc, params);
|
|
280
|
+
}
|
|
281
|
+
callAbort(connectionId, callId) {
|
|
282
|
+
const { context } = this.connections.get(connectionId);
|
|
283
|
+
const call = context.calls.get(callId) ?? throwError('Call not found');
|
|
284
|
+
call.abort();
|
|
285
|
+
}
|
|
286
|
+
callAbortRaw(connectionId, buffer) {
|
|
287
|
+
const callId = decodeNumber(buffer, 'Uint32');
|
|
288
|
+
return this.callAbort(connectionId, callId);
|
|
289
|
+
}
|
|
290
|
+
notify(connectionId, event, payload) {
|
|
291
|
+
throw Error('Unimplemented');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/protocol.ts"],"sourcesContent":["import { type Callback, createPromise, defer, throwError } from '@nmtjs/common'\nimport { type Container, Hook, type Logger, Scope } from '@nmtjs/core'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ErrorCode, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport type { ProtocolApi, ProtocolApiCallResult } from './api.ts'\nimport {\n Connection,\n ConnectionContext,\n type ConnectionOptions,\n} from './connection.ts'\nimport type { Format } from './format.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\nimport type { Transport } from './transport.ts'\nimport { type ResolveFormatParams, getFormat } from './utils.ts'\n\nexport class ProtocolError extends Error {\n code: string\n data?: any\n\n constructor(code: string, message?: string, data?: any) {\n super(message)\n this.code = code\n this.data = data\n }\n\n get message() {\n return `${this.code} ${super.message}`\n }\n\n toString() {\n return `${this.code} ${this.message}`\n }\n\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n data: this.data,\n }\n }\n}\n\nexport class ProtocolConnections {\n readonly #collection = new Map<\n string,\n {\n connection: Connection\n context: ConnectionContext\n transport: Transport\n }\n >()\n\n constructor(\n private readonly application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n },\n ) {}\n\n get(connectionId: string) {\n const connection = this.#collection.get(connectionId)\n if (!connection) throwError('Connection not found')\n return connection\n }\n\n async add<T>(\n transport: Transport<any>,\n options: ConnectionOptions<T>,\n params: ResolveFormatParams,\n ) {\n const connection = new Connection(options)\n const format = getFormat(this.application.format, params)\n const container = this.application.container.fork(Scope.Connection)\n const context = new ConnectionContext(container, format)\n\n this.#collection.set(connection.id, { connection, context, transport })\n\n await this.application.registry.hooks.call(\n Hook.OnConnect,\n { concurrent: false },\n connection,\n )\n\n return { connection, context }\n }\n\n async remove(connectionId: string) {\n const { connection, context } = this.get(connectionId)\n\n this.application.registry.hooks.call(\n Hook.OnDisconnect,\n { concurrent: true },\n connection,\n )\n\n this.#collection.delete(connectionId)\n\n const { calls, serverStreams, clientStreams, container } = context\n\n for (const call of calls.values()) {\n call.reject(new Error('Connection closed'))\n }\n\n for (const stream of clientStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of serverStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n try {\n await container.dispose()\n } catch (error) {\n this.application.logger.error(\n { error, connection },\n 'Error during closing connection',\n )\n }\n }\n}\n\nexport class ProtocolClientStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = clientStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n clientStreams.get(streamId) || throwError('Stream not found')\n clientStreams.delete(streamId)\n }\n\n add(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = new ProtocolClientStream(streamId, metadata, { read })\n clientStreams.set(streamId, stream)\n return stream\n }\n\n push(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(connectionId, streamId)\n stream.push(Buffer.from(chunk))\n }\n\n end(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.push(null)\n this.remove(connectionId, streamId)\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = serverStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n add(connectionId: string, streamId: number, blob: ProtocolBlob) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = new ProtocolServerStream(streamId, blob)\n serverStreams.set(streamId, stream)\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n serverStreams.has(streamId) || throwError('Stream not found')\n serverStreams.delete(streamId)\n }\n\n pull(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.resume()\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class Protocol {\n readonly connections: ProtocolConnections\n readonly clientStreams: ProtocolClientStreams\n readonly serverStreams: ProtocolServerStreams\n\n constructor(\n protected readonly application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n },\n ) {\n this.connections = new ProtocolConnections(this.application)\n this.clientStreams = new ProtocolClientStreams(this.connections)\n this.serverStreams = new ProtocolServerStreams(this.connections)\n }\n\n async call(\n connectionId: string,\n rpc: ProtocolRPC,\n params: { signal?: AbortSignal } = {},\n ) {\n const { connection, context, transport } =\n this.connections.get(connectionId)\n const { calls, format } = context\n const { callId, namespace, procedure, payload } = rpc\n const abortController = new AbortController()\n const signal = params.signal\n ? AbortSignal.any([params.signal, abortController.signal])\n : abortController.signal\n\n const call = Object.assign(createPromise<ProtocolApiCallResult>(), {\n abort: () => abortController.abort(),\n })\n\n calls.set(callId, call)\n call.promise.finally(() => calls.delete(callId))\n\n const callIdEncoded = encodeNumber(callId, 'Uint32')\n const container = context.container.fork(Scope.Call)\n\n try {\n const response = await this.application.api.call({\n connection,\n container,\n namespace,\n payload,\n procedure,\n signal,\n })\n\n const responseEncoded = format.encoder.encodeRPC(\n {\n callId,\n payload: response.output,\n },\n {\n addStream: (blob) => {\n const id = context.streamId++\n const stream = this.serverStreams.add(connectionId, id, blob)\n stream.on('data', (chunk) => {\n stream.pause()\n transport.send(\n connection,\n ServerMessageType.ServerStreamPush,\n concat(\n encodeNumber(id, 'Uint32'),\n Buffer.from(chunk).buffer as ArrayBuffer,\n ),\n )\n })\n stream.on('error', (err) => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamAbort,\n encodeNumber(id, 'Uint32'),\n )\n })\n stream.on('end', () => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamEnd,\n encodeNumber(id, 'Uint32'),\n )\n })\n return stream\n },\n getStream: (id) => {\n return this.clientStreams.get(connectionId, id)\n },\n },\n )\n\n if ('subscription' in response) {\n throwError('Unimplemented')\n } else if ('iterable' in response) {\n transport.send(\n connection,\n ServerMessageType.RpcStreamResponse,\n responseEncoded,\n )\n try {\n const iterable =\n typeof response.iterable === 'function'\n ? response.iterable()\n : response.iterable\n for await (const chunk of iterable) {\n const chunkEncoded = format.encoder.encode(chunk)\n transport.send(\n connection,\n ServerMessageType.RpcStreamChunk,\n concat(callIdEncoded, chunkEncoded),\n )\n }\n } catch (error) {\n this.application.logger.error(error)\n transport.send(\n connection,\n ServerMessageType.RpcStreamAbort,\n callIdEncoded,\n )\n }\n } else {\n transport.send(\n connection,\n ServerMessageType.RpcResponse,\n responseEncoded,\n )\n }\n } catch (error) {\n if (error instanceof ProtocolError === false) {\n this.application.logger.error(\n { error, connection },\n 'Error during RPC call',\n )\n\n // biome-ignore lint/suspicious/noCatchAssign:\n error = new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal server error',\n )\n }\n\n const payload = format.encoder.encodeRPC(\n { callId, error },\n {\n addStream(blob) {\n throwError('Cannot handle stream for error response')\n },\n getStream(id) {\n throwError('Cannot handle stream for error response')\n },\n },\n )\n transport.send(connection, ServerMessageType.RpcResponse, payload)\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n \"Error during disposing connection's container\",\n )\n })\n }\n }\n\n async callRaw(\n connectionId: string,\n buffer: ArrayBuffer,\n params: { signal?: AbortSignal } = {},\n ) {\n const { connection, context, transport } =\n this.connections.get(connectionId)\n\n const { format } = context\n\n const rpc = format.decoder.decodeRPC(buffer, {\n addStream: (id, metadata) => {\n return this.clientStreams.add(connectionId, id, metadata, (size) => {\n transport.send(\n connection,\n ServerMessageType.ClientStreamPull,\n concat(encodeNumber(id, 'Uint32'), encodeNumber(size, 'Uint32')),\n )\n })\n },\n getStream: (id) => {\n return this.serverStreams.get(connectionId, id)\n },\n })\n\n return await this.call(connectionId, rpc, params)\n }\n\n callAbort(connectionId: string, callId: number) {\n const { context } = this.connections.get(connectionId)\n const call = context.calls.get(callId) ?? throwError('Call not found')\n call.abort()\n }\n\n callAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.callAbort(connectionId, callId)\n }\n\n notify(connectionId: string, event, payload) {\n throw Error('Unimplemented')\n }\n}\n"],"names":["createPromise","throwError","Hook","Scope","concat","decodeNumber","encodeNumber","ErrorCode","ServerMessageType","Connection","ConnectionContext","ProtocolClientStream","ProtocolServerStream","getFormat","ProtocolError","Error","code","data","constructor","message","toString","toJSON","ProtocolConnections","application","Map","get","connectionId","connection","add","transport","options","params","format","container","fork","context","set","id","registry","hooks","call","OnConnect","concurrent","remove","OnDisconnect","delete","calls","serverStreams","clientStreams","values","reject","stream","destroy","dispose","error","logger","ProtocolClientStreams","connections","streamId","metadata","read","push","chunk","Buffer","from","end","abort","ProtocolServerStreams","blob","has","pull","resume","Protocol","rpc","callId","namespace","procedure","payload","abortController","AbortController","signal","AbortSignal","any","Object","assign","promise","finally","callIdEncoded","Call","response","api","responseEncoded","encoder","encodeRPC","output","addStream","on","pause","send","ServerStreamPush","buffer","err","ServerStreamAbort","ServerStreamEnd","getStream","RpcStreamResponse","iterable","chunkEncoded","encode","RpcStreamChunk","RpcStreamAbort","RpcResponse","InternalServerError","catch","callRaw","decoder","decodeRPC","size","ClientStreamPull","callAbort","callAbortRaw","notify","event"],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Registry } from '@nmtjs/core';
|
|
2
|
+
import { compile } from '@nmtjs/type/compiler';
|
|
3
|
+
export class ProtocolRegistry extends Registry {
|
|
4
|
+
types = new Set();
|
|
5
|
+
compiled = new Map();
|
|
6
|
+
registerType(type) {
|
|
7
|
+
this.types.add(type);
|
|
8
|
+
}
|
|
9
|
+
compile() {
|
|
10
|
+
for (const type of this.types){
|
|
11
|
+
this.compiled.set(type, compile(type));
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
clear() {
|
|
15
|
+
super.clear();
|
|
16
|
+
this.types.clear();
|
|
17
|
+
this.compiled.clear();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/registry.ts"],"sourcesContent":["import { Registry } from '@nmtjs/core'\nimport type { BaseType, BaseTypeAny } from '@nmtjs/type'\nimport { type Compiled, compile } from '@nmtjs/type/compiler'\n\nexport class ProtocolRegistry extends Registry {\n readonly types = new Set<BaseType>()\n readonly compiled = new Map<any, Compiled>()\n\n registerType(type: BaseTypeAny) {\n this.types.add(type)\n }\n\n compile() {\n for (const type of this.types) {\n this.compiled.set(type, compile(type))\n }\n }\n\n clear() {\n super.clear()\n this.types.clear()\n this.compiled.clear()\n }\n}\n"],"names":["Registry","compile","ProtocolRegistry","types","Set","compiled","Map","registerType","type","add","set","clear"],"mappings":"AAAA,SAASA,QAAQ,QAAQ,cAAa;AAEtC,SAAwBC,OAAO,QAAQ,uBAAsB;AAE7D,OAAO,MAAMC,yBAAyBF;IAC3BG,QAAQ,IAAIC,MAAe;IAC3BC,WAAW,IAAIC,MAAoB;IAE5CC,aAAaC,IAAiB,EAAE;QAC9B,IAAI,CAACL,KAAK,CAACM,GAAG,CAACD;IACjB;IAEAP,UAAU;QACR,KAAK,MAAMO,QAAQ,IAAI,CAACL,KAAK,CAAE;YAC7B,IAAI,CAACE,QAAQ,CAACK,GAAG,CAACF,MAAMP,QAAQO;QAClC;IACF;IAEAG,QAAQ;QACN,KAAK,CAACA;QACN,IAAI,CAACR,KAAK,CAACQ,KAAK;QAChB,IAAI,CAACN,QAAQ,CAACM,KAAK;IACrB;AACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PassThrough, Readable } from 'node:stream';
|
|
2
|
+
import { ReadableStream } from 'node:stream/web';
|
|
3
|
+
export class ProtocolClientStream extends Readable {
|
|
4
|
+
id;
|
|
5
|
+
metadata;
|
|
6
|
+
constructor(id, metadata, options){
|
|
7
|
+
super(options);
|
|
8
|
+
this.id = id;
|
|
9
|
+
this.metadata = metadata;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class ProtocolServerStream extends PassThrough {
|
|
13
|
+
id;
|
|
14
|
+
metadata;
|
|
15
|
+
constructor(id, blob){
|
|
16
|
+
let readable;
|
|
17
|
+
if (blob.source instanceof Readable) {
|
|
18
|
+
readable = blob.source;
|
|
19
|
+
} else if (blob.source instanceof ReadableStream) {
|
|
20
|
+
readable = Readable.fromWeb(blob.source);
|
|
21
|
+
} else {
|
|
22
|
+
throw new Error('Invalid source type');
|
|
23
|
+
}
|
|
24
|
+
super();
|
|
25
|
+
this.pause();
|
|
26
|
+
readable.pipe(this);
|
|
27
|
+
this.id = id;
|
|
28
|
+
this.metadata = blob.metadata;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/server/stream.ts"],"sourcesContent":["import {\n PassThrough,\n Readable,\n type ReadableOptions,\n type TransformOptions,\n} from 'node:stream'\nimport { ReadableStream } from 'node:stream/web'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\n\nexport class ProtocolClientStream extends Readable {\n constructor(\n public readonly id: number,\n public readonly metadata: ProtocolBlobMetadata,\n options?: ReadableOptions,\n ) {\n super(options)\n }\n}\n\nexport class ProtocolServerStream extends PassThrough {\n public readonly id: number\n public readonly metadata: ProtocolBlobMetadata\n\n constructor(id: number, blob: ProtocolBlob) {\n let readable: Readable\n\n if (blob.source instanceof Readable) {\n readable = blob.source\n } else if (blob.source instanceof ReadableStream) {\n readable = Readable.fromWeb(blob.source as ReadableStream)\n } else {\n throw new Error('Invalid source type')\n }\n\n super()\n\n this.pause()\n readable.pipe(this)\n\n this.id = id\n this.metadata = blob.metadata\n }\n}\n"],"names":["PassThrough","Readable","ReadableStream","ProtocolClientStream","constructor","id","metadata","options","ProtocolServerStream","blob","readable","source","fromWeb","Error","pause","pipe"],"mappings":"AAAA,SACEA,WAAW,EACXC,QAAQ,QAGH,cAAa;AACpB,SAASC,cAAc,QAAQ,kBAAiB;AAGhD,OAAO,MAAMC,6BAA6BF;;;IACxCG,YACE,AAAgBC,EAAU,EAC1B,AAAgBC,QAA8B,EAC9CC,OAAyB,CACzB;QACA,KAAK,CAACA;aAJUF,KAAAA;aACAC,WAAAA;IAIlB;AACF;AAEA,OAAO,MAAME,6BAA6BR;IACxBK,GAAU;IACVC,SAA8B;IAE9CF,YAAYC,EAAU,EAAEI,IAAkB,CAAE;QAC1C,IAAIC;QAEJ,IAAID,KAAKE,MAAM,YAAYV,UAAU;YACnCS,WAAWD,KAAKE,MAAM;QACxB,OAAO,IAAIF,KAAKE,MAAM,YAAYT,gBAAgB;YAChDQ,WAAWT,SAASW,OAAO,CAACH,KAAKE,MAAM;QACzC,OAAO;YACL,MAAM,IAAIE,MAAM;QAClB;QAEA,KAAK;QAEL,IAAI,CAACC,KAAK;QACVJ,SAASK,IAAI,CAAC,IAAI;QAElB,IAAI,CAACV,EAAE,GAAGA;QACV,IAAI,CAACC,QAAQ,GAAGG,KAAKH,QAAQ;IAC/B;AACF"}
|