json-rpc-dual-engine
Version:
JSON-RPC-2.0 client and server protocol-agnostic engine.
60 lines (59 loc) • 2.01 kB
JavaScript
import { JsonRpcClient } from './json-rpc-client.js';
import { JsonRpcRequest } from './json-rpc-request.js';
import { JsonRpcResponse } from './json-rpc-response.js';
import { JsonRpcServer } from './json-rpc-server.js';
export class JsonRpcDualEngine {
constructor(handler, options) {
this.server = new JsonRpcServer(handler, options);
this.client = new JsonRpcClient(options);
}
server;
client;
get transport() {
return this.client.transport || this.server.transport;
}
set transport(transport) {
this.client.transport = this.server.transport = transport;
}
async accept(message) {
try {
await this.#accept(message);
}
catch (cause) {
throw new Error('Failed to accept json-rpc message.', { cause });
}
}
async #accept(message) {
const object = typeof message === 'string' ? JSON.parse(message) : message;
const parsed = (() => {
try {
return JsonRpcRequest.parse(object);
}
catch (requestError) {
try {
return JsonRpcResponse.parse(object);
}
catch (responseError) {
throw new Error('Failed to parse json-rpc message.', { cause: { requestError, responseError } });
}
}
})();
await 'method' in parsed
? this.server.accept(parsed)
: this.client.accept(parsed);
}
toStream() {
let localTransport = undefined;
return new TransformStream({
start: controller => {
localTransport = this.transport = messageStr => controller.enqueue(messageStr);
},
transform: message => this.accept(message),
flush: () => {
if (this.transport === localTransport) {
this.transport = undefined;
}
},
});
}
}