UNPKG

@eclipse-ditto/ditto-javascript-client-node

Version:

Node.js(r) implementation of Eclipse Ditto JavaScript API.

148 lines 5.32 kB
"use strict"; /*! * Copyright (c) 2019 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ Object.defineProperty(exports, "__esModule", { value: true }); exports.NodeWebSocketBuilder = exports.NodeWebSocket = void 0; const auth_provider_1 = require("../../api/src/auth/auth-provider"); const WebSocket = require("ws"); /** * Converts a Map to a plain js object. * * @param aMap - the map to convert. * @return the plain js object. */ const mapToPlainObject = (aMap) => { const objects = [...aMap.entries()].map(([k, v]) => ({ [k]: v })); return Object.assign({}, ...objects); }; /** * NodeJs implementation of a web socket requester. */ class NodeWebSocket { constructor(webSocket, webSocketUrl, handler, options, reconnect = true) { this.webSocket = webSocket; this.webSocketUrl = webSocketUrl; this.handler = handler; this.options = options; this.connected = true; this.shouldReconnect = reconnect; this.setHandles(); } /** * Builds an instance of NodeWebSocket. * * @param url - The Url of the service. * @param handler - The handler that gets called for responses from the web socket. * @param authProviders - The auth providers to use. * @param agent - The proxy agent to use to establish the connection. * @param reconnect - Whether to automatically reconnect on connection loss. * @return a Promise for the web socket connection. */ static buildInstance(url, handler, authProviders, agent, reconnect = true) { return new Promise(resolve => { const [authenticatedUrl, authenticatedHeaders] = (0, auth_provider_1.authenticateWithUrlAndHeaders)(url, new Map(), authProviders); const plainHeaders = mapToPlainObject(authenticatedHeaders); const options = { agent: NodeWebSocket.getProxyAgentForProtocol(url, agent), rejectUnauthorized: false, headers: plainHeaders }; const plainUrl = authenticatedUrl.toString(); const webSocket = new WebSocket(plainUrl, options); webSocket.on('open', () => { resolve(new NodeWebSocket(webSocket, plainUrl, handler, options, reconnect)); }); }); } static getProxyAgentForProtocol(url, agent) { if ('wss' === url.protocol) { return agent.proxyAgent; } return agent.httpProxyAgent; } executeCommand(request) { this.webSocket.send(request); } close(code, reason) { this.shouldReconnect = false; if (this.connected) { this.webSocket.close(code, reason); } } /** * Reestablishes a failed web socket connection. * * @param retry - The amount of time to wait to reconnect. * @return a Promise for the reestablished web socket connection. */ reconnect(retry) { if (this.shouldReconnect) { return new Promise((resolve, reject) => { this.webSocket = new WebSocket(this.webSocketUrl, this.options); this.webSocket.on('open', () => { this.connected = true; this.setHandles(); resolve(this); }); setTimeout(() => { if (this.connected) { return; } if (retry <= 120000) { console.log('Reconnect failed! Trying again!'); resolve(this.reconnect(retry * 2)); } console.log('Reconnect failed!'); reject('Reconnect failed: Timed out'); }, retry); }); } else { return Promise.reject('Reconnect disabled'); } } /** * Sets up the handler so it receives events from the web socket. */ setHandles() { this.webSocket.on('message', data => { this.handler.handleInput(data.toString()); }); this.webSocket.on('close', () => { this.connected = false; this.handler.handleClose(Promise.resolve(this.reconnect(1000))); }); this.webSocket.on('error', event => { this.handler.handleError(event.toString()); }); } } exports.NodeWebSocket = NodeWebSocket; /** * Builder for the Node implementation of a web socket. */ class NodeWebSocketBuilder { constructor(agent) { this.agent = agent; } withHandler(handler, reconnect = true) { return NodeWebSocket.buildInstance(this.dittoUrl, handler, this.authProviders, this.agent, reconnect); } withConnectionDetails(url, authProviders) { this.dittoUrl = url; this.authProviders = authProviders; return this; } } exports.NodeWebSocketBuilder = NodeWebSocketBuilder; //# sourceMappingURL=node-websocket.js.map