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.
211 lines
5.5 KiB
211 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); |
|
}
|
|
|