@ch1/rpc
Version:
JavaScript Remote Procedure Call (RPC)
203 lines (202 loc) • 5.52 kB
TypeScript
/**
* Project interfaces
*/
/**
* Generic Dictionary
*/
export interface Dictionary<T> {
[key: string]: T;
}
/**
* Where `T` is the type of the complete interface you wish to expose
*/
export interface Remote<T> extends Dictionary<Function | Object> {
}
/**
* Specify async types on the remote
*/
export interface RemoteDesc extends Dictionary<number | Dictionary<number>> {
}
/**
* Async style function union
*/
export declare type RPCAsync<T> = RPCDefer<T> | RPCNodeCallback<T> | RPCNodeEventInternal | RPCNotify<T>;
/**
* Ensures correct async response
*/
export interface RPCAsyncContainer<T> {
type: number;
async: RPCAsync<T> | Dictionary<RPCNodeEventInternal>;
}
export interface RPCNodeEventInternal {
listener: Function;
uid: string;
}
export declare type RPCAsyncContainerDictionary = Dictionary<RPCAsyncContainer<any>>;
export interface RPCNodeCallback<T> {
(error: Error, param?: T): any;
(error: Error, ...rest: any[]): any;
}
/**
* tl;dr these are used in `RemoteDesc` to describe given API functions
*
* js-rpc uses these strings to identify types of "real world" functions that
* it can interface with.
*
* These types are actually used by consumers of the library since they are the
* specific strings enforced by `RemoteDesc`
*
* - ### "nodeCallback"
* nodeCallback refers to JavaScript callback functions that strictly follow
* two rules:
*
* - the _last_ parameter passed to a function is the callback
* - a "Nullable Error" is the _first_ parameter passed to the callback
*
* Example:
*
* ```js
* function add(a, b, callback) {
* setTimeout(() => {
* if (isNumber(a) && (isNumber(b)) {
* callback(null, result);
* } else {
* callback(new TypeError('add is for numbers'));
* }
* }, 0);
* }
*
* add(1, 2, (err, result) => expect(result).toBe(3);
* add(1, 2, (err, result) => expect(error).toBeFalsey();
* add('1', 2), (erro, result) => expect(error instanceof Error).toBe(true);
* ```
*
* - ### "nodeEvent"/"nodeEventInternal"
* nodeEvents are a _limited_ interface to *
* [node EventEmitters](https://nodejs.org/api/events.html "docs")
*
* - ### "observable"
* In this case observables refer to
* [RxJS5](https://github.com/ReactiveX/rxjs, "RxJS")
*
* - ### "promise"
* promises are es6 promises or any A+ promises that implement `.then` and
* `.catch` along with the global `Promise`
*/
export declare const RPCAsyncType: {
observable: number;
promise: number;
};
export interface RPCDefer<T> {
resolve: (any: any) => any;
reject: (any: any) => any;
promise: Promise<T>;
}
/**
* The Different Types of RPC Events
*/
export declare const RPCEventType: Readonly<{
ack: number;
create: number;
createReturn: number;
destroy: number;
destroyReturn: number;
fnReturn: number;
invoke: number;
promise: number;
subscribe: number;
unsubscribe: number;
}>;
export interface RPCEmit {
(message: string, payload: RPCEvent): any;
}
export interface ConfiguredRPCEmit {
(payload: RPCEvent): any;
}
export interface RPCNotify<T> {
(param: T, ...args: any[]): any;
(...args: any[]): any;
}
export interface RPCObservable<T> {
subscribe: (next: (param: T) => any, onError: (error: Error) => any, onComplete: () => any) => () => void;
}
export interface RPCOn {
(message: string, callback: (payload: RPCEvent) => void): () => void;
}
export interface ConfiguredRPCOn {
(callback: (payload: RPCEvent) => any): () => any;
}
export interface RPCOptions {
defaultAsyncType?: number;
defaultCreateRetry?: number;
defaultCreateRetryCurve?: number;
defaultCreateWait?: number;
enableStackTrace?: boolean;
maxAckDelay?: number;
useAcks?: Dictionary<number>;
}
export interface FunctionalState {
responders: RPCEventRegistry;
successHandlers: RPCEventRegistry;
errorHandlers: RPCEventRegistry;
}
export interface RPCAbstractConfig extends RPCOptions {
message?: string;
remote?: Object;
emit?: ConfiguredRPCEmit;
on?: ConfiguredRPCOn;
functionalState?: FunctionalState;
callbacks?: RPCAsyncContainerDictionary;
uid?: () => string;
}
export interface RPCConfig extends RPCAbstractConfig {
emit: ConfiguredRPCEmit;
on: ConfiguredRPCOn;
}
export declare type RPCEventRegistry = {
[key: number]: (...args: any[]) => any;
};
export declare type RPCAsyncRegistry = {
[key: number]: (...args: any[]) => any;
};
export declare type RPCRegister = (key: number, value: (...args: any[]) => any) => void;
/**
* JavaScript error with a code number
*/
export interface CodedError extends Error {
code?: number;
stack?: string;
}
/**
* Serializable Error
*/
export interface RPCError {
code?: number;
message: string;
stack?: string;
type?: string;
}
export interface RPCInvocationPayload {
fn: string;
args: any[];
}
export interface RPCErrorPayload {
error: RPCError;
}
export interface RPCReturnPayload {
result: any[];
}
export declare type RPCPayload = RPCInvocationPayload | RPCReturnPayload | RPCErrorPayload;
export interface RPCEvent {
type: number;
payload: RPCPayload;
uid: string;
useAcks?: boolean;
}
export interface RPC<T> {
config: RPCConfig;
destroy: (reason?: string) => Promise<void>;
onDestroy: (callback: (reason?: string) => any) => () => void;
ready: Promise<void>;
remote: T;
}