// tslint:disable:interface-over-type-literal export type DefaultRequestTypes = {}; export type DefaultResponseTypes = {}; export type DefaultErrorType = { code: number; message: string; data?: any; }; export type DefaultNotificationTypes = {}; // tslint:enable:interface-over-type-literal // export interface RpcTypes { // RequestTypes: DefaultRequestTypes; // ResponseTypes: DefaultResponseTypes; // NotificationTypes: DefaultNotificationTypes; // ErrorType: DefaultErrorType; // } export interface Request< RequestTypes = DefaultRequestTypes, Method extends keyof RequestTypes = keyof RequestTypes > { type: "request"; id: number; method: Method; params: RequestTypes[Method]; } export interface ResponseBase { type: "response"; id: number; method: Method; } export interface SuccessData { result: "success"; data: ResponseType; } export interface ErrorData { result: "error"; error: ErrorType; } export type ResponseData< ResponseTypes, ErrorType, Method extends keyof ResponseTypes = keyof ResponseTypes > = SuccessData | ErrorData; export type Response< ResponseTypes, ErrorType = DefaultErrorType, Method extends keyof ResponseTypes = keyof ResponseTypes > = ResponseBase & ResponseData; export interface Notification< NotificationTypes = DefaultNotificationTypes, Method extends keyof NotificationTypes = keyof NotificationTypes > { type: "notification"; method: Method; data: NotificationTypes[Method]; } export type Message< RequestTypes = DefaultRequestTypes, ResponseTypes = DefaultResponseTypes, ErrorType = DefaultErrorType, NotificationTypes = DefaultNotificationTypes > = | Request | Response | Notification; // export type TypesMessage = // Message; export function isRequestMethod< Method extends keyof RequestTypes, RequestTypes >( message: Request, method: Method ): message is Request { return message.method === method; } export function isResponseMethod< Method extends keyof ResponseTypes, ErrorType, ResponseTypes >( message: Response, method: Method ): message is Response { return message.method === method; } export function isNotificationMethod< Method extends keyof NotificationTypes, NotificationTypes = any >( message: Notification, method: Method ): message is Notification { return message.method === method; } export type IRequestHandler< RequestTypes, ResponseTypes extends { [M in Method]: any }, ErrorType, Method extends keyof RequestTypes > = ( request: RequestTypes[Method] ) => Promise>; export type RequestHandlers< RequestTypes, ResponseTypes extends { [M in keyof RequestTypes]: any }, ErrorType > = { [Method in keyof RequestTypes]: IRequestHandler< RequestTypes, ResponseTypes, ErrorType, Method > }; export type IResponseHandler< ResponseTypes, ErrorType, Method extends keyof ResponseTypes = keyof ResponseTypes > = (response: Response) => void; export interface ResponseHandlers< ResponseTypes = DefaultResponseTypes, ErrorType = DefaultErrorType > { [id: number]: IResponseHandler; } export type NotificationHandler< NotificationTypes, Method extends keyof NotificationTypes > = (notification: NotificationTypes[Method]) => void; export type NotificationHandlers = { [Method in keyof NotificationTypes]: NotificationHandler< NotificationTypes, Method > }; export function listRequestHandlerMethods< RequestTypes, ResponseTypes extends { [Method in keyof RequestTypes]: any }, ErrorType >( handlers: RequestHandlers ): Array { return Object.keys(handlers) as any; } export function listNotificationHandlerMethods( handlers: NotificationHandlers ): Array { return Object.keys(handlers) as any; } export async function handleRequest< RequestTypes, ResponseTypes extends { [Method in keyof RequestTypes]: any }, ErrorType >( handlers: RequestHandlers, message: Request, thisParam?: any ): Promise> { const handler = handlers[message.method]; if (!handler) { throw new Error("No handler for request method " + message.method); } return handler.call(thisParam, message.params); } export function handleResponse( handlers: ResponseHandlers, message: Response, thisParam?: any ) { const handler = handlers[message.id]; if (!handler) { return; } return handler.call(thisParam, message); } export function handleNotification( handlers: NotificationHandlers, message: Notification, thisParam?: any ) { const handler = handlers[message.method]; if (!handler) { throw new Error("No handler for notification method " + message.method); } return handler.call(thisParam, message.data); }