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