Alex Mikhalev
7 years ago
17 changed files with 464 additions and 196 deletions
@ -0,0 +1,155 @@ |
|||||||
|
// 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); |
||||||
|
} |
@ -1,52 +1,76 @@ |
|||||||
import { Response as ResponseData } from "@common/sprinklers/requests"; |
import * as rpc from "../jsonRpc/index"; |
||||||
|
|
||||||
export interface IError { |
import { Response as ResponseData } from "@common/sprinklers/deviceRequests"; |
||||||
type: "error"; |
|
||||||
message: string; |
export interface IAuthenticateRequest { |
||||||
data: any; |
accessToken: string; |
||||||
} |
} |
||||||
|
|
||||||
export interface IDeviceSubscribeResponse { |
export interface IDeviceSubscribeRequest { |
||||||
type: "deviceSubscribeResponse"; |
|
||||||
deviceId: string; |
deviceId: string; |
||||||
result: "success" | "noPermission"; |
|
||||||
} |
} |
||||||
|
|
||||||
export interface IDeviceUpdate { |
export interface IDeviceCallRequest { |
||||||
type: "deviceUpdate"; |
|
||||||
deviceId: string; |
deviceId: string; |
||||||
data: any; |
data: any; |
||||||
} |
} |
||||||
|
|
||||||
|
export interface IClientRequestTypes { |
||||||
|
"authenticate": IAuthenticateRequest; |
||||||
|
"deviceSubscribe": IDeviceSubscribeRequest; |
||||||
|
"deviceCall": IDeviceCallRequest; |
||||||
|
} |
||||||
|
|
||||||
|
export interface IAuthenticateResponse { |
||||||
|
authenticated: boolean; |
||||||
|
message: string; |
||||||
|
data?: any; |
||||||
|
} |
||||||
|
|
||||||
|
export interface IDeviceSubscribeResponse { |
||||||
|
deviceId: string; |
||||||
|
} |
||||||
|
|
||||||
export interface IDeviceCallResponse { |
export interface IDeviceCallResponse { |
||||||
type: "deviceCallResponse"; |
|
||||||
requestId: number; |
|
||||||
data: ResponseData; |
data: ResponseData; |
||||||
} |
} |
||||||
|
|
||||||
export interface IBrokerConnectionUpdate { |
export interface IServerResponseTypes { |
||||||
type: "brokerConnectionUpdate"; |
"authenticate": IAuthenticateResponse; |
||||||
brokerConnected: boolean; |
"deviceSubscribe": IDeviceSubscribeResponse; |
||||||
|
"deviceCall": IDeviceCallResponse; |
||||||
} |
} |
||||||
|
|
||||||
export type IServerMessage = IError | IDeviceSubscribeResponse | IDeviceUpdate | IDeviceCallResponse | |
export type ClientRequestMethods = keyof IClientRequestTypes; |
||||||
IBrokerConnectionUpdate; |
|
||||||
|
|
||||||
export interface IAuthenticateRequest { |
export interface IBrokerConnectionUpdate { |
||||||
type: "authenticateRequest"; |
brokerConnected: boolean; |
||||||
accessToken: string; |
|
||||||
} |
} |
||||||
|
|
||||||
export interface IDeviceSubscribeRequest { |
export interface IDeviceUpdate { |
||||||
type: "deviceSubscribeRequest"; |
|
||||||
deviceId: string; |
deviceId: string; |
||||||
|
data: any; |
||||||
} |
} |
||||||
|
|
||||||
export interface IDeviceCallRequest { |
export interface IServerNotificationTypes { |
||||||
type: "deviceCallRequest"; |
"brokerConnectionUpdate": IBrokerConnectionUpdate; |
||||||
requestId: number; |
"deviceUpdate": IDeviceUpdate; |
||||||
deviceId: string; |
"error": Error; |
||||||
data: any; |
|
||||||
} |
} |
||||||
|
export type ServerNotificationMethod = keyof IServerNotificationTypes; |
||||||
|
|
||||||
|
export type Error = rpc.DefaultErrorType; |
||||||
|
export type ErrorData = rpc.ErrorData<Error>; |
||||||
|
|
||||||
|
export type ServerMessage = rpc.Message<{}, IServerResponseTypes, Error, IServerNotificationTypes>; |
||||||
|
export type ServerNotification = rpc.Notification<IServerNotificationTypes>; |
||||||
|
export type ServerResponse = rpc.Response<IServerResponseTypes, Error>; |
||||||
|
export type ServerResponseData<Method extends keyof IServerResponseTypes = keyof IServerResponseTypes> = |
||||||
|
rpc.ResponseData<IServerResponseTypes, Error, Method>; |
||||||
|
export type ServerResponseHandlers = rpc.ResponseHandlers<IServerResponseTypes, Error>; |
||||||
|
export type ServerNotificationHandlers = rpc.NotificationHandlers<IServerNotificationTypes>; |
||||||
|
|
||||||
export type IClientMessage = IDeviceSubscribeRequest | IDeviceCallRequest; |
export type ClientRequest<Method extends keyof IClientRequestTypes = keyof IClientRequestTypes> = |
||||||
|
rpc.Request<IClientRequestTypes, Method>; |
||||||
|
export type ClientMessage = rpc.Message<IClientRequestTypes, {}, Error, {}>; |
||||||
|
export type ClientRequestHandlers = rpc.RequestHandlers<IClientRequestTypes, IServerResponseTypes, Error>; |
||||||
|
Loading…
Reference in new issue