UNPKG

jsonrpc-websocket-client

Version:
201 lines (155 loc) 4.59 kB
"use strict"; exports.__esModule = true; exports.default = exports.OPEN = exports.MESSAGE = exports.ConnectionError = exports.CONNECTING = exports.CLOSED = exports.AbortedConnection = void 0; var _fromEvent = _interopRequireDefault(require("promise-toolbox/fromEvent")); var _fromEvents = _interopRequireDefault(require("promise-toolbox/fromEvents")); var _try = _interopRequireDefault(require("promise-toolbox/try")); var _isomorphicWs = _interopRequireDefault(require("isomorphic-ws")); var _makeError = require("make-error"); var _events = require("events"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); class ConnectionError extends _makeError.BaseError {} exports.ConnectionError = ConnectionError; class AbortedConnection extends ConnectionError { constructor() { super("connection aborted"); } } exports.AbortedConnection = AbortedConnection; const CLOSED = "closed"; exports.CLOSED = CLOSED; const CONNECTING = "connecting"; exports.CONNECTING = CONNECTING; const MESSAGE = "message"; exports.MESSAGE = MESSAGE; const OPEN = "open"; exports.OPEN = OPEN; class WebSocketClient extends _events.EventEmitter { constructor(url, protocols, opts) { super(); if (opts && !url.startsWith("wss")) { delete opts.rejectUnauthorized; } this._opts = opts; this._protocols = protocols; this._url = url; this._protocol = null; this._socket = null; this._status = CLOSED; this._onClose = this._onClose.bind(this); } get protocol() { return this._protocol; } get status() { return this._status; } close() { return (0, _try.default)(() => { const status = this._status; if (status === CLOSED) { return; } const socket = this._socket; if (status === CONNECTING) { socket.abort = true; socket.close(); return; } const promise = (0, _fromEvent.default)(socket, "close"); socket.close(); return promise; }); } open(backoff) { if (!backoff) { return this._open(); } const iterator = backoff[Symbol.iterator](); let cancelled = false; const cancel = () => { cancelled = true; }; let error_; const attempt = () => { if (cancelled) { throw error_; } return this._open().catch(error => { let current; if (error instanceof AbortedConnection || (current = iterator.next()).done) { throw error; } const { value } = current; this.emit("scheduledAttempt", { cancel, delay: value }); error_ = error; return delay(current.value).then(attempt); }); }; const promise = attempt(); promise.cancel = cancel; return promise; } send(data) { this._assertStatus(OPEN); this._socket.send(data); } _assertNotStatus(notExpected) { if (this._status === notExpected) { throw new ConnectionError(`invalid status ${this._status}`); } } _assertStatus(expected) { if (this._status !== expected) { throw new ConnectionError(`invalid status ${this._status}, expected ${expected}`); } } _onClose() { const previous = this._status; this._socket = null; this._status = CLOSED; if (previous === OPEN) { this.emit(CLOSED); } } _open() { return (0, _try.default)(() => { this._assertStatus(CLOSED); this._status = CONNECTING; return (0, _try.default)(() => { const socket = this._socket = new _isomorphicWs.default(this._url, this._protocols, this._opts); return (0, _fromEvents.default)(socket, ["open"], ["close", "error"]).then(() => { socket.addEventListener("close", this._onClose); socket.addEventListener("error", error => { this.emit("error", error); }); socket.addEventListener("message", _ref => { let { data } = _ref; this.emit(MESSAGE, data); }); this._status = OPEN; this.emit(OPEN); }, _ref2 => { let [error] = _ref2; if (socket.abort) { throw new AbortedConnection(); } throw error; }); }).catch(error => { this._onClose(); throw error; }); }); } } exports.default = WebSocketClient; //# sourceMappingURL=websocket-client.js.map