121 lines
3.4 KiB
TypeScript
121 lines
3.4 KiB
TypeScript
|
//@template-ignore
|
||
|
import { RequestObject, ResponseObject, ErrorCodes, Logging } from "./ts_service_base";
|
||
|
|
||
|
|
||
|
export class Service<T> {
|
||
|
public name: string = null as any;
|
||
|
public functions = new Set<string>();
|
||
|
|
||
|
constructor() {}
|
||
|
}
|
||
|
|
||
|
type ISendMessageCB = (data: any, catchedErr?: Error) => void;
|
||
|
|
||
|
export class ServiceProvider<T = any> {
|
||
|
services = new Map<string, Service<T>>();
|
||
|
addService(service: Service<T>) {
|
||
|
this.services.set(service.name, service);
|
||
|
Logging.log("SERVER: Adding Service to provider:", service.name);
|
||
|
Logging.log("SERVER: Service provides:", [...service.functions.keys()])
|
||
|
}
|
||
|
|
||
|
getSession(send: ISendMessageCB, ctx?: Partial<T>): Session<T> {
|
||
|
return new Session(this, send, ctx);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class Session<T> {
|
||
|
ctx: Partial<T>;
|
||
|
|
||
|
constructor(
|
||
|
private provider: ServiceProvider,
|
||
|
private _send: ISendMessageCB,
|
||
|
ctx?: Partial<T>
|
||
|
) {
|
||
|
this.ctx = ctx || {};
|
||
|
}
|
||
|
|
||
|
send(data: any, catchedErr?:Error) {
|
||
|
Logging.log("SERVER: Sending Message", data)
|
||
|
this._send(data, catchedErr);
|
||
|
}
|
||
|
|
||
|
async onMessage(data: RequestObject) {
|
||
|
Logging.log("SERVER: Received Message", data);
|
||
|
try {
|
||
|
if (!data.method) {
|
||
|
if (data.id) {
|
||
|
this.send({
|
||
|
jsonrpc: "2.0",
|
||
|
id: data.id,
|
||
|
error: {
|
||
|
code: ErrorCodes.InvalidRequest,
|
||
|
message: "No method defined!",
|
||
|
},
|
||
|
} as ResponseObject);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const [srvName, fncName] = data.method.split(".");
|
||
|
Logging.log("SERVER: Message for", srvName, fncName);
|
||
|
|
||
|
const service = this.provider.services.get(srvName);
|
||
|
if (!service) {
|
||
|
Logging.log("SERVER: Did not find Service");
|
||
|
if (data.id) {
|
||
|
this.send({
|
||
|
jsonrpc: "2.0",
|
||
|
id: data.id,
|
||
|
error: {
|
||
|
code: ErrorCodes.MethodNotFound,
|
||
|
message: "Service not found!",
|
||
|
},
|
||
|
} as ResponseObject);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const fnc = service.functions.has(fncName);
|
||
|
if (!fnc) {
|
||
|
Logging.log("SERVER: Did not find Function");
|
||
|
if (data.id) {
|
||
|
this.send({
|
||
|
jsonrpc: "2.0",
|
||
|
id: data.id,
|
||
|
error: {
|
||
|
code: ErrorCodes.MethodNotFound,
|
||
|
message: "Function not found!",
|
||
|
},
|
||
|
} as ResponseObject);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let result = await (service as any)["_" + fncName](data.params, this.ctx);
|
||
|
if(data.id) { //Request
|
||
|
this.send({
|
||
|
jsonrpc: "2.0",
|
||
|
id: data.id,
|
||
|
result: result,
|
||
|
} as ResponseObject);
|
||
|
} //else Notification and response is ignored
|
||
|
} catch (err) {
|
||
|
if (data.id) {
|
||
|
this.send(
|
||
|
{
|
||
|
jsonrpc: "2.0",
|
||
|
id: data.id,
|
||
|
error: {
|
||
|
code: ErrorCodes.InternalError,
|
||
|
message: err.message,
|
||
|
},
|
||
|
} as ResponseObject,
|
||
|
err
|
||
|
);
|
||
|
}
|
||
|
//TODO: Think about else case
|
||
|
}
|
||
|
}
|
||
|
}
|