UNPKG

kepler.gl

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

385 lines (373 loc) 35.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.KEPLER_FORMAT = exports.FILE_CONFLICT_MSG = void 0; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _upload = _interopRequireDefault(require("./upload")); // SPDX-License-Identifier: MIT // Copyright contributors to the kepler.gl project var NAME = 'cloud-provider'; var DISPLAY_NAME = 'Cloud Provider'; var THUMBNAIL = { width: 300, height: 200 }; var ICON = _upload["default"]; var KEPLER_FORMAT = exports.KEPLER_FORMAT = 'keplergl'; var FILE_CONFLICT_MSG = exports.FILE_CONFLICT_MSG = 'file_conflict'; /** * The default provider class * @param {object} props * @param {string} props.name * @param {string} props.displayName * @param {React.Component} props.icon - React element * @param {object} props.thumbnail - thumbnail size object * @param {number} props.thumbnail.width - thumbnail width in pixels * @param {number} props.thumbnail.height - thumbnail height in pixels * @public * @example * * const myProvider = new Provider({ * name: 'foo', * displayName: 'Foo Storage' * icon: Icon, * thumbnail: {width: 300, height: 200} * }) */ var Provider = exports["default"] = /*#__PURE__*/function () { function Provider(props) { (0, _classCallCheck2["default"])(this, Provider); (0, _defineProperty2["default"])(this, "name", void 0); (0, _defineProperty2["default"])(this, "displayName", void 0); (0, _defineProperty2["default"])(this, "storageMessage", void 0); (0, _defineProperty2["default"])(this, "icon", void 0); (0, _defineProperty2["default"])(this, "thumbnail", void 0); (0, _defineProperty2["default"])(this, "isNew", false); this.name = props.name || NAME; this.displayName = props.displayName || DISPLAY_NAME; this.storageMessage = props.storageMessage; this.icon = props.icon || ICON; this.thumbnail = props.thumbnail || THUMBNAIL; } /** * Whether this provider support upload map to a private storage. If truthy, user will be displayed with the storage save icon on the top right of the side bar. * @returns * @public */ return (0, _createClass2["default"])(Provider, [{ key: "hasPrivateStorage", value: function hasPrivateStorage() { return true; } /** * Whether this provider support share map via a public url, if truthy, user will be displayed with a share map via url under the export map option on the top right of the side bar * @returns * @public */ }, { key: "hasSharingUrl", value: function hasSharingUrl() { return false; } /** * This method is called after user share a map, to display the share url. * @param fullUrl - Whether to return the full url with domain, or just the location * @returns shareUrl * @public */ // eslint-disable-next-line @typescript-eslint/no-unused-vars }, { key: "getShareUrl", value: function getShareUrl() { var fullUrl = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; return ''; } /** * This method is called by kepler.gl demo app to pushes a new location to history, becoming the current location. * @returns mapUrl * @public */ // eslint-disable-next-line @typescript-eslint/no-unused-vars }, { key: "getMapUrl", value: function getMapUrl(loadParams) { return ''; } /** * This method is called to determine whether user already logged in to this provider * @public * @returns {Promise<string>} return the access token if a user already logged in */ }, { key: "getAccessToken", value: (function () { var _getAccessToken = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { return _regenerator["default"].wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", Promise.reject('You must implement getAccessToken')); case 1: case "end": return _context.stop(); } }, _callee); })); function getAccessToken() { return _getAccessToken.apply(this, arguments); } return getAccessToken; }() /** * This method is called to get the user name of the current user. It will be displayed in the cloud provider tile. * @public * @deprecated please use getUser * @returns true if a user already logged in */ ) }, { key: "getUserName", value: function getUserName() { return ''; } /** * return a Promise with the user object */ }, { key: "getUser", value: (function () { var _getUser = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2() { return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: return _context2.abrupt("return", Promise.reject('You must implement getUser')); case 1: case "end": return _context2.stop(); } }, _callee2); })); function getUser() { return _getUser.apply(this, arguments); } return getUser; }() /** * This return a standard error that will trigger the overwrite map modal */ ) }, { key: "getFileConflictError", value: function getFileConflictError() { return new Error(FILE_CONFLICT_MSG); } /** * This method will be called when user click the login button in the cloud provider tile. * Upon login success and return the user Object {name, email, abbreviated} * @public */ }, { key: "login", value: (function () { var _login = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3() { return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: return _context3.abrupt("return", Promise.reject(new Error('you must implement the `login` method'))); case 1: case "end": return _context3.stop(); } }, _callee3); })); function login() { return _login.apply(this, arguments); } return login; }() /** * This method will be called when user click the logout button under the cloud provider tile. * Upon login success * @public */ ) }, { key: "logout", value: (function () { var _logout = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4() { return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: return _context4.abrupt("return", Promise.reject(new Error('you must implement the `logout` method'))); case 1: case "end": return _context4.stop(); } }, _callee4); })); function logout() { return _logout.apply(this, arguments); } return logout; }() /** * This method will be called to upload map for saving and sharing. Kepler.gl will package map data, config, title, description and thumbnail for upload to storage. * With the option to overwrite already saved map, and upload as private or public map. * * @param {Object} param * @param {Object} param.mapData - the map object * @param {Object} param.mapData.map - {datasets. config, info: {title, description}} * @param {Blob} param.mapData.thumbnail - A thumbnail of current map. thumbnail size can be defined by provider by this.thumbnail * @param {object} [param.options] * @param {boolean} [param.options.overwrite] - whether user choose to overwrite already saved map under the same name * @param {boolean} [param.options.isPublic] - whether user wish to share the map with others. if isPublic is truthy, kepler will call this.getShareUrl() to display an URL they can share with others * @public */ ) }, { key: "uploadMap", value: (function () { var _uploadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(_ref) { var mapData, _ref$options, options; return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: mapData = _ref.mapData, _ref$options = _ref.options, options = _ref$options === void 0 ? {} : _ref$options; return _context5.abrupt("return", Promise.reject('You must implement uploadMap')); case 2: case "end": return _context5.stop(); } }, _callee5); })); function uploadMap(_x) { return _uploadMap.apply(this, arguments); } return uploadMap; }() /** * This method is called to get a list of maps saved by the current logged in user. * @returns visualizations an array of Viz objects * @public * @example * async listMaps() { * return [ * { * id: 'a', * title: 'My map', * description: 'My first kepler map', * imageUrl: 'http://', * updatedAt: 1582677787000, * privateMap: false, * loadParams: {} * } * ]; * } */ ) }, { key: "listMaps", value: (function () { var _listMaps = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6() { return _regenerator["default"].wrap(function _callee6$(_context6) { while (1) switch (_context6.prev = _context6.next) { case 0: return _context6.abrupt("return", []); case 1: case "end": return _context6.stop(); } }, _callee6); })); function listMaps() { return _listMaps.apply(this, arguments); } return listMaps; }() /** * This method will be called when user select a map to load from the storage map viewer * @param {*} loadParams - the loadParams property of each visualization object * @returns mapResponse - the map object containing dataset config info and format option * @public * @example * async downloadMap(loadParams) { * const mockResponse = { * map: { * datasets: [], * config: {}, * info: { * app: 'kepler.gl', * created_at: '' * title: 'test map', * description: 'Hello this is my test dropbox map' * } * }, * // pass csv here if your provider currently only support save / load file as csv * format: 'keplergl' * }; * * return downloadMap; * } */ // eslint-disable-next-line @typescript-eslint/no-unused-vars ) }, { key: "downloadMap", value: (function () { var _downloadMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(loadParams) { return _regenerator["default"].wrap(function _callee7$(_context7) { while (1) switch (_context7.prev = _context7.next) { case 0: return _context7.abrupt("return", Promise.reject('You must implement downloadMap')); case 1: case "end": return _context7.stop(); } }, _callee7); })); function downloadMap(_x2) { return _downloadMap.apply(this, arguments); } return downloadMap; }() /** * @return {string} return the storage location url for the current provider * @public */ ) }, { key: "getManagementUrl", value: function getManagementUrl() { throw new Error('You must implement getManagementUrl'); } /** * @typedef {Object} Viz * @property {string} id - An unique id * @property {string} title - The title of the map * @property {string} description - The description of the map * @property {string} imageUrl - The imageUrl of the map * @property {number} updatedAt - An epoch timestamp in milliseconds * @property {boolean} privateMap - Optional, whether if this map is private to the user, or can be accessed by others via URL * @property {*} loadParams - A property to be passed to `downloadMap` * @public */ /** * The returned object of `downloadMap`. The response object should contain: datasets: [], config: {}, and info: {} * each dataset object should be {info: {id, label}, data: {...}} * to inform how kepler should process your data object, pass in `format` * @typedef {Object} MapResponse * @property {Object} map * @property {Array<Object>} map.datasets * @property {Object} map.config * @property {Object} map.info * @property {string} format - one of 'csv': csv file string, 'geojson': geojson object, 'row': row object, 'keplergl': datasets array saved using KeplerGlSchema.save * @public */ }]); }(); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfdXBsb2FkIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJOQU1FIiwiRElTUExBWV9OQU1FIiwiVEhVTUJOQUlMIiwid2lkdGgiLCJoZWlnaHQiLCJJQ09OIiwiVXBsb2FkIiwiS0VQTEVSX0ZPUk1BVCIsImV4cG9ydHMiLCJGSUxFX0NPTkZMSUNUX01TRyIsIlByb3ZpZGVyIiwicHJvcHMiLCJfY2xhc3NDYWxsQ2hlY2syIiwiX2RlZmluZVByb3BlcnR5MiIsIm5hbWUiLCJkaXNwbGF5TmFtZSIsInN0b3JhZ2VNZXNzYWdlIiwiaWNvbiIsInRodW1ibmFpbCIsIl9jcmVhdGVDbGFzczIiLCJrZXkiLCJ2YWx1ZSIsImhhc1ByaXZhdGVTdG9yYWdlIiwiaGFzU2hhcmluZ1VybCIsImdldFNoYXJlVXJsIiwiZnVsbFVybCIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsImdldE1hcFVybCIsImxvYWRQYXJhbXMiLCJfZ2V0QWNjZXNzVG9rZW4iLCJfYXN5bmNUb0dlbmVyYXRvcjIiLCJfcmVnZW5lcmF0b3IiLCJtYXJrIiwiX2NhbGxlZSIsIndyYXAiLCJfY2FsbGVlJCIsIl9jb250ZXh0IiwicHJldiIsIm5leHQiLCJhYnJ1cHQiLCJQcm9taXNlIiwicmVqZWN0Iiwic3RvcCIsImdldEFjY2Vzc1Rva2VuIiwiYXBwbHkiLCJnZXRVc2VyTmFtZSIsIl9nZXRVc2VyIiwiX2NhbGxlZTIiLCJfY2FsbGVlMiQiLCJfY29udGV4dDIiLCJnZXRVc2VyIiwiZ2V0RmlsZUNvbmZsaWN0RXJyb3IiLCJFcnJvciIsIl9sb2dpbiIsIl9jYWxsZWUzIiwiX2NhbGxlZTMkIiwiX2NvbnRleHQzIiwibG9naW4iLCJfbG9nb3V0IiwiX2NhbGxlZTQiLCJfY2FsbGVlNCQiLCJfY29udGV4dDQiLCJsb2dvdXQiLCJfdXBsb2FkTWFwIiwiX2NhbGxlZTUiLCJfcmVmIiwibWFwRGF0YSIsIl9yZWYkb3B0aW9ucyIsIm9wdGlvbnMiLCJfY2FsbGVlNSQiLCJfY29udGV4dDUiLCJ1cGxvYWRNYXAiLCJfeCIsIl9saXN0TWFwcyIsIl9jYWxsZWU2IiwiX2NhbGxlZTYkIiwiX2NvbnRleHQ2IiwibGlzdE1hcHMiLCJfZG93bmxvYWRNYXAiLCJfY2FsbGVlNyIsIl9jYWxsZWU3JCIsIl9jb250ZXh0NyIsImRvd25sb2FkTWFwIiwiX3gyIiwiZ2V0TWFuYWdlbWVudFVybCJdLCJzb3VyY2VzIjpbIi4uL3NyYy9wcm92aWRlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgVXBsb2FkIGZyb20gJy4vdXBsb2FkJztcbmltcG9ydCB7TWFwRGF0YSwgRXhwb3J0RmlsZU9wdGlvbnMsIE1pbGxpc2Vjb25kLCBTYXZlZE1hcH0gZnJvbSAnQGtlcGxlci5nbC90eXBlcyc7XG5pbXBvcnQge0NvbXBvbmVudFR5cGV9IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IHR5cGUgTWFwSXRlbUxvYWRQYXJhbXMgPSB7XG4gIGlkOiBzdHJpbmc7XG4gIHBhdGg6IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIE1hcExpc3RJdGVtID0ge1xuICBpZDogc3RyaW5nO1xuICB0aXRsZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICBsb2FkUGFyYW1zOiBhbnk7XG4gIGltYWdlVXJsPzogc3RyaW5nO1xuICB1cGRhdGVkQXQ/OiBNaWxsaXNlY29uZDtcbiAgcHJpdmF0ZU1hcD86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBDbG91ZFVzZXIgPSB7XG4gIG5hbWU6IHN0cmluZztcbiAgZW1haWw6IHN0cmluZztcbiAgdGh1bWJuYWlsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgVGh1bWJuYWlsID0ge1xuICB3aWR0aDogbnVtYmVyO1xuICBoZWlnaHQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIFByb3ZpZGVyUHJvcHMgPSB7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIGRpc3BsYXlOYW1lPzogc3RyaW5nO1xuICBzdG9yYWdlTWVzc2FnZT86IHN0cmluZztcbiAgaWNvbj86IENvbXBvbmVudFR5cGU8SWNvblByb3BzPjtcbiAgdGh1bWJuYWlsPzogVGh1bWJuYWlsO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBJY29uUHJvcHMge1xuICBoZWlnaHQ/OiBzdHJpbmc7XG4gIHdpZHRoPzogc3RyaW5nO1xufVxuXG5jb25zdCBOQU1FID0gJ2Nsb3VkLXByb3ZpZGVyJztcbmNvbnN0IERJU1BMQVlfTkFNRSA9ICdDbG91ZCBQcm92aWRlcic7XG5jb25zdCBUSFVNQk5BSUwgPSB7d2lkdGg6IDMwMCwgaGVpZ2h0OiAyMDB9O1xuY29uc3QgSUNPTiA9IFVwbG9hZDtcbmV4cG9ydCBjb25zdCBLRVBMRVJfRk9STUFUID0gJ2tlcGxlcmdsJztcbmV4cG9ydCBjb25zdCBGSUxFX0NPTkZMSUNUX01TRyA9ICdmaWxlX2NvbmZsaWN0JztcblxuLyoqXG4gKiBUaGUgZGVmYXVsdCBwcm92aWRlciBjbGFzc1xuICogQHBhcmFtIHtvYmplY3R9IHByb3BzXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcHMubmFtZVxuICogQHBhcmFtIHtzdHJpbmd9IHByb3BzLmRpc3BsYXlOYW1lXG4gKiBAcGFyYW0ge1JlYWN0LkNvbXBvbmVudH0gcHJvcHMuaWNvbiAtIFJlYWN0IGVsZW1lbnRcbiAqIEBwYXJhbSB7b2JqZWN0fSBwcm9wcy50aHVtYm5haWwgLSB0aHVtYm5haWwgc2l6ZSBvYmplY3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBwcm9wcy50aHVtYm5haWwud2lkdGggLSB0aHVtYm5haWwgd2lkdGggaW4gcGl4ZWxzXG4gKiBAcGFyYW0ge251bWJlcn0gcHJvcHMudGh1bWJuYWlsLmhlaWdodCAtIHRodW1ibmFpbCBoZWlnaHQgaW4gcGl4ZWxzXG4gKiBAcHVibGljXG4gKiBAZXhhbXBsZVxuICpcbiAqIGNvbnN0IG15UHJvdmlkZXIgPSBuZXcgUHJvdmlkZXIoe1xuICogIG5hbWU6ICdmb28nLFxuICogIGRpc3BsYXlOYW1lOiAnRm9vIFN0b3JhZ2UnXG4gKiAgaWNvbjogSWNvbixcbiAqICB0aHVtYm5haWw6IHt3aWR0aDogMzAwLCBoZWlnaHQ6IDIwMH1cbiAqIH0pXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFByb3ZpZGVyIHtcbiAgbmFtZTogc3RyaW5nO1xuICBkaXNwbGF5TmFtZTogc3RyaW5nO1xuICBzdG9yYWdlTWVzc2FnZT86IHN0cmluZztcbiAgaWNvbjogQ29tcG9uZW50VHlwZTxJY29uUHJvcHM+O1xuICB0aHVtYm5haWw6IFRodW1ibmFpbDtcbiAgaXNOZXcgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUHJvdmlkZXJQcm9wcykge1xuICAgIHRoaXMubmFtZSA9IHByb3BzLm5hbWUgfHwgTkFNRTtcbiAgICB0aGlzLmRpc3BsYXlOYW1lID0gcHJvcHMuZGlzcGxheU5hbWUgfHwgRElTUExBWV9OQU1FO1xuICAgIHRoaXMuc3RvcmFnZU1lc3NhZ2UgPSBwcm9wcy5zdG9yYWdlTWVzc2FnZTtcbiAgICB0aGlzLmljb24gPSBwcm9wcy5pY29uIHx8IElDT047XG4gICAgdGhpcy50aHVtYm5haWwgPSBwcm9wcy50aHVtYm5haWwgfHwgVEhVTUJOQUlMO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBwcm92aWRlciBzdXBwb3J0IHVwbG9hZCBtYXAgdG8gYSBwcml2YXRlIHN0b3JhZ2UuIElmIHRydXRoeSwgdXNlciB3aWxsIGJlIGRpc3BsYXllZCB3aXRoIHRoZSBzdG9yYWdlIHNhdmUgaWNvbiBvbiB0aGUgdG9wIHJpZ2h0IG9mIHRoZSBzaWRlIGJhci5cbiAgICogQHJldHVybnNcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgaGFzUHJpdmF0ZVN0b3JhZ2UoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3ZpZGVyIHN1cHBvcnQgc2hhcmUgbWFwIHZpYSBhIHB1YmxpYyB1cmwsIGlmIHRydXRoeSwgdXNlciB3aWxsIGJlIGRpc3BsYXllZCB3aXRoIGEgc2hhcmUgbWFwIHZpYSB1cmwgdW5kZXIgdGhlIGV4cG9ydCBtYXAgb3B0aW9uIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIHNpZGUgYmFyXG4gICAqIEByZXR1cm5zXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGhhc1NoYXJpbmdVcmwoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBhZnRlciB1c2VyIHNoYXJlIGEgbWFwLCB0byBkaXNwbGF5IHRoZSBzaGFyZSB1cmwuXG4gICAqIEBwYXJhbSBmdWxsVXJsIC0gV2hldGhlciB0byByZXR1cm4gdGhlIGZ1bGwgdXJsIHdpdGggZG9tYWluLCBvciBqdXN0IHRoZSBsb2NhdGlvblxuICAgKiBAcmV0dXJucyBzaGFyZVVybFxuICAgKiBAcHVibGljXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGdldFNoYXJlVXJsKGZ1bGxVcmwgPSBmYWxzZSk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBrZXBsZXIuZ2wgZGVtbyBhcHAgdG8gcHVzaGVzIGEgbmV3IGxvY2F0aW9uIHRvIGhpc3RvcnksIGJlY29taW5nIHRoZSBjdXJyZW50IGxvY2F0aW9uLlxuICAgKiBAcmV0dXJucyBtYXBVcmxcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBnZXRNYXBVcmwobG9hZFBhcmFtczogTWFwSXRlbUxvYWRQYXJhbXMpOiBzdHJpbmcge1xuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdXNlciBhbHJlYWR5IGxvZ2dlZCBpbiB0byB0aGlzIHByb3ZpZGVyXG4gICAqIEBwdWJsaWNcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gcmV0dXJuIHRoZSBhY2Nlc3MgdG9rZW4gaWYgYSB1c2VyIGFscmVhZHkgbG9nZ2VkIGluXG4gICAqL1xuICBhc3luYyBnZXRBY2Nlc3NUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1lvdSBtdXN0IGltcGxlbWVudCBnZXRBY2Nlc3NUb2tlbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB0byBnZXQgdGhlIHVzZXIgbmFtZSBvZiB0aGUgY3VycmVudCB1c2VyLiBJdCB3aWxsIGJlIGRpc3BsYXllZCBpbiB0aGUgY2xvdWQgcHJvdmlkZXIgdGlsZS5cbiAgICogQHB1YmxpY1xuICAgKiBAZGVwcmVjYXRlZCBwbGVhc2UgdXNlIGdldFVzZXJcbiAgICogQHJldHVybnMgdHJ1ZSBpZiBhIHVzZXIgYWxyZWFkeSBsb2dnZWQgaW5cbiAgICovXG4gIGdldFVzZXJOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIHJldHVybiBhIFByb21pc2Ugd2l0aCB0aGUgdXNlciBvYmplY3RcbiAgICovXG4gIGFzeW5jIGdldFVzZXIoKTogUHJvbWlzZTxDbG91ZFVzZXIgfCBudWxsPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCdZb3UgbXVzdCBpbXBsZW1lbnQgZ2V0VXNlcicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgcmV0dXJuIGEgc3RhbmRhcmQgZXJyb3IgdGhhdCB3aWxsIHRyaWdnZXIgdGhlIG92ZXJ3cml0ZSBtYXAgbW9kYWxcbiAgICovXG4gIGdldEZpbGVDb25mbGljdEVycm9yKCkge1xuICAgIHJldHVybiBuZXcgRXJyb3IoRklMRV9DT05GTElDVF9NU0cpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBjbGljayB0aGUgbG9naW4gYnV0dG9uIGluIHRoZSBjbG91ZCBwcm92aWRlciB0aWxlLlxuICAgKiBVcG9uIGxvZ2luIHN1Y2Nlc3MgYW5kIHJldHVybiB0aGUgdXNlciBPYmplY3Qge25hbWUsIGVtYWlsLCBhYmJyZXZpYXRlZH1cbiAgICogQHB1YmxpY1xuICAgKi9cbiAgYXN5bmMgbG9naW4oKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcigneW91IG11c3QgaW1wbGVtZW50IHRoZSBgbG9naW5gIG1ldGhvZCcpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIGJlIGNhbGxlZCB3aGVuIHVzZXIgY2xpY2sgdGhlIGxvZ291dCBidXR0b24gdW5kZXIgdGhlIGNsb3VkIHByb3ZpZGVyIHRpbGUuXG4gICAqIFVwb24gbG9naW4gc3VjY2Vzc1xuICAgKiBAcHVibGljXG4gICAqL1xuICBhc3luYyBsb2dvdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KG5ldyBFcnJvcigneW91IG11c3QgaW1wbGVtZW50IHRoZSBgbG9nb3V0YCBtZXRob2QnKSk7XG4gIH1cblxuICAvKipcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgdG8gdXBsb2FkIG1hcCBmb3Igc2F2aW5nIGFuZCBzaGFyaW5nLiBLZXBsZXIuZ2wgd2lsbCBwYWNrYWdlIG1hcCBkYXRhLCBjb25maWcsIHRpdGxlLCBkZXNjcmlwdGlvbiBhbmQgdGh1bWJuYWlsIGZvciB1cGxvYWQgdG8gc3RvcmFnZS5cbiAgICogV2l0aCB0aGUgb3B0aW9uIHRvIG92ZXJ3cml0ZSBhbHJlYWR5IHNhdmVkIG1hcCwgYW5kIHVwbG9hZCBhcyBwcml2YXRlIG9yIHB1YmxpYyBtYXAuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbVxuICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW0ubWFwRGF0YSAtIHRoZSBtYXAgb2JqZWN0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbS5tYXBEYXRhLm1hcCAtIHtkYXRhc2V0cy4gY29uZmlnLCBpbmZvOiB7dGl0bGUsIGRlc2NyaXB0aW9ufX1cbiAgICogQHBhcmFtIHtCbG9ifSBwYXJhbS5tYXBEYXRhLnRodW1ibmFpbCAtIEEgdGh1bWJuYWlsIG9mIGN1cnJlbnQgbWFwLiB0aHVtYm5haWwgc2l6ZSBjYW4gYmUgZGVmaW5lZCBieSBwcm92aWRlciBieSB0aGlzLnRodW1ibmFpbFxuICAgKiBAcGFyYW0ge29iamVjdH0gW3BhcmFtLm9wdGlvbnNdXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3BhcmFtLm9wdGlvbnMub3ZlcndyaXRlXSAtIHdoZXRoZXIgdXNlciBjaG9vc2UgdG8gb3ZlcndyaXRlIGFscmVhZHkgc2F2ZWQgbWFwIHVuZGVyIHRoZSBzYW1lIG5hbWVcbiAgICogQHBhcmFtIHtib29sZWFufSBbcGFyYW0ub3B0aW9ucy5pc1B1YmxpY10gLSB3aGV0aGVyIHVzZXIgd2lzaCB0byBzaGFyZSB0aGUgbWFwIHdpdGggb3RoZXJzLiBpZiBpc1B1YmxpYyBpcyB0cnV0aHksIGtlcGxlciB3aWxsIGNhbGwgdGhpcy5nZXRTaGFyZVVybCgpIHRvIGRpc3BsYXkgYW4gVVJMIHRoZXkgY2FuIHNoYXJlIHdpdGggb3RoZXJzXG4gICAqIEBwdWJsaWNcbiAgICovXG4gIGFzeW5jIHVwbG9hZE1hcCh7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG1hcERhdGEsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9wdGlvbnMgPSB7fVxuICB9OiB7XG4gICAgbWFwRGF0YTogTWFwRGF0YTtcbiAgICBvcHRpb25zOiBFeHBvcnRGaWxlT3B0aW9ucztcbiAgfSk6IFByb21pc2U8TWFwTGlzdEl0ZW0+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1lvdSBtdXN0IGltcGxlbWVudCB1cGxvYWRNYXAnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgdG8gZ2V0IGEgbGlzdCBvZiBtYXBzIHNhdmVkIGJ5IHRoZSBjdXJyZW50IGxvZ2dlZCBpbiB1c2VyLlxuICAgKiBAcmV0dXJucyB2aXN1YWxpemF0aW9ucyBhbiBhcnJheSBvZiBWaXogb2JqZWN0c1xuICAgKiBAcHVibGljXG4gICAqIEBleGFtcGxlXG4gICAqICBhc3luYyBsaXN0TWFwcygpIHtcbiAgICogICAgcmV0dXJuIFtcbiAgICogICAgICB7XG4gICAqICAgICAgICBpZDogJ2EnLFxuICAgKiAgICAgICAgdGl0bGU6ICdNeSBtYXAnLFxuICAgKiAgICAgICAgZGVzY3JpcHRpb246ICdNeSBmaXJzdCBrZXBsZXIgbWFwJyxcbiAgICogICAgICAgIGltYWdlVXJsOiAnaHR0cDovLycsXG4gICAqICAgICAgICB1cGRhdGVkQXQ6IDE1ODI2Nzc3ODcwMDAsXG4gICAqICAgICAgICBwcml2YXRlTWFwOiBmYWxzZSxcbiAgICogICAgICAgIGxvYWRQYXJhbXM6IHt9XG4gICAqICAgICAgfVxuICAgKiAgICBdO1xuICAgKiAgfVxuICAgKi9cbiAgYXN5bmMgbGlzdE1hcHMoKTogUHJvbWlzZTxNYXBMaXN0SXRlbVtdPiB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgbWV0aG9kIHdpbGwgYmUgY2FsbGVkIHdoZW4gdXNlciBzZWxlY3QgYSBtYXAgdG8gbG9hZCBmcm9tIHRoZSBzdG9yYWdlIG1hcCB2aWV3ZXJcbiAgICogQHBhcmFtIHsqfSBsb2FkUGFyYW1zIC0gdGhlIGxvYWRQYXJhbXMgcHJvcGVydHkgb2YgZWFjaCB2aXN1YWxpemF0aW9uIG9iamVjdFxuICAgKiBAcmV0dXJucyBtYXBSZXNwb25zZSAtIHRoZSBtYXAgb2JqZWN0IGNvbnRhaW5pbmcgZGF0YXNldCBjb25maWcgaW5mbyBhbmQgZm9ybWF0IG9wdGlvblxuICAgKiBAcHVibGljXG4gICAqIEBleGFtcGxlXG4gICAqIGFzeW5jIGRvd25sb2FkTWFwKGxvYWRQYXJhbXMpIHtcbiAgICogIGNvbnN0IG1vY2tSZXNwb25zZSA9IHtcbiAgICogICAgbWFwOiB7XG4gICAqICAgICAgZGF0YXNldHM6IFtdLFxuICAgKiAgICAgIGNvbmZpZzoge30sXG4gICAqICAgICAgaW5mbzoge1xuICAgKiAgICAgICAgYXBwOiAna2VwbGVyLmdsJyxcbiAgICogICAgICAgIGNyZWF0ZWRfYXQ6ICcnXG4gICAqICAgICAgICB0aXRsZTogJ3Rlc3QgbWFwJyxcbiAgICogICAgICAgIGRlc2NyaXB0aW9uOiAnSGVsbG8gdGhpcyBpcyBteSB0ZXN0IGRyb3Bib3ggbWFwJ1xuICAgKiAgICAgIH1cbiAgICogICAgfSxcbiAgICogICAgLy8gcGFzcyBjc3YgaGVyZSBpZiB5b3VyIHByb3ZpZGVyIGN1cnJlbnRseSBvbmx5IHN1cHBvcnQgc2F2ZSAvIGxvYWQgZmlsZSBhcyBjc3ZcbiAgICogICAgZm9ybWF0OiAna2VwbGVyZ2wnXG4gICAqICB9O1xuICAgKlxuICAgKiAgcmV0dXJuIGRvd25sb2FkTWFwO1xuICAgKiB9XG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGFzeW5jIGRvd25sb2FkTWFwKGxvYWRQYXJhbXMpOiBQcm9taXNlPHttYXA6IFNhdmVkTWFwOyBmb3JtYXQ6IHN0cmluZ30+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ1lvdSBtdXN0IGltcGxlbWVudCBkb3dubG9hZE1hcCcpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm4ge3N0cmluZ30gcmV0dXJuIHRoZSBzdG9yYWdlIGxvY2F0aW9uIHVybCBmb3IgdGhlIGN1cnJlbnQgcHJvdmlkZXJcbiAgICogQHB1YmxpY1xuICAgKi9cbiAgZ2V0TWFuYWdlbWVudFVybCgpOiBzdHJpbmcge1xuICAgIHRocm93IG5ldyBFcnJvcignWW91IG11c3QgaW1wbGVtZW50IGdldE1hbmFnZW1lbnRVcmwnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBWaXpcbiAgICogQHByb3BlcnR5IHtzdHJpbmd9IGlkIC0gQW4gdW5pcXVlIGlkXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB0aXRsZSAtIFRoZSB0aXRsZSBvZiB0aGUgbWFwXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBkZXNjcmlwdGlvbiAtIFRoZSBkZXNjcmlwdGlvbiBvZiB0aGUgbWFwXG4gICAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBpbWFnZVVybCAtIFRoZSBpbWFnZVVybCBvZiB0aGUgbWFwXG4gICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSB1cGRhdGVkQXQgLSBBbiBlcG9jaCB0aW1lc3RhbXAgaW4gbWlsbGlzZWNvbmRzXG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gcHJpdmF0ZU1hcCAtIE9wdGlvbmFsLCB3aGV0aGVyIGlmIHRoaXMgbWFwIGlzIHByaXZhdGUgdG8gdGhlIHVzZXIsIG9yIGNhbiBiZSBhY2Nlc3NlZCBieSBvdGhlcnMgdmlhIFVSTFxuICAgKiBAcHJvcGVydHkgeyp9IGxvYWRQYXJhbXMgLSBBIHByb3BlcnR5IHRvIGJlIHBhc3NlZCB0byBgZG93bmxvYWRNYXBgXG4gICAqIEBwdWJsaWNcbiAgICovXG5cbiAgLyoqXG4gICAqIFRoZSByZXR1cm5lZCBvYmplY3Qgb2YgYGRvd25sb2FkTWFwYC4gVGhlIHJlc3BvbnNlIG9iamVjdCBzaG91bGQgY29udGFpbjogZGF0YXNldHM6IFtdLCBjb25maWc6IHt9LCBhbmQgaW5mbzoge31cbiAgICogZWFjaCBkYXRhc2V0IG9iamVjdCBzaG91bGQgYmUge2luZm86IHtpZCwgbGFiZWx9LCBkYXRhOiB7Li4ufX1cbiAgICogdG8gaW5mb3JtIGhvdyBrZXBsZXIgc2hvdWxkIHByb2Nlc3MgeW91ciBkYXRhIG9iamVjdCwgcGFzcyBpbiBgZm9ybWF0YFxuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBNYXBSZXNwb25zZVxuICAgKiBAcHJvcGVydHkge09iamVjdH0gbWFwXG4gICAqIEBwcm9wZXJ0eSB7QXJyYXk8T2JqZWN0Pn0gbWFwLmRhdGFzZXRzXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXAuY29uZmlnXG4gICAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBtYXAuaW5mb1xuICAgKiBAcHJvcGVydHkge3N0cmluZ30gZm9ybWF0IC0gb25lIG9mICdjc3YnOiBjc3YgZmlsZSBzdHJpbmcsICdnZW9qc29uJzogZ2VvanNvbiBvYmplY3QsICdyb3cnOiByb3cgb2JqZWN0LCAna2VwbGVyZ2wnOiBkYXRhc2V0cyBhcnJheSBzYXZlZCB1c2luZyBLZXBsZXJHbFNjaGVtYS5zYXZlXG4gICAqIEBwdWJsaWNcbiAgICovXG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUdBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUhBO0FBQ0E7O0FBNkNBLElBQU1DLElBQUksR0FBRyxnQkFBZ0I7QUFDN0IsSUFBTUMsWUFBWSxHQUFHLGdCQUFnQjtBQUNyQyxJQUFNQyxTQUFTLEdBQUc7RUFBQ0MsS0FBSyxFQUFFLEdBQUc7RUFBRUMsTUFBTSxFQUFFO0FBQUcsQ0FBQztBQUMzQyxJQUFNQyxJQUFJLEdBQUdDLGtCQUFNO0FBQ1osSUFBTUMsYUFBYSxHQUFBQyxPQUFBLENBQUFELGFBQUEsR0FBRyxVQUFVO0FBQ2hDLElBQU1FLGlCQUFpQixHQUFBRCxPQUFBLENBQUFDLGlCQUFBLEdBQUcsZUFBZTs7QUFFaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFsQkEs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