@nmtjs/protocol 0.11.6 → 0.11.8
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/api.js +12 -2
- package/dist/server/api.js.map +1 -1
- package/dist/server/constants.js +1 -0
- package/dist/server/constants.js.map +1 -1
- package/dist/server/protocol.js +3 -5
- package/dist/server/protocol.js.map +1 -1
- package/package.json +7 -7
- package/src/server/api.ts +31 -18
- package/src/server/constants.ts +5 -0
- package/src/server/protocol.ts +3 -8
package/dist/server/api.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
1
|
+
import { kIterableResponse } from "./constants.js";
|
|
2
|
+
export function isIterableResult(value) {
|
|
3
|
+
return value && value[kIterableResponse] === true;
|
|
4
|
+
}
|
|
5
|
+
export function createStreamResponse(iterable, { onFinish, output = undefined }) {
|
|
6
|
+
return {
|
|
7
|
+
[kIterableResponse]: true,
|
|
8
|
+
iterable,
|
|
9
|
+
output,
|
|
10
|
+
onFinish
|
|
11
|
+
};
|
|
12
|
+
}
|
|
3
13
|
|
|
4
14
|
//# sourceMappingURL=api.js.map
|
package/dist/server/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"
|
|
1
|
+
{"mappings":"AAEA,SAAS,yBAAyB,gBAAgB;AAmClD,OAAO,SAAS,iBACdA,OACwC;AACxC,QAAO,SAAS,MAAM,uBAAuB;AAC9C;AAED,OAAO,SAAS,qBACdC,UACA,EACE,UACA,SAAS,WAIV,EACoC;AACrC,QAAO;GACJ,oBAAoB;EACrB;EACA;EACA;CACD;AACF","names":["value: any","iterable: ProtocolAnyIterable<Y>"],"sources":["../../src/server/api.ts"],"sourcesContent":["import type { Container, Hook, MetadataStore } from '@nmtjs/core'\nimport type { Connection } from './connection.ts'\nimport { kIterableResponse } from './constants.ts'\n\nexport type ProtocolApiCallOptions = {\n connection: Connection\n namespace: string\n procedure: string\n container: Container\n payload: any\n signal: AbortSignal\n metadata?: (metadata: MetadataStore) => void\n}\n\nexport type ProtocolAnyIterable<T> =\n | ((signal: AbortSignal) => AsyncGenerator<T>)\n | AsyncIterable<T>\n\nexport interface ProtocolApiCallBaseResult<T = unknown> {\n output: T\n}\n\nexport interface ProtocolApiCallIterableResult<Y = unknown, O = unknown>\n extends ProtocolApiCallBaseResult<O> {\n [kIterableResponse]: true\n iterable: ProtocolAnyIterable<Y>\n onFinish?: () => void\n}\n\nexport type ProtocolApiCallResult =\n | ProtocolApiCallBaseResult\n | ProtocolApiCallIterableResult\n\nexport interface ProtocolApi {\n call(options: ProtocolApiCallOptions): Promise<ProtocolApiCallResult>\n}\n\nexport function isIterableResult(\n value: any,\n): value is ProtocolApiCallIterableResult {\n return value && value[kIterableResponse] === true\n}\n\nexport function createStreamResponse<Y, O>(\n iterable: ProtocolAnyIterable<Y>,\n {\n onFinish,\n output = undefined as O,\n }: {\n output?: O\n onFinish?: () => void\n },\n): ProtocolApiCallIterableResult<Y, O> {\n return {\n [kIterableResponse]: true as const,\n iterable,\n output,\n onFinish,\n }\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"],"version":3,"file":"api.js"}
|
package/dist/server/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,OAAO,MAAMA,mBAAkC,OAAO,IACpD,6BACD","names":["kTransportPlugin: unique symbol"],"sources":["../../src/server/constants.ts"],"sourcesContent":["export const kTransportPlugin: unique symbol = Symbol.for(\n 'neemata:TransportPluginKey',\n)\nexport type kTransportPlugin = typeof kTransportPlugin\n"],"version":3,"file":"constants.js"}
|
|
1
|
+
{"mappings":"AAAA,OAAO,MAAMA,mBAAkC,OAAO,IACpD,6BACD;AAGD,OAAO,MAAMC,oBAAmC,OAAO,IACrD,8BACD","names":["kTransportPlugin: unique symbol","kIterableResponse: unique symbol"],"sources":["../../src/server/constants.ts"],"sourcesContent":["export const kTransportPlugin: unique symbol = Symbol.for(\n 'neemata:TransportPluginKey',\n)\nexport type kTransportPlugin = typeof kTransportPlugin\n\nexport const kIterableResponse: unique symbol = Symbol.for(\n 'neemata:IterableResponseKey',\n)\nexport type kIterableResponse = typeof kIterableResponse\n"],"version":3,"file":"constants.js"}
|
package/dist/server/protocol.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defer, throwError } from "@nmtjs/common";
|
|
1
|
+
import { defer, isAbortError, throwError } from "@nmtjs/common";
|
|
2
2
|
import { Hook, Scope } from "@nmtjs/core";
|
|
3
3
|
import { concat, decodeNumber, encodeNumber } from "../common/binary.js";
|
|
4
4
|
import { ErrorCode, ServerMessageType } from "../common/enums.js";
|
|
@@ -256,9 +256,7 @@ export class Protocol {
|
|
|
256
256
|
return this.#serverStreams.get(connectionId, id);
|
|
257
257
|
}
|
|
258
258
|
});
|
|
259
|
-
if (
|
|
260
|
-
throwError("Unimplemented");
|
|
261
|
-
} else if (isIterableResult(response)) {
|
|
259
|
+
if (isIterableResult(response)) {
|
|
262
260
|
transport.send(connection, ServerMessageType.RpcStreamResponse, responseEncoded, { callId });
|
|
263
261
|
try {
|
|
264
262
|
const controller = new AbortController();
|
|
@@ -272,7 +270,7 @@ export class Protocol {
|
|
|
272
270
|
}
|
|
273
271
|
transport.send(connection, ServerMessageType.RpcStreamEnd, callIdEncoded, { callId });
|
|
274
272
|
} catch (error) {
|
|
275
|
-
if (error
|
|
273
|
+
if (!isAbortError(error)) {
|
|
276
274
|
throw error;
|
|
277
275
|
}
|
|
278
276
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","names":["code: string","message?: string","data?: any","#collection","application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n }","connectionId: string","transport: ProtocolConnectionTransport","options: ConnectionOptions<T>","params: ResolveFormatParams","connection: Connection","connections: ProtocolConnections","streamId: number","metadata: ProtocolBlobMetadata","read: Callback","chunk: ArrayBuffer","blob: ProtocolBlob","application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n }","#connections","#clientStreams","#serverStreams","options: ProtocolApiCallOptions","rpc: ProtocolRPC","params: ProtocolRPCOptions","buffer: ArrayBuffer","callId: number","options: ConnectionOptions","error?: Error"],"sources":["../../src/server/protocol.ts"],"sourcesContent":["import { type Callback, defer, throwError } from '@nmtjs/common'\nimport {\n type AnyInjectable,\n type Container,\n Hook,\n type Logger,\n Scope,\n} from '@nmtjs/core'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ErrorCode, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport {\n isIterableResult,\n type ProtocolApi,\n type ProtocolApiCallOptions,\n} from './api.ts'\nimport {\n Connection,\n ConnectionContext,\n type ConnectionOptions,\n} from './connection.ts'\nimport type { Format } from './format.ts'\nimport { ProtocolInjectables } from './injectables.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\nimport type { Transport } from './transport.ts'\nimport { getFormat, type ResolveFormatParams } from './utils.ts'\n\nexport class ProtocolError extends Error {\n code: string\n data?: any\n\n constructor(code: string, message?: string, data?: any) {\n super(message)\n this.code = code\n this.data = data\n }\n\n get message() {\n return `${this.code} ${super.message}`\n }\n\n toString() {\n return `${this.code} ${this.message}`\n }\n\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n data: this.data,\n }\n }\n}\n\nexport type ProtocolConnectionTransport = {\n send: Transport<any>['send']\n}\n\nexport class ProtocolConnections {\n readonly #collection = new Map<\n string,\n {\n connection: Connection\n context: ConnectionContext\n transport: ProtocolConnectionTransport\n }\n >()\n\n constructor(\n private readonly application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n },\n ) {}\n\n get(connectionId: string) {\n const connection = this.#collection.get(connectionId)\n if (!connection) throwError('Connection not found')\n return connection\n }\n\n async add<T>(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions<T>,\n params: ResolveFormatParams,\n ) {\n const connection = new Connection(options)\n const format = getFormat(this.application.format, params)\n const container = this.application.container.fork(Scope.Connection)\n const context = new ConnectionContext(container, format)\n container.provide(ProtocolInjectables.connection, connection)\n try {\n await this.initialize(connection)\n this.#collection.set(connection.id, { connection, context, transport })\n return { connection, context }\n } catch (error) {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n throw error\n }\n }\n\n async remove(connectionId: string) {\n const { connection, context } = this.get(connectionId)\n\n this.application.registry.hooks.call(\n Hook.OnDisconnect,\n { concurrent: true },\n connection,\n )\n\n this.#collection.delete(connectionId)\n\n const { calls, serverStreams, clientStreams, rpcStreams, container } =\n context\n\n for (const call of calls.values()) {\n call.abort(new Error('Connection closed'))\n }\n\n for (const stream of clientStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of serverStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of rpcStreams.values()) {\n stream.abort(new Error('Connection closed'))\n }\n\n try {\n await container.dispose()\n } catch (error) {\n this.application.logger.error(\n { error, connection },\n 'Error during closing connection',\n )\n }\n }\n\n async initialize(connection: Connection) {\n await this.application.registry.hooks.call(\n Hook.OnConnect,\n { concurrent: false },\n connection,\n )\n }\n}\n\nexport class ProtocolClientStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = clientStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n clientStreams.get(streamId) || throwError('Stream not found')\n clientStreams.delete(streamId)\n }\n\n add(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = new ProtocolClientStream(streamId, metadata, { read })\n clientStreams.set(streamId, stream)\n return stream\n }\n\n push(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(connectionId, streamId)\n stream.write(Buffer.from(chunk))\n }\n\n end(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.end(null)\n this.remove(connectionId, streamId)\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = serverStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n add(connectionId: string, streamId: number, blob: ProtocolBlob) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = new ProtocolServerStream(streamId, blob)\n serverStreams.set(streamId, stream)\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n serverStreams.has(streamId) || throwError('Stream not found')\n serverStreams.delete(streamId)\n }\n\n pull(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.resume()\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport type ProtocolRPCOptions = {\n signal?: AbortSignal\n provides?: [AnyInjectable, any][]\n metadata?: ProtocolApiCallOptions['metadata']\n}\n\nexport class Protocol {\n #connections: ProtocolConnections\n #clientStreams: ProtocolClientStreams\n #serverStreams: ProtocolServerStreams\n\n constructor(\n protected readonly application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n },\n ) {\n this.#connections = new ProtocolConnections(this.application)\n this.#clientStreams = new ProtocolClientStreams(this.#connections)\n this.#serverStreams = new ProtocolServerStreams(this.#connections)\n }\n\n async call(options: ProtocolApiCallOptions) {\n const { container, connection } = options\n try {\n return await this.application.api.call(options)\n } catch (error) {\n if (error instanceof ProtocolError === false) {\n this.application.logger.error(\n { error, connection },\n 'Error during RPC call',\n )\n throw new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal server error',\n )\n }\n throw error\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n \"Error during disposing connection's container\",\n )\n })\n }\n }\n\n async rpc(\n connectionId: string,\n rpc: ProtocolRPC,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n const { calls, format } = context\n const { callId, namespace, procedure, payload } = rpc\n const abortController = new AbortController()\n const signal = params.signal\n ? AbortSignal.any([params.signal, abortController.signal])\n : abortController.signal\n\n calls.set(callId, abortController)\n\n const callIdEncoded = encodeNumber(callId, 'Uint32')\n const container = context.container.fork(Scope.Call)\n\n if (params.provides) {\n for (const [key, value] of params.provides) {\n container.provide(key, value)\n }\n }\n\n try {\n const response = await this.call({\n connection,\n container,\n namespace,\n payload,\n procedure,\n signal,\n metadata: params.metadata,\n })\n\n const responseEncoded = format.encoder.encodeRPC(\n {\n callId,\n result: response.output,\n },\n {\n addStream: (blob) => {\n const streamId = context.streamId++\n const stream = this.#serverStreams.add(connectionId, streamId, blob)\n stream.on('data', (chunk) => {\n stream.pause()\n const buf = Buffer.from(chunk)\n transport.send(\n connection,\n ServerMessageType.ServerStreamPush,\n concat(\n encodeNumber(streamId, 'Uint32'),\n (buf.buffer as ArrayBuffer).slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n ),\n ),\n { callId, streamId },\n )\n })\n stream.on('error', (err) => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamAbort,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n stream.on('end', () => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamEnd,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n return stream\n },\n getStream: (id) => {\n return this.#serverStreams.get(connectionId, id)\n },\n },\n )\n\n if ('subscription' in response) {\n throwError('Unimplemented')\n } else if (isIterableResult(response)) {\n transport.send(\n connection,\n ServerMessageType.RpcStreamResponse,\n responseEncoded,\n { callId },\n )\n try {\n const controller = new AbortController()\n context.rpcStreams.set(callId, controller)\n const iterable =\n typeof response.iterable === 'function'\n ? response.iterable(controller.signal)\n : response.iterable\n try {\n for await (const chunk of iterable) {\n controller.signal.throwIfAborted()\n const chunkEncoded = format.encoder.encode(chunk)\n transport.send(\n connection,\n ServerMessageType.RpcStreamChunk,\n concat(callIdEncoded, chunkEncoded),\n { callId },\n )\n }\n transport.send(\n connection,\n ServerMessageType.RpcStreamEnd,\n callIdEncoded,\n { callId },\n )\n } catch (error) {\n // do not re-throw AbortError errors, they are expected\n if (\n error instanceof Error === false ||\n error.name !== 'AbortError'\n ) {\n throw error\n }\n }\n } catch (error) {\n this.application.logger.error(error)\n transport.send(\n connection,\n ServerMessageType.RpcStreamAbort,\n callIdEncoded,\n { callId },\n )\n } finally {\n context.rpcStreams.delete(callId)\n response.onFinish && defer(response.onFinish)\n }\n } else {\n transport.send(\n connection,\n ServerMessageType.RpcResponse,\n responseEncoded,\n { callId },\n )\n }\n } catch (error) {\n const payload = format.encoder.encodeRPC(\n { callId, error },\n {\n addStream(blob) {\n throwError('Cannot handle stream for error response')\n },\n getStream(id) {\n throwError('Cannot handle stream for error response')\n },\n },\n )\n\n transport.send(connection, ServerMessageType.RpcResponse, payload, {\n error,\n callId,\n })\n } finally {\n calls.delete(callId)\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n }\n }\n\n async rpcRaw(\n connectionId: string,\n buffer: ArrayBuffer,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n\n const { format } = context\n\n const rpc = format.decoder.decodeRPC(buffer, {\n addStream: (streamId, callId, metadata) => {\n return this.#clientStreams.add(\n connectionId,\n streamId,\n metadata,\n (size) => {\n transport.send(\n connection,\n ServerMessageType.ClientStreamPull,\n concat(\n encodeNumber(streamId, 'Uint32'),\n encodeNumber(size, 'Uint32'),\n ),\n { callId, streamId },\n )\n },\n )\n },\n getStream: (id) => {\n return this.#clientStreams.get(connectionId, id)\n },\n })\n\n return await this.rpc(connectionId, rpc, params)\n }\n\n rpcAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const call = context.calls.get(callId) ?? throwError('Call not found')\n call.abort()\n }\n\n rpcAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcAbort(connectionId, callId)\n }\n\n rpcStreamAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const ab =\n context.rpcStreams.get(callId) ?? throwError('Call stream not found')\n ab.abort()\n }\n\n rpcStreamAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcStreamAbort(connectionId, callId)\n }\n\n notify(connectionId: string, event, payload) {\n throw Error('Unimplemented')\n }\n\n addConnection(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions,\n params: ResolveFormatParams,\n ) {\n return this.#connections.add(transport, options, params)\n }\n\n removeConnection(connectionId: string) {\n return this.#connections.remove(connectionId)\n }\n\n getConnection(connectionId: string) {\n return this.#connections.get(connectionId)\n }\n\n initializeConnection(connection: Connection) {\n return this.#connections.initialize(connection)\n }\n\n getClientStream(\n connectionId: string,\n streamId: number,\n ): ProtocolClientStream {\n return this.#clientStreams.get(connectionId, streamId)\n }\n\n addClientStream(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n return this.#clientStreams.add(connectionId, streamId, metadata, read)\n }\n\n removeClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.remove(connectionId, streamId)\n }\n\n pushClientStream(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n return this.#clientStreams.push(connectionId, streamId, chunk)\n }\n\n endClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.end(connectionId, streamId)\n }\n\n abortClientStream(connectionId: string, streamId: number, error?: Error) {\n return this.#clientStreams.abort(connectionId, streamId, error)\n }\n\n getServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.get(connectionId, streamId)\n }\n\n addServerStream(connectionId: string, streamId: number, blob: ProtocolBlob) {\n return this.#serverStreams.add(connectionId, streamId, blob)\n }\n\n removeServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.remove(connectionId, streamId)\n }\n\n pullServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.pull(connectionId, streamId)\n }\n\n abortServerStream(connectionId: string, streamId: number, error?: Error) {\n return this.#serverStreams.abort(connectionId, streamId, error)\n }\n}\n"],"version":3,"file":"protocol.js"}
|
|
1
|
+
{"mappings":"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","names":["code: string","message?: string","data?: any","#collection","application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n }","connectionId: string","transport: ProtocolConnectionTransport","options: ConnectionOptions<T>","params: ResolveFormatParams","connection: Connection","connections: ProtocolConnections","streamId: number","metadata: ProtocolBlobMetadata","read: Callback","chunk: ArrayBuffer","blob: ProtocolBlob","application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n }","#connections","#clientStreams","#serverStreams","options: ProtocolApiCallOptions","rpc: ProtocolRPC","params: ProtocolRPCOptions","buffer: ArrayBuffer","callId: number","options: ConnectionOptions","error?: Error"],"sources":["../../src/server/protocol.ts"],"sourcesContent":["import { type Callback, defer, isAbortError, throwError } from '@nmtjs/common'\nimport {\n type AnyInjectable,\n type Container,\n Hook,\n type Logger,\n Scope,\n} from '@nmtjs/core'\nimport { concat, decodeNumber, encodeNumber } from '../common/binary.ts'\nimport type { ProtocolBlob, ProtocolBlobMetadata } from '../common/blob.ts'\nimport { ErrorCode, ServerMessageType } from '../common/enums.ts'\nimport type { ProtocolRPC } from '../common/types.ts'\nimport {\n isIterableResult,\n type ProtocolApi,\n type ProtocolApiCallOptions,\n} from './api.ts'\nimport {\n Connection,\n ConnectionContext,\n type ConnectionOptions,\n} from './connection.ts'\nimport type { Format } from './format.ts'\nimport { ProtocolInjectables } from './injectables.ts'\nimport type { ProtocolRegistry } from './registry.ts'\nimport { ProtocolClientStream, ProtocolServerStream } from './stream.ts'\nimport type { Transport } from './transport.ts'\nimport { getFormat, type ResolveFormatParams } from './utils.ts'\n\nexport class ProtocolError extends Error {\n code: string\n data?: any\n\n constructor(code: string, message?: string, data?: any) {\n super(message)\n this.code = code\n this.data = data\n }\n\n get message() {\n return `${this.code} ${super.message}`\n }\n\n toString() {\n return `${this.code} ${this.message}`\n }\n\n toJSON() {\n return {\n code: this.code,\n message: this.message,\n data: this.data,\n }\n }\n}\n\nexport type ProtocolConnectionTransport = {\n send: Transport<any>['send']\n}\n\nexport class ProtocolConnections {\n readonly #collection = new Map<\n string,\n {\n connection: Connection\n context: ConnectionContext\n transport: ProtocolConnectionTransport\n }\n >()\n\n constructor(\n private readonly application: {\n logger: Logger\n registry: ProtocolRegistry\n format: Format\n container: Container\n },\n ) {}\n\n get(connectionId: string) {\n const connection = this.#collection.get(connectionId)\n if (!connection) throwError('Connection not found')\n return connection\n }\n\n async add<T>(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions<T>,\n params: ResolveFormatParams,\n ) {\n const connection = new Connection(options)\n const format = getFormat(this.application.format, params)\n const container = this.application.container.fork(Scope.Connection)\n const context = new ConnectionContext(container, format)\n container.provide(ProtocolInjectables.connection, connection)\n try {\n await this.initialize(connection)\n this.#collection.set(connection.id, { connection, context, transport })\n return { connection, context }\n } catch (error) {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n throw error\n }\n }\n\n async remove(connectionId: string) {\n const { connection, context } = this.get(connectionId)\n\n this.application.registry.hooks.call(\n Hook.OnDisconnect,\n { concurrent: true },\n connection,\n )\n\n this.#collection.delete(connectionId)\n\n const { calls, serverStreams, clientStreams, rpcStreams, container } =\n context\n\n for (const call of calls.values()) {\n call.abort(new Error('Connection closed'))\n }\n\n for (const stream of clientStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of serverStreams.values()) {\n stream.destroy(new Error('Connection closed'))\n }\n\n for (const stream of rpcStreams.values()) {\n stream.abort(new Error('Connection closed'))\n }\n\n try {\n await container.dispose()\n } catch (error) {\n this.application.logger.error(\n { error, connection },\n 'Error during closing connection',\n )\n }\n }\n\n async initialize(connection: Connection) {\n await this.application.registry.hooks.call(\n Hook.OnConnect,\n { concurrent: false },\n connection,\n )\n }\n}\n\nexport class ProtocolClientStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = clientStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n clientStreams.get(streamId) || throwError('Stream not found')\n clientStreams.delete(streamId)\n }\n\n add(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n const { context } = this.connections.get(connectionId)\n const { clientStreams } = context\n const stream = new ProtocolClientStream(streamId, metadata, { read })\n clientStreams.set(streamId, stream)\n return stream\n }\n\n push(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n const stream = this.get(connectionId, streamId)\n stream.write(Buffer.from(chunk))\n }\n\n end(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.end(null)\n this.remove(connectionId, streamId)\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport class ProtocolServerStreams {\n constructor(private readonly connections: ProtocolConnections) {}\n\n get(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = serverStreams.get(streamId) ?? throwError('Stream not found')\n return stream\n }\n\n add(connectionId: string, streamId: number, blob: ProtocolBlob) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n const stream = new ProtocolServerStream(streamId, blob)\n serverStreams.set(streamId, stream)\n return stream\n }\n\n remove(connectionId: string, streamId: number) {\n const { context } = this.connections.get(connectionId)\n const { serverStreams } = context\n serverStreams.has(streamId) || throwError('Stream not found')\n serverStreams.delete(streamId)\n }\n\n pull(connectionId: string, streamId: number) {\n const stream = this.get(connectionId, streamId)\n stream.resume()\n }\n\n abort(connectionId: string, streamId: number, error = new Error('Aborted')) {\n const stream = this.get(connectionId, streamId)\n stream.destroy(error)\n this.remove(connectionId, streamId)\n }\n}\n\nexport type ProtocolRPCOptions = {\n signal?: AbortSignal\n provides?: [AnyInjectable, any][]\n metadata?: ProtocolApiCallOptions['metadata']\n}\n\nexport class Protocol {\n #connections: ProtocolConnections\n #clientStreams: ProtocolClientStreams\n #serverStreams: ProtocolServerStreams\n\n constructor(\n protected readonly application: {\n logger: Logger\n format: Format\n container: Container\n registry: ProtocolRegistry\n api: ProtocolApi\n },\n ) {\n this.#connections = new ProtocolConnections(this.application)\n this.#clientStreams = new ProtocolClientStreams(this.#connections)\n this.#serverStreams = new ProtocolServerStreams(this.#connections)\n }\n\n async call(options: ProtocolApiCallOptions) {\n const { container, connection } = options\n try {\n return await this.application.api.call(options)\n } catch (error) {\n if (error instanceof ProtocolError === false) {\n this.application.logger.error(\n { error, connection },\n 'Error during RPC call',\n )\n throw new ProtocolError(\n ErrorCode.InternalServerError,\n 'Internal server error',\n )\n }\n throw error\n } finally {\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n \"Error during disposing connection's container\",\n )\n })\n }\n }\n\n async rpc(\n connectionId: string,\n rpc: ProtocolRPC,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n const { calls, format } = context\n const { callId, namespace, procedure, payload } = rpc\n const abortController = new AbortController()\n const signal = params.signal\n ? AbortSignal.any([params.signal, abortController.signal])\n : abortController.signal\n\n calls.set(callId, abortController)\n\n const callIdEncoded = encodeNumber(callId, 'Uint32')\n const container = context.container.fork(Scope.Call)\n\n if (params.provides) {\n for (const [key, value] of params.provides) {\n container.provide(key, value)\n }\n }\n\n try {\n const response = await this.call({\n connection,\n container,\n namespace,\n payload,\n procedure,\n signal,\n metadata: params.metadata,\n })\n\n const responseEncoded = format.encoder.encodeRPC(\n {\n callId,\n result: response.output,\n },\n {\n addStream: (blob) => {\n const streamId = context.streamId++\n const stream = this.#serverStreams.add(connectionId, streamId, blob)\n stream.on('data', (chunk) => {\n stream.pause()\n const buf = Buffer.from(chunk)\n transport.send(\n connection,\n ServerMessageType.ServerStreamPush,\n concat(\n encodeNumber(streamId, 'Uint32'),\n (buf.buffer as ArrayBuffer).slice(\n buf.byteOffset,\n buf.byteOffset + buf.byteLength,\n ),\n ),\n { callId, streamId },\n )\n })\n stream.on('error', (err) => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamAbort,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n stream.on('end', () => {\n transport.send(\n connection,\n ServerMessageType.ServerStreamEnd,\n encodeNumber(streamId, 'Uint32'),\n { callId, streamId },\n )\n })\n return stream\n },\n getStream: (id) => {\n return this.#serverStreams.get(connectionId, id)\n },\n },\n )\n\n if (isIterableResult(response)) {\n transport.send(\n connection,\n ServerMessageType.RpcStreamResponse,\n responseEncoded,\n { callId },\n )\n try {\n const controller = new AbortController()\n context.rpcStreams.set(callId, controller)\n const iterable =\n typeof response.iterable === 'function'\n ? response.iterable(controller.signal)\n : response.iterable\n try {\n for await (const chunk of iterable) {\n controller.signal.throwIfAborted()\n const chunkEncoded = format.encoder.encode(chunk)\n transport.send(\n connection,\n ServerMessageType.RpcStreamChunk,\n concat(callIdEncoded, chunkEncoded),\n { callId },\n )\n }\n transport.send(\n connection,\n ServerMessageType.RpcStreamEnd,\n callIdEncoded,\n { callId },\n )\n } catch (error) {\n // do not re-throw AbortError errors, they are expected\n if (!isAbortError(error)) {\n throw error\n }\n }\n } catch (error) {\n this.application.logger.error(error)\n transport.send(\n connection,\n ServerMessageType.RpcStreamAbort,\n callIdEncoded,\n { callId },\n )\n } finally {\n context.rpcStreams.delete(callId)\n response.onFinish && defer(response.onFinish)\n }\n } else {\n transport.send(\n connection,\n ServerMessageType.RpcResponse,\n responseEncoded,\n { callId },\n )\n }\n } catch (error) {\n const payload = format.encoder.encodeRPC(\n { callId, error },\n {\n addStream(blob) {\n throwError('Cannot handle stream for error response')\n },\n getStream(id) {\n throwError('Cannot handle stream for error response')\n },\n },\n )\n\n transport.send(connection, ServerMessageType.RpcResponse, payload, {\n error,\n callId,\n })\n } finally {\n calls.delete(callId)\n container.dispose().catch((error) => {\n this.application.logger.error(\n { error, connection },\n 'Error during disposing connection',\n )\n })\n }\n }\n\n async rpcRaw(\n connectionId: string,\n buffer: ArrayBuffer,\n params: ProtocolRPCOptions = {},\n ) {\n const { connection, context, transport } =\n this.#connections.get(connectionId)\n\n const { format } = context\n\n const rpc = format.decoder.decodeRPC(buffer, {\n addStream: (streamId, callId, metadata) => {\n return this.#clientStreams.add(\n connectionId,\n streamId,\n metadata,\n (size) => {\n transport.send(\n connection,\n ServerMessageType.ClientStreamPull,\n concat(\n encodeNumber(streamId, 'Uint32'),\n encodeNumber(size, 'Uint32'),\n ),\n { callId, streamId },\n )\n },\n )\n },\n getStream: (id) => {\n return this.#clientStreams.get(connectionId, id)\n },\n })\n\n return await this.rpc(connectionId, rpc, params)\n }\n\n rpcAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const call = context.calls.get(callId) ?? throwError('Call not found')\n call.abort()\n }\n\n rpcAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcAbort(connectionId, callId)\n }\n\n rpcStreamAbort(connectionId: string, callId: number) {\n const { context } = this.#connections.get(connectionId)\n const ab =\n context.rpcStreams.get(callId) ?? throwError('Call stream not found')\n ab.abort()\n }\n\n rpcStreamAbortRaw(connectionId: string, buffer: ArrayBuffer) {\n const callId = decodeNumber(buffer, 'Uint32')\n return this.rpcStreamAbort(connectionId, callId)\n }\n\n notify(connectionId: string, event, payload) {\n throw Error('Unimplemented')\n }\n\n addConnection(\n transport: ProtocolConnectionTransport,\n options: ConnectionOptions,\n params: ResolveFormatParams,\n ) {\n return this.#connections.add(transport, options, params)\n }\n\n removeConnection(connectionId: string) {\n return this.#connections.remove(connectionId)\n }\n\n getConnection(connectionId: string) {\n return this.#connections.get(connectionId)\n }\n\n initializeConnection(connection: Connection) {\n return this.#connections.initialize(connection)\n }\n\n getClientStream(\n connectionId: string,\n streamId: number,\n ): ProtocolClientStream {\n return this.#clientStreams.get(connectionId, streamId)\n }\n\n addClientStream(\n connectionId: string,\n streamId: number,\n metadata: ProtocolBlobMetadata,\n read: Callback,\n ) {\n return this.#clientStreams.add(connectionId, streamId, metadata, read)\n }\n\n removeClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.remove(connectionId, streamId)\n }\n\n pushClientStream(connectionId: string, streamId: number, chunk: ArrayBuffer) {\n return this.#clientStreams.push(connectionId, streamId, chunk)\n }\n\n endClientStream(connectionId: string, streamId: number) {\n return this.#clientStreams.end(connectionId, streamId)\n }\n\n abortClientStream(connectionId: string, streamId: number, error?: Error) {\n return this.#clientStreams.abort(connectionId, streamId, error)\n }\n\n getServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.get(connectionId, streamId)\n }\n\n addServerStream(connectionId: string, streamId: number, blob: ProtocolBlob) {\n return this.#serverStreams.add(connectionId, streamId, blob)\n }\n\n removeServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.remove(connectionId, streamId)\n }\n\n pullServerStream(connectionId: string, streamId: number) {\n return this.#serverStreams.pull(connectionId, streamId)\n }\n\n abortServerStream(connectionId: string, streamId: number, error?: Error) {\n return this.#serverStreams.abort(connectionId, streamId, error)\n }\n}\n"],"version":3,"file":"protocol.js"}
|
package/package.json
CHANGED
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@nmtjs/common": "0.11.
|
|
20
|
-
"@nmtjs/type": "0.11.
|
|
21
|
-
"@nmtjs/core": "0.11.
|
|
19
|
+
"@nmtjs/common": "0.11.8",
|
|
20
|
+
"@nmtjs/type": "0.11.8",
|
|
21
|
+
"@nmtjs/core": "0.11.8"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@nmtjs/
|
|
25
|
-
"@nmtjs/
|
|
26
|
-
"@nmtjs/
|
|
24
|
+
"@nmtjs/type": "0.11.8",
|
|
25
|
+
"@nmtjs/core": "0.11.8",
|
|
26
|
+
"@nmtjs/common": "0.11.8"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"src",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"LICENSE.md",
|
|
32
32
|
"README.md"
|
|
33
33
|
],
|
|
34
|
-
"version": "0.11.
|
|
34
|
+
"version": "0.11.8",
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "neemata-build --root=./src './**/*.ts'",
|
|
37
37
|
"type-check": "tsc --noEmit"
|
package/src/server/api.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Container, Hook, MetadataStore } from '@nmtjs/core'
|
|
2
2
|
import type { Connection } from './connection.ts'
|
|
3
|
+
import { kIterableResponse } from './constants.ts'
|
|
3
4
|
|
|
4
5
|
export type ProtocolApiCallOptions = {
|
|
5
6
|
connection: Connection
|
|
@@ -15,37 +16,49 @@ export type ProtocolAnyIterable<T> =
|
|
|
15
16
|
| ((signal: AbortSignal) => AsyncGenerator<T>)
|
|
16
17
|
| AsyncIterable<T>
|
|
17
18
|
|
|
18
|
-
export interface ProtocolApiCallBaseResult {
|
|
19
|
-
output:
|
|
20
|
-
}
|
|
21
|
-
export interface ProtocolApiCallSubscriptionResult
|
|
22
|
-
extends ProtocolApiCallBaseResult {
|
|
23
|
-
subscription: never
|
|
19
|
+
export interface ProtocolApiCallBaseResult<T = unknown> {
|
|
20
|
+
output: T
|
|
24
21
|
}
|
|
25
22
|
|
|
26
|
-
export interface ProtocolApiCallIterableResult
|
|
27
|
-
extends ProtocolApiCallBaseResult {
|
|
28
|
-
|
|
23
|
+
export interface ProtocolApiCallIterableResult<Y = unknown, O = unknown>
|
|
24
|
+
extends ProtocolApiCallBaseResult<O> {
|
|
25
|
+
[kIterableResponse]: true
|
|
26
|
+
iterable: ProtocolAnyIterable<Y>
|
|
29
27
|
onFinish?: () => void
|
|
30
28
|
}
|
|
31
29
|
|
|
32
30
|
export type ProtocolApiCallResult =
|
|
33
31
|
| ProtocolApiCallBaseResult
|
|
34
|
-
| ProtocolApiCallSubscriptionResult
|
|
35
32
|
| ProtocolApiCallIterableResult
|
|
36
33
|
|
|
37
|
-
export const isIterableResult = (
|
|
38
|
-
result: ProtocolApiCallResult,
|
|
39
|
-
): result is ProtocolApiCallIterableResult => 'iterable' in result
|
|
40
|
-
|
|
41
|
-
export const isSubscriptionResult = (
|
|
42
|
-
result: ProtocolApiCallResult,
|
|
43
|
-
): result is ProtocolApiCallSubscriptionResult => 'subscription' in result
|
|
44
|
-
|
|
45
34
|
export interface ProtocolApi {
|
|
46
35
|
call(options: ProtocolApiCallOptions): Promise<ProtocolApiCallResult>
|
|
47
36
|
}
|
|
48
37
|
|
|
38
|
+
export function isIterableResult(
|
|
39
|
+
value: any,
|
|
40
|
+
): value is ProtocolApiCallIterableResult {
|
|
41
|
+
return value && value[kIterableResponse] === true
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function createStreamResponse<Y, O>(
|
|
45
|
+
iterable: ProtocolAnyIterable<Y>,
|
|
46
|
+
{
|
|
47
|
+
onFinish,
|
|
48
|
+
output = undefined as O,
|
|
49
|
+
}: {
|
|
50
|
+
output?: O
|
|
51
|
+
onFinish?: () => void
|
|
52
|
+
},
|
|
53
|
+
): ProtocolApiCallIterableResult<Y, O> {
|
|
54
|
+
return {
|
|
55
|
+
[kIterableResponse]: true as const,
|
|
56
|
+
iterable,
|
|
57
|
+
output,
|
|
58
|
+
onFinish,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
declare module '@nmtjs/core' {
|
|
50
63
|
export interface HookType {
|
|
51
64
|
[Hook.OnConnect]: (connection: Connection) => any
|
package/src/server/constants.ts
CHANGED
|
@@ -2,3 +2,8 @@ export const kTransportPlugin: unique symbol = Symbol.for(
|
|
|
2
2
|
'neemata:TransportPluginKey',
|
|
3
3
|
)
|
|
4
4
|
export type kTransportPlugin = typeof kTransportPlugin
|
|
5
|
+
|
|
6
|
+
export const kIterableResponse: unique symbol = Symbol.for(
|
|
7
|
+
'neemata:IterableResponseKey',
|
|
8
|
+
)
|
|
9
|
+
export type kIterableResponse = typeof kIterableResponse
|
package/src/server/protocol.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Callback, defer, throwError } from '@nmtjs/common'
|
|
1
|
+
import { type Callback, defer, isAbortError, throwError } from '@nmtjs/common'
|
|
2
2
|
import {
|
|
3
3
|
type AnyInjectable,
|
|
4
4
|
type Container,
|
|
@@ -378,9 +378,7 @@ export class Protocol {
|
|
|
378
378
|
},
|
|
379
379
|
)
|
|
380
380
|
|
|
381
|
-
if (
|
|
382
|
-
throwError('Unimplemented')
|
|
383
|
-
} else if (isIterableResult(response)) {
|
|
381
|
+
if (isIterableResult(response)) {
|
|
384
382
|
transport.send(
|
|
385
383
|
connection,
|
|
386
384
|
ServerMessageType.RpcStreamResponse,
|
|
@@ -413,10 +411,7 @@ export class Protocol {
|
|
|
413
411
|
)
|
|
414
412
|
} catch (error) {
|
|
415
413
|
// do not re-throw AbortError errors, they are expected
|
|
416
|
-
if (
|
|
417
|
-
error instanceof Error === false ||
|
|
418
|
-
error.name !== 'AbortError'
|
|
419
|
-
) {
|
|
414
|
+
if (!isAbortError(error)) {
|
|
420
415
|
throw error
|
|
421
416
|
}
|
|
422
417
|
}
|