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.
156 lines
5.4 KiB
156 lines
5.4 KiB
7 years ago
|
// 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);
|
||
|
}
|