happypandax-client
Version:
A javascript client library for communicating with HappyPanda X servers
941 lines (940 loc) • 37.9 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(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 (g && (g = 0, op[0] && (_ = 0)), _) 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 });
exports.Client = exports.finalize = exports.ServerDisconnectError = exports.ConnectionError = exports.TimeoutError = exports.ClientError = exports.AuthMissingCredentials = exports.AuthRequiredError = exports.AuthWrongCredentialsError = exports.AuthError = exports.ServerError = exports.log = exports.exception_codes = void 0;
var net = __importStar(require("net"));
var stream_1 = require("stream");
var ts_custom_error_1 = require("ts-custom-error");
var msgpack_1 = require("@msgpack/msgpack");
var encoding = "utf8";
var postfix = Buffer.from("<EOF>", encoding);
exports.exception_codes = {
AuthRequiredError: 407,
AuthWrongCredentialsError: 411,
AuthMissingCredentials: 412,
ServerError: 400,
AuthError: 406,
ClientError: 500,
ConnectionError: 501,
ServerDisconnectError: 502,
};
/**
* The logger
* @group Logging
*/
exports.log = {
/**
* Enable or disable logging
*/
enabled: true,
/**
* Can be set to a custom logger that will be used instead of console
*/
logger: undefined,
d: function (msg) {
if (!this.enabled)
return;
this.logger ? this.logger.debug(msg) : console.debug(msg);
},
i: function (msg) {
if (!this.enabled)
return;
this.logger ? this.logger.info(msg) : console.info(msg);
},
w: function (msg) {
if (!this.enabled)
return;
this.logger ? this.logger.warning(msg) : console.warn(msg);
},
e: function (msg) {
if (!this.enabled)
return;
this.logger ? this.logger.error(msg) : console.error(msg);
},
};
var EError = /** @class */ (function (_super) {
__extends(EError, _super);
function EError(message) {
var _this = _super.call(this, message) || this;
_this.code = exports.exception_codes[_this.name];
Object.defineProperty(_this, "name", { value: "EError" });
return _this;
}
return EError;
}(ts_custom_error_1.CustomError));
/**
* Base class for all server errors
* @extends Error
* @category Errors
*/
var ServerError = /** @class */ (function (_super) {
__extends(ServerError, _super);
function ServerError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "ServerError" });
return _this;
}
return ServerError;
}(EError));
exports.ServerError = ServerError;
/**
* Base class for all authentication errors
* @extends ServerError
* @category Errors
*/
var AuthError = /** @class */ (function (_super) {
__extends(AuthError, _super);
function AuthError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "AuthError" });
return _this;
}
return AuthError;
}(ServerError));
exports.AuthError = AuthError;
/**
* Wrong credentials error
* @extends AuthError
* @category Errors
*/
var AuthWrongCredentialsError = /** @class */ (function (_super) {
__extends(AuthWrongCredentialsError, _super);
function AuthWrongCredentialsError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "AuthWrongCredentialsError" });
return _this;
}
return AuthWrongCredentialsError;
}(AuthError));
exports.AuthWrongCredentialsError = AuthWrongCredentialsError;
/**
* Authentication required error
* @extends AuthError
* @category Errors
*/
var AuthRequiredError = /** @class */ (function (_super) {
__extends(AuthRequiredError, _super);
function AuthRequiredError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "AuthRequiredError" });
return _this;
}
return AuthRequiredError;
}(AuthError));
exports.AuthRequiredError = AuthRequiredError;
/**
* Missing credentials error
* @extends AuthError
* @category Errors
*/
var AuthMissingCredentials = /** @class */ (function (_super) {
__extends(AuthMissingCredentials, _super);
function AuthMissingCredentials(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "AuthMissingCredentials" });
return _this;
}
return AuthMissingCredentials;
}(AuthError));
exports.AuthMissingCredentials = AuthMissingCredentials;
/**
* Base class for all client errors
* @extends ServerError
* @category Errors
*/
var ClientError = /** @class */ (function (_super) {
__extends(ClientError, _super);
function ClientError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "ClientError" });
return _this;
}
return ClientError;
}(ServerError));
exports.ClientError = ClientError;
/**
* Timeout error
* @extends ClientError
* @category Errors
*/
var TimeoutError = /** @class */ (function (_super) {
__extends(TimeoutError, _super);
function TimeoutError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "TimoutError" });
return _this;
}
return TimeoutError;
}(ClientError));
exports.TimeoutError = TimeoutError;
/**
* Base class for all connection errors
* @extends ClientError
* @category Errors
*/
var ConnectionError = /** @class */ (function (_super) {
__extends(ConnectionError, _super);
function ConnectionError(message) {
var _this = _super.call(this, message) || this;
Object.defineProperty(_this, "name", { value: "ConnectionError" });
return _this;
}
return ConnectionError;
}(ClientError));
exports.ConnectionError = ConnectionError;
/**
* Server disconnect error
* @extends ConnectionError
* @category Errors
*/
var ServerDisconnectError = /** @class */ (function (_super) {
__extends(ServerDisconnectError, _super);
function ServerDisconnectError() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ServerDisconnectError;
}(ConnectionError));
exports.ServerDisconnectError = ServerDisconnectError;
;
/**
* A helper function that will wrap your message up like this:
* ```
* msg = {
* 'session': session_id,
* 'name': name,
* 'command': command, <--- your command is put here
* 'data': data, # <--- your message is put here
* }
* ```
* @param {ServerCommand} command - message to wrap
* @param {AnyJson} data - message to wrap
* @param {string} session_id - optional, session id
* @param {string} name - name of client
* @param {AnyJson} msg_id - optional message id
* @return {ServerMsg}
*/
function finalize(command, data, session_id, name, msg_id) {
session_id = session_id || "";
var msg = {
__id__: msg_id,
command: command,
session: session_id,
name: name ? name : "js-client",
data: data,
};
return msg;
}
exports.finalize = finalize;
var HPXTransform = /** @class */ (function (_super) {
__extends(HPXTransform, _super);
function HPXTransform(client_name, options) {
var _this = _super.call(this, options) || this;
_this._buffer = Buffer.from("", encoding);
_this._client_name = client_name;
return _this;
}
HPXTransform.prototype._end_of_msg = function (buffer) {
var remaining_buffer = buffer;
var idx = buffer.indexOf(postfix);
var eof = false;
var data = Buffer.from("", encoding);
if (idx !== -1) {
data = buffer.slice(0, idx);
remaining_buffer = buffer.slice(idx + postfix.length);
eof = true;
}
return { data: data, remaining_buffer: remaining_buffer, eof: eof };
};
HPXTransform.prototype._transform = function (chunk, enc, callback) {
var err = null;
if (!chunk.length)
err = new ServerDisconnectError("Server disconnected for client '" + this._client_name + "'");
this._buffer = Buffer.concat([this._buffer, chunk]);
var eof = true;
while (eof && err == null) {
var _a = this._end_of_msg(this._buffer), data = _a.data, remaining_buffer = _a.remaining_buffer, eof_ = _a.eof;
eof = eof_;
this._buffer = remaining_buffer;
if (eof && data.length) {
this.push(data);
}
}
callback(err);
};
return HPXTransform;
}(stream_1.Transform));
/**
* A class representing a HappyPanda X client
*/
var Client = /** @class */ (function () {
/**
* @param {Object} params - optional params
* @param [params.name=js-client] {string} - name of client
* @param [params.host] {string} - server host
* @param [params.port] {integer} - server port
* @param [params.user] {string} - username
* @param [params.password] {string} - password
* @param [params.session_id] {string} - a server session id
* @param [params.timeout] {integer} - connection timeout
*/
function Client(_a) {
var name = _a.name, host = _a.host, port = _a.port, session_id = _a.session_id, timeout = _a.timeout, user = _a.user, password = _a.password;
this.name = name || "js-client";
this.endpoint = [host || "localhost", port || 7007]; // [host, port]
this._alive = false;
this._disconnected = false; // specifically used by _on_disconnect
this._ready = false;
this.session = session_id || "";
this.resolve_IPV4_localhost = true; // see https://github.com/nodejs/node/issues/40702
this.version = null;
this.guest_allowed = false;
this._id_counter = 0;
this._last_user = user !== null && user !== void 0 ? user : "";
this._last_pass = password !== null && password !== void 0 ? password : "";
this._stream = new HPXTransform(this.name, {
defaultEncoding: encoding,
});
this._stream.on("data", this._recv.bind(this));
this._timeout = timeout || 5000;
this._sock = null;
// lol
this._encoder = new msgpack_1.Encoder(undefined, undefined, undefined, undefined, undefined, undefined, true);
this._decoder = new msgpack_1.Decoder();
this.__data_promises = {};
this.__data_promises_order = [];
this._connecting = false;
this._create_socket();
}
Client.prototype._create_socket = function () {
var _this = this;
this._sock = new net.Socket();
this._sock.setTimeout(this.timeout, this._on_timeout.bind(this));
this._sock.on("data", function (data) { return _this._stream.write(data); });
this._sock.on("connect", this._on_connect.bind(this));
this._sock.on("close", this._on_disconnect.bind(this));
this._sock.on("end", this._on_disconnect.bind(this));
this._sock.on("error", this._on_error.bind(this));
};
/**
* Add a listener to the underlying socket
* @param {string} event - event name
* @param {Function} listener - listener function
* @return {Client}
*/
Client.prototype.on = function (event, listener) {
var _a;
(_a = this._sock) === null || _a === void 0 ? void 0 : _a.on(event, listener);
return this;
};
/**
* Add a listener to the underlying socket
* @param {string} event - event name
* @param {Function} listener - listener function
* @return {Client}
*/
Client.prototype.once = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
(_a = this._sock) === null || _a === void 0 ? void 0 : _a.once.apply(_a, args);
return this;
};
/**
* Remove a listener from the underlying socket
* @param {string} event - event name
* @param {Function} listener - listener function
* @return {Client}
*/
Client.prototype.off = function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
(_a = this._sock) === null || _a === void 0 ? void 0 : _a.off.apply(_a, args);
return this;
};
/**
* Check if server is still alive
* @return {boolean}
*/
Client.prototype.alive = function () {
var _a;
return this._alive && !((_a = this._sock) === null || _a === void 0 ? void 0 : _a.destroyed);
};
/**
* Check if client is ready to exchange messages with server
* @return {boolean}
*/
Client.prototype.ready = function () {
return this._ready;
};
Object.defineProperty(Client.prototype, "timeout", {
/**
* Get the timeout value
* @return {number}
*/
get: function () {
return this._timeout;
},
set: function (t) {
var _a;
this._timeout = t;
(_a = this._sock) === null || _a === void 0 ? void 0 : _a.setTimeout(this._timeout, this._on_timeout.bind(this));
},
enumerable: false,
configurable: true
});
Object.defineProperty(Client.prototype, "_connect_msg_id", {
get: function () {
return this.name + "_connect";
},
enumerable: false,
configurable: true
});
Object.defineProperty(Client.prototype, "_close_msg_id", {
get: function () {
return this.name + "_close";
},
enumerable: false,
configurable: true
});
Client.prototype._next_id = function () {
this._id_counter = (this._id_counter + 1) % 99999;
return this.name + "_msg_" + this._id_counter;
};
Client.prototype._add_data_promise = function (msg_id, resolve, reject) {
this.__data_promises[msg_id] = [resolve, reject];
this.__data_promises_order.push(msg_id);
};
Client.prototype._get_data_promise = function (msg_id) {
if (!msg_id)
return;
var v = this.__data_promises[msg_id];
if (v) {
delete this.__data_promises[msg_id];
var idx = this.__data_promises_order.indexOf(msg_id);
if (idx > -1) {
this.__data_promises_order.splice(idx, 1);
}
}
return v;
};
Client.prototype._get_earliest_data_promise = function () {
var msg_id = this.__data_promises_order.shift();
if (msg_id) {
var v = this.__data_promises[msg_id];
if (v) {
delete this.__data_promises[msg_id];
}
return v;
}
};
Client.prototype._server_info = function (msg) {
if (msg) {
var serv_data = msg === null || msg === void 0 ? void 0 : msg.data;
if (serv_data && (serv_data === null || serv_data === void 0 ? void 0 : serv_data.version)) {
this.guest_allowed = serv_data.guest_allowed || false;
this.version = serv_data.version;
this._ready = true;
}
}
};
/**
* Set server address
* @param {string} host - server host
* @param {integer} port - server port
*/
Client.prototype.set_endpoint = function (host, port) {
this.endpoint = [host, port];
};
/**
* Perfom a handshake with the HPX server
* @category async
* @param {object} params - optinal params
* @param [params.user] {string} - username
* @param [params.password] {integer} - password
* @param [params.ignore_err] {boolean} - ignore error
* @throws {AuthError}
* @returns {Promise}
*/
Client.prototype.handshake = function (params) {
return __awaiter(this, void 0, void 0, function () {
var user, password, ignore_err, d, data, serv_error, serv_data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
user = params.user;
password = params.password;
if (user === undefined) {
user = this._last_user;
password = this._last_pass;
}
ignore_err = params.ignore_err;
if (!this.alive()) return [3 /*break*/, 2];
if (password === undefined)
password = null;
if (user) {
this._last_user = user;
this._last_pass = password;
}
d = {};
if (user) {
d.user = user;
d.password = password;
}
exports.log.d("Client '".concat(this.name, "' handshaking server at ").concat(JSON.stringify(this.endpoint)));
return [4 /*yield*/, this.send_raw(finalize("handshake", d, undefined, this.name))];
case 1:
data = _a.sent();
if (!ignore_err && data) {
serv_error = data.error;
if (serv_error) {
if (serv_error.code === exports.exception_codes["AuthWrongCredentialsError"])
throw new AuthWrongCredentialsError(serv_error.msg);
else if (serv_error.code === exports.exception_codes["AuthRequiredError"])
throw new AuthRequiredError(serv_error.msg);
else if (serv_error.code === exports.exception_codes["AuthMissingCredentials"])
throw new AuthMissingCredentials(serv_error.msg);
else
throw new AuthError(serv_error.code.toString() + ": " + serv_error.msg);
}
}
serv_data = data.data;
if (serv_data === "Authenticated") {
this.session = data.session;
return [2 /*return*/, true];
}
_a.label = 2;
case 2: return [2 /*return*/, false];
}
});
});
};
/**
* Forces client to request a new handshake, but doesn't invalidate previous session
* @category async
* @returns {Promise}
*/
Client.prototype.request_auth = function () {
return __awaiter(this, void 0, void 0, function () {
var data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send_raw(finalize("requestauth", null, undefined, this.name))];
case 1:
data = _a.sent();
this._server_info(data);
this.session = "";
return [2 /*return*/];
}
});
});
};
/**
* Logout and invalidates the session
* @category async
* @returns {Promise}
*/
Client.prototype.drop_auth = function () {
return __awaiter(this, void 0, void 0, function () {
var data;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send_raw(finalize("dropauth", null, this.session, this.name))];
case 1:
data = _a.sent();
this._server_info(data);
this.session = "";
return [2 /*return*/];
}
});
});
};
/**
* Send the serverquit command
* @category async
* @returns {Promise}
*/
Client.prototype.server_quit = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send_raw(finalize("serverquit", null, this.session, this.name))];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Send the serverrestart command
* @category async
* @returns {Promise}
*/
Client.prototype.server_restart = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send_raw(finalize("serverrestart", null, this.session, this.name))];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Call a single function, this is even more of a shortcut than send
* @category async
* @param {ClientMsg<'call'>['data']} data - data
* @returns {Promise}
*/
Client.prototype.call = function (data) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send('call', data)];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Call a single function, this is even more of a shortcut than send
* @category async
* @param {string} fname - function name
* @param [args] {object} - function arguments
* @returns {Promise}
*/
Client.prototype.call_function = function (fname, args) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.send('call', [__assign({ fname: fname }, args)])];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Check if the client is still connected to the server
* @return {boolean}
*/
Client.prototype.is_connected = function () {
return this.alive();
};
/**
* Connect to HPX server
* @category async
* @param {object} params - optional params
* @param [params.host] {string} - server host
* @param [params.port] {integer} - server port
* @returns {Promise}
*/
Client.prototype.connect = function (params) {
return __awaiter(this, void 0, void 0, function () {
var host, port, p;
var _this = this;
return __generator(this, function (_a) {
host = params === null || params === void 0 ? void 0 : params.host;
port = params === null || params === void 0 ? void 0 : params.port;
p = new Promise(function (resolve, reject) {
var _a, _b;
if (!_this._alive && !_this._connecting) {
var endpoint = _this.endpoint;
if (host !== undefined)
endpoint[0] = host;
if (port !== undefined)
endpoint[1] = port;
exports.log.d("Client '".concat(_this.name, "' connecting to server at: ").concat(JSON.stringify(endpoint)));
_this._connecting = true;
_this._disconnected = false;
_this._add_data_promise(_this._connect_msg_id, resolve, reject);
var h = endpoint[0];
if (_this.resolve_IPV4_localhost) {
if (h === "localhost")
h = "127.0.0.1";
}
if ((_a = _this._sock) === null || _a === void 0 ? void 0 : _a.destroyed) {
_this._create_socket();
}
(_b = _this._sock) === null || _b === void 0 ? void 0 : _b.connect(endpoint[1], h);
_this.endpoint = endpoint;
}
else
reject(Error("Client '".concat(_this.name, "' already connected or trying to connect")));
});
return [2 /*return*/, p];
});
});
};
Client.prototype._on_timeout = function () {
var _a;
this._connecting = false;
var err = new TimeoutError("timeout");
if (!this._ready) {
this._disconnect();
(_a = this._sock) === null || _a === void 0 ? void 0 : _a.destroy(err);
}
exports.log.e("Client '".concat(this.name, "' timed out after ").concat(this.timeout, "ms"));
var connect_p = this._get_data_promise(this._connect_msg_id);
if (connect_p) {
return connect_p[1](err);
}
var close_p = this._get_data_promise(this._close_msg_id);
if (close_p) {
return close_p[1](err);
}
var p = this._get_earliest_data_promise();
if (p) {
return p[1](err);
}
};
Client.prototype._on_connect = function () {
this._connecting = false;
this._alive = true;
exports.log.d("Client '".concat(this.name, "' successfully connected to server at: ").concat(JSON.stringify(this.endpoint)));
};
Client.prototype._on_error = function (error) {
this._connecting = false;
this._disconnect();
exports.log.e("An error occured in client '".concat(this.name, "': ").concat(error.message));
var connect_p = this._get_data_promise(this._connect_msg_id);
if (connect_p) {
return connect_p[1](error);
}
var p = this._get_earliest_data_promise();
if (p) {
return p[1](error);
}
};
Client.prototype._on_disconnect = function () {
if (this._disconnected) {
return;
}
exports.log.d("Client '".concat(this.name, "' disconnected from server at: ").concat(JSON.stringify(this.endpoint)));
this._disconnect();
var p = this._get_data_promise(this._close_msg_id);
if (p) {
p[0]();
}
};
Client.prototype._disconnect = function () {
this._alive = false;
this._disconnected = true;
this.session = "";
this._ready = false;
};
/**
* Like {@link send_raw}, but as a convenience, this method will wrap your message into the required message structure HPX expects and automatically sets the session and name
* @category async
* @param {JsonMap} data - the data part of the message
* @param {ServerCommand} command - the command, defaults to 'call'
* @returns {Promise}
* @fullfil {Object} - message from server
*/
Client.prototype.send = function (command, data) {
return __awaiter(this, void 0, void 0, function () {
var msg_id;
return __generator(this, function (_a) {
msg_id = this._next_id();
return [2 /*return*/, this._send(finalize(command, data, this.session, this.name, msg_id), msg_id)];
});
});
};
/**
* Send json-compatible Object to server. Receive json-compatible Object from server.
*
* Note that this method will not modify your message and expects you to add the name and session yourself. See the {@link finalize} function.
* @category async
* @param {Object} msg - message to send to the server
* @returns {Promise}
* @fullfil {Object} - message from server
*/
Client.prototype.send_raw = function (msg) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (!msg.__id__) {
msg.__id__ = this._next_id();
}
return [2 /*return*/, this._send(msg, msg.__id__)];
});
});
};
Client.prototype._send = function (msg_bytes, msg_id) {
return __awaiter(this, void 0, void 0, function () {
var p;
var _this = this;
return __generator(this, function (_a) {
p = new Promise(function (resolve, reject) {
var _a, _b;
if (!_this._alive) {
return reject(new ClientError("Client '".concat(_this.name, "' is not connected to server")));
}
try {
var d = _this._encoder.encode(msg_bytes);
(_a = _this._sock) === null || _a === void 0 ? void 0 : _a.write(d);
(_b = _this._sock) === null || _b === void 0 ? void 0 : _b.write(postfix);
_this._add_data_promise(msg_id, resolve, reject);
exports.log.d("Client '".concat(_this.name, "' sending ").concat(d.length.toString(), " bytes to server ").concat(JSON.stringify(_this.endpoint)));
}
catch (err) {
reject(err);
}
});
return [2 /*return*/, p];
});
});
};
Client.prototype._recv = function (data) {
exports.log.d("Client '".concat(this.name, "' recieved ").concat(data.length.toString(), " bytes from server"));
if (!this._alive) {
return;
}
var err;
var parsed_data;
try {
parsed_data = this._decoder.decode(data);
}
catch (e) {
err = e;
}
var connect_p = this._get_data_promise(this._connect_msg_id);
if (connect_p) {
if (err) {
return connect_p[1](err);
}
this._server_info(parsed_data);
return connect_p[0](parsed_data);
}
if (parsed_data) {
var p = this._get_data_promise(parsed_data.__id__);
if (p) {
return p[0](parsed_data);
}
}
else if (err) {
var p = this._get_earliest_data_promise();
if (p) {
return p[1](err);
}
}
};
/**
* Close the connection
* @returns {Promise}
*/
Client.prototype.close = function () {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
exports.log.d("Client '".concat(this.name, "' closing connection to server"));
this._disconnect();
return [2 /*return*/, new Promise(function (resolve, reject) {
var _a;
_this._add_data_promise(_this._close_msg_id, resolve, reject);
(_a = _this._sock) === null || _a === void 0 ? void 0 : _a.end(function () {
setTimeout(function () {
var _a;
if (!_this._disconnected) {
(_a = _this._sock) === null || _a === void 0 ? void 0 : _a.destroy();
_this._on_disconnect();
}
var p = _this._get_data_promise(_this._close_msg_id);
if (p) {
return p[0]();
}
}, 1000);
});
})];
});
});
};
return Client;
}());
exports.Client = Client;
exports.default = Client;