diff --git a/dist/browser-connector.js b/dist/browser-connector.js
index 1c33d91d..ae1c7e9d 100644
--- a/dist/browser-connector.js
+++ b/dist/browser-connector.js
@@ -114,8 +114,6 @@
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
var _helpers = __webpack_require__(10);
var helpers = _interopRequireWildcard(_helpers);
@@ -124,7 +122,7 @@
var _mapdClientV2 = _interopRequireDefault(_mapdClientV);
- var _processQueryResults = __webpack_require__(117);
+ var _processQueryResults = __webpack_require__(118);
var _processQueryResults2 = _interopRequireDefault(_processQueryResults);
@@ -132,9 +130,7 @@
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
- var _ref = isNodeRuntime() && __webpack_require__(116) || window,
+ var _ref = isNodeRuntime() && __webpack_require__(117) || window,
TDatumType = _ref.TDatumType,
TEncodingType = _ref.TEncodingType,
TPixel = _ref.TPixel; // eslint-disable-line global-require
@@ -143,7 +139,7 @@
var MapDThrift = isNodeRuntime() && __webpack_require__(13); // eslint-disable-line global-require
var Thrift = isNodeRuntime() && __webpack_require__(14) || window.Thrift; // eslint-disable-line global-require
var thriftWrapper = Thrift;
- var parseUrl = isNodeRuntime() && __webpack_require__(59).parse; // eslint-disable-line global-require
+ var parseUrl = isNodeRuntime() && __webpack_require__(60).parse; // eslint-disable-line global-require
if (isNodeRuntime()) {
// Because browser Thrift and Node Thrift are exposed slightly differently.
Thrift = Thrift.Thrift;
@@ -152,1245 +148,837 @@
}
- var COMPRESSION_LEVEL_DEFAULT = 3;
-
- function arrayify(maybeArray) {
- return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
- }
-
- function isNodeRuntime() {
- return typeof window === "undefined";
+ // Set a global Connector function when Connector is brought in via script tag.
+ if (( false ? "undefined" : _typeof(module)) === "object" && module.exports) {
+ if (!isNodeRuntime()) {
+ window.Connector = Connector;
+ }
}
+ module.exports = Connector;
+ exports.default = Connector;
- var MapdCon = function () {
- function MapdCon() {
- var _this = this;
-
- _classCallCheck(this, MapdCon);
-
- this.updateQueryTimes = function (conId, queryId, estimatedQueryTime, execution_time_ms) {
- _this.queryTimes[queryId] = execution_time_ms;
- };
-
- this.getFrontendViews = function (callback) {
- if (_this._sessionId) {
- _this._client[0].get_frontend_views(_this._sessionId[0], callback);
- } else {
- callback(new Error("No Session ID"));
- }
- };
-
- this.getFrontendViewsAsync = function () {
- return new Promise(function (resolve, reject) {
- _this.getFrontendViews(function (error, views) {
- if (error) {
- reject(error);
- } else {
- resolve(views);
- }
- });
- });
- };
-
- this.getFrontendView = function (viewName, callback) {
- if (_this._sessionId && viewName) {
- _this._client[0].get_frontend_view(_this._sessionId[0], viewName, callback);
- } else {
- callback(new Error("No Session ID"));
- }
- };
-
- this.getFrontendViewAsync = function (viewName) {
- return new Promise(function (resolve, reject) {
- _this.getFrontendView(viewName, function (err, view) {
- if (err) {
- reject(err);
- } else {
- resolve(view);
- }
- });
- });
- };
-
- this.getServerStatus = function (callback) {
- _this._client[0].get_server_status(_this._sessionId[0], callback);
- };
-
- this.getServerStatusAsync = function () {
- return new Promise(function (resolve, reject) {
- _this.getServerStatus(function (err, result) {
- if (err) {
- reject(err);
- } else {
- resolve(result);
- }
- });
- });
- };
-
- this.deleteFrontendViewAsync = function (viewName) {
- return new Promise(function (resolve, reject) {
- _this.deleteFrontendView(viewName, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve(viewName);
- }
- });
- });
- };
- this.getLinkView = function (link, callback) {
- _this._client[0].get_link_view(_this._sessionId[0], link, callback);
- };
-
- this.getLinkViewAsync = function (link) {
- return new Promise(function (resolve, reject) {
- _this.getLinkView(link, function (err, theLink) {
- if (err) {
- reject(err);
- } else {
- resolve(theLink);
- }
- });
- });
- };
-
- this.queryAsync = this.query;
-
- this.createTableAsync = function (tableName, rowDescObj, tableType) {
- return new Promise(function (resolve, reject) {
- _this.createTable(tableName, rowDescObj, tableType, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- });
- });
- };
-
- this.importTableAsync = this.importTableAsyncWrapper(false);
- this.importTableGeoAsync = this.importTableAsyncWrapper(true);
-
- this._host = null;
- this._user = null;
- this._password = null;
- this._port = null;
- this._dbName = null;
- this._client = null;
- this._sessionId = null;
- this._protocol = null;
- this._datumEnum = {};
- this._logging = false;
- this._platform = "mapd";
- this._nonce = 0;
- this._balanceStrategy = "adaptive";
- this._numConnections = 0;
- this._lastRenderCon = 0;
- this.queryTimes = {};
- this.serverQueueTimes = null;
- this.serverPingTimes = null;
- this.pingCount = null;
- this.DEFAULT_QUERY_TIME = 50;
- this.NUM_PINGS_PER_SERVER = 4;
- this.importerRowDesc = null;
-
- // invoke initialization methods
- this.invertDatumTypes();
-
- this.processResults = function () {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var result = arguments[1];
- var callback = arguments[2];
-
- var processor = (0, _processQueryResults2.default)(_this._logging, _this.updateQueryTimes);
- var processResultsObject = processor(options, _this._datumEnum, result, callback);
- return processResultsObject;
- };
-
- // return this to allow chaining off of instantiation
- return this;
- }
+ var COMPRESSION_LEVEL_DEFAULT = 3;
+ var DEFAULT_QUERY_TIME = 50;
+
+ function Connector() {
+ // initialize variables
+ var _datumEnum = {};
+ var _queryTimes = {};
+ var _client = null;
+ var _dbName = null;
+ var _host = null;
+ var _logging = false;
+ var _nonce = 0;
+ var _password = null;
+ var _port = null;
+ var _protocol = null;
+ var _sessionId = null;
+ var _user = null;
+
+ // invoke initialization methods
+ publicizeMethods(this, [connect, createFrontendView, createLink, createTable, dbName, deleteFrontendView, detectColumnTypes, disconnect, getFields, getFrontendView, getFrontendViews, getLinkView, getPixel, getServerStatus, getTables, host, importShapeTable, importTable, logging, password, port, protocol, query, renderVega, sessionId, user, validateQuery]);
+ invertDatumTypes(_datumEnum);
+
+ // return this to allow chaining off of instantiation
+ return this;
+ // public methods
/**
* Create a connection to the server, generating a client and session id.
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
- * @return {MapdCon} Object
+ * @param {Function} callback (error, session) => {…}
+ * @returns {undefined}
*
* @example
Connect to a MapD server:
- * var con = new MapdCon()
+ * var con = new Connector()
* .host('localhost')
* .port('8080')
* .dbName('myDatabase')
* .user('foo')
* .password('bar')
- * .connect((err, con) => console.log(con.sessionId()));
+ * .connect((error, con) => console.log(con.sessionId()));
*
* // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
*/
+ function connect(callback) {
+ var _this = this;
-
- _createClass(MapdCon, [{
- key: "connect",
- value: function connect(callback) {
- var _this2 = this;
-
- if (this._sessionId) {
- this.disconnect();
- }
-
- // TODO: should be its own function
- var allAreArrays = Array.isArray(this._host) && Array.isArray(this._port) && Array.isArray(this._user) && Array.isArray(this._password) && Array.isArray(this._dbName);
- if (!allAreArrays) {
- return callback("All connection parameters must be arrays.");
- }
-
- this._client = [];
- this._sessionId = [];
-
- if (!this._user[0]) {
- return callback("Please enter a username.");
- } else if (!this._password[0]) {
- return callback("Please enter a password.");
- } else if (!this._dbName[0]) {
- return callback("Please enter a database.");
- } else if (!this._host[0]) {
- return callback("Please enter a host name.");
- } else if (!this._port[0]) {
- return callback("Please enter a port.");
- }
-
- // now check to see if length of all arrays are the same and > 0
- var hostLength = this._host.length;
- if (hostLength < 1) {
- return callback("Must have at least one server to connect to.");
- }
- if (hostLength !== this._port.length || hostLength !== this._user.length || hostLength !== this._password.length || hostLength !== this._dbName.length) {
- return callback("Array connection parameters must be of equal length.");
- }
-
- if (!this._protocol) {
- this._protocol = this._host.map(function () {
- return window.location.protocol.replace(":", "");
- });
+ // eslint-disable-line consistent-return
+ if (_sessionId) {
+ disconnect();
+ }
+
+ if ([_host, _port, _user, _password, _dbName].some(Array.isArray)) {
+ console.warn("Connection parameters as arrays is deprecated; use single values."); // eslint-disable-line no-console
+ _host = Array.isArray(_host) ? _host[0] : _host;
+ _port = Array.isArray(_port) ? _port[0] : _port;
+ _user = Array.isArray(_user) ? _user[0] : _user;
+ _password = Array.isArray(_password) ? _password[0] : _password;
+ _dbName = Array.isArray(_dbName) ? _dbName[0] : _dbName;
+ }
+
+ if (!_user) {
+ return callback("Please enter a username.");
+ } else if (!_password) {
+ return callback("Please enter a password.");
+ } else if (!_dbName) {
+ return callback("Please enter a database.");
+ } else if (!_host) {
+ return callback("Please enter a host name.");
+ } else if (!_port) {
+ return callback("Please enter a port.");
+ }
+
+ _client = null;
+ _sessionId = null;
+ _protocol = _protocol || window.location.protocol.replace(":", "");
+
+ var transportUrl = _protocol + "://" + _host + ":" + _port;
+ var client = null;
+
+ if (isNodeRuntime()) {
+ var _parseUrl = parseUrl(transportUrl),
+ parsedProtocol = _parseUrl.protocol,
+ parsedHost = _parseUrl.hostname,
+ parsedPort = _parseUrl.port;
+
+ var connection = thriftWrapper.createHttpConnection(parsedHost, parsedPort, {
+ transport: thriftWrapper.TBufferedTransport,
+ protocol: thriftWrapper.TJSONProtocol,
+ path: "/",
+ headers: { Connection: "close" },
+ https: parsedProtocol === "https:"
+ });
+ connection.on("error", console.error); // eslint-disable-line no-console
+ client = thriftWrapper.createClient(MapDThrift, connection);
+ resetThriftClientOnArgumentErrorForMethods(this, client, Object.keys(this));
+ } else {
+ var thriftTransport = new Thrift.Transport(transportUrl);
+ var thriftProtocol = new Thrift.Protocol(thriftTransport);
+ client = new _mapdClientV2.default(thriftProtocol);
+ }
+ client.connect(_user, _password, _dbName, function (error, newSessionId) {
+ // eslint-disable-line no-loop-func
+ if (error) {
+ return callback(normalizeError(error));
}
+ _client = client;
+ _sessionId = newSessionId;
+ return callback(null, _this);
+ });
+ }
+ /**
+ * Disconnect from the server then clears the client and session values.
+ * @param {Function} callback (error) => {…}
+ * @returns {undefined}
+ *
+ * @example Disconnect from the server:
+ *
+ * con.sessionId() // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
+ * con.disconnect((err) => {
+ * console.error(err);
+ * con.sessionId() === null;
+ * })
+ */
+ function disconnect() {
+ var _this2 = this;
- var transportUrls = this.getEndpoints();
-
- var _loop = function _loop(h) {
- var client = null;
-
- if (isNodeRuntime()) {
- var _parseUrl = parseUrl(transportUrls[h]),
- protocol = _parseUrl.protocol,
- hostname = _parseUrl.hostname,
- port = _parseUrl.port;
+ var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop;
- var connection = thriftWrapper.createHttpConnection(hostname, port, {
- transport: thriftWrapper.TBufferedTransport,
- protocol: thriftWrapper.TJSONProtocol,
- path: "/",
- headers: { Connection: "close" },
- https: protocol === "https:"
- });
- connection.on("error", console.error); // eslint-disable-line no-console
- client = thriftWrapper.createClient(MapDThrift, connection);
- resetThriftClientOnArgumentErrorForMethods(_this2, client, ["connect", "createFrontendViewAsync", "createLinkAsync", "createTableAsync", "dbName", "deleteFrontendViewAsync", "detectColumnTypesAsync", "disconnect", "getFields", "getFrontendViewAsync", "getFrontendViewsAsync", "getLinkViewAsync", "getResultRowForPixel", "getServerStatusAsync", "getTablesAsync", "host", "importTableAsync", "importTableGeoAsync", "logging", "password", "port", "protocol", "query", "renderVega", "sessionId", "user", "validateQuery"]);
- } else {
- var thriftTransport = new Thrift.Transport(transportUrls[h]);
- var thriftProtocol = new Thrift.Protocol(thriftTransport);
- client = new _mapdClientV2.default(thriftProtocol);
+ if (_sessionId !== null) {
+ _client.disconnect(_sessionId, function (error) {
+ // eslint-disable-line no-loop-func
+ if (error) {
+ return callback(error, _this2);
}
-
- client.connect(_this2._user[h], _this2._password[h], _this2._dbName[h], function (error, sessionId) {
- if (error) {
- callback(error);
- return;
- }
- _this2._client.push(client);
- _this2._sessionId.push(sessionId);
- _this2._numConnections = _this2._client.length;
- callback(null, _this2);
- });
- };
-
- for (var h = 0; h < hostLength; h++) {
- _loop(h);
- }
-
- return this;
+ _sessionId = null;
+ _client = null;
+ return callback(null, _this2);
+ });
}
- }, {
- key: "convertFromThriftTypes",
- value: function convertFromThriftTypes(fields) {
- var fieldsArray = [];
- // silly to change this from map to array
- // - then later it turns back to map
- for (var key in fields) {
- if (fields.hasOwnProperty(key)) {
- fieldsArray.push({
- name: key,
- type: this._datumEnum[fields[key].col_type.type],
- is_array: fields[key].col_type.is_array,
- is_dict: fields[key].col_type.encoding === TEncodingType.DICT // eslint-disable-line no-undef
- });
- }
- }
- return fieldsArray;
- }
-
- /**
- * Disconnect from the server then clears the client and session values.
- * @return {MapdCon} Object
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
- *
- * @example Disconnect from the server:
- *
- * con.sessionId() // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
- * con.disconnect((err, con) => console.log(err, con))
- * con.sessionId() === null;
- */
-
- }, {
- key: "disconnect",
- value: function disconnect(callback) {
- var _this3 = this;
-
- if (this._sessionId !== null) {
- for (var c = 0; c < this._client.length; c++) {
- this._client[c].disconnect(this._sessionId[c], function (error) {
- // Success will return NULL
-
- if (error) {
- return callback(error, _this3);
- }
- _this3._sessionId = null;
- _this3._client = null;
- _this3._numConnections = 0;
- _this3.serverPingTimes = null;
- return callback(null, _this3);
- });
- }
- }
- return this;
+ }
+ /**
+ * Get a dashboard object containing a value for the view_state
property.
+ * This object contains a value for the view_state
property,
+ * but not for the view_name
property.
+ * @param {String} viewName the name of the dashboard
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get a specific dashboard from the server:
+ *
+ * con.getFrontendView('dashboard_name').then((result) => console.log(result))
+ * // {TFrontendView}
+ */
+ function getFrontendView(viewName, callback) {
+ if (_sessionId && viewName) {
+ _client.get_frontend_view(_sessionId, viewName, callback);
+ return;
+ } else {
+ callback(new Error("No Session ID"));
+ return;
}
-
- /**
- * Get the recent dashboards as a list of TFrontendView
objects.
- * These objects contain a value for the view_name
property,
- * but not for the view_state
property.
- * @return {Promise} An array which has all saved dashboards.
- *
- * @example Get the list of dashboards from the server:
- *
- * con.getFrontendViewsAsync().then((results) => console.log(results))
- * // [TFrontendView, TFrontendView]
- */
-
-
- /**
- * Get a dashboard object containing a value for the view_state
property.
- * This object contains a value for the view_state
property,
- * but not for the view_name
property.
- * @param {String} viewName the name of the dashboard
- * @return {Promise.} An object that contains all data and metadata related to the dashboard
- *
- * @example Get a specific dashboard from the server:
- *
- * con.getFrontendViewAsync('dashboard_name').then((result) => console.log(result))
- * // {TFrontendView}
- */
-
-
- /**
- * Get the status of the server as a TServerStatus
object.
- * This includes whether the server is read-only,
- * has backend rendering enabled, and the version number.
- * @return {Promise.}
- *
- * @example Get the server status:
- *
- * con.getServerStatusAsync().then((result) => console.log(result))
- * // {
- * // "read_only": false,
- * // "version": "3.0.0dev-20170503-40e2de3",
- * // "rendering_enabled": true,
- * // "start_time": 1493840131
- * // }
- */
-
- }, {
- key: "createFrontendViewAsync",
-
-
- /**
- * Add a new dashboard to the server.
- * @param {String} viewName - the name of the new dashboard
- * @param {String} viewState - the base64-encoded state string of the new dashboard
- * @param {String} imageHash - the numeric hash of the dashboard thumbnail
- * @param {String} metaData - Stringified metaData related to the view
- * @return {Promise} Returns empty if success
- *
- * @example Add a new dashboard to the server:
- *
- * con.createFrontendViewAsync('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
- */
- value: function createFrontendViewAsync(viewName, viewState, imageHash, metaData) {
- var _this4 = this;
-
- if (!this._sessionId) {
- return new Promise(function (resolve, reject) {
- reject(new Error("You are not connected to a server. Try running the connect method first."));
- });
- }
-
- return Promise.all(this._client.map(function (client, i) {
- return new Promise(function (resolve, reject) {
- client.create_frontend_view(_this4._sessionId[i], viewName, viewState, imageHash, metaData, function (error, data) {
- if (error) {
- reject(error);
- } else {
- resolve(data);
- }
- });
- });
- }));
+ }
+ /**
+ * Get the recent dashboards as a list of TFrontendView
objects.
+ * These objects contain a value for the view_name
property,
+ * but not for the view_state
property.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of dashboards from the server:
+ *
+ * con.getFrontendViews().then((results) => console.log(results))
+ * // [TFrontendView, TFrontendView]
+ */
+ function getFrontendViews(callback) {
+ if (_sessionId) {
+ _client.get_frontend_views(_sessionId, callback);
+ } else {
+ callback(new Error("No Session ID"));
+ return;
}
- }, {
- key: "deleteFrontendView",
- value: function deleteFrontendView(viewName, callback) {
- var _this5 = this;
-
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
- }
- try {
- this._client.forEach(function (client, i) {
- // do we want to try each one individually so if we fail we keep going?
- client.delete_frontend_view(_this5._sessionId[i], viewName, callback);
- });
- } catch (err) {
- console.log("ERROR: Could not delete the frontend view. Check your session id.", err);
- }
- }
-
- /**
- * Delete a dashboard object containing a value for the view_state
property.
- * @param {String} viewName - the name of the dashboard
- * @return {Promise.} Name of dashboard successfully deleted
- *
- * @example Delete a specific dashboard from the server:
- *
- * con.deleteFrontendViewAsync('dashboard_name').then(res => console.log(res))
- */
-
- }, {
- key: "createLinkAsync",
-
-
- /**
- * Create a short hash to make it easy to share a link to a specific dashboard.
- * @param {String} viewState - the base64-encoded state string of the new dashboard
- * @param {String} metaData - Stringified metaData related to the link
- * @return {Promise.} link - A short hash of the dashboard used for URLs
- *
- * @example Create a link to the current state of a dashboard:
- *
- * con.createLinkAsync("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
- * // ["28127951"]
- */
- value: function createLinkAsync(viewState, metaData) {
- var _this6 = this;
-
- return Promise.all(this._client.map(function (client, i) {
- return new Promise(function (resolve, reject) {
- client.create_link(_this6._sessionId[i], viewState, metaData, function (error, data) {
- if (error) {
- reject(error);
- } else {
- var result = data.split(",").reduce(function (links, link) {
- if (links.indexOf(link) === -1) {
- links.push(link);
- }
- return links;
- }, []);
- if (!result || result.length !== 1) {
- reject(new Error("Different links were created on connection"));
- } else {
- resolve(result.join());
- }
- }
- });
- });
- }));
+ }
+ /**
+ * Get the status of the server as a TServerStatus
object.
+ * This includes whether the server is read-only,
+ * has backend rendering enabled, and the version number.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the server status:
+ *
+ * con.getServerStatus().then((result) => console.log(result))
+ * // {
+ * // "read_only": false,
+ * // "version": "3.0.0dev-20170503-40e2de3",
+ * // "rendering_enabled": true,
+ * // "start_time": 1493840131
+ * // }
+ */
+ function getServerStatus(callback) {
+ _client.get_server_status(_sessionId, callback);
+ }
+ /**
+ * Add a new dashboard to the server.
+ * @param {String} viewName - the name of the new dashboard
+ * @param {String} viewState - the base64-encoded state string of the new dashboard
+ * @param {String} imageHash - the numeric hash of the dashboard thumbnail
+ * @param {String} metaData - Stringified metaData related to the view
+ * @param {Function} callback (error) => {…} success returns null
+ * @returns {undefined}
+ *
+ * @example Add a new dashboard to the server:
+ *
+ * con.createFrontendView('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
+ */
+ function createFrontendView(viewName, viewState, imageHash, metaData, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
-
- /**
- * Get a fully-formed dashboard object from a generated share link.
- * This object contains the given link for the view_name
property,
- * @param {String} link - the short hash of the dashboard, see {@link createLink}
- * @return {Promise.} Object of the dashboard and metadata
- *
- * @example Get a dashboard from a link:
- *
- * con.getLinkViewAsync('28127951').then(res => console.log(res))
- * // {
- * // "view_name": "28127951",
- * // "view_state": "eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==",
- * // "image_hash": "",
- * // "update_time": "2017-04-28T21:34:01Z",
- * // "view_metadata": "metaData"
- * // }
- */
-
- }, {
- key: "detectColumnTypes",
- value: function detectColumnTypes(fileName, copyParams, callback) {
- var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
- this._client[0].detect_column_types(this._sessionId[0], fileName, thriftCopyParams, callback);
- }
-
- /**
- * Asynchronously get the data from an importable file,
- * such as a .csv or plaintext file with a header.
- * @param {String} fileName - the name of the importable file
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @returns {Promise.} An object which has copy_params and row_set
- *
- * @example Get data from table_data.csv:
- *
- * var copyParams = new TCopyParams();
- * con.detectColumnTypesAsync('table_data.csv', copyParams).then(res => console.log(res))
- * // TDetectResult {row_set: TRowSet, copy_params: TCopyParams}
- *
- */
-
- }, {
- key: "detectColumnTypesAsync",
- value: function detectColumnTypesAsync(fileName, copyParams) {
- var _this7 = this;
-
- return new Promise(function (resolve, reject) {
- _this7.detectColumnTypes.bind(_this7, fileName, copyParams)(function (err, res) {
- if (err) {
- reject(err);
- } else {
- _this7.importerRowDesc = res.row_set.row_desc;
- resolve(res);
- }
- });
- });
+ return _client.create_frontend_view(_sessionId, viewName, viewState, imageHash, metaData, callback);
+ }
+ /**
+ * Delete a dashboard object containing a value for the view_state
property.
+ * @param {String} viewName - the name of the dashboard
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Delete a specific dashboard from the server:
+ *
+ * con.deleteFrontendView('dashboard_name').then(res => console.log(res))
+ */
+ function deleteFrontendView(viewName, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
-
- /**
- * Submit a query to the database and process the results.
- * @param {String} query The query to perform
- * @param {Object} options the options for the query
- * @param {Function} callback that takes `(err, result) => result`
- * @returns {Object} The result of the query
- *
- * @example create a query
- *
- * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
- * var options = {};
- *
- * con.query(query, options, function(err, result) {
- * console.log(result)
- * });
- *
- */
-
- }, {
- key: "query",
- value: function query(_query, options, callback) {
- var _this8 = this;
-
- var columnarResults = true;
- var eliminateNullRows = false;
- var queryId = null;
- var returnTiming = false;
- var limit = -1;
- if (options) {
- columnarResults = options.hasOwnProperty("columnarResults") ? options.columnarResults : columnarResults;
- eliminateNullRows = options.hasOwnProperty("eliminateNullRows") ? options.eliminateNullRows : eliminateNullRows;
- queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
- returnTiming = options.hasOwnProperty("returnTiming") ? options.returnTiming : returnTiming;
- limit = options.hasOwnProperty("limit") ? options.limit : limit;
- }
-
- var lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME;
-
- var curNonce = (this._nonce++).toString();
-
- var conId = 0;
-
- var processResultsOptions = {
- returnTiming: returnTiming,
- eliminateNullRows: eliminateNullRows,
- query: _query,
- queryId: queryId,
- conId: conId,
- estimatedQueryTime: lastQueryTime
- };
-
- try {
- if (callback) {
- this._client[conId].sql_execute(this._sessionId[conId], _query, columnarResults, curNonce, limit, function (error, result) {
- if (error) {
- callback(error);
- } else {
- _this8.processResults(processResultsOptions, result, callback);
- }
- });
- return curNonce;
- } else if (!callback) {
- var SQLExecuteResult = this._client[conId].sql_execute(this._sessionId[conId], _query, columnarResults, curNonce, limit);
- return this.processResults(processResultsOptions, SQLExecuteResult);
- }
- } catch (err) {
- if (err.name === "NetworkError") {
- this.removeConnection(conId);
- if (this._numConnections === 0) {
- err.msg = "No remaining database connections";
- throw err;
- }
- this.query(_query, options, callback);
- } else if (callback) {
- callback(err);
- } else {
- throw err;
- }
- }
- }
-
- /** @deprecated will default to query */
-
- }, {
- key: "validateQuery",
-
-
- /**
- * Submit a query to validate whether the backend can create a result set based on the SQL statement.
- * @param {String} query The query to perform
- * @returns {Promise.} The result of whether the query is valid
- *
- * @example create a query
- *
- * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
- *
- * con.validateQuery(query).then(res => console.log(res))
- *
- * // [{
- * // "name": "n",
- * // "type": "INT",
- * // "is_array": false,
- * // "is_dict": false
- * // }]
- *
- */
- value: function validateQuery(query) {
- var _this9 = this;
-
- return new Promise(function (resolve, reject) {
- _this9._client[0].sql_validate(_this9._sessionId[0], query, function (error, res) {
- if (error) {
- reject(error);
- } else {
- resolve(_this9.convertFromThriftTypes(res));
- }
- });
- });
+ try {
+ // eslint-disable-line no-restricted-syntax
+ return _client.delete_frontend_view(_sessionId, viewName, callback);
+ } catch (err) {
+ return callback(new Error("Could not delete the frontend view; check your session id.", err));
}
- }, {
- key: "removeConnection",
- value: function removeConnection(conId) {
- if (conId < 0 || conId >= this.numConnections) {
- var err = {
- msg: "Remove connection id invalid"
- };
- throw err;
+ }
+ /**
+ * Create a short hash to make it easy to share a link to a specific dashboard.
+ * @param {String} viewState - the base64-encoded state string of the new dashboard
+ * @param {String} metaData - Stringified metaData related to the link
+ * @param {Function} callback (error, id) => {…}
+ * @returns {undefined}
+ *
+ * @example Create a link to the current state of a dashboard:
+ *
+ * con.createLink("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
+ * // ["28127951"]
+ */
+ function createLink(viewState, metaData, callback) {
+ return _client.create_link(_sessionId, viewState, metaData, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
}
- this._client.splice(conId, 1);
- this._sessionId.splice(conId, 1);
- this._numConnections--;
- }
- }, {
- key: "getTables",
- value: function getTables(callback) {
- this._client[0].get_tables(this._sessionId[0], function (error, tables) {
- if (error) {
- callback(error);
- } else {
- callback(null, tables.map(function (table) {
- return {
- name: table,
- label: "obs"
- };
- }));
- }
- });
- }
-
- /**
- * Get the names of the databases that exist on the current session's connectdion.
- * @return {Promise.} list of table objects containing the label and table names.
- *
- * @example Get the list of tables from a connection:
- *
- * con.getTablesAsync().then(res => console.log(res))
- *
- * // [{
- * // label: 'obs', // deprecated property
- * // name: 'myDatabaseName'
- * // },
- * // ...]
- */
-
- }, {
- key: "getTablesAsync",
- value: function getTablesAsync() {
- var _this10 = this;
-
- return new Promise(function (resolve, reject) {
- _this10.getTables.bind(_this10)(function (error, tables) {
- if (error) {
- reject(error);
- } else {
- resolve(tables);
- }
- });
- });
- }
-
- /**
- * Create an array-like object from {@link TDatumType} by
- * flipping the string key and numerical value around.
- *
- * @returns {Undefined} This function does not return anything
- */
-
- }, {
- key: "invertDatumTypes",
- value: function invertDatumTypes() {
- var datumType = TDatumType; // eslint-disable-line no-undef
- for (var key in datumType) {
- if (datumType.hasOwnProperty(key)) {
- this._datumEnum[datumType[key]] = key;
- }
- }
- }
-
- /**
- * Get a list of field objects for a given table.
- * @param {String} tableName - name of table containing field names
- * @param {Function} callback - (err, results)
- * @return {Array} fields - the formmatted list of field objects
- *
- * @example Get the list of fields from a specific table:
- *
- * con.getFields('flights', (err, res) => console.log(res))
- * // [{
- * name: 'fieldName',
- * type: 'BIGINT',
- * is_array: false,
- * is_dict: false
- * }, ...]
- */
-
- }, {
- key: "getFields",
- value: function getFields(tableName, callback) {
- var _this11 = this;
-
- this._client[0].get_table_details(this._sessionId[0], tableName, function (error, fields) {
- if (fields) {
- var rowDict = fields.row_desc.reduce(function (accum, value) {
- accum[value.col_name] = value;
- return accum;
- }, {});
- callback(null, _this11.convertFromThriftTypes(rowDict));
- } else {
- callback(new Error("Table (" + tableName + ") not found" + error));
+ var result = data.split(",").reduce(function (links, link) {
+ // eslint-disable-line max-nested-callbacks
+ if (!links.includes(link)) {
+ links.push(link);
}
- });
- }
- }, {
- key: "createTable",
- value: function createTable(tableName, rowDescObj, tableType, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
+ return links;
+ }, []);
+ if (!result || result.length !== 1) {
+ return callback(new Error("Different links were created on connection"));
+ } else {
+ return callback(null, result.join());
}
-
- var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc);
-
- for (var c = 0; c < this._numConnections; c++) {
- this._client[c].create_table(this._sessionId[c], tableName, thriftRowDesc, tableType, function (err) {
- if (err) {
- callback(err);
- } else {
- callback();
- }
- });
+ });
+ }
+ /**
+ * Get a fully-formed dashboard object from a generated share link.
+ * This object contains the given link for the view_name
property,
+ * @param {String} link - the short hash of the dashboard, see {@link createLink}
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get a dashboard from a link:
+ *
+ * con.getLinkView('28127951').then(res => console.log(res))
+ * // {
+ * // "view_name": "28127951",
+ * // "view_state": "eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==",
+ * // "image_hash": "",
+ * // "update_time": "2017-04-28T21:34:01Z",
+ * // "view_metadata": "metaData"
+ * // }
+ */
+ function getLinkView(link, callback) {
+ _client.get_link_view(_sessionId, link, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, data);
}
- }
-
- /**
- * Create a table and persist it to the backend.
- * @param {String} tableName - desired name of the new table
- * @param {Array} rowDescObj - fields of the new table
- * @param {Number} tableType - the types of tables a user can import into the db
- * @return {Promise.} it will either catch an error or return undefined on success
- *
- * @example Create a new table:
- *
- * con.createTable('mynewtable', [TColumnType, TColumnType, ...], 0).then(res => console.log(res));
- * // undefined
- */
+ });
+ }
+ /**
+ * Asynchronously get the data from an importable file,
+ * such as a .csv or plaintext file with a header.
+ * @param {String} fileName - the name of the importable file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get data from table_data.csv:
+ *
+ * var copyParams = new TCopyParams();
+ * con.detectColumnTypes('table_data.csv', copyParams).then(res => console.log(res))
+ * // TDetectResult {row_set: TRowSet, copy_params: TCopyParams}
+ *
+ */
+ function detectColumnTypes(fileName, copyParams, callback) {
+ var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
+ _client.detect_column_types(_sessionId, fileName, thriftCopyParams, callback);
+ }
+ /**
+ * Submit a query to the database and process the results.
+ * @param {String} sql The query to perform
+ * @param {Object} options the options for the query
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example create a query
+ *
+ * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
+ * var options = {};
+ *
+ * con.query(query, options, function(error, data) {
+ * console.log(data)
+ * });
+ *
+ */
+ function query(sql, options, callback) {
+ var columnarResults = true;
+ var eliminateNullRows = false;
+ var queryId = null;
+ var returnTiming = false;
+ var limit = -1;
+ if (options) {
+ columnarResults = options.hasOwnProperty("columnarResults") ? options.columnarResults : columnarResults;
+ eliminateNullRows = options.hasOwnProperty("eliminateNullRows") ? options.eliminateNullRows : eliminateNullRows;
+ queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
+ returnTiming = options.hasOwnProperty("returnTiming") ? options.returnTiming : returnTiming;
+ limit = options.hasOwnProperty("limit") ? options.limit : limit;
+ }
+
+ var lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME;
+
+ var curNonce = (_nonce++).toString();
+
+ var processResultsOptions = {
+ returnTiming: returnTiming,
+ eliminateNullRows: eliminateNullRows,
+ sql: sql,
+ queryId: queryId,
+ conId: 0,
+ estimatedQueryTime: lastQueryTime
+ };
- }, {
- key: "importTable",
- value: function importTable(tableName, fileName, copyParams, rowDescObj, isShapeFile, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
+ _client.sql_execute(_sessionId, sql, columnarResults, curNonce, limit, function (error, result) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions);
}
-
- var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
- var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc);
-
- var thriftCallBack = function thriftCallBack(err, res) {
- if (err) {
- callback(err);
- } else {
- callback(null, res);
- }
- };
-
- for (var c = 0; c < this._numConnections; c++) {
- if (isShapeFile) {
- this._client[c].import_geo_table(this._sessionId[c], tableName, fileName, thriftCopyParams, thriftRowDesc, thriftCallBack);
- } else {
- this._client[c].import_table(this._sessionId[c], tableName, fileName, thriftCopyParams, thriftCallBack);
- }
+ });
+ }
+ /**
+ * Submit a query to validate whether the backend can create a result set based on the SQL statement.
+ * @param {String} sql The query to perform
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example create a query
+ *
+ * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
+ *
+ * con.validateQuery(query).then(res => console.log(res))
+ *
+ * // [{
+ * // "name": "n",
+ * // "type": "INT",
+ * // "is_array": false,
+ * // "is_dict": false
+ * // }]
+ *
+ */
+ function validateQuery(sql, callback) {
+ _client.sql_validate(_sessionId, sql, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, convertFromThriftTypes(data, _datumEnum));
}
+ });
+ }
+ /**
+ * Get the names of the databases that exist on the current session's connectdion.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of tables from a connection:
+ *
+ * con.getTables().then(res => console.log(res))
+ *
+ * // [{
+ * // label: 'obs', // deprecated property
+ * // name: 'myDatabaseName'
+ * // },
+ * // ...]
+ */
+ function getTables(callback) {
+ _client.get_tables(_sessionId, function (error, tables) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, tables.map(function (table) {
+ return { name: table, label: "obs" };
+ }));
+ }
+ });
+ }
+ /**
+ * Get a list of field objects for a given table.
+ * @param {String} tableName - name of table containing field names
+ * @param {Function} callback - (error, fields) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of fields from a specific table:
+ *
+ * con.getFields('flights', (error, res) => console.log(res))
+ * // [{
+ * name: 'fieldName',
+ * type: 'BIGINT',
+ * is_array: false,
+ * is_dict: false
+ * }, ...]
+ */
+ function getFields(tableName, callback) {
+ _client.get_table_details(_sessionId, tableName, function (error, fields) {
+ if (fields) {
+ var rowDict = fields.row_desc.reduce(function (accum, value) {
+ accum[value.col_name] = value;
+ return accum;
+ }, {});
+ return callback(null, convertFromThriftTypes(rowDict, _datumEnum));
+ } else {
+ return callback(normalizeError(error));
+ }
+ });
+ }
+ /**
+ * Create a table and persist it to the backend.
+ * @param {String} tableName - desired name of the new table
+ * @param {Array} rowDescObj - fields of the new table
+ * @param {Number} tableType - the types of tables a user can import into the db
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Create a new table:
+ *
+ * con.createTable('mynewtable', [TColumnType, TColumnType, ...], 0).then(res => console.log(res));
+ * // undefined
+ */
+ function createTable(tableName, rowDescObj, tableType, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
- }, {
- key: "importTableAsyncWrapper",
- value: function importTableAsyncWrapper(isShapeFile) {
- var _this12 = this;
+ var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null);
+ return _client.create_table(_sessionId, tableName, thriftRowDesc, tableType, callback);
+ }
+ /**
+ * Import a delimited table from a file.
+ * @param {String} tableName - desired name of the new table
+ * @param {String} fileName - name of imported file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @param {Boolean} isShapeFile false by default, enabled to import shape data.
+ * @returns {undefined}
+ */
+ function importTable(tableName, fileName, copyParams, rowDescObj, callback) {
+ var isShapeFile = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
- return function (tableName, fileName, copyParams, headers) {
- return new Promise(function (resolve, reject) {
- _this12.importTable(tableName, fileName, copyParams, headers, isShapeFile, function (err, link) {
- if (err) {
- reject(err);
- } else {
- resolve(link);
- }
- });
- });
- };
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
- /**
- * Import a delimited table from a file.
- * @param {String} tableName - desired name of the new table
- * @param {String} fileName
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
- */
-
-
- /**
- * Import a geo table from a file.
- * @param {String} tableName - desired name of the new table
- * @param {String} fileName
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
- */
-
- }, {
- key: "renderVega",
-
-
- /**
- * Use for backend rendering. This method will fetch a PNG image
- * that is a render of the vega json object.
- *
- * @param {Number} widgetid the widget id of the calling widget
- * @param {String} vega the vega json
- * @param {Object} options the options for the render query
- * @param {Number} options.compressionLevel the png compression level.
- * range 1 (low compression, faster) to 10 (high compression, slower).
- * Default 3.
- * @param {Function} callback takes `(err, success)` as its signature. Returns con singleton on success.
- *
- * @returns {Image} Base 64 Image
- */
- value: function renderVega(widgetid, vega, options, callback) /* istanbul ignore next */{
- var _this13 = this;
-
- var queryId = null;
- var compressionLevel = COMPRESSION_LEVEL_DEFAULT;
- if (options) {
- queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
- compressionLevel = options.hasOwnProperty("compressionLevel") ? options.compressionLevel : compressionLevel;
- }
-
- var lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME;
-
- var curNonce = (this._nonce++).toString();
-
- var conId = 0;
- this._lastRenderCon = conId;
-
- var processResultsOptions = {
- isImage: true,
- query: "render: " + vega,
- queryId: queryId,
- conId: conId,
- estimatedQueryTime: lastQueryTime
- };
+ var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
+ var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null);
- try {
- if (!callback) {
- var renderResult = this._client[conId].render_vega(this._sessionId[conId], widgetid, vega, compressionLevel, curNonce);
- return this.processResults(processResultsOptions, renderResult);
- }
-
- this._client[conId].render_vega(this._sessionId[conId], widgetid, vega, compressionLevel, curNonce, function (error, result) {
- if (error) {
- callback(error);
- } else {
- _this13.processResults(processResultsOptions, result, callback);
- }
- });
- } catch (err) {
- throw err;
- }
-
- return curNonce;
+ if (isShapeFile) {
+ return _client.import_geo_table(_sessionId, tableName, fileName, thriftCopyParams, thriftRowDesc, callback);
+ } else {
+ return _client.import_table(_sessionId, tableName, fileName, thriftCopyParams, callback);
+ }
+ }
+ /**
+ * Import a geo table from a file.
+ * @param {String} tableName - desired name of the new table
+ * @param {String} fileName - name of imported file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ */
+ function importShapeTable(tableName, fileName, copyParams, rowDescObj, callback) {
+ return importTable(tableName, fileName, copyParams, rowDescObj, callback, true);
+ }
+ /**
+ * Use for backend rendering. This method will fetch a PNG image
+ * that is a render of the vega json object.
+ *
+ * @param {Number} widgetid the widget id of the calling widget
+ * @param {String} vega the vega json
+ * @param {Object} options the options for the render query
+ * @param {Number} options.compressionLevel the png compression level.
+ * range 1 (low compression, faster) to 10 (high compression, slower).
+ * Default 3.
+ * @param {Function} callback (error, Base64Image) => {…}
+ * @returns {undefined}
+ */
+ function renderVega(widgetid, vega, options, callback) {
+ var queryId = null;
+ var compressionLevel = COMPRESSION_LEVEL_DEFAULT;
+ if (options) {
+ queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
+ compressionLevel = options.hasOwnProperty("compressionLevel") ? options.compressionLevel : compressionLevel;
}
- /**
- * Used primarily for backend rendered maps, this method will fetch the row
- * for a specific table that was last rendered at a pixel.
- *
- * @param {widgetId} Number - the widget id of the caller
- * @param {TPixel} pixel - the pixel (lower left-hand corner is pixel (0,0))
- * @param {String} tableName - the table containing the geo data
- * @param {Object} tableColNamesMap - object of tableName -> array of col names
- * @param {Array} callbacks
- * @param {Number} [pixelRadius=2] - the radius around the primary pixel to search
- */
+ var lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME;
- }, {
- key: "getResultRowForPixel",
- value: function getResultRowForPixel(widgetId, pixel, tableColNamesMap, callbacks) /* istanbul ignore next */{
- var pixelRadius = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2;
+ var curNonce = (_nonce++).toString();
- if (!(pixel instanceof TPixel)) {
- pixel = new TPixel(pixel);
- }
- var columnFormat = true; // BOOL
- var curNonce = (this._nonce++).toString();
- try {
- if (!callbacks) {
- return this.processPixelResults(undefined, // eslint-disable-line no-undefined
- this._client[this._lastRenderCon].get_result_row_for_pixel(this._sessionId[this._lastRenderCon], widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce));
- }
- this._client[this._lastRenderCon].get_result_row_for_pixel(this._sessionId[this._lastRenderCon], widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce, this.processPixelResults.bind(this, callbacks));
- } catch (err) {
- throw err;
+ var processResultsOptions = {
+ isImage: true,
+ query: "render: " + vega,
+ queryId: queryId,
+ conId: 0,
+ estimatedQueryTime: lastQueryTime
+ };
+
+ _client.render_vega(_sessionId, widgetid, vega, compressionLevel, curNonce, function (error, result) {
+ if (error) {
+ return callback(normalizeError(error));
}
- return curNonce;
- }
-
- /**
- * Formats the pixel results into the same pattern as textual results.
- *
- * @param {Array} callbacks a collection of callbacks
- * @param {Object} error an error if one was thrown, otherwise null
- * @param {Array|Object} results unformatted results of pixel rowId information
- *
- * @returns {Object} An object with the pixel results formatted for display
- */
-
- }, {
- key: "processPixelResults",
- value: function processPixelResults(callbacks, error, results) {
- callbacks = Array.isArray(callbacks) ? callbacks : [callbacks];
- results = Array.isArray(results) ? results.pixel_rows : [results];
- var numPixels = results.length;
- var processResultsOptions = {
- isImage: false,
- eliminateNullRows: false,
- query: "pixel request",
- queryId: -2
- };
- for (var p = 0; p < numPixels; p++) {
- results[p].row_set = this.processResults(processResultsOptions, results[p]);
- }
- if (!callbacks) {
- return results;
- }
- callbacks.pop()(error, results);
- }
-
- /**
- * Get or set the session ID used by the server to serve the correct data.
- * This is typically set by {@link connect} and should not be set manually.
- * @param {Number} sessionId - The session ID of the current connection
- * @return {Number|MapdCon} - The session ID or the MapdCon itself
- *
- * @example Get the session id:
- *
- * con.sessionId();
- * // sessionID === 3145846410
- *
- * @example Set the session id:
- * var con = new MapdCon().connect().sessionId(3415846410);
- * // NOTE: It is generally unsafe to set the session id manually.
- */
-
- }, {
- key: "sessionId",
- value: function sessionId(_sessionId) {
- if (!arguments.length) {
- return this._sessionId;
- }
- this._sessionId = _sessionId;
- return this;
- }
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions);
+ });
+ }
+ /**
+ * Used primarily for backend rendered maps, this method will fetch the row
+ * for a specific table that was last rendered at a pixel.
+ * @param {Number} widgetId - the widget id of the caller
+ * @param {TPixel} pixel - the pixel (lower left-hand corner is pixel (0,0))
+ * @param {Object} tableColNamesMap - object of tableName -> array of col names
+ * @param {Function} callback (error, results) => {…}
+ * @param {Number} [pixelRadius=2] - the radius around the primary pixel to search
+ * @returns {undefined}
+ */
+ function getPixel(widgetId, pixel, tableColNamesMap, callback) {
+ var pixelRadius = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2;
- /**
- * Get or set the connection server hostname.
- * This is is typically the first method called after instantiating a new MapdCon.
- * @param {String} host - The hostname address
- * @return {String|MapdCon} - The hostname or the MapdCon itself
- *
- * @example Set the hostname:
- * var con = new MapdCon().host('localhost');
- *
- * @example Get the hostname:
- * var host = con.host();
- * // host === 'localhost'
- */
-
- }, {
- key: "host",
- value: function host(_host) {
- if (!arguments.length) {
- return this._host;
- }
- this._host = arrayify(_host);
- return this;
+ if (Array.isArray(callback)) {
+ console.warn("getPixel callbacks array deprecated; pass single callback instead."); // eslint-disable-line no-console
+ callback = callback[0];
}
-
- /**
- * Get or set the connection port.
- * @param {String} port - The port to connect on
- * @return {String|MapdCon} - The port or the MapdCon itself
- *
- * @example Set the port:
- * var con = new MapdCon().port('8080');
- *
- * @example Get the port:
- * var port = con.port();
- * // port === '8080'
- */
-
- }, {
- key: "port",
- value: function port(_port) {
- if (!arguments.length) {
- return this._port;
- }
- this._port = arrayify(_port);
- return this;
+ if (!(pixel instanceof TPixel)) {
+ pixel = new TPixel(pixel);
}
-
- /**
- * Get or set the username to authenticate with.
- * @param {String} user - The username to authenticate with
- * @return {String|MapdCon} - The username or the MapdCon itself
- *
- * @example Set the username:
- * var con = new MapdCon().user('foo');
- *
- * @example Get the username:
- * var username = con.user();
- * // user === 'foo'
- */
-
- }, {
- key: "user",
- value: function user(_user) {
- if (!arguments.length) {
- return this._user;
- }
- this._user = arrayify(_user);
- return this;
+ var columnFormat = true;
+ var curNonce = String(_nonce++);
+ _client.get_result_row_for_pixel(_sessionId, widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce, processPixelResults.bind(this, callback, _logging, _datumEnum));
+ }
+ /**
+ * Get or set the session ID used by the server to serve the correct data.
+ * This is typically set by {@link connect} and should not be set manually.
+ * @param {Number} newSessionId - The session ID of the current connection
+ * @returns {Number|Connector} - The session ID or the Connector itself
+ *
+ * @example Get the session id:
+ *
+ * con.sessionId();
+ * // sessionID === 3145846410
+ *
+ * @example Set the session id:
+ * var con = new Connector().connect().sessionId(3415846410);
+ * // NOTE: It is generally unsafe to set the session id manually.
+ */
+ function sessionId(newSessionId) {
+ if (!arguments.length) {
+ return _sessionId;
}
-
- /**
- * Get or set the user's password to authenticate with.
- * @param {String} password - The password to authenticate with
- * @return {String|MapdCon} - The password or the MapdCon itself
- *
- * @example Set the password:
- * var con = new MapdCon().password('bar');
- *
- * @example Get the username:
- * var password = con.password();
- * // password === 'bar'
- */
-
- }, {
- key: "password",
- value: function password(_password) {
- if (!arguments.length) {
- return this._password;
- }
- this._password = arrayify(_password);
- return this;
+ _sessionId = newSessionId;
+ return this;
+ }
+ /**
+ * Get or set the connection server hostname.
+ * This is is typically the first method called after instantiating a new Connector.
+ * @param {String} hostname - The hostname address
+ * @returns {String|Connector} - The hostname or the Connector itself
+ *
+ * @example Set the hostname:
+ * var con = new Connector().host('localhost');
+ *
+ * @example Get the hostname:
+ * var host = con.host();
+ * // host === 'localhost'
+ */
+ function host(hostname) {
+ if (!arguments.length) {
+ return _host;
}
-
- /**
- * Get or set the name of the database to connect to.
- * @param {String} dbName - The database to connect to
- * @return {String|MapdCon} - The name of the database or the MapdCon itself
- *
- * @example Set the database name:
- * var con = new MapdCon().dbName('myDatabase');
- *
- * @example Get the database name:
- * var dbName = con.dbName();
- * // dbName === 'myDatabase'
- */
-
- }, {
- key: "dbName",
- value: function dbName(_dbName) {
- if (!arguments.length) {
- return this._dbName;
- }
- this._dbName = arrayify(_dbName);
- return this;
+ _host = hostname;
+ return this;
+ }
+ /**
+ * Get or set the connection port.
+ * @param {String} thePort - The port to connect on
+ * @returns {String|Connector} - The port or the Connector itself
+ *
+ * @example Set the port:
+ * var con = new Connector().port('8080');
+ *
+ * @example Get the port:
+ * var port = con.port();
+ * // port === '8080'
+ */
+ function port(thePort) {
+ if (!arguments.length) {
+ return _port;
}
-
- /**
- * Whether the raw queries strings will be logged to the console.
- * Used primarily for debugging and defaults to false
.
- * @param {Boolean} logging - Set to true to enable logging
- * @return {Boolean|MapdCon} - The current logging flag or MapdCon itself
- *
- * @example Set logging to true:
- * var con = new MapdCon().logging(true);
- *
- * @example Get the logging flag:
- * var isLogging = con.logging();
- * // isLogging === true
- */
-
- }, {
- key: "logging",
- value: function logging(_logging) {
- if (typeof _logging === "undefined") {
- return this._logging;
- } else if (typeof _logging !== "boolean") {
- return "logging can only be set with boolean values";
- }
- this._logging = _logging;
- var isEnabledTxt = _logging ? "enabled" : "disabled";
- return "SQL logging is now " + isEnabledTxt;
- }
-
- /**
- * The name of the platform.
- * @param {String} platform - The platform, default is "mapd"
- * @return {String|MapdCon} - The platform or the MapdCon itself
- *
- * @example Set the platform name:
- * var con = new MapdCon().platform('myPlatform');
- *
- * @example Get the platform name:
- * var platform = con.platform();
- * // platform === 'myPlatform'
- */
-
- }, {
- key: "platform",
- value: function platform(_platform) {
- if (!arguments.length) {
- return this._platform;
- }
- this._platform = _platform;
- return this;
+ _port = thePort;
+ return this;
+ }
+ /**
+ * Get or set the username to authenticate with.
+ * @param {String} username - The username to authenticate with
+ * @returns {String|Connector} - The username or the Connector itself
+ *
+ * @example Set the username:
+ * var con = new Connector().user('foo');
+ *
+ * @example Get the username:
+ * var username = con.user();
+ * // user === 'foo'
+ */
+ function user(username) {
+ if (!arguments.length) {
+ return _user;
}
-
- /**
- * Get the number of connections that are currently open.
- * @return {Number} - number of open connections
- *
- * @example Get the number of connections:
- *
- * var numConnections = con.numConnections();
- * // numConnections === 1
- */
-
- }, {
- key: "numConnections",
- value: function numConnections() {
- return this._numConnections;
- }
-
- /**
- * The protocol to use for requests.
- * @param {String} protocol - http or https
- * @return {String|MapdCon} - protocol or MapdCon itself
- *
- * @example Set the protocol:
- * var con = new MapdCon().protocol('http');
- *
- * @example Get the protocol:
- * var protocol = con.protocol();
- * // protocol === 'http'
- */
-
- }, {
- key: "protocol",
- value: function protocol(_protocol) {
- if (!arguments.length) {
- return this._protocol;
- }
- this._protocol = arrayify(_protocol);
- return this;
+ _user = username;
+ return this;
+ }
+ /**
+ * Get or set the user's password to authenticate with.
+ * @param {String} pass - The password to authenticate with
+ * @returns {String|Connector} - The password or the Connector itself
+ *
+ * @example Set the password:
+ * var con = new Connector().password('bar');
+ *
+ * @example Get the username:
+ * var password = con.password();
+ * // password === 'bar'
+ */
+ function password(pass) {
+ if (!arguments.length) {
+ return _password;
}
+ _password = pass;
+ return this;
+ }
+ /**
+ * Get or set the name of the database to connect to.
+ * @param {String} db - The database to connect to
+ * @returns {String|Connector} - The name of the database or the Connector itself
+ *
+ * @example Set the database name:
+ * var con = new Connector().dbName('myDatabase');
+ *
+ * @example Get the database name:
+ * var dbName = con.dbName();
+ * // dbName === 'myDatabase'
+ */
+ function dbName(db) {
+ if (!arguments.length) {
+ return _dbName;
+ }
+ _dbName = db;
+ return this;
+ }
+ /**
+ * Whether the raw queries strings will be logged to the console.
+ * Used primarily for debugging and defaults to false
.
+ * @param {Boolean} loggingEnabled - Set to true to enable logging
+ * @returns {Boolean|Connector} - The current logging flag or Connector itself
+ *
+ * @example Set logging to true:
+ * var con = new Connector().logging(true);
+ *
+ * @example Get the logging flag:
+ * var isLogging = con.logging();
+ * // isLogging === true
+ */
+ function logging(loggingEnabled) {
+ if (typeof loggingEnabled === "undefined") {
+ return _logging;
+ } else if (typeof loggingEnabled !== "boolean") {
+ return "logging can only be set with boolean values";
+ }
+ _logging = loggingEnabled;
+ var isEnabledTxt = loggingEnabled ? "enabled" : "disabled";
+ return "SQL logging is now " + isEnabledTxt;
+ }
+ /**
+ * The protocol to use for requests.
+ * @param {String} theProtocol - http or https
+ * @returns {String|Connector} - protocol or Connector itself
+ *
+ * @example Set the protocol:
+ * var con = new Connector().protocol('http');
+ *
+ * @example Get the protocol:
+ * var protocol = con.protocol();
+ * // protocol === 'http'
+ */
+ function protocol(theProtocol) {
+ if (!arguments.length) {
+ return _protocol;
+ }
+ _protocol = theProtocol;
+ return this;
+ }
+ }
+
+ // helper functions
+
+ function noop() {/* noop */}
- /**
- * Generates a list of endpoints from the connection params.
- * @return {Array} - list of endpoints
- *
- * @example Get the endpoints:
- * var con = new MapdCon().protocol('http').host('localhost').port('8000');
- * var endpoints = con.getEndpoints();
- * // endpoints === [ 'http://localhost:8000' ]
- */
+ function isNodeRuntime() {
+ return typeof window === "undefined";
+ }
- }, {
- key: "getEndpoints",
- value: function getEndpoints() {
- var _this14 = this;
+ function publicizeMethods(theClass, methods) {
+ methods.forEach(function (method) {
+ theClass[method.name] = method;
+ });
+ }
- return this._host.map(function (host, i) {
- return _this14._protocol[i] + "://" + host + ":" + _this14._port[i];
+ function convertFromThriftTypes(fields, _datumEnum) {
+ var fieldsArray = [];
+ for (var key in fields) {
+ if (fields.hasOwnProperty(key)) {
+ fieldsArray.push({
+ name: key,
+ type: _datumEnum[fields[key].col_type.type],
+ is_array: fields[key].col_type.is_array,
+ is_dict: fields[key].col_type.encoding === TEncodingType.DICT
});
}
- }]);
+ }
+ return fieldsArray;
+ }
- return MapdCon;
- }();
+ function updateQueryTimes(queryTimes) {
+ return function (conId, queryId, estimatedQueryTime, execution_time_ms) {
+ queryTimes[queryId] = execution_time_ms;
+ };
+ }
+
+ function processPixelResults(callback, _logging, _datumEnum, error, results) {
+ // eslint-disable-line consistent-return
+ if (error) {
+ return callback(normalizeError(error));
+ }
+ results = Array.isArray(results) ? results.pixel_rows : [results];
+ var numPixels = results.length;
+ var processResultsOptions = {
+ isImage: false,
+ eliminateNullRows: false,
+ query: "pixel request",
+ queryId: -2
+ };
+ var numResultsProcessed = 0;
+ for (var p = 0; p < numPixels; p++) {
+ processResults(results[p], aggregatingCallback(p), _logging, _datumEnum, processResultsOptions);
+ }
+ function aggregatingCallback(index) {
+ return function (processResultsError, row_set) {
+ results[index].row_set = row_set;
+ if (processResultsError) {
+ numResultsProcessed = -Infinity; // avoid invoking callback again
+ return callback(processResultsError);
+ } else if (numResultsProcessed === numPixels - 1) {
+ return callback(null, results);
+ } else {
+ return numResultsProcessed++;
+ }
+ };
+ }
+ }
+
+ function processResults(result, callback, _logging, _datumEnum) {
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
+
+ var processor = (0, _processQueryResults2.default)(_logging, updateQueryTimes);
+ var processResultsObject = processor(options, _datumEnum, result, callback);
+ return processResultsObject;
+ }
+
+ function invertDatumTypes(datumEnum) {
+ var datumType = TDatumType;
+ for (var key in datumType) {
+ if (datumType.hasOwnProperty(key)) {
+ datumEnum[datumType[key]] = key;
+ }
+ }
+ }
function resetThriftClientOnArgumentErrorForMethods(connector, client, methodNames) {
methodNames.forEach(function (methodName) {
@@ -1416,14 +1004,13 @@
});
}
- // Set a global mapdcon function when mapdcon is brought in via script tag.
- if (( false ? "undefined" : _typeof(module)) === "object" && module.exports) {
- if (!isNodeRuntime()) {
- window.MapdCon = MapdCon;
+ function normalizeError(error) {
+ if (isNodeRuntime()) {
+ return new Error(error.name + " " + error.error_msg);
+ } else {
+ return new Error("TMapDException " + error.message);
}
}
- module.exports = MapdCon;
- exports.default = MapdCon;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9)(module)))
/***/ }),
@@ -1512,8 +1099,8 @@
};
MapDClientV2.prototype.get_result_row_for_pixel = function () {
- var getResultRowForPixelWithErrorHandling = (0, _wrapWithErrorHandling.wrapWithErrorHandling)(this, "get_result_row_for_pixel");
- return getResultRowForPixelWithErrorHandling.apply(undefined, arguments);
+ var getPixelWithErrorHandling = (0, _wrapWithErrorHandling.wrapWithErrorHandling)(this, "get_result_row_for_pixel");
+ return getPixelWithErrorHandling.apply(undefined, arguments);
};
MapDClientV2.prototype.delete_frontend_view = function () {
@@ -1600,7 +1187,7 @@
exports.wrapMethod = wrapMethod;
exports.wrapWithErrorHandling = wrapWithErrorHandling;
var MapDClient = typeof window !== "undefined" && window.MapDClient || __webpack_require__(13).Client; // eslint-disable-line global-require
- var TMapDException = typeof window !== "undefined" && window.TMapDException || __webpack_require__(116).TMapDException; // eslint-disable-line global-require
+ var TMapDException = typeof window !== "undefined" && window.TMapDException || __webpack_require__(117).TMapDException; // eslint-disable-line global-require
var Thrift = typeof window !== "undefined" && window.Thrift || __webpack_require__(14).Thrift; // eslint-disable-line global-require
function isResultError(result) {
@@ -1672,7 +1259,7 @@
var Thrift = thrift.Thrift;
var Q = thrift.Q;
- var ttypes = __webpack_require__(116);
+ var ttypes = __webpack_require__(117);
//HELPER FUNCTIONS AND STRUCTURES
var MapD_connect_args = function MapD_connect_args(args) {
@@ -12455,28 +12042,28 @@
exports.createHttpConnection = httpConnection.createHttpConnection;
exports.createHttpClient = httpConnection.createHttpClient;
- var wsConnection = __webpack_require__(66);
+ var wsConnection = __webpack_require__(67);
exports.WSConnection = wsConnection.WSConnection;
exports.createWSConnection = wsConnection.createWSConnection;
exports.createWSClient = wsConnection.createWSClient;
- var xhrConnection = __webpack_require__(75);
+ var xhrConnection = __webpack_require__(76);
exports.XHRConnection = xhrConnection.XHRConnection;
exports.createXHRConnection = xhrConnection.createXHRConnection;
exports.createXHRClient = xhrConnection.createXHRClient;
- var server = __webpack_require__(76);
+ var server = __webpack_require__(77);
exports.createServer = server.createServer;
exports.createMultiplexServer = server.createMultiplexServer;
- var web_server = __webpack_require__(77);
+ var web_server = __webpack_require__(78);
exports.createWebServer = web_server.createWebServer;
exports.Int64 = __webpack_require__(32);
- exports.Q = __webpack_require__(114);
+ exports.Q = __webpack_require__(115);
- var mprocessor = __webpack_require__(113);
- var mprotocol = __webpack_require__(115);
+ var mprocessor = __webpack_require__(114);
+ var mprotocol = __webpack_require__(116);
exports.Multiplexer = mprotocol.Multiplexer;
exports.MultiplexedProcessor = mprocessor.MultiplexedProcessor;
@@ -12484,11 +12071,11 @@
* Export transport and protocol so they can be used outside of a
* cassandra/server context
*/
- exports.TFramedTransport = __webpack_require__(69);
+ exports.TFramedTransport = __webpack_require__(70);
exports.TBufferedTransport = __webpack_require__(23);
exports.TBinaryProtocol = __webpack_require__(30);
- exports.TJSONProtocol = __webpack_require__(72);
- exports.TCompactProtocol = __webpack_require__(71);
+ exports.TJSONProtocol = __webpack_require__(73);
+ exports.TCompactProtocol = __webpack_require__(72);
/***/ }),
@@ -16242,22 +15829,22 @@
function byteLength (b64) {
// base64 is 4/3 + up to two characters of the original data
- return b64.length * 3 / 4 - placeHoldersCount(b64)
+ return (b64.length * 3 / 4) - placeHoldersCount(b64)
}
function toByteArray (b64) {
- var i, j, l, tmp, placeHolders, arr
+ var i, l, tmp, placeHolders, arr
var len = b64.length
placeHolders = placeHoldersCount(b64)
- arr = new Arr(len * 3 / 4 - placeHolders)
+ arr = new Arr((len * 3 / 4) - placeHolders)
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? len - 4 : len
var L = 0
- for (i = 0, j = 0; i < l; i += 4, j += 3) {
+ for (i = 0; i < l; i += 4) {
tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
arr[L++] = (tmp >> 16) & 0xFF
arr[L++] = (tmp >> 8) & 0xFF
@@ -17364,7 +16951,7 @@
*/
var util = __webpack_require__(16);
var http = __webpack_require__(35);
- var https = __webpack_require__(65);
+ var https = __webpack_require__(66);
var EventEmitter = __webpack_require__(21).EventEmitter;
var thrift = __webpack_require__(15);
@@ -17590,9 +17177,9 @@
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global) {var ClientRequest = __webpack_require__(36)
- var extend = __webpack_require__(57)
- var statusCodes = __webpack_require__(58)
- var url = __webpack_require__(59)
+ var extend = __webpack_require__(58)
+ var statusCodes = __webpack_require__(59)
+ var url = __webpack_require__(60)
var http = exports
@@ -17678,7 +17265,7 @@
var inherits = __webpack_require__(38)
var response = __webpack_require__(39)
var stream = __webpack_require__(40)
- var toArrayBuffer = __webpack_require__(56)
+ var toArrayBuffer = __webpack_require__(57)
var IncomingMessage = response.IncomingMessage
var rStates = response.readyStates
@@ -18284,24 +17871,46 @@
exports = module.exports = __webpack_require__(41);
exports.Stream = exports;
exports.Readable = exports;
- exports.Writable = __webpack_require__(49);
- exports.Duplex = __webpack_require__(48);
- exports.Transform = __webpack_require__(54);
- exports.PassThrough = __webpack_require__(55);
+ exports.Writable = __webpack_require__(50);
+ exports.Duplex = __webpack_require__(49);
+ exports.Transform = __webpack_require__(55);
+ exports.PassThrough = __webpack_require__(56);
/***/ }),
/* 41 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(process) {'use strict';
+ /* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
- module.exports = Readable;
+ 'use strict';
/**/
+
var processNextTick = __webpack_require__(42);
/* */
+ module.exports = Readable;
+
/**/
var isArray = __webpack_require__(27);
/* */
@@ -18324,9 +17933,16 @@
var Stream = __webpack_require__(43);
/**/
- var Buffer = __webpack_require__(24).Buffer;
+ // TODO(bmeurer): Change this back to const once hole checks are
+ // properly optimized away early in Ignition+TurboFan.
/**/
- var bufferShim = __webpack_require__(44);
+ var Buffer = __webpack_require__(44).Buffer;
+ function _uint8ArrayToBuffer(chunk) {
+ return Buffer.from(chunk);
+ }
+ function _isUint8Array(obj) {
+ return Object.prototype.toString.call(obj) === '[object Uint8Array]' || Buffer.isBuffer(obj);
+ }
/* */
/**/
@@ -18345,6 +17961,7 @@
/* */
var BufferList = __webpack_require__(47);
+ var destroyImpl = __webpack_require__(48);
var StringDecoder;
util.inherits(Readable, Stream);
@@ -18366,7 +17983,7 @@
}
function ReadableState(options, stream) {
- Duplex = Duplex || __webpack_require__(48);
+ Duplex = Duplex || __webpack_require__(49);
options = options || {};
@@ -18383,7 +18000,7 @@
this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
// cast to ints.
- this.highWaterMark = ~~this.highWaterMark;
+ this.highWaterMark = Math.floor(this.highWaterMark);
// A linked list is used to store data chunks instead of an array because the
// linked list can remove elements from the beginning faster than
@@ -18397,10 +18014,10 @@
this.endEmitted = false;
this.reading = false;
- // a flag to be able to tell if the onwrite cb is called immediately,
- // or on a later tick. We set this to true at first, because any
- // actions that shouldn't happen until "later" should generally also
- // not happen before the first write call.
+ // a flag to be able to tell if the event 'readable'/'data' is emitted
+ // immediately, or on a later tick. We set this to true at first, because
+ // any actions that shouldn't happen until "later" should generally also
+ // not happen before the first read call.
this.sync = true;
// whenever we return null, then we set a flag to say
@@ -18410,15 +18027,14 @@
this.readableListening = false;
this.resumeScheduled = false;
+ // has it been destroyed
+ this.destroyed = false;
+
// Crypto is kind of old and crusty. Historically, its default string
// encoding is 'binary' so we have to make this configurable.
// Everything else in the universe uses 'utf8', though.
this.defaultEncoding = options.defaultEncoding || 'utf8';
- // when piping, we only care about 'readable' events that happen
- // after read()ing all the bytes and not getting any pushback.
- this.ranOut = false;
-
// the number of writers that are awaiting a drain event in .pipe()s
this.awaitDrain = 0;
@@ -18428,14 +18044,14 @@
this.decoder = null;
this.encoding = null;
if (options.encoding) {
- if (!StringDecoder) StringDecoder = __webpack_require__(53).StringDecoder;
+ if (!StringDecoder) StringDecoder = __webpack_require__(54).StringDecoder;
this.decoder = new StringDecoder(options.encoding);
this.encoding = options.encoding;
}
}
function Readable(options) {
- Duplex = Duplex || __webpack_require__(48);
+ Duplex = Duplex || __webpack_require__(49);
if (!(this instanceof Readable)) return new Readable(options);
@@ -18444,87 +18060,129 @@
// legacy
this.readable = true;
- if (options && typeof options.read === 'function') this._read = options.read;
+ if (options) {
+ if (typeof options.read === 'function') this._read = options.read;
+
+ if (typeof options.destroy === 'function') this._destroy = options.destroy;
+ }
Stream.call(this);
}
+ Object.defineProperty(Readable.prototype, 'destroyed', {
+ get: function () {
+ if (this._readableState === undefined) {
+ return false;
+ }
+ return this._readableState.destroyed;
+ },
+ set: function (value) {
+ // we ignore the value if the stream
+ // has not been initialized yet
+ if (!this._readableState) {
+ return;
+ }
+
+ // backward compatibility, the user is explicitly
+ // managing destroyed
+ this._readableState.destroyed = value;
+ }
+ });
+
+ Readable.prototype.destroy = destroyImpl.destroy;
+ Readable.prototype._undestroy = destroyImpl.undestroy;
+ Readable.prototype._destroy = function (err, cb) {
+ this.push(null);
+ cb(err);
+ };
+
// Manually shove something into the read() buffer.
// This returns true if the highWaterMark has not been hit yet,
// similar to how Writable.write() returns true if you should
// write() some more.
Readable.prototype.push = function (chunk, encoding) {
var state = this._readableState;
+ var skipChunkCheck;
- if (!state.objectMode && typeof chunk === 'string') {
- encoding = encoding || state.defaultEncoding;
- if (encoding !== state.encoding) {
- chunk = bufferShim.from(chunk, encoding);
- encoding = '';
+ if (!state.objectMode) {
+ if (typeof chunk === 'string') {
+ encoding = encoding || state.defaultEncoding;
+ if (encoding !== state.encoding) {
+ chunk = Buffer.from(chunk, encoding);
+ encoding = '';
+ }
+ skipChunkCheck = true;
}
+ } else {
+ skipChunkCheck = true;
}
- return readableAddChunk(this, state, chunk, encoding, false);
+ return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
};
// Unshift should *always* be something directly out of read()
Readable.prototype.unshift = function (chunk) {
- var state = this._readableState;
- return readableAddChunk(this, state, chunk, '', true);
- };
-
- Readable.prototype.isPaused = function () {
- return this._readableState.flowing === false;
+ return readableAddChunk(this, chunk, null, true, false);
};
- function readableAddChunk(stream, state, chunk, encoding, addToFront) {
- var er = chunkInvalid(state, chunk);
- if (er) {
- stream.emit('error', er);
- } else if (chunk === null) {
+ function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
+ var state = stream._readableState;
+ if (chunk === null) {
state.reading = false;
onEofChunk(stream, state);
- } else if (state.objectMode || chunk && chunk.length > 0) {
- if (state.ended && !addToFront) {
- var e = new Error('stream.push() after EOF');
- stream.emit('error', e);
- } else if (state.endEmitted && addToFront) {
- var _e = new Error('stream.unshift() after end event');
- stream.emit('error', _e);
- } else {
- var skipAdd;
- if (state.decoder && !addToFront && !encoding) {
- chunk = state.decoder.write(chunk);
- skipAdd = !state.objectMode && chunk.length === 0;
- }
-
- if (!addToFront) state.reading = false;
-
- // Don't add to the buffer if we've decoded to an empty string chunk and
- // we're not in object mode
- if (!skipAdd) {
- // if we want the data now, just emit it.
- if (state.flowing && state.length === 0 && !state.sync) {
- stream.emit('data', chunk);
- stream.read(0);
+ } else {
+ var er;
+ if (!skipChunkCheck) er = chunkInvalid(state, chunk);
+ if (er) {
+ stream.emit('error', er);
+ } else if (state.objectMode || chunk && chunk.length > 0) {
+ if (typeof chunk !== 'string' && Object.getPrototypeOf(chunk) !== Buffer.prototype && !state.objectMode) {
+ chunk = _uint8ArrayToBuffer(chunk);
+ }
+
+ if (addToFront) {
+ if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true);
+ } else if (state.ended) {
+ stream.emit('error', new Error('stream.push() after EOF'));
+ } else {
+ state.reading = false;
+ if (state.decoder && !encoding) {
+ chunk = state.decoder.write(chunk);
+ if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state);
} else {
- // update the buffer info.
- state.length += state.objectMode ? 1 : chunk.length;
- if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
-
- if (state.needReadable) emitReadable(stream);
+ addChunk(stream, state, chunk, false);
}
}
-
- maybeReadMore(stream, state);
+ } else if (!addToFront) {
+ state.reading = false;
}
- } else if (!addToFront) {
- state.reading = false;
}
return needMoreData(state);
}
+ function addChunk(stream, state, chunk, addToFront) {
+ if (state.flowing && state.length === 0 && !state.sync) {
+ stream.emit('data', chunk);
+ stream.read(0);
+ } else {
+ // update the buffer info.
+ state.length += state.objectMode ? 1 : chunk.length;
+ if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk);
+
+ if (state.needReadable) emitReadable(stream);
+ }
+ maybeReadMore(stream, state);
+ }
+
+ function chunkInvalid(state, chunk) {
+ var er;
+ if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) {
+ er = new TypeError('Invalid non-string/buffer chunk');
+ }
+ return er;
+ }
+
// if it's past the high water mark, we can push in some more.
// Also, if we have no data yet, we can stand some
// more bytes. This is to work around cases where hwm=0,
@@ -18536,9 +18194,13 @@
return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0);
}
+ Readable.prototype.isPaused = function () {
+ return this._readableState.flowing === false;
+ };
+
// backwards compatibility.
Readable.prototype.setEncoding = function (enc) {
- if (!StringDecoder) StringDecoder = __webpack_require__(53).StringDecoder;
+ if (!StringDecoder) StringDecoder = __webpack_require__(54).StringDecoder;
this._readableState.decoder = new StringDecoder(enc);
this._readableState.encoding = enc;
return this;
@@ -18684,14 +18346,6 @@
return ret;
};
- function chunkInvalid(state, chunk) {
- var er = null;
- if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) {
- er = new TypeError('Invalid non-string/buffer chunk');
- }
- return er;
- }
-
function onEofChunk(stream, state) {
if (state.ended) return;
if (state.decoder) {
@@ -18779,14 +18433,17 @@
var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr;
- var endFn = doEnd ? onend : cleanup;
+ var endFn = doEnd ? onend : unpipe;
if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn);
dest.on('unpipe', onunpipe);
- function onunpipe(readable) {
+ function onunpipe(readable, unpipeInfo) {
debug('onunpipe');
if (readable === src) {
- cleanup();
+ if (unpipeInfo && unpipeInfo.hasUnpiped === false) {
+ unpipeInfo.hasUnpiped = true;
+ cleanup();
+ }
}
}
@@ -18812,7 +18469,7 @@
dest.removeListener('error', onerror);
dest.removeListener('unpipe', onunpipe);
src.removeListener('end', onend);
- src.removeListener('end', cleanup);
+ src.removeListener('end', unpipe);
src.removeListener('data', ondata);
cleanedUp = true;
@@ -18905,6 +18562,7 @@
Readable.prototype.unpipe = function (dest) {
var state = this._readableState;
+ var unpipeInfo = { hasUnpiped: false };
// if we're not piping anywhere, then do nothing.
if (state.pipesCount === 0) return this;
@@ -18920,7 +18578,7 @@
state.pipes = null;
state.pipesCount = 0;
state.flowing = false;
- if (dest) dest.emit('unpipe', this);
+ if (dest) dest.emit('unpipe', this, unpipeInfo);
return this;
}
@@ -18935,7 +18593,7 @@
state.flowing = false;
for (var i = 0; i < len; i++) {
- dests[i].emit('unpipe', this);
+ dests[i].emit('unpipe', this, unpipeInfo);
}return this;
}
@@ -18947,7 +18605,7 @@
state.pipesCount -= 1;
if (state.pipesCount === 1) state.pipes = state.pipes[0];
- dest.emit('unpipe', this);
+ dest.emit('unpipe', this, unpipeInfo);
return this;
};
@@ -18968,7 +18626,7 @@
if (!state.reading) {
processNextTick(nReadingNextTick, this);
} else if (state.length) {
- emitReadable(this, state);
+ emitReadable(this);
}
}
}
@@ -19169,7 +18827,7 @@
// This function is designed to be inlinable, so please take care when making
// changes to the function body.
function copyFromBuffer(n, list) {
- var ret = bufferShim.allocUnsafe(n);
+ var ret = Buffer.allocUnsafe(n);
var p = list.head;
var c = 1;
p.data.copy(ret);
@@ -19292,116 +18950,69 @@
/* 44 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(global) {'use strict';
+ /* eslint-disable node/no-deprecated-api */
+ var buffer = __webpack_require__(24)
+ var Buffer = buffer.Buffer
- var buffer = __webpack_require__(24);
- var Buffer = buffer.Buffer;
- var SlowBuffer = buffer.SlowBuffer;
- var MAX_LEN = buffer.kMaxLength || 2147483647;
- exports.alloc = function alloc(size, fill, encoding) {
- if (typeof Buffer.alloc === 'function') {
- return Buffer.alloc(size, fill, encoding);
+ // alternative to using Object.keys for old browsers
+ function copyProps (src, dst) {
+ for (var key in src) {
+ dst[key] = src[key]
}
- if (typeof encoding === 'number') {
- throw new TypeError('encoding must not be number');
+ }
+ if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
+ module.exports = buffer
+ } else {
+ // Copy properties from require('buffer')
+ copyProps(buffer, exports)
+ exports.Buffer = SafeBuffer
+ }
+
+ function SafeBuffer (arg, encodingOrOffset, length) {
+ return Buffer(arg, encodingOrOffset, length)
+ }
+
+ // Copy static methods from Buffer
+ copyProps(Buffer, SafeBuffer)
+
+ SafeBuffer.from = function (arg, encodingOrOffset, length) {
+ if (typeof arg === 'number') {
+ throw new TypeError('Argument must not be a number')
}
+ return Buffer(arg, encodingOrOffset, length)
+ }
+
+ SafeBuffer.alloc = function (size, fill, encoding) {
if (typeof size !== 'number') {
- throw new TypeError('size must be a number');
- }
- if (size > MAX_LEN) {
- throw new RangeError('size is too large');
- }
- var enc = encoding;
- var _fill = fill;
- if (_fill === undefined) {
- enc = undefined;
- _fill = 0;
+ throw new TypeError('Argument must be a number')
}
- var buf = new Buffer(size);
- if (typeof _fill === 'string') {
- var fillBuf = new Buffer(_fill, enc);
- var flen = fillBuf.length;
- var i = -1;
- while (++i < size) {
- buf[i] = fillBuf[i % flen];
+ var buf = Buffer(size)
+ if (fill !== undefined) {
+ if (typeof encoding === 'string') {
+ buf.fill(fill, encoding)
+ } else {
+ buf.fill(fill)
}
} else {
- buf.fill(_fill);
+ buf.fill(0)
}
- return buf;
+ return buf
}
- exports.allocUnsafe = function allocUnsafe(size) {
- if (typeof Buffer.allocUnsafe === 'function') {
- return Buffer.allocUnsafe(size);
- }
+
+ SafeBuffer.allocUnsafe = function (size) {
if (typeof size !== 'number') {
- throw new TypeError('size must be a number');
- }
- if (size > MAX_LEN) {
- throw new RangeError('size is too large');
+ throw new TypeError('Argument must be a number')
}
- return new Buffer(size);
+ return Buffer(size)
}
- exports.from = function from(value, encodingOrOffset, length) {
- if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) {
- return Buffer.from(value, encodingOrOffset, length);
- }
- if (typeof value === 'number') {
- throw new TypeError('"value" argument must not be a number');
- }
- if (typeof value === 'string') {
- return new Buffer(value, encodingOrOffset);
- }
- if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
- var offset = encodingOrOffset;
- if (arguments.length === 1) {
- return new Buffer(value);
- }
- if (typeof offset === 'undefined') {
- offset = 0;
- }
- var len = length;
- if (typeof len === 'undefined') {
- len = value.byteLength - offset;
- }
- if (offset >= value.byteLength) {
- throw new RangeError('\'offset\' is out of bounds');
- }
- if (len > value.byteLength - offset) {
- throw new RangeError('\'length\' is out of bounds');
- }
- return new Buffer(value.slice(offset, offset + len));
- }
- if (Buffer.isBuffer(value)) {
- var out = new Buffer(value.length);
- value.copy(out, 0, 0, value.length);
- return out;
- }
- if (value) {
- if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) {
- return new Buffer(value);
- }
- if (value.type === 'Buffer' && Array.isArray(value.data)) {
- return new Buffer(value.data);
- }
- }
- throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.');
- }
- exports.allocUnsafeSlow = function allocUnsafeSlow(size) {
- if (typeof Buffer.allocUnsafeSlow === 'function') {
- return Buffer.allocUnsafeSlow(size);
- }
+ SafeBuffer.allocUnsafeSlow = function (size) {
if (typeof size !== 'number') {
- throw new TypeError('size must be a number');
+ throw new TypeError('Argument must be a number')
}
- if (size >= MAX_LEN) {
- throw new RangeError('size is too large');
- }
- return new SlowBuffer(size);
+ return buffer.SlowBuffer(size)
}
- /* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ }),
/* 45 */
@@ -19529,73 +19140,181 @@
'use strict';
- var Buffer = __webpack_require__(24).Buffer;
/**/
- var bufferShim = __webpack_require__(44);
- /* */
- module.exports = BufferList;
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- function BufferList() {
- this.head = null;
- this.tail = null;
- this.length = 0;
+ var Buffer = __webpack_require__(44).Buffer;
+ /**/
+
+ function copyBuffer(src, target, offset) {
+ src.copy(target, offset);
}
- BufferList.prototype.push = function (v) {
- var entry = { data: v, next: null };
- if (this.length > 0) this.tail.next = entry;else this.head = entry;
- this.tail = entry;
- ++this.length;
- };
+ module.exports = function () {
+ function BufferList() {
+ _classCallCheck(this, BufferList);
- BufferList.prototype.unshift = function (v) {
- var entry = { data: v, next: this.head };
- if (this.length === 0) this.tail = entry;
- this.head = entry;
- ++this.length;
- };
+ this.head = null;
+ this.tail = null;
+ this.length = 0;
+ }
- BufferList.prototype.shift = function () {
- if (this.length === 0) return;
- var ret = this.head.data;
- if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
- --this.length;
- return ret;
- };
+ BufferList.prototype.push = function push(v) {
+ var entry = { data: v, next: null };
+ if (this.length > 0) this.tail.next = entry;else this.head = entry;
+ this.tail = entry;
+ ++this.length;
+ };
- BufferList.prototype.clear = function () {
- this.head = this.tail = null;
- this.length = 0;
- };
+ BufferList.prototype.unshift = function unshift(v) {
+ var entry = { data: v, next: this.head };
+ if (this.length === 0) this.tail = entry;
+ this.head = entry;
+ ++this.length;
+ };
- BufferList.prototype.join = function (s) {
- if (this.length === 0) return '';
- var p = this.head;
- var ret = '' + p.data;
- while (p = p.next) {
- ret += s + p.data;
- }return ret;
- };
+ BufferList.prototype.shift = function shift() {
+ if (this.length === 0) return;
+ var ret = this.head.data;
+ if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
+ --this.length;
+ return ret;
+ };
+
+ BufferList.prototype.clear = function clear() {
+ this.head = this.tail = null;
+ this.length = 0;
+ };
+
+ BufferList.prototype.join = function join(s) {
+ if (this.length === 0) return '';
+ var p = this.head;
+ var ret = '' + p.data;
+ while (p = p.next) {
+ ret += s + p.data;
+ }return ret;
+ };
+
+ BufferList.prototype.concat = function concat(n) {
+ if (this.length === 0) return Buffer.alloc(0);
+ if (this.length === 1) return this.head.data;
+ var ret = Buffer.allocUnsafe(n >>> 0);
+ var p = this.head;
+ var i = 0;
+ while (p) {
+ copyBuffer(p.data, ret, i);
+ i += p.data.length;
+ p = p.next;
+ }
+ return ret;
+ };
+
+ return BufferList;
+ }();
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ /**/
- BufferList.prototype.concat = function (n) {
- if (this.length === 0) return bufferShim.alloc(0);
- if (this.length === 1) return this.head.data;
- var ret = bufferShim.allocUnsafe(n >>> 0);
- var p = this.head;
- var i = 0;
- while (p) {
- p.data.copy(ret, i);
- i += p.data.length;
- p = p.next;
+ var processNextTick = __webpack_require__(42);
+ /* */
+
+ // undocumented cb() API, needed for core, not for public API
+ function destroy(err, cb) {
+ var _this = this;
+
+ var readableDestroyed = this._readableState && this._readableState.destroyed;
+ var writableDestroyed = this._writableState && this._writableState.destroyed;
+
+ if (readableDestroyed || writableDestroyed) {
+ if (cb) {
+ cb(err);
+ } else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
+ processNextTick(emitErrorNT, this, err);
+ }
+ return;
}
- return ret;
+
+ // we set destroyed to true before firing error callbacks in order
+ // to make it re-entrance safe in case destroy() is called within callbacks
+
+ if (this._readableState) {
+ this._readableState.destroyed = true;
+ }
+
+ // if this is a duplex stream mark the writable part as destroyed as well
+ if (this._writableState) {
+ this._writableState.destroyed = true;
+ }
+
+ this._destroy(err || null, function (err) {
+ if (!cb && err) {
+ processNextTick(emitErrorNT, _this, err);
+ if (_this._writableState) {
+ _this._writableState.errorEmitted = true;
+ }
+ } else if (cb) {
+ cb(err);
+ }
+ });
+ }
+
+ function undestroy() {
+ if (this._readableState) {
+ this._readableState.destroyed = false;
+ this._readableState.reading = false;
+ this._readableState.ended = false;
+ this._readableState.endEmitted = false;
+ }
+
+ if (this._writableState) {
+ this._writableState.destroyed = false;
+ this._writableState.ended = false;
+ this._writableState.ending = false;
+ this._writableState.finished = false;
+ this._writableState.errorEmitted = false;
+ }
+ }
+
+ function emitErrorNT(self, err) {
+ self.emit('error', err);
+ }
+
+ module.exports = {
+ destroy: destroy,
+ undestroy: undestroy
};
/***/ }),
-/* 48 */
+/* 49 */
/***/ (function(module, exports, __webpack_require__) {
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
// a duplex stream is just a stream that is both readable and writable.
// Since JS doesn't have multiple prototypal inheritance, this class
// prototypally inherits from Readable, and then parasitically from
@@ -19605,6 +19324,10 @@
/**/
+ var processNextTick = __webpack_require__(42);
+ /* */
+
+ /**/
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
@@ -19615,17 +19338,13 @@
module.exports = Duplex;
- /**/
- var processNextTick = __webpack_require__(42);
- /* */
-
/**/
var util = __webpack_require__(45);
util.inherits = __webpack_require__(38);
/* */
var Readable = __webpack_require__(41);
- var Writable = __webpack_require__(49);
+ var Writable = __webpack_require__(50);
util.inherits(Duplex, Readable);
@@ -19666,6 +19385,34 @@
self.end();
}
+ Object.defineProperty(Duplex.prototype, 'destroyed', {
+ get: function () {
+ if (this._readableState === undefined || this._writableState === undefined) {
+ return false;
+ }
+ return this._readableState.destroyed && this._writableState.destroyed;
+ },
+ set: function (value) {
+ // we ignore the value if the stream
+ // has not been initialized yet
+ if (this._readableState === undefined || this._writableState === undefined) {
+ return;
+ }
+
+ // backward compatibility, the user is explicitly
+ // managing destroyed
+ this._readableState.destroyed = value;
+ this._writableState.destroyed = value;
+ }
+ });
+
+ Duplex.prototype._destroy = function (err, cb) {
+ this.push(null);
+ this.end();
+
+ processNextTick(cb, err);
+ };
+
function forEach(xs, f) {
for (var i = 0, l = xs.length; i < l; i++) {
f(xs[i], i);
@@ -19673,21 +19420,64 @@
}
/***/ }),
-/* 49 */
+/* 50 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(process, setImmediate) {// A bit simpler than readable streams.
+ /* WEBPACK VAR INJECTION */(function(process, setImmediate) {// Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ // A bit simpler than readable streams.
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
// the drain event emission and buffering.
'use strict';
- module.exports = Writable;
-
/**/
+
var processNextTick = __webpack_require__(42);
/* */
+ module.exports = Writable;
+
+ /* */
+ function WriteReq(chunk, encoding, cb) {
+ this.chunk = chunk;
+ this.encoding = encoding;
+ this.callback = cb;
+ this.next = null;
+ }
+
+ // It seems a linked list but it is not
+ // there will be only 2 of these for each stream
+ function CorkedRequest(state) {
+ var _this = this;
+
+ this.next = null;
+ this.entry = null;
+ this.finish = function () {
+ onCorkedFinish(_this, state);
+ };
+ }
+ /* */
+
/**/
var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick;
/* */
@@ -19705,7 +19495,7 @@
/**/
var internalUtil = {
- deprecate: __webpack_require__(52)
+ deprecate: __webpack_require__(53)
};
/* */
@@ -19713,24 +19503,24 @@
var Stream = __webpack_require__(43);
/* */
- var Buffer = __webpack_require__(24).Buffer;
/**/
- var bufferShim = __webpack_require__(44);
+ var Buffer = __webpack_require__(44).Buffer;
+ function _uint8ArrayToBuffer(chunk) {
+ return Buffer.from(chunk);
+ }
+ function _isUint8Array(obj) {
+ return Object.prototype.toString.call(obj) === '[object Uint8Array]' || Buffer.isBuffer(obj);
+ }
/* */
+ var destroyImpl = __webpack_require__(48);
+
util.inherits(Writable, Stream);
function nop() {}
- function WriteReq(chunk, encoding, cb) {
- this.chunk = chunk;
- this.encoding = encoding;
- this.callback = cb;
- this.next = null;
- }
-
function WritableState(options, stream) {
- Duplex = Duplex || __webpack_require__(48);
+ Duplex = Duplex || __webpack_require__(49);
options = options || {};
@@ -19748,7 +19538,10 @@
this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm;
// cast to ints.
- this.highWaterMark = ~~this.highWaterMark;
+ this.highWaterMark = Math.floor(this.highWaterMark);
+
+ // if _final has been called
+ this.finalCalled = false;
// drain event flag.
this.needDrain = false;
@@ -19759,6 +19552,9 @@
// when 'finish' is emitted
this.finished = false;
+ // has it been destroyed
+ this.destroyed = false;
+
// should we decode strings into buffers before passing to _write?
// this is here so that some node-core streams can optimize string
// handling at a lower level.
@@ -19840,7 +19636,7 @@
Object.defineProperty(WritableState.prototype, 'buffer', {
get: internalUtil.deprecate(function () {
return this.getBuffer();
- }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.')
+ }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
});
} catch (_) {}
})();
@@ -19864,7 +19660,7 @@
}
function Writable(options) {
- Duplex = Duplex || __webpack_require__(48);
+ Duplex = Duplex || __webpack_require__(49);
// Writable ctor is applied to Duplexes, too.
// `realHasInstance` is necessary because using plain `instanceof`
@@ -19886,6 +19682,10 @@
if (typeof options.write === 'function') this._write = options.write;
if (typeof options.writev === 'function') this._writev = options.writev;
+
+ if (typeof options.destroy === 'function') this._destroy = options.destroy;
+
+ if (typeof options.final === 'function') this._final = options.final;
}
Stream.call(this);
@@ -19926,7 +19726,11 @@
Writable.prototype.write = function (chunk, encoding, cb) {
var state = this._writableState;
var ret = false;
- var isBuf = Buffer.isBuffer(chunk);
+ var isBuf = _isUint8Array(chunk) && !state.objectMode;
+
+ if (isBuf && !Buffer.isBuffer(chunk)) {
+ chunk = _uint8ArrayToBuffer(chunk);
+ }
if (typeof encoding === 'function') {
cb = encoding;
@@ -19971,7 +19775,7 @@
function decodeChunk(state, chunk, encoding) {
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
- chunk = bufferShim.from(chunk, encoding);
+ chunk = Buffer.from(chunk, encoding);
}
return chunk;
}
@@ -19981,8 +19785,12 @@
// If we return false, then we need a drain event, so set that flag.
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
if (!isBuf) {
- chunk = decodeChunk(state, chunk, encoding);
- if (Buffer.isBuffer(chunk)) encoding = 'buffer';
+ var newChunk = decodeChunk(state, chunk, encoding);
+ if (chunk !== newChunk) {
+ isBuf = true;
+ encoding = 'buffer';
+ chunk = newChunk;
+ }
}
var len = state.objectMode ? 1 : chunk.length;
@@ -19994,7 +19802,13 @@
if (state.writing || state.corked) {
var last = state.lastBufferedRequest;
- state.lastBufferedRequest = new WriteReq(chunk, encoding, cb);
+ state.lastBufferedRequest = {
+ chunk: chunk,
+ encoding: encoding,
+ isBuf: isBuf,
+ callback: cb,
+ next: null
+ };
if (last) {
last.next = state.lastBufferedRequest;
} else {
@@ -20019,10 +19833,26 @@
function onwriteError(stream, state, sync, er, cb) {
--state.pendingcb;
- if (sync) processNextTick(cb, er);else cb(er);
- stream._writableState.errorEmitted = true;
- stream.emit('error', er);
+ if (sync) {
+ // defer the callback if we are being called synchronously
+ // to avoid piling up things on the stack
+ processNextTick(cb, er);
+ // this can emit finish, and it will always happen
+ // after error
+ processNextTick(finishMaybe, stream, state);
+ stream._writableState.errorEmitted = true;
+ stream.emit('error', er);
+ } else {
+ // the caller expect this to happen before if
+ // it is async
+ cb(er);
+ stream._writableState.errorEmitted = true;
+ stream.emit('error', er);
+ // this can emit finish, but finish must
+ // always follow error
+ finishMaybe(stream, state);
+ }
}
function onwriteStateUpdate(state) {
@@ -20087,11 +19917,14 @@
holder.entry = entry;
var count = 0;
+ var allBuffers = true;
while (entry) {
buffer[count] = entry;
+ if (!entry.isBuf) allBuffers = false;
entry = entry.next;
count += 1;
}
+ buffer.allBuffers = allBuffers;
doWrite(stream, state, true, state.length, buffer, '', holder.finish);
@@ -20165,23 +19998,37 @@
function needFinish(state) {
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
}
-
- function prefinish(stream, state) {
- if (!state.prefinished) {
+ function callFinal(stream, state) {
+ stream._final(function (err) {
+ state.pendingcb--;
+ if (err) {
+ stream.emit('error', err);
+ }
state.prefinished = true;
stream.emit('prefinish');
+ finishMaybe(stream, state);
+ });
+ }
+ function prefinish(stream, state) {
+ if (!state.prefinished && !state.finalCalled) {
+ if (typeof stream._final === 'function') {
+ state.pendingcb++;
+ state.finalCalled = true;
+ processNextTick(callFinal, stream, state);
+ } else {
+ state.prefinished = true;
+ stream.emit('prefinish');
+ }
}
}
function finishMaybe(stream, state) {
var need = needFinish(state);
if (need) {
+ prefinish(stream, state);
if (state.pendingcb === 0) {
- prefinish(stream, state);
state.finished = true;
stream.emit('finish');
- } else {
- prefinish(stream, state);
}
}
return need;
@@ -20197,33 +20044,53 @@
stream.writable = false;
}
- // It seems a linked list but it is not
- // there will be only 2 of these for each stream
- function CorkedRequest(state) {
- var _this = this;
+ function onCorkedFinish(corkReq, state, err) {
+ var entry = corkReq.entry;
+ corkReq.entry = null;
+ while (entry) {
+ var cb = entry.callback;
+ state.pendingcb--;
+ cb(err);
+ entry = entry.next;
+ }
+ if (state.corkedRequestsFree) {
+ state.corkedRequestsFree.next = corkReq;
+ } else {
+ state.corkedRequestsFree = corkReq;
+ }
+ }
- this.next = null;
- this.entry = null;
- this.finish = function (err) {
- var entry = _this.entry;
- _this.entry = null;
- while (entry) {
- var cb = entry.callback;
- state.pendingcb--;
- cb(err);
- entry = entry.next;
+ Object.defineProperty(Writable.prototype, 'destroyed', {
+ get: function () {
+ if (this._writableState === undefined) {
+ return false;
}
- if (state.corkedRequestsFree) {
- state.corkedRequestsFree.next = _this;
- } else {
- state.corkedRequestsFree = _this;
+ return this._writableState.destroyed;
+ },
+ set: function (value) {
+ // we ignore the value if the stream
+ // has not been initialized yet
+ if (!this._writableState) {
+ return;
}
- };
- }
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17), __webpack_require__(50).setImmediate))
+
+ // backward compatibility, the user is explicitly
+ // managing destroyed
+ this._writableState.destroyed = value;
+ }
+ });
+
+ Writable.prototype.destroy = destroyImpl.destroy;
+ Writable.prototype._undestroy = destroyImpl.undestroy;
+ Writable.prototype._destroy = function (err, cb) {
+ this.end();
+ cb(err);
+ };
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17), __webpack_require__(51).setImmediate))
/***/ }),
-/* 50 */
+/* 51 */
/***/ (function(module, exports, __webpack_require__) {
var apply = Function.prototype.apply;
@@ -20276,13 +20143,13 @@
};
// setimmediate attaches itself to the global object
- __webpack_require__(51);
+ __webpack_require__(52);
exports.setImmediate = setImmediate;
exports.clearImmediate = clearImmediate;
/***/ }),
-/* 51 */
+/* 52 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) {
@@ -20475,7 +20342,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(17)))
/***/ }),
-/* 52 */
+/* 53 */
/***/ (function(module, exports) {
/* WEBPACK VAR INJECTION */(function(global) {
@@ -20549,13 +20416,12 @@
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
/***/ }),
-/* 53 */
+/* 54 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
- var Buffer = __webpack_require__(24).Buffer;
- var bufferShim = __webpack_require__(44);
+ var Buffer = __webpack_require__(44).Buffer;
var isEncoding = Buffer.isEncoding || function (encoding) {
encoding = '' + encoding;
@@ -20632,7 +20498,7 @@
}
this.lastNeed = 0;
this.lastTotal = 0;
- this.lastChar = bufferShim.allocUnsafe(nb);
+ this.lastChar = Buffer.allocUnsafe(nb);
}
StringDecoder.prototype.write = function (buf) {
@@ -20827,9 +20693,30 @@
}
/***/ }),
-/* 54 */
+/* 55 */
/***/ (function(module, exports, __webpack_require__) {
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
// a transform stream is a readable/writable stream where you do
// something with the data. Sometimes it's called a "filter",
// but that's not a great name for it, since that implies a thing where
@@ -20876,7 +20763,7 @@
module.exports = Transform;
- var Duplex = __webpack_require__(48);
+ var Duplex = __webpack_require__(49);
/**/
var util = __webpack_require__(45);
@@ -20903,7 +20790,9 @@
var cb = ts.writecb;
- if (!cb) return stream.emit('error', new Error('no writecb in Transform class'));
+ if (!cb) {
+ return stream.emit('error', new Error('write callback called multiple times'));
+ }
ts.writechunk = null;
ts.writecb = null;
@@ -20996,6 +20885,15 @@
}
};
+ Transform.prototype._destroy = function (err, cb) {
+ var _this = this;
+
+ Duplex.prototype._destroy.call(this, err, function (err2) {
+ cb(err2);
+ _this.emit('close');
+ });
+ };
+
function done(stream, er, data) {
if (er) return stream.emit('error', er);
@@ -21014,9 +20912,30 @@
}
/***/ }),
-/* 55 */
+/* 56 */
/***/ (function(module, exports, __webpack_require__) {
+ // Copyright Joyent, Inc. and other Node contributors.
+ //
+ // Permission is hereby granted, free of charge, to any person obtaining a
+ // copy of this software and associated documentation files (the
+ // "Software"), to deal in the Software without restriction, including
+ // without limitation the rights to use, copy, modify, merge, publish,
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
+ // persons to whom the Software is furnished to do so, subject to the
+ // following conditions:
+ //
+ // The above copyright notice and this permission notice shall be included
+ // in all copies or substantial portions of the Software.
+ //
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
+
// a passthrough stream.
// basically just the most minimal sort of Transform stream.
// Every written chunk gets output as-is.
@@ -21025,7 +20944,7 @@
module.exports = PassThrough;
- var Transform = __webpack_require__(54);
+ var Transform = __webpack_require__(55);
/**/
var util = __webpack_require__(45);
@@ -21045,7 +20964,7 @@
};
/***/ }),
-/* 56 */
+/* 57 */
/***/ (function(module, exports, __webpack_require__) {
var Buffer = __webpack_require__(24).Buffer
@@ -21078,7 +20997,7 @@
/***/ }),
-/* 57 */
+/* 58 */
/***/ (function(module, exports) {
module.exports = extend
@@ -21103,7 +21022,7 @@
/***/ }),
-/* 58 */
+/* 59 */
/***/ (function(module, exports) {
module.exports = {
@@ -21173,7 +21092,7 @@
/***/ }),
-/* 59 */
+/* 60 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright Joyent, Inc. and other Node contributors.
@@ -21199,8 +21118,8 @@
'use strict';
- var punycode = __webpack_require__(60);
- var util = __webpack_require__(61);
+ var punycode = __webpack_require__(61);
+ var util = __webpack_require__(62);
exports.parse = urlParse;
exports.resolve = urlResolve;
@@ -21275,7 +21194,7 @@
'gopher:': true,
'file:': true
},
- querystring = __webpack_require__(62);
+ querystring = __webpack_require__(63);
function urlParse(url, parseQueryString, slashesDenoteHost) {
if (url && util.isObject(url) && url instanceof Url) return url;
@@ -21911,7 +21830,7 @@
/***/ }),
-/* 60 */
+/* 61 */
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module, global) {/*! https://mths.be/punycode v1.3.2 by @mathias */
@@ -22446,7 +22365,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(9)(module), (function() { return this; }())))
/***/ }),
-/* 61 */
+/* 62 */
/***/ (function(module, exports) {
'use strict';
@@ -22468,17 +22387,17 @@
/***/ }),
-/* 62 */
+/* 63 */
/***/ (function(module, exports, __webpack_require__) {
'use strict';
- exports.decode = exports.parse = __webpack_require__(63);
- exports.encode = exports.stringify = __webpack_require__(64);
+ exports.decode = exports.parse = __webpack_require__(64);
+ exports.encode = exports.stringify = __webpack_require__(65);
/***/ }),
-/* 63 */
+/* 64 */
/***/ (function(module, exports) {
// Copyright Joyent, Inc. and other Node contributors.
@@ -22564,7 +22483,7 @@
/***/ }),
-/* 64 */
+/* 65 */
/***/ (function(module, exports) {
// Copyright Joyent, Inc. and other Node contributors.
@@ -22634,7 +22553,7 @@
/***/ }),
-/* 65 */
+/* 66 */
/***/ (function(module, exports, __webpack_require__) {
var http = __webpack_require__(35);
@@ -22654,7 +22573,7 @@
/***/ }),
-/* 66 */
+/* 67 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -22676,14 +22595,14 @@
* under the License.
*/
var util = __webpack_require__(16);
- var WebSocket = __webpack_require__(67);
+ var WebSocket = __webpack_require__(68);
var EventEmitter = __webpack_require__(21).EventEmitter;
var thrift = __webpack_require__(15);
- var ttransport = __webpack_require__(68);
- var tprotocol = __webpack_require__(70);
+ var ttransport = __webpack_require__(69);
+ var tprotocol = __webpack_require__(71);
var TBufferedTransport = __webpack_require__(23);
- var TJSONProtocol = __webpack_require__(72);
+ var TJSONProtocol = __webpack_require__(73);
var InputBufferUnderrunError = __webpack_require__(29);
var createClient = __webpack_require__(33);
@@ -22947,7 +22866,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 67 */
+/* 68 */
/***/ (function(module, exports) {
@@ -22996,7 +22915,7 @@
/***/ }),
-/* 68 */
+/* 69 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -23019,12 +22938,12 @@
*/
module.exports.TBufferedTransport = __webpack_require__(23);
- module.exports.TFramedTransport = __webpack_require__(69);
+ module.exports.TFramedTransport = __webpack_require__(70);
module.exports.InputBufferUnderrunError = __webpack_require__(29);
/***/ }),
-/* 69 */
+/* 70 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -23213,7 +23132,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 70 */
+/* 71 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -23236,12 +23155,12 @@
*/
module.exports.TBinaryProtocol = __webpack_require__(30);
- module.exports.TCompactProtocol = __webpack_require__(71);
- module.exports.TJSONProtocol = __webpack_require__(72);
+ module.exports.TCompactProtocol = __webpack_require__(72);
+ module.exports.TJSONProtocol = __webpack_require__(73);
/***/ }),
-/* 71 */
+/* 72 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -24166,7 +24085,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 72 */
+/* 73 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -24190,13 +24109,13 @@
var log = __webpack_require__(31);
var Int64 = __webpack_require__(32);
- var InputBufferUnderrunError = __webpack_require__(68).InputBufferUnderrunError;
+ var InputBufferUnderrunError = __webpack_require__(69).InputBufferUnderrunError;
var Thrift = __webpack_require__(15);
var Type = Thrift.Type;
var util = __webpack_require__(16);
- var Int64Util = __webpack_require__(73);
- var json_parse = __webpack_require__(74);
+ var Int64Util = __webpack_require__(74);
+ var json_parse = __webpack_require__(75);
var InputBufferUnderrunError = __webpack_require__(29);
@@ -24916,7 +24835,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 73 */
+/* 74 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -25014,7 +24933,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 74 */
+/* 75 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -25040,7 +24959,7 @@
*/
var Int64 = __webpack_require__(32);
- var Int64Util = __webpack_require__(73);
+ var Int64Util = __webpack_require__(74);
var json_parse = module.exports = (function () {
"use strict";
@@ -25319,7 +25238,7 @@
/***/ }),
-/* 75 */
+/* 76 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -25345,7 +25264,7 @@
var thrift = __webpack_require__(15);
var TBufferedTransport = __webpack_require__(23);
- var TJSONProtocol = __webpack_require__(72);
+ var TJSONProtocol = __webpack_require__(73);
var InputBufferUnderrunError = __webpack_require__(29);
var createClient = __webpack_require__(33);
@@ -25606,7 +25525,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 76 */
+/* 77 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -25719,7 +25638,7 @@
/***/ }),
-/* 77 */
+/* 78 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {/*
@@ -25741,13 +25660,13 @@
* under the License.
*/
var http = __webpack_require__(35);
- var https = __webpack_require__(65);
- var url = __webpack_require__(59);
- var path = __webpack_require__(78);
+ var https = __webpack_require__(66);
+ var url = __webpack_require__(60);
+ var path = __webpack_require__(79);
var fs = __webpack_require__(22);
- var crypto = __webpack_require__(79);
+ var crypto = __webpack_require__(80);
- var MultiplexedProcessor = __webpack_require__(113).MultiplexedProcessor;
+ var MultiplexedProcessor = __webpack_require__(114).MultiplexedProcessor;
var TBufferedTransport = __webpack_require__(23);
var TBinaryProtocol = __webpack_require__(30);
@@ -26290,7 +26209,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 78 */
+/* 79 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors.
@@ -26521,10 +26440,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17)))
/***/ }),
-/* 79 */
+/* 80 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var rng = __webpack_require__(80)
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var rng = __webpack_require__(81)
function error () {
var m = [].slice.call(arguments).join(' ')
@@ -26535,9 +26454,9 @@
].join('\n'))
}
- exports.createHash = __webpack_require__(82)
+ exports.createHash = __webpack_require__(83)
- exports.createHmac = __webpack_require__(91)
+ exports.createHmac = __webpack_require__(92)
exports.randomBytes = function(size, callback) {
if (callback && callback.call) {
@@ -26558,10 +26477,10 @@
return ['sha1', 'sha256', 'sha512', 'md5', 'rmd160']
}
- var p = __webpack_require__(92)(exports)
+ var p = __webpack_require__(93)(exports)
exports.pbkdf2 = p.pbkdf2
exports.pbkdf2Sync = p.pbkdf2Sync
- __webpack_require__(94)(exports, module.exports);
+ __webpack_require__(95)(exports, module.exports);
// the least I can do is make error messages for the rest of the node.js/crypto api.
each(['createCredentials'
@@ -26577,13 +26496,13 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 80 */
+/* 81 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(global, Buffer) {(function() {
var g = ('undefined' === typeof window ? global : window) || {}
_crypto = (
- g.crypto || g.msCrypto || __webpack_require__(81)
+ g.crypto || g.msCrypto || __webpack_require__(82)
)
module.exports = function(size) {
// Modern Browsers
@@ -26610,19 +26529,19 @@
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }()), __webpack_require__(24).Buffer))
/***/ }),
-/* 81 */
+/* 82 */
/***/ (function(module, exports) {
/* (ignored) */
/***/ }),
-/* 82 */
+/* 83 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(83)
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(84)
- var md5 = toConstructor(__webpack_require__(88))
- var rmd160 = toConstructor(__webpack_require__(90))
+ var md5 = toConstructor(__webpack_require__(89))
+ var rmd160 = toConstructor(__webpack_require__(91))
function toConstructor (fn) {
return function () {
@@ -26653,7 +26572,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 83 */
+/* 84 */
/***/ (function(module, exports, __webpack_require__) {
var exports = module.exports = function (alg) {
@@ -26663,15 +26582,15 @@
}
var Buffer = __webpack_require__(24).Buffer
- var Hash = __webpack_require__(84)(Buffer)
+ var Hash = __webpack_require__(85)(Buffer)
- exports.sha1 = __webpack_require__(85)(Buffer, Hash)
- exports.sha256 = __webpack_require__(86)(Buffer, Hash)
- exports.sha512 = __webpack_require__(87)(Buffer, Hash)
+ exports.sha1 = __webpack_require__(86)(Buffer, Hash)
+ exports.sha256 = __webpack_require__(87)(Buffer, Hash)
+ exports.sha512 = __webpack_require__(88)(Buffer, Hash)
/***/ }),
-/* 84 */
+/* 85 */
/***/ (function(module, exports) {
module.exports = function (Buffer) {
@@ -26754,7 +26673,7 @@
/***/ }),
-/* 85 */
+/* 86 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -26898,7 +26817,7 @@
/***/ }),
-/* 86 */
+/* 87 */
/***/ (function(module, exports, __webpack_require__) {
@@ -27051,7 +26970,7 @@
/***/ }),
-/* 87 */
+/* 88 */
/***/ (function(module, exports, __webpack_require__) {
var inherits = __webpack_require__(16).inherits
@@ -27301,7 +27220,7 @@
/***/ }),
-/* 88 */
+/* 89 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -27313,7 +27232,7 @@
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
- var helpers = __webpack_require__(89);
+ var helpers = __webpack_require__(90);
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
@@ -27462,7 +27381,7 @@
/***/ }),
-/* 89 */
+/* 90 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {var intSize = 4;
@@ -27503,7 +27422,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 90 */
+/* 91 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {
@@ -27715,10 +27634,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 91 */
+/* 92 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(82)
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var createHash = __webpack_require__(83)
var zeroBuffer = new Buffer(128)
zeroBuffer.fill(0)
@@ -27765,10 +27684,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 92 */
+/* 93 */
/***/ (function(module, exports, __webpack_require__) {
- var pbkdf2Export = __webpack_require__(93)
+ var pbkdf2Export = __webpack_require__(94)
module.exports = function (crypto, exports) {
exports = exports || {}
@@ -27783,7 +27702,7 @@
/***/ }),
-/* 93 */
+/* 94 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {module.exports = function(crypto) {
@@ -27874,18 +27793,18 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 94 */
+/* 95 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = function (crypto, exports) {
exports = exports || {};
- var ciphers = __webpack_require__(95)(crypto);
+ var ciphers = __webpack_require__(96)(crypto);
exports.createCipher = ciphers.createCipher;
exports.createCipheriv = ciphers.createCipheriv;
- var deciphers = __webpack_require__(112)(crypto);
+ var deciphers = __webpack_require__(113)(crypto);
exports.createDecipher = deciphers.createDecipher;
exports.createDecipheriv = deciphers.createDecipheriv;
- var modes = __webpack_require__(103);
+ var modes = __webpack_require__(104);
function listCiphers () {
return Object.keys(modes);
}
@@ -27895,15 +27814,15 @@
/***/ }),
-/* 95 */
+/* 96 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(96);
- var Transform = __webpack_require__(97);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(97);
+ var Transform = __webpack_require__(98);
var inherits = __webpack_require__(38);
- var modes = __webpack_require__(103);
- var ebtk = __webpack_require__(104);
- var StreamCipher = __webpack_require__(105);
+ var modes = __webpack_require__(104);
+ var ebtk = __webpack_require__(105);
+ var StreamCipher = __webpack_require__(106);
inherits(Cipher, Transform);
function Cipher(mode, key, iv) {
if (!(this instanceof Cipher)) {
@@ -27964,11 +27883,11 @@
return out;
};
var modelist = {
- ECB: __webpack_require__(106),
- CBC: __webpack_require__(107),
- CFB: __webpack_require__(109),
- OFB: __webpack_require__(110),
- CTR: __webpack_require__(111)
+ ECB: __webpack_require__(107),
+ CBC: __webpack_require__(108),
+ CFB: __webpack_require__(110),
+ OFB: __webpack_require__(111),
+ CTR: __webpack_require__(112)
};
module.exports = function (crypto) {
function createCipheriv(suite, password, iv) {
@@ -28010,7 +27929,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 96 */
+/* 97 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {var uint_max = Math.pow(2, 32);
@@ -28212,10 +28131,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 97 */
+/* 98 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var Transform = __webpack_require__(98).Transform;
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var Transform = __webpack_require__(99).Transform;
var inherits = __webpack_require__(38);
module.exports = CipherBase;
@@ -28250,7 +28169,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 98 */
+/* 99 */
/***/ (function(module, exports, __webpack_require__) {
// Copyright Joyent, Inc. and other Node contributors.
@@ -28281,10 +28200,10 @@
inherits(Stream, EE);
Stream.Readable = __webpack_require__(40);
- Stream.Writable = __webpack_require__(99);
- Stream.Duplex = __webpack_require__(100);
- Stream.Transform = __webpack_require__(101);
- Stream.PassThrough = __webpack_require__(102);
+ Stream.Writable = __webpack_require__(100);
+ Stream.Duplex = __webpack_require__(101);
+ Stream.Transform = __webpack_require__(102);
+ Stream.PassThrough = __webpack_require__(103);
// Backwards-compat with node 0.4.x
Stream.Stream = Stream;
@@ -28383,35 +28302,35 @@
/***/ }),
-/* 99 */
+/* 100 */
/***/ (function(module, exports, __webpack_require__) {
- module.exports = __webpack_require__(49);
+ module.exports = __webpack_require__(50);
/***/ }),
-/* 100 */
+/* 101 */
/***/ (function(module, exports, __webpack_require__) {
- module.exports = __webpack_require__(48);
+ module.exports = __webpack_require__(49);
/***/ }),
-/* 101 */
+/* 102 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(40).Transform
/***/ }),
-/* 102 */
+/* 103 */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(40).PassThrough
/***/ }),
-/* 103 */
+/* 104 */
/***/ (function(module, exports) {
exports['aes-128-ecb'] = {
@@ -28524,7 +28443,7 @@
};
/***/ }),
-/* 104 */
+/* 105 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {
@@ -28587,11 +28506,11 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 105 */
+/* 106 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(96);
- var Transform = __webpack_require__(97);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(97);
+ var Transform = __webpack_require__(98);
var inherits = __webpack_require__(38);
inherits(StreamCipher, Transform);
@@ -28619,7 +28538,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 106 */
+/* 107 */
/***/ (function(module, exports) {
exports.encrypt = function (self, block) {
@@ -28630,10 +28549,10 @@
};
/***/ }),
-/* 107 */
+/* 108 */
/***/ (function(module, exports, __webpack_require__) {
- var xor = __webpack_require__(108);
+ var xor = __webpack_require__(109);
exports.encrypt = function (self, block) {
var data = xor(block, self._prev);
self._prev = self._cipher.encryptBlock(data);
@@ -28647,7 +28566,7 @@
};
/***/ }),
-/* 108 */
+/* 109 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(Buffer) {module.exports = xor;
@@ -28663,10 +28582,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 109 */
+/* 110 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(108);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(109);
exports.encrypt = function (self, data, decrypt) {
var out = new Buffer('');
var len;
@@ -28696,10 +28615,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 110 */
+/* 111 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(108);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(109);
function getBlock(self) {
self._prev = self._cipher.encryptBlock(self._prev);
return self._prev;
@@ -28715,10 +28634,10 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 111 */
+/* 112 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(108);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var xor = __webpack_require__(109);
function getBlock(self) {
var out = self._cipher.encryptBlock(self._prev);
incr32(self._prev);
@@ -28749,15 +28668,15 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 112 */
+/* 113 */
/***/ (function(module, exports, __webpack_require__) {
- /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(96);
- var Transform = __webpack_require__(97);
+ /* WEBPACK VAR INJECTION */(function(Buffer) {var aes = __webpack_require__(97);
+ var Transform = __webpack_require__(98);
var inherits = __webpack_require__(38);
- var modes = __webpack_require__(103);
- var StreamCipher = __webpack_require__(105);
- var ebtk = __webpack_require__(104);
+ var modes = __webpack_require__(104);
+ var StreamCipher = __webpack_require__(106);
+ var ebtk = __webpack_require__(105);
inherits(Decipher, Transform);
function Decipher(mode, key, iv) {
@@ -28825,11 +28744,11 @@
}
var modelist = {
- ECB: __webpack_require__(106),
- CBC: __webpack_require__(107),
- CFB: __webpack_require__(109),
- OFB: __webpack_require__(110),
- CTR: __webpack_require__(111)
+ ECB: __webpack_require__(107),
+ CBC: __webpack_require__(108),
+ CFB: __webpack_require__(110),
+ OFB: __webpack_require__(111),
+ CTR: __webpack_require__(112)
};
module.exports = function (crypto) {
@@ -28873,7 +28792,7 @@
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24).Buffer))
/***/ }),
-/* 113 */
+/* 114 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -28942,7 +28861,7 @@
/***/ }),
-/* 114 */
+/* 115 */
/***/ (function(module, exports, __webpack_require__) {
/* WEBPACK VAR INJECTION */(function(process, setImmediate) {// vim:ts=4:sts=4:sw=4:
@@ -30850,10 +30769,10 @@
});
- /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17), __webpack_require__(50).setImmediate))
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(17), __webpack_require__(51).setImmediate))
/***/ }),
-/* 115 */
+/* 116 */
/***/ (function(module, exports, __webpack_require__) {
/*
@@ -30932,7 +30851,7 @@
/***/ }),
-/* 116 */
+/* 117 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -35056,7 +34975,7 @@
};
/***/ }),
-/* 117 */
+/* 118 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
@@ -35066,11 +34985,11 @@
});
exports.default = processQueryResults;
- var _processColumnarResults = __webpack_require__(118);
+ var _processColumnarResults = __webpack_require__(119);
var _processColumnarResults2 = _interopRequireDefault(_processColumnarResults);
- var _processRowResults = __webpack_require__(119);
+ var _processRowResults = __webpack_require__(120);
var _processRowResults2 = _interopRequireDefault(_processRowResults);
@@ -35158,7 +35077,7 @@
}
/***/ }),
-/* 118 */
+/* 119 */
/***/ (function(module, exports) {
"use strict";
@@ -35282,7 +35201,7 @@
}
/***/ }),
-/* 119 */
+/* 120 */
/***/ (function(module, exports) {
"use strict";
diff --git a/dist/node-connector.js b/dist/node-connector.js
index 3ef47f5d..91348d35 100644
--- a/dist/node-connector.js
+++ b/dist/node-connector.js
@@ -25406,8 +25406,6 @@ module.exports =
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
- var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
-
var _helpers = __webpack_require__(56);
var helpers = _interopRequireWildcard(_helpers);
@@ -25424,8 +25422,6 @@ module.exports =
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-
var _ref = isNodeRuntime() && __webpack_require__(52) || window,
TDatumType = _ref.TDatumType,
TEncodingType = _ref.TEncodingType,
@@ -25444,1245 +25440,837 @@ module.exports =
}
- var COMPRESSION_LEVEL_DEFAULT = 3;
-
- function arrayify(maybeArray) {
- return Array.isArray(maybeArray) ? maybeArray : [maybeArray];
- }
-
- function isNodeRuntime() {
- return typeof window === "undefined";
+ // Set a global Connector function when Connector is brought in via script tag.
+ if (( false ? "undefined" : _typeof(module)) === "object" && module.exports) {
+ if (!isNodeRuntime()) {
+ window.Connector = Connector;
+ }
}
+ module.exports = Connector;
+ exports.default = Connector;
- var MapdCon = function () {
- function MapdCon() {
- var _this = this;
-
- _classCallCheck(this, MapdCon);
-
- this.updateQueryTimes = function (conId, queryId, estimatedQueryTime, execution_time_ms) {
- _this.queryTimes[queryId] = execution_time_ms;
- };
-
- this.getFrontendViews = function (callback) {
- if (_this._sessionId) {
- _this._client[0].get_frontend_views(_this._sessionId[0], callback);
- } else {
- callback(new Error("No Session ID"));
- }
- };
-
- this.getFrontendViewsAsync = function () {
- return new Promise(function (resolve, reject) {
- _this.getFrontendViews(function (error, views) {
- if (error) {
- reject(error);
- } else {
- resolve(views);
- }
- });
- });
- };
-
- this.getFrontendView = function (viewName, callback) {
- if (_this._sessionId && viewName) {
- _this._client[0].get_frontend_view(_this._sessionId[0], viewName, callback);
- } else {
- callback(new Error("No Session ID"));
- }
- };
-
- this.getFrontendViewAsync = function (viewName) {
- return new Promise(function (resolve, reject) {
- _this.getFrontendView(viewName, function (err, view) {
- if (err) {
- reject(err);
- } else {
- resolve(view);
- }
- });
- });
- };
-
- this.getServerStatus = function (callback) {
- _this._client[0].get_server_status(_this._sessionId[0], callback);
- };
-
- this.getServerStatusAsync = function () {
- return new Promise(function (resolve, reject) {
- _this.getServerStatus(function (err, result) {
- if (err) {
- reject(err);
- } else {
- resolve(result);
- }
- });
- });
- };
-
- this.deleteFrontendViewAsync = function (viewName) {
- return new Promise(function (resolve, reject) {
- _this.deleteFrontendView(viewName, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve(viewName);
- }
- });
- });
- };
-
- this.getLinkView = function (link, callback) {
- _this._client[0].get_link_view(_this._sessionId[0], link, callback);
- };
-
- this.getLinkViewAsync = function (link) {
- return new Promise(function (resolve, reject) {
- _this.getLinkView(link, function (err, theLink) {
- if (err) {
- reject(err);
- } else {
- resolve(theLink);
- }
- });
- });
- };
-
- this.queryAsync = this.query;
-
- this.createTableAsync = function (tableName, rowDescObj, tableType) {
- return new Promise(function (resolve, reject) {
- _this.createTable(tableName, rowDescObj, tableType, function (err) {
- if (err) {
- reject(err);
- } else {
- resolve();
- }
- });
- });
- };
-
- this.importTableAsync = this.importTableAsyncWrapper(false);
- this.importTableGeoAsync = this.importTableAsyncWrapper(true);
-
- this._host = null;
- this._user = null;
- this._password = null;
- this._port = null;
- this._dbName = null;
- this._client = null;
- this._sessionId = null;
- this._protocol = null;
- this._datumEnum = {};
- this._logging = false;
- this._platform = "mapd";
- this._nonce = 0;
- this._balanceStrategy = "adaptive";
- this._numConnections = 0;
- this._lastRenderCon = 0;
- this.queryTimes = {};
- this.serverQueueTimes = null;
- this.serverPingTimes = null;
- this.pingCount = null;
- this.DEFAULT_QUERY_TIME = 50;
- this.NUM_PINGS_PER_SERVER = 4;
- this.importerRowDesc = null;
-
- // invoke initialization methods
- this.invertDatumTypes();
-
- this.processResults = function () {
- var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
- var result = arguments[1];
- var callback = arguments[2];
-
- var processor = (0, _processQueryResults2.default)(_this._logging, _this.updateQueryTimes);
- var processResultsObject = processor(options, _this._datumEnum, result, callback);
- return processResultsObject;
- };
- // return this to allow chaining off of instantiation
- return this;
- }
+ var COMPRESSION_LEVEL_DEFAULT = 3;
+ var DEFAULT_QUERY_TIME = 50;
+
+ function Connector() {
+ // initialize variables
+ var _datumEnum = {};
+ var _queryTimes = {};
+ var _client = null;
+ var _dbName = null;
+ var _host = null;
+ var _logging = false;
+ var _nonce = 0;
+ var _password = null;
+ var _port = null;
+ var _protocol = null;
+ var _sessionId = null;
+ var _user = null;
+
+ // invoke initialization methods
+ publicizeMethods(this, [connect, createFrontendView, createLink, createTable, dbName, deleteFrontendView, detectColumnTypes, disconnect, getFields, getFrontendView, getFrontendViews, getLinkView, getPixel, getServerStatus, getTables, host, importShapeTable, importTable, logging, password, port, protocol, query, renderVega, sessionId, user, validateQuery]);
+ invertDatumTypes(_datumEnum);
+
+ // return this to allow chaining off of instantiation
+ return this;
+ // public methods
/**
* Create a connection to the server, generating a client and session id.
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
- * @return {MapdCon} Object
+ * @param {Function} callback (error, session) => {…}
+ * @returns {undefined}
*
* @example Connect to a MapD server:
- * var con = new MapdCon()
+ * var con = new Connector()
* .host('localhost')
* .port('8080')
* .dbName('myDatabase')
* .user('foo')
* .password('bar')
- * .connect((err, con) => console.log(con.sessionId()));
+ * .connect((error, con) => console.log(con.sessionId()));
*
* // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
*/
+ function connect(callback) {
+ var _this = this;
+ // eslint-disable-line consistent-return
+ if (_sessionId) {
+ disconnect();
+ }
+
+ if ([_host, _port, _user, _password, _dbName].some(Array.isArray)) {
+ console.warn("Connection parameters as arrays is deprecated; use single values."); // eslint-disable-line no-console
+ _host = Array.isArray(_host) ? _host[0] : _host;
+ _port = Array.isArray(_port) ? _port[0] : _port;
+ _user = Array.isArray(_user) ? _user[0] : _user;
+ _password = Array.isArray(_password) ? _password[0] : _password;
+ _dbName = Array.isArray(_dbName) ? _dbName[0] : _dbName;
+ }
+
+ if (!_user) {
+ return callback("Please enter a username.");
+ } else if (!_password) {
+ return callback("Please enter a password.");
+ } else if (!_dbName) {
+ return callback("Please enter a database.");
+ } else if (!_host) {
+ return callback("Please enter a host name.");
+ } else if (!_port) {
+ return callback("Please enter a port.");
+ }
+
+ _client = null;
+ _sessionId = null;
+ _protocol = _protocol || window.location.protocol.replace(":", "");
+
+ var transportUrl = _protocol + "://" + _host + ":" + _port;
+ var client = null;
+
+ if (isNodeRuntime()) {
+ var _parseUrl = parseUrl(transportUrl),
+ parsedProtocol = _parseUrl.protocol,
+ parsedHost = _parseUrl.hostname,
+ parsedPort = _parseUrl.port;
+
+ var connection = thriftWrapper.createHttpConnection(parsedHost, parsedPort, {
+ transport: thriftWrapper.TBufferedTransport,
+ protocol: thriftWrapper.TJSONProtocol,
+ path: "/",
+ headers: { Connection: "close" },
+ https: parsedProtocol === "https:"
+ });
+ connection.on("error", console.error); // eslint-disable-line no-console
+ client = thriftWrapper.createClient(MapDThrift, connection);
+ resetThriftClientOnArgumentErrorForMethods(this, client, Object.keys(this));
+ } else {
+ var thriftTransport = new Thrift.Transport(transportUrl);
+ var thriftProtocol = new Thrift.Protocol(thriftTransport);
+ client = new _mapdClientV2.default(thriftProtocol);
+ }
+ client.connect(_user, _password, _dbName, function (error, newSessionId) {
+ // eslint-disable-line no-loop-func
+ if (error) {
+ return callback(normalizeError(error));
+ }
+ _client = client;
+ _sessionId = newSessionId;
+ return callback(null, _this);
+ });
+ }
+ /**
+ * Disconnect from the server then clears the client and session values.
+ * @param {Function} callback (error) => {…}
+ * @returns {undefined}
+ *
+ * @example Disconnect from the server:
+ *
+ * con.sessionId() // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
+ * con.disconnect((err) => {
+ * console.error(err);
+ * con.sessionId() === null;
+ * })
+ */
+ function disconnect() {
+ var _this2 = this;
- _createClass(MapdCon, [{
- key: "connect",
- value: function connect(callback) {
- var _this2 = this;
+ var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop;
- if (this._sessionId) {
- this.disconnect();
+ if (_sessionId !== null) {
+ _client.disconnect(_sessionId, function (error) {
+ // eslint-disable-line no-loop-func
+ if (error) {
+ return callback(error, _this2);
+ }
+ _sessionId = null;
+ _client = null;
+ return callback(null, _this2);
+ });
+ }
+ }
+ /**
+ * Get a dashboard object containing a value for the view_state
property.
+ * This object contains a value for the view_state
property,
+ * but not for the view_name
property.
+ * @param {String} viewName the name of the dashboard
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get a specific dashboard from the server:
+ *
+ * con.getFrontendView('dashboard_name').then((result) => console.log(result))
+ * // {TFrontendView}
+ */
+ function getFrontendView(viewName, callback) {
+ if (_sessionId && viewName) {
+ _client.get_frontend_view(_sessionId, viewName, callback);
+ return;
+ } else {
+ callback(new Error("No Session ID"));
+ return;
+ }
+ }
+ /**
+ * Get the recent dashboards as a list of TFrontendView
objects.
+ * These objects contain a value for the view_name
property,
+ * but not for the view_state
property.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of dashboards from the server:
+ *
+ * con.getFrontendViews().then((results) => console.log(results))
+ * // [TFrontendView, TFrontendView]
+ */
+ function getFrontendViews(callback) {
+ if (_sessionId) {
+ _client.get_frontend_views(_sessionId, callback);
+ } else {
+ callback(new Error("No Session ID"));
+ return;
+ }
+ }
+ /**
+ * Get the status of the server as a TServerStatus
object.
+ * This includes whether the server is read-only,
+ * has backend rendering enabled, and the version number.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the server status:
+ *
+ * con.getServerStatus().then((result) => console.log(result))
+ * // {
+ * // "read_only": false,
+ * // "version": "3.0.0dev-20170503-40e2de3",
+ * // "rendering_enabled": true,
+ * // "start_time": 1493840131
+ * // }
+ */
+ function getServerStatus(callback) {
+ _client.get_server_status(_sessionId, callback);
+ }
+ /**
+ * Add a new dashboard to the server.
+ * @param {String} viewName - the name of the new dashboard
+ * @param {String} viewState - the base64-encoded state string of the new dashboard
+ * @param {String} imageHash - the numeric hash of the dashboard thumbnail
+ * @param {String} metaData - Stringified metaData related to the view
+ * @param {Function} callback (error) => {…} success returns null
+ * @returns {undefined}
+ *
+ * @example Add a new dashboard to the server:
+ *
+ * con.createFrontendView('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
+ */
+ function createFrontendView(viewName, viewState, imageHash, metaData, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
+ }
+ return _client.create_frontend_view(_sessionId, viewName, viewState, imageHash, metaData, callback);
+ }
+ /**
+ * Delete a dashboard object containing a value for the view_state
property.
+ * @param {String} viewName - the name of the dashboard
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Delete a specific dashboard from the server:
+ *
+ * con.deleteFrontendView('dashboard_name').then(res => console.log(res))
+ */
+ function deleteFrontendView(viewName, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
+ }
+ try {
+ // eslint-disable-line no-restricted-syntax
+ return _client.delete_frontend_view(_sessionId, viewName, callback);
+ } catch (err) {
+ return callback(new Error("Could not delete the frontend view; check your session id.", err));
+ }
+ }
+ /**
+ * Create a short hash to make it easy to share a link to a specific dashboard.
+ * @param {String} viewState - the base64-encoded state string of the new dashboard
+ * @param {String} metaData - Stringified metaData related to the link
+ * @param {Function} callback (error, id) => {…}
+ * @returns {undefined}
+ *
+ * @example Create a link to the current state of a dashboard:
+ *
+ * con.createLink("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
+ * // ["28127951"]
+ */
+ function createLink(viewState, metaData, callback) {
+ return _client.create_link(_sessionId, viewState, metaData, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
}
-
- // TODO: should be its own function
- var allAreArrays = Array.isArray(this._host) && Array.isArray(this._port) && Array.isArray(this._user) && Array.isArray(this._password) && Array.isArray(this._dbName);
- if (!allAreArrays) {
- return callback("All connection parameters must be arrays.");
+ var result = data.split(",").reduce(function (links, link) {
+ // eslint-disable-line max-nested-callbacks
+ if (!links.includes(link)) {
+ links.push(link);
+ }
+ return links;
+ }, []);
+ if (!result || result.length !== 1) {
+ return callback(new Error("Different links were created on connection"));
+ } else {
+ return callback(null, result.join());
}
-
- this._client = [];
- this._sessionId = [];
-
- if (!this._user[0]) {
- return callback("Please enter a username.");
- } else if (!this._password[0]) {
- return callback("Please enter a password.");
- } else if (!this._dbName[0]) {
- return callback("Please enter a database.");
- } else if (!this._host[0]) {
- return callback("Please enter a host name.");
- } else if (!this._port[0]) {
- return callback("Please enter a port.");
+ });
+ }
+ /**
+ * Get a fully-formed dashboard object from a generated share link.
+ * This object contains the given link for the view_name
property,
+ * @param {String} link - the short hash of the dashboard, see {@link createLink}
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get a dashboard from a link:
+ *
+ * con.getLinkView('28127951').then(res => console.log(res))
+ * // {
+ * // "view_name": "28127951",
+ * // "view_state": "eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==",
+ * // "image_hash": "",
+ * // "update_time": "2017-04-28T21:34:01Z",
+ * // "view_metadata": "metaData"
+ * // }
+ */
+ function getLinkView(link, callback) {
+ _client.get_link_view(_sessionId, link, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, data);
}
+ });
+ }
+ /**
+ * Asynchronously get the data from an importable file,
+ * such as a .csv or plaintext file with a header.
+ * @param {String} fileName - the name of the importable file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get data from table_data.csv:
+ *
+ * var copyParams = new TCopyParams();
+ * con.detectColumnTypes('table_data.csv', copyParams).then(res => console.log(res))
+ * // TDetectResult {row_set: TRowSet, copy_params: TCopyParams}
+ *
+ */
+ function detectColumnTypes(fileName, copyParams, callback) {
+ var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
+ _client.detect_column_types(_sessionId, fileName, thriftCopyParams, callback);
+ }
+ /**
+ * Submit a query to the database and process the results.
+ * @param {String} sql The query to perform
+ * @param {Object} options the options for the query
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example create a query
+ *
+ * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
+ * var options = {};
+ *
+ * con.query(query, options, function(error, data) {
+ * console.log(data)
+ * });
+ *
+ */
+ function query(sql, options, callback) {
+ var columnarResults = true;
+ var eliminateNullRows = false;
+ var queryId = null;
+ var returnTiming = false;
+ var limit = -1;
+ if (options) {
+ columnarResults = options.hasOwnProperty("columnarResults") ? options.columnarResults : columnarResults;
+ eliminateNullRows = options.hasOwnProperty("eliminateNullRows") ? options.eliminateNullRows : eliminateNullRows;
+ queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
+ returnTiming = options.hasOwnProperty("returnTiming") ? options.returnTiming : returnTiming;
+ limit = options.hasOwnProperty("limit") ? options.limit : limit;
+ }
+
+ var lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME;
+
+ var curNonce = (_nonce++).toString();
+
+ var processResultsOptions = {
+ returnTiming: returnTiming,
+ eliminateNullRows: eliminateNullRows,
+ sql: sql,
+ queryId: queryId,
+ conId: 0,
+ estimatedQueryTime: lastQueryTime
+ };
- // now check to see if length of all arrays are the same and > 0
- var hostLength = this._host.length;
- if (hostLength < 1) {
- return callback("Must have at least one server to connect to.");
+ _client.sql_execute(_sessionId, sql, columnarResults, curNonce, limit, function (error, result) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions);
}
- if (hostLength !== this._port.length || hostLength !== this._user.length || hostLength !== this._password.length || hostLength !== this._dbName.length) {
- return callback("Array connection parameters must be of equal length.");
+ });
+ }
+ /**
+ * Submit a query to validate whether the backend can create a result set based on the SQL statement.
+ * @param {String} sql The query to perform
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example create a query
+ *
+ * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
+ *
+ * con.validateQuery(query).then(res => console.log(res))
+ *
+ * // [{
+ * // "name": "n",
+ * // "type": "INT",
+ * // "is_array": false,
+ * // "is_dict": false
+ * // }]
+ *
+ */
+ function validateQuery(sql, callback) {
+ _client.sql_validate(_sessionId, sql, function (error, data) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, convertFromThriftTypes(data, _datumEnum));
}
-
- if (!this._protocol) {
- this._protocol = this._host.map(function () {
- return window.location.protocol.replace(":", "");
- });
+ });
+ }
+ /**
+ * Get the names of the databases that exist on the current session's connectdion.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of tables from a connection:
+ *
+ * con.getTables().then(res => console.log(res))
+ *
+ * // [{
+ * // label: 'obs', // deprecated property
+ * // name: 'myDatabaseName'
+ * // },
+ * // ...]
+ */
+ function getTables(callback) {
+ _client.get_tables(_sessionId, function (error, tables) {
+ if (error) {
+ return callback(normalizeError(error));
+ } else {
+ return callback(null, tables.map(function (table) {
+ return { name: table, label: "obs" };
+ }));
}
-
- var transportUrls = this.getEndpoints();
-
- var _loop = function _loop(h) {
- var client = null;
-
- if (isNodeRuntime()) {
- var _parseUrl = parseUrl(transportUrls[h]),
- protocol = _parseUrl.protocol,
- hostname = _parseUrl.hostname,
- port = _parseUrl.port;
-
- var connection = thriftWrapper.createHttpConnection(hostname, port, {
- transport: thriftWrapper.TBufferedTransport,
- protocol: thriftWrapper.TJSONProtocol,
- path: "/",
- headers: { Connection: "close" },
- https: protocol === "https:"
- });
- connection.on("error", console.error); // eslint-disable-line no-console
- client = thriftWrapper.createClient(MapDThrift, connection);
- resetThriftClientOnArgumentErrorForMethods(_this2, client, ["connect", "createFrontendViewAsync", "createLinkAsync", "createTableAsync", "dbName", "deleteFrontendViewAsync", "detectColumnTypesAsync", "disconnect", "getFields", "getFrontendViewAsync", "getFrontendViewsAsync", "getLinkViewAsync", "getResultRowForPixel", "getServerStatusAsync", "getTablesAsync", "host", "importTableAsync", "importTableGeoAsync", "logging", "password", "port", "protocol", "query", "renderVega", "sessionId", "user", "validateQuery"]);
- } else {
- var thriftTransport = new Thrift.Transport(transportUrls[h]);
- var thriftProtocol = new Thrift.Protocol(thriftTransport);
- client = new _mapdClientV2.default(thriftProtocol);
- }
-
- client.connect(_this2._user[h], _this2._password[h], _this2._dbName[h], function (error, sessionId) {
- if (error) {
- callback(error);
- return;
- }
- _this2._client.push(client);
- _this2._sessionId.push(sessionId);
- _this2._numConnections = _this2._client.length;
- callback(null, _this2);
- });
- };
-
- for (var h = 0; h < hostLength; h++) {
- _loop(h);
- }
-
- return this;
- }
- }, {
- key: "convertFromThriftTypes",
- value: function convertFromThriftTypes(fields) {
- var fieldsArray = [];
- // silly to change this from map to array
- // - then later it turns back to map
- for (var key in fields) {
- if (fields.hasOwnProperty(key)) {
- fieldsArray.push({
- name: key,
- type: this._datumEnum[fields[key].col_type.type],
- is_array: fields[key].col_type.is_array,
- is_dict: fields[key].col_type.encoding === TEncodingType.DICT // eslint-disable-line no-undef
- });
- }
+ });
+ }
+ /**
+ * Get a list of field objects for a given table.
+ * @param {String} tableName - name of table containing field names
+ * @param {Function} callback - (error, fields) => {…}
+ * @returns {undefined}
+ *
+ * @example Get the list of fields from a specific table:
+ *
+ * con.getFields('flights', (error, res) => console.log(res))
+ * // [{
+ * name: 'fieldName',
+ * type: 'BIGINT',
+ * is_array: false,
+ * is_dict: false
+ * }, ...]
+ */
+ function getFields(tableName, callback) {
+ _client.get_table_details(_sessionId, tableName, function (error, fields) {
+ if (fields) {
+ var rowDict = fields.row_desc.reduce(function (accum, value) {
+ accum[value.col_name] = value;
+ return accum;
+ }, {});
+ return callback(null, convertFromThriftTypes(rowDict, _datumEnum));
+ } else {
+ return callback(normalizeError(error));
}
- return fieldsArray;
+ });
+ }
+ /**
+ * Create a table and persist it to the backend.
+ * @param {String} tableName - desired name of the new table
+ * @param {Array} rowDescObj - fields of the new table
+ * @param {Number} tableType - the types of tables a user can import into the db
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Create a new table:
+ *
+ * con.createTable('mynewtable', [TColumnType, TColumnType, ...], 0).then(res => console.log(res));
+ * // undefined
+ */
+ function createTable(tableName, rowDescObj, tableType, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
+ var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null);
+ return _client.create_table(_sessionId, tableName, thriftRowDesc, tableType, callback);
+ }
+ /**
+ * Import a delimited table from a file.
+ * @param {String} tableName - desired name of the new table
+ * @param {String} fileName - name of imported file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @param {Boolean} isShapeFile false by default, enabled to import shape data.
+ * @returns {undefined}
+ */
+ function importTable(tableName, fileName, copyParams, rowDescObj, callback) {
+ var isShapeFile = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
- /**
- * Disconnect from the server then clears the client and session values.
- * @return {MapdCon} Object
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
- *
- * @example Disconnect from the server:
- *
- * con.sessionId() // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
- * con.disconnect((err, con) => console.log(err, con))
- * con.sessionId() === null;
- */
-
- }, {
- key: "disconnect",
- value: function disconnect(callback) {
- var _this3 = this;
-
- if (this._sessionId !== null) {
- for (var c = 0; c < this._client.length; c++) {
- this._client[c].disconnect(this._sessionId[c], function (error) {
- // Success will return NULL
-
- if (error) {
- return callback(error, _this3);
- }
- _this3._sessionId = null;
- _this3._client = null;
- _this3._numConnections = 0;
- _this3.serverPingTimes = null;
- return callback(null, _this3);
- });
- }
- }
- return this;
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."));
}
- /**
- * Get the recent dashboards as a list of TFrontendView
objects.
- * These objects contain a value for the view_name
property,
- * but not for the view_state
property.
- * @return {Promise} An array which has all saved dashboards.
- *
- * @example Get the list of dashboards from the server:
- *
- * con.getFrontendViewsAsync().then((results) => console.log(results))
- * // [TFrontendView, TFrontendView]
- */
+ var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
+ var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null);
+ if (isShapeFile) {
+ return _client.import_geo_table(_sessionId, tableName, fileName, thriftCopyParams, thriftRowDesc, callback);
+ } else {
+ return _client.import_table(_sessionId, tableName, fileName, thriftCopyParams, callback);
+ }
+ }
+ /**
+ * Import a geo table from a file.
+ * @param {String} tableName - desired name of the new table
+ * @param {String} fileName - name of imported file
+ * @param {TCopyParams} copyParams - see {@link TCopyParams}
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ */
+ function importShapeTable(tableName, fileName, copyParams, rowDescObj, callback) {
+ return importTable(tableName, fileName, copyParams, rowDescObj, callback, true);
+ }
+ /**
+ * Use for backend rendering. This method will fetch a PNG image
+ * that is a render of the vega json object.
+ *
+ * @param {Number} widgetid the widget id of the calling widget
+ * @param {String} vega the vega json
+ * @param {Object} options the options for the render query
+ * @param {Number} options.compressionLevel the png compression level.
+ * range 1 (low compression, faster) to 10 (high compression, slower).
+ * Default 3.
+ * @param {Function} callback (error, Base64Image) => {…}
+ * @returns {undefined}
+ */
+ function renderVega(widgetid, vega, options, callback) {
+ var queryId = null;
+ var compressionLevel = COMPRESSION_LEVEL_DEFAULT;
+ if (options) {
+ queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
+ compressionLevel = options.hasOwnProperty("compressionLevel") ? options.compressionLevel : compressionLevel;
+ }
- /**
- * Get a dashboard object containing a value for the view_state
property.
- * This object contains a value for the view_state
property,
- * but not for the view_name
property.
- * @param {String} viewName the name of the dashboard
- * @return {Promise.} An object that contains all data and metadata related to the dashboard
- *
- * @example Get a specific dashboard from the server:
- *
- * con.getFrontendViewAsync('dashboard_name').then((result) => console.log(result))
- * // {TFrontendView}
- */
+ var lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME;
+ var curNonce = (_nonce++).toString();
- /**
- * Get the status of the server as a TServerStatus
object.
- * This includes whether the server is read-only,
- * has backend rendering enabled, and the version number.
- * @return {Promise.}
- *
- * @example Get the server status:
- *
- * con.getServerStatusAsync().then((result) => console.log(result))
- * // {
- * // "read_only": false,
- * // "version": "3.0.0dev-20170503-40e2de3",
- * // "rendering_enabled": true,
- * // "start_time": 1493840131
- * // }
- */
+ var processResultsOptions = {
+ isImage: true,
+ query: "render: " + vega,
+ queryId: queryId,
+ conId: 0,
+ estimatedQueryTime: lastQueryTime
+ };
- }, {
- key: "createFrontendViewAsync",
+ _client.render_vega(_sessionId, widgetid, vega, compressionLevel, curNonce, function (error, result) {
+ if (error) {
+ return callback(normalizeError(error));
+ }
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions);
+ });
+ }
+ /**
+ * Used primarily for backend rendered maps, this method will fetch the row
+ * for a specific table that was last rendered at a pixel.
+ * @param {Number} widgetId - the widget id of the caller
+ * @param {TPixel} pixel - the pixel (lower left-hand corner is pixel (0,0))
+ * @param {Object} tableColNamesMap - object of tableName -> array of col names
+ * @param {Function} callback (error, results) => {…}
+ * @param {Number} [pixelRadius=2] - the radius around the primary pixel to search
+ * @returns {undefined}
+ */
+ function getPixel(widgetId, pixel, tableColNamesMap, callback) {
+ var pixelRadius = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2;
-
- /**
- * Add a new dashboard to the server.
- * @param {String} viewName - the name of the new dashboard
- * @param {String} viewState - the base64-encoded state string of the new dashboard
- * @param {String} imageHash - the numeric hash of the dashboard thumbnail
- * @param {String} metaData - Stringified metaData related to the view
- * @return {Promise} Returns empty if success
- *
- * @example Add a new dashboard to the server:
- *
- * con.createFrontendViewAsync('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
- */
- value: function createFrontendViewAsync(viewName, viewState, imageHash, metaData) {
- var _this4 = this;
-
- if (!this._sessionId) {
- return new Promise(function (resolve, reject) {
- reject(new Error("You are not connected to a server. Try running the connect method first."));
- });
- }
-
- return Promise.all(this._client.map(function (client, i) {
- return new Promise(function (resolve, reject) {
- client.create_frontend_view(_this4._sessionId[i], viewName, viewState, imageHash, metaData, function (error, data) {
- if (error) {
- reject(error);
- } else {
- resolve(data);
- }
- });
- });
- }));
+ if (Array.isArray(callback)) {
+ console.warn("getPixel callbacks array deprecated; pass single callback instead."); // eslint-disable-line no-console
+ callback = callback[0];
}
- }, {
- key: "deleteFrontendView",
- value: function deleteFrontendView(viewName, callback) {
- var _this5 = this;
-
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
- }
- try {
- this._client.forEach(function (client, i) {
- // do we want to try each one individually so if we fail we keep going?
- client.delete_frontend_view(_this5._sessionId[i], viewName, callback);
- });
- } catch (err) {
- console.log("ERROR: Could not delete the frontend view. Check your session id.", err);
- }
+ if (!(pixel instanceof TPixel)) {
+ pixel = new TPixel(pixel);
}
-
- /**
- * Delete a dashboard object containing a value for the view_state
property.
- * @param {String} viewName - the name of the dashboard
- * @return {Promise.} Name of dashboard successfully deleted
- *
- * @example Delete a specific dashboard from the server:
- *
- * con.deleteFrontendViewAsync('dashboard_name').then(res => console.log(res))
- */
-
- }, {
- key: "createLinkAsync",
-
-
- /**
- * Create a short hash to make it easy to share a link to a specific dashboard.
- * @param {String} viewState - the base64-encoded state string of the new dashboard
- * @param {String} metaData - Stringified metaData related to the link
- * @return {Promise.} link - A short hash of the dashboard used for URLs
- *
- * @example Create a link to the current state of a dashboard:
- *
- * con.createLinkAsync("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
- * // ["28127951"]
- */
- value: function createLinkAsync(viewState, metaData) {
- var _this6 = this;
-
- return Promise.all(this._client.map(function (client, i) {
- return new Promise(function (resolve, reject) {
- client.create_link(_this6._sessionId[i], viewState, metaData, function (error, data) {
- if (error) {
- reject(error);
- } else {
- var result = data.split(",").reduce(function (links, link) {
- if (links.indexOf(link) === -1) {
- links.push(link);
- }
- return links;
- }, []);
- if (!result || result.length !== 1) {
- reject(new Error("Different links were created on connection"));
- } else {
- resolve(result.join());
- }
- }
- });
- });
- }));
+ var columnFormat = true;
+ var curNonce = String(_nonce++);
+ _client.get_result_row_for_pixel(_sessionId, widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce, processPixelResults.bind(this, callback, _logging, _datumEnum));
+ }
+ /**
+ * Get or set the session ID used by the server to serve the correct data.
+ * This is typically set by {@link connect} and should not be set manually.
+ * @param {Number} newSessionId - The session ID of the current connection
+ * @returns {Number|Connector} - The session ID or the Connector itself
+ *
+ * @example Get the session id:
+ *
+ * con.sessionId();
+ * // sessionID === 3145846410
+ *
+ * @example Set the session id:
+ * var con = new Connector().connect().sessionId(3415846410);
+ * // NOTE: It is generally unsafe to set the session id manually.
+ */
+ function sessionId(newSessionId) {
+ if (!arguments.length) {
+ return _sessionId;
}
-
- /**
- * Get a fully-formed dashboard object from a generated share link.
- * This object contains the given link for the view_name
property,
- * @param {String} link - the short hash of the dashboard, see {@link createLink}
- * @return {Promise.} Object of the dashboard and metadata
- *
- * @example Get a dashboard from a link:
- *
- * con.getLinkViewAsync('28127951').then(res => console.log(res))
- * // {
- * // "view_name": "28127951",
- * // "view_state": "eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==",
- * // "image_hash": "",
- * // "update_time": "2017-04-28T21:34:01Z",
- * // "view_metadata": "metaData"
- * // }
- */
-
- }, {
- key: "detectColumnTypes",
- value: function detectColumnTypes(fileName, copyParams, callback) {
- var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
- this._client[0].detect_column_types(this._sessionId[0], fileName, thriftCopyParams, callback);
+ _sessionId = newSessionId;
+ return this;
+ }
+ /**
+ * Get or set the connection server hostname.
+ * This is is typically the first method called after instantiating a new Connector.
+ * @param {String} hostname - The hostname address
+ * @returns {String|Connector} - The hostname or the Connector itself
+ *
+ * @example Set the hostname:
+ * var con = new Connector().host('localhost');
+ *
+ * @example Get the hostname:
+ * var host = con.host();
+ * // host === 'localhost'
+ */
+ function host(hostname) {
+ if (!arguments.length) {
+ return _host;
}
-
- /**
- * Asynchronously get the data from an importable file,
- * such as a .csv or plaintext file with a header.
- * @param {String} fileName - the name of the importable file
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @returns {Promise.} An object which has copy_params and row_set
- *
- * @example Get data from table_data.csv:
- *
- * var copyParams = new TCopyParams();
- * con.detectColumnTypesAsync('table_data.csv', copyParams).then(res => console.log(res))
- * // TDetectResult {row_set: TRowSet, copy_params: TCopyParams}
- *
- */
-
- }, {
- key: "detectColumnTypesAsync",
- value: function detectColumnTypesAsync(fileName, copyParams) {
- var _this7 = this;
-
- return new Promise(function (resolve, reject) {
- _this7.detectColumnTypes.bind(_this7, fileName, copyParams)(function (err, res) {
- if (err) {
- reject(err);
- } else {
- _this7.importerRowDesc = res.row_set.row_desc;
- resolve(res);
- }
- });
- });
+ _host = hostname;
+ return this;
+ }
+ /**
+ * Get or set the connection port.
+ * @param {String} thePort - The port to connect on
+ * @returns {String|Connector} - The port or the Connector itself
+ *
+ * @example Set the port:
+ * var con = new Connector().port('8080');
+ *
+ * @example Get the port:
+ * var port = con.port();
+ * // port === '8080'
+ */
+ function port(thePort) {
+ if (!arguments.length) {
+ return _port;
}
-
- /**
- * Submit a query to the database and process the results.
- * @param {String} query The query to perform
- * @param {Object} options the options for the query
- * @param {Function} callback that takes `(err, result) => result`
- * @returns {Object} The result of the query
- *
- * @example create a query
- *
- * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
- * var options = {};
- *
- * con.query(query, options, function(err, result) {
- * console.log(result)
- * });
- *
- */
-
- }, {
- key: "query",
- value: function query(_query, options, callback) {
- var _this8 = this;
-
- var columnarResults = true;
- var eliminateNullRows = false;
- var queryId = null;
- var returnTiming = false;
- var limit = -1;
- if (options) {
- columnarResults = options.hasOwnProperty("columnarResults") ? options.columnarResults : columnarResults;
- eliminateNullRows = options.hasOwnProperty("eliminateNullRows") ? options.eliminateNullRows : eliminateNullRows;
- queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
- returnTiming = options.hasOwnProperty("returnTiming") ? options.returnTiming : returnTiming;
- limit = options.hasOwnProperty("limit") ? options.limit : limit;
- }
-
- var lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME;
-
- var curNonce = (this._nonce++).toString();
-
- var conId = 0;
-
- var processResultsOptions = {
- returnTiming: returnTiming,
- eliminateNullRows: eliminateNullRows,
- query: _query,
- queryId: queryId,
- conId: conId,
- estimatedQueryTime: lastQueryTime
- };
-
- try {
- if (callback) {
- this._client[conId].sql_execute(this._sessionId[conId], _query, columnarResults, curNonce, limit, function (error, result) {
- if (error) {
- callback(error);
- } else {
- _this8.processResults(processResultsOptions, result, callback);
- }
- });
- return curNonce;
- } else if (!callback) {
- var SQLExecuteResult = this._client[conId].sql_execute(this._sessionId[conId], _query, columnarResults, curNonce, limit);
- return this.processResults(processResultsOptions, SQLExecuteResult);
- }
- } catch (err) {
- if (err.name === "NetworkError") {
- this.removeConnection(conId);
- if (this._numConnections === 0) {
- err.msg = "No remaining database connections";
- throw err;
- }
- this.query(_query, options, callback);
- } else if (callback) {
- callback(err);
- } else {
- throw err;
- }
- }
+ _port = thePort;
+ return this;
+ }
+ /**
+ * Get or set the username to authenticate with.
+ * @param {String} username - The username to authenticate with
+ * @returns {String|Connector} - The username or the Connector itself
+ *
+ * @example Set the username:
+ * var con = new Connector().user('foo');
+ *
+ * @example Get the username:
+ * var username = con.user();
+ * // user === 'foo'
+ */
+ function user(username) {
+ if (!arguments.length) {
+ return _user;
}
-
- /** @deprecated will default to query */
-
- }, {
- key: "validateQuery",
-
-
- /**
- * Submit a query to validate whether the backend can create a result set based on the SQL statement.
- * @param {String} query The query to perform
- * @returns {Promise.} The result of whether the query is valid
- *
- * @example create a query
- *
- * var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
- *
- * con.validateQuery(query).then(res => console.log(res))
- *
- * // [{
- * // "name": "n",
- * // "type": "INT",
- * // "is_array": false,
- * // "is_dict": false
- * // }]
- *
- */
- value: function validateQuery(query) {
- var _this9 = this;
-
- return new Promise(function (resolve, reject) {
- _this9._client[0].sql_validate(_this9._sessionId[0], query, function (error, res) {
- if (error) {
- reject(error);
- } else {
- resolve(_this9.convertFromThriftTypes(res));
- }
- });
- });
+ _user = username;
+ return this;
+ }
+ /**
+ * Get or set the user's password to authenticate with.
+ * @param {String} pass - The password to authenticate with
+ * @returns {String|Connector} - The password or the Connector itself
+ *
+ * @example Set the password:
+ * var con = new Connector().password('bar');
+ *
+ * @example Get the username:
+ * var password = con.password();
+ * // password === 'bar'
+ */
+ function password(pass) {
+ if (!arguments.length) {
+ return _password;
}
- }, {
- key: "removeConnection",
- value: function removeConnection(conId) {
- if (conId < 0 || conId >= this.numConnections) {
- var err = {
- msg: "Remove connection id invalid"
- };
- throw err;
- }
- this._client.splice(conId, 1);
- this._sessionId.splice(conId, 1);
- this._numConnections--;
+ _password = pass;
+ return this;
+ }
+ /**
+ * Get or set the name of the database to connect to.
+ * @param {String} db - The database to connect to
+ * @returns {String|Connector} - The name of the database or the Connector itself
+ *
+ * @example Set the database name:
+ * var con = new Connector().dbName('myDatabase');
+ *
+ * @example Get the database name:
+ * var dbName = con.dbName();
+ * // dbName === 'myDatabase'
+ */
+ function dbName(db) {
+ if (!arguments.length) {
+ return _dbName;
}
- }, {
- key: "getTables",
- value: function getTables(callback) {
- this._client[0].get_tables(this._sessionId[0], function (error, tables) {
- if (error) {
- callback(error);
- } else {
- callback(null, tables.map(function (table) {
- return {
- name: table,
- label: "obs"
- };
- }));
- }
- });
+ _dbName = db;
+ return this;
+ }
+ /**
+ * Whether the raw queries strings will be logged to the console.
+ * Used primarily for debugging and defaults to false
.
+ * @param {Boolean} loggingEnabled - Set to true to enable logging
+ * @returns {Boolean|Connector} - The current logging flag or Connector itself
+ *
+ * @example Set logging to true:
+ * var con = new Connector().logging(true);
+ *
+ * @example Get the logging flag:
+ * var isLogging = con.logging();
+ * // isLogging === true
+ */
+ function logging(loggingEnabled) {
+ if (typeof loggingEnabled === "undefined") {
+ return _logging;
+ } else if (typeof loggingEnabled !== "boolean") {
+ return "logging can only be set with boolean values";
}
-
- /**
- * Get the names of the databases that exist on the current session's connectdion.
- * @return {Promise.} list of table objects containing the label and table names.
- *
- * @example Get the list of tables from a connection:
- *
- * con.getTablesAsync().then(res => console.log(res))
- *
- * // [{
- * // label: 'obs', // deprecated property
- * // name: 'myDatabaseName'
- * // },
- * // ...]
- */
-
- }, {
- key: "getTablesAsync",
- value: function getTablesAsync() {
- var _this10 = this;
-
- return new Promise(function (resolve, reject) {
- _this10.getTables.bind(_this10)(function (error, tables) {
- if (error) {
- reject(error);
- } else {
- resolve(tables);
- }
- });
- });
+ _logging = loggingEnabled;
+ var isEnabledTxt = loggingEnabled ? "enabled" : "disabled";
+ return "SQL logging is now " + isEnabledTxt;
+ }
+ /**
+ * The protocol to use for requests.
+ * @param {String} theProtocol - http or https
+ * @returns {String|Connector} - protocol or Connector itself
+ *
+ * @example Set the protocol:
+ * var con = new Connector().protocol('http');
+ *
+ * @example Get the protocol:
+ * var protocol = con.protocol();
+ * // protocol === 'http'
+ */
+ function protocol(theProtocol) {
+ if (!arguments.length) {
+ return _protocol;
}
+ _protocol = theProtocol;
+ return this;
+ }
+ }
- /**
- * Create an array-like object from {@link TDatumType} by
- * flipping the string key and numerical value around.
- *
- * @returns {Undefined} This function does not return anything
- */
+ // helper functions
- }, {
- key: "invertDatumTypes",
- value: function invertDatumTypes() {
- var datumType = TDatumType; // eslint-disable-line no-undef
- for (var key in datumType) {
- if (datumType.hasOwnProperty(key)) {
- this._datumEnum[datumType[key]] = key;
- }
- }
- }
+ function noop() {/* noop */}
- /**
- * Get a list of field objects for a given table.
- * @param {String} tableName - name of table containing field names
- * @param {Function} callback - (err, results)
- * @return {Array} fields - the formmatted list of field objects
- *
- * @example Get the list of fields from a specific table:
- *
- * con.getFields('flights', (err, res) => console.log(res))
- * // [{
- * name: 'fieldName',
- * type: 'BIGINT',
- * is_array: false,
- * is_dict: false
- * }, ...]
- */
+ function isNodeRuntime() {
+ return typeof window === "undefined";
+ }
- }, {
- key: "getFields",
- value: function getFields(tableName, callback) {
- var _this11 = this;
+ function publicizeMethods(theClass, methods) {
+ methods.forEach(function (method) {
+ theClass[method.name] = method;
+ });
+ }
- this._client[0].get_table_details(this._sessionId[0], tableName, function (error, fields) {
- if (fields) {
- var rowDict = fields.row_desc.reduce(function (accum, value) {
- accum[value.col_name] = value;
- return accum;
- }, {});
- callback(null, _this11.convertFromThriftTypes(rowDict));
- } else {
- callback(new Error("Table (" + tableName + ") not found" + error));
- }
+ function convertFromThriftTypes(fields, _datumEnum) {
+ var fieldsArray = [];
+ for (var key in fields) {
+ if (fields.hasOwnProperty(key)) {
+ fieldsArray.push({
+ name: key,
+ type: _datumEnum[fields[key].col_type.type],
+ is_array: fields[key].col_type.is_array,
+ is_dict: fields[key].col_type.encoding === TEncodingType.DICT
});
}
- }, {
- key: "createTable",
- value: function createTable(tableName, rowDescObj, tableType, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
- }
-
- var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc);
-
- for (var c = 0; c < this._numConnections; c++) {
- this._client[c].create_table(this._sessionId[c], tableName, thriftRowDesc, tableType, function (err) {
- if (err) {
- callback(err);
- } else {
- callback();
- }
- });
- }
- }
-
- /**
- * Create a table and persist it to the backend.
- * @param {String} tableName - desired name of the new table
- * @param {Array} rowDescObj - fields of the new table
- * @param {Number} tableType - the types of tables a user can import into the db
- * @return {Promise.} it will either catch an error or return undefined on success
- *
- * @example Create a new table:
- *
- * con.createTable('mynewtable', [TColumnType, TColumnType, ...], 0).then(res => console.log(res));
- * // undefined
- */
-
- }, {
- key: "importTable",
- value: function importTable(tableName, fileName, copyParams, rowDescObj, isShapeFile, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.");
- }
-
- var thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams);
- var thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc);
-
- var thriftCallBack = function thriftCallBack(err, res) {
- if (err) {
- callback(err);
- } else {
- callback(null, res);
- }
- };
-
- for (var c = 0; c < this._numConnections; c++) {
- if (isShapeFile) {
- this._client[c].import_geo_table(this._sessionId[c], tableName, fileName, thriftCopyParams, thriftRowDesc, thriftCallBack);
- } else {
- this._client[c].import_table(this._sessionId[c], tableName, fileName, thriftCopyParams, thriftCallBack);
- }
- }
- }
- }, {
- key: "importTableAsyncWrapper",
- value: function importTableAsyncWrapper(isShapeFile) {
- var _this12 = this;
-
- return function (tableName, fileName, copyParams, headers) {
- return new Promise(function (resolve, reject) {
- _this12.importTable(tableName, fileName, copyParams, headers, isShapeFile, function (err, link) {
- if (err) {
- reject(err);
- } else {
- resolve(link);
- }
- });
- });
- };
- }
-
- /**
- * Import a delimited table from a file.
- * @param {String} tableName - desired name of the new table
- * @param {String} fileName
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
- */
-
-
- /**
- * Import a geo table from a file.
- * @param {String} tableName - desired name of the new table
- * @param {String} fileName
- * @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
- */
-
- }, {
- key: "renderVega",
-
-
- /**
- * Use for backend rendering. This method will fetch a PNG image
- * that is a render of the vega json object.
- *
- * @param {Number} widgetid the widget id of the calling widget
- * @param {String} vega the vega json
- * @param {Object} options the options for the render query
- * @param {Number} options.compressionLevel the png compression level.
- * range 1 (low compression, faster) to 10 (high compression, slower).
- * Default 3.
- * @param {Function} callback takes `(err, success)` as its signature. Returns con singleton on success.
- *
- * @returns {Image} Base 64 Image
- */
- value: function renderVega(widgetid, vega, options, callback) /* istanbul ignore next */{
- var _this13 = this;
-
- var queryId = null;
- var compressionLevel = COMPRESSION_LEVEL_DEFAULT;
- if (options) {
- queryId = options.hasOwnProperty("queryId") ? options.queryId : queryId;
- compressionLevel = options.hasOwnProperty("compressionLevel") ? options.compressionLevel : compressionLevel;
- }
-
- var lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME;
-
- var curNonce = (this._nonce++).toString();
-
- var conId = 0;
- this._lastRenderCon = conId;
-
- var processResultsOptions = {
- isImage: true,
- query: "render: " + vega,
- queryId: queryId,
- conId: conId,
- estimatedQueryTime: lastQueryTime
- };
-
- try {
- if (!callback) {
- var renderResult = this._client[conId].render_vega(this._sessionId[conId], widgetid, vega, compressionLevel, curNonce);
- return this.processResults(processResultsOptions, renderResult);
- }
-
- this._client[conId].render_vega(this._sessionId[conId], widgetid, vega, compressionLevel, curNonce, function (error, result) {
- if (error) {
- callback(error);
- } else {
- _this13.processResults(processResultsOptions, result, callback);
- }
- });
- } catch (err) {
- throw err;
- }
-
- return curNonce;
- }
-
- /**
- * Used primarily for backend rendered maps, this method will fetch the row
- * for a specific table that was last rendered at a pixel.
- *
- * @param {widgetId} Number - the widget id of the caller
- * @param {TPixel} pixel - the pixel (lower left-hand corner is pixel (0,0))
- * @param {String} tableName - the table containing the geo data
- * @param {Object} tableColNamesMap - object of tableName -> array of col names
- * @param {Array} callbacks
- * @param {Number} [pixelRadius=2] - the radius around the primary pixel to search
- */
-
- }, {
- key: "getResultRowForPixel",
- value: function getResultRowForPixel(widgetId, pixel, tableColNamesMap, callbacks) /* istanbul ignore next */{
- var pixelRadius = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 2;
-
- if (!(pixel instanceof TPixel)) {
- pixel = new TPixel(pixel);
- }
- var columnFormat = true; // BOOL
- var curNonce = (this._nonce++).toString();
- try {
- if (!callbacks) {
- return this.processPixelResults(undefined, // eslint-disable-line no-undefined
- this._client[this._lastRenderCon].get_result_row_for_pixel(this._sessionId[this._lastRenderCon], widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce));
- }
- this._client[this._lastRenderCon].get_result_row_for_pixel(this._sessionId[this._lastRenderCon], widgetId, pixel, tableColNamesMap, columnFormat, pixelRadius, curNonce, this.processPixelResults.bind(this, callbacks));
- } catch (err) {
- throw err;
- }
- return curNonce;
- }
-
- /**
- * Formats the pixel results into the same pattern as textual results.
- *
- * @param {Array} callbacks a collection of callbacks
- * @param {Object} error an error if one was thrown, otherwise null
- * @param {Array|Object} results unformatted results of pixel rowId information
- *
- * @returns {Object} An object with the pixel results formatted for display
- */
-
- }, {
- key: "processPixelResults",
- value: function processPixelResults(callbacks, error, results) {
- callbacks = Array.isArray(callbacks) ? callbacks : [callbacks];
- results = Array.isArray(results) ? results.pixel_rows : [results];
- var numPixels = results.length;
- var processResultsOptions = {
- isImage: false,
- eliminateNullRows: false,
- query: "pixel request",
- queryId: -2
- };
- for (var p = 0; p < numPixels; p++) {
- results[p].row_set = this.processResults(processResultsOptions, results[p]);
- }
- if (!callbacks) {
- return results;
- }
- callbacks.pop()(error, results);
- }
-
- /**
- * Get or set the session ID used by the server to serve the correct data.
- * This is typically set by {@link connect} and should not be set manually.
- * @param {Number} sessionId - The session ID of the current connection
- * @return {Number|MapdCon} - The session ID or the MapdCon itself
- *
- * @example Get the session id:
- *
- * con.sessionId();
- * // sessionID === 3145846410
- *
- * @example Set the session id:
- * var con = new MapdCon().connect().sessionId(3415846410);
- * // NOTE: It is generally unsafe to set the session id manually.
- */
-
- }, {
- key: "sessionId",
- value: function sessionId(_sessionId) {
- if (!arguments.length) {
- return this._sessionId;
- }
- this._sessionId = _sessionId;
- return this;
- }
-
- /**
- * Get or set the connection server hostname.
- * This is is typically the first method called after instantiating a new MapdCon.
- * @param {String} host - The hostname address
- * @return {String|MapdCon} - The hostname or the MapdCon itself
- *
- * @example Set the hostname:
- * var con = new MapdCon().host('localhost');
- *
- * @example Get the hostname:
- * var host = con.host();
- * // host === 'localhost'
- */
-
- }, {
- key: "host",
- value: function host(_host) {
- if (!arguments.length) {
- return this._host;
- }
- this._host = arrayify(_host);
- return this;
- }
-
- /**
- * Get or set the connection port.
- * @param {String} port - The port to connect on
- * @return {String|MapdCon} - The port or the MapdCon itself
- *
- * @example Set the port:
- * var con = new MapdCon().port('8080');
- *
- * @example Get the port:
- * var port = con.port();
- * // port === '8080'
- */
-
- }, {
- key: "port",
- value: function port(_port) {
- if (!arguments.length) {
- return this._port;
- }
- this._port = arrayify(_port);
- return this;
- }
-
- /**
- * Get or set the username to authenticate with.
- * @param {String} user - The username to authenticate with
- * @return {String|MapdCon} - The username or the MapdCon itself
- *
- * @example Set the username:
- * var con = new MapdCon().user('foo');
- *
- * @example Get the username:
- * var username = con.user();
- * // user === 'foo'
- */
-
- }, {
- key: "user",
- value: function user(_user) {
- if (!arguments.length) {
- return this._user;
- }
- this._user = arrayify(_user);
- return this;
- }
-
- /**
- * Get or set the user's password to authenticate with.
- * @param {String} password - The password to authenticate with
- * @return {String|MapdCon} - The password or the MapdCon itself
- *
- * @example Set the password:
- * var con = new MapdCon().password('bar');
- *
- * @example Get the username:
- * var password = con.password();
- * // password === 'bar'
- */
-
- }, {
- key: "password",
- value: function password(_password) {
- if (!arguments.length) {
- return this._password;
- }
- this._password = arrayify(_password);
- return this;
- }
-
- /**
- * Get or set the name of the database to connect to.
- * @param {String} dbName - The database to connect to
- * @return {String|MapdCon} - The name of the database or the MapdCon itself
- *
- * @example Set the database name:
- * var con = new MapdCon().dbName('myDatabase');
- *
- * @example Get the database name:
- * var dbName = con.dbName();
- * // dbName === 'myDatabase'
- */
-
- }, {
- key: "dbName",
- value: function dbName(_dbName) {
- if (!arguments.length) {
- return this._dbName;
- }
- this._dbName = arrayify(_dbName);
- return this;
- }
-
- /**
- * Whether the raw queries strings will be logged to the console.
- * Used primarily for debugging and defaults to false
.
- * @param {Boolean} logging - Set to true to enable logging
- * @return {Boolean|MapdCon} - The current logging flag or MapdCon itself
- *
- * @example Set logging to true:
- * var con = new MapdCon().logging(true);
- *
- * @example Get the logging flag:
- * var isLogging = con.logging();
- * // isLogging === true
- */
-
- }, {
- key: "logging",
- value: function logging(_logging) {
- if (typeof _logging === "undefined") {
- return this._logging;
- } else if (typeof _logging !== "boolean") {
- return "logging can only be set with boolean values";
- }
- this._logging = _logging;
- var isEnabledTxt = _logging ? "enabled" : "disabled";
- return "SQL logging is now " + isEnabledTxt;
- }
-
- /**
- * The name of the platform.
- * @param {String} platform - The platform, default is "mapd"
- * @return {String|MapdCon} - The platform or the MapdCon itself
- *
- * @example Set the platform name:
- * var con = new MapdCon().platform('myPlatform');
- *
- * @example Get the platform name:
- * var platform = con.platform();
- * // platform === 'myPlatform'
- */
-
- }, {
- key: "platform",
- value: function platform(_platform) {
- if (!arguments.length) {
- return this._platform;
- }
- this._platform = _platform;
- return this;
- }
-
- /**
- * Get the number of connections that are currently open.
- * @return {Number} - number of open connections
- *
- * @example Get the number of connections:
- *
- * var numConnections = con.numConnections();
- * // numConnections === 1
- */
-
- }, {
- key: "numConnections",
- value: function numConnections() {
- return this._numConnections;
- }
+ }
+ return fieldsArray;
+ }
- /**
- * The protocol to use for requests.
- * @param {String} protocol - http or https
- * @return {String|MapdCon} - protocol or MapdCon itself
- *
- * @example Set the protocol:
- * var con = new MapdCon().protocol('http');
- *
- * @example Get the protocol:
- * var protocol = con.protocol();
- * // protocol === 'http'
- */
+ function updateQueryTimes(queryTimes) {
+ return function (conId, queryId, estimatedQueryTime, execution_time_ms) {
+ queryTimes[queryId] = execution_time_ms;
+ };
+ }
- }, {
- key: "protocol",
- value: function protocol(_protocol) {
- if (!arguments.length) {
- return this._protocol;
+ function processPixelResults(callback, _logging, _datumEnum, error, results) {
+ // eslint-disable-line consistent-return
+ if (error) {
+ return callback(normalizeError(error));
+ }
+ results = Array.isArray(results) ? results.pixel_rows : [results];
+ var numPixels = results.length;
+ var processResultsOptions = {
+ isImage: false,
+ eliminateNullRows: false,
+ query: "pixel request",
+ queryId: -2
+ };
+ var numResultsProcessed = 0;
+ for (var p = 0; p < numPixels; p++) {
+ processResults(results[p], aggregatingCallback(p), _logging, _datumEnum, processResultsOptions);
+ }
+ function aggregatingCallback(index) {
+ return function (processResultsError, row_set) {
+ results[index].row_set = row_set;
+ if (processResultsError) {
+ numResultsProcessed = -Infinity; // avoid invoking callback again
+ return callback(processResultsError);
+ } else if (numResultsProcessed === numPixels - 1) {
+ return callback(null, results);
+ } else {
+ return numResultsProcessed++;
}
- this._protocol = arrayify(_protocol);
- return this;
- }
+ };
+ }
+ }
- /**
- * Generates a list of endpoints from the connection params.
- * @return {Array} - list of endpoints
- *
- * @example Get the endpoints:
- * var con = new MapdCon().protocol('http').host('localhost').port('8000');
- * var endpoints = con.getEndpoints();
- * // endpoints === [ 'http://localhost:8000' ]
- */
+ function processResults(result, callback, _logging, _datumEnum) {
+ var options = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
- }, {
- key: "getEndpoints",
- value: function getEndpoints() {
- var _this14 = this;
+ var processor = (0, _processQueryResults2.default)(_logging, updateQueryTimes);
+ var processResultsObject = processor(options, _datumEnum, result, callback);
+ return processResultsObject;
+ }
- return this._host.map(function (host, i) {
- return _this14._protocol[i] + "://" + host + ":" + _this14._port[i];
- });
+ function invertDatumTypes(datumEnum) {
+ var datumType = TDatumType;
+ for (var key in datumType) {
+ if (datumType.hasOwnProperty(key)) {
+ datumEnum[datumType[key]] = key;
}
- }]);
-
- return MapdCon;
- }();
+ }
+ }
function resetThriftClientOnArgumentErrorForMethods(connector, client, methodNames) {
methodNames.forEach(function (methodName) {
@@ -26708,14 +26296,13 @@ module.exports =
});
}
- // Set a global mapdcon function when mapdcon is brought in via script tag.
- if (( false ? "undefined" : _typeof(module)) === "object" && module.exports) {
- if (!isNodeRuntime()) {
- window.MapdCon = MapdCon;
+ function normalizeError(error) {
+ if (isNodeRuntime()) {
+ return new Error(error.name + " " + error.error_msg);
+ } else {
+ return new Error("TMapDException " + error.message);
}
}
- module.exports = MapdCon;
- exports.default = MapdCon;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(55)(module)))
/***/ }),
@@ -26804,8 +26391,8 @@ module.exports =
};
MapDClientV2.prototype.get_result_row_for_pixel = function () {
- var getResultRowForPixelWithErrorHandling = (0, _wrapWithErrorHandling.wrapWithErrorHandling)(this, "get_result_row_for_pixel");
- return getResultRowForPixelWithErrorHandling.apply(undefined, arguments);
+ var getPixelWithErrorHandling = (0, _wrapWithErrorHandling.wrapWithErrorHandling)(this, "get_result_row_for_pixel");
+ return getPixelWithErrorHandling.apply(undefined, arguments);
};
MapDClientV2.prototype.delete_frontend_view = function () {
diff --git a/examples/browser.html b/examples/browser.html
index c9dfe4d6..0e5cc12c 100644
--- a/examples/browser.html
+++ b/examples/browser.html
@@ -38,7 +38,7 @@
// The total number of tweets from Columbia
const query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'"
const defaultQueryOptions = {}
- var connector = new MapdCon()
+ var connector = new Connector()
connector
.protocol("https")
@@ -50,9 +50,10 @@
.connect((connectError, session) => { // eslint-disable-line consistent-return
if (connectError) { return console.error("Error connecting", connectError) }
- session.getTablesAsync()
- .then(data => console.log("All tables available at metis.mapd.com:", data.map(x => x.name)))
- .catch(error => console.error("getTablesAsync error:", error))
+ session.getTables((error, data) => {
+ if (error) { return console.error("getTablesAsync error:", error) }
+ return console.log("All tables available at metis.mapd.com:", data.map(x => x.name))
+ })
session.query(query, defaultQueryOptions, (error, data) => {
if (error) { return console.error("Query 1 error:", error) }
diff --git a/examples/node.js b/examples/node.js
index ab0f85ac..748a7382 100644
--- a/examples/node.js
+++ b/examples/node.js
@@ -17,9 +17,10 @@ connector
.connect((connectError, session) => { // eslint-disable-line consistent-return
if (connectError) { return console.error("Error connecting", connectError) }
- session.getTablesAsync()
- .then(data => console.log("All tables available at metis.mapd.com:", data.map(x => x.name)))
- .catch(error => console.error("getTablesAsync error:", error))
+ session.getTables((error, data) => {
+ if (error) { return console.error("getTablesAsync error:", error) }
+ return console.log("All tables available at metis.mapd.com:", data.map(x => x.name))
+ })
session.query(query, defaultQueryOptions, (error, data) => {
if (error) { return console.error("Query 1 error:", error) }
diff --git a/src/mapd-client-v2.js b/src/mapd-client-v2.js
index 7a788956..1bd0b2e4 100644
--- a/src/mapd-client-v2.js
+++ b/src/mapd-client-v2.js
@@ -37,8 +37,8 @@ MapDClientV2.prototype.render_vega = function (...args) {
}
MapDClientV2.prototype.get_result_row_for_pixel = function (...args) {
- const getResultRowForPixelWithErrorHandling = wrapWithErrorHandling(this, "get_result_row_for_pixel")
- return getResultRowForPixelWithErrorHandling(...args)
+ const getPixelWithErrorHandling = wrapWithErrorHandling(this, "get_result_row_for_pixel")
+ return getPixelWithErrorHandling(...args)
}
MapDClientV2.prototype.delete_frontend_view = function (...args) {
diff --git a/src/mapd-con-es6.js b/src/mapd-con-es6.js
index 8d542557..c54ef3b8 100644
--- a/src/mapd-con-es6.js
+++ b/src/mapd-con-es6.js
@@ -12,301 +12,221 @@ import * as helpers from "./helpers"
import MapDClientV2 from "./mapd-client-v2"
import processQueryResults from "./process-query-results"
-const COMPRESSION_LEVEL_DEFAULT = 3
-
-function arrayify (maybeArray) { return Array.isArray(maybeArray) ? maybeArray : [maybeArray] }
-
-function isNodeRuntime () { return typeof window === "undefined" }
-
-class MapdCon {
-
- constructor () {
- this._host = null
- this._user = null
- this._password = null
- this._port = null
- this._dbName = null
- this._client = null
- this._sessionId = null
- this._protocol = null
- this._datumEnum = {}
- this._logging = false
- this._platform = "mapd"
- this._nonce = 0
- this._balanceStrategy = "adaptive"
- this._numConnections = 0
- this._lastRenderCon = 0
- this.queryTimes = { }
- this.serverQueueTimes = null
- this.serverPingTimes = null
- this.pingCount = null
- this.DEFAULT_QUERY_TIME = 50
- this.NUM_PINGS_PER_SERVER = 4
- this.importerRowDesc = null
-
- // invoke initialization methods
- this.invertDatumTypes()
-
- this.processResults = (options = {}, result, callback) => {
- const processor = processQueryResults(this._logging, this.updateQueryTimes)
- const processResultsObject = processor(options, this._datumEnum, result, callback)
- return processResultsObject
- }
-
- // return this to allow chaining off of instantiation
- return this
+// Set a global Connector function when Connector is brought in via script tag.
+if (typeof module === "object" && module.exports) {
+ if (!isNodeRuntime()) {
+ window.Connector = Connector
}
+}
+module.exports = Connector
+export default Connector
+const COMPRESSION_LEVEL_DEFAULT = 3
+const DEFAULT_QUERY_TIME = 50
+
+function Connector () {
+ // initialize variables
+ const _datumEnum = {}
+ const _queryTimes = {}
+ let _client = null
+ let _dbName = null
+ let _host = null
+ let _logging = false
+ let _nonce = 0
+ let _password = null
+ let _port = null
+ let _protocol = null
+ let _sessionId = null
+ let _user = null
+
+ // invoke initialization methods
+ publicizeMethods(this, [
+ connect,
+ createFrontendView,
+ createLink,
+ createTable,
+ dbName,
+ deleteFrontendView,
+ detectColumnTypes,
+ disconnect,
+ getFields,
+ getFrontendView,
+ getFrontendViews,
+ getLinkView,
+ getPixel,
+ getServerStatus,
+ getTables,
+ host,
+ importShapeTable,
+ importTable,
+ logging,
+ password,
+ port,
+ protocol,
+ query,
+ renderVega,
+ sessionId,
+ user,
+ validateQuery
+ ])
+ invertDatumTypes(_datumEnum)
+
+ // return this to allow chaining off of instantiation
+ return this
+
+ // public methods
/**
* Create a connection to the server, generating a client and session id.
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
- * @return {MapdCon} Object
+ * @param {Function} callback (error, session) => {…}
+ * @returns {undefined}
*
* @example Connect to a MapD server:
- * var con = new MapdCon()
+ * var con = new Connector()
* .host('localhost')
* .port('8080')
* .dbName('myDatabase')
* .user('foo')
* .password('bar')
- * .connect((err, con) => console.log(con.sessionId()));
+ * .connect((error, con) => console.log(con.sessionId()));
*
* // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
*/
- connect (callback) {
- if (this._sessionId) {
- this.disconnect()
+ function connect (callback) { // eslint-disable-line consistent-return
+ if (_sessionId) {
+ disconnect()
}
- // TODO: should be its own function
- const allAreArrays = Array.isArray(this._host) && Array.isArray(this._port) && Array.isArray(this._user) && Array.isArray(this._password) && Array.isArray(this._dbName)
- if (!allAreArrays) {
- return callback("All connection parameters must be arrays.")
+ if ([_host, _port, _user, _password, _dbName].some(Array.isArray)) {
+ console.warn("Connection parameters as arrays is deprecated; use single values.") // eslint-disable-line no-console
+ _host = Array.isArray(_host) ? _host[0] : _host
+ _port = Array.isArray(_port) ? _port[0] : _port
+ _user = Array.isArray(_user) ? _user[0] : _user
+ _password = Array.isArray(_password) ? _password[0] : _password
+ _dbName = Array.isArray(_dbName) ? _dbName[0] : _dbName
}
- this._client = []
- this._sessionId = []
-
- if (!this._user[0]) {
+ if (!_user) {
return callback("Please enter a username.")
- } else if (!this._password[0]) {
+ } else if (!_password) {
return callback("Please enter a password.")
- } else if (!this._dbName[0]) {
+ } else if (!_dbName) {
return callback("Please enter a database.")
- } else if (!this._host[0]) {
+ } else if (!_host) {
return callback("Please enter a host name.")
- } else if (!this._port[0]) {
+ } else if (!_port) {
return callback("Please enter a port.")
}
- // now check to see if length of all arrays are the same and > 0
- const hostLength = this._host.length
- if (hostLength < 1) {
- return callback("Must have at least one server to connect to.")
- }
- if (hostLength !== this._port.length || hostLength !== this._user.length || hostLength !== this._password.length || hostLength !== this._dbName.length) {
- return callback("Array connection parameters must be of equal length.")
- }
-
- if (!this._protocol) {
- this._protocol = this._host.map(() => window.location.protocol.replace(":", ""))
- }
-
- const transportUrls = this.getEndpoints()
- for (let h = 0; h < hostLength; h++) {
- let client = null
-
- if (isNodeRuntime()) {
- const {protocol, hostname, port} = parseUrl(transportUrls[h])
- const connection = thriftWrapper.createHttpConnection(
- hostname,
- port,
- {
- transport: thriftWrapper.TBufferedTransport,
- protocol: thriftWrapper.TJSONProtocol,
- path: "/",
- headers: {Connection: "close"},
- https: protocol === "https:"
- }
- )
- connection.on("error", console.error) // eslint-disable-line no-console
- client = thriftWrapper.createClient(MapDThrift, connection)
- resetThriftClientOnArgumentErrorForMethods(this, client, [
- "connect",
- "createFrontendViewAsync",
- "createLinkAsync",
- "createTableAsync",
- "dbName",
- "deleteFrontendViewAsync",
- "detectColumnTypesAsync",
- "disconnect",
- "getFields",
- "getFrontendViewAsync",
- "getFrontendViewsAsync",
- "getLinkViewAsync",
- "getResultRowForPixel",
- "getServerStatusAsync",
- "getTablesAsync",
- "host",
- "importTableAsync",
- "importTableGeoAsync",
- "logging",
- "password",
- "port",
- "protocol",
- "query",
- "renderVega",
- "sessionId",
- "user",
- "validateQuery"
- ])
- } else {
- const thriftTransport = new Thrift.Transport(transportUrls[h])
- const thriftProtocol = new Thrift.Protocol(thriftTransport)
- client = new MapDClientV2(thriftProtocol)
- }
-
- client.connect(this._user[h], this._password[h], this._dbName[h], (error, sessionId) => {
- if (error) {
- callback(error)
- return
+ _client = null
+ _sessionId = null
+ _protocol = _protocol || window.location.protocol.replace(":", "")
+
+ const transportUrl = `${_protocol}://${_host}:${_port}`
+ let client = null
+
+ if (isNodeRuntime()) {
+ const {protocol: parsedProtocol, hostname: parsedHost, port: parsedPort} = parseUrl(transportUrl)
+ const connection = thriftWrapper.createHttpConnection(
+ parsedHost,
+ parsedPort,
+ {
+ transport: thriftWrapper.TBufferedTransport,
+ protocol: thriftWrapper.TJSONProtocol,
+ path: "/",
+ headers: {Connection: "close"},
+ https: parsedProtocol === "https:"
}
- this._client.push(client)
- this._sessionId.push(sessionId)
- this._numConnections = this._client.length
- callback(null, this)
- })
- }
-
- return this
- }
-
- convertFromThriftTypes (fields) {
- const fieldsArray = []
- // silly to change this from map to array
- // - then later it turns back to map
- for (const key in fields) {
- if (fields.hasOwnProperty(key)) {
- fieldsArray.push({
- name: key,
- type: this._datumEnum[fields[key].col_type.type],
- is_array: fields[key].col_type.is_array,
- is_dict: fields[key].col_type.encoding === TEncodingType.DICT // eslint-disable-line no-undef
- })
- }
- }
- return fieldsArray
+ )
+ connection.on("error", console.error) // eslint-disable-line no-console
+ client = thriftWrapper.createClient(MapDThrift, connection)
+ resetThriftClientOnArgumentErrorForMethods(this, client, Object.keys(this))
+ } else {
+ const thriftTransport = new Thrift.Transport(transportUrl)
+ const thriftProtocol = new Thrift.Protocol(thriftTransport)
+ client = new MapDClientV2(thriftProtocol)
+ }
+ client.connect(_user, _password, _dbName, (error, newSessionId) => { // eslint-disable-line no-loop-func
+ if (error) { return callback(normalizeError(error)) }
+ _client = client
+ _sessionId = newSessionId
+ return callback(null, this)
+ })
}
-
/**
* Disconnect from the server then clears the client and session values.
- * @return {MapdCon} Object
- * @param {Function} callback A callback that takes `(err, success)` as its signature. Returns con singleton on success.
+ * @param {Function} callback (error) => {…}
+ * @returns {undefined}
*
* @example Disconnect from the server:
*
* con.sessionId() // ["om9E9Ujgbhl6wIzWgLENncjWsaXRDYLy"]
- * con.disconnect((err, con) => console.log(err, con))
- * con.sessionId() === null;
- */
- disconnect (callback) {
- if (this._sessionId !== null) {
- for (let c = 0; c < this._client.length; c++) {
- this._client[c].disconnect(this._sessionId[c], error => {
- // Success will return NULL
-
- if (error) {
- return callback(error, this)
- }
- this._sessionId = null
- this._client = null
- this._numConnections = 0
- this.serverPingTimes = null
- return callback(null, this)
- })
- }
+ * con.disconnect((err) => {
+ * console.error(err);
+ * con.sessionId() === null;
+ * })
+ */
+ function disconnect (callback = noop) {
+ if (_sessionId !== null) {
+ _client.disconnect(_sessionId, error => { // eslint-disable-line no-loop-func
+ if (error) { return callback(error, this) }
+ _sessionId = null
+ _client = null
+ return callback(null, this)
+ })
}
- return this
- }
-
- updateQueryTimes = (conId, queryId, estimatedQueryTime, execution_time_ms) => {
- this.queryTimes[queryId] = execution_time_ms
}
-
- getFrontendViews = (callback) => {
- if (this._sessionId) {
- this._client[0].get_frontend_views(this._sessionId[0], callback)
+ /**
+ * Get a dashboard object containing a value for the view_state
property.
+ * This object contains a value for the view_state
property,
+ * but not for the view_name
property.
+ * @param {String} viewName the name of the dashboard
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
+ *
+ * @example Get a specific dashboard from the server:
+ *
+ * con.getFrontendView('dashboard_name').then((result) => console.log(result))
+ * // {TFrontendView}
+ */
+ function getFrontendView (viewName, callback) {
+ if (_sessionId && viewName) {
+ _client.get_frontend_view(_sessionId, viewName, callback)
+ return
} else {
callback(new Error("No Session ID"))
+ return
}
}
-
/**
* Get the recent dashboards as a list of TFrontendView
objects.
* These objects contain a value for the view_name
property,
* but not for the view_state
property.
- * @return {Promise} An array which has all saved dashboards.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Get the list of dashboards from the server:
*
- * con.getFrontendViewsAsync().then((results) => console.log(results))
+ * con.getFrontendViews().then((results) => console.log(results))
* // [TFrontendView, TFrontendView]
*/
- getFrontendViewsAsync = () => (
- new Promise((resolve, reject) => {
- this.getFrontendViews((error, views) => {
- if (error) {
- reject(error)
- } else {
- resolve(views)
- }
- })
- })
- )
-
- getFrontendView = (viewName, callback) => {
- if (this._sessionId && viewName) {
- this._client[0].get_frontend_view(this._sessionId[0], viewName, callback)
+ function getFrontendViews (callback) {
+ if (_sessionId) {
+ _client.get_frontend_views(_sessionId, callback)
} else {
callback(new Error("No Session ID"))
+ return
}
}
-
- /**
- * Get a dashboard object containing a value for the view_state
property.
- * This object contains a value for the view_state
property,
- * but not for the view_name
property.
- * @param {String} viewName the name of the dashboard
- * @return {Promise.} An object that contains all data and metadata related to the dashboard
- *
- * @example Get a specific dashboard from the server:
- *
- * con.getFrontendViewAsync('dashboard_name').then((result) => console.log(result))
- * // {TFrontendView}
- */
- getFrontendViewAsync = (viewName) => new Promise((resolve, reject) => {
- this.getFrontendView(viewName, (err, view) => {
- if (err) {
- reject(err)
- } else {
- resolve(view)
- }
- })
- })
-
- getServerStatus = (callback) => {
- this._client[0].get_server_status(this._sessionId[0], callback)
- }
-
/**
* Get the status of the server as a TServerStatus
object.
* This includes whether the server is read-only,
* has backend rendering enabled, and the version number.
- * @return {Promise.}
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Get the server status:
*
- * con.getServerStatusAsync().then((result) => console.log(result))
+ * con.getServerStatus().then((result) => console.log(result))
* // {
* // "read_only": false,
* // "version": "3.0.0dev-20170503-40e2de3",
@@ -314,126 +234,82 @@ class MapdCon {
* // "start_time": 1493840131
* // }
*/
-
- getServerStatusAsync = () => (
- new Promise((resolve, reject) => {
- this.getServerStatus((err, result) => {
- if (err) {
- reject(err)
- } else {
- resolve(result)
- }
- })
- })
- )
-
+ function getServerStatus (callback) {
+ _client.get_server_status(_sessionId, callback)
+ }
/**
* Add a new dashboard to the server.
* @param {String} viewName - the name of the new dashboard
* @param {String} viewState - the base64-encoded state string of the new dashboard
* @param {String} imageHash - the numeric hash of the dashboard thumbnail
* @param {String} metaData - Stringified metaData related to the view
- * @return {Promise} Returns empty if success
+ * @param {Function} callback (error) => {…} success returns null
+ * @returns {undefined}
*
* @example Add a new dashboard to the server:
*
- * con.createFrontendViewAsync('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
+ * con.createFrontendView('newSave', 'viewstateBase64', null, 'metaData').then(res => console.log(res))
*/
- createFrontendViewAsync (viewName, viewState, imageHash, metaData) {
- if (!this._sessionId) {
- return new Promise((resolve, reject) => {
- reject(new Error("You are not connected to a server. Try running the connect method first."))
- })
- }
-
- return Promise.all(this._client.map((client, i) => new Promise((resolve, reject) => {
- client.create_frontend_view(this._sessionId[i], viewName, viewState, imageHash, metaData, (error, data) => {
- if (error) {
- reject(error)
- } else {
- resolve(data)
- }
- })
- })))
+ function createFrontendView (viewName, viewState, imageHash, metaData, callback) {
+ if (!_sessionId) { return callback(new Error("You are not connected to a server. Try running the connect method first.")) }
+ return _client.create_frontend_view(_sessionId, viewName, viewState, imageHash, metaData, callback)
}
-
- deleteFrontendView (viewName, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.")
- }
- try {
- this._client.forEach((client, i) => {
- // do we want to try each one individually so if we fail we keep going?
- client.delete_frontend_view(this._sessionId[i], viewName, callback)
- })
- } catch (err) {
- console.log("ERROR: Could not delete the frontend view. Check your session id.", err)
- }
- }
-
/**
* Delete a dashboard object containing a value for the view_state
property.
* @param {String} viewName - the name of the dashboard
- * @return {Promise.} Name of dashboard successfully deleted
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Delete a specific dashboard from the server:
*
- * con.deleteFrontendViewAsync('dashboard_name').then(res => console.log(res))
+ * con.deleteFrontendView('dashboard_name').then(res => console.log(res))
*/
- deleteFrontendViewAsync = (viewName) => new Promise((resolve, reject) => {
- this.deleteFrontendView(viewName, (err) => {
- if (err) {
- reject(err)
- } else {
- resolve(viewName)
- }
- })
- })
-
+ function deleteFrontendView (viewName, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."))
+ }
+ try { // eslint-disable-line no-restricted-syntax
+ return _client.delete_frontend_view(_sessionId, viewName, callback)
+ } catch (err) {
+ return callback(new Error("Could not delete the frontend view; check your session id.", err))
+ }
+ }
/**
* Create a short hash to make it easy to share a link to a specific dashboard.
* @param {String} viewState - the base64-encoded state string of the new dashboard
* @param {String} metaData - Stringified metaData related to the link
- * @return {Promise.} link - A short hash of the dashboard used for URLs
+ * @param {Function} callback (error, id) => {…}
+ * @returns {undefined}
*
* @example Create a link to the current state of a dashboard:
*
- * con.createLinkAsync("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
+ * con.createLink("eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==", 'metaData').then(res => console.log(res));
* // ["28127951"]
*/
- createLinkAsync (viewState, metaData) {
- return Promise.all(this._client.map((client, i) => new Promise((resolve, reject) => {
- client.create_link(this._sessionId[i], viewState, metaData, (error, data) => {
- if (error) {
- reject(error)
- } else {
- const result = data.split(",").reduce((links, link) => {
- if (links.indexOf(link) === -1) { links.push(link) }
- return links
- }, [])
- if (!result || result.length !== 1) {
- reject(new Error("Different links were created on connection"))
- } else {
- resolve(result.join())
- }
- }
- })
- })))
- }
-
- getLinkView = (link, callback) => {
- this._client[0].get_link_view(this._sessionId[0], link, callback)
+ function createLink (viewState, metaData, callback) {
+ return _client.create_link(_sessionId, viewState, metaData, (error, data) => {
+ if (error) { return callback(normalizeError(error)) }
+ const result = data.split(",").reduce((links, link) => { // eslint-disable-line max-nested-callbacks
+ if (!links.includes(link)) { links.push(link) }
+ return links
+ }, [])
+ if (!result || result.length !== 1) {
+ return callback(new Error("Different links were created on connection"))
+ } else {
+ return callback(null, result.join())
+ }
+ })
}
-
/**
* Get a fully-formed dashboard object from a generated share link.
* This object contains the given link for the view_name
property,
* @param {String} link - the short hash of the dashboard, see {@link createLink}
- * @return {Promise.} Object of the dashboard and metadata
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Get a dashboard from a link:
*
- * con.getLinkViewAsync('28127951').then(res => console.log(res))
+ * con.getLinkView('28127951').then(res => console.log(res))
* // {
* // "view_name": "28127951",
* // "view_state": "eyJuYW1lIjoibXlkYXNoYm9hcmQifQ==",
@@ -442,66 +318,52 @@ class MapdCon {
* // "view_metadata": "metaData"
* // }
*/
- getLinkViewAsync = (link) => new Promise((resolve, reject) => {
- this.getLinkView(link, (err, theLink) => {
- if (err) {
- reject(err)
+ function getLinkView (link, callback) {
+ _client.get_link_view(_sessionId, link, (error, data) => {
+ if (error) {
+ return callback(normalizeError(error))
} else {
- resolve(theLink)
+ return callback(null, data)
}
})
- })
-
- detectColumnTypes (fileName, copyParams, callback) {
- const thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams)
- this._client[0].detect_column_types(this._sessionId[0], fileName, thriftCopyParams, callback)
}
-
/**
* Asynchronously get the data from an importable file,
* such as a .csv or plaintext file with a header.
* @param {String} fileName - the name of the importable file
* @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @returns {Promise.} An object which has copy_params and row_set
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Get data from table_data.csv:
*
* var copyParams = new TCopyParams();
- * con.detectColumnTypesAsync('table_data.csv', copyParams).then(res => console.log(res))
+ * con.detectColumnTypes('table_data.csv', copyParams).then(res => console.log(res))
* // TDetectResult {row_set: TRowSet, copy_params: TCopyParams}
*
*/
- detectColumnTypesAsync (fileName, copyParams) {
- return new Promise((resolve, reject) => {
- this.detectColumnTypes.bind(this, fileName, copyParams)((err, res) => {
- if (err) {
- reject(err)
- } else {
- this.importerRowDesc = res.row_set.row_desc
- resolve(res)
- }
- })
- })
+ function detectColumnTypes (fileName, copyParams, callback) {
+ const thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams)
+ _client.detect_column_types(_sessionId, fileName, thriftCopyParams, callback)
}
-
/**
* Submit a query to the database and process the results.
- * @param {String} query The query to perform
+ * @param {String} sql The query to perform
* @param {Object} options the options for the query
- * @param {Function} callback that takes `(err, result) => result`
- * @returns {Object} The result of the query
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example create a query
*
* var query = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'";
* var options = {};
*
- * con.query(query, options, function(err, result) {
- * console.log(result)
+ * con.query(query, options, function(error, data) {
+ * console.log(data)
* });
*
*/
- query (query, options, callback) {
+ function query (sql, options, callback) {
let columnarResults = true
let eliminateNullRows = false
let queryId = null
@@ -515,64 +377,32 @@ class MapdCon {
limit = options.hasOwnProperty("limit") ? options.limit : limit
}
- const lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME
+ const lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME
- const curNonce = (this._nonce++).toString()
-
- const conId = 0
+ const curNonce = (_nonce++).toString()
const processResultsOptions = {
returnTiming,
eliminateNullRows,
- query,
+ sql,
queryId,
- conId,
+ conId: 0,
estimatedQueryTime: lastQueryTime
}
- try {
- if (callback) {
- this._client[conId].sql_execute(this._sessionId[conId], query, columnarResults, curNonce, limit, (error, result) => {
- if (error) {
- callback(error)
- } else {
- this.processResults(processResultsOptions, result, callback)
- }
- })
- return curNonce
- } else if (!callback) {
- const SQLExecuteResult = this._client[conId].sql_execute(
- this._sessionId[conId],
- query,
- columnarResults,
- curNonce,
- limit
- )
- return this.processResults(processResultsOptions, SQLExecuteResult)
- }
- } catch (err) {
- if (err.name === "NetworkError") {
- this.removeConnection(conId)
- if (this._numConnections === 0) {
- err.msg = "No remaining database connections"
- throw err
- }
- this.query(query, options, callback)
- } else if (callback) {
- callback(err)
+ _client.sql_execute(_sessionId, sql, columnarResults, curNonce, limit, (error, result) => {
+ if (error) {
+ return callback(normalizeError(error))
} else {
- throw err
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions)
}
- }
+ })
}
-
- /** @deprecated will default to query */
- queryAsync = this.query
-
/**
* Submit a query to validate whether the backend can create a result set based on the SQL statement.
- * @param {String} query The query to perform
- * @returns {Promise.} The result of whether the query is valid
+ * @param {String} sql The query to perform
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example create a query
*
@@ -588,50 +418,23 @@ class MapdCon {
* // }]
*
*/
- validateQuery (query) {
- return new Promise((resolve, reject) => {
- this._client[0].sql_validate(this._sessionId[0], query, (error, res) => {
- if (error) {
- reject(error)
- } else {
- resolve(this.convertFromThriftTypes(res))
- }
- })
- })
- }
-
- removeConnection (conId) {
- if (conId < 0 || conId >= this.numConnections) {
- const err = {
- msg: "Remove connection id invalid"
- }
- throw err
- }
- this._client.splice(conId, 1)
- this._sessionId.splice(conId, 1)
- this._numConnections--
- }
-
- getTables (callback) {
- this._client[0].get_tables(this._sessionId[0], (error, tables) => {
+ function validateQuery (sql, callback) {
+ _client.sql_validate(_sessionId, sql, (error, data) => {
if (error) {
- callback(error)
+ return callback(normalizeError(error))
} else {
- callback(null, tables.map((table) => ({
- name: table,
- label: "obs"
- })))
+ return callback(null, convertFromThriftTypes(data, _datumEnum))
}
})
}
-
/**
* Get the names of the databases that exist on the current session's connectdion.
- * @return {Promise.} list of table objects containing the label and table names.
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Get the list of tables from a connection:
*
- * con.getTablesAsync().then(res => console.log(res))
+ * con.getTables().then(res => console.log(res))
*
* // [{
* // label: 'obs', // deprecated property
@@ -639,42 +442,24 @@ class MapdCon {
* // },
* // ...]
*/
- getTablesAsync () {
- return new Promise((resolve, reject) => {
- this.getTables.bind(this)((error, tables) => {
- if (error) {
- reject(error)
- } else {
- resolve(tables)
- }
- })
- })
- }
-
- /**
- * Create an array-like object from {@link TDatumType} by
- * flipping the string key and numerical value around.
- *
- * @returns {Undefined} This function does not return anything
- */
- invertDatumTypes () {
- const datumType = TDatumType // eslint-disable-line no-undef
- for (const key in datumType) {
- if (datumType.hasOwnProperty(key)) {
- this._datumEnum[datumType[key]] = key
+ function getTables (callback) {
+ _client.get_tables(_sessionId, (error, tables) => {
+ if (error) {
+ return callback(normalizeError(error))
+ } else {
+ return callback(null, tables.map((table) => ({name: table, label: "obs"})))
}
- }
+ })
}
-
/**
* Get a list of field objects for a given table.
* @param {String} tableName - name of table containing field names
- * @param {Function} callback - (err, results)
- * @return {Array} fields - the formmatted list of field objects
+ * @param {Function} callback - (error, fields) => {…}
+ * @returns {undefined}
*
* @example Get the list of fields from a specific table:
*
- * con.getFields('flights', (err, res) => console.log(res))
+ * con.getFields('flights', (error, res) => console.log(res))
* // [{
* name: 'fieldName',
* type: 'BIGINT',
@@ -682,136 +467,94 @@ class MapdCon {
* is_dict: false
* }, ...]
*/
- getFields (tableName, callback) {
- this._client[0].get_table_details(this._sessionId[0], tableName, (error, fields) => {
+ function getFields (tableName, callback) {
+ _client.get_table_details(_sessionId, tableName, (error, fields) => {
if (fields) {
const rowDict = fields.row_desc.reduce((accum, value) => {
accum[value.col_name] = value
return accum
}, {})
- callback(null, this.convertFromThriftTypes(rowDict))
+ return callback(null, convertFromThriftTypes(rowDict, _datumEnum))
} else {
- callback(new Error("Table (" + tableName + ") not found" + error))
+ return callback(normalizeError(error))
}
})
}
-
-
- createTable (tableName, rowDescObj, tableType, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.")
- }
-
- const thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc)
-
- for (let c = 0; c < this._numConnections; c++) {
- this._client[c].create_table(
- this._sessionId[c],
- tableName,
- thriftRowDesc,
- tableType,
- (err) => {
- if (err) {
- callback(err)
- } else {
- callback()
- }
- }
- )
- }
-
- }
-
/**
* Create a table and persist it to the backend.
* @param {String} tableName - desired name of the new table
* @param {Array} rowDescObj - fields of the new table
* @param {Number} tableType - the types of tables a user can import into the db
- * @return {Promise.} it will either catch an error or return undefined on success
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*
* @example Create a new table:
*
* con.createTable('mynewtable', [TColumnType, TColumnType, ...], 0).then(res => console.log(res));
* // undefined
*/
- createTableAsync = (tableName, rowDescObj, tableType) => new Promise((resolve, reject) => {
- this.createTable(tableName, rowDescObj, tableType, (err) => {
- if (err) {
- reject(err)
- } else {
- resolve()
- }
- })
- })
-
- importTable (tableName, fileName, copyParams, rowDescObj, isShapeFile, callback) {
- if (!this._sessionId) {
- throw new Error("You are not connected to a server. Try running the connect method first.")
- }
-
- const thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams)
- const thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, this.importerRowDesc)
-
- const thriftCallBack = (err, res) => {
- if (err) {
- callback(err)
- } else {
- callback(null, res)
- }
+ function createTable (tableName, rowDescObj, tableType, callback) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."))
}
-
- for (let c = 0; c < this._numConnections; c++) {
- if (isShapeFile) {
- this._client[c].import_geo_table(
- this._sessionId[c],
- tableName,
- fileName,
- thriftCopyParams,
- thriftRowDesc,
- thriftCallBack
- )
- } else {
- this._client[c].import_table(
- this._sessionId[c],
- tableName,
- fileName,
- thriftCopyParams,
- thriftCallBack
- )
- }
- }
- }
-
- importTableAsyncWrapper (isShapeFile) {
- return (tableName, fileName, copyParams, headers) => new Promise((resolve, reject) => {
- this.importTable(tableName, fileName, copyParams, headers, isShapeFile, (err, link) => {
- if (err) {
- reject(err)
- } else {
- resolve(link)
- }
- })
- })
+ const thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null)
+ return _client.create_table(
+ _sessionId,
+ tableName,
+ thriftRowDesc,
+ tableType,
+ callback
+ )
}
-
/**
* Import a delimited table from a file.
* @param {String} tableName - desired name of the new table
- * @param {String} fileName
+ * @param {String} fileName - name of imported file
* @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @param {Boolean} isShapeFile false by default, enabled to import shape data.
+ * @returns {undefined}
*/
- importTableAsync = this.importTableAsyncWrapper(false)
+ function importTable (tableName, fileName, copyParams, rowDescObj, callback, isShapeFile = false) {
+ if (!_sessionId) {
+ return callback(new Error("You are not connected to a server. Try running the connect method first."))
+ }
+ const thriftCopyParams = helpers.convertObjectToThriftCopyParams(copyParams)
+ const thriftRowDesc = helpers.mutateThriftRowDesc(rowDescObj, null)
+
+ if (isShapeFile) {
+ return _client.import_geo_table(
+ _sessionId,
+ tableName,
+ fileName,
+ thriftCopyParams,
+ thriftRowDesc,
+ callback
+ )
+ } else {
+ return _client.import_table(
+ _sessionId,
+ tableName,
+ fileName,
+ thriftCopyParams,
+ callback
+ )
+ }
+ }
/**
* Import a geo table from a file.
* @param {String} tableName - desired name of the new table
- * @param {String} fileName
+ * @param {String} fileName - name of imported file
* @param {TCopyParams} copyParams - see {@link TCopyParams}
- * @param {TColumnType[]} headers -- a colleciton of metadata related to the table headers
+ * @param {TColumnType[]} rowDescObj -- a colleciton of metadata related to the table headers
+ * @param {Function} callback (error, data) => {…}
+ * @returns {undefined}
*/
- importTableGeoAsync = this.importTableAsyncWrapper(true)
-
+ function importShapeTable (tableName, fileName, copyParams, rowDescObj, callback) {
+ return importTable(tableName, fileName, copyParams, rowDescObj, callback, true)
+ }
/**
* Use for backend rendering. This method will fetch a PNG image
* that is a render of the vega json object.
@@ -822,11 +565,10 @@ class MapdCon {
* @param {Number} options.compressionLevel the png compression level.
* range 1 (low compression, faster) to 10 (high compression, slower).
* Default 3.
- * @param {Function} callback takes `(err, success)` as its signature. Returns con singleton on success.
- *
- * @returns {Image} Base 64 Image
+ * @param {Function} callback (error, Base64Image) => {…}
+ * @returns {undefined}
*/
- renderVega (widgetid, vega, options, callback) /* istanbul ignore next */ {
+ function renderVega (widgetid, vega, options, callback) {
let queryId = null
let compressionLevel = COMPRESSION_LEVEL_DEFAULT
if (options) {
@@ -834,127 +576,57 @@ class MapdCon {
compressionLevel = options.hasOwnProperty("compressionLevel") ? options.compressionLevel : compressionLevel
}
- const lastQueryTime = queryId in this.queryTimes ? this.queryTimes[queryId] : this.DEFAULT_QUERY_TIME
-
- const curNonce = (this._nonce++).toString()
+ const lastQueryTime = queryId in _queryTimes ? _queryTimes[queryId] : DEFAULT_QUERY_TIME
- const conId = 0
- this._lastRenderCon = conId
+ const curNonce = (_nonce++).toString()
const processResultsOptions = {
isImage: true,
query: "render: " + vega,
queryId,
- conId,
+ conId: 0,
estimatedQueryTime: lastQueryTime
}
- try {
- if (!callback) {
- const renderResult = this._client[conId].render_vega(
- this._sessionId[conId],
- widgetid,
- vega,
- compressionLevel,
- curNonce
- )
- return this.processResults(processResultsOptions, renderResult)
- }
-
- this._client[conId].render_vega(this._sessionId[conId], widgetid, vega, compressionLevel, curNonce, (error, result) => {
- if (error) {
- callback(error)
- } else {
- this.processResults(processResultsOptions, result, callback)
- }
- })
- } catch (err) {
- throw err
- }
-
- return curNonce
+ _client.render_vega(_sessionId, widgetid, vega, compressionLevel, curNonce, (error, result) => {
+ if (error) { return callback(normalizeError(error)) }
+ return processResults(result, callback, _logging, _datumEnum, processResultsOptions)
+ })
}
-
/**
* Used primarily for backend rendered maps, this method will fetch the row
* for a specific table that was last rendered at a pixel.
- *
- * @param {widgetId} Number - the widget id of the caller
+ * @param {Number} widgetId - the widget id of the caller
* @param {TPixel} pixel - the pixel (lower left-hand corner is pixel (0,0))
- * @param {String} tableName - the table containing the geo data
* @param {Object} tableColNamesMap - object of tableName -> array of col names
- * @param {Array} callbacks
+ * @param {Function} callback (error, results) => {…}
* @param {Number} [pixelRadius=2] - the radius around the primary pixel to search
+ * @returns {undefined}
*/
-
- getResultRowForPixel (widgetId, pixel, tableColNamesMap, callbacks, pixelRadius = 2) /* istanbul ignore next */ {
- if (!(pixel instanceof TPixel)) { pixel = new TPixel(pixel) }
- const columnFormat = true // BOOL
- const curNonce = (this._nonce++).toString()
- try {
- if (!callbacks) {
- return this.processPixelResults(
- undefined, // eslint-disable-line no-undefined
- this._client[this._lastRenderCon].get_result_row_for_pixel(
- this._sessionId[this._lastRenderCon],
- widgetId,
- pixel,
- tableColNamesMap,
- columnFormat,
- pixelRadius,
- curNonce
- ))
- }
- this._client[this._lastRenderCon].get_result_row_for_pixel(
- this._sessionId[this._lastRenderCon],
- widgetId,
- pixel,
- tableColNamesMap,
- columnFormat,
- pixelRadius,
- curNonce,
- this.processPixelResults.bind(this, callbacks)
- )
- } catch (err) {
- throw err
- }
- return curNonce
- }
-
-
- /**
- * Formats the pixel results into the same pattern as textual results.
- *
- * @param {Array} callbacks a collection of callbacks
- * @param {Object} error an error if one was thrown, otherwise null
- * @param {Array|Object} results unformatted results of pixel rowId information
- *
- * @returns {Object} An object with the pixel results formatted for display
- */
- processPixelResults (callbacks, error, results) {
- callbacks = Array.isArray(callbacks) ? callbacks : [callbacks]
- results = Array.isArray(results) ? results.pixel_rows : [results]
- const numPixels = results.length
- const processResultsOptions = {
- isImage: false,
- eliminateNullRows: false,
- query: "pixel request",
- queryId: -2
- }
- for (let p = 0; p < numPixels; p++) {
- results[p].row_set = this.processResults(processResultsOptions, results[p])
- }
- if (!callbacks) {
- return results
+ function getPixel (widgetId, pixel, tableColNamesMap, callback, pixelRadius = 2) {
+ if (Array.isArray(callback)) {
+ console.warn("getPixel callbacks array deprecated; pass single callback instead.") // eslint-disable-line no-console
+ callback = callback[0]
}
- callbacks.pop()(error, results)
+ if (!(pixel instanceof TPixel)) { pixel = new TPixel(pixel) }
+ const columnFormat = true
+ const curNonce = String(_nonce++)
+ _client.get_result_row_for_pixel(
+ _sessionId,
+ widgetId,
+ pixel,
+ tableColNamesMap,
+ columnFormat,
+ pixelRadius,
+ curNonce,
+ processPixelResults.bind(this, callback, _logging, _datumEnum)
+ )
}
-
/**
* Get or set the session ID used by the server to serve the correct data.
* This is typically set by {@link connect} and should not be set manually.
- * @param {Number} sessionId - The session ID of the current connection
- * @return {Number|MapdCon} - The session ID or the MapdCon itself
+ * @param {Number} newSessionId - The session ID of the current connection
+ * @returns {Number|Connector} - The session ID or the Connector itself
*
* @example Get the session id:
*
@@ -962,206 +634,226 @@ class MapdCon {
* // sessionID === 3145846410
*
* @example Set the session id:
- * var con = new MapdCon().connect().sessionId(3415846410);
+ * var con = new Connector().connect().sessionId(3415846410);
* // NOTE: It is generally unsafe to set the session id manually.
*/
- sessionId (sessionId) {
+ function sessionId (newSessionId) {
if (!arguments.length) {
- return this._sessionId
+ return _sessionId
}
- this._sessionId = sessionId
+ _sessionId = newSessionId
return this
}
-
/**
* Get or set the connection server hostname.
- * This is is typically the first method called after instantiating a new MapdCon.
- * @param {String} host - The hostname address
- * @return {String|MapdCon} - The hostname or the MapdCon itself
+ * This is is typically the first method called after instantiating a new Connector.
+ * @param {String} hostname - The hostname address
+ * @returns {String|Connector} - The hostname or the Connector itself
*
* @example Set the hostname:
- * var con = new MapdCon().host('localhost');
+ * var con = new Connector().host('localhost');
*
* @example Get the hostname:
* var host = con.host();
* // host === 'localhost'
*/
- host (host) {
+ function host (hostname) {
if (!arguments.length) {
- return this._host
+ return _host
}
- this._host = arrayify(host)
+ _host = hostname
return this
}
-
/**
* Get or set the connection port.
- * @param {String} port - The port to connect on
- * @return {String|MapdCon} - The port or the MapdCon itself
+ * @param {String} thePort - The port to connect on
+ * @returns {String|Connector} - The port or the Connector itself
*
* @example Set the port:
- * var con = new MapdCon().port('8080');
+ * var con = new Connector().port('8080');
*
* @example Get the port:
* var port = con.port();
* // port === '8080'
*/
- port (port) {
+ function port (thePort) {
if (!arguments.length) {
- return this._port
+ return _port
}
- this._port = arrayify(port)
+ _port = thePort
return this
}
-
/**
* Get or set the username to authenticate with.
- * @param {String} user - The username to authenticate with
- * @return {String|MapdCon} - The username or the MapdCon itself
+ * @param {String} username - The username to authenticate with
+ * @returns {String|Connector} - The username or the Connector itself
*
* @example Set the username:
- * var con = new MapdCon().user('foo');
+ * var con = new Connector().user('foo');
*
* @example Get the username:
* var username = con.user();
* // user === 'foo'
*/
- user (user) {
+ function user (username) {
if (!arguments.length) {
- return this._user
+ return _user
}
- this._user = arrayify(user)
+ _user = username
return this
}
-
/**
* Get or set the user's password to authenticate with.
- * @param {String} password - The password to authenticate with
- * @return {String|MapdCon} - The password or the MapdCon itself
+ * @param {String} pass - The password to authenticate with
+ * @returns {String|Connector} - The password or the Connector itself
*
* @example Set the password:
- * var con = new MapdCon().password('bar');
+ * var con = new Connector().password('bar');
*
* @example Get the username:
* var password = con.password();
* // password === 'bar'
*/
- password (password) {
+ function password (pass) {
if (!arguments.length) {
- return this._password
+ return _password
}
- this._password = arrayify(password)
+ _password = pass
return this
}
-
/**
* Get or set the name of the database to connect to.
- * @param {String} dbName - The database to connect to
- * @return {String|MapdCon} - The name of the database or the MapdCon itself
+ * @param {String} db - The database to connect to
+ * @returns {String|Connector} - The name of the database or the Connector itself
*
* @example Set the database name:
- * var con = new MapdCon().dbName('myDatabase');
+ * var con = new Connector().dbName('myDatabase');
*
* @example Get the database name:
* var dbName = con.dbName();
* // dbName === 'myDatabase'
*/
- dbName (dbName) {
+ function dbName (db) {
if (!arguments.length) {
- return this._dbName
+ return _dbName
}
- this._dbName = arrayify(dbName)
+ _dbName = db
return this
}
-
/**
* Whether the raw queries strings will be logged to the console.
* Used primarily for debugging and defaults to false
.
- * @param {Boolean} logging - Set to true to enable logging
- * @return {Boolean|MapdCon} - The current logging flag or MapdCon itself
+ * @param {Boolean} loggingEnabled - Set to true to enable logging
+ * @returns {Boolean|Connector} - The current logging flag or Connector itself
*
* @example Set logging to true:
- * var con = new MapdCon().logging(true);
+ * var con = new Connector().logging(true);
*
* @example Get the logging flag:
* var isLogging = con.logging();
* // isLogging === true
*/
- logging (logging) {
- if (typeof logging === "undefined") {
- return this._logging
- } else if (typeof (logging) !== "boolean") {
+ function logging (loggingEnabled) {
+ if (typeof loggingEnabled === "undefined") {
+ return _logging
+ } else if (typeof loggingEnabled !== "boolean") {
return "logging can only be set with boolean values"
}
- this._logging = logging
- const isEnabledTxt = logging ? "enabled" : "disabled"
+ _logging = loggingEnabled
+ const isEnabledTxt = loggingEnabled ? "enabled" : "disabled"
return `SQL logging is now ${isEnabledTxt}`
}
-
- /**
- * The name of the platform.
- * @param {String} platform - The platform, default is "mapd"
- * @return {String|MapdCon} - The platform or the MapdCon itself
- *
- * @example Set the platform name:
- * var con = new MapdCon().platform('myPlatform');
- *
- * @example Get the platform name:
- * var platform = con.platform();
- * // platform === 'myPlatform'
- */
- platform (platform) {
- if (!arguments.length) {
- return this._platform
- }
- this._platform = platform
- return this
- }
-
- /**
- * Get the number of connections that are currently open.
- * @return {Number} - number of open connections
- *
- * @example Get the number of connections:
- *
- * var numConnections = con.numConnections();
- * // numConnections === 1
- */
- numConnections () {
- return this._numConnections
- }
-
/**
* The protocol to use for requests.
- * @param {String} protocol - http or https
- * @return {String|MapdCon} - protocol or MapdCon itself
+ * @param {String} theProtocol - http or https
+ * @returns {String|Connector} - protocol or Connector itself
*
* @example Set the protocol:
- * var con = new MapdCon().protocol('http');
+ * var con = new Connector().protocol('http');
*
* @example Get the protocol:
* var protocol = con.protocol();
* // protocol === 'http'
*/
- protocol (protocol) {
+ function protocol (theProtocol) {
if (!arguments.length) {
- return this._protocol
+ return _protocol
}
- this._protocol = arrayify(protocol)
+ _protocol = theProtocol
return this
}
+}
- /**
- * Generates a list of endpoints from the connection params.
- * @return {Array} - list of endpoints
- *
- * @example Get the endpoints:
- * var con = new MapdCon().protocol('http').host('localhost').port('8000');
- * var endpoints = con.getEndpoints();
- * // endpoints === [ 'http://localhost:8000' ]
- */
- getEndpoints () {
- return this._host.map((host, i) => this._protocol[i] + "://" + host + ":" + this._port[i])
+// helper functions
+
+function noop () { /* noop */ }
+
+function isNodeRuntime () { return typeof window === "undefined" }
+
+function publicizeMethods (theClass, methods) { methods.forEach(method => { theClass[method.name] = method }) }
+
+function convertFromThriftTypes (fields, _datumEnum) {
+ const fieldsArray = []
+ for (const key in fields) {
+ if (fields.hasOwnProperty(key)) {
+ fieldsArray.push({
+ name: key,
+ type: _datumEnum[fields[key].col_type.type],
+ is_array: fields[key].col_type.is_array,
+ is_dict: fields[key].col_type.encoding === TEncodingType.DICT
+ })
+ }
+ }
+ return fieldsArray
+}
+
+function updateQueryTimes (queryTimes) {
+ return (conId, queryId, estimatedQueryTime, execution_time_ms) => {
+ queryTimes[queryId] = execution_time_ms
+ }
+}
+
+function processPixelResults (callback, _logging, _datumEnum, error, results) { // eslint-disable-line consistent-return
+ if (error) { return callback(normalizeError(error)) }
+ results = Array.isArray(results) ? results.pixel_rows : [results]
+ const numPixels = results.length
+ const processResultsOptions = {
+ isImage: false,
+ eliminateNullRows: false,
+ query: "pixel request",
+ queryId: -2
+ }
+ let numResultsProcessed = 0
+ for (let p = 0; p < numPixels; p++) {
+ processResults(results[p], aggregatingCallback(p), _logging, _datumEnum, processResultsOptions)
+ }
+ function aggregatingCallback (index) {
+ return (processResultsError, row_set) => {
+ results[index].row_set = row_set
+ if (processResultsError) {
+ numResultsProcessed = -Infinity // avoid invoking callback again
+ return callback(processResultsError)
+ } else if (numResultsProcessed === numPixels - 1) {
+ return callback(null, results)
+ } else {
+ return numResultsProcessed++
+ }
+ }
+ }
+}
+
+function processResults (result, callback, _logging, _datumEnum, options = {}) {
+ const processor = processQueryResults(_logging, updateQueryTimes)
+ const processResultsObject = processor(options, _datumEnum, result, callback)
+ return processResultsObject
+}
+
+function invertDatumTypes (datumEnum) {
+ const datumType = TDatumType
+ for (const key in datumType) {
+ if (datumType.hasOwnProperty(key)) {
+ datumEnum[datumType[key]] = key
+ }
}
}
@@ -1184,11 +876,10 @@ function resetThriftClientOnArgumentErrorForMethods (connector, client, methodNa
})
}
-// Set a global mapdcon function when mapdcon is brought in via script tag.
-if (typeof module === "object" && module.exports) {
- if (!isNodeRuntime()) {
- window.MapdCon = MapdCon
+function normalizeError (error) {
+ if (isNodeRuntime()) {
+ return new Error(`${error.name} ${error.error_msg}`)
+ } else {
+ return new Error(`TMapDException ${error.message}`)
}
}
-module.exports = MapdCon
-export default MapdCon
diff --git a/test/integration.spec.js b/test/integration.spec.js
index 03e9a6cf..13ff07f9 100644
--- a/test/integration.spec.js
+++ b/test/integration.spec.js
@@ -1,8 +1,11 @@
"use strict"
+/* eslint-disable no-unused-expressions */
+/* eslint-disable max-nested-callbacks */
+/* eslint-disable no-magic-numbers */
const isNodeRuntime = typeof window === "undefined"
const expect = isNodeRuntime ? require("chai").expect : window.expect
const convertToDataUrl = isNodeRuntime ? require("base64-arraybuffer").encode : x => x
-const Connector = isNodeRuntime ? require("../dist/node-connector.js") : window.MapdCon
+const Connector = isNodeRuntime ? require("../dist/node-connector.js") : window.Connector
const imageRegex = /^iVBOR/
// An empty image data url will have about 80 header chars, then repeat 12 chars till it ends with a roughly 35 char footer.
@@ -10,14 +13,29 @@ const imageRegex = /^iVBOR/
// Note that \1 substitutes in the value of the first capture group (the 12 chars).
const emptyImageRegex = /^.{70,90}(.{12})\1+.{30,50}$/
-describe(isNodeRuntime ? "node" : "browser", () => {
- let connector
- beforeEach(() => {
- connector = new Connector().protocol("https").host("metis.mapd.com").port("443").dbName("mapd").user("mapd").password("HyperInteractive")
+describe(`${isNodeRuntime ? "node" : "browser"} Connector`, () => {
+ it(".connect success", done => {
+ new Connector().protocol("https").host("metis.mapd.com").port("443").dbName("mapd").user("mapd").password("HyperInteractive")
+ .connect((error, session) => {
+ expect(error).not.be.an.error
+ expect(session).to.be.an.instanceOf(Connector)
+ expect(session).to.respondTo("query")
+ done()
+ })
})
- const widgetId = 0
- const options = {}
+ it(".connect error", done => {
+ new Connector().password("invalid password").protocol("https").host("metis.mapd.com").port("443").dbName("mapd").user("mapd")
+ .connect((error, session) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Password for User mapd is incorrect.")
+ expect(session).to.be.undefined
+ done()
+ })
+ })
+})
+
+describe(`${isNodeRuntime ? "node" : "browser"} Connector session`, () => {
const vega = JSON.stringify({ // vega must be a JSON-parsable string
width: 384,
height: 541,
@@ -48,165 +66,357 @@ describe(isNodeRuntime ? "node" : "browser", () => {
}]
})
- it(".connect", done => {
- connector.connect((connectError, session) => {
- expect(connectError).not.be.an("error")
- expect(session).to.respondTo("query")
+ let session = null
+ beforeEach(done => {
+ new Connector().protocol("https").host("metis.mapd.com").port("443").dbName("mapd").user("mapd").password("HyperInteractive")
+ .connect((error, newSession) => {
+ expect(error).not.be.an.error
+ session = newSession
done()
})
})
- it(".disconnect", done => {
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.disconnect(disconnectError => {
- expect(disconnectError).not.be.an("error")
- expect(session.getServerStatus).to.throw() // example use of disconnected client should fail
- done()
- })
+ it(".disconnect success", done => {
+ expect(session.sessionId()).not.to.be.null
+ session.disconnect((error, newSession) => {
+ expect(error).not.be.an.error
+ expect(newSession).to.be.an.instanceOf(Connector)
+ expect(newSession.sessionId()).to.be.null
+ done()
})
})
- it(".getTablesAsync", done => {
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.getTablesAsync()
- .then(data => {
- expect(data).to.deep.equal([
- {name: "flights_donotmodify", label: "obs"},
- {name: "contributions_donotmodify", label: "obs"},
- {name: "tweets_nov_feb", label: "obs"},
- {name: "zipcodes", label: "obs"}
- ])
- done()
+ it(".getFrontendView success", done => {
+ session.getFrontendView("__E2E_NUMBER_CHART__DO_NOT_MODIFY__", (error, data) => {
+ expect(error).to.be.null
+ expect(JSON.parse(JSON.stringify(data))).to.deep.equal({ // parse stringify because some hidden prop fails deep equals.
+ view_name: "__E2E_NUMBER_CHART__DO_NOT_MODIFY__",
+ view_state: "eyJjaGFydHMiOnsiMCI6eyJkY0ZsYWciOjF9LCIxIjp7ImFyZUZpbHRlcnNJbnZlcnNlIjpmYWxzZSwiYmluUGFyYW1zIjpudWxsLCJjYXAiOjEyLCJjb2xvciI6eyJ0eXBlIjoic29saWQiLCJrZXkiOiJibHVlIiwidmFsIjpbIiMyN2FlZWYiXX0sImNvbG9yRG9tYWluIjpudWxsLCJkY0ZsYWciOjQsImRpbWVuc2lvbnMiOltdLCJlbGFzdGljWCI6dHJ1ZSwiZmlsdGVycyI6W10sImdlb0pzb24iOm51bGwsImhlaWdodCI6bnVsbCwibG9hZGluZyI6ZmFsc2UsIm1lYXN1cmVzIjpbeyJpc0Vycm9yIjpmYWxzZSwiaXNSZXF1aXJlZCI6ZmFsc2UsInRhYmxlIjoiZmxpZ2h0c19kb25vdG1vZGlmeSIsInR5cGUiOiJTTUFMTElOVCIsImlzX2FycmF5IjpmYWxzZSwiaXNfZGljdCI6ZmFsc2UsIm5hbWVfaXNfYW1iaWd1b3VzIjpmYWxzZSwibGFiZWwiOiJ0YXhpb3V0IiwidmFsdWUiOiJ0YXhpb3V0IiwiY29sb3JUeXBlIjoicXVhbnRpdGF0aXZlIiwiYWdnVHlwZSI6IkF2ZyIsImN1c3RvbSI6ZmFsc2UsIm9yaWdpbkluZGV4IjowLCJuYW1lIjoidmFsIiwiaW5hY3RpdmUiOmZhbHNlfV0sIm9yZGVyaW5nIjoiZGVzYyIsIm90aGVyc0dyb3VwZXIiOmZhbHNlLCJzYXZlZENvbG9ycyI6e30sInNvcnRDb2x1bW4iOnsiY29sIjp7Im5hbWUiOiJjb3VudHZhbCJ9LCJpbmRleCI6MSwib3JkZXIiOiJkZXNjIn0sInRpY2tzIjozLCJ0aW1lQmluSW5wdXRWYWwiOiIiLCJ0aXRsZSI6IiIsInR5cGUiOiJudW1iZXIiLCJ3aWR0aCI6bnVsbCwiaGFzRXJyb3IiOmZhbHNlfX0sInVpIjp7InNob3dGaWx0ZXJQYW5lbCI6ZmFsc2UsInNob3dDbGVhckZpbHRlcnNEcm9wZG93biI6ZmFsc2UsIm1vZGFsIjp7Im9wZW4iOmZhbHNlLCJjb250ZW50IjoiIiwiaGVhZGVyIjoiIiwiY2FuY2VsQnV0dG9uIjpmYWxzZX0sInNlbGVjdG9yUGlsbEhvdmVyIjp7InNob3VsZFNob3dQcm9tcHQiOmZhbHNlLCJtZXNzYWdlIjoiIiwidG9wIjowfSwic2VsZWN0b3JQb3NpdGlvbnMiOnsiZGltZW5zaW9ucyI6WzExMCwxMDYsMTUwLDExMCwxMTBdLCJtZWFzdXJlcyI6WzE5OSwxOTksMjM5LDI3OSwxOTUsMjM5LDE5OV19fSwiZmlsdGVycyI6W10sImRhc2hib2FyZCI6eyJ0aXRsZSI6Il9fRTJFX05VTUJFUl9DSEFSVF9fRE9fTk9UX01PRElGWV9fIiwiY2hhcnRDb250YWluZXJzIjpbeyJpZCI6IjEifV0sInRhYmxlIjoiZmxpZ2h0c19kb25vdG1vZGlmeSIsImZpbHRlcnNJZCI6W10sImxheW91dCI6W3sidyI6MTAsImgiOjEwLCJ4IjowLCJ5IjowLCJpIjoiMSIsIm1vdmVkIjpmYWxzZSwic3RhdGljIjpmYWxzZX1dLCJzYXZlTGlua1N0YXRlIjp7ImVycm9yIjpmYWxzZSwicmVxdWVzdCI6ZmFsc2UsInNhdmVMaW5rSWQiOm51bGx9LCJsb2FkU3RhdGUiOnsiZXJyb3IiOmZhbHNlLCJyZXF1ZXN0IjpmYWxzZSwibG9hZExpbmtJZCI6bnVsbH0sInNhdmVTdGF0ZSI6eyJlcnJvciI6ZmFsc2UsInJlcXVlc3QiOmZhbHNlLCJsYXN0U3RhdGUiOm51bGwsImlzU2F2ZWQiOmZhbHNlfX19",
+ image_hash: "",
+ update_time: "2016-10-15T05:32:44Z",
+ view_metadata: "{\"table\":\"flights_donotmodify\",\"version\":\"v2\"}"
})
- .catch(getTablesAsyncError => expect(getTablesAsyncError).to.not.be.an("error"))
- })
- })
-
- it(".getFields", done => {
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.getFields("flights_donotmodify", (getFieldsError, data) => {
- expect(getFieldsError).to.not.be.an("error")
- expect(data).to.deep.equal([
- {is_array: false, is_dict: false, name: "flight_year", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "flight_month", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "flight_dayofmonth", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "flight_dayofweek", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "deptime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "crsdeptime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "arrtime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "crsarrtime", type: "SMALLINT"},
- {is_array: false, is_dict: true, name: "uniquecarrier", type: "STR"},
- {is_array: false, is_dict: false, name: "flightnum", type: "SMALLINT"},
- {is_array: false, is_dict: true, name: "tailnum", type: "STR"},
- {is_array: false, is_dict: false, name: "actualelapsedtime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "crselapsedtime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "airtime", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "arrdelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "depdelay", type: "SMALLINT"},
- {is_array: false, is_dict: true, name: "origin", type: "STR"},
- {is_array: false, is_dict: true, name: "dest", type: "STR"},
- {is_array: false, is_dict: false, name: "distance", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "taxiin", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "taxiout", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "cancelled", type: "SMALLINT"},
- {is_array: false, is_dict: true, name: "cancellationcode", type: "STR"},
- {is_array: false, is_dict: false, name: "diverted", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "carrierdelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "weatherdelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "nasdelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "securitydelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "lateaircraftdelay", type: "SMALLINT"},
- {is_array: false, is_dict: false, name: "dep_timestamp", type: "TIMESTAMP"},
- {is_array: false, is_dict: false, name: "arr_timestamp", type: "TIMESTAMP"},
- {is_array: false, is_dict: true, name: "carrier_name", type: "STR"},
- {is_array: false, is_dict: true, name: "plane_type", type: "STR"},
- {is_array: false, is_dict: true, name: "plane_manufacturer", type: "STR"},
- {is_array: false, is_dict: false, name: "plane_issue_date", type: "DATE"},
- {is_array: false, is_dict: true, name: "plane_model", type: "STR"},
- {is_array: false, is_dict: true, name: "plane_status", type: "STR"},
- {is_array: false, is_dict: true, name: "plane_aircraft_type", type: "STR"},
- {is_array: false, is_dict: true, name: "plane_engine_type", type: "STR"},
- {is_array: false, is_dict: false, name: "plane_year", type: "SMALLINT"},
- {is_array: false, is_dict: true, name: "origin_name", type: "STR"},
- {is_array: false, is_dict: true, name: "origin_city", type: "STR"},
- {is_array: false, is_dict: true, name: "origin_state", type: "STR"},
- {is_array: false, is_dict: true, name: "origin_country", type: "STR"},
- {is_array: false, is_dict: false, name: "origin_lat", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "origin_lon", type: "FLOAT"},
- {is_array: false, is_dict: true, name: "dest_name", type: "STR"},
- {is_array: false, is_dict: true, name: "dest_city", type: "STR"},
- {is_array: false, is_dict: true, name: "dest_state", type: "STR"},
- {is_array: false, is_dict: true, name: "dest_country", type: "STR"},
- {is_array: false, is_dict: false, name: "dest_lat", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "dest_lon", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "origin_merc_x", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "origin_merc_y", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "dest_merc_x", type: "FLOAT"},
- {is_array: false, is_dict: false, name: "dest_merc_y", type: "FLOAT"}
- ])
- done()
+ done()
+ })
+ })
+
+ it(".getFrontendViews success", done => {
+ session.getFrontendViews((error, data) => {
+ expect(error).to.be.null
+ expect(JSON.parse(JSON.stringify(data))).to.deep.equal([ // parse stringify because some hidden prop fails deep equals.
+ {
+ image_hash: "",
+ update_time: "2016-10-15T05:44:20Z",
+ view_metadata: "{\"table\":\"flights_donotmodify\",\"version\":\"v2\"}",
+ view_name: "__E2E_LINE_CHART_BRUSH__DO_NOT_MODIFY__",
+ view_state: ""
+ }, {
+ image_hash: "",
+ update_time: "2016-10-15T05:40:39Z",
+ view_metadata: "{\"table\":\"flights_donotmodify\",\"version\":\"v2\"}",
+ view_name: "__E2E_MULTI_BIN_DIM_HEATMAP_FILTER__DO_NOT_MODIFY__",
+ view_state: ""
+ }, {
+ image_hash: "",
+ update_time: "2016-10-15T05:32:44Z",
+ view_metadata: "{\"table\":\"flights_donotmodify\",\"version\":\"v2\"}",
+ view_name: "__E2E_NUMBER_CHART__DO_NOT_MODIFY__",
+ view_state: ""
+ }, {
+ image_hash: "",
+ update_time: "2016-10-15T05:55:33Z",
+ view_metadata: "{\"table\":\"contributions_donotmodify\",\"version\":\"v2\"}",
+ view_name: "__E2E__ALL_CHARTS__DO_NOT_MODIFY__",
+ view_state: ""
+ }
+ ])
+ done()
+ })
+ })
+
+ it(".getServerStatus success", done => {
+ session.getServerStatus((error, data) => {
+ expect(error).to.be.null
+ expect(Object.keys(data).sort()).to.deep.equal(["edition", "read_only", "rendering_enabled", "start_time", "version"])
+ expect(data.edition).to.be.null
+ expect(data.read_only).to.equal(true)
+ expect(data.rendering_enabled).to.equal(true)
+ expect(Number(data.start_time)).to.be.a.number // timestamp likely to change
+ expect(isNaN(data.start_time)).to.equal(false) // timestamp likely to change
+ expect(data.version).to.be.a.string // version likely to change
+ done()
+ })
+ })
+
+ xit(".createFrontendView success")
+
+ xit(".deleteFrontendView success")
+
+ xit(".createLink success")
+
+ it(".getLinkView success", done => {
+ const link = "1563954d"
+ session.getLinkView(link, (error, data) => {
+ expect(error).to.be.null
+ expect(JSON.parse(JSON.stringify(data))).to.deep.equal({ // parse stringify because some hidden prop fails deep equals.
+ view_name: "1563954d",
+ view_state: "eyJjaGFydHMiOnsiMCI6eyJkY0ZsYWciOjF9LCIxIjp7ImFyZUZpbHRlcnNJbnZlcnNlIjpmYWxzZSwiYmluUGFyYW1zIjpudWxsLCJjYXAiOjEyLCJjb2xvciI6eyJ0eXBlIjoic29saWQiLCJrZXkiOiJibHVlIiwidmFsIjpbIiMyN2FlZWYiXX0sImNvbG9yRG9tYWluIjpudWxsLCJkaW1lbnNpb25zIjpbXSwiZWxhc3RpY1giOnRydWUsImZpbHRlcnMiOltdLCJnZW9Kc29uIjpudWxsLCJoZWlnaHQiOm51bGwsImxvYWRpbmciOmZhbHNlLCJtZWFzdXJlcyI6W3siaXNFcnJvciI6ZmFsc2UsImlzUmVxdWlyZWQiOmZhbHNlLCJ0YWJsZSI6ImZsaWdodHNfZG9ub3Rtb2RpZnkiLCJ0eXBlIjoiU01BTExJTlQiLCJpc19hcnJheSI6ZmFsc2UsImlzX2RpY3QiOmZhbHNlLCJuYW1lX2lzX2FtYmlndW91cyI6ZmFsc2UsImxhYmVsIjoidGF4aW91dCIsInZhbHVlIjoidGF4aW91dCIsImNvbG9yVHlwZSI6InF1YW50aXRhdGl2ZSIsImFnZ1R5cGUiOiJBdmciLCJjdXN0b20iOmZhbHNlLCJvcmlnaW5JbmRleCI6MCwibmFtZSI6InZhbCIsImluYWN0aXZlIjpmYWxzZX1dLCJvdGhlcnNHcm91cGVyIjpmYWxzZSwic2F2ZWRDb2xvcnMiOnt9LCJzb3J0Q29sdW1uIjp7ImNvbCI6eyJuYW1lIjoiY291bnR2YWwifSwiaW5kZXgiOjEsIm9yZGVyIjoiZGVzYyJ9LCJ0aWNrcyI6MywidGltZUJpbklucHV0VmFsIjoiIiwidGl0bGUiOiIiLCJ0eXBlIjoibnVtYmVyIiwid2lkdGgiOm51bGwsImhhc0Vycm9yIjpmYWxzZSwic2hvd051bGxEaW1lbnNpb25zIjpmYWxzZSwicmFuZ2VGaWx0ZXIiOltdLCJkY0ZsYWciOjJ9fSwidWkiOnsic2VsZWN0b3JQb3NpdGlvbnMiOnsiZGltZW5zaW9ucyI6WzExMCwxMDYsMTUwLDExMCwxMTBdLCJtZWFzdXJlcyI6WzE5OSwxOTksMjM5LDI3OSwxOTUsMjM5LDE5OV19LCJzaG93RmlsdGVyUGFuZWwiOmZhbHNlLCJzaG93Q2xlYXJGaWx0ZXJzRHJvcGRvd24iOmZhbHNlLCJtb2RhbCI6eyJvcGVuIjpmYWxzZSwiY29udGVudCI6IiIsImhlYWRlciI6IiIsImNhbmNlbEJ1dHRvbiI6ZmFsc2V9LCJzZWxlY3RvclBpbGxIb3ZlciI6eyJzaG91bGRTaG93UHJvbXB0IjpmYWxzZSwibWVzc2FnZSI6IiIsInRvcCI6MH19LCJmaWx0ZXJzIjpbXSwiZGFzaGJvYXJkIjp7InRpdGxlIjoiX19FMkVfTlVNQkVSX0NIQVJUX19ET19OT1RfTU9ESUZZX18iLCJjaGFydENvbnRhaW5lcnMiOlt7ImlkIjoiMSJ9XSwidGFibGUiOiJmbGlnaHRzX2Rvbm90bW9kaWZ5IiwiZmlsdGVyc0lkIjpbXSwibGF5b3V0IjpbeyJ3IjoxMCwiaCI6MTAsIngiOjAsInkiOjAsImkiOiIxIiwibW92ZWQiOmZhbHNlLCJzdGF0aWMiOmZhbHNlfV0sInNhdmVMaW5rU3RhdGUiOnsiZXJyb3IiOmZhbHNlLCJyZXF1ZXN0IjpmYWxzZSwic2F2ZUxpbmtJZCI6bnVsbH0sImxvYWRTdGF0ZSI6eyJyZXF1ZXN0IjpmYWxzZSwiZXJyb3IiOmZhbHNlfSwic2F2ZVN0YXRlIjp7ImlzU2F2ZWQiOmZhbHNlLCJyZXF1ZXN0IjpmYWxzZSwiZXJyb3IiOmZhbHNlfSwiaW5pdGlhbGl6YXRpb24iOnsiZG9uZSI6ZmFsc2UsInBlbmRpbmciOmZhbHNlLCJlcnJvciI6ZmFsc2UsImNvdW50ZXIiOjB9LCJ2ZXJzaW9uIjoiMy4wLjAtMjAxNzA1MDItOWU1YmE5NSJ9fQ==",
+ image_hash: "",
+ update_time: "2017-06-25T05:29:11Z",
+ view_metadata: ""
})
+ done()
+ })
+ })
+
+ it(".getLinkView error", done => {
+ const link = "BAD"
+ session.getLinkView(link, (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Link BAD is not valid.")
+ expect(data).to.be.undefined
+ done()
+ })
+ })
+
+ xit(".detectColumnTypes success", done => { // TODO Can this be done without the file locally? What are valid copyParams?
+ const fileName = "test.csv"
+ const copyParams = {}
+ session.detectColumnTypes(fileName, copyParams, (error, data) => {
+ expect(error).to.be.null
+ expect(data).to.deep.equal([])
+ done()
+ })
+ })
+
+ it(".query success", done => {
+ const sql = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'"
+ const options = {}
+ session.query(sql, options, (error, data) => {
+ expect(error).not.be.an.error
+ expect(Number(data[0].n)).to.equal(6400)
+ done()
+ })
+ })
+
+ it(".query error", done => {
+ const sql = "invalid sql"
+ const options = {}
+ session.query(sql, options, (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Exception: ERROR-- Parse failed: line 1, column 1, Non-query expression encountered in illegal context")
+ expect(data).to.be.undefined
+ done()
})
})
- it(".query", done => {
+ it(".validateQuery success", done => {
const sql = "SELECT count(*) AS n FROM tweets_nov_feb WHERE country='CO'"
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.query(sql, options, (error, data) => {
- expect(error).not.be.an("error")
- expect(Number(data[0].n)).to.equal(6400)
+ session.validateQuery(sql, (error, data) => {
+ expect(error).not.be.an.error
+ expect(data).to.deep.equal([{name: "n", type: "INT", is_array: false, is_dict: false}])
+ done()
+ })
+ })
+
+ it(".validateQuery error", done => {
+ const sql = "invalid sql"
+ session.validateQuery(sql, (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Exception: ERROR-- Parse failed: line 1, column 1, Non-query expression encountered in illegal context")
+ expect(data).to.be.undefined
+ done()
+ })
+ })
+
+ it(".getTables success", done => {
+ session.getTables((getTablesError, data) => {
+ expect(getTablesError).to.not.be.an.error
+ expect(data).to.deep.equal([
+ {name: "flights_donotmodify", label: "obs"},
+ {name: "contributions_donotmodify", label: "obs"},
+ {name: "tweets_nov_feb", label: "obs"},
+ {name: "zipcodes", label: "obs"}
+ ])
+ done()
+ })
+ })
+
+ xit(".getTables error")
+
+ it(".getFields success", done => {
+ session.getFields("flights_donotmodify", (getFieldsError, data) => {
+ expect(getFieldsError).to.not.be.an.error
+ expect(data).to.deep.equal([
+ {is_array: false, is_dict: false, name: "flight_year", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "flight_month", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "flight_dayofmonth", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "flight_dayofweek", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "deptime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "crsdeptime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "arrtime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "crsarrtime", type: "SMALLINT"},
+ {is_array: false, is_dict: true, name: "uniquecarrier", type: "STR"},
+ {is_array: false, is_dict: false, name: "flightnum", type: "SMALLINT"},
+ {is_array: false, is_dict: true, name: "tailnum", type: "STR"},
+ {is_array: false, is_dict: false, name: "actualelapsedtime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "crselapsedtime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "airtime", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "arrdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "depdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: true, name: "origin", type: "STR"},
+ {is_array: false, is_dict: true, name: "dest", type: "STR"},
+ {is_array: false, is_dict: false, name: "distance", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "taxiin", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "taxiout", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "cancelled", type: "SMALLINT"},
+ {is_array: false, is_dict: true, name: "cancellationcode", type: "STR"},
+ {is_array: false, is_dict: false, name: "diverted", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "carrierdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "weatherdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "nasdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "securitydelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "lateaircraftdelay", type: "SMALLINT"},
+ {is_array: false, is_dict: false, name: "dep_timestamp", type: "TIMESTAMP"},
+ {is_array: false, is_dict: false, name: "arr_timestamp", type: "TIMESTAMP"},
+ {is_array: false, is_dict: true, name: "carrier_name", type: "STR"},
+ {is_array: false, is_dict: true, name: "plane_type", type: "STR"},
+ {is_array: false, is_dict: true, name: "plane_manufacturer", type: "STR"},
+ {is_array: false, is_dict: false, name: "plane_issue_date", type: "DATE"},
+ {is_array: false, is_dict: true, name: "plane_model", type: "STR"},
+ {is_array: false, is_dict: true, name: "plane_status", type: "STR"},
+ {is_array: false, is_dict: true, name: "plane_aircraft_type", type: "STR"},
+ {is_array: false, is_dict: true, name: "plane_engine_type", type: "STR"},
+ {is_array: false, is_dict: false, name: "plane_year", type: "SMALLINT"},
+ {is_array: false, is_dict: true, name: "origin_name", type: "STR"},
+ {is_array: false, is_dict: true, name: "origin_city", type: "STR"},
+ {is_array: false, is_dict: true, name: "origin_state", type: "STR"},
+ {is_array: false, is_dict: true, name: "origin_country", type: "STR"},
+ {is_array: false, is_dict: false, name: "origin_lat", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "origin_lon", type: "FLOAT"},
+ {is_array: false, is_dict: true, name: "dest_name", type: "STR"},
+ {is_array: false, is_dict: true, name: "dest_city", type: "STR"},
+ {is_array: false, is_dict: true, name: "dest_state", type: "STR"},
+ {is_array: false, is_dict: true, name: "dest_country", type: "STR"},
+ {is_array: false, is_dict: false, name: "dest_lat", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "dest_lon", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "origin_merc_x", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "origin_merc_y", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "dest_merc_x", type: "FLOAT"},
+ {is_array: false, is_dict: false, name: "dest_merc_y", type: "FLOAT"}
+ ])
+ done()
+ })
+ })
+
+ it(".getFields error", done => {
+ session.getFields("NOT A TABLE", (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Table doesn't exist")
+ expect(data).to.be.undefined
+ done()
+ })
+ })
+
+ xit(".createTable success")
+
+ xit(".importTable success")
+
+ xit(".importShapeTable success")
+
+ it(".renderVega success", done => {
+ const widgetId = 0
+ const options = {}
+ session.renderVega(widgetId, vega, options, (renderVegaError, data) => {
+ expect(renderVegaError).to.not.be.an.error
+ const imageData = convertToDataUrl(data.image)
+ expect(imageData, "should be a image data URL").to.match(imageRegex)
+ expect(imageData, "shouldn't be an empty image").to.not.match(emptyImageRegex)
+ done()
+ })
+ })
+
+ it(".renderVega error", done => {
+ const widgetId = 0
+ const options = {}
+ const badVega = "BAD"
+ session.renderVega(widgetId, badVega, options, (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException Exception: /home/jenkins-slave/workspace/mapd2-multi/compiler/gcc/gpu/cuda/host/centos/render/render/QueryRenderer/QueryRenderer.cpp:164 JSON parse error: json offset: 0, error: Invalid value.")
+ expect(data).to.be.undefined
+ done()
+ })
+ })
+
+ it(".getPixel success", done => {
+ const widgetId = 0
+ const options = {}
+ const pixel = {x: 70, y: 275}
+ const tableColNamesMap = {points: ["dest_lon"]}
+ session.renderVega(widgetId, vega, options, renderVegaError => {
+ expect(renderVegaError).to.not.be.an.error
+ session.getPixel(widgetId, pixel, tableColNamesMap, (pixelError, data) => {
+ expect(pixelError).to.not.be.an.error
+ expect(data[0].row_set).to.deep.equal([{dest_lon: -119.056770324707}]) // Ran 100 times; seems deterministic.
done()
})
})
})
- it(".render", done => {
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.renderVega(widgetId, vega, options, (renderVegaError, data) => {
- expect(renderVegaError).to.not.be.an("error")
- const imageData = convertToDataUrl(data.image)
- expect(imageData, "should be a image data URL").to.match(imageRegex)
- expect(imageData, "shouldn't be an empty image").to.not.match(emptyImageRegex)
+ it(".getPixel success empty", done => {
+ const widgetId = 0
+ const options = {}
+ const pixelWithNoResults = {x: 0, y: 0}
+ const tableColNamesMap = {points: ["dest_lon"]}
+ session.renderVega(widgetId, vega, options, renderVegaError => {
+ expect(renderVegaError).to.not.be.an.error
+ session.getPixel(widgetId, pixelWithNoResults, tableColNamesMap, (pixelError, data) => {
+ expect(pixelError).to.not.be.an.error
+ expect(data[0].row_set).to.deep.equal([])
done()
})
})
})
- it(".getResultRowForPixel", done => {
+ xit(".getPixel error unrendered", done => { // TODO should throw rather than succeed empty
+ const widgetId = -947647 // not rendered
const pixel = {x: 70, y: 275}
- const tableColNamesMap = {points: ["dest_lon"]} // {vegaDataLayerName: [columnFromDataLayerTable]}
- connector.connect((connectError, session) => {
- expect(connectError).to.not.be.an("error")
- session.renderVega(widgetId, vega, options, renderVegaError => {
- expect(renderVegaError).to.not.be.an("error")
- session.getResultRowForPixel(widgetId, pixel, tableColNamesMap, (pixelError, data) => {
- expect(pixelError).to.not.be.an("error")
- expect(data[0].row_set).to.deep.equal([{dest_lon: -119.056770324707}]) // Ran 100 times; seems deterministic.
- done()
- })
+ const tableColNamesMap = {points: ["dest_lon"]}
+ session.getPixel(widgetId, pixel, tableColNamesMap, (error, data) => {
+ expect(error).to.be.an.error
+ expect(error.message).to.equal("TMapDException no vega rendered for id -947647.")
+ expect(data).to.be.undefined
+ done()
+ })
+ })
+
+ it(".getPixel error", done => {
+ const widgetId = 0
+ const options = {}
+ const pixel = {x: 70, y: 275}
+ const badTableColNamesMap = {points: ["NOT_A_COLUMN"]}
+ session.renderVega(widgetId, vega, options, renderVegaError => {
+ expect(renderVegaError).to.not.be.an.error
+ session.getPixel(widgetId, pixel, badTableColNamesMap, (pixelError, data) => {
+ expect(pixelError).to.be.an.error
+ expect(pixelError.message).to.equal("TMapDException Exception: TException - service has thrown: TMapDException(error_msg=Exception: ERROR-- Validate failed: From line 1, column 8 to line 1, column 21: Column 'NOT_A_COLUMN' not found in any table)")
+ expect(data).to.be.undefined
+ done()
})
})
})
if (isNodeRuntime) { // bug only applies to node; in browser thriftTransportInstance is undefined.
- it("on bad arguments: passes error, flushes internal buffer so next RPC doesn't fail, dereferences callback to avoid memory leak", done => {
+ it("on bad arguments: passes error, flushes internal buffer so next RPC doesn't fail, dereferences callback to avoid memory leak", () => {
const BAD_ARG = {}
- const callback = () => { /* noop */ }
- connector.connect((_, session) => {
- expect(() => session.getFields(BAD_ARG, callback)).to.throw("writeString called without a string/Buffer argument: [object Object]")
- const thriftClient = connector._client[0]
+ expect(() => session.getFields(BAD_ARG, () => {
+ const thriftClient = session._client[0]
const thriftTransportInstance = thriftClient.output
expect(thriftTransportInstance.outCount).to.equal(0)
expect(thriftTransportInstance.outBuffers).to.deep.equal([])
expect(thriftTransportInstance._seqid).to.equal(null)
expect(thriftClient._reqs[thriftClient._seqid]).to.equal(null)
- done()
- })
+ })).to.throw("writeString called without a string/Buffer argument: [object Object]")
})
}
})