You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
5.5 KiB

// 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: Response<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>,
thisParam?: any
): Promise<ResponseData<ResponseTypes, ErrorType>> {
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<ResponseTypes, ErrorType>(
handlers: ResponseHandlers<ResponseTypes, ErrorType>,
message: Response<ResponseTypes, ErrorType>,
thisParam?: any
) {
const handler = handlers[message.id];
if (!handler) {
return;
}
return handler.call(thisParam, message);
}
export function handleNotification<NotificationTypes>(
handlers: NotificationHandlers<NotificationTypes>,
message: Notification<NotificationTypes>,
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);
}