UNPKG

@qubit-rs/client

Version:

Seamless RPC for Rust & TypeScript

151 lines (139 loc) 5.17 kB
type RpcRequest = { jsonrpc: "2.0"; method: string; id: string | number; params: unknown; }; /** * A JSONRPC-2.0 error. */ type RpcError = { code: number; message: string; data: any; }; /** * An incoming message for a specific subscription */ type RpcSubscriptionMessage<T> = { type: "message"; id: string | number; value: T; }; type RpcResponse<T> = { type: "ok"; id: string | number; value: T; } | { type: "error"; id: string | number; value: RpcError; } | RpcSubscriptionMessage<T>; type SocketOptions = { WebSocket: unknown; }; declare function ws(host: string, socket_options?: SocketOptions): { query: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<any>>; mutate: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<any>>; subscribe: (id: string | number, on_data: ((value: any) => void) | undefined) => () => void; }; type HttpOptions = { fetch?: typeof fetch; }; declare function http(host: string, http_options?: HttpOptions): { query: (_id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; mutate: (_id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; }; type MultiOptions = { ws?: SocketOptions; http?: HttpOptions; }; /** * Transport that combines both `http` for query and mutate, and `ws` for subscriptions. */ declare function multi(host: string, options?: MultiOptions): { query: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; mutate: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; subscribe: (id: string | number, on_data: ((value: any) => void) | undefined) => () => void; }; type ClientBuilder<Server> = (host: string) => Server; /** * Interface required for a transport. */ type Transport = { /** * Make a request that is a query, meaning that it is safe to be cached. */ query: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; /** * Make a request that is a mutation, meaning that it should not be cached. */ mutate: (id: string | number, payload: RpcRequest) => Promise<RpcResponse<unknown> | null>; /** * Start a subscription, calling `on_data` for every message from the server. An unsubscribe * method must be returned, which must terminate the subscription when called. */ subscribe?: (id: string | number, on_data?: (value: any) => void) => () => void; }; type Query<Args extends any[], Return> = { query: (...args: Args) => Promise<Return>; }; type Mutation<Args extends any[], Return> = { mutate: (...args: Args) => Promise<Return>; }; type StreamHandlers<T> = { on_data: (data: T) => void; on_error: (error: Error) => void; on_end: () => void; }; type StreamHandler<T> = ((data: T) => void) | Partial<StreamHandlers<T>>; type StreamUnsubscribe = () => void; /** * Helper type to add handler to a list of arguments, in a way that it will be named. */ type AddHandler<Arr extends any[], Item> = [...Arr, handler: StreamHandler<Item>]; type Subscription<Args extends any[], Item> = { subscribe: (...args: AddHandler<Args, Item>) => StreamUnsubscribe; }; /** * A handler function which must always take the path, represented as an array of strings. */ type HandlerFn<TArgs extends any[], TReturn> = (path: string[], ...args: TArgs) => TReturn; /** * Strips the `path` parameter (first parameter) from a `HandlerFn`. This represents the function * that is exposed to the end-user. */ type StripPath<F> = F extends HandlerFn<infer TArgs, infer TReturn> ? (...args: TArgs) => TReturn : never; /** * A collection of plugins, meaning handlers that include the path parameter. */ type Plugins = Record<string, HandlerFn<any[], any>>; /** * For all available handlers, will produce a handler that has the `path` parameter stripped from * it. */ type Handlers<THandlers extends Plugins> = { [K in keyof THandlers]: StripPath<THandlers[K]>; }; /** * Determines if the provided type has a nested object, or is just made up of functions. */ type HasNestedObject<T> = { [K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : never; }; type AtEdge<T, Yes, No> = T extends HasNestedObject<T> ? Yes : No; /** * Inject the provided plugins into the edges of the server. */ type InjectPlugins<TServer, TPlugins extends Plugins> = AtEdge<TServer, TServer & TPlugins, { [K in keyof TServer]: InjectPlugins<TServer[K], TPlugins>; }>; /** * Build a new client for a server. */ declare function build_client<Server>(client: Transport): Server; /** * Build a new client and inject the following plugins. */ declare function build_client<Server, TPlugins extends Plugins>(transport: Transport, plugins: TPlugins): InjectPlugins<Server, Handlers<TPlugins>>; export { type ClientBuilder, type HandlerFn, type HttpOptions, type MultiOptions, type Mutation, type Plugins, type Query, type SocketOptions, type StreamHandler, type StreamUnsubscribe, type Subscription, type Transport, build_client, http, multi, ws };