UNPKG

@pamlight/admin

Version:

The library for syncing data changes to multiple devices from your database

226 lines (225 loc) 12.2 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var socket_io_client_1 = require("socket.io-client"); var config_1 = require("./config"); var shared_1 = require("../shared"); var services_1 = require("../services"); var lodash_1 = require("lodash"); var ConnectionStatusTypes; (function (ConnectionStatusTypes) { ConnectionStatusTypes[ConnectionStatusTypes["IDLE"] = 1] = "IDLE"; ConnectionStatusTypes[ConnectionStatusTypes["PROGRESS"] = 2] = "PROGRESS"; ConnectionStatusTypes[ConnectionStatusTypes["SUCCESS"] = 3] = "SUCCESS"; ConnectionStatusTypes[ConnectionStatusTypes["FAILURE"] = 4] = "FAILURE"; })(ConnectionStatusTypes || (ConnectionStatusTypes = {})); var ServerSocketIOClient = /** @class */ (function () { function ServerSocketIOClient(cred) { this.isReconnection = false; this.connectionStatus = ConnectionStatusTypes.IDLE; this.credentials = cred; this.production = true; } ServerSocketIOClient.prototype.enableDevMode = function () { this.production = false; }; ServerSocketIOClient.prototype.request = function (payload) { var _this = this; return new Promise(function (resolve, reject) { payload.responseId = payload.responseId || Date.now() + "_" + services_1.getRandomString(40); // listens to response _this.socket.once(payload.responseId, function (res) { if (res.error) { reject(res.error); } else { resolve(res.data); } }); // dispatch action _this.socket.emit(shared_1.PamlightConstants.ADMIN_SOCKET_API_ACTION, payload); }); }; ServerSocketIOClient.prototype.toggleAppState = function (status, readRoutes, writeRoutes) { var _this = this; return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { var options, e_1; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: options = { action: status ? shared_1.PamlightAdminActionTypes.START_APP : shared_1.PamlightAdminActionTypes.STOP_APP, body: { readRoutes: readRoutes, writeRoutes: writeRoutes } }; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, this.request(options)]; case 2: _a.sent(); if (status) { // for reads this.socket.on(shared_1.PamlightConstants.ADMIN_SOCKET_GET_QUERY, function (params) { var route = lodash_1.find(_this._routes.reads, { routeId: params.routeId }); if (route) { try { var query = route.queryFn(params.body); _this.socket.emit(params.responseId, { data: query }); } catch (e) { _this.socket.emit(params.responseId, { error: { message: e ? e.message : 'Unknown error' } }); } } else { _this.socket.emit(params.responseId, { error: { message: 'Invalid route request' } }); } }); // for writes this.socket.on(shared_1.PamlightConstants.ADMIN_SOCKET_WRITE_CONFIG, function (params) { return __awaiter(_this, void 0, void 0, function () { var route, query, e_2; return __generator(this, function (_a) { switch (_a.label) { case 0: route = lodash_1.find(this._routes.writes, { routeId: params.routeId }); if (!route) return [3 /*break*/, 5]; _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, route.docFn(params.body.clientData, params.body.parentData)]; case 2: query = _a.sent(); this.socket.emit(params.responseId, { data: query }); return [3 /*break*/, 4]; case 3: e_2 = _a.sent(); this.socket.emit(params.responseId, { error: { message: e_2 ? e_2.message : 'Unknown error' } }); return [3 /*break*/, 4]; case 4: return [3 /*break*/, 6]; case 5: this.socket.emit(params.responseId, { error: { message: 'Invalid write route request' } }); _a.label = 6; case 6: return [2 /*return*/]; } }); }); }); } else { this.socket.off(shared_1.PamlightConstants.ADMIN_SOCKET_GET_QUERY); this.socket.off(shared_1.PamlightConstants.ADMIN_SOCKET_WRITE_CONFIG); } resolve(); return [3 /*break*/, 4]; case 3: e_1 = _a.sent(); reject(e_1); return [3 /*break*/, 4]; case 4: this._routes = { reads: readRoutes, writes: writeRoutes }; return [2 /*return*/]; } }); }); }); }; ServerSocketIOClient.prototype.handleSocketConnection = function (cb) { var _this = this; this.connectionStatus = ConnectionStatusTypes.PROGRESS; this.socket.once('connect', function () { _this.socket.on(shared_1.PamlightConstants.ADMIN_SOCKET_VERIFIED, function () { _this.connectionStatus = ConnectionStatusTypes.SUCCESS; if (_this.isReconnection) { _this.toggleAppState(!!_this._routes, _this._routes.reads, _this._routes.writes).then(function () { }); } else if (cb) { cb(); } _this.isReconnection = false; }); _this.socket.on(shared_1.PamlightConstants.ADMIN_SOCKET_VERIFY_ERROR, function (err) { _this.connectionStatus = ConnectionStatusTypes.FAILURE; throw Error(err); }); _this.socket.emit(shared_1.PamlightConstants.ADMIN_VERIFY_SOCKET, _this.credentials); }); this.socket.once('disconnect', function () { _this.isReconnection = true; _this.handleSocketConnection(); }); }; ServerSocketIOClient.prototype.ensureConnection = function () { var _this = this; switch (this.connectionStatus) { case ConnectionStatusTypes.IDLE: { // initialize connection return new Promise(function (resolve) { var opts = { reconnection: true, query: { isAdmin: 'true' } }; _this.socket = socket_io_client_1.connect(_this.production ? config_1.sdkConfig.sdkDomain : 'http://localhost:8002', opts); _this.handleSocketConnection(resolve); }); } case ConnectionStatusTypes.PROGRESS: { return new Promise(function (resolve, reject) { var counter = 0; var interval = setInterval(function () { counter++; // max 10 seconds is enough for progress state if (counter >= 20) { _this.connectionStatus = ConnectionStatusTypes.FAILURE; } if (_this.connectionStatus !== ConnectionStatusTypes.PROGRESS) { clearInterval(interval); _this.ensureConnection().then(resolve).catch(reject); } }, 500); }); } case ConnectionStatusTypes.SUCCESS: { return Promise.resolve(); } default: { return Promise.reject('Unable to establish connection to Pamlight service'); } } }; return ServerSocketIOClient; }()); exports.ServerSocketIOClient = ServerSocketIOClient;