/**
* Base-class for any MHub client.
*
* Derived classes add actual transport logic to connect to
* e.g. a Node.JS websocket API, a browser version, or a version
* specifically for testing.
*/
///
import * as events from "events";
import Message, { Headers } from "./message";
import * as protocol from "./protocol";
/**
* Options to be passed to constructor.
*/
export interface BaseClientOptions {
/**
* Number of milliseconds of idleness (i.e. no data
* transmitted or received) before sending a ping to
* the server. If it doesn't respond within that same
* interval, the connection is closed with an error.
* Use 0 to disable.
*/
keepalive?: number;
}
export declare const defaultBaseClientOptions: BaseClientOptions;
/**
* Interface for coupling of MHub client to transport protocol
* such as a WebSocket or raw TCP stream.
*
* Events expected from the interface:
* @event open() Emitted when connection was established.
* @event close() Emitted when connection was closed.
* @event error(e: Error) Emitted when there was a connection, server or protocol error.
* @event message(data: protocol.Response) Emitted when a message (object) was received.
* Note: object needs to be deserialized already. Don't pass a string.
*/
export interface Connection extends events.EventEmitter {
/**
* Transmit data object.
* @return Promise that resolves when transmit is accepted (i.e. not necessarily
* arrived at other side, can be e.g. queued).
*/
send(data: protocol.Command): Promise;
/**
* Gracefully close connection, i.e. allow pending transmissions
* to be completed.
* @return Promise that resolves when connection is succesfully closed.
*/
close(): Promise;
/**
* Forcefully close connection.
* @return Promise that resolves when connection is succesfully closed.
*/
terminate(): Promise;
}
export interface BaseClient {
/**
* Attach event handler for connection established event.
*/
on(event: "open", listener: () => void): this;
/**
* Attache event handler for connection closed event.
*/
on(event: "close", listener: () => void): this;
/**
* Attach event handler for error event.
*/
on(event: "error", listener: (error: Error) => void): this;
/**
* Attach event handler for receiving a new message.
* If no explicit subscriptionId was passed during subscribe, string "default" is used.
*/
on(event: "message", listener: (message: Message, subscriptionId: string) => void): this;
}
/**
* Abstract MHub client.
*
* Implements MHub client protocol, but does not implement the transport layer
* such as WebSocket, raw TCP, etc.
*
* @event open() Emitted when connection was established.
* @event close() Emitted when connection was closed.
* @event error(e: Error) Emitted when there was a connection, server or protocol error.
* @event message(m: Message, subscriptionId: string) Emitted when message was received (due to subscription).
*/
export declare abstract class BaseClient extends events.EventEmitter {
private _options;
private _socket;
private _transactions;
private _seqNo;
private _idleTimer;
private _connecting;
private _closing;
private _socketConstructor;
private _connected;
/**
* Create new BaseClient.
* @param options Protocol settings
*/
constructor(socketConstructor: () => Connection, options?: BaseClientOptions);
/**
* Connect to the MServer.
* If connection is already active or pending, this is a no-op.
* Note: a connection is already initiated when the constructor is called.
*/
connect(): Promise;
/**
* Disconnect from MServer.
* Pending requests will be rejected with an error.
* If already disconnected, this becomes a no-op.
*
* Note: any existing subscriptions will be lost.
*
* Optionally pass an error to signal abrupt failure,
* forcefully terminating the connection.
* The same error will be used to reject any pending
* requests.
* @param error (optional) Error to emit, reject transactions with, and
* forcefully close connection.
*/
close(error?: Error): Promise;
/**
* Login to server using username/password.
*
* Warning: the username and password are sent in plain text.
* Only use this on secure connections such as wss://.
*
* @param username Username.
* @param password Password.
*/
login(username: string, password: string): Promise;
/**
* Subscribe to a node.
*
* Emits the "message" event when a message is received for this subscription.
* First argument of that event is the message, second is the subscription id
* (or "default" if no id was given).
*
* @param nodeName Name of node in MServer to subscribe to (e.g. "default")
* @param pattern Optional pattern glob (e.g. "/some/foo*"). Matches all topics if omitted.
* @param id Optional subscription ID sent back with all matching messages
*/
subscribe(nodeName: string, pattern?: string, id?: string): Promise;
/**
* Unsubscribe `pattern` (or all if omitted) from given `node` and `id`.
* Subscription id "default" is used if `id` is omitted.
*
* @param nodeName Name of node in MServer to unsubscribe from (e.g. "default")
* @param pattern Optional pattern glob (e.g. "/some/foo*"). Unsubscribes all (on `node` and `id`)
* if omitted.
* @param id Subscription ID, or "default"
*/
unsubscribe(nodeName: string, pattern?: string, id?: string): Promise;
/**
* Publish message to a node.
*
* @param nodeName Name of node in MServer to publish to (e.g. "default")
* @param topic Message topic
* @param data Message data
* @param headers Message headers
*/
publish(nodeName: string, topic: string, data?: any, headers?: Headers): Promise;
/**
* Publish message to a node.
*
* @param nodeName Name of node in MServer to publish to (e.g. "default")
* @param message Message object
*/
publish(nodeName: string, message: Message): Promise;
/**
* Ping server.
* Mostly used to check whether connection is still alive.
* Note that the client will automatically send pings in the
* absence of other communication, so there should be no need to
* manually send pings.
*
* @param timeout (optional) Timeout in milliseconds before rejecting
* the promise with an error, or infinite if not given.
*/
ping(timeout?: number): Promise;
/**
* Defer calling of events to next tick, to prevent e.g. errors
* in handlers from interfering with client state, and to
* prevent hard-to-debug async weirdness.
*/
private _asyncEmit;
private _handleSocketOpen;
private _handleSocketError;
private _handleSocketClose;
private _handleSocketMessage;
/**
* (Re-)start idle timer and send pings when connection is idle
* for too long.
*/
private _restartIdleTimer;
private _stopIdleTimer;
private _handleIdleTimeout;
private _send;
/**
* Resolve pending transaction promise (either fulfill or reject with error).
* Returns true when the given sequence number was actually found.
*/
private _release;
/**
* Compute next available sequence number.
* Throws an error when no sequence number is available (too many
* pending transactions).
*/
private _nextSeq;
}
export default BaseClient;